From dff7f1ce02cf1de8233e4e60cc962e346eaee8a8 Mon Sep 17 00:00:00 2001 From: Anders Svensson Date: Sun, 16 Apr 2017 15:02:21 +0200 Subject: Make encoding of Diameter header more efficient On the same theme as the parent commit, building binaries in fewer steps. --- lib/diameter/src/base/diameter_codec.erl | 79 ++++++++++++++++---------------- 1 file changed, 40 insertions(+), 39 deletions(-) (limited to 'lib/diameter/src/base/diameter_codec.erl') diff --git a/lib/diameter/src/base/diameter_codec.erl b/lib/diameter/src/base/diameter_codec.erl index 656c86df5f..8f313e8e39 100644 --- a/lib/diameter/src/base/diameter_codec.erl +++ b/lib/diameter/src/base/diameter_codec.erl @@ -39,8 +39,10 @@ -include_lib("diameter/include/diameter.hrl"). -include("diameter_internal.hrl"). --define(MASK(N,I), ((I) band (1 bsl (N)))). -define(PAD(Len), ((4 - (Len rem 4)) rem 4)). +-define(BIT(B), (if B -> 1; true -> 0 end)). +-define(FLAGS(R,P,E,T), ?BIT(R):1, ?BIT(P):1, ?BIT(E):1, ?BIT(T):1, 0:4). +-define(FLAG(B,D), (if is_boolean(B) -> B; true -> 0 /= (D) end)). -type u32() :: 0..16#FFFFFFFF. -type u24() :: 0..16#FFFFFF. @@ -142,20 +144,22 @@ encode(Mod, Msg) -> e(_, #diameter_packet{msg = [#diameter_header{} = Hdr | As]} = Pkt) -> try encode_avps(reorder(As)) of Avps -> - Length = size(Avps) + 20, + Len = 20 + size(Avps), #diameter_header{version = Vsn, + is_request = R, + is_proxiable = P, + is_error = E, + is_retransmitted = T, cmd_code = Code, application_id = Aid, hop_by_hop_id = Hid, end_to_end_id = Eid} = Hdr, - Flags = make_flags(0, Hdr), - Pkt#diameter_packet{header = Hdr, - bin = < end; e(Mod, #diameter_packet{header = Hdr0, msg = Msg} = Pkt) -> + MsgName = rec2msg(Mod, Msg), + {Code, Flags, Aid} = msg_header(Mod, MsgName, Hdr0), + #diameter_header{version = Vsn, + is_request = R, + is_proxiable = P, + is_error = E, + is_retransmitted = T, hop_by_hop_id = Hid, end_to_end_id = Eid} = Hdr0, - MsgName = rec2msg(Mod, Msg), - {Code, Flags0, Aid} = msg_header(Mod, MsgName, Hdr0), - Flags = make_flags(Flags0, Hdr0), - Hdr = Hdr0#diameter_header{cmd_code = Code, - application_id = Aid, - is_request = 0 /= ?MASK(7, Flags), - is_proxiable = 0 /= ?MASK(6, Flags), - is_error = 0 /= ?MASK(5, Flags), - is_retransmitted = 0 /= ?MASK(4, Flags)}, + RB = ?FLAG(R, Flags band 2#10000000), + PB = ?FLAG(P, Flags band 2#01000000), + EB = ?FLAG(E, Flags band 2#00100000), + TB = ?FLAG(T, Flags band 2#00010000), + Values = values(Msg), try encode_avps(Mod, MsgName, Values) of Avps -> - Length = size(Avps) + 20, - Pkt#diameter_packet{header = Hdr#diameter_header{length = Length}, - bin = <>} catch error: Reason -> + Hdr = Hdr0#diameter_header{cmd_code = Code, + application_id = Aid, + is_request = RB, + is_proxiable = PB, + is_error = EB, + is_retransmitted = TB}, exit({Reason, diameter_lib:get_stacktrace(), Hdr}) end. -%% make_flags/2 - -make_flags(Flags0, #diameter_header{is_request = R, - is_proxiable = P, - is_error = E, - is_retransmitted = T}) -> - {Flags, 3} = lists:foldl(fun(B,{F,N}) -> {mf(B,F,N), N-1} end, - {Flags0, 7}, - [R,P,E,T]), - Flags. - -mf(undefined, F, _) -> - F; -mf(B, F, N) -> %% reset the affected bit - (F bxor (F band (1 bsl N))) bor bit(B, N). - -bit(true, N) -> 1 bsl N; -bit(false, _) -> 0. - %% values/1 values([H|T]) @@ -517,7 +518,7 @@ msg_id(#diameter_packet{header = #diameter_header{} = Hdr}) -> msg_id(#diameter_header{application_id = A, cmd_code = C, is_request = R}) -> - {A, C, if R -> 1; true -> 0 end}; + {A, C, ?BIT(R)}; msg_id(<<_:32, Rbit:1, _:7, CmdCode:24, ApplId:32, _/binary>>) -> {ApplId, CmdCode, Rbit}. -- cgit v1.2.3