YDZ3R5NY7II7WX4Q5O2UQ72TMCABDPPRLEMTTIBH5DGKOLAOPOPAC PFC6VDDZ55HDVMZYGJJOBUA4PTKDYIOBV7GKHT2FCWUJGXHXAPCAC YWCRGWVDIMCPXBQFM23MKCYZCXJJSD733NJEPB6WUU4G4BSREILAC 755UGKECZ3PFYEA2TFFOUZTF27CRQTBZWO7UYFU6WQDJMZDBVPRAC CZG24QKIB45EL7PK4UA6XVG3VEVKI7OAQXN4YMFUKKI2MXLHRANQC AQ2M4QZFKBNHMJF25P275ISB7QV7JWKMFV632PI7NWJJGFXE6Q5AC 55WLMLEEVBRSTAFRZ5RGF7TOGUF5OPVCPA2TMHAQK45OUO7PA3YQC MONVI5STEDKY5ALVMEXJJXDUX6XQRKTFLP7BBNOQML3VSJEM2JAAC encode_post_request(Header, Hashes) when is_list(Hashes) ->[{requestId, RequestId}, {circuitId, CircuitId}, {ttl, TTL}] = Header,TTLBin = encode_varint(TTL),HashCount = encode_varint(length(Hashes)),Msg = [<<2>>, CircuitId, RequestId, TTLBin, HashCount] ++ Hashes,length_encode_fields(Msg).encode_cancel_request(Header, CancelId) when is_binary(CancelId) ->[{requestId, RequestId}, {circuitId, CircuitId}, {ttl, TTL}] = Header,TTLBin = encode_varint(TTL),length_encode_fields([<<3>>, CircuitId, RequestId, TTLBin,CancelId]).
Msg = iolist_to_binary([<<5>>, CircuitId, RequestId, TTLbin,ChannelLen, ChannelBin, FutureBin]),MsgLen = encode_varint(byte_size(Msg)),<<MsgLen/binary, Msg/binary>>.encode_bool(V) when is_boolean(V) ->case V oftrue -> <<1>>;false -> <<0>>end.
length_encode_fields([<<5>>, CircuitId, RequestId, TTLbin,ChannelLen, ChannelBin, FutureBin]).
{ok, LisAddr} = inet:getaddr(Host, inet),LisOpts = [binary, {packet, 0}, {active, false}, {reuseaddr, true}, {ifaddr, LisAddr}],{ok, Lis} = gen_tcp:listen(Port, LisOpts),io:format("Listening on ~p:~p~n", [LisAddr, Port]),Db = db:start_link(cabal),% TODO: supervise this handlerHandler = spawn(fun() -> handle_messages(Db) end),State = #state{handler=Handler, db=Db},server_loop(State, Lis).
{ok, LisAddr} = inet:getaddr(Host, inet),LisOpts = [binary, {packet, 0}, {active, false}, {reuseaddr, true}, {ifaddr, LisAddr}],{ok, Lis} = gen_tcp:listen(Port, LisOpts),io:format("Listening on ~p:~p~n", [LisAddr, Port]),Db = db:start_link(cabal),% TODO: supervise this handlerState = #state{db=Db},Handler = spawn(fun() -> handle_messages(State) end),server_loop(Handler, Lis).
server_loop(State, Lis) ->{ok, Sock} = gen_tcp:accept(Lis, infinity),Handler = spawn(fun() -> decode_loop(State, Sock) end),% TODO: read docs of this linkageok = gen_tcp:controlling_process(Sock, Handler),{ok, {RemoteIp, _}} = inet:peername(Sock),io:format("~n~nIncoming Connection ~p~n", [RemoteIp]),server_loop(State, Lis).
server_loop(Handler, Lis) ->{ok, Sock} = gen_tcp:accept(Lis, infinity),ConnReader = spawn(fun() -> decode_loop(Handler, Sock) end),% TODO: read docs of this linkageok = gen_tcp:controlling_process(Sock, ConnReader),{ok, {RemoteIp, _}} = inet:peername(Sock),io:format("~n~nIncoming Connection ~p (~p)~n", [RemoteIp, Sock]),% init connectionReqId = send_channel_state_request(Sock, "#default", true),Handler ! {newOutRequest, ReqId, Sock},server_loop(Handler, Lis).
{incoming, Conn, [Header, Body]} ->[_, {msgType, MsgType}, _, {requestId, ReqIdBin}, _] = Header,ReqId = hex:bin_to_hexstr(ReqIdBin),io:format("Received RequestId:~p from ~p~n", [ReqId, Conn]),io:format("Type:~p - Body:~p~n", [MsgType, Body]),handle_messages(Db)
{newOutRequest, ReqId, Conn} ->UpdatedOut = maps:put(ReqId, {sent, Conn}, ActiveOut),NewState = State#state{activeOut = UpdatedOut},handle_messages(NewState);{incomingMsg, Conn, Msg} ->[Header, Body] = Msg,[{msgType, MsgType}, _, {requestId, ReqId}] = Header,ReqIdStr = hex:bin_to_hexstr(ReqId),io:format("DEBUG new message Type:~p - Body:~p~n", [MsgType, Body]),case maps:is_key(ReqId, ActiveOut) oftrue ->io:format("Received reply to ~p!~n", [ReqIdStr]),case MsgType of0 ->Hashes = proplists:get_value(hashes, Body),PostReqId = send_post_request(Conn, Hashes),UpdatedOut = maps:put(PostReqId, {sent, Conn}, ActiveOut),NewState = State#state{activeOut = UpdatedOut},handle_messages(NewState);1 ->Posts = proplists:get_value(posts, Body),[io:format("got post reply:~n~p~n", [P]) || P <- Posts]end;%send_cancel_request(Conn, ReqId),%NewState = State#state{activeOut = maps:remove(ReqId, ActiveOut)},%handle_messages(NewState);false ->NewState = State#state{activeIn = maps:put(ReqId, {received, Conn, Msg}, ActiveIn)},io:format("Received incoming RequestId:~p from ~p~n", [ReqIdStr, Conn]),handle_messages(NewState)end,handle_messages(State)
% TODO: track request id
send_cancel_request(Peer, CancelId) ->ReqId = crypto:strong_rand_bytes(4),Header = [{requestId, ReqId},{circuitId, <<0,0,0,0>>},{ttl, 0}],Message = wire:encode_cancel_request(Header, CancelId),ok = gen_tcp:send(Peer, Message),io:format("DEBUG: sending cancel for request(~p) to ~p~n", [hex:bin_to_hexstr(CancelId), Peer]),ReqId.
gen_tcp:send(Peer, Message).
ok = gen_tcp:send(Peer, Message),io:format("DEBUG: sending channel state request(~p) for ~p to ~p~n", [hex:bin_to_hexstr(ReqId),Channel, Peer]),ReqId.send_post_request(Peer, Hashes) ->ReqId = crypto:strong_rand_bytes(4),Header = [{requestId, ReqId},{circuitId, <<0,0,0,0>>},{ttl, 0}],Message = wire:encode_post_request(Header, Hashes),ok = gen_tcp:send(Peer, Message),io:format("DEBUG: sending post request(~p) for ~p hashes to ~p~n", [hex:bin_to_hexstr(ReqId),length(Hashes), Peer]),ReqId.