mirror of
https://github.com/tmate-io/tmate-ssh-server.git
synced 2020-11-18 19:53:51 -08:00
Added communication with master
This commit is contained in:
parent
4ac1183848
commit
825ad72720
@ -182,6 +182,7 @@ dist_tmate_slave_SOURCES = \
|
|||||||
tmate-client-decoder.c \
|
tmate-client-decoder.c \
|
||||||
tmate-client-encoder.c \
|
tmate-client-encoder.c \
|
||||||
tmate-msgpack.c \
|
tmate-msgpack.c \
|
||||||
|
tmate-master.c \
|
||||||
tmate-slave.c \
|
tmate-slave.c \
|
||||||
tmate-ssh-client-pty.c \
|
tmate-ssh-client-pty.c \
|
||||||
tmate-ssh-client.c \
|
tmate-ssh-client.c \
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include "tmate.h"
|
#include "tmate.h"
|
||||||
|
#include "tmate-protocol.h"
|
||||||
|
|
||||||
char *tmate_left_status, *tmate_right_status;
|
char *tmate_left_status, *tmate_right_status;
|
||||||
|
|
||||||
@ -362,14 +363,14 @@ void tmate_dispatch_daemon_message(struct tmate_session *session,
|
|||||||
|
|
||||||
int cmd = unpack_int(uk);
|
int cmd = unpack_int(uk);
|
||||||
switch (cmd) {
|
switch (cmd) {
|
||||||
dispatch(TMATE_HEADER, tmate_header);
|
dispatch(TMATE_OUT_HEADER, tmate_header);
|
||||||
dispatch(TMATE_SYNC_LAYOUT, tmate_sync_layout);
|
dispatch(TMATE_OUT_SYNC_LAYOUT, tmate_sync_layout);
|
||||||
dispatch(TMATE_PTY_DATA, tmate_pty_data);
|
dispatch(TMATE_OUT_PTY_DATA, tmate_pty_data);
|
||||||
dispatch(TMATE_EXEC_CMD, tmate_exec_cmd);
|
dispatch(TMATE_OUT_EXEC_CMD, tmate_exec_cmd);
|
||||||
dispatch(TMATE_FAILED_CMD, tmate_failed_cmd);
|
dispatch(TMATE_OUT_FAILED_CMD, tmate_failed_cmd);
|
||||||
dispatch(TMATE_STATUS, tmate_status);
|
dispatch(TMATE_OUT_STATUS, tmate_status);
|
||||||
dispatch(TMATE_SYNC_COPY_MODE, tmate_sync_copy_mode);
|
dispatch(TMATE_OUT_SYNC_COPY_MODE, tmate_sync_copy_mode);
|
||||||
dispatch(TMATE_WRITE_COPY_MODE, tmate_write_copy_mode);
|
dispatch(TMATE_OUT_WRITE_COPY_MODE, tmate_write_copy_mode);
|
||||||
default: tmate_fatal("Bad message type: %d", cmd);
|
default: tmate_fatal("Bad message type: %d", cmd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,11 +1,12 @@
|
|||||||
#include "tmate.h"
|
#include "tmate.h"
|
||||||
|
#include "tmate-protocol.h"
|
||||||
|
|
||||||
#define pack(what, ...) _pack(&tmate_session->client_encoder, what, __VA_ARGS__)
|
#define pack(what, ...) _pack(&tmate_session->client_encoder, what, __VA_ARGS__)
|
||||||
|
|
||||||
static void __tmate_notify(const char *msg)
|
static void __tmate_notify(const char *msg)
|
||||||
{
|
{
|
||||||
pack(array, 2);
|
pack(array, 2);
|
||||||
pack(int, TMATE_NOTIFY);
|
pack(int, TMATE_IN_NOTIFY);
|
||||||
pack(string, msg);
|
pack(string, msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -101,7 +102,7 @@ void tmate_send_client_ready(void)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
pack(array, 1);
|
pack(array, 1);
|
||||||
pack(int, TMATE_CLIENT_READY);
|
pack(int, TMATE_IN_READY);
|
||||||
}
|
}
|
||||||
|
|
||||||
void tmate_send_env(const char *name, const char *value)
|
void tmate_send_env(const char *name, const char *value)
|
||||||
@ -110,7 +111,7 @@ void tmate_send_env(const char *name, const char *value)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
pack(array, 3);
|
pack(array, 3);
|
||||||
pack(int, TMATE_CLIENT_ENV);
|
pack(int, TMATE_IN_SET_ENV);
|
||||||
pack(string, name);
|
pack(string, name);
|
||||||
pack(string, value);
|
pack(string, value);
|
||||||
}
|
}
|
||||||
@ -118,7 +119,7 @@ void tmate_send_env(const char *name, const char *value)
|
|||||||
void tmate_client_resize(u_int sx, u_int sy)
|
void tmate_client_resize(u_int sx, u_int sy)
|
||||||
{
|
{
|
||||||
pack(array, 3);
|
pack(array, 3);
|
||||||
pack(int, TMATE_CLIENT_RESIZE);
|
pack(int, TMATE_IN_RESIZE);
|
||||||
/* cast to signed, -1 == no clients */
|
/* cast to signed, -1 == no clients */
|
||||||
pack(int, sx);
|
pack(int, sx);
|
||||||
pack(int, sy);
|
pack(int, sy);
|
||||||
@ -132,7 +133,7 @@ void tmate_client_pane_key(int pane_id, int key)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
pack(array, 2);
|
pack(array, 2);
|
||||||
pack(int, TMATE_CLIENT_PANE_KEY);
|
pack(int, TMATE_IN_PANE_KEY);
|
||||||
pack(int, key);
|
pack(int, key);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -159,7 +160,7 @@ int tmate_should_exec_cmd_locally(const struct cmd_entry *cmd)
|
|||||||
void tmate_client_cmd(int client_id, const char *cmd)
|
void tmate_client_cmd(int client_id, const char *cmd)
|
||||||
{
|
{
|
||||||
pack(array, 3);
|
pack(array, 3);
|
||||||
pack(int, TMATE_CLIENT_EXEC_CMD);
|
pack(int, TMATE_IN_EXEC_CMD);
|
||||||
pack(int, client_id);
|
pack(int, client_id);
|
||||||
pack(string, cmd);
|
pack(string, cmd);
|
||||||
}
|
}
|
||||||
|
138
tmate-master.c
Normal file
138
tmate-master.c
Normal file
@ -0,0 +1,138 @@
|
|||||||
|
#include <sys/socket.h>
|
||||||
|
#include <netinet/tcp.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
#include "tmate.h"
|
||||||
|
#include "tmate-protocol.h"
|
||||||
|
|
||||||
|
#define pack(what, ...) _pack(&tmate_session->master_encoder, what, __VA_ARGS__)
|
||||||
|
|
||||||
|
void tmate_send_master_keyframe(struct tmate_session *session)
|
||||||
|
{
|
||||||
|
struct timespec time_diff;
|
||||||
|
|
||||||
|
if (!tmate_has_master())
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* Eventually the deamon will send the timestamps and keyframe number */
|
||||||
|
|
||||||
|
if (clock_gettime(CLOCK_MONOTONIC, &session->keyframe_start_time) < 0)
|
||||||
|
tmate_fatal("Cannot get time");
|
||||||
|
|
||||||
|
timespec_subtract(&time_diff, &session->keyframe_start_time,
|
||||||
|
&session->session_start_time);
|
||||||
|
session->keyframe_size = 0;
|
||||||
|
|
||||||
|
pack(array, 3);
|
||||||
|
pack(int, TMATE_CTL_KEYFRAME);
|
||||||
|
pack(unsigned_int, session->keyframe_cnt++);
|
||||||
|
pack(unsigned_long_long, timespec_to_millisec(&time_diff));
|
||||||
|
}
|
||||||
|
|
||||||
|
void tmate_send_master_daemon_msg(struct tmate_session *session,
|
||||||
|
struct tmate_unpacker *uk)
|
||||||
|
{
|
||||||
|
struct timespec time_diff, current_time;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (!tmate_has_master())
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (clock_gettime(CLOCK_MONOTONIC, ¤t_time) < 0)
|
||||||
|
tmate_fatal("Cannot get time");
|
||||||
|
|
||||||
|
timespec_subtract(&time_diff, ¤t_time,
|
||||||
|
&session->keyframe_start_time);
|
||||||
|
|
||||||
|
pack(array, 3);
|
||||||
|
pack(int, TMATE_CTL_DEAMON_OUT_MSG);
|
||||||
|
pack(unsigned_int, timespec_to_millisec(&time_diff));
|
||||||
|
|
||||||
|
pack(array, uk->argc);
|
||||||
|
for (i = 0; i < uk->argc; i++)
|
||||||
|
pack(object, uk->argv[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void tmate_send_master_header(struct tmate_session *session)
|
||||||
|
{
|
||||||
|
if (!tmate_has_master())
|
||||||
|
return;
|
||||||
|
|
||||||
|
pack(array, 6);
|
||||||
|
pack(int, TMATE_CTL_AUTH);
|
||||||
|
pack(int, CONTROL_PROTOCOL_VERSION);
|
||||||
|
pack(string, session->ssh_client.ip_address);
|
||||||
|
pack(string, session->ssh_client.pubkey);
|
||||||
|
pack(string, session->session_token);
|
||||||
|
pack(string, session->session_token_ro);
|
||||||
|
}
|
||||||
|
|
||||||
|
void tmate_init_master_session(struct tmate_session *session)
|
||||||
|
{
|
||||||
|
if (!tmate_has_master())
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (clock_gettime(CLOCK_MONOTONIC, &session->session_start_time) < 0)
|
||||||
|
tmate_fatal("Cannot get time");
|
||||||
|
|
||||||
|
session->keyframe_cnt = 0;
|
||||||
|
session->keyframe_size = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _tmate_connect_to_master(const char *hostname, int port)
|
||||||
|
{
|
||||||
|
int sockfd = -1;
|
||||||
|
struct sockaddr_in servaddr;
|
||||||
|
struct hostent *host;
|
||||||
|
|
||||||
|
sockfd = socket(AF_INET, SOCK_STREAM, 0);
|
||||||
|
if (sockfd < 0)
|
||||||
|
tmate_fatal("Cannot create socket");
|
||||||
|
|
||||||
|
host = gethostbyname(hostname);
|
||||||
|
if (!host)
|
||||||
|
tmate_fatal("Cannot resolve %s", hostname);
|
||||||
|
|
||||||
|
memset(&servaddr, 0, sizeof(servaddr));
|
||||||
|
servaddr.sin_family = host->h_addrtype;
|
||||||
|
memcpy(&servaddr.sin_addr, host->h_addr, host->h_length);
|
||||||
|
servaddr.sin_port = htons(port);
|
||||||
|
|
||||||
|
if (connect(sockfd, &servaddr, sizeof(servaddr)) < 0)
|
||||||
|
tmate_fatal("Cannot connect to master at %s:%d", hostname, port);
|
||||||
|
|
||||||
|
int flag = 1;
|
||||||
|
if (setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, &flag, sizeof(flag)) < 0)
|
||||||
|
tmate_fatal("Can't set master socket to TCP_NODELAY");
|
||||||
|
|
||||||
|
if (fcntl(sockfd, F_SETFL, O_NONBLOCK) < 0)
|
||||||
|
tmate_fatal("Can't set master socket to non-blocking");
|
||||||
|
|
||||||
|
tmate_notice("Connected to master at %s:%d", hostname, port);
|
||||||
|
|
||||||
|
return sockfd;
|
||||||
|
}
|
||||||
|
|
||||||
|
int tmate_connect_to_master(void)
|
||||||
|
{
|
||||||
|
return _tmate_connect_to_master(tmate_settings->master_hostname,
|
||||||
|
tmate_settings->master_port);
|
||||||
|
}
|
||||||
|
|
||||||
|
void timespec_subtract(struct timespec *result,
|
||||||
|
struct timespec *x, struct timespec *y)
|
||||||
|
{
|
||||||
|
if (x->tv_nsec < y->tv_nsec) {
|
||||||
|
result->tv_sec = x->tv_sec - y->tv_sec - 1;
|
||||||
|
result->tv_nsec = x->tv_nsec - y->tv_nsec + 1000000000;
|
||||||
|
} else {
|
||||||
|
result->tv_sec = x->tv_sec - y->tv_sec;
|
||||||
|
result->tv_nsec = x->tv_nsec - y->tv_nsec;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned long long timespec_to_millisec(struct timespec *ts)
|
||||||
|
{
|
||||||
|
return ts->tv_sec * 1000ULL + ts->tv_nsec / 1000000ULL;
|
||||||
|
}
|
@ -1,4 +1,5 @@
|
|||||||
#include "tmate.h"
|
#include "tmate.h"
|
||||||
|
#include "tmate-protocol.h"
|
||||||
|
|
||||||
static void on_encoder_buffer_ready(evutil_socket_t fd, short what, void *arg)
|
static void on_encoder_buffer_ready(evutil_socket_t fd, short what, void *arg)
|
||||||
{
|
{
|
||||||
|
36
tmate-protocol.h
Normal file
36
tmate-protocol.h
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
#ifndef TMATE_PROTOCOL_H
|
||||||
|
#define TMATE_PROTOCOL_H
|
||||||
|
|
||||||
|
/* 17 and not 16 because the sender does not takes into account envelope size */
|
||||||
|
#define TMATE_MAX_MESSAGE_SIZE (17*1024)
|
||||||
|
|
||||||
|
#define CONTROL_PROTOCOL_VERSION 1
|
||||||
|
|
||||||
|
/* TODO document each msg */
|
||||||
|
|
||||||
|
enum tmate_control_msg_types {
|
||||||
|
TMATE_CTL_AUTH,
|
||||||
|
TMATE_CTL_DEAMON_OUT_MSG,
|
||||||
|
TMATE_CTL_KEYFRAME,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum tmate_daemon_out_msg_types {
|
||||||
|
TMATE_OUT_HEADER,
|
||||||
|
TMATE_OUT_SYNC_LAYOUT,
|
||||||
|
TMATE_OUT_PTY_DATA,
|
||||||
|
TMATE_OUT_EXEC_CMD,
|
||||||
|
TMATE_OUT_FAILED_CMD,
|
||||||
|
TMATE_OUT_STATUS,
|
||||||
|
TMATE_OUT_SYNC_COPY_MODE,
|
||||||
|
TMATE_OUT_WRITE_COPY_MODE,
|
||||||
|
};
|
||||||
|
enum tmate_daemon_in_msg_types {
|
||||||
|
TMATE_IN_NOTIFY,
|
||||||
|
TMATE_IN_PANE_KEY,
|
||||||
|
TMATE_IN_RESIZE,
|
||||||
|
TMATE_IN_EXEC_CMD,
|
||||||
|
TMATE_IN_SET_ENV,
|
||||||
|
TMATE_IN_READY,
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
@ -33,7 +33,7 @@ extern int client_connect(char *path, int start_server);
|
|||||||
struct tmate_settings _tmate_settings = {
|
struct tmate_settings _tmate_settings = {
|
||||||
.keys_dir = TMATE_SSH_DEFAULT_KEYS_DIR,
|
.keys_dir = TMATE_SSH_DEFAULT_KEYS_DIR,
|
||||||
.ssh_port = TMATE_SSH_DEFAULT_PORT,
|
.ssh_port = TMATE_SSH_DEFAULT_PORT,
|
||||||
.master_hostname = TMATE_DEFAULT_MASTER_HOST,
|
.master_hostname = NULL,
|
||||||
.master_port = TMATE_DEFAULT_MASTER_PORT,
|
.master_port = TMATE_DEFAULT_MASTER_PORT,
|
||||||
.tmate_host = NULL,
|
.tmate_host = NULL,
|
||||||
.log_level = LOG_NOTICE,
|
.log_level = LOG_NOTICE,
|
||||||
@ -328,16 +328,16 @@ static void tmate_spawn_slave_server(struct tmate_session *session)
|
|||||||
*/
|
*/
|
||||||
setup_ncurse(STDOUT_FILENO, "screen-256color");
|
setup_ncurse(STDOUT_FILENO, "screen-256color");
|
||||||
|
|
||||||
|
tmate_daemon_init(session);
|
||||||
|
|
||||||
close_fds_except((int[]){session->tmux_socket_fd,
|
close_fds_except((int[]){session->tmux_socket_fd,
|
||||||
ssh_get_fd(session->ssh_client.session),
|
ssh_get_fd(session->ssh_client.session),
|
||||||
log_file ? fileno(log_file) : -1}, 3);
|
log_file ? fileno(log_file) : -1,
|
||||||
|
session->master_fd}, 4);
|
||||||
|
|
||||||
jail();
|
jail();
|
||||||
|
|
||||||
event_reinit(ev_base);
|
event_reinit(ev_base);
|
||||||
|
|
||||||
tmate_daemon_init(session);
|
|
||||||
|
|
||||||
tmux_server_init(IDENTIFY_UTF8 | IDENTIFY_256COLOURS);
|
tmux_server_init(IDENTIFY_UTF8 | IDENTIFY_256COLOURS);
|
||||||
/* never reached */
|
/* never reached */
|
||||||
}
|
}
|
||||||
@ -399,6 +399,11 @@ static void tmate_spawn_slave_client(struct tmate_session *session)
|
|||||||
dup2(slave_pty, STDERR_FILENO);
|
dup2(slave_pty, STDERR_FILENO);
|
||||||
|
|
||||||
setup_ncurse(slave_pty, "screen-256color");
|
setup_ncurse(slave_pty, "screen-256color");
|
||||||
|
|
||||||
|
tmate_ssh_client_pty_init(session);
|
||||||
|
|
||||||
|
/* the unused session->master_fd will get closed automatically */
|
||||||
|
|
||||||
close_fds_except((int[]){STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO,
|
close_fds_except((int[]){STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO,
|
||||||
session->tmux_socket_fd,
|
session->tmux_socket_fd,
|
||||||
ssh_get_fd(session->ssh_client.session),
|
ssh_get_fd(session->ssh_client.session),
|
||||||
@ -406,8 +411,6 @@ static void tmate_spawn_slave_client(struct tmate_session *session)
|
|||||||
jail();
|
jail();
|
||||||
event_reinit(ev_base);
|
event_reinit(ev_base);
|
||||||
|
|
||||||
tmate_ssh_client_pty_init(session);
|
|
||||||
|
|
||||||
ret = client_main(argc, argv, IDENTIFY_UTF8 | IDENTIFY_256COLOURS);
|
ret = client_main(argc, argv, IDENTIFY_UTF8 | IDENTIFY_256COLOURS);
|
||||||
tmate_flush_pty(session);
|
tmate_flush_pty(session);
|
||||||
exit(ret);
|
exit(ret);
|
||||||
|
@ -1,8 +1,84 @@
|
|||||||
#include "tmate.h"
|
#include "tmate.h"
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
static void on_decoder_read(void *userdata, struct tmate_unpacker *uk)
|
static void on_master_decoder_read(void *userdata, struct tmate_unpacker *uk)
|
||||||
|
{
|
||||||
|
/* struct tmate_session *session = userdata; */
|
||||||
|
tmate_info("Received master data!");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void on_master_read(struct bufferevent *bev, void *_session)
|
||||||
|
{
|
||||||
|
struct tmate_session *session = _session;
|
||||||
|
struct evbuffer *master_in;
|
||||||
|
ssize_t written;
|
||||||
|
char *buf;
|
||||||
|
size_t len;
|
||||||
|
|
||||||
|
master_in = bufferevent_get_input(session->bev_master);
|
||||||
|
|
||||||
|
while (evbuffer_get_length(master_in)) {
|
||||||
|
tmate_decoder_get_buffer(&session->client_decoder, &buf, &len);
|
||||||
|
|
||||||
|
if (len == 0)
|
||||||
|
tmate_fatal("No more room in client decoder. Message too big?");
|
||||||
|
|
||||||
|
written = evbuffer_remove(master_in, buf, len);
|
||||||
|
if (written < 0)
|
||||||
|
tmate_fatal("Cannot read master buffer");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void on_master_encoder_write(void *userdata, struct evbuffer *buffer)
|
||||||
{
|
{
|
||||||
struct tmate_session *session = userdata;
|
struct tmate_session *session = userdata;
|
||||||
|
struct evbuffer *master_out;
|
||||||
|
size_t len;
|
||||||
|
|
||||||
|
master_out = bufferevent_get_output(session->bev_master);
|
||||||
|
|
||||||
|
len = evbuffer_get_length(buffer);
|
||||||
|
|
||||||
|
if (session->keyframe_size + len > TMATE_KEYFRAME_MAX_SIZE) {
|
||||||
|
if (session->keyframe_size == 0)
|
||||||
|
tmate_fatal("keyframe max size too small");
|
||||||
|
tmate_send_master_keyframe(session);
|
||||||
|
}
|
||||||
|
|
||||||
|
session->keyframe_size += len;
|
||||||
|
|
||||||
|
if (evbuffer_add_buffer(master_out, buffer) < 0)
|
||||||
|
tmate_fatal("Cannot write to master buffer");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static void on_master_event(struct bufferevent *bev, short events, void *_session)
|
||||||
|
{
|
||||||
|
if (events & BEV_EVENT_EOF)
|
||||||
|
tmate_fatal("Connection to master closed");
|
||||||
|
|
||||||
|
if (events & BEV_EVENT_ERROR)
|
||||||
|
tmate_fatal("Connection to master error: %s",
|
||||||
|
evutil_socket_error_to_string(EVUTIL_SOCKET_ERROR()));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void on_daemon_decoder_read(void *userdata, struct tmate_unpacker *uk)
|
||||||
|
{
|
||||||
|
struct tmate_session *session = userdata;
|
||||||
|
struct timespec time_diff, current_time;
|
||||||
|
|
||||||
|
if (tmate_has_master()) {
|
||||||
|
if (clock_gettime(CLOCK_MONOTONIC, ¤t_time) < 0)
|
||||||
|
tmate_fatal("Cannot get time");
|
||||||
|
|
||||||
|
timespec_subtract(&time_diff, ¤t_time,
|
||||||
|
&session->keyframe_start_time);
|
||||||
|
if (time_diff.tv_sec > TMATE_KEYFRAME_INTERVAL_SEC - 1)
|
||||||
|
tmate_send_master_keyframe(session);
|
||||||
|
|
||||||
|
tmate_send_master_daemon_msg(session, uk);
|
||||||
|
}
|
||||||
|
|
||||||
tmate_dispatch_daemon_message(session, uk);
|
tmate_dispatch_daemon_message(session, uk);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -37,7 +113,7 @@ static int on_ssh_channel_read(ssh_session _session, ssh_channel channel,
|
|||||||
return written;
|
return written;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void on_encoder_write(void *userdata, struct evbuffer *buffer)
|
static void on_daemon_encoder_write(void *userdata, struct evbuffer *buffer)
|
||||||
{
|
{
|
||||||
struct tmate_session *session = userdata;
|
struct tmate_session *session = userdata;
|
||||||
ssize_t len, written;
|
ssize_t len, written;
|
||||||
@ -62,6 +138,27 @@ static void on_encoder_write(void *userdata, struct evbuffer *buffer)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void init_master(struct tmate_session *session)
|
||||||
|
{
|
||||||
|
/* session->master_fd is already connected */
|
||||||
|
session->bev_master = bufferevent_socket_new(ev_base, session->master_fd,
|
||||||
|
BEV_OPT_CLOSE_ON_FREE);
|
||||||
|
if (!session->bev_master)
|
||||||
|
tmate_fatal("Cannot setup socket bufferevent");
|
||||||
|
|
||||||
|
bufferevent_setcb(session->bev_master,
|
||||||
|
on_master_read, NULL, on_master_event, session);
|
||||||
|
bufferevent_enable(session->bev_master, EV_READ | EV_WRITE);
|
||||||
|
|
||||||
|
tmate_encoder_init(&session->master_encoder, on_master_encoder_write, session);
|
||||||
|
tmate_decoder_init(&session->master_decoder, on_master_decoder_read, session);
|
||||||
|
|
||||||
|
tmate_init_master_session(session);
|
||||||
|
tmate_send_master_header(session);
|
||||||
|
|
||||||
|
tmate_send_master_keyframe(session);
|
||||||
|
}
|
||||||
|
|
||||||
void tmate_daemon_init(struct tmate_session *session)
|
void tmate_daemon_init(struct tmate_session *session)
|
||||||
{
|
{
|
||||||
struct tmate_ssh_client *client = &session->ssh_client;
|
struct tmate_ssh_client *client = &session->ssh_client;
|
||||||
@ -72,6 +169,9 @@ void tmate_daemon_init(struct tmate_session *session)
|
|||||||
client->channel_cb.channel_data_function = on_ssh_channel_read,
|
client->channel_cb.channel_data_function = on_ssh_channel_read,
|
||||||
ssh_set_channel_callbacks(client->channel, &client->channel_cb);
|
ssh_set_channel_callbacks(client->channel, &client->channel_cb);
|
||||||
|
|
||||||
tmate_encoder_init(&session->client_encoder, on_encoder_write, session);
|
tmate_encoder_init(&session->client_encoder, on_daemon_encoder_write, session);
|
||||||
tmate_decoder_init(&session->client_decoder, on_decoder_read, session);
|
tmate_decoder_init(&session->client_decoder, on_daemon_decoder_read, session);
|
||||||
|
|
||||||
|
if (tmate_has_master())
|
||||||
|
init_master(session);
|
||||||
}
|
}
|
||||||
|
@ -300,6 +300,10 @@ void tmate_ssh_server_main(struct tmate_session *session,
|
|||||||
pid_t pid;
|
pid_t pid;
|
||||||
|
|
||||||
setup_signals();
|
setup_signals();
|
||||||
|
|
||||||
|
if (tmate_has_master())
|
||||||
|
close(tmate_connect_to_master());
|
||||||
|
|
||||||
bind = prepare_ssh(keys_dir, port);
|
bind = prepare_ssh(keys_dir, port);
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
@ -314,6 +318,14 @@ void tmate_ssh_server_main(struct tmate_session *session,
|
|||||||
if (ssh_bind_accept(bind, client->session) < 0)
|
if (ssh_bind_accept(bind, client->session) < 0)
|
||||||
tmate_fatal("Error accepting connection: %s", ssh_get_error(bind));
|
tmate_fatal("Error accepting connection: %s", ssh_get_error(bind));
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We should die if we can't connect to master. This way the
|
||||||
|
* tmate daemon will pick another server to work on.
|
||||||
|
*/
|
||||||
|
session->master_fd = -1;
|
||||||
|
if (tmate_has_master())
|
||||||
|
session->master_fd = tmate_connect_to_master();
|
||||||
|
|
||||||
if (get_ip(ssh_get_fd(client->session),
|
if (get_ip(ssh_get_fd(client->session),
|
||||||
client->ip_address, sizeof(client->ip_address)) < 0)
|
client->ip_address, sizeof(client->ip_address)) < 0)
|
||||||
tmate_fatal("Error getting IP address from connection");
|
tmate_fatal("Error getting IP address from connection");
|
||||||
@ -325,6 +337,7 @@ void tmate_ssh_server_main(struct tmate_session *session,
|
|||||||
tmate_info("Child spawned pid=%d, ip=%s",
|
tmate_info("Child spawned pid=%d, ip=%s",
|
||||||
pid, client->ip_address);
|
pid, client->ip_address);
|
||||||
ssh_free(client->session);
|
ssh_free(client->session);
|
||||||
|
close(session->master_fd);
|
||||||
} else {
|
} else {
|
||||||
ssh_bind_free(bind);
|
ssh_bind_free(bind);
|
||||||
session->session_token = "init";
|
session->session_token = "init";
|
||||||
|
63
tmate.h
63
tmate.h
@ -7,6 +7,7 @@
|
|||||||
#include <libssh/libssh.h>
|
#include <libssh/libssh.h>
|
||||||
#include <libssh/callbacks.h>
|
#include <libssh/callbacks.h>
|
||||||
#include <event.h>
|
#include <event.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
#include "tmux.h"
|
#include "tmux.h"
|
||||||
struct tmate_session;
|
struct tmate_session;
|
||||||
@ -106,15 +107,6 @@ extern void unpack_array(struct tmate_unpacker *uk, struct tmate_unpacker *neste
|
|||||||
|
|
||||||
#define TMATE_LATEST_VERSION "1.8.10"
|
#define TMATE_LATEST_VERSION "1.8.10"
|
||||||
|
|
||||||
enum tmate_client_commands {
|
|
||||||
TMATE_NOTIFY,
|
|
||||||
TMATE_CLIENT_PANE_KEY,
|
|
||||||
TMATE_CLIENT_RESIZE,
|
|
||||||
TMATE_CLIENT_EXEC_CMD,
|
|
||||||
TMATE_CLIENT_ENV,
|
|
||||||
TMATE_CLIENT_READY,
|
|
||||||
};
|
|
||||||
|
|
||||||
extern void tmate_client_encoder_init(struct tmate_encoder *encoder);
|
extern void tmate_client_encoder_init(struct tmate_encoder *encoder);
|
||||||
|
|
||||||
extern void printflike1 tmate_notify(const char *fmt, ...);
|
extern void printflike1 tmate_notify(const char *fmt, ...);
|
||||||
@ -133,29 +125,17 @@ extern void tmate_send_client_ready(void);
|
|||||||
/* tmate-client-decoder.c */
|
/* tmate-client-decoder.c */
|
||||||
|
|
||||||
#define TMATE_HLIMIT 2000
|
#define TMATE_HLIMIT 2000
|
||||||
/* 17 and not 16 because the sender does not takes into account envelope size */
|
|
||||||
#define TMATE_MAX_MESSAGE_SIZE (17*1024)
|
|
||||||
|
|
||||||
extern char *tmate_left_status, *tmate_right_status;
|
|
||||||
|
|
||||||
enum tmate_commands {
|
|
||||||
TMATE_HEADER,
|
|
||||||
TMATE_SYNC_LAYOUT,
|
|
||||||
TMATE_PTY_DATA,
|
|
||||||
TMATE_EXEC_CMD,
|
|
||||||
TMATE_FAILED_CMD,
|
|
||||||
TMATE_STATUS,
|
|
||||||
TMATE_SYNC_COPY_MODE,
|
|
||||||
TMATE_WRITE_COPY_MODE,
|
|
||||||
};
|
|
||||||
|
|
||||||
#define TMATE_PANE_ACTIVE 1
|
#define TMATE_PANE_ACTIVE 1
|
||||||
|
|
||||||
|
extern char *tmate_left_status, *tmate_right_status;
|
||||||
extern void tmate_dispatch_daemon_message(struct tmate_session *session,
|
extern void tmate_dispatch_daemon_message(struct tmate_session *session,
|
||||||
struct tmate_unpacker *uk);
|
struct tmate_unpacker *uk);
|
||||||
|
|
||||||
/* tmate-ssh-client.c */
|
/* tmate-ssh-client.c */
|
||||||
|
|
||||||
|
#define TMATE_KEYFRAME_INTERVAL_SEC 10
|
||||||
|
#define TMATE_KEYFRAME_MAX_SIZE 1024*1024
|
||||||
|
|
||||||
extern void tmate_daemon_init(struct tmate_session *session);
|
extern void tmate_daemon_init(struct tmate_session *session);
|
||||||
|
|
||||||
/* tmate-ssh-client-pty.c */
|
/* tmate-ssh-client-pty.c */
|
||||||
@ -208,7 +188,6 @@ extern void tmate_ssh_server_main(struct tmate_session *session,
|
|||||||
|
|
||||||
#define TMATE_SSH_DEFAULT_KEYS_DIR "keys"
|
#define TMATE_SSH_DEFAULT_KEYS_DIR "keys"
|
||||||
|
|
||||||
#define TMATE_DEFAULT_MASTER_HOST NULL
|
|
||||||
#define TMATE_DEFAULT_MASTER_PORT 7000
|
#define TMATE_DEFAULT_MASTER_PORT 7000
|
||||||
|
|
||||||
#define TMATE_TOKEN_LEN 25
|
#define TMATE_TOKEN_LEN 25
|
||||||
@ -231,18 +210,23 @@ struct tmate_session {
|
|||||||
int tmux_socket_fd;
|
int tmux_socket_fd;
|
||||||
|
|
||||||
/* only for deamon */
|
/* only for deamon */
|
||||||
|
const char *session_token;
|
||||||
|
const char *session_token_ro;
|
||||||
|
|
||||||
struct tmate_encoder client_encoder;
|
struct tmate_encoder client_encoder;
|
||||||
struct tmate_decoder client_decoder;
|
struct tmate_decoder client_decoder;
|
||||||
int client_protocol_version;
|
int client_protocol_version;
|
||||||
|
struct event ev_notify_timer;
|
||||||
|
|
||||||
|
int master_fd;
|
||||||
|
struct bufferevent *bev_master;
|
||||||
struct tmate_encoder master_encoder;
|
struct tmate_encoder master_encoder;
|
||||||
struct tmate_decoder master_decoder;
|
struct tmate_decoder master_decoder;
|
||||||
|
|
||||||
const char *session_token;
|
struct timespec session_start_time;
|
||||||
const char *session_token_ro;
|
struct timespec keyframe_start_time;
|
||||||
|
unsigned int keyframe_cnt;
|
||||||
struct event ev_notify_timer;
|
size_t keyframe_size;
|
||||||
|
|
||||||
/* only for client-pty */
|
/* only for client-pty */
|
||||||
int pty;
|
int pty;
|
||||||
@ -256,6 +240,25 @@ extern long tmate_get_random_long(void);
|
|||||||
extern void request_server_termination(void);
|
extern void request_server_termination(void);
|
||||||
extern void tmate_spawn_slave(struct tmate_session *session);
|
extern void tmate_spawn_slave(struct tmate_session *session);
|
||||||
|
|
||||||
|
/* tmate-master.c */
|
||||||
|
|
||||||
|
extern void tmate_send_master_keyframe(struct tmate_session *session);
|
||||||
|
extern void tmate_send_master_daemon_msg(struct tmate_session *session,
|
||||||
|
struct tmate_unpacker *uk);
|
||||||
|
extern void tmate_send_master_header(struct tmate_session *session);
|
||||||
|
extern void tmate_init_master_session(struct tmate_session *session);
|
||||||
|
|
||||||
|
extern int tmate_connect_to_master(void);
|
||||||
|
static inline bool tmate_has_master(void)
|
||||||
|
{
|
||||||
|
return !!tmate_settings->master_hostname;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
extern void timespec_subtract(struct timespec *result,
|
||||||
|
struct timespec *x, struct timespec *y);
|
||||||
|
extern unsigned long long timespec_to_millisec(struct timespec *ts);
|
||||||
|
|
||||||
/* tmate-debug.c */
|
/* tmate-debug.c */
|
||||||
|
|
||||||
extern void tmate_preload_trace_lib(void);
|
extern void tmate_preload_trace_lib(void);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user