aboutsummaryrefslogtreecommitdiffstats
path: root/lib/ssl/src/ssl_connection.erl
diff options
context:
space:
mode:
Diffstat (limited to 'lib/ssl/src/ssl_connection.erl')
-rw-r--r--lib/ssl/src/ssl_connection.erl55
1 files changed, 36 insertions, 19 deletions
diff --git a/lib/ssl/src/ssl_connection.erl b/lib/ssl/src/ssl_connection.erl
index 3849d240da..d4784604fd 100644
--- a/lib/ssl/src/ssl_connection.erl
+++ b/lib/ssl/src/ssl_connection.erl
@@ -90,6 +90,7 @@
log_alert, % boolean()
renegotiation, % {boolean(), From | internal | peer}
start_or_recv_from, % "gen_fsm From"
+ timer, % start_or_recv_timer
send_queue, % queue()
terminated = false, %
allow_renegotiate = true
@@ -755,8 +756,9 @@ handle_sync_event({application_data, Data}, From, StateName,
get_timeout(State)};
handle_sync_event({start, Timeout}, StartFrom, hello, State) ->
- start_or_recv_cancel_timer(Timeout, StartFrom),
- hello(start, State#state{start_or_recv_from = StartFrom});
+ Timer = start_or_recv_cancel_timer(Timeout, StartFrom),
+ hello(start, State#state{start_or_recv_from = StartFrom,
+ timer = Timer});
%% The two clauses below could happen if a server upgrades a socket in
%% active mode. Note that in this case we are lucky that
@@ -772,8 +774,9 @@ handle_sync_event({start,_}, _From, error, {Error, State = #state{}}) ->
{stop, {shutdown, Error}, {error, Error}, State};
handle_sync_event({start, Timeout}, StartFrom, StateName, State) ->
- start_or_recv_cancel_timer(Timeout, StartFrom),
- {next_state, StateName, State#state{start_or_recv_from = StartFrom}, get_timeout(State)};
+ Timer = start_or_recv_cancel_timer(Timeout, StartFrom),
+ {next_state, StateName, State#state{start_or_recv_from = StartFrom,
+ timer = Timer}, get_timeout(State)};
handle_sync_event(close, _, StateName, State) ->
%% Run terminate before returning
@@ -805,14 +808,16 @@ handle_sync_event({shutdown, How0}, _, StateName,
end;
handle_sync_event({recv, N, Timeout}, RecvFrom, connection = StateName, State0) ->
- start_or_recv_cancel_timer(Timeout, RecvFrom),
- passive_receive(State0#state{bytes_to_read = N, start_or_recv_from = RecvFrom}, StateName);
+ Timer = start_or_recv_cancel_timer(Timeout, RecvFrom),
+ passive_receive(State0#state{bytes_to_read = N,
+ start_or_recv_from = RecvFrom, timer = Timer}, StateName);
%% Doing renegotiate wait with handling request until renegotiate is
%% finished. Will be handled by next_state_is_connection/2.
handle_sync_event({recv, N, Timeout}, RecvFrom, StateName, State) ->
- start_or_recv_cancel_timer(Timeout, RecvFrom),
- {next_state, StateName, State#state{bytes_to_read = N, start_or_recv_from = RecvFrom},
+ Timer = start_or_recv_cancel_timer(Timeout, RecvFrom),
+ {next_state, StateName, State#state{bytes_to_read = N, start_or_recv_from = RecvFrom,
+ timer = Timer},
get_timeout(State)};
handle_sync_event({new_user, User}, _From, StateName,
@@ -982,17 +987,19 @@ handle_info({'DOWN', MonitorRef, _, _, _}, _,
handle_info(allow_renegotiate, StateName, State) ->
{next_state, StateName, State#state{allow_renegotiate = true}, get_timeout(State)};
-handle_info({cancel_start_or_recv, StartFrom}, StateName, #state{renegotiation = {false, first}} = State) when StateName =/= connection ->
+handle_info({cancel_start_or_recv, StartFrom}, StateName,
+ #state{renegotiation = {false, first}} = State) when StateName =/= connection ->
gen_fsm:reply(StartFrom, {error, timeout}),
- {stop, {shutdown, user_timeout}, State};
+ {stop, {shutdown, user_timeout}, State#state{timer = undefined}};
handle_info({cancel_start_or_recv, RecvFrom}, StateName, #state{start_or_recv_from = RecvFrom} = State) ->
gen_fsm:reply(RecvFrom, {error, timeout}),
{next_state, StateName, State#state{start_or_recv_from = undefined,
- bytes_to_read = undefined}, get_timeout(State)};
+ bytes_to_read = undefined,
+ timer = undefined}, get_timeout(State)};
handle_info({cancel_start_or_recv, _RecvFrom}, StateName, State) ->
- {next_state, StateName, State, get_timeout(State)};
+ {next_state, StateName, State#state{timer = undefined}, get_timeout(State)};
handle_info(Msg, StateName, State) ->
Report = io_lib:format("SSL: Got unexpected info: ~p ~n", [Msg]),
@@ -1734,10 +1741,11 @@ passive_receive(State0 = #state{user_data_buffer = Buffer}, StateName) ->
end.
read_application_data(Data, #state{user_application = {_Mon, Pid},
- socket_options = SOpts,
- bytes_to_read = BytesToRead,
- start_or_recv_from = RecvFrom,
- user_data_buffer = Buffer0} = State0) ->
+ socket_options = SOpts,
+ bytes_to_read = BytesToRead,
+ start_or_recv_from = RecvFrom,
+ timer = Timer,
+ user_data_buffer = Buffer0} = State0) ->
Buffer1 = if
Buffer0 =:= <<>> -> Data;
Data =:= <<>> -> Buffer0;
@@ -1746,8 +1754,10 @@ read_application_data(Data, #state{user_application = {_Mon, Pid},
case get_data(SOpts, BytesToRead, Buffer1) of
{ok, ClientData, Buffer} -> % Send data
SocketOpt = deliver_app_data(SOpts, ClientData, Pid, RecvFrom),
+ cancel_timer(Timer),
State = State0#state{user_data_buffer = Buffer,
start_or_recv_from = undefined,
+ timer = undefined,
bytes_to_read = undefined,
socket_options = SocketOpt
},
@@ -2334,9 +2344,11 @@ ack_connection(#state{renegotiation = {true, From}} = State) ->
gen_fsm:reply(From, ok),
State#state{renegotiation = undefined};
ack_connection(#state{renegotiation = {false, first},
- start_or_recv_from = StartFrom} = State) when StartFrom =/= undefined ->
+ start_or_recv_from = StartFrom,
+ timer = Timer} = State) when StartFrom =/= undefined ->
gen_fsm:reply(StartFrom, connected),
- State#state{renegotiation = undefined, start_or_recv_from = undefined};
+ cancel_timer(Timer),
+ State#state{renegotiation = undefined, start_or_recv_from = undefined, timer = undefined};
ack_connection(State) ->
State.
@@ -2474,10 +2486,15 @@ default_hashsign(_Version, KeyExchange)
{null, anon}.
start_or_recv_cancel_timer(infinity, _RecvFrom) ->
- ok;
+ undefined;
start_or_recv_cancel_timer(Timeout, RecvFrom) ->
erlang:send_after(Timeout, self(), {cancel_start_or_recv, RecvFrom}).
+cancel_timer(undefined) ->
+ ok;
+cancel_timer(Timer) ->
+ erlang:cancel_timer(Timer).
+
handle_unrecv_data(StateName, #state{socket = Socket, transport_cb = Transport} = State) ->
inet:setopts(Socket, [{active, false}]),
case Transport:recv(Socket, 0, 0) of