anchor.diff:      {ok, unopened, #state{}}.
   
   %% states
  +
  +%% worth putting specs on these?
   
   unopened({open, Socket, Connect}, From,
            S0 = #state{ socket = undefined }) ->
  
positive.code: 
  %%% Internal functions
  
  write(#state{ socket = S }, Frame) ->
      ok = gen_tcp:send(S, mqtt_framing:serialise(Frame)),
      ok.
  
  recv(State = #state{ frame_buf = Buf }) ->
      parse_frame(Buf, State, fun mqtt_framing:parse/1).
  
  
negative.code:           frame_buf = <<>>
           }).
  
  -type(connection() :: pid()).
  
  start_link() ->
      gen_fsm:start_link(?MODULE, [], []).
  
  -spec(connect(connection(),
                address(),
                client_id(),
                [connect_option()]) -> ok).
  connect(Conn, Address, ClientId, ConnectOpts) ->
      Connect = #connect{ client_id = iolist_to_binary([ClientId]) },
      Connect1 = opts(Connect, ConnectOpts),
      {Host, Port} = make_address(Address),
      {ok, Sock} = gen_tcp:connect(Host, Port,
                                   [{active, false},
                                    binary]),
      open(Conn, Sock, Connect1).
  
  %% NB this assumes that the calling process controls the socket
  open(Conn, Sock, ConnectFrame) ->
      ok = gen_tcp:controlling_process(Sock, Conn),
      gen_fsm:sync_send_event(Conn, {open, Sock, ConnectFrame}).
  
  %%% gen_fsm callbacks
  
  