From 6c62b10e0a8647a33c0ab2c78766b75660ce357e Mon Sep 17 00:00:00 2001 From: Nicolas Viennot Date: Mon, 5 Oct 2015 17:58:53 -0700 Subject: [PATCH] client notification through master --- client.c | 5 ++++- log.c | 1 + resize.c | 7 +++++++ server-client.c | 8 ++++++-- tmate-daemon-encoder.c | 45 ----------------------------------------- tmate-master.c | 38 ++++++++++++++++++++++++++++++++-- tmate-protocol.h | 46 ++++++++++++++++++++++++++++++++++++++++++ tmate-ssh-server.c | 18 ++++++++++------- tmate.h | 5 +++-- tmux.h | 2 ++ 10 files changed, 116 insertions(+), 59 deletions(-) diff --git a/client.c b/client.c index b52798bc..db1e2ae5 100644 --- a/client.c +++ b/client.c @@ -325,7 +325,10 @@ client_send_identify(int flags) int fd; #ifdef TMATE_SLAVE - strcpy(data.ip_address, tmate_session->ssh_client.ip_address); + strncpy(data.ip_address, tmate_session->ssh_client.ip_address, + sizeof(data.ip_address)); + strncpy(data.pubkey, tmate_session->ssh_client.pubkey, + sizeof(data.pubkey)); #endif data.flags = flags; diff --git a/log.c b/log.c index 5228e735..1e40b900 100644 --- a/log.c +++ b/log.c @@ -47,6 +47,7 @@ void log_event_cb(unused int severity, const char *msg) { log_warnx("%s", msg); + sleep(1); } void init_logging(const char *program_name, bool use_syslog, int log_level) diff --git a/resize.c b/resize.c index 326a2679..3ee4a726 100644 --- a/resize.c +++ b/resize.c @@ -78,6 +78,13 @@ recalculate_sizes(void) } #ifdef TMATE_SLAVE + if (tmate_has_master()) { + if (tmate_session->master_sy < ssy) + ssy = tmate_session->master_sy; + if (tmate_session->master_sx < ssx) + ssx = tmate_session->master_sx; + } + tmate_client_resize(ssx, ssy); return; #endif diff --git a/server-client.c b/server-client.c index 1372ea67..a692effe 100644 --- a/server-client.c +++ b/server-client.c @@ -111,6 +111,7 @@ server_client_create(int fd) #ifdef TMATE_SLAVE c->ip_address = NULL; + c->pubkey = NULL; #endif for (i = 0; i < ARRAY_LENGTH(&clients); i++) { @@ -159,7 +160,7 @@ server_client_lost(struct client *c) log_debug("lost client %d", c->ibuf.fd); #ifdef TMATE_SLAVE - tmate_notify_client_left(c); + tmate_notify_client_left(tmate_session, c); #endif /* @@ -205,6 +206,8 @@ server_client_lost(struct client *c) #ifdef TMATE_SLAVE free(c->ip_address); c->ip_address = NULL; + free(c->pubkey); + c->pubkey = NULL; #endif environ_free(&c->environ); @@ -1029,7 +1032,8 @@ server_client_msg_identify( #ifdef TMATE_SLAVE c->ip_address = xstrdup(data->ip_address); - tmate_notify_client_join(c); + c->pubkey = xstrdup(data->pubkey); + tmate_notify_client_join(tmate_session, c); #endif } diff --git a/tmate-daemon-encoder.c b/tmate-daemon-encoder.c index 9f0dab61..32b4d6d6 100644 --- a/tmate-daemon-encoder.c +++ b/tmate-daemon-encoder.c @@ -51,51 +51,6 @@ void printflike2 tmate_notify_later(int timeout, const char *fmt, ...) evtimer_add(&tmate_session->ev_notify_timer, &tv); } -static int num_clients(void) -{ - unsigned int i, count = 0; - - for (i = 0; i < ARRAY_LENGTH(&clients); i++) { - if (ARRAY_ITEM(&clients, i)) - count++; - } - - return count; -} - -static void mate_notify_message(struct client *c, int join) -{ - char buf[100]; - int count; - static int multi_client; - - count = num_clients(); - if (count > 1) - multi_client = 1; - - if (multi_client) - sprintf(buf, " -- %d mate%s %sconnected", - count, - count == 1 ? " is" : "s are", - (join || !count) ? "" : "still "); - - tmate_notify("%s mate has %s the session (%s)%s", - multi_client ? "A" : "Your", - join ? "joined" : "left", - c->ip_address, - multi_client ? buf : ""); -} - -void tmate_notify_client_join(struct client *c) -{ - mate_notify_message(c, 1); -} - -void tmate_notify_client_left(struct client *c) -{ - mate_notify_message(c, 0); -} - void tmate_send_client_ready(void) { if (tmate_session->client_protocol_version < 4) diff --git a/tmate-master.c b/tmate-master.c index 36336fa3..ebac9ac6 100644 --- a/tmate-master.c +++ b/tmate-master.c @@ -139,6 +139,14 @@ static void ctl_pane_keys(struct tmate_session *session, free(str); } +static void ctl_resize(struct tmate_session *session, + struct tmate_unpacker *uk) +{ + session->master_sx = (u_int)unpack_int(uk); + session->master_sy = (u_int)unpack_int(uk); + recalculate_sizes(); +} + void tmate_dispatch_master_message(struct tmate_session *session, struct tmate_unpacker *uk) { @@ -148,10 +156,35 @@ void tmate_dispatch_master_message(struct tmate_session *session, dispatch(TMATE_CTL_DEAMON_FWD_MSG, ctl_daemon_fwd_msg); dispatch(TMATE_CTL_REQUEST_SNAPSHOT, ctl_daemon_request_snapshot); dispatch(TMATE_CTL_PANE_KEYS, ctl_pane_keys); - default: tmate_fatal("Bad master message type: %d", cmd); + dispatch(TMATE_CTL_RESIZE, ctl_resize); + default: tmate_warn("Bad master message type: %d", cmd); } } +void tmate_notify_client_join(struct tmate_session *session, + struct client *c) +{ + if (!tmate_has_master()) + return; + + pack(array, 4); + pack(int, TMATE_CTL_CLIENT_JOIN); + pack(int, c->id); + pack(string, c->ip_address); + pack(string, c->pubkey); +} + +void tmate_notify_client_left(struct tmate_session *session, + struct client *c) +{ + if (!tmate_has_master()) + return; + + pack(array, 2); + pack(int, TMATE_CTL_CLIENT_LEFT); + pack(int, c->id); +} + void tmate_send_master_daemon_msg(struct tmate_session *session, struct tmate_unpacker *uk) { @@ -188,7 +221,8 @@ void tmate_init_master_session(struct tmate_session *session) if (!tmate_has_master()) return; - /* Further init */ + session->master_sx = -1; + session->master_sy = -1; } static int _tmate_connect_to_master(const char *hostname, int port) diff --git a/tmate-protocol.h b/tmate-protocol.h index 7e51ab10..e27000f1 100644 --- a/tmate-protocol.h +++ b/tmate-protocol.h @@ -10,14 +10,34 @@ enum tmate_control_out_msg_types { TMATE_CTL_AUTH, TMATE_CTL_DEAMON_OUT_MSG, TMATE_CTL_SNAPSHOT, + TMATE_CTL_CLIENT_JOIN, + TMATE_CTL_CLIENT_LEFT, }; +/* +[TMATE_CTL_AUTH, int: ctl_proto_version, string: ip_address, string: pubkey, + string: session_token, string: session_token_ro] +[TMATE_CTL_DEAMON_OUT_MSG, object: msg] +[TMATE_CTL_SNAPSHOT, [[int: pane_id, [int: cur_x, int: cur_y], int: mode, + [[string: line_utf8, [int: char_attr, ...]], ...], ...], ...]] +[TMATE_CTL_CLIENT_JOIN, int: client_id, string: ip_address, string: pubkey] +[TMATE_CTL_CLIENT_LEFT, int: client_id] +*/ + enum tmate_control_in_msg_types { TMATE_CTL_DEAMON_FWD_MSG, TMATE_CTL_REQUEST_SNAPSHOT, TMATE_CTL_PANE_KEYS, + TMATE_CTL_RESIZE, }; +/* +[TMATE_CTL_DEAMON_FWD_MSG, object: msg] +[TMATE_CTL_REQUEST_SNAPSHOT, int: max_history_lines] +[TMATE_CTL_PANE_KEYS, int: pane_id, string: keys] +[TMATE_CTL_RESIZE, int: sx, int: sy] // sx == -1: no clients +*/ + enum tmate_daemon_out_msg_types { TMATE_OUT_HEADER, TMATE_OUT_SYNC_LAYOUT, @@ -28,6 +48,23 @@ enum tmate_daemon_out_msg_types { TMATE_OUT_SYNC_COPY_MODE, TMATE_OUT_WRITE_COPY_MODE, }; + +/* +[TMATE_OUT_HEADER, int: proto_version, string: version] +[TMATE_OUT_SYNC_LAYOUT, [int: sx, int: sy, [[int: win_id, string: win_name, + [[int: pane_id, int: sx, int: sy, int: xoff, int: yoff], ...], + int: active_pane_id], ...], int: active_win_id] +[TMATE_OUT_PTY_DATA, int: pane_id, binary: buffer] +[TMATE_OUT_EXEC_CMD, string: cmd] +[TMATE_OUT_FAILED_CMD, int: client_id, string: cause] +[TMATE_OUT_STATUS, string: left, string: right] +[TMATE_OUT_SYNC_COPY_MODE, int: pane_id, [int: backing, int: oy, int: cx, int: cy, + [int: selx, int: sely, int: flags], + [int: type, string: input_prompt, string: input_str]]) + // Any of the array can be [] +[TMATE_OUT_WRITE_COPY_MODE, int: pane_id, string: str] +*/ + enum tmate_daemon_in_msg_types { TMATE_IN_NOTIFY, TMATE_IN_PANE_KEY, @@ -37,4 +74,13 @@ enum tmate_daemon_in_msg_types { TMATE_IN_READY, }; +/* +[TMATE_IN_NOTIFY, string: msg] +[TMATE_IN_PANE_KEY, int: key] +[TMATE_IN_RESIZE, int: sx, int: sy] // sx == -1: no clients +[TMATE_IN_EXEC_CMD, int: client_id, string: cmd] +[TMATE_IN_SET_ENV, string: name, string: value] +[TMATE_IN_READY] +*/ + #endif diff --git a/tmate-ssh-server.c b/tmate-ssh-server.c index d1ac14f1..23a2184b 100644 --- a/tmate-ssh-server.c +++ b/tmate-ssh-server.c @@ -123,6 +123,8 @@ static void on_ssh_read(evutil_socket_t fd, short what, void *arg) if (!ssh_is_connected(client->session)) { tmate_warn("SSH Disconnected"); + event_del(&client->ev_ssh); + /* For graceful tmux client termination */ request_server_termination(); } @@ -190,14 +192,16 @@ static void client_bootstrap(struct tmate_session *_session) static void handle_sigchld(void) { - siginfo_t si; + int status; + pid_t pid; - /* TODO cleanup the socket when the client dies */ - while (waitid(P_ALL, 0, &si, WEXITED | WNOHANG) >= 0 && si.si_pid) { - tmate_info("Child %d %s (%d)", - si.si_pid, - si.si_code == CLD_EXITED ? "exited" : "killed", - si.si_status); + while ((pid = waitpid(WAIT_ANY, &status, WNOHANG)) > 0) { + if (WIFEXITED(status)) + tmate_info("Child %d exited (%d)", pid, WEXITSTATUS(status)); + if (WIFSIGNALED(status)) + tmate_info("Child %d killed (%d)", pid, WTERMSIG(status)); + if (WIFSTOPPED(status)) + tmate_info("Child %d stopped (%d)", pid, WSTOPSIG(status)); } } diff --git a/tmate.h b/tmate.h index d2c7726e..400d33d8 100644 --- a/tmate.h +++ b/tmate.h @@ -88,8 +88,8 @@ extern void unpack_array(struct tmate_unpacker *uk, struct tmate_unpacker *neste extern void printflike1 tmate_notify(const char *fmt, ...); extern void printflike2 tmate_notify_later(int timeout, const char *fmt, ...); -extern void tmate_notify_client_join(struct client *c); -extern void tmate_notify_client_left(struct client *c); +extern void tmate_notify_client_join(struct tmate_session *s, struct client *c); +extern void tmate_notify_client_left(struct tmate_session *s, struct client *c); extern void tmate_client_resize(u_int sx, u_int sy); extern void tmate_client_pane_key(int pane_id, int key); @@ -200,6 +200,7 @@ struct tmate_session { struct bufferevent *bev_master; struct tmate_encoder master_encoder; struct tmate_decoder master_decoder; + u_int master_sx, master_sy; /* only for client-pty */ int pty; diff --git a/tmux.h b/tmux.h index e86b9bd5..0282fce7 100644 --- a/tmux.h +++ b/tmux.h @@ -479,6 +479,7 @@ struct msg_identify_data { #ifdef TMATE_SLAVE char ip_address[64]; + char pubkey[2048]; /* hopefully enough :) */ #endif #define IDENTIFY_UTF8 0x1 @@ -1387,6 +1388,7 @@ struct client { #ifdef TMATE_SLAVE char *ip_address; + char *pubkey; #endif }; ARRAY_DECL(clients, struct client *);