diff options
Diffstat (limited to 'lib/ssh/src/ssh_connection.erl')
-rw-r--r-- | lib/ssh/src/ssh_connection.erl | 128 |
1 files changed, 70 insertions, 58 deletions
diff --git a/lib/ssh/src/ssh_connection.erl b/lib/ssh/src/ssh_connection.erl index 2b8780a991..ed03b4e2ed 100644 --- a/lib/ssh/src/ssh_connection.erl +++ b/lib/ssh/src/ssh_connection.erl @@ -64,29 +64,32 @@ bound_channel/3, encode_ip/1 ]). +-type connection_ref() :: ssh:connection_ref(). +-type channel_id() :: ssh:channel_id(). + %%-------------------------------------------------------------------- %%% API %%-------------------------------------------------------------------- %%-------------------------------------------------------------------- --spec session_channel(connection_ref(), timeout()) -> {ok, channel_id()} | {error, timeout | closed}. --spec session_channel(connection_ref(), integer(), integer(), timeout()) -> {ok, channel_id()} | {error, timeout | closed}. - %% Description: Opens a channel for a ssh session. A session is a %% remote execution of a program. The program may be a shell, an %% application, a system command, or some built-in subsystem. %% -------------------------------------------------------------------- +-spec session_channel(connection_ref(), timeout()) -> + {ok, channel_id()} | {error, timeout | closed}. + session_channel(ConnectionHandler, Timeout) -> - session_channel(ConnectionHandler, - ?DEFAULT_WINDOW_SIZE, ?DEFAULT_PACKET_SIZE, - Timeout). + session_channel(ConnectionHandler, ?DEFAULT_WINDOW_SIZE, ?DEFAULT_PACKET_SIZE, Timeout). -session_channel(ConnectionHandler, InitialWindowSize, - MaxPacketSize, Timeout) -> +-spec session_channel(connection_ref(), integer(), integer(), timeout()) -> + {ok, channel_id()} | {error, timeout | closed}. + +session_channel(ConnectionHandler, InitialWindowSize, MaxPacketSize, Timeout) -> case ssh_connection_handler:open_channel(ConnectionHandler, "session", <<>>, - InitialWindowSize, - MaxPacketSize, Timeout) of + InitialWindowSize, + MaxPacketSize, Timeout) of {open, Channel} -> {ok, Channel}; Error -> @@ -94,55 +97,63 @@ session_channel(ConnectionHandler, InitialWindowSize, end. %%-------------------------------------------------------------------- --spec exec(connection_ref(), channel_id(), string(), timeout()) -> - success | failure | {error, timeout | closed}. - %% Description: Will request that the server start the %% execution of the given command. %%-------------------------------------------------------------------- +-spec exec(connection_ref(), channel_id(), string(), timeout()) -> + success | failure | {error, timeout | closed}. + exec(ConnectionHandler, ChannelId, Command, TimeOut) -> ssh_connection_handler:request(ConnectionHandler, self(), ChannelId, "exec", true, [?string(Command)], TimeOut). %%-------------------------------------------------------------------- --spec shell(connection_ref(), channel_id()) -> _. - %% Description: Will request that the user's default shell (typically %% defined in /etc/passwd in UNIX systems) be started at the other %% end. %%-------------------------------------------------------------------- +-spec shell(connection_ref(), channel_id()) -> + ok | success | failure | {error, timeout}. + shell(ConnectionHandler, ChannelId) -> ssh_connection_handler:request(ConnectionHandler, self(), ChannelId, "shell", false, <<>>, 0). %%-------------------------------------------------------------------- --spec subsystem(connection_ref(), channel_id(), string(), timeout()) -> - success | failure | {error, timeout | closed}. %% %% Description: Executes a predefined subsystem. %%-------------------------------------------------------------------- +-spec subsystem(connection_ref(), channel_id(), string(), timeout()) -> + success | failure | {error, timeout | closed}. + subsystem(ConnectionHandler, ChannelId, SubSystem, TimeOut) -> ssh_connection_handler:request(ConnectionHandler, self(), ChannelId, "subsystem", true, [?string(SubSystem)], TimeOut). %%-------------------------------------------------------------------- --spec send(connection_ref(), channel_id(), iodata()) -> - ok | {error, closed}. --spec send(connection_ref(), channel_id(), integer()| iodata(), timeout() | iodata()) -> - ok | {error, timeout} | {error, closed}. --spec send(connection_ref(), channel_id(), integer(), iodata(), timeout()) -> - ok | {error, timeout} | {error, closed}. -%% -%% %% Description: Sends channel data. %%-------------------------------------------------------------------- +-spec send(connection_ref(), channel_id(), iodata()) -> + ok | {error, timeout | closed}. send(ConnectionHandler, ChannelId, Data) -> send(ConnectionHandler, ChannelId, 0, Data, infinity). + + +-spec send(connection_ref(), channel_id(), integer()| iodata(), timeout() | iodata()) -> + ok | {error, timeout | closed}. + send(ConnectionHandler, ChannelId, Data, TimeOut) when is_integer(TimeOut) -> send(ConnectionHandler, ChannelId, 0, Data, TimeOut); + send(ConnectionHandler, ChannelId, Data, infinity) -> send(ConnectionHandler, ChannelId, 0, Data, infinity); + send(ConnectionHandler, ChannelId, Type, Data) -> send(ConnectionHandler, ChannelId, Type, Data, infinity). + + +-spec send(connection_ref(), channel_id(), integer(), iodata(), timeout()) -> + ok | {error, timeout | closed}. + send(ConnectionHandler, ChannelId, Type, Data, TimeOut) -> ssh_connection_handler:send(ConnectionHandler, ChannelId, Type, Data, TimeOut). @@ -156,7 +167,7 @@ send_eof(ConnectionHandler, Channel) -> ssh_connection_handler:send_eof(ConnectionHandler, Channel). %%-------------------------------------------------------------------- --spec adjust_window(connection_ref(), channel_id(), integer()) -> ok | {error, closed}. +-spec adjust_window(connection_ref(), channel_id(), integer()) -> ok. %% %% %% Description: Adjusts the ssh flowcontrol window. @@ -198,17 +209,18 @@ reply_request(_,false, _, _) -> ok. %%-------------------------------------------------------------------- --spec ptty_alloc(connection_ref(), channel_id(), proplists:proplist()) -> - success | failiure | {error, closed}. --spec ptty_alloc(connection_ref(), channel_id(), proplists:proplist(), timeout()) -> - success | failiure | {error, timeout} | {error, closed}. - -%% -%% %% Description: Sends a ssh connection protocol pty_req. %%-------------------------------------------------------------------- +-spec ptty_alloc(connection_ref(), channel_id(), proplists:proplist()) -> + success | failure | {error, timeout}. + ptty_alloc(ConnectionHandler, Channel, Options) -> ptty_alloc(ConnectionHandler, Channel, Options, infinity). + + +-spec ptty_alloc(connection_ref(), channel_id(), proplists:proplist(), timeout()) -> + success | failure | {error, timeout | closed}. + ptty_alloc(ConnectionHandler, Channel, Options0, TimeOut) -> TermData = backwards_compatible(Options0, []), % FIXME {Width, PixWidth} = pty_default_dimensions(width, TermData), @@ -259,7 +271,7 @@ channel_data(ChannelId, DataType, Data, Connection, From) when is_list(Data)-> channel_data(ChannelId, DataType, Data, #connection{channel_cache = Cache} = Connection, From) -> - case ssh_channel:cache_lookup(Cache, ChannelId) of + case ssh_client_channel:cache_lookup(Cache, ChannelId) of #channel{remote_id = Id, sent_close = false} = Channel0 -> {SendList, Channel} = update_send_window(Channel0#channel{flow_control = From}, DataType, @@ -291,9 +303,9 @@ handle_msg(#ssh_msg_channel_open_confirmation{recipient_channel = ChannelId, #connection{channel_cache = Cache} = Connection0, _) -> #channel{remote_id = undefined} = Channel = - ssh_channel:cache_lookup(Cache, ChannelId), + ssh_client_channel:cache_lookup(Cache, ChannelId), - ssh_channel:cache_update(Cache, Channel#channel{ + ssh_client_channel:cache_update(Cache, Channel#channel{ remote_id = RemoteId, recv_packet_size = max(32768, % rfc4254/5.2 min(PacketSz, Channel#channel.recv_packet_size) @@ -307,8 +319,8 @@ handle_msg(#ssh_msg_channel_open_failure{recipient_channel = ChannelId, description = Descr, lang = Lang}, #connection{channel_cache = Cache} = Connection0, _) -> - Channel = ssh_channel:cache_lookup(Cache, ChannelId), - ssh_channel:cache_delete(Cache, ChannelId), + Channel = ssh_client_channel:cache_lookup(Cache, ChannelId), + ssh_client_channel:cache_delete(Cache, ChannelId), reply_msg(Channel, Connection0, {open_error, Reason, Descr, Lang}); handle_msg(#ssh_msg_channel_success{recipient_channel = ChannelId}, Connection, _) -> @@ -323,10 +335,10 @@ handle_msg(#ssh_msg_channel_eof{recipient_channel = ChannelId}, Connection, _) - handle_msg(#ssh_msg_channel_close{recipient_channel = ChannelId}, #connection{channel_cache = Cache} = Connection0, _) -> - case ssh_channel:cache_lookup(Cache, ChannelId) of + case ssh_client_channel:cache_lookup(Cache, ChannelId) of #channel{sent_close = Closed, remote_id = RemoteId, flow_control = FlowControl} = Channel -> - ssh_channel:cache_delete(Cache, ChannelId), + ssh_client_channel:cache_delete(Cache, ChannelId), {CloseMsg, Connection} = reply_msg(Channel, Connection0, {closed, ChannelId}), ConnReplyMsgs = @@ -367,7 +379,7 @@ handle_msg(#ssh_msg_channel_window_adjust{recipient_channel = ChannelId, bytes_to_add = Add}, #connection{channel_cache = Cache} = Connection, _) -> #channel{send_window_size = Size, remote_id = RemoteId} = - Channel0 = ssh_channel:cache_lookup(Cache, ChannelId), + Channel0 = ssh_client_channel:cache_lookup(Cache, ChannelId), {SendList, Channel} = %% TODO: Datatype 0 ? update_send_window(Channel0#channel{send_window_size = Size + Add}, @@ -443,7 +455,7 @@ handle_msg(#ssh_msg_channel_request{recipient_channel = ChannelId, ?BOOLEAN(_Core), ?DEC_BIN(Err, _ErrLen), ?DEC_BIN(Lang, _LangLen)>> = Data, - Channel = ssh_channel:cache_lookup(Cache, ChannelId), + Channel = ssh_client_channel:cache_lookup(Cache, ChannelId), RemoteId = Channel#channel.remote_id, {Reply, Connection} = reply_msg(Channel, Connection0, {exit_signal, ChannelId, @@ -488,7 +500,7 @@ handle_msg(#ssh_msg_channel_request{recipient_channel = ChannelId, <<?DEC_BIN(SsName,_SsLen)>> = Data, #channel{remote_id = RemoteId} = Channel0 = - ssh_channel:cache_lookup(Cache, ChannelId), + ssh_client_channel:cache_lookup(Cache, ChannelId), ReplyMsg = {subsystem, ChannelId, WantReply, binary_to_list(SsName)}, @@ -496,7 +508,7 @@ handle_msg(#ssh_msg_channel_request{recipient_channel = ChannelId, {ok, Pid} = start_subsystem(SsName, Connection, Channel0, ReplyMsg), erlang:monitor(process, Pid), Channel = Channel0#channel{user = Pid}, - ssh_channel:cache_update(Cache, Channel), + ssh_client_channel:cache_update(Cache, Channel), Reply = {connection_reply, channel_success_msg(RemoteId)}, {[Reply], Connection} @@ -576,7 +588,7 @@ handle_msg(#ssh_msg_channel_request{recipient_channel = ChannelId, want_reply = WantReply}, #connection{channel_cache = Cache} = Connection, _) -> if WantReply == true -> - case ssh_channel:cache_lookup(Cache, ChannelId) of + case ssh_client_channel:cache_lookup(Cache, ChannelId) of #channel{remote_id = RemoteId} -> FailMsg = channel_failure_msg(RemoteId), {[{connection_reply, FailMsg}], Connection}; @@ -619,14 +631,14 @@ handle_msg(#ssh_msg_disconnect{code = Code, %%% handle_stop(#connection{channel_cache = Cache} = Connection0) -> {Connection, Replies} = - ssh_channel:cache_foldl( + ssh_client_channel:cache_foldl( fun(Channel, {Connection1, Acc}) -> {Reply, Connection2} = reply_msg(Channel, Connection1, {closed, Channel#channel.local_id}), {Connection2, Reply ++ Acc} end, {Connection0, []}, Cache), - ssh_channel:cache_delete(Cache), + ssh_client_channel:cache_delete(Cache), {Replies, Connection}. %%%---------------------------------------------------------------- @@ -767,7 +779,7 @@ setup_session(#connection{channel_cache = Cache, send_buf = queue:new(), remote_id = RemoteId }, - ssh_channel:cache_update(Cache, Channel), + ssh_client_channel:cache_update(Cache, Channel), OpenConfMsg = channel_open_confirmation_msg(RemoteId, NewChannelID, ?DEFAULT_WINDOW_SIZE, ?DEFAULT_PACKET_SIZE), @@ -810,14 +822,14 @@ start_channel(Cb, Id, Args, SubSysSup, Exec, Opts) -> ChannelSup = ssh_subsystem_sup:channel_supervisor(SubSysSup), case max_num_channels_not_exceeded(ChannelSup, Opts) of true -> - ssh_channel_sup:start_child(ChannelSup, Cb, Id, Args, Exec); + ssh_server_channel_sup:start_child(ChannelSup, Cb, Id, Args, Exec); false -> throw(max_num_channels_exceeded) end. max_num_channels_not_exceeded(ChannelSup, Opts) -> MaxNumChannels = ?GET_OPT(max_channels, Opts), - NumChannels = length([x || {_,_,worker,[ssh_channel]} <- + NumChannels = length([x || {_,_,worker,[ssh_server_channel]} <- supervisor:which_children(ChannelSup)]), %% Note that NumChannels is BEFORE starting a new one NumChannels < MaxNumChannels. @@ -856,7 +868,7 @@ update_send_window(#channel{send_buf = SendBuffer} = Channel, DataType, Data, do_update_send_window(Channel0, Cache) -> {SendMsgs, Channel} = get_window(Channel0, []), - ssh_channel:cache_update(Cache, Channel), + ssh_client_channel:cache_update(Cache, Channel), {SendMsgs, Channel}. get_window(#channel{send_window_size = 0 @@ -907,13 +919,13 @@ flow_control(Channel, Cache) -> flow_control([window_adjusted], Channel, Cache). flow_control([], Channel, Cache) -> - ssh_channel:cache_update(Cache, Channel), + ssh_client_channel:cache_update(Cache, Channel), []; flow_control([_|_], #channel{flow_control = From, send_buf = Buffer} = Channel, Cache) when From =/= undefined -> case queue:is_empty(Buffer) of true -> - ssh_channel:cache_update(Cache, Channel#channel{flow_control = undefined}), + ssh_client_channel:cache_update(Cache, Channel#channel{flow_control = undefined}), [{flow_control, Cache, Channel, From, ok}]; false -> [] @@ -1157,14 +1169,14 @@ backwards_compatible([Value| Rest], Acc) -> handle_cli_msg(C0, ChId, Reply0) -> Cache = C0#connection.channel_cache, - Ch0 = ssh_channel:cache_lookup(Cache, ChId), + Ch0 = ssh_client_channel:cache_lookup(Cache, ChId), case Ch0#channel.user of undefined -> case (catch start_cli(C0, ChId)) of {ok, Pid} -> erlang:monitor(process, Pid), Ch = Ch0#channel{user = Pid}, - ssh_channel:cache_update(Cache, Ch), + ssh_client_channel:cache_update(Cache, Ch), reply_msg(Ch, C0, Reply0); _Other -> Reply = {connection_reply, channel_failure_msg(Ch0#channel.remote_id)}, @@ -1182,10 +1194,10 @@ handle_cli_msg(C0, ChId, Reply0) -> %%% channel_data_reply_msg(ChannelId, Connection, DataType, Data) -> - case ssh_channel:cache_lookup(Connection#connection.channel_cache, ChannelId) of + case ssh_client_channel:cache_lookup(Connection#connection.channel_cache, ChannelId) of #channel{recv_window_size = Size} = Channel -> WantedSize = Size - size(Data), - ssh_channel:cache_update(Connection#connection.channel_cache, + ssh_client_channel:cache_update(Connection#connection.channel_cache, Channel#channel{recv_window_size = WantedSize}), reply_msg(Channel, Connection, {data, ChannelId, DataType, Data}); undefined -> @@ -1194,7 +1206,7 @@ channel_data_reply_msg(ChannelId, Connection, DataType, Data) -> reply_msg(ChId, C, Reply) when is_integer(ChId) -> - reply_msg(ssh_channel:cache_lookup(C#connection.channel_cache, ChId), C, Reply); + reply_msg(ssh_client_channel:cache_lookup(C#connection.channel_cache, ChId), C, Reply); reply_msg(Channel, Connection, {open, _} = Reply) -> request_reply_or_data(Channel, Connection, Reply); |