summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNicolas Viennot <nicolas@viennot.biz>2019-11-10 03:44:37 -0500
committerNicolas Viennot <nicolas@viennot.biz>2019-11-10 03:58:59 -0500
commit2b860313088465044a596b7604dc184336c93e54 (patch)
treefc8d6d88ba8eecf40c609cf29e7438e811adffee
parent2b146115446ca0477d2c3d7155f07f22fdb9c265 (diff)
Fix keepalive bug
-rw-r--r--tmate-session.c6
-rw-r--r--tmate-ssh-client.c69
-rw-r--r--tmate.h1
3 files changed, 50 insertions, 26 deletions
diff --git a/tmate-session.c b/tmate-session.c
index 1863f78c..10c6123b 100644
--- a/tmate-session.c
+++ b/tmate-session.c
@@ -36,6 +36,9 @@ static void dns_cb(int errcode, struct evutil_addrinfo *addr, void *ptr)
struct evutil_addrinfo *ai;
const char *host = ptr;
+ evdns_base_free(tmate_session.ev_dnsbase, 0);
+ tmate_session.ev_dnsbase = NULL;
+
if (errcode) {
struct tmate_session *session = &tmate_session;
@@ -81,9 +84,6 @@ static void dns_cb(int errcode, struct evutil_addrinfo *addr, void *ptr)
connect_ssh_client(ssh_clients[i]);
evutil_freeaddrinfo(addr);
-
- evdns_base_free(tmate_session.ev_dnsbase, 0);
- tmate_session.ev_dnsbase = NULL;
}
static void lookup_and_connect(void)
diff --git a/tmate-ssh-client.c b/tmate-ssh-client.c
index 030b330a..221d7c9f 100644
--- a/tmate-ssh-client.c
+++ b/tmate-ssh-client.c
@@ -167,57 +167,84 @@ static void request_passphrase(struct tmate_ssh_client *client)
data->password_cb_private = client;
}
-#define KEEPALIVE_CNT 3
-#define KEEPALIVE_IDLE 20
-#define KEEPALIVE_INTVL 10
+#define KEEPALIVE_IDLE 30
+#define KEEPALIVE_CNT 4
+#define KEEPALIVE_INTVL 11
+#define WRITE_TIMEOUT 80
static void tune_socket_opts(int fd)
{
#define SSO(level, optname, val) ({ \
int _flag = val; \
if (setsockopt(fd, level, optname, &(_flag), sizeof(int)) < 0) { \
- tmate_debug("setsockopt(" #level ", " #optname ", %d) failed", val); \
+ tmate_info("setsockopt(" #level ", " #optname ", %d) failed", val); \
} \
})
SSO(IPPROTO_TCP, TCP_NODELAY, 1);
SSO(SOL_SOCKET, SO_KEEPALIVE, 1);
#ifdef TCP_KEEPALIVE
+ /*
+ * The TCP_KEEPALIVE options enable to specify the amount of time, in
+ * seconds, that the connection must be idle before keepalive probes
+ * (if enabled) are sent.
+ */
SSO(IPPROTO_TCP, TCP_KEEPALIVE, KEEPALIVE_IDLE);
#endif
-#ifdef TCP_KEEPCNT
- SSO(IPPROTO_TCP, TCP_KEEPCNT, KEEPALIVE_CNT);
-#endif
#ifdef TCP_KEEPIDLE
+ /*
+ * Same as TCP_KEEPALIVE, but on different systems
+ */
SSO(IPPROTO_TCP, TCP_KEEPIDLE, KEEPALIVE_IDLE);
#endif
+#ifdef TCP_KEEPCNT
+ /*
+ * When keepalive probes are enabled, this option will set the number
+ * of times a keepalive probe should be repeated if the peer is not
+ * responding. After this many probes, the connection will be closed.
+ */
+ SSO(IPPROTO_TCP, TCP_KEEPCNT, KEEPALIVE_CNT);
+#endif
#ifdef TCP_KEEPINTVL
+ /*
+ * When keepalive probes are enabled, this option will set the amount
+ * of time in seconds between successive keepalives sent to probe an
+ * unresponsive peer.
+ */
SSO(IPPROTO_TCP, TCP_KEEPINTVL, KEEPALIVE_INTVL);
#endif
+#ifdef TCP_USER_TIMEOUT
+ /*
+ * This option takes an unsigned int as an argument. When the
+ * value is greater than 0, it specifies the maximum amount of
+ * time in milliseconds that transmitted data may remain
+ * unacknowledged before TCP will forcibly close the
+ * corresponding connection and return ETIMEDOUT to the
+ * application.
+ */
+ SSO(IPPROTO_TCP, TCP_USER_TIMEOUT, 1000*WRITE_TIMEOUT);
+#endif
#undef SSO
}
-static void init_conn_fd(struct tmate_ssh_client *client, bool tune_socket)
+static void init_conn_fd(struct tmate_ssh_client *client)
{
int fd;
- if (client->has_init_conn_fd)
+ if (client->ev_ssh)
return;
if ((fd = ssh_get_fd(client->session)) < 0)
return;
- if (tune_socket)
- tune_socket_opts(fd);
+ tune_socket_opts(fd);
- assert(!client->ev_ssh);
- client->ev_ssh = event_new(client->tmate_session->ev_base,
- fd, EV_READ | EV_PERSIST, __on_ssh_client_event, client);
+ client->ev_ssh = event_new(client->tmate_session->ev_base, fd,
+ EV_READ | EV_PERSIST,
+ __on_ssh_client_event, client);
if (!client->ev_ssh)
tmate_fatal("out of memory");
event_add(client->ev_ssh, NULL);
-
- client->has_init_conn_fd = true;
}
static void on_ssh_client_event(struct tmate_ssh_client *client)
@@ -273,14 +300,14 @@ static void on_ssh_client_event(struct tmate_ssh_client *client)
case SSH_CONNECT:
switch (ssh_connect(session)) {
case SSH_AGAIN:
- init_conn_fd(client, false);
+ init_conn_fd(client);
return;
case SSH_ERROR:
kill_ssh_client(client, "Error connecting: %s",
ssh_get_error(session));
return;
case SSH_OK:
- init_conn_fd(client, true);
+ init_conn_fd(client);
tmate_debug("Establishing connection to %s", client->server_ip);
client->state = SSH_AUTH_SERVER;
@@ -482,10 +509,10 @@ static void kill_ssh_client(struct tmate_ssh_client *client,
tmate_debug("SSH client killed (%s)", client->server_ip);
- if (client->has_init_conn_fd) {
+ if (client->ev_ssh) {
event_del(client->ev_ssh);
event_free(client->ev_ssh);
- client->has_init_conn_fd = false;
+ client->ev_ssh = NULL;
}
if (client->state == SSH_READY) {
@@ -548,7 +575,5 @@ struct tmate_ssh_client *tmate_ssh_client_alloc(struct tmate_session *session,
client->channel = NULL;
client->has_encoder = 0;
- client->has_init_conn_fd = false;
-
return client;
}
diff --git a/tmate.h b/tmate.h
index 9b177120..5c3af6a0 100644
--- a/tmate.h
+++ b/tmate.h
@@ -141,7 +141,6 @@ struct tmate_ssh_client {
ssh_session session;
ssh_channel channel;
- bool has_init_conn_fd;
struct event *ev_ssh;
};
TAILQ_HEAD(tmate_ssh_clients, tmate_ssh_client);