aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIngela Anderton Andin <[email protected]>2016-09-23 16:00:00 +0200
committerIngela Anderton Andin <[email protected]>2016-09-27 15:55:55 +0200
commit8757505b5e4e85fd8039412b3ebc2df0326ef325 (patch)
treedfee8828629a6a778807290be7662b3fd787ebc9
parente6059f94571a6c968c15b9de6b7d63ebd64f9acf (diff)
downloadotp-8757505b5e4e85fd8039412b3ebc2df0326ef325.tar.gz
otp-8757505b5e4e85fd8039412b3ebc2df0326ef325.tar.bz2
otp-8757505b5e4e85fd8039412b3ebc2df0326ef325.zip
ssl: Avoid event reordering
Several handshake events may be received in the same TLS packet. Then there will be several events pushed to the gen_statems internal queue. New events already in the socket-buffer should not be processed if there are more unprocessed handshake events in next_event queue. We need to handle this in the next_record/1 function.
-rw-r--r--lib/ssl/src/ssl_connection.hrl1
-rw-r--r--lib/ssl/src/tls_connection.erl13
2 files changed, 12 insertions, 2 deletions
diff --git a/lib/ssl/src/ssl_connection.hrl b/lib/ssl/src/ssl_connection.hrl
index f1e612a41b..d1ed62829c 100644
--- a/lib/ssl/src/ssl_connection.hrl
+++ b/lib/ssl/src/ssl_connection.hrl
@@ -48,6 +48,7 @@
socket_options :: #socket_options{},
connection_states :: ssl_record:connection_states() | secret_printout(),
protocol_buffers :: term() | secret_printout() , %% #protocol_buffers{} from tls_record.hrl or dtls_recor.hrl
+ unprocessed_handshake_events = 0 :: integer(),
tls_handshake_history :: ssl_handshake:ssl_handshake_history() | secret_printout()
| 'undefined',
cert_db :: reference() | 'undefined',
diff --git a/lib/ssl/src/tls_connection.erl b/lib/ssl/src/tls_connection.erl
index 9b9031473a..763f1c7253 100644
--- a/lib/ssl/src/tls_connection.erl
+++ b/lib/ssl/src/tls_connection.erl
@@ -421,7 +421,7 @@ handle_common_event(internal, #ssl_tls{type = ?HANDSHAKE, fragment = Data},
connection ->
ssl_connection:hibernate_after(StateName, State, Events);
_ ->
- {next_state, StateName, State, Events}
+ {next_state, StateName, State#state{unprocessed_handshake_events = unprocessed_events(Events)}, Events}
end
catch throw:#alert{} = Alert ->
ssl_connection:handle_own_alert(Alert, Version, StateName, State0)
@@ -537,7 +537,9 @@ next_tls_record(Data, #state{protocol_buffers = #protocol_buffers{tls_record_buf
#alert{} = Alert ->
Alert
end.
-
+next_record(#state{unprocessed_handshake_events = N} = State) when N > 0 ->
+ {no_record, State#state{unprocessed_handshake_events = N-1}};
+
next_record(#state{protocol_buffers =
#protocol_buffers{tls_packets = [], tls_cipher_texts = [CT | Rest]}
= Buffers,
@@ -712,3 +714,10 @@ gen_info(Event, StateName, #state{negotiated_version = Version} = State) ->
Version, StateName, State)
end.
+unprocessed_events(Events) ->
+ %% The first handshake event will be processed immediately
+ %% as it is entered first in the event queue and
+ %% when it is processed there will be length(Events)-1
+ %% handshake events left to process before we should
+ %% process more TLS-records received on the socket.
+ erlang:length(Events)-1.