anchor.diff:  'CONNECT'(timeout, #fsm{peer={Host, Port}, opts=Opts} = S) ->
      % socket connect timeout
      T  = proplists:get_value(timeout, S#fsm.opts, ?T_CONNECT),    
  -   % TODO: overwrite default sock opts with user 
      T1 = erlang:now(),
  -   case gen_tcp:connect(check_host(Host), Port, ?SOCK_OPTS ++ Opts, T) of
  +   case gen_tcp:connect(check_host(Host), Port, opts(Opts, ?TCP_OPTS) ++ ?SOCK_OPTS, T) of
         {ok, Sock} ->
            {ok, Peer} = inet:peername(Sock),
            {ok, Addr} = inet:sockname(Sock),
  
positive.code:    {ok, LSock} = gen_tcp:listen(Port, [
        Inet, 
        {ip, IP}, 
        {reuseaddr, true} | ?SOCK_OPTS
     ]),
     pns:register(knet, {iid(Inet), listen, Addr}, self()),
     lager:info("tcp/ip listen on ~p", [Addr]),
  
negative.code:       S
     };
  
  'ESTABLISHED'({tcp, _, Data}, #fsm{peer=Peer, trecv=Cnt}=S) ->
     lager:debug("tcp/ip recv ~p~n~p~n", [Peer, Data]),
     % TODO: flexible flow control
     inet:setopts(S#fsm.sock, [{active, once}]),
     {emit, 
        {tcp, Peer, {recv, Data}},
        'ESTABLISHED',
        S#fsm{trecv=counter:add(now, Cnt)}
     };
     
  'ESTABLISHED'({send, _Peer, Data}, #fsm{peer=Peer, tsend=Cnt}=S) ->
     lager:debug("tcp/ip send ~p~n~p~n", [Peer, Data]),
     case gen_tcp:send(S#fsm.sock, Data) of
        ok ->
           {next_state, 'ESTABLISHED', S#fsm{tsend=counter:add(now, Cnt)}};
        {error, Reason} ->
           lager:error("tcp/ip error ~p, peer ~p", [Reason, Peer]),
           {reply,
  