YWCRGWVDIMCPXBQFM23MKCYZCXJJSD733NJEPB6WUU4G4BSREILAC MONVI5STEDKY5ALVMEXJJXDUX6XQRKTFLP7BBNOQML3VSJEM2JAAC YA3ELS7AQZ2XCZZVNMZOM3TSVCWU7HSBVMDXFCIOFTXAYFZSRL2AC 755UGKECZ3PFYEA2TFFOUZTF27CRQTBZWO7UYFU6WQDJMZDBVPRAC CZG24QKIB45EL7PK4UA6XVG3VEVKI7OAQXN4YMFUKKI2MXLHRANQC WHYWDNSL67TTB2AGAUACXERJ6X54YMNYVC32KJQFEXFFRYA4K3HQC OJ6KWAG7XUCYNQ6T3FRJK2QOP7DBO26PZEWDVH3Q2MJKIBMNWRPQC JGA5PAC4QBPH62IPO4HPJ6ETR6BYZDR6SKE6NOTOP3YZVM4XY62AC 55WLMLEEVBRSTAFRZ5RGF7TOGUF5OPVCPA2TMHAQK45OUO7PA3YQC %% full circleencode_channel_state_req_test() ->TH = make_test_header(),Msg = wire:encode_channel_state_request(TH, "Foo", true),{ok, [Header, Body]} = wire:decode(Msg),[{requestId, Req}, {circuitId, Circ}, _] = TH,?assertEqual(Req, proplists:get_value(requestId, Header)),?assertEqual(Circ, proplists:get_value(circuitId, Header)),?assertEqual(<<"Foo">>, proplists:get_value(channel, Body)),?assertEqual(1, proplists:get_value(future, Body)).make_test_header() ->[{requestId, crypto:strong_rand_bytes(4)},{circuitId, crypto:strong_rand_bytes(4)},{ttl, rand:uniform(20)}].
-export([decode_post_request/1, decode_hash_response/1, decode_cancel_request/1, decode_channel_time_range_request/1, decode_channel_state_request/1, decode_channel_list_request/1, decode_post_response/1, decode_channel_list_response/1]).
-export([decode/1]).%-export([decode_post_request/1, decode_hash_response/1, decode_cancel_request/1, decode_channel_time_range_request/1, decode_channel_state_request/1, decode_channel_list_request/1, decode_post_response/1, decode_channel_list_response/1]).-export([encode_channel_state_request/3]).
encode_channel_state_request(Header, Channel, Future) when is_list(Channel), is_boolean(Future) ->[{requestId, RequestId}, {circuitId, CircuitId}, {ttl, TTL}] = Header,ChannelLen = encode_varint(length(Channel)),ChannelBin = list_to_binary(Channel),FutureBin = encode_bool(Future),TTLbin = encode_varint(TTL),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.decode(Data) ->{ok, [Header, Payload]} = decode_header(Data),Body = case proplists:get_value(msgType, Header) of0 -> decode_hash_response(Payload);1 -> decode_post_response(Payload);2 -> decode_post_request(Payload);3 -> decode_cancel_request(Payload);4 -> decode_channel_time_range_request(Payload);5 -> decode_channel_state_request(Payload);6 -> decode_channel_list_request(Payload);7 -> decode_channel_list_response(Payload)end,{ok, [Header, Body]}.
{MsgType, Rest2} = decode_varint(Rest),<< CircuitId:4/binary, ReqId:4/binary, Rest3/binary >> = Rest2,[ {msgLen, MsgLen}, {msgType, MsgType}, {circuitId, CircuitId}, {requestId, ReqId}, {payload, Rest3}].% TODO: assert message type on all concrete decoders
case MsgLen =:= byte_size(Rest) oftrue ->{MsgType, Rest2} = decode_varint(Rest),<< CircuitId:4/binary, ReqId:4/binary, Rest3/binary >> = Rest2,Header = [ {msgLen, MsgLen}, {msgType, MsgType}, {circuitId, CircuitId}, {requestId, ReqId}],{ok, [Header, Rest3]};false ->% we currently assume the passed data is a full message% but a client _could_ send multiple in a single (tcp) writeerlang:error("TODO: implement proper message chunking")end.
decode_post_response(Data) ->Header = decode_header(Data),Payload = proplists:get_value(payload, Header),[ {header, proplists:delete(payload, Header)}, {posts, decode_list_of_strings(Payload)}
decode_post_response(Payload) ->[ {posts, decode_list_of_strings(Payload)}
decode_channel_list_response(Data) ->Header = decode_header(Data),Payload = proplists:get_value(payload, Header),[ {header, proplists:delete(payload, Header)}, {channels, decode_list_of_strings(Payload)}
decode_channel_list_response(Payload) ->[ {channels, decode_list_of_strings(Payload)}
Db = db:start_link(),Handler = spawn(fun() -> handle_messages() end),State = #state{handler= Handler, db = Db},
Db = db:start_link(cabal),% TODO: supervise this handlerHandler = spawn(fun() -> handle_messages(Db) end),State = #state{handler=Handler, db=Db},
Msg = wire:decode_header(Data),Handler ! {incoming, Conn, Msg},
Result = wire:decode(Data),% not sure if it's good to produce this many messages but i'm fine with it for nowcase Result of{ok, Msg} ->Handler ! {incoming, Conn, Msg};{multiple, Msgs} -> lists:foreach(fun(Msg) ->Handler ! {incoming, conn, Msg} end, Msgs)end,
handle_messages(Db) ->receive{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)end.
handle_messages() ->receive{incoming, Conn, Msg} ->Type = proplists:get_value(msgType, Msg),io:format("Received MsgType: ~p from ~p~n", [Type, Conn]),handle_messages()end.
% TODO: track request idsend_channel_state_request(Peer, Channel, Future) ->Header = [{requestId, crypto:strong_rand_bytes(4)},{circuitId, <<0,0,0,0>>},{ttl, 5}],Message = wire:encode_channel_state_request(Header, Channel, Future),gen_tcp:send(Peer, Message).% H = spawn(fun() -> peer:start_server('localhost', 13333) end).