diff options
| author | Raimo Niskanen <[email protected]> | 2019-02-08 11:41:27 +0100 | 
|---|---|---|
| committer | Raimo Niskanen <[email protected]> | 2019-02-13 14:18:23 +0100 | 
| commit | 96cd83b6efed8ae8a1a0008e24885bae66c1834b (patch) | |
| tree | 56097aece57096bf7fc9e0d485ecbe4a5e0b627b /lib/ssl | |
| parent | 38ce21e37be4578a7a89856ddb91516279e58c13 (diff) | |
| download | otp-96cd83b6efed8ae8a1a0008e24885bae66c1834b.tar.gz otp-96cd83b6efed8ae8a1a0008e24885bae66c1834b.tar.bz2 otp-96cd83b6efed8ae8a1a0008e24885bae66c1834b.zip  | |
Use iovec() internally in send path
Diffstat (limited to 'lib/ssl')
| -rw-r--r-- | lib/ssl/src/ssl.erl | 4 | ||||
| -rw-r--r-- | lib/ssl/src/ssl_connection.erl | 6 | ||||
| -rw-r--r-- | lib/ssl/src/tls_record.erl | 78 | ||||
| -rw-r--r-- | lib/ssl/src/tls_sender.erl | 34 | 
4 files changed, 70 insertions, 52 deletions
diff --git a/lib/ssl/src/ssl.erl b/lib/ssl/src/ssl.erl index a7d6f28c7a..4a6e022661 100644 --- a/lib/ssl/src/ssl.erl +++ b/lib/ssl/src/ssl.erl @@ -1,7 +1,7 @@  %%  %% %CopyrightBegin%  %% -%% Copyright Ericsson AB 1999-2018. All Rights Reserved. +%% Copyright Ericsson AB 1999-2019. All Rights Reserved.  %%  %% Licensed under the Apache License, Version 2.0 (the "License");  %% you may not use this file except in compliance with the License. @@ -626,7 +626,7 @@ close(#sslsocket{pid = {ListenSocket, #config{transport_info={Transport,_, _, _}  send(#sslsocket{pid = [Pid]}, Data) when is_pid(Pid) ->      ssl_connection:send(Pid, Data);  send(#sslsocket{pid = [_, Pid]}, Data) when is_pid(Pid) -> -    tls_sender:send_data(Pid,  erlang:iolist_to_binary(Data)); +    tls_sender:send_data(Pid,  erlang:iolist_to_iovec(Data));  send(#sslsocket{pid = {_, #config{transport_info={_, udp, _, _}}}}, _) ->      {error,enotconn}; %% Emulate connection behaviour  send(#sslsocket{pid = {dtls,_}}, _) -> diff --git a/lib/ssl/src/ssl_connection.erl b/lib/ssl/src/ssl_connection.erl index 461f51dd3a..61524347eb 100644 --- a/lib/ssl/src/ssl_connection.erl +++ b/lib/ssl/src/ssl_connection.erl @@ -211,9 +211,9 @@ socket_control(dtls_connection = Connection, {_, Socket}, [Pid|_] = Pids, Transp  %%--------------------------------------------------------------------  send(Pid, Data) ->       call(Pid, {application_data,  -				    %% iolist_to_binary should really -				    %% be called iodata_to_binary() -				    erlang:iolist_to_binary(Data)}). +				    %% iolist_to_iovec should really +				    %% be called iodata_to_iovec() +				    erlang:iolist_to_iovec(Data)}).  %%--------------------------------------------------------------------  -spec recv(pid(), integer(), timeout()) ->   diff --git a/lib/ssl/src/tls_record.erl b/lib/ssl/src/tls_record.erl index e68f9a19df..7d1f2f5e92 100644 --- a/lib/ssl/src/tls_record.erl +++ b/lib/ssl/src/tls_record.erl @@ -105,8 +105,8 @@ encode_handshake(Frag, Version,  		     ConnectionStates) ->      case iolist_size(Frag) of  	N  when N > ?MAX_PLAIN_TEXT_LENGTH -> -	    Data = split_bin(iolist_to_binary(Frag), Version, BCA, BeastMitigation), -	    encode_iolist(?HANDSHAKE, Version, Data, ConnectionStates); +	    Data = split_iovec(erlang:iolist_to_iovec(Frag), Version, BCA, BeastMitigation), +	    encode_fragments(?HANDSHAKE, Version, Data, ConnectionStates);  	_  ->  	    encode_plain_text(?HANDSHAKE, Version, Frag, ConnectionStates)      end. @@ -137,13 +137,13 @@ encode_change_cipher_spec(Version, ConnectionStates) ->  %%  %% Description: Encodes data to send on the ssl-socket.  %%-------------------------------------------------------------------- -encode_data(Frag, Version, +encode_data(Data, Version,  	    #{current_write := #{beast_mitigation := BeastMitigation,  				 security_parameters :=  				     #security_parameters{bulk_cipher_algorithm = BCA}}} =  		ConnectionStates) -> -    Data = split_bin(Frag, Version, BCA, BeastMitigation), -    encode_iolist(?APPLICATION_DATA, Version, Data, ConnectionStates). +    Fragments = split_iovec(Data, Version, BCA, BeastMitigation), +    encode_fragments(?APPLICATION_DATA, Version, Fragments, ConnectionStates).  %%====================================================================  %% Decoding @@ -520,22 +520,22 @@ binary_from_front(BinSize, [Bin|Front], Size, Rear, Acc) ->  %%--------------------------------------------------------------------  encode_plain_text(Type, Version, Data, ConnectionStates0) -> -    {[CipherText],ConnectionStates} = encode_iolist(Type, Version, [Data], ConnectionStates0), +    {[CipherText],ConnectionStates} = encode_fragments(Type, Version, [Data], ConnectionStates0),      {CipherText,ConnectionStates}.  %%-------------------------------------------------------------------- -encode_iolist(Type, Version, Data, +encode_fragments(Type, Version, Data,                #{current_write := #{compression_state := CompS,                                     cipher_state := CipherS,                                     sequence_number := Seq}} = ConnectionStates) -> -    encode_iolist(Type, Version, Data, ConnectionStates, CompS, CipherS, Seq, []). +    encode_fragments(Type, Version, Data, ConnectionStates, CompS, CipherS, Seq, []).  %% -encode_iolist(_Type, _Version, [], #{current_write := WriteS} = CS, +encode_fragments(_Type, _Version, [], #{current_write := WriteS} = CS,                CompS, CipherS, Seq, CipherFragments) ->      {lists:reverse(CipherFragments),       CS#{current_write := WriteS#{compression_state := CompS,                                    cipher_state := CipherS,                                    sequence_number := Seq}}}; -encode_iolist(Type, Version, [Text|Data], +encode_fragments(Type, Version, [Text|Data],                #{current_write := #{security_parameters :=                                         #security_parameters{cipher_type = ?AEAD,                                                              bulk_cipher_algorithm = BCAlg, @@ -550,9 +550,9 @@ encode_iolist(Type, Version, [Text|Data],      {CipherFragment,CipherS} = ssl_record:cipher_aead(Version, CompText, CipherS1, StartAdditionalData, SecPars),      Length = byte_size(CipherFragment),      CipherHeader = <<?BYTE(Type), VersionBin/binary, ?UINT16(Length)>>, -    encode_iolist(Type, Version, Data, CS, CompS, CipherS, Seq + 1, +    encode_fragments(Type, Version, Data, CS, CompS, CipherS, Seq + 1,                    [[CipherHeader, CipherFragment] | CipherFragments]); -encode_iolist(Type, Version, [Text|Data], +encode_fragments(Type, Version, [Text|Data],                #{current_write := #{security_parameters :=                                         #security_parameters{compression_algorithm = CompAlg,                                                              mac_algorithm = MacAlgorithm} = SecPars, @@ -564,35 +564,49 @@ encode_iolist(Type, Version, [Text|Data],      Length = byte_size(CipherFragment),      {MajVer, MinVer} = Version,      CipherHeader = <<?BYTE(Type), ?BYTE(MajVer), ?BYTE(MinVer), ?UINT16(Length)>>, -    encode_iolist(Type, Version, Data, CS, CompS, CipherS, Seq + 1, +    encode_fragments(Type, Version, Data, CS, CompS, CipherS, Seq + 1,                    [[CipherHeader, CipherFragment] | CipherFragments]); -encode_iolist(_Type, _Version, _Data, CS, _CompS, _CipherS, _Seq, _CipherFragments) -> +encode_fragments(_Type, _Version, _Data, CS, _CompS, _CipherS, _Seq, _CipherFragments) ->      exit({cs, CS}).  %%--------------------------------------------------------------------  %% 1/n-1 splitting countermeasure Rizzo/Duong-Beast, RC4 chiphers are  %% not vulnerable to this attack. -split_bin(<<FirstByte:8, Rest/binary>>, Version, BCA, one_n_minus_one) when -      BCA =/= ?RC4 andalso ({3, 1} == Version orelse -			    {3, 0} == Version) -> -    [[FirstByte]|do_split_bin(Rest)]; +split_iovec([<<FirstByte:8, Rest/binary>>|Data], Version, BCA, one_n_minus_one) +  when (BCA =/= ?RC4) andalso ({3, 1} == Version orelse +                               {3, 0} == Version) -> +    [[FirstByte]|split_iovec([Rest|Data])];  %% 0/n splitting countermeasure for clients that are incompatible with 1/n-1  %% splitting. -split_bin(Bin, Version, BCA, zero_n) when -      BCA =/= ?RC4 andalso ({3, 1} == Version orelse -			    {3, 0} == Version) -> -    [<<>>|do_split_bin(Bin)]; -split_bin(Bin, _, _, _) -> -    do_split_bin(Bin). - -do_split_bin(<<>>) -> []; -do_split_bin(Bin) -> +split_iovec(Data, Version, BCA, zero_n) +  when (BCA =/= ?RC4) andalso ({3, 1} == Version orelse +                               {3, 0} == Version) -> +    [<<>>|split_iovec(Data)]; +split_iovec(Data, _Version, _BCA, _BeatMitigation) -> +    split_iovec(Data). + +split_iovec([]) -> +    []; +split_iovec(Data) -> +    {Part,Rest} = split_iovec(Data, ?MAX_PLAIN_TEXT_LENGTH, []), +    [Part|split_iovec(Rest)]. +%% +split_iovec([Bin|Data], Size, Acc) ->      case Bin of -        <<Chunk:?MAX_PLAIN_TEXT_LENGTH/binary, Rest/binary>> -> -            [Chunk|do_split_bin(Rest)]; -        _ -> -            [Bin] -    end. +        <<Last:Size/binary, Rest/binary>> -> +            {lists:reverse(Acc, [Last]), +             case Rest of +                 <<>> -> +                     Data; +                 <<_/binary>> -> +                     [Rest|Data] +             end}; +        <<_/binary>> -> +            split_iovec(Data, Size - byte_size(Bin), [Bin|Acc]) +    end; +split_iovec([], _Size, Acc) -> +    {lists:reverse(Acc),[]}. +  %%--------------------------------------------------------------------  lowest_list_protocol_version(Ver, []) ->      Ver; diff --git a/lib/ssl/src/tls_sender.erl b/lib/ssl/src/tls_sender.erl index 8ccb8e287f..feda0b8672 100644 --- a/lib/ssl/src/tls_sender.erl +++ b/lib/ssl/src/tls_sender.erl @@ -272,7 +272,7 @@ connection({call, From}, {dist_handshake_complete, _Node, DHandle},                [];            Data ->                [{next_event, internal, -               {application_packets,{self(),undefined},Data}}] +               {application_packets,{self(),undefined},erlang:iolist_to_iovec(Data)}}]        end]};  connection(internal, {application_packets, From, Data}, StateData) ->      send_application_data(Data, From, ?FUNCTION_NAME, StateData); @@ -294,11 +294,11 @@ connection(info, dist_data, #data{static = #static{dist_handle = DHandle}}) ->                [];            Data ->                [{next_event, internal, -               {application_packets,{self(),undefined},Data}}] +               {application_packets,{self(),undefined},erlang:iolist_to_iovec(Data)}}]        end};  connection(info, tick, StateData) ->        consume_ticks(), -    Data = <<0:32>>, % encode_packet(4, <<>>) +    Data = [<<0:32>>], % encode_packet(4, <<>>)      From = {self(), undefined},      send_application_data(Data, From, ?FUNCTION_NAME, StateData);  connection(info, {send, From, Ref, Data}, _StateData) ->  @@ -309,7 +309,7 @@ connection(info, {send, From, Ref, Data}, _StateData) ->      From ! {Ref, ok},      {keep_state_and_data,       [{next_event, {call, {self(), undefined}}, -       {application_data, iolist_to_binary(Data)}}]}; +       {application_data, erlang:iolist_to_iovec(Data)}}]};  ?HANDLE_COMMON.  %%-------------------------------------------------------------------- @@ -432,9 +432,7 @@ send_application_data(Data, From, StateName,              {next_state, handshake, StateData0,                [{next_event, internal, {application_packets, From, Data}}]};  	false -> -	    {Msgs, ConnectionStates} = -                Connection:encode_data( -                  iolist_to_binary(Data), Version, ConnectionStates0), +	    {Msgs, ConnectionStates} = Connection:encode_data(Data, Version, ConnectionStates0),              StateData = StateData0#data{connection_states = ConnectionStates},  	    case Connection:send(Transport, Socket, Msgs) of                  ok when DistHandle =/=  undefined -> @@ -452,9 +450,9 @@ send_application_data(Data, From, StateName,  encode_packet(Packet, Data) ->      Len = iolist_size(Data),      case Packet of -        1 when Len < (1 bsl 8) ->  [<<Len:8>>,Data]; -        2 when Len < (1 bsl 16) -> [<<Len:16>>,Data]; -        4 when Len < (1 bsl 32) -> [<<Len:32>>,Data]; +        1 when Len < (1 bsl 8) ->  [<<Len:8>>|Data]; +        2 when Len < (1 bsl 16) -> [<<Len:16>>|Data]; +        4 when Len < (1 bsl 32) -> [<<Len:32>>|Data];          N when N =:= 1; N =:= 2; N =:= 4 ->              {error,               {badarg, {packet_to_large, Len, (1 bsl (Packet bsl 3)) - 1}}}; @@ -498,11 +496,17 @@ dist_data(DHandle) ->          none ->              erlang:dist_ctrl_get_data_notification(DHandle),              []; -        Data -> -            %% This is encode_packet(4, Data) without Len check -            %% since the emulator will always deliver a Data -            %% smaller than 4 GB, and the distribution will -            %% therefore always have to use {packet,4} +        %% This is encode_packet(4, Data) without Len check +        %% since the emulator will always deliver a Data +        %% smaller than 4 GB, and the distribution will +        %% therefore always have to use {packet,4} +        Data when is_binary(Data) -> +            Len = byte_size(Data), +            [<<Len:32>>,Data|dist_data(DHandle)]; +        [BA,BB] = Data -> +            Len = byte_size(BA) + byte_size(BB), +            [<<Len:32>>,Data|dist_data(DHandle)]; +        Data when is_list(Data) ->              Len = iolist_size(Data),              [<<Len:32>>,Data|dist_data(DHandle)]      end.  | 
