diff --git a/tmate-encoder.c b/tmate-encoder.c index 10c9e8c8..1a6c7b19 100644 --- a/tmate-encoder.c +++ b/tmate-encoder.c @@ -150,13 +150,48 @@ int tmate_should_replicate_cmd(const struct cmd_entry *cmd) return 0; } -void tmate_exec_cmd(const char *cmd) +#define sc (&session->saved_tmux_cmds) +#define SAVED_TMUX_CMD_INITIAL_SIZE 256 +static void __tmate_exec_cmd(const char *cmd); + +static void append_saved_cmd(struct tmate_session *session, + const char *cmd) +{ + if (!sc->cmds) { + sc->capacity = SAVED_TMUX_CMD_INITIAL_SIZE; + sc->cmds = xmalloc(sizeof(char *) * sc->capacity); + sc->tail = 0; + } + + if (sc->tail == sc->capacity) { + sc->capacity *= 2; + sc->cmds = xrealloc(sc->cmds, sizeof(char *) * sc->capacity); + } + + sc->cmds[sc->tail++] = xstrdup(cmd); +} + +static void replay_saved_cmd(struct tmate_session *session) +{ + unsigned int i; + for (i = 0; i < sc->tail; i++) + __tmate_exec_cmd(sc->cmds[i]); +} +#undef sc + +static void __tmate_exec_cmd(const char *cmd) { pack(array, 2); pack(int, TMATE_OUT_EXEC_CMD); pack(string, cmd); } +void tmate_exec_cmd(const char *cmd) +{ + __tmate_exec_cmd(cmd); + append_saved_cmd(&tmate_session, cmd); +} + void tmate_failed_cmd(int client_id, const char *cause) { pack(array, 3); @@ -363,6 +398,7 @@ void tmate_send_reconnection_state(struct tmate_session *session) tmate_write_header(); tmate_send_reconnection_data(session); + replay_saved_cmd(session); /* TODO send all option variables */ tmate_write_ready(); diff --git a/tmate.h b/tmate.h index 0dca56f9..e6d3ef09 100644 --- a/tmate.h +++ b/tmate.h @@ -175,6 +175,17 @@ struct tmate_session { struct event ev_connection_retry; char *last_server_ip; char *reconnection_data; + /* + * When we reconnect, instead of serializing the key bindings and + * options, we replay all the tmux commands we replicated. + * It may be a little innacurate to replicate the state, but + * it's much easier. + */ + struct { + unsigned int capacity; + unsigned int tail; + char **cmds; + } saved_tmux_cmds; }; extern struct tmate_session tmate_session;