1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218
|
#ifndef TMATE_H
#define TMATE_H
#include <sys/types.h>
#include <msgpack.h>
#include <libssh/libssh.h>
#include <libssh/callbacks.h>
#include <event.h>
#include "tmux.h"
#define tmate_debug(...) log_emit(LOG_DEBUG, __VA_ARGS__)
#define tmate_info(...) log_emit(LOG_INFO, __VA_ARGS__)
#define tmate_fatal(...) fatalx( __VA_ARGS__)
/* tmate-msgpack.c */
typedef void tmate_encoder_write_cb(void *userdata, struct evbuffer *buffer);
struct tmate_encoder {
msgpack_packer pk;
tmate_encoder_write_cb *ready_callback;
void *userdata;
struct evbuffer *buffer;
struct event *ev_buffer;
bool ev_active;
};
extern void tmate_encoder_init(struct tmate_encoder *encoder,
tmate_encoder_write_cb *callback,
void *userdata);
extern void tmate_encoder_destroy(struct tmate_encoder *encoder);
extern void tmate_encoder_set_ready_callback(struct tmate_encoder *encoder,
tmate_encoder_write_cb *callback,
void *userdata);
extern void msgpack_pack_string(msgpack_packer *pk, const char *str);
extern void msgpack_pack_boolean(msgpack_packer *pk, bool value);
#define _pack(enc, what, ...) msgpack_pack_##what(&(enc)->pk, ##__VA_ARGS__)
struct tmate_unpacker;
struct tmate_decoder;
typedef void tmate_decoder_reader(void *userdata, struct tmate_unpacker *uk);
struct tmate_decoder {
struct msgpack_unpacker unpacker;
tmate_decoder_reader *reader;
void *userdata;
};
extern void tmate_decoder_init(struct tmate_decoder *decoder, tmate_decoder_reader *reader, void *userdata);
extern void tmate_decoder_destroy(struct tmate_decoder *decoder);
extern void tmate_decoder_get_buffer(struct tmate_decoder *decoder, char **buf, size_t *len);
extern void tmate_decoder_commit(struct tmate_decoder *decoder, size_t len);
struct tmate_unpacker {
int argc;
msgpack_object *argv;
};
extern void init_unpacker(struct tmate_unpacker *uk, msgpack_object obj);
extern void tmate_decoder_error(void);
extern int64_t unpack_int(struct tmate_unpacker *uk);
extern bool unpack_bool(struct tmate_unpacker *uk);
extern void unpack_buffer(struct tmate_unpacker *uk, const char **buf, size_t *len);
extern char *unpack_string(struct tmate_unpacker *uk);
extern void unpack_array(struct tmate_unpacker *uk, struct tmate_unpacker *nested);
#define unpack_each(nested_uk, tmp_uk, uk) \
for (unpack_array(uk, tmp_uk); \
(tmp_uk)->argc > 0 && (init_unpacker(nested_uk, (tmp_uk)->argv[0]), 1); \
(tmp_uk)->argv++, (tmp_uk)->argc--)
/* tmate-encoder.c */
#define TMATE_PROTOCOL_VERSION 6
struct tmate_session;
extern void tmate_write_header(void);
extern void tmate_write_uname(void);
extern void tmate_write_ready(void);
extern void tmate_sync_layout(void);
extern void tmate_pty_data(struct window_pane *wp, const char *buf, size_t len);
extern int tmate_should_replicate_cmd(const struct cmd_entry *cmd);
extern void tmate_set_val(const char *name, const char *value);
extern void tmate_exec_cmd_args(int argc, const char **argv);
extern void tmate_exec_cmd(struct cmd *cmd);
extern void tmate_failed_cmd(int client_id, const char *cause);
extern void tmate_status(const char *left, const char *right);
extern void tmate_sync_copy_mode(struct window_pane *wp);
extern void tmate_write_copy_mode(struct window_pane *wp, const char *str);
extern void tmate_write_fin(void);
extern void tmate_send_reconnection_state(struct tmate_session *session);
/* tmate-decoder.c */
struct tmate_session;
extern void tmate_dispatch_slave_message(struct tmate_session *session,
struct tmate_unpacker *uk);
/* tmate-ssh-client.c */
enum tmate_ssh_client_state_types {
SSH_NONE,
SSH_INIT,
SSH_CONNECT,
SSH_AUTH_SERVER,
SSH_AUTH_CLIENT_NONE,
SSH_AUTH_CLIENT_PUBKEY,
SSH_NEW_CHANNEL,
SSH_OPEN_CHANNEL,
SSH_BOOTSTRAP,
SSH_READY,
};
struct tmate_ssh_client {
/* XXX The "session" word is used for three things:
* - the ssh session
* - the tmate sesssion
* - the tmux session
* A tmux session is associated 1:1 with a tmate session.
* An ssh session belongs to a tmate session, and a tmate session
* has one ssh session, except during bootstrapping where
* there is one ssh session per tmate server, and the first one wins.
*/
struct tmate_session *tmate_session;
TAILQ_ENTRY(tmate_ssh_client) node;
char *server_ip;
int state;
/*
* ssh_callbacks is allocated because the libssh API sucks (userdata
* has to be in the struct itself).
*/
struct ssh_callbacks_struct ssh_callbacks;
char *tried_passphrase;
ssh_session session;
ssh_channel channel;
struct event *ev_ssh;
};
TAILQ_HEAD(tmate_ssh_clients, tmate_ssh_client);
extern void connect_ssh_client(struct tmate_ssh_client *client);
extern struct tmate_ssh_client *tmate_ssh_client_alloc(struct tmate_session *session,
const char *server_ip);
/* tmate-session.c */
struct tmate_session {
struct event_base *ev_base;
struct evdns_base *ev_dnsbase;
struct event *ev_dns_retry;
struct tmate_encoder encoder;
struct tmate_decoder decoder;
/* True when the slave has sent all the environment variables */
int tmate_env_ready;
int min_sx;
int min_sy;
/*
* This list contains one connection per IP. The first connected
* client wins, and saved in *client. When we have a winner, the
* losers are disconnected and killed.
*/
struct tmate_ssh_clients clients;
int need_passphrase;
char *passphrase;
bool reconnected;
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;
struct {
int argc;
char **argv;
} *cmds;
} saved_tmux_cmds;
};
extern struct tmate_session tmate_session;
extern void tmate_session_init(struct event_base *base);
extern void tmate_session_start(void);
extern void tmate_reconnect_session(struct tmate_session *session, const char *message);
/* tmate-debug.c */
extern void tmate_print_stack_trace(void);
extern void tmate_catch_sigsegv(void);
extern void tmate_preload_trace_lib(void);
/* tmate-msg.c */
extern void __tmate_status_message(const char *fmt, va_list ap);
extern void printflike(1, 2) tmate_status_message(const char *fmt, ...);
/* tmate-env.c */
extern int tmate_has_received_env(void);
extern void tmate_set_env(const char *name, const char *value);
extern void tmate_format(struct format_tree *ft);
#endif
|