mirror of
https://github.com/tmate-io/tmate-ssh-server.git
synced 2020-11-18 19:53:51 -08:00
Support for multiple IP on DNS
This commit is contained in:
parent
2e3661a0f6
commit
36bfa71b78
@ -182,7 +182,7 @@ dist_tmate_SOURCES = \
|
|||||||
tmate-encoder.c \
|
tmate-encoder.c \
|
||||||
tmate-decoder.c \
|
tmate-decoder.c \
|
||||||
tmate-msg.c \
|
tmate-msg.c \
|
||||||
tmate.c \
|
tmate-session.c \
|
||||||
tmux.c \
|
tmux.c \
|
||||||
tty-acs.c \
|
tty-acs.c \
|
||||||
tty-keys.c \
|
tty-keys.c \
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
# $Id$
|
# $Id$
|
||||||
|
|
||||||
# Miscellaneous autofoo bullshit.
|
# Miscellaneous autofoo bullshit.
|
||||||
AC_INIT(tmate, 1.8.4)
|
AC_INIT(tmate, 1.8.6)
|
||||||
|
|
||||||
AC_CONFIG_AUX_DIR(etc)
|
AC_CONFIG_AUX_DIR(etc)
|
||||||
AM_INIT_AUTOMAKE([foreign])
|
AM_INIT_AUTOMAKE([foreign])
|
||||||
|
2
server.c
2
server.c
@ -187,7 +187,7 @@ server_start(int lockfd, char *lockfile)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
tmate_client_start();
|
tmate_session_start();
|
||||||
|
|
||||||
cmdq_continue(cfg_cmd_q);
|
cmdq_continue(cfg_cmd_q);
|
||||||
|
|
||||||
|
@ -73,3 +73,17 @@ void tmate_print_trace(void)
|
|||||||
|
|
||||||
free (strings);
|
free (strings);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void handle_sigsegv(int sig)
|
||||||
|
{
|
||||||
|
/* TODO send stack trace to server */
|
||||||
|
tmate_info("CRASH, printing stack trace");
|
||||||
|
tmate_print_trace();
|
||||||
|
tmate_fatal("CRASHED");
|
||||||
|
}
|
||||||
|
|
||||||
|
void tmate_catch_sigsegv(void)
|
||||||
|
{
|
||||||
|
signal(SIGSEGV, handle_sigsegv);
|
||||||
|
}
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
#include "tmate.h"
|
#include "tmate.h"
|
||||||
|
|
||||||
|
#define DEFAULT_ENCODER (&tmate_session.encoder)
|
||||||
|
|
||||||
static int msgpack_write(void *data, const char *buf, unsigned int len)
|
static int msgpack_write(void *data, const char *buf, unsigned int len)
|
||||||
{
|
{
|
||||||
struct tmate_encoder *encoder = data;
|
struct tmate_encoder *encoder = data;
|
||||||
@ -26,13 +28,14 @@ void tmate_encoder_init(struct tmate_encoder *encoder)
|
|||||||
msgpack_pack_raw_body(pk, str, __strlen); \
|
msgpack_pack_raw_body(pk, str, __strlen); \
|
||||||
} while(0)
|
} while(0)
|
||||||
|
|
||||||
#define pack(what, ...) msgpack_pack_##what(&tmate_encoder->pk, __VA_ARGS__)
|
#define pack(what, ...) msgpack_pack_##what(&DEFAULT_ENCODER->pk, __VA_ARGS__)
|
||||||
|
|
||||||
void tmate_write_header(void)
|
void tmate_write_header(void)
|
||||||
{
|
{
|
||||||
pack(array, 2);
|
pack(array, 3);
|
||||||
pack(int, TMATE_HEADER);
|
pack(int, TMATE_HEADER);
|
||||||
pack(int, TMATE_PROTOCOL_VERSION);
|
pack(int, TMATE_PROTOCOL_VERSION);
|
||||||
|
pack(string, VERSION);
|
||||||
}
|
}
|
||||||
|
|
||||||
void tmate_sync_layout(void)
|
void tmate_sync_layout(void)
|
||||||
|
107
tmate-session.c
Normal file
107
tmate-session.c
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
#include <event2/dns.h>
|
||||||
|
#include <event2/util.h>
|
||||||
|
#include <event2/event.h>
|
||||||
|
|
||||||
|
#include <sys/socket.h>
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
#include "tmate.h"
|
||||||
|
|
||||||
|
#define TMATE_DNS_RETRY_TIMEOUT 10
|
||||||
|
|
||||||
|
struct tmate_session tmate_session;
|
||||||
|
|
||||||
|
static struct evdns_base *ev_dnsbase;
|
||||||
|
static struct event ev_dns_retry;
|
||||||
|
static void lookup_and_connect(void);
|
||||||
|
|
||||||
|
static void on_dns_retry(evutil_socket_t fd, short what, void *arg)
|
||||||
|
{
|
||||||
|
lookup_and_connect();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dns_cb(int errcode, struct evutil_addrinfo *addr, void *ptr)
|
||||||
|
{
|
||||||
|
struct tmate_ssh_client *client;
|
||||||
|
struct evutil_addrinfo *ai;
|
||||||
|
struct timeval tv;
|
||||||
|
|
||||||
|
if (errcode) {
|
||||||
|
tmate_status_message("%s lookup failure. Retrying in %d seconds (%s)",
|
||||||
|
TMATE_HOST, TMATE_DNS_RETRY_TIMEOUT,
|
||||||
|
evutil_gai_strerror(errcode));
|
||||||
|
|
||||||
|
tv.tv_sec = TMATE_DNS_RETRY_TIMEOUT;
|
||||||
|
tv.tv_usec = 0;
|
||||||
|
|
||||||
|
evtimer_assign(&ev_dns_retry, ev_base, on_dns_retry, NULL);
|
||||||
|
evtimer_add(&ev_dns_retry, &tv);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
tmate_status_message("Connecting to %s...", TMATE_HOST);
|
||||||
|
|
||||||
|
for (ai = addr; ai; ai = ai->ai_next) {
|
||||||
|
char buf[128];
|
||||||
|
const char *ip = NULL;
|
||||||
|
if (ai->ai_family == AF_INET) {
|
||||||
|
struct sockaddr_in *sin = (struct sockaddr_in *)ai->ai_addr;
|
||||||
|
ip = evutil_inet_ntop(AF_INET, &sin->sin_addr, buf, 128);
|
||||||
|
} else if (ai->ai_family == AF_INET6) {
|
||||||
|
struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)ai->ai_addr;
|
||||||
|
ip = evutil_inet_ntop(AF_INET6, &sin6->sin6_addr, buf, 128);
|
||||||
|
}
|
||||||
|
|
||||||
|
tmate_debug("Trying server %s", ip);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Note: We don't deal with the client list. Clients manage it
|
||||||
|
* and free client structs when necessary.
|
||||||
|
*/
|
||||||
|
(void)tmate_ssh_client_alloc(&tmate_session, ip);
|
||||||
|
}
|
||||||
|
|
||||||
|
evutil_freeaddrinfo(addr);
|
||||||
|
|
||||||
|
evdns_base_free(ev_dnsbase, 0);
|
||||||
|
ev_dnsbase = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void lookup_and_connect(void)
|
||||||
|
{
|
||||||
|
struct evutil_addrinfo hints;
|
||||||
|
|
||||||
|
if (!ev_dnsbase)
|
||||||
|
ev_dnsbase = evdns_base_new(ev_base, 1);
|
||||||
|
if (!ev_dnsbase)
|
||||||
|
tmate_fatal("Cannot initialize the DNS lookup service");
|
||||||
|
|
||||||
|
memset(&hints, 0, sizeof(hints));
|
||||||
|
hints.ai_family = AF_UNSPEC;
|
||||||
|
hints.ai_flags = 0;
|
||||||
|
hints.ai_socktype = SOCK_STREAM;
|
||||||
|
hints.ai_protocol = IPPROTO_TCP;
|
||||||
|
|
||||||
|
tmate_status_message("Looking up %s...", TMATE_HOST);
|
||||||
|
(void)evdns_getaddrinfo(ev_dnsbase, TMATE_HOST, NULL,
|
||||||
|
&hints, dns_cb, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
void tmate_session_start(void)
|
||||||
|
{
|
||||||
|
tmate_catch_sigsegv();
|
||||||
|
|
||||||
|
TAILQ_INIT(&tmate_session.clients);
|
||||||
|
tmate_encoder_init(&tmate_session.encoder);
|
||||||
|
tmate_decoder_init(&tmate_session.decoder);
|
||||||
|
|
||||||
|
lookup_and_connect();
|
||||||
|
|
||||||
|
/* The header will be written as soon as the first client connects */
|
||||||
|
tmate_write_header();
|
||||||
|
}
|
@ -1,9 +1,8 @@
|
|||||||
#include <libssh/libssh.h>
|
|
||||||
#include <libssh/callbacks.h>
|
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <netinet/tcp.h>
|
#include <netinet/tcp.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <event.h>
|
#include <event.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
#include "tmate.h"
|
#include "tmate.h"
|
||||||
|
|
||||||
@ -19,14 +18,10 @@ static void printflike2 reconnect_session(struct tmate_ssh_client *client,
|
|||||||
static void log_function(ssh_session session, int priority,
|
static void log_function(ssh_session session, int priority,
|
||||||
const char *message, void *userdata)
|
const char *message, void *userdata)
|
||||||
{
|
{
|
||||||
tmate_debug("[%d] %s", priority, message);
|
struct tmate_ssh_client *client = userdata;
|
||||||
|
tmate_debug("[%s] [%d] %s", client->server_ip, priority, message);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct ssh_callbacks_struct ssh_session_callbacks = {
|
|
||||||
.log_function = log_function
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
static void register_session_fd_event(struct tmate_ssh_client *client)
|
static void register_session_fd_event(struct tmate_ssh_client *client)
|
||||||
{
|
{
|
||||||
if (!event_initialized(&client->ev_ssh)) {
|
if (!event_initialized(&client->ev_ssh)) {
|
||||||
@ -42,20 +37,24 @@ static void register_session_fd_event(struct tmate_ssh_client *client)
|
|||||||
|
|
||||||
static void register_input_stream_event(struct tmate_ssh_client *client)
|
static void register_input_stream_event(struct tmate_ssh_client *client)
|
||||||
{
|
{
|
||||||
if (!event_initialized(&client->encoder->ev_readable)) {
|
struct tmate_encoder *encoder = &client->tmate_session->encoder;
|
||||||
event_assign(&client->encoder->ev_readable, ev_base, -1,
|
|
||||||
|
if (!event_initialized(&encoder->ev_readable)) {
|
||||||
|
event_assign(&encoder->ev_readable, ev_base, -1,
|
||||||
EV_READ | EV_PERSIST, __flush_input_stream, client);
|
EV_READ | EV_PERSIST, __flush_input_stream, client);
|
||||||
event_add(&client->encoder->ev_readable, NULL);
|
event_add(&encoder->ev_readable, NULL);
|
||||||
|
client->has_encoder = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void consume_channel(struct tmate_ssh_client *client)
|
static void consume_channel(struct tmate_ssh_client *client)
|
||||||
{
|
{
|
||||||
|
struct tmate_decoder *decoder = &client->tmate_session->decoder;
|
||||||
char *buf;
|
char *buf;
|
||||||
ssize_t len;
|
ssize_t len;
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
tmate_decoder_get_buffer(client->decoder, &buf, &len);
|
tmate_decoder_get_buffer(decoder, &buf, &len);
|
||||||
len = ssh_channel_read_nonblocking(client->channel, buf, len, 0);
|
len = ssh_channel_read_nonblocking(client->channel, buf, len, 0);
|
||||||
if (len < 0) {
|
if (len < 0) {
|
||||||
reconnect_session(client, "Error reading from channel: %s",
|
reconnect_session(client, "Error reading from channel: %s",
|
||||||
@ -66,7 +65,21 @@ static void consume_channel(struct tmate_ssh_client *client)
|
|||||||
if (len == 0)
|
if (len == 0)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
tmate_decoder_commit(client->decoder, len);
|
tmate_decoder_commit(decoder, len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void connection_complete(struct tmate_ssh_client *connected_client)
|
||||||
|
{
|
||||||
|
struct tmate_session *session = connected_client->tmate_session;
|
||||||
|
struct tmate_ssh_client *client, *tmp_client;
|
||||||
|
|
||||||
|
TAILQ_FOREACH_SAFE(client, &session->clients, node, tmp_client) {
|
||||||
|
if (client == connected_client)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
assert(!client->has_encoder);
|
||||||
|
tmate_ssh_client_free(client);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -93,7 +106,7 @@ static void on_session_event(struct tmate_ssh_client *client)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ssh_set_callbacks(session, &ssh_session_callbacks);
|
ssh_set_callbacks(session, &client->ssh_callbacks);
|
||||||
|
|
||||||
client->channel = channel = ssh_channel_new(session);
|
client->channel = channel = ssh_channel_new(session);
|
||||||
if (!channel) {
|
if (!channel) {
|
||||||
@ -102,13 +115,12 @@ static void on_session_event(struct tmate_ssh_client *client)
|
|||||||
}
|
}
|
||||||
|
|
||||||
ssh_set_blocking(session, 0);
|
ssh_set_blocking(session, 0);
|
||||||
ssh_options_set(session, SSH_OPTIONS_HOST, TMATE_HOST);
|
ssh_options_set(session, SSH_OPTIONS_HOST, client->server_ip);
|
||||||
ssh_options_set(session, SSH_OPTIONS_LOG_VERBOSITY, &verbosity);
|
ssh_options_set(session, SSH_OPTIONS_LOG_VERBOSITY, &verbosity);
|
||||||
ssh_options_set(session, SSH_OPTIONS_PORT, &port);
|
ssh_options_set(session, SSH_OPTIONS_PORT, &port);
|
||||||
ssh_options_set(session, SSH_OPTIONS_USER, "tmate");
|
ssh_options_set(session, SSH_OPTIONS_USER, "tmate");
|
||||||
ssh_options_set(session, SSH_OPTIONS_COMPRESSION, "yes");
|
ssh_options_set(session, SSH_OPTIONS_COMPRESSION, "yes");
|
||||||
|
|
||||||
tmate_status_message("Connecting to %s...", TMATE_HOST);
|
|
||||||
client->state = SSH_CONNECT;
|
client->state = SSH_CONNECT;
|
||||||
/* fall through */
|
/* fall through */
|
||||||
|
|
||||||
@ -123,14 +135,14 @@ static void on_session_event(struct tmate_ssh_client *client)
|
|||||||
return;
|
return;
|
||||||
case SSH_OK:
|
case SSH_OK:
|
||||||
register_session_fd_event(client);
|
register_session_fd_event(client);
|
||||||
tmate_debug("Connected");
|
tmate_debug("Establishing connection to %s", client->server_ip);
|
||||||
client->state = SSH_AUTH_SERVER;
|
client->state = SSH_AUTH_SERVER;
|
||||||
/* fall through */
|
/* fall through */
|
||||||
}
|
}
|
||||||
|
|
||||||
case SSH_AUTH_SERVER:
|
case SSH_AUTH_SERVER:
|
||||||
if ((hash_len = ssh_get_pubkey_hash(session, &hash)) < 0) {
|
if ((hash_len = ssh_get_pubkey_hash(session, &hash)) < 0) {
|
||||||
disconnect_session(client, "Cannnot authenticate server");
|
disconnect_session(client, "Cannot authenticate server");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -165,11 +177,20 @@ static void on_session_event(struct tmate_ssh_client *client)
|
|||||||
free(hash_str);
|
free(hash_str);
|
||||||
|
|
||||||
if (!match) {
|
if (!match) {
|
||||||
disconnect_session(client, "Cannnot authenticate server");
|
disconnect_session(client, "Cannot authenticate server");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* At this point, we abort other connection attempts to the
|
||||||
|
* other tmate servers, since we have reached the fastest one.
|
||||||
|
* We need to do it before we ask the user its passphrase,
|
||||||
|
* otherwise the speed test would be biased.
|
||||||
|
*/
|
||||||
|
tmate_debug("Connected to %s", client->server_ip);
|
||||||
|
connection_complete(client);
|
||||||
client->state = SSH_AUTH_CLIENT;
|
client->state = SSH_AUTH_CLIENT;
|
||||||
|
|
||||||
/* fall through */
|
/* fall through */
|
||||||
|
|
||||||
case SSH_AUTH_CLIENT:
|
case SSH_AUTH_CLIENT:
|
||||||
@ -179,7 +200,8 @@ static void on_session_event(struct tmate_ssh_client *client)
|
|||||||
case SSH_AUTH_PARTIAL:
|
case SSH_AUTH_PARTIAL:
|
||||||
case SSH_AUTH_INFO:
|
case SSH_AUTH_INFO:
|
||||||
case SSH_AUTH_DENIED:
|
case SSH_AUTH_DENIED:
|
||||||
disconnect_session(client, "Access denied. Check your SSH keys.");
|
disconnect_session(client, "Access denied. Check your SSH keys "
|
||||||
|
"(passphrases are not supported yet).");
|
||||||
return;
|
return;
|
||||||
case SSH_AUTH_ERROR:
|
case SSH_AUTH_ERROR:
|
||||||
reconnect_session(client, "Auth error: %s",
|
reconnect_session(client, "Auth error: %s",
|
||||||
@ -236,7 +258,8 @@ static void on_session_event(struct tmate_ssh_client *client)
|
|||||||
|
|
||||||
static void flush_input_stream(struct tmate_ssh_client *client)
|
static void flush_input_stream(struct tmate_ssh_client *client)
|
||||||
{
|
{
|
||||||
struct evbuffer *evb = client->encoder->buffer;
|
struct tmate_encoder *encoder = &client->tmate_session->encoder;
|
||||||
|
struct evbuffer *evb = encoder->buffer;
|
||||||
ssize_t len, written;
|
ssize_t len, written;
|
||||||
char *buf;
|
char *buf;
|
||||||
|
|
||||||
@ -274,16 +297,23 @@ static void __on_session_event(evutil_socket_t fd, short what, void *arg)
|
|||||||
static void __disconnect_session(struct tmate_ssh_client *client,
|
static void __disconnect_session(struct tmate_ssh_client *client,
|
||||||
const char *fmt, va_list va)
|
const char *fmt, va_list va)
|
||||||
{
|
{
|
||||||
__tmate_status_message(fmt, va);
|
struct tmate_encoder *encoder;
|
||||||
|
|
||||||
|
if (fmt)
|
||||||
|
__tmate_status_message(fmt, va);
|
||||||
|
else
|
||||||
|
tmate_debug("Disconnecting %s", client->server_ip);
|
||||||
|
|
||||||
if (event_initialized(&client->ev_ssh)) {
|
if (event_initialized(&client->ev_ssh)) {
|
||||||
event_del(&client->ev_ssh);
|
event_del(&client->ev_ssh);
|
||||||
client->ev_ssh.ev_flags = 0;
|
client->ev_ssh.ev_flags = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (event_initialized(&client->encoder->ev_readable)) {
|
if (client->has_encoder) {
|
||||||
event_del(&client->encoder->ev_readable);
|
encoder = &client->tmate_session->encoder;
|
||||||
client->encoder->ev_readable.ev_flags = 0;
|
event_del(&encoder->ev_readable);
|
||||||
|
encoder->ev_readable.ev_flags = 0;
|
||||||
|
client->has_encoder = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (client->session) {
|
if (client->session) {
|
||||||
@ -337,21 +367,38 @@ static void printflike2 reconnect_session(struct tmate_ssh_client *client,
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void tmate_ssh_client_init(struct tmate_ssh_client *client,
|
|
||||||
struct tmate_encoder *encoder,
|
|
||||||
struct tmate_decoder *decoder)
|
|
||||||
{
|
|
||||||
ssh_callbacks_init(&ssh_session_callbacks);
|
|
||||||
|
|
||||||
|
struct tmate_ssh_client *tmate_ssh_client_alloc(struct tmate_session *session,
|
||||||
|
const char *server_ip)
|
||||||
|
{
|
||||||
|
struct tmate_ssh_client *client;
|
||||||
|
client = xmalloc(sizeof(*client));
|
||||||
|
|
||||||
|
ssh_callbacks_init(&client->ssh_callbacks);
|
||||||
|
client->ssh_callbacks.log_function = log_function;
|
||||||
|
client->ssh_callbacks.userdata = client;
|
||||||
|
|
||||||
|
client->tmate_session = session;
|
||||||
|
TAILQ_INSERT_TAIL(&session->clients, client, node);
|
||||||
|
|
||||||
|
client->server_ip = xstrdup(server_ip);
|
||||||
client->state = SSH_NONE;
|
client->state = SSH_NONE;
|
||||||
client->session = NULL;
|
client->session = NULL;
|
||||||
client->channel = NULL;
|
client->channel = NULL;
|
||||||
|
client->has_encoder = 0;
|
||||||
client->encoder = encoder;
|
|
||||||
client->decoder = decoder;
|
|
||||||
|
|
||||||
evtimer_assign(&client->ev_ssh_reconnect, ev_base,
|
evtimer_assign(&client->ev_ssh_reconnect, ev_base,
|
||||||
on_reconnect_timer, client);
|
on_reconnect_timer, client);
|
||||||
|
|
||||||
connect_session(client);
|
connect_session(client);
|
||||||
|
|
||||||
|
return client;
|
||||||
|
}
|
||||||
|
|
||||||
|
void tmate_ssh_client_free(struct tmate_ssh_client *client)
|
||||||
|
{
|
||||||
|
disconnect_session(client, NULL);
|
||||||
|
TAILQ_REMOVE(&client->tmate_session->clients, client, node);
|
||||||
|
free(client->server_ip);
|
||||||
|
free(client);
|
||||||
}
|
}
|
||||||
|
18
tmate.c
18
tmate.c
@ -1,18 +0,0 @@
|
|||||||
#include "tmate.h"
|
|
||||||
|
|
||||||
struct tmate_encoder *tmate_encoder;
|
|
||||||
|
|
||||||
static struct tmate_ssh_client client;
|
|
||||||
static struct tmate_encoder encoder;
|
|
||||||
static struct tmate_decoder decoder;
|
|
||||||
|
|
||||||
void tmate_client_start(void)
|
|
||||||
{
|
|
||||||
tmate_encoder_init(&encoder);
|
|
||||||
tmate_decoder_init(&decoder);
|
|
||||||
tmate_encoder = &encoder;
|
|
||||||
|
|
||||||
tmate_ssh_client_init(&client, &encoder, &decoder);
|
|
||||||
|
|
||||||
tmate_write_header();
|
|
||||||
}
|
|
57
tmate.h
57
tmate.h
@ -4,6 +4,7 @@
|
|||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <msgpack.h>
|
#include <msgpack.h>
|
||||||
#include <libssh/libssh.h>
|
#include <libssh/libssh.h>
|
||||||
|
#include <libssh/callbacks.h>
|
||||||
#include <event.h>
|
#include <event.h>
|
||||||
|
|
||||||
#include "tmux.h"
|
#include "tmux.h"
|
||||||
@ -17,7 +18,7 @@
|
|||||||
|
|
||||||
#define TMATE_MAX_MESSAGE_SIZE (16*1024)
|
#define TMATE_MAX_MESSAGE_SIZE (16*1024)
|
||||||
|
|
||||||
#define TMATE_PROTOCOL_VERSION 2
|
#define TMATE_PROTOCOL_VERSION 3
|
||||||
|
|
||||||
enum tmate_commands {
|
enum tmate_commands {
|
||||||
TMATE_HEADER,
|
TMATE_HEADER,
|
||||||
@ -72,7 +73,7 @@ extern void tmate_decoder_commit(struct tmate_decoder *decoder, size_t len);
|
|||||||
/* tmate-ssh-client.c */
|
/* tmate-ssh-client.c */
|
||||||
|
|
||||||
#ifdef DEVENV
|
#ifdef DEVENV
|
||||||
#define TMATE_HOST "127.0.0.1"
|
#define TMATE_HOST "localhost"
|
||||||
#define TMATE_PORT 2200
|
#define TMATE_PORT 2200
|
||||||
#else
|
#else
|
||||||
#define TMATE_HOST "master.tmate.io"
|
#define TMATE_HOST "master.tmate.io"
|
||||||
@ -94,28 +95,60 @@ enum tmate_ssh_client_state_types {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct tmate_ssh_client {
|
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 has_encoder;
|
||||||
int state;
|
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;
|
||||||
ssh_session session;
|
ssh_session session;
|
||||||
ssh_channel channel;
|
ssh_channel channel;
|
||||||
|
|
||||||
struct tmate_encoder *encoder;
|
|
||||||
struct tmate_decoder *decoder;
|
|
||||||
|
|
||||||
struct event ev_ssh;
|
struct event ev_ssh;
|
||||||
struct event ev_ssh_reconnect;
|
struct event ev_ssh_reconnect;
|
||||||
};
|
};
|
||||||
|
TAILQ_HEAD(tmate_ssh_clients, tmate_ssh_client);
|
||||||
|
|
||||||
extern void tmate_ssh_client_init(struct tmate_ssh_client *client,
|
extern struct tmate_ssh_client *tmate_ssh_client_alloc(struct tmate_session *session,
|
||||||
struct tmate_encoder *encoder,
|
const char *server_ip);
|
||||||
struct tmate_decoder *decoder);
|
extern void tmate_ssh_client_free(struct tmate_ssh_client *client);
|
||||||
|
|
||||||
/* tmate.c */
|
/* tmate-session.c */
|
||||||
|
|
||||||
extern struct tmate_encoder *tmate_encoder;
|
struct tmate_session {
|
||||||
extern void tmate_client_start(void);
|
struct tmate_encoder encoder;
|
||||||
|
struct tmate_decoder decoder;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern struct tmate_session tmate_session;
|
||||||
|
extern void tmate_session_start(void);
|
||||||
|
|
||||||
/* tmate-debug.c */
|
/* tmate-debug.c */
|
||||||
extern void tmate_print_trace (void);
|
extern void tmate_print_trace(void);
|
||||||
|
extern void tmate_catch_sigsegv(void);
|
||||||
|
|
||||||
/* tmate-msg.c */
|
/* tmate-msg.c */
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user