diff options
author | Hans Nilsson <[email protected]> | 2016-01-04 15:21:51 +0100 |
---|---|---|
committer | Hans Nilsson <[email protected]> | 2016-01-18 12:21:01 +0100 |
commit | b9b704f8b584994cbbb4975133d6032d5d0d294e (patch) | |
tree | ef66a43c8d6318845e370d295db0c3dd4a4baa91 /lib/ssh/src/ssh_message.erl | |
parent | 4d08c9292af4cbefce1e067a0c2b28386843ef55 (diff) | |
download | otp-b9b704f8b584994cbbb4975133d6032d5d0d294e.tar.gz otp-b9b704f8b584994cbbb4975133d6032d5d0d294e.tar.bz2 otp-b9b704f8b584994cbbb4975133d6032d5d0d294e.zip |
ssh: Optimization - inline encoding in ssh_message:encode/1, now 8 times faster.
Also fixes minor error in ssh_protocol_SUITE that the new encoder found.
Diffstat (limited to 'lib/ssh/src/ssh_message.erl')
-rw-r--r-- | lib/ssh/src/ssh_message.erl | 169 |
1 files changed, 92 insertions, 77 deletions
diff --git a/lib/ssh/src/ssh_message.erl b/lib/ssh/src/ssh_message.erl index b6c4496be2..a0e9a4961c 100644 --- a/lib/ssh/src/ssh_message.erl +++ b/lib/ssh/src/ssh_message.erl @@ -32,16 +32,44 @@ -export([encode/1, decode/1, decode_keyboard_interactive_prompts/2]). +-define('2bin'(X), (if is_binary(X) -> X; + is_list(X) -> list_to_binary(X); + X==undefined -> <<>> + end) ). + +-define('E...'(X), ?'2bin'(X)/binary ). +-define(Eboolean(X), ?BOOLEAN(case X of + true -> ?TRUE; + false -> ?FALSE + end) ). +-define(Ebyte(X), ?BYTE(X) ). +-define(Euint32(X), ?UINT32(X) ). +-define(Estring(X), ?STRING(?'2bin'(X)) ). +-define(Estring_utf8(X), ?string_utf8(X)/binary ). +-define(Ename_list(X), ?STRING(ssh_bits:name_list(X)) ). +-define(Empint(X), (ssh_bits:mpint(X))/binary ). +-define(Ebinary(X), ?STRING(X) ). + +%% encode(Msg) -> +%% try encode1(Msg) +%% catch +%% C:E -> +%% io:format('***********************~n~p:~p ~p~n',[C,E,Msg]), +%% error(E) +%% end. + encode(#ssh_msg_global_request{ name = Name, want_reply = Bool, data = Data}) -> - ssh_bits:encode([?SSH_MSG_GLOBAL_REQUEST, - Name, Bool, Data], [byte, string, boolean, '...']); + <<?Ebyte(?SSH_MSG_GLOBAL_REQUEST), ?Estring(Name), ?Eboolean(Bool), ?'E...'(Data)>>; + encode(#ssh_msg_request_success{data = Data}) -> - <<?BYTE(?SSH_MSG_REQUEST_SUCCESS), Data/binary>>; + <<?Ebyte(?SSH_MSG_REQUEST_SUCCESS), Data/binary>>; + encode(#ssh_msg_request_failure{}) -> - <<?BYTE(?SSH_MSG_REQUEST_FAILURE)>>; + <<?Ebyte(?SSH_MSG_REQUEST_FAILURE)>>; + encode(#ssh_msg_channel_open{ channel_type = Type, sender_channel = Sender, @@ -49,9 +77,8 @@ encode(#ssh_msg_channel_open{ maximum_packet_size = Max, data = Data }) -> - ssh_bits:encode([?SSH_MSG_CHANNEL_OPEN, - Type, Sender, Window, Max, Data], [byte, string, uint32, - uint32, uint32, '...']); + <<?Ebyte(?SSH_MSG_CHANNEL_OPEN), ?Estring(Type), ?Euint32(Sender), ?Euint32(Window), ?Euint32(Max), ?'E...'(Data)>>; + encode(#ssh_msg_channel_open_confirmation{ recipient_channel = Recipient, sender_channel = Sender, @@ -59,60 +86,63 @@ encode(#ssh_msg_channel_open_confirmation{ maximum_packet_size = MaxPacketSize, data = Data }) -> - ssh_bits:encode([?SSH_MSG_CHANNEL_OPEN_CONFIRMATION, Recipient, - Sender, InitWindowSize, MaxPacketSize, Data], - [byte, uint32, uint32, uint32, uint32, '...']); + <<?Ebyte(?SSH_MSG_CHANNEL_OPEN_CONFIRMATION), + ?Euint32(Recipient), ?Euint32(Sender), ?Euint32(InitWindowSize), ?Euint32(MaxPacketSize), + ?'E...'(Data)>>; + encode(#ssh_msg_channel_open_failure{ recipient_channel = Recipient, reason = Reason, description = Desc, lang = Lang }) -> - ssh_bits:encode([?SSH_MSG_CHANNEL_OPEN_FAILURE, Recipient, - Reason, Desc, Lang], [byte, uint32, uint32, string, string]); + <<?Ebyte(?SSH_MSG_CHANNEL_OPEN_FAILURE), ?Euint32(Recipient),?Euint32(Reason), ?Estring(Desc), ?Estring(Lang)>>; + encode(#ssh_msg_channel_window_adjust{ recipient_channel = Recipient, bytes_to_add = Bytes }) -> - ssh_bits:encode([?SSH_MSG_CHANNEL_WINDOW_ADJUST, Recipient, Bytes], - [byte, uint32, uint32]); + <<?Ebyte(?SSH_MSG_CHANNEL_WINDOW_ADJUST), ?Euint32(Recipient), ?Euint32(Bytes)>>; + encode(#ssh_msg_channel_data{ recipient_channel = Recipient, data = Data }) -> - ssh_bits:encode([?SSH_MSG_CHANNEL_DATA, Recipient, Data], [byte, uint32, binary]); + <<?Ebyte(?SSH_MSG_CHANNEL_DATA), ?Euint32(Recipient), ?Ebinary(Data)>>; encode(#ssh_msg_channel_extended_data{ recipient_channel = Recipient, data_type_code = DataType, data = Data }) -> - ssh_bits:encode([?SSH_MSG_CHANNEL_EXTENDED_DATA, Recipient, - DataType, Data], [byte, uint32, uint32, binary]); + <<?Ebyte(?SSH_MSG_CHANNEL_EXTENDED_DATA), ?Euint32(Recipient), ?Euint32(DataType), ?Ebinary(Data)>>; encode(#ssh_msg_channel_eof{recipient_channel = Recipient }) -> - <<?BYTE(?SSH_MSG_CHANNEL_EOF), ?UINT32(Recipient)>>; + <<?Ebyte(?SSH_MSG_CHANNEL_EOF), ?Euint32(Recipient)>>; + encode(#ssh_msg_channel_close{ recipient_channel = Recipient }) -> - <<?BYTE(?SSH_MSG_CHANNEL_CLOSE), ?UINT32(Recipient)>>; + <<?Ebyte(?SSH_MSG_CHANNEL_CLOSE), ?Euint32(Recipient)>>; + encode(#ssh_msg_channel_request{ recipient_channel = Recipient, request_type = Type, want_reply = Bool, data = Data }) -> - ssh_bits:encode([?SSH_MSG_CHANNEL_REQUEST, Recipient, Type, Bool, Data], - [byte, uint32, string, boolean, '...']); + <<?Ebyte(?SSH_MSG_CHANNEL_REQUEST), ?Euint32(Recipient), ?Estring(Type), ?Eboolean(Bool), ?'E...'(Data)>>; + encode(#ssh_msg_channel_success{ recipient_channel = Recipient }) -> - <<?BYTE(?SSH_MSG_CHANNEL_SUCCESS), ?UINT32(Recipient)>>; + <<?Ebyte(?SSH_MSG_CHANNEL_SUCCESS), ?Euint32(Recipient)>>; + encode(#ssh_msg_channel_failure{ recipient_channel = Recipient }) -> - <<?BYTE(?SSH_MSG_CHANNEL_FAILURE), ?UINT32(Recipient)>>; + <<?Ebyte(?SSH_MSG_CHANNEL_FAILURE), ?Euint32(Recipient)>>; encode(#ssh_msg_userauth_request{ user = User, @@ -120,36 +150,33 @@ encode(#ssh_msg_userauth_request{ method = Method, data = Data }) -> - ssh_bits:encode([?SSH_MSG_USERAUTH_REQUEST, User, Service, Method, Data], - [byte, string_utf8, string, string, '...']); + <<?Ebyte(?SSH_MSG_USERAUTH_REQUEST), ?Estring_utf8(User), ?Estring(Service), ?Estring(Method), ?'E...'(Data)>>; + encode(#ssh_msg_userauth_failure{ authentications = Auths, partial_success = Bool }) -> - ssh_bits:encode([?SSH_MSG_USERAUTH_FAILURE, Auths, Bool], - [byte, string, boolean]); + <<?Ebyte(?SSH_MSG_USERAUTH_FAILURE), ?Estring(Auths), ?Eboolean(Bool)>>; + encode(#ssh_msg_userauth_success{}) -> - <<?BYTE(?SSH_MSG_USERAUTH_SUCCESS)>>; + <<?Ebyte(?SSH_MSG_USERAUTH_SUCCESS)>>; encode(#ssh_msg_userauth_banner{ message = Banner, language = Lang }) -> - ssh_bits:encode([?SSH_MSG_USERAUTH_BANNER, Banner, Lang], - [byte, string_utf8, string]); + <<?Ebyte(?SSH_MSG_USERAUTH_BANNER), ?Estring_utf8(Banner), ?Estring(Lang)>>; encode(#ssh_msg_userauth_pk_ok{ algorithm_name = Alg, key_blob = KeyBlob }) -> - ssh_bits:encode([?SSH_MSG_USERAUTH_PK_OK, Alg, KeyBlob], - [byte, string, binary]); + <<?Ebyte(?SSH_MSG_USERAUTH_PK_OK), ?Estring(Alg), ?Ebinary(KeyBlob)>>; encode(#ssh_msg_userauth_passwd_changereq{prompt = Prompt, languge = Lang })-> - ssh_bits:encode([?SSH_MSG_USERAUTH_PASSWD_CHANGEREQ, Prompt, Lang], - [byte, string, string]); + <<?Ebyte(?SSH_MSG_USERAUTH_PASSWD_CHANGEREQ), ?Estring(Prompt), ?Estring(Lang)>>; encode(#ssh_msg_userauth_info_request{ name = Name, @@ -157,41 +184,37 @@ encode(#ssh_msg_userauth_info_request{ language_tag = Lang, num_prompts = NumPromtps, data = Data}) -> - ssh_bits:encode([?SSH_MSG_USERAUTH_INFO_REQUEST, Name, Inst, Lang, NumPromtps, Data], - [byte, string, string, string, uint32, '...']); + <<?Ebyte(?SSH_MSG_USERAUTH_INFO_REQUEST), ?Estring(Name), ?Estring(Inst), ?Estring(Lang), + ?Euint32(NumPromtps), ?'E...'(Data)>>; encode(#ssh_msg_userauth_info_response{ num_responses = Num, data = Data}) -> - Responses = lists:map(fun("") -> - <<>>; - (Response) -> - ssh_bits:encode([Response], [string]) - end, Data), - Start = ssh_bits:encode([?SSH_MSG_USERAUTH_INFO_RESPONSE, Num], - [byte, uint32]), - iolist_to_binary([Start, Responses]); + lists:foldl(fun %%("", Acc) -> Acc; % commented out since it seem wrong + (Response, Acc) -> <<Acc/binary, ?Estring(Response)>> + end, + <<?Ebyte(?SSH_MSG_USERAUTH_INFO_RESPONSE), ?Euint32(Num)>>, + Data); encode(#ssh_msg_disconnect{ code = Code, description = Desc, language = Lang }) -> - ssh_bits:encode([?SSH_MSG_DISCONNECT, Code, Desc, Lang], - [byte, uint32, string, string]); + <<?Ebyte(?SSH_MSG_DISCONNECT), ?Euint32(Code), ?Estring(Desc), ?Estring(Lang)>>; encode(#ssh_msg_service_request{ name = Service }) -> - ssh_bits:encode([?SSH_MSG_SERVICE_REQUEST, Service], [byte, string]); + <<?Ebyte(?SSH_MSG_SERVICE_REQUEST), ?Estring(Service)>>; encode(#ssh_msg_service_accept{ name = Service }) -> - ssh_bits:encode([?SSH_MSG_SERVICE_ACCEPT, Service], [byte, string]); + <<?Ebyte(?SSH_MSG_SERVICE_ACCEPT), ?Estring(Service)>>; encode(#ssh_msg_newkeys{}) -> - <<?BYTE(?SSH_MSG_NEWKEYS)>>; + <<?Ebyte(?SSH_MSG_NEWKEYS)>>; encode(#ssh_msg_kexinit{ cookie = Cookie, @@ -208,19 +231,13 @@ encode(#ssh_msg_kexinit{ first_kex_packet_follows = Bool, reserved = Reserved }) -> - ssh_bits:encode([?SSH_MSG_KEXINIT, Cookie, KeyAlgs, HostKeyAlgs, EncAlgC2S, EncAlgS2C, - MacAlgC2S, MacAlgS2C, CompAlgS2C, CompAlgC2S, LangC2S, LangS2C, Bool, - Reserved], - [byte, cookie, - name_list, name_list, - name_list, name_list, - name_list, name_list, - name_list, name_list, - name_list, name_list, - boolean, uint32]); + <<?Ebyte(?SSH_MSG_KEXINIT), Cookie/binary, + ?Ename_list(KeyAlgs), ?Ename_list(HostKeyAlgs), ?Ename_list(EncAlgC2S), ?Ename_list(EncAlgS2C), ?Ename_list(MacAlgC2S), + ?Ename_list(MacAlgS2C), ?Ename_list(CompAlgS2C), ?Ename_list(CompAlgC2S), ?Ename_list(LangC2S), ?Ename_list(LangS2C), + ?Eboolean(Bool), ?Euint32(Reserved)>>; encode(#ssh_msg_kexdh_init{e = E}) -> - ssh_bits:encode([?SSH_MSG_KEXDH_INIT, E], [byte, mpint]); + <<?Ebyte(?SSH_MSG_KEXDH_INIT), ?Empint(E)>>; encode(#ssh_msg_kexdh_reply{ public_host_key = Key, @@ -229,25 +246,23 @@ encode(#ssh_msg_kexdh_reply{ }) -> EncKey = public_key:ssh_encode(Key, ssh2_pubkey), EncSign = encode_signature(Key, Signature), - ssh_bits:encode([?SSH_MSG_KEXDH_REPLY, EncKey, F, EncSign], [byte, binary, mpint, binary]); + <<?Ebyte(?SSH_MSG_KEXDH_REPLY), ?Ebinary(EncKey), ?Empint(F), ?Ebinary(EncSign)>>; encode(#ssh_msg_kex_dh_gex_request{ min = Min, n = N, max = Max }) -> - ssh_bits:encode([?SSH_MSG_KEX_DH_GEX_REQUEST, Min, N, Max], - [byte, uint32, uint32, uint32]); + <<?Ebyte(?SSH_MSG_KEX_DH_GEX_REQUEST), ?Euint32(Min), ?Euint32(N), ?Euint32(Max)>>; + encode(#ssh_msg_kex_dh_gex_request_old{n = N}) -> - ssh_bits:encode([?SSH_MSG_KEX_DH_GEX_REQUEST_OLD, N], - [byte, uint32]); + <<?Ebyte(?SSH_MSG_KEX_DH_GEX_REQUEST_OLD), ?Euint32(N)>>; encode(#ssh_msg_kex_dh_gex_group{p = Prime, g = Generator}) -> - ssh_bits:encode([?SSH_MSG_KEX_DH_GEX_GROUP, Prime, Generator], - [byte, mpint, mpint]); + <<?Ebyte(?SSH_MSG_KEX_DH_GEX_GROUP), ?Empint(Prime), ?Empint(Generator)>>; encode(#ssh_msg_kex_dh_gex_init{e = Public}) -> - ssh_bits:encode([?SSH_MSG_KEX_DH_GEX_INIT, Public], [byte, mpint]); + <<?Ebyte(?SSH_MSG_KEX_DH_GEX_INIT), ?Empint(Public)>>; encode(#ssh_msg_kex_dh_gex_reply{ %% Will be private key encode_host_key extracts only the public part! @@ -257,26 +272,26 @@ encode(#ssh_msg_kex_dh_gex_reply{ }) -> EncKey = public_key:ssh_encode(Key, ssh2_pubkey), EncSign = encode_signature(Key, Signature), - ssh_bits:encode([?SSH_MSG_KEX_DH_GEX_REPLY, EncKey, F, EncSign], [byte, binary, mpint, binary]); + <<?Ebyte(?SSH_MSG_KEX_DH_GEX_REPLY), ?Ebinary(EncKey), ?Empint(F), ?Ebinary(EncSign)>>; encode(#ssh_msg_kex_ecdh_init{q_c = Q_c}) -> - ssh_bits:encode([?SSH_MSG_KEX_ECDH_INIT, Q_c], [byte, mpint]); + <<?Ebyte(?SSH_MSG_KEX_ECDH_INIT), ?Empint(Q_c)>>; encode(#ssh_msg_kex_ecdh_reply{public_host_key = Key, q_s = Q_s, h_sig = Sign}) -> EncKey = public_key:ssh_encode(Key, ssh2_pubkey), EncSign = encode_signature(Key, Sign), - ssh_bits:encode([?SSH_MSG_KEX_ECDH_REPLY, EncKey, Q_s, EncSign], [byte, binary, mpint, binary]); + <<?Ebyte(?SSH_MSG_KEX_ECDH_REPLY), ?Ebinary(EncKey), ?Empint(Q_s), ?Ebinary(EncSign)>>; encode(#ssh_msg_ignore{data = Data}) -> - ssh_bits:encode([?SSH_MSG_IGNORE, Data], [byte, string]); + <<?Ebyte(?SSH_MSG_IGNORE), ?Estring(Data)>>; encode(#ssh_msg_unimplemented{sequence = Seq}) -> - ssh_bits:encode([?SSH_MSG_UNIMPLEMENTED, Seq], [byte, uint32]); + <<?Ebyte(?SSH_MSG_UNIMPLEMENTED), ?Euint32(Seq)>>; encode(#ssh_msg_debug{always_display = Bool, message = Msg, language = Lang}) -> - ssh_bits:encode([?SSH_MSG_DEBUG, Bool, Msg, Lang], [byte, boolean, string, string]). + <<?Ebyte(?SSH_MSG_DEBUG), ?Eboolean(Bool), ?Estring(Msg), ?Estring(Lang)>>. %% Connection Messages @@ -553,10 +568,10 @@ decode_signature(<<?DEC_BIN(_Alg,__0), ?UINT32(_), Signature/binary>>) -> encode_signature(#'RSAPublicKey'{}, Signature) -> - ssh_bits:encode(["ssh-rsa", Signature],[string, binary]); + <<?Ebinary(<<"ssh-rsa">>), ?Ebinary(Signature)>>; encode_signature({_, #'Dss-Parms'{}}, Signature) -> - ssh_bits:encode(["ssh-dss", Signature],[string, binary]); + <<?Ebinary(<<"ssh-dss">>), ?Ebinary(Signature)>>; encode_signature({#'ECPoint'{}, {namedCurve,OID}}, Signature) -> CurveName = public_key:oid2ssh_curvename(OID), - ssh_bits:encode([<<"ecdsa-sha2-",CurveName/binary>>, Signature], [binary,binary]). + <<?Ebinary(<<"ecdsa-sha2-",CurveName/binary>>), ?Ebinary(Signature)>>. |