summaryrefslogtreecommitdiff
path: root/lib/chessh/ssh/tui.ex
diff options
context:
space:
mode:
authorSimponic <loganhunt@simponic.xyz>2022-12-31 02:29:38 -0700
committerSimponic <loganhunt@simponic.xyz>2022-12-31 02:31:58 -0700
commit58d0b1a89c461467c9ea6229f9a6b3d5ed573da5 (patch)
treef0e91ce7bccb93e755357395f1ed7a7a18d6257b /lib/chessh/ssh/tui.ex
parent3308036c0859dcca2d80d80396a19a3cca269e78 (diff)
downloadchessh-58d0b1a89c461467c9ea6229f9a6b3d5ed573da5.tar.gz
chessh-58d0b1a89c461467c9ea6229f9a6b3d5ed573da5.zip
A simple stalling TUI! Also, ensure sessions are counted correctly. Next up, some way of pub-sub across multiple nodes
Diffstat (limited to 'lib/chessh/ssh/tui.ex')
-rw-r--r--lib/chessh/ssh/tui.ex163
1 files changed, 163 insertions, 0 deletions
diff --git a/lib/chessh/ssh/tui.ex b/lib/chessh/ssh/tui.ex
new file mode 100644
index 0000000..78360a9
--- /dev/null
+++ b/lib/chessh/ssh/tui.ex
@@ -0,0 +1,163 @@
+defmodule Chessh.SSH.Tui do
+ require Logger
+
+ @behaviour :ssh_server_channel
+
+ def init(opts) do
+ Logger.debug("#{inspect(opts)}")
+
+ {:ok,
+ %{
+ channel: nil,
+ cm: nil,
+ pty: %{term: nil, width: nil, height: nil, pixwidth: nil, pixheight: nil, modes: nil},
+ shell: false,
+ client_pid: nil
+ }}
+ end
+
+ @spec handle_msg(any, any) ::
+ :ok
+ | {:ok, atom | %{:channel => any, :cm => any, optional(any) => any}}
+ | {:stop, any, %{:channel => any, :client_pid => any, optional(any) => any}}
+ def handle_msg({:ssh_channel_up, channel_id, connection_handler}, state) do
+ Logger.debug(
+ "SSH CHANNEL UP #{inspect(connection_handler)} #{inspect(:ssh.connection_info(connection_handler))}"
+ )
+
+ {:ok, %{state | channel: channel_id, cm: connection_handler}}
+ end
+
+ def handle_msg({:EXIT, client_pid, _reason}, %{client_pid: client_pid} = state) do
+ {:stop, state.channel, state}
+ end
+
+ ### commands we expect from the client ###
+ def handle_msg({:send_data, data}, state) do
+ Logger.debug("DATA SENT #{inspect(data)}")
+ :ssh_connection.send(state.cm, state.channel, data)
+ {:ok, state}
+ end
+
+ ### catch all for what we haven't seen ###
+ 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
+ ) do
+ Logger.debug("DATA #{inspect(data)}")
+ 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, modes} = _pty}},
+ state
+ ) do
+ :ssh_connection.reply_request(connection_handler, want_reply?, :success, channel_id)
+
+ {:ok,
+ %{
+ state
+ | pty: %{
+ term: term,
+ width: width,
+ height: height,
+ pixwidth: pixwidth,
+ pixheight: pixheight,
+ modes: modes
+ }
+ }}
+ 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)
+ Logger.debug("ENV #{var} = #{value}")
+ {:ok, state}
+ end
+
+ def handle_ssh_msg(
+ {:ssh_cm, _connection_handler,
+ {:window_change, _channel_id, width, height, pixwidth, pixheight}},
+ state
+ ) do
+ Logger.debug("WINDOW CHANGE")
+ # SSHnakes.Client.resize(state.client_pid, width, height)
+
+ {:ok,
+ %{
+ state
+ | pty: %{
+ state.pty
+ | width: width,
+ height: height,
+ pixwidth: pixwidth,
+ pixheight: pixheight
+ }
+ }}
+ end
+
+ def handle_ssh_msg(
+ {:ssh_cm, connection_handler, {:shell, channel_id, want_reply?}},
+ state
+ ) do
+ :ssh_connection.reply_request(connection_handler, want_reply?, :success, channel_id)
+
+ {:ok, client_pid} =
+ GenServer.start_link(Chessh.SSH.Client, [self(), state.pty.width, state.pty.height])
+
+ {:ok, %{state | client_pid: client_pid, shell: true}}
+ end
+
+ def handle_ssh_msg(
+ {:ssh_cm, connection_handler, {:exec, channel_id, want_reply?, cmd}},
+ state
+ ) do
+ :ssh_connection.reply_request(connection_handler, want_reply?, :success, channel_id)
+ Logger.debug("EXEC #{cmd}")
+ {:ok, state}
+ end
+
+ def handle_ssh_msg(
+ {:ssh_cm, _connection_handler, {:eof, _channel_id}},
+ state
+ ) do
+ Logger.debug("EOF")
+ {:ok, state}
+ end
+
+ def handle_ssh_msg(
+ {:ssh_cm, _connection_handler, {:signal, _channel_id, signal}},
+ state
+ ) do
+ Logger.debug("SIGNAL #{signal}")
+ {:ok, state}
+ end
+
+ def handle_ssh_msg(
+ {:ssh_cm, _connection_handler, {:exit_signal, channel_id, signal, err, lang}},
+ state
+ ) do
+ Logger.debug("EXIT SIGNAL #{signal} #{err} #{lang}")
+ {:stop, channel_id, state}
+ end
+
+ def handle_ssh_msg(
+ {:ssh_cm, _connection_handler, {:exit_STATUS, channel_id, status}},
+ state
+ ) do
+ Logger.debug("EXIT STATUS #{status}")
+ {:stop, channel_id, state}
+ end
+
+ def terminate(_reason, _state) do
+ :ok
+ end
+end