diff --git a/src/mtp_rpc.erl b/src/mtp_rpc.erl index 7d77763..e7156f3 100644 --- a/src/mtp_rpc.erl +++ b/src/mtp_rpc.erl @@ -37,6 +37,9 @@ -define(RPC_SIMPLE_ACK, 155,64,172,59). %0x3bac409b -define(TL_PROXY_TAG, 174,38,30,219). +-define(RPC_PING, 223,162,48,87). %0x5730a2df +-define(RPC_PONG, 167,234,48,132). %0x8430eaa7 + -define(RPC_NONCE, 170,135,203,122). -define(RPC_HANDSHAKE, 245,238,130,118). -define(RPC_FLAGS, 0, 0, 0, 0). @@ -46,7 +49,7 @@ -define(FLAG_HAS_AD_TAG , 16#8). -define(FLAG_MAGIC , 16#1000). -define(FLAG_EXTMODE2 , 16#20000). --define(FLAG_PAD , 16#8000000). %TODO: use it +-define(FLAG_PAD , 16#8000000). -define(FLAG_INTERMEDIATE , 16#20000000). -define(FLAG_ABRIDGED , 16#40000000). -define(FLAG_QUICKACK , 16#80000000). @@ -56,7 +59,8 @@ -type conn_id() :: integer(). -type packet() :: {proxy_ans, conn_id(), binary()} | {close_ext, conn_id()} - | {simple_ack, conn_id(), binary()}. + | {simple_ack, conn_id(), binary()} + | {ping, integer()}. decode_nonce(<>) -> decode_packet(<>) -> %% mtproto/mtproto-proxy.c:push_rpc_confirmation {simple_ack, ConnId, Confirm}; +decode_packet(<>) -> + {ping, PingId}; decode_packet(<>) -> {unknown, Tag, Tail}. -encode_packet({data, Msg}, {{ConnId, ClientAddr, ProxyTag}, ProxyAddr}) -> +%% Maps the client-side transport protocol to the corresponding RPC_PROXY_REQ flags. +%% See net/net-tcp-rpc-ext-server.c for how MTProxy assigns these from the tag byte. +-spec protocol_flag(mtp_abridged | mtp_intermediate | mtp_secure) -> non_neg_integer(). +protocol_flag(mtp_abridged) -> ?FLAG_ABRIDGED; +protocol_flag(mtp_intermediate) -> ?FLAG_INTERMEDIATE; +protocol_flag(mtp_secure) -> ?FLAG_INTERMEDIATE bor ?FLAG_PAD. + +encode_packet({data, Msg}, {{ConnId, ClientAddr, ProxyTag, Protocol}, ProxyAddr}) -> %% See mtproto/mtproto-proxy.c:forward_mtproto_packet ((iolist_size(Msg) rem 4) == 0) orelse error({not_aligned, Msg}), Flags1 = (?FLAG_HAS_AD_TAG bor ?FLAG_MAGIC bor ?FLAG_EXTMODE2 - bor ?FLAG_ABRIDGED), + bor protocol_flag(Protocol)), %% if (auth_key_id) ... Flags = case Msg of %% XXX: what if Msg is iolist? @@ -128,7 +141,9 @@ encode_packet({data, Msg}, {{ConnId, ClientAddr, ProxyTag}, ProxyAddr}) -> | Msg ]; encode_packet(remote_closed, ConnId) -> - <>. + <>; +encode_packet({pong, PingId}, _) -> + <>. %% %% Middle-proxy side encoding and decodong (FOR TESTS ONLY!) @@ -174,7 +189,8 @@ inet_pton(IPv6) when tuple_size(IPv6) == 8 -> tst_new() -> {{1, encode_ip_port({109, 238, 131, 159}, 1128), - <<220,190,143,20,147,250,76,217,171,48,8,145,192,181,179,38>>}, + <<220,190,143,20,147,250,76,217,171,48,8,145,192,181,179,38>>, + mtp_abridged}, encode_ip_port({80, 211, 29, 34}, 53634)}. decode_none_test() -> diff --git a/test/prop_mtp_rpc.erl b/test/prop_mtp_rpc.erl index 474a16e..f20162b 100644 --- a/test/prop_mtp_rpc.erl +++ b/test/prop_mtp_rpc.erl @@ -75,17 +75,18 @@ c2s_packet_gen() -> {{data, mtp_prop_gen:packet_4b() %Data }, - {{proper_types:integer(), %ConnId - proper_types:binary(20), %ClientAddr - proper_types:binary(16) %ProxyTag - }, - proper_types:binary(20) %ProxyAddr - }}, + {{proper_types:integer(), %ConnId + proper_types:binary(20), %ClientAddr + proper_types:binary(16), %ProxyTag + proper_types:oneof([mtp_abridged, mtp_intermediate, mtp_secure]) %Protocol + }, + proper_types:binary(20) %ProxyAddr + }}, {remote_closed, proper_types:integer()} ]). -c2s_packet({{data, Data} = Packet, {{ConnId, _, _}, _} = Static}) -> +c2s_packet({{data, Data} = Packet, {{ConnId, _, _, _}, _} = Static}) -> Bin = mtp_rpc:encode_packet(Packet, Static), {data, ConnId, Data} == mtp_rpc:srv_decode_packet(iolist_to_binary(Bin)); c2s_packet({remote_closed, ConnId} = Packet) ->