diff options
| author | Elizabeth Hunt <elizabeth.hunt@simponic.xyz> | 2023-10-01 20:41:48 -0600 |
|---|---|---|
| committer | Elizabeth Hunt <elizabeth.hunt@simponic.xyz> | 2023-10-01 20:41:48 -0600 |
| commit | ffa3d553f693494c218a0244c946ba83dfbf7cd1 (patch) | |
| tree | 092a824dad118c37960ab67da98cdbc445a35d2b /lib/ssh/conn_cli_manager.ex | |
| download | tronglessh-ffa3d553f693494c218a0244c946ba83dfbf7cd1.tar.gz tronglessh-ffa3d553f693494c218a0244c946ba83dfbf7cd1.zip | |
Diffstat (limited to 'lib/ssh/conn_cli_manager.ex')
| -rw-r--r-- | lib/ssh/conn_cli_manager.ex | 143 |
1 files changed, 143 insertions, 0 deletions
diff --git a/lib/ssh/conn_cli_manager.ex b/lib/ssh/conn_cli_manager.ex new file mode 100644 index 0000000..19360f8 --- /dev/null +++ b/lib/ssh/conn_cli_manager.ex @@ -0,0 +1,143 @@ +defmodule TrongleSSH.SSH.ConnectionCLIManager do + alias TrongleSSH.SSH.{Session, Tui} + alias IO.ANSI + require Logger + + @behaviour :ssh_server_channel + @session_closed_message [ + ANSI.clear(), + ["This session has been closed."] + ] + + defmodule State do + defstruct channel_id: nil, + width: nil, + height: nil, + client_pid: nil, + connection_ref: nil, + session: %Session{} + end + + def init([%State{} = init_state]) do + {:ok, init_state} + end + + def handle_msg({:ssh_channel_up, channel_id, connection_ref}, %State{} = state) do + connected_user = + :ssh.connection_info(connection_ref) + |> Keyword.fetch!(:user) + |> String.Chars.to_string() + + {:ok, + %State{ + state + | channel_id: channel_id, + connection_ref: connection_ref, + session: %Session{username: connected_user} + }} + end + + def handle_msg( + {:EXIT, client_pid, _reason}, + %State{client_pid: client_pid, channel_id: channel_id} = state + ) do + send(client_pid, :quit) + {:stop, channel_id, state} + end + + def handle_msg( + {:send_data, data}, + %State{connection_ref: connection_ref, channel_id: channel_id} = state + ) do + :ssh_connection.send(connection_ref, channel_id, data) + {:ok, state} + end + + def handle_msg( + :session_closed, + %State{connection_ref: connection_ref, channel_id: channel_id} = state + ) do + :ssh_connection.send(connection_ref, channel_id, @session_closed_message) + {:stop, channel_id, state} + end + + def handle_msg(msg, term) do + Logger.debug("Unknown msg #{inspect(msg)}, #{inspect(term)}") + end + + def handle_ssh_msg( + {:ssh_cm, _connection_handler, {:data, _channel_id, _type, data}}, + %State{} = state + ) do + send(state.client_pid, {:data, data}) + {:ok, state} + end + + def handle_ssh_msg( + {:ssh_cm, connection_handler, + {:pty, channel_id, want_reply?, {_term, width, height, _pixwidth, _pixheight, _opts}}}, + %State{} = state + ) do + :ssh_connection.reply_request(connection_handler, want_reply?, :success, channel_id) + + {:ok, + %{ + state + | width: width, + height: height + }} + end + + def handle_ssh_msg( + {:ssh_cm, connection_handler, {:env, channel_id, want_reply?, _var, _value}}, + state + ) do + :ssh_connection.reply_request(connection_handler, want_reply?, :failure, channel_id) + {:ok, state} + end + + def handle_ssh_msg( + {:ssh_cm, _connection_handler, + {:window_change, _channel_id, width, height, _pixwidth, _pixheight}}, + %State{client_pid: client_pid} = state + ) do + send(client_pid, {:resize, {width, height}}) + + {:ok, + %State{ + state + | width: width, + height: height + }} + end + + def handle_ssh_msg( + {:ssh_cm, connection_handler, {:shell, channel_id, want_reply?}}, + %State{width: width, height: height, session: session} = state + ) do + :ssh_connection.reply_request(connection_handler, want_reply?, :success, channel_id) + + {:ok, client_pid} = + GenServer.start_link(Tui, [ + %Tui.State{ + connection_manager_pid: self(), + width: width, + height: height, + session: session + } + ]) + + send(client_pid, :refresh) + {:ok, %State{state | client_pid: client_pid}} + end + + def handle_ssh_msg( + msg, + %State{channel_id: channel_id} = state + ) do + Logger.debug("unknown ssh #{inspect(msg)}") + {:stop, channel_id, state} + end + + def terminate(_reason, _state), do: :ok +end |
