summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNicolas Viennot <nicolas@viennot.biz>2016-04-21 16:05:52 -0400
committerNicolas Viennot <nicolas@viennot.biz>2016-04-21 16:20:27 -0400
commitfe81322cc4801860c33b1e31970b8f0f6bf603c7 (patch)
treefb0a76416a182fd1e725449f45a9a4a06d4290b7
parentd433fe69565db25b4248b8e9f0316d2cd04fe7e3 (diff)
Keep alive the socket to make reconnections work properly
-rw-r--r--tmate-ssh-client.c44
1 files changed, 35 insertions, 9 deletions
diff --git a/tmate-ssh-client.c b/tmate-ssh-client.c
index b280400d..8b78f5cc 100644
--- a/tmate-ssh-client.c
+++ b/tmate-ssh-client.c
@@ -165,22 +165,48 @@ 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
+
+static void setup_socket(int fd)
+{
+#define SSO(level, optname, val) ({ \
+ int _flag = val; \
+ if (setsockopt(fd, level, optname, &(_flag), sizeof(int)) < 0) { \
+ tmate_warn("setsockopt(" #level ", " #optname ", %d) failed", val); \
+ } \
+})
+
+ SSO(IPPROTO_TCP, TCP_NODELAY, 1);
+ SSO(SOL_SOCKET, SO_KEEPALIVE, 1);
+#ifdef TCP_KEEPALIVE
+ SSO(IPPROTO_TCP, TCP_KEEPALIVE, KEEPALIVE_IDLE);
+#endif
+#ifdef TCP_KEEPCNT
+ SSO(IPPROTO_TCP, TCP_KEEPCNT, KEEPALIVE_CNT);
+#endif
+#ifdef TCP_KEEPIDLE
+ SSO(IPPROTO_TCP, TCP_KEEPIDLE, KEEPALIVE_IDLE);
+#endif
+#ifdef TCP_KEEPINTVL
+ SSO(IPPROTO_TCP, TCP_KEEPINTVL, KEEPALIVE_INTVL);
+#endif
+#undef SSO
+}
+
static void init_conn_fd(struct tmate_ssh_client *client)
{
+ int fd;
+
if (client->has_init_conn_fd)
return;
- if (ssh_get_fd(client->session) < 0)
+ if ((fd = ssh_get_fd(client->session)) < 0)
return;
- {
- int flag = 1;
- setsockopt(ssh_get_fd(client->session), IPPROTO_TCP,
- TCP_NODELAY, &flag, sizeof(flag));
- }
-
- event_set(&client->ev_ssh, ssh_get_fd(client->session),
- EV_READ | EV_PERSIST, __on_ssh_client_event, client);
+ setup_socket(fd);
+ event_set(&client->ev_ssh, fd, EV_READ | EV_PERSIST, __on_ssh_client_event, client);
event_add(&client->ev_ssh, NULL);
client->has_init_conn_fd = true;