diff options
| author | Fredrik Gustafsson <[email protected]> | 2012-11-16 15:07:02 +0100 | 
|---|---|---|
| committer | Fredrik Gustafsson <[email protected]> | 2012-11-16 15:07:02 +0100 | 
| commit | 67bb449ebc3e51a39c73b04eefb25feba6e1aa1e (patch) | |
| tree | aa7752f9851ad87409542d206adb279598207841 /lib/ssh/src | |
| parent | 9278347678eea78419c0c310f767eaa1f4be4040 (diff) | |
| parent | 49fef147845655e44f91cd4fdf4be92162e65710 (diff) | |
| download | otp-67bb449ebc3e51a39c73b04eefb25feba6e1aa1e.tar.gz otp-67bb449ebc3e51a39c73b04eefb25feba6e1aa1e.tar.bz2 otp-67bb449ebc3e51a39c73b04eefb25feba6e1aa1e.zip | |
Merge branch 'fredrik/ssh/timer-on-connect/OTP-10514'
* fredrik/ssh/timer-on-connect/OTP-10514:
  New setup in testing idle_time
  Use same connect as the rest of testcases
  Fixed doc
  Added testcase for idle timer
  Not start the idle timer on connect
  Doc about idle_time option to ssh:connect
  Check cache on channel exec
  handle no idle-timer on check cache
  Option idle_time introduced, it will trigger the timer and if it is not given the timer_ref entry is infinity
  Timeout after 1h of idle on connection, which exits the connection
Conflicts:
	lib/ssh/src/ssh.erl
Diffstat (limited to 'lib/ssh/src')
| -rw-r--r-- | lib/ssh/src/ssh.erl | 13 | ||||
| -rw-r--r-- | lib/ssh/src/ssh_connection_manager.erl | 66 | 
2 files changed, 75 insertions, 4 deletions
| diff --git a/lib/ssh/src/ssh.erl b/lib/ssh/src/ssh.erl index 7d68b1d7bd..a569298056 100644 --- a/lib/ssh/src/ssh.erl +++ b/lib/ssh/src/ssh.erl @@ -79,7 +79,7 @@ connect(Host, Port, Options, Timeout) ->  	    DisableIpv6 =  proplists:get_value(ip_v6_disabled, SshOptions, false),  	    Inet = inetopt(DisableIpv6),  	    do_connect(Host, Port, [Inet | SocketOptions],  -		       [{user_pid, self()}, {host, Host} | SshOptions], Timeout, DisableIpv6) +		       [{user_pid, self()}, {host, Host} | fix_idle_time(SshOptions)], Timeout, DisableIpv6)      end.  do_connect(Host, Port, SocketOptions, SshOptions, Timeout, DisableIpv6) -> @@ -246,6 +246,13 @@ shell(Host, Port, Options) ->  %%--------------------------------------------------------------------  %%% Internal functions  %%-------------------------------------------------------------------- +fix_idle_time(SshOptions) -> +    case proplists:get_value(idle_time, SshOptions) of +	undefined -> +	    [{idle_time, infinity}|SshOptions]; +	_ -> +	    SshOptions +    end.  start_daemon(Host, Port, Options, Inet) ->      case handle_options(Options) of  	{error, _Reason} = Error -> @@ -355,6 +362,8 @@ handle_option([{pref_public_key_algs, _} = Opt | Rest], SocketOptions, SshOption      handle_option(Rest, SocketOptions, [handle_ssh_option(Opt) | SshOptions]);  handle_option([{quiet_mode, _} = Opt|Rest], SocketOptions, SshOptions) ->      handle_option(Rest, SocketOptions, [handle_ssh_option(Opt) | SshOptions]); +handle_option([{idle_time, _} = Opt | Rest], SocketOptions, SshOptions) -> +    handle_option(Rest, SocketOptions, [handle_ssh_option(Opt) | SshOptions]);  handle_option([Opt | Rest], SocketOptions, SshOptions) ->      handle_option(Rest, [handle_inet_option(Opt) | SocketOptions], SshOptions). @@ -430,6 +439,8 @@ handle_ssh_option({shell, Value} = Opt) when is_function(Value) ->  handle_ssh_option({quiet_mode, Value} = Opt) when Value == true;   						  Value == false ->       Opt; +handle_ssh_option({idle_time, Value} = Opt) when is_integer(Value), Value > 0 -> +    Opt;  handle_ssh_option(Opt) ->      throw({error, {eoptions, Opt}}). diff --git a/lib/ssh/src/ssh_connection_manager.erl b/lib/ssh/src/ssh_connection_manager.erl index 513b0f86c7..0c1eee5186 100644 --- a/lib/ssh/src/ssh_connection_manager.erl +++ b/lib/ssh/src/ssh_connection_manager.erl @@ -62,6 +62,7 @@  	  latest_channel_id = 0,   	  opts,  	  channel_args, +	  idle_timer_ref, % timerref  	  connected   	 }). @@ -203,6 +204,8 @@ init([client, Opts]) ->      ChannelPid = proplists:get_value(channel_pid, Opts),      self() !   	{start_connection, client, [Parent, Address, Port, SocketOpts, Options]}, +    TimerRef = get_idle_time(Options), +	      {ok, #state{role = client,   		client = ChannelPid,  		connection_state = #connection{channel_cache = Cache, @@ -211,6 +214,7 @@ init([client, Opts]) ->  					       connection_supervisor = Parent,  					       requests = []},  		opts = Opts, +		idle_timer_ref = TimerRef,  		connected = false}}.  %%-------------------------------------------------------------------- @@ -230,6 +234,13 @@ handle_call({request, ChannelPid, ChannelId, Type, Data}, From, State0) ->      %% channel is sent later when reply arrives from the connection      %% handler.       lists:foreach(fun send_msg/1, Replies), +    SshOpts = proplists:get_value(ssh_opts, State0#state.opts), +    case proplists:get_value(idle_time, SshOpts) of +	infinity -> +	    ok; +	_IdleTime -> +	    erlang:send_after(5000, self(), {check_cache, [], []}) +    end,      {noreply, State};  handle_call({request, ChannelId, Type, Data}, From, State0) -> @@ -358,7 +369,7 @@ handle_call({open, ChannelPid, Type, InitialWindowSize, MaxPacketSize, Data},  		       recv_packet_size = MaxPacketSize},      ssh_channel:cache_update(Cache, Channel),      State = add_request(true, ChannelId, From, State1), -    {noreply, State}; +    {noreply, remove_timer_ref(State)};  handle_call({send_window, ChannelId}, _From,   	    #state{connection_state =  @@ -403,6 +414,13 @@ handle_call({close, ChannelId}, _,  	    send_msg({connection_reply, Pid,   		      ssh_connection:channel_close_msg(Id)}),  	    ssh_channel:cache_update(Cache, Channel#channel{sent_close = true}), +	    SshOpts = proplists:get_value(ssh_opts, State#state.opts), +	    case proplists:get_value(idle_time, SshOpts) of +		infinity -> +		    ok; +		_IdleTime -> +		    erlang:send_after(5000, self(), {check_cache, [], []}) +	    end,  	    {reply, ok, State};  	undefined ->   	    {reply, ok, State} @@ -523,7 +541,10 @@ handle_info({start_connection, client,  	    Pid ! {self(), not_connected, Reason},  	    {stop, {shutdown, normal}, State}      end; - +handle_info({check_cache, _ , _},  +	    #state{connection_state =  +		       #connection{channel_cache = Cache}} = State) -> +    {noreply, check_cache(State, Cache)};  handle_info({ssh_cm, _Sender, Msg}, State0) ->      %% Backwards compatibility!        State = cm_message(Msg, State0), @@ -621,6 +642,45 @@ code_change(_OldVsn, State, _Extra) ->  %%--------------------------------------------------------------------  %%% Internal functions  %%-------------------------------------------------------------------- +get_idle_time(SshOptions) -> +    case proplists:get_value(idle_time, SshOptions) of +	infinity -> +	    infinity; +       _IdleTime -> %% We dont want to set the timeout on first connect +	    undefined +    end. +check_cache(State, Cache) -> +    %% Check the number of entries in Cache +    case proplists:get_value(size, ets:info(Cache)) of +	0 -> +	    Opts = proplists:get_value(ssh_opts, State#state.opts), +	    case proplists:get_value(idle_time, Opts) of +		infinity -> +		    State; +		undefined -> +		    State; +		Time -> +		    case State#state.idle_timer_ref of +			undefined -> +			    TimerRef = erlang:send_after(Time, self(), {'EXIT', [], "Timeout"}), +			    State#state{idle_timer_ref=TimerRef}; +			_ -> +			    State +		    end +	    end; +	_ -> +	    State +    end. +remove_timer_ref(State) -> +    case State#state.idle_timer_ref of +	infinity -> %% If the timer is not activated +	    State; +	undefined -> %% If we already has cancelled the timer +	    State; +	TimerRef -> %% Timer is active +	    erlang:cancel_timer(TimerRef), +	    State#state{idle_timer_ref = undefined} +    end.  channel_data(Id, Type, Data, Connection0, ConnectionPid, From, State) ->      case ssh_connection:channel_data(Id, Type, Data, Connection0,  				     ConnectionPid, From) of @@ -718,7 +778,7 @@ handle_channel_down(ChannelPid, #state{connection_state =  		  (_,Acc) ->  		       Acc  	       end, [], Cache), -    {{replies, []}, State}. +    {{replies, []}, check_cache(State, Cache)}.  update_sys(Cache, Channel, Type, ChannelPid) ->      ssh_channel:cache_update(Cache,  | 
