forked from seriyps/mtproto_proxy
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmtp_intermediate.erl
73 lines (62 loc) · 2.06 KB
/
mtp_intermediate.erl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
%%% @author Sergey <[email protected]>
%%% @copyright (C) 2018, Sergey
%%% @doc
%%% MTProto intermediate protocol
%%% @end
%%% Created : 18 Jun 2018 by Sergey <[email protected]>
-module(mtp_intermediate).
-behaviour(mtp_codec).
-export([new/0,
new/1,
try_decode_packet/2,
encode_packet/2]).
-export_type([codec/0]).
-dialyzer(no_improper_lists).
-record(int_st,
{padding = false :: boolean()}).
-define(MAX_PACKET_SIZE, 1 * 1024 * 1024). % 1mb
-define(APP, mtproto_proxy).
-define(MAX_SIZE, 16#80000000).
-opaque codec() :: #int_st{}.
new() ->
new(#{}).
new(Opts) ->
#int_st{padding = maps:get(padding, Opts, false)}.
-spec try_decode_packet(binary(), codec()) -> {ok, binary(), binary(), codec()}
| {incomplete, codec()}.
try_decode_packet(<<Len:32/unsigned-little, Tail/binary>>, St) ->
Len1 = case Len < ?MAX_SIZE of
true -> Len;
false -> Len - ?MAX_SIZE
end,
(Len1 < ?MAX_PACKET_SIZE)
orelse
begin
error({protocol_error, intermediate_max_size, Len1})
end,
try_decode_packet_len(Len1, Tail, St);
try_decode_packet(_, St) ->
{incomplete, St}.
try_decode_packet_len(Len, Data, #int_st{padding = Pad} = St) ->
Padding = case Pad of
true -> Len rem 4;
false -> 0
end,
NopadLen = Len - Padding,
case Data of
<<Packet:NopadLen/binary, _Padding:Padding/binary, Rest/binary>> ->
{ok, Packet, Rest, St};
_ ->
{incomplete, St}
end.
-spec encode_packet(iodata(), codec()) -> {iodata(), codec()}.
encode_packet(Data, #int_st{padding = Pad} = St) ->
Size = iolist_size(Data),
Packet = case Pad of
false -> [<<Size:32/little>> | Data];
true ->
PadSize = rand:uniform(4) - 1,
Padding = crypto:strong_rand_bytes(PadSize), % 0 is ok
[<<(Size + PadSize):32/little>>, Data | Padding]
end,
{Packet, St}.