diff options
author | Anders Svensson <[email protected]> | 2017-08-07 02:59:49 +0200 |
---|---|---|
committer | Anders Svensson <[email protected]> | 2017-08-10 11:16:00 +0200 |
commit | 64e0dbd8f002d076f5d6c079f9166840c5fb17e3 (patch) | |
tree | 072a8586dffcfa4c2803fd8b543a0a98db22eccd /lib/diameter | |
parent | b435807b3aec896493cf3f2fc029c6c12b80ed55 (diff) | |
download | otp-64e0dbd8f002d076f5d6c079f9166840c5fb17e3.tar.gz otp-64e0dbd8f002d076f5d6c079f9166840c5fb17e3.tar.bz2 otp-64e0dbd8f002d076f5d6c079f9166840c5fb17e3.zip |
Simplify extraction of incoming Diameter messages in diameter_tcp
Appending to a binary is efficient, so just append message fragments
Only match out the length once per message since doing so for every
packet from TCP causes the binary to be copied.
Diffstat (limited to 'lib/diameter')
-rw-r--r-- | lib/diameter/src/transport/diameter_tcp.erl | 78 |
1 files changed, 26 insertions, 52 deletions
diff --git a/lib/diameter/src/transport/diameter_tcp.erl b/lib/diameter/src/transport/diameter_tcp.erl index a2f393d5d4..e6168652de 100644 --- a/lib/diameter/src/transport/diameter_tcp.erl +++ b/lib/diameter/src/transport/diameter_tcp.erl @@ -87,8 +87,7 @@ module :: module() | undefined}). -type length() :: 0..16#FFFFFF. %% message length from Diameter header --type size() :: non_neg_integer(). %% accumulated binary size --type frag() :: {length(), size(), binary(), list(binary())} +-type frag() :: maybe_improper_list(length(), binary()) | binary(). -type connect_option() :: {raddr, inet:ip_address()} @@ -721,7 +720,7 @@ tls(accept, Sock, Opts) -> %% Receive packets until a full message is received, recv(Bin, #transport{frag = Head} = S) -> - case rcv(Head, Bin) of + case acc(Head, Bin) of {Msg, B} -> %% have a complete message ... message(recv, Msg, S#transport{frag = B}); Frag -> %% read more on the socket @@ -729,77 +728,52 @@ recv(Bin, #transport{frag = Head} = S) -> flush = false})) end. -%% rcv/2 +%% acc/2 -%% No previous fragment. -rcv(<<>>, Bin) -> - rcv(Bin); +%% Know how many bytes to extract. +acc([Len | Acc], Bin) -> + acc1(Len, <<Acc/binary, Bin/binary>>); -%% Not even the first four bytes of the header. -rcv(Head, Bin) - when is_binary(Head) -> - rcv(<<Head/binary, Bin/binary>>); +%% Or not. +acc(Head, Bin) -> + acc(<<Head/binary, Bin/binary>>). -%% Or enough to know how many bytes to extract. -rcv({Len, N, Head, Acc}, Bin) -> - rcv(Len, N + size(Bin), Head, [Bin | Acc]). - -%% rcv/4 +%% acc1/3 %% Extract a message for which we have all bytes. -rcv(Len, N, Head, Acc) - when Len =< N -> - recv1(Len, bin(Head, Acc)); +acc1(Len, Bin) + when Len =< byte_size(Bin) -> + <<Msg:Len/binary, Rest/binary>> = Bin, + {Msg, Rest}; %% Wait for more packets. -rcv(Len, N, Head, Acc) -> - {Len, N, Head, Acc}. - -%% rcv/1 +acc1(Len, Bin) -> + [Len | Bin]. -%% Nothing left. -rcv(<<>> = Bin) -> - Bin; +%% acc/1 %% The Message Length isn't even sufficient for a header. Chances are %% things will go south from here but if we're lucky then the bytes we %% have extend to an intended message boundary and we can recover by %% simply receiving them. Make it so. -rcv(<<_:1/binary, Len:24, _/binary>> = Bin) +acc(<<_:1/binary, Len:24, _/binary>> = Bin) when Len < 20 -> {Bin, <<>>}; -%% Enough bytes to extract a message. -rcv(<<_:1/binary, Len:24, _/binary>> = Bin) - when Len =< size(Bin) -> - recv1(Len, Bin); - -%% Or not: wait for more packets. -rcv(<<_:1/binary, Len:24, _/binary>> = Head) -> - {Len, size(Head), Head, []}; +%% Know the message length. +acc(<<_:1/binary, Len:24, _/binary>> = Bin) -> + acc1(Len, Bin); %% Not even 4 bytes yet. -rcv(Head) -> - Head. - -%% recv1/2 - -recv1(Len, Bin) -> - <<Msg:Len/binary, Rest/binary>> = Bin, - {Msg, Rest}. - -%% bin/2 - -bin(Head, Acc) -> - list_to_binary([Head | lists:reverse(Acc)]). +acc(Bin) -> + Bin. %% bin/1 -bin({_, _, Head, Acc}) -> - bin(Head, Acc); +bin([_ | Bin]) -> + Bin; -bin(Bin) - when is_binary(Bin) -> +bin(Bin) -> Bin. %% flush/1 |