]> asedeno.scripts.mit.edu Git - PuTTY.git/commitdiff
Add a configuration option for TCP keepalives (SO_KEEPALIVE), default off.
authorJacob Nevins <jacobn@chiark.greenend.org.uk>
Sun, 20 Jun 2004 17:07:38 +0000 (17:07 +0000)
committerJacob Nevins <jacobn@chiark.greenend.org.uk>
Sun, 20 Jun 2004 17:07:38 +0000 (17:07 +0000)
No very good reason, but I've occasionally wanted to frob it to see if it
makes any difference to problems I'm having, and it was easy.

Tested that it does actually cause keepalives on Windows (with tcpdump);
should also work on Unix. Not implemented on Mac (does nothing), but then
neither is TCP_NODELAY.

Quite a big checkin, much of which is adding `keepalive' alongside `nodelay'
in network function calls.

[originally from svn r4309]

29 files changed:
config.c
doc/config.but
mac/macnet.c
mac/macterm.c
mac/mtcpnet.c
mac/otnet.c
network.h
plink.c
portfwd.c
pproxy.c
proxy.c
psftp.c
putty.h
raw.c
rlogin.c
scp.c
settings.c
ssh.c
telnet.c
testback.c
unix/pterm.c
unix/pty.c
unix/uxnet.c
unix/uxplink.c
unix/uxproxy.c
window.c
winhelp.h
winnet.c
x11fwd.c

index 50548eee4253e24eaac9bd6c617137f4ef9df8a7..d3d76f57e249d7a0331a58e18c6d058846950cfa 100644 (file)
--- a/config.c
+++ b/config.c
@@ -1292,6 +1292,10 @@ void setup_config_box(struct controlbox *b, struct sesslist *sesslist,
                          'n', HELPCTX(connection_nodelay),
                          dlg_stdcheckbox_handler,
                          I(offsetof(Config,tcp_nodelay)));
+           ctrl_checkbox(s, "Enable TCP keepalives (SO_KEEPALIVE option)",
+                         'p', HELPCTX(connection_tcpkeepalive),
+                         dlg_stdcheckbox_handler,
+                         I(offsetof(Config,tcp_keepalives)));
        }
 
     }
index 7572a779c33eaa826208e97e805992993d24cc21..2279db58aa348a9d6df4db853fe695bf9ded985b 100644 (file)
@@ -1,4 +1,4 @@
-\versionid $Id: config.but,v 1.83 2004/06/15 11:31:30 jacob Exp $
+\versionid $Id: config.but,v 1.84 2004/06/20 17:07:36 jacob Exp $
 
 \C{config} Configuring PuTTY
 
@@ -1506,7 +1506,8 @@ what \e{kind} of network problems you have between you and the
 server.
 
 Keepalives are only supported in Telnet and SSH; the Rlogin and Raw
-protocols offer no way of implementing them.
+protocols offer no way of implementing them. (For an alternative, see
+\k{config-tcp-keepalives}.)
 
 Note that if you are using SSH1 and the server has a bug that makes
 it unable to deal with SSH1 ignore messages (see
@@ -1525,6 +1526,34 @@ types of server.
 
 The Nagle algorithm is disabled by default.
 
+\S{config-tcp-keepalives} \q{Enable TCP keepalives}
+
+\cfg{winhelp-topic}{connection.tcpkeepalive}
+
+\e{NOTE:} TCP keepalives should not be confused with the
+application-level keepalives described in \k{config-keepalive}. If in
+doubt, you probably want application-level keepalives; TCP keepalives
+are provided for completeness.
+
+The idea of TCP keepalives is similar to application-level keepalives,
+and the same caveats apply. The main differences are:
+
+\b TCP keepalives are available on \e{all} connection types, including
+Raw and Rlogin.
+
+\b The interval between TCP keepalives is usually much longer,
+typically two hours; this is set by the operating system, and cannot
+be configured within PuTTY.
+
+\b If the operating system does not receive a response to a keepalive,
+it may send out more in quick succession and if terminate the connection
+if no response is received.
+
+TCP keepalives may be useful for ensuring that half-open connections
+are terminated than for keeping a connection alive.
+
+TCP keepalives are disabled by default.
+
 \H{config-proxy} The Proxy panel
 
 \cfg{winhelp-topic}{proxy.main}
index 106a63150cb4c2d469e7c1e0b440258516ced059..9fab15bcdd2ac5a5e303a828218d633edb86bf7d 100644 (file)
@@ -12,7 +12,7 @@ struct macnet_stack {
     void (*addrcopy)(SockAddr, char *);
     void (*addr_free)(SockAddr);
     Socket (*skregister)(void *, Plug); /* "register" is a reserved word */
-    Socket (*new)(SockAddr, int, int, int, int, Plug);
+    Socket (*new)(SockAddr, int, int, int, int, int, Plug);
     Socket (*newlistener)(char *, int, Plug, int);
     char *(*addr_error)(SockAddr);
     void (*poll)(void);
@@ -128,11 +128,12 @@ Socket sk_register(void *sock, Plug plug)
 }
 
 Socket sk_new(SockAddr addr, int port, int privport, int oobinline,
-             int nodelay, Plug plug)
+             int nodelay, int keepalive, Plug plug)
 {
 
     if (stack != NULL)
-       return stack->new(addr, port, privport, oobinline, nodelay, plug);
+       return stack->new(addr, port, privport, oobinline, nodelay, keepalive,
+                         plug);
     return NULL;
 }
 
index 88eb26680bff15d495ac4a32e7d7752e4dc4c788..7766c7b96276f99d49566c91b805ee63ba64e7bf 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: macterm.c,v 1.75 2003/05/04 14:18:18 simon Exp $ */
+/* $Id: macterm.c,v 1.76 2004/06/20 17:07:37 jacob Exp $ */
 /*
  * Copyright (c) 1999 Simon Tatham
  * Copyright (c) 1999, 2002 Ben Harris
@@ -158,7 +158,8 @@ void mac_startsession(Session *s)
     term_provide_logctx(s->term, s->logctx);
 
     errmsg = s->back->init(s, &s->backhandle, &s->cfg, s->cfg.host,
-                          s->cfg.port, &s->realhost, s->cfg.tcp_nodelay);
+                          s->cfg.port, &s->realhost, s->cfg.tcp_nodelay,
+                          s->cfg.tcp_keepalives);
     if (errmsg != NULL)
        fatalbox("%s", errmsg);
     s->back->provide_logctx(s->backhandle, s->logctx);
index a8404b7a12b1202646694daef5f40f5923d5bd9f..791557d24c3254128bc3e3076d2278460ce4aac7 100644 (file)
@@ -410,7 +410,7 @@ Socket mactcp_register(void *sock, Plug plug)
 static TCPNotifyUPP mactcp_asr_upp;
 
 Socket mactcp_new(SockAddr addr, int port, int privport, int oobinline,
-             int nodelay, Plug plug)
+             int nodelay, int keepalive, Plug plug)
 {
     static struct socket_function_table fn_table = {
        mactcp_plug,
index 7881e02ad3edf69fc740c7a37ed8ea1b8ec64cf1..35d3b16cb0c15e37395c488ed126ab9314507946 100644 (file)
@@ -234,7 +234,7 @@ Socket ot_register(void *sock, Plug plug)
 }
 
 Socket ot_new(SockAddr addr, int port, int privport, int oobinline,
-             int nodelay, Plug plug)
+             int nodelay, int keepalive, Plug plug)
 {
     static struct socket_function_table fn_table = {
        ot_tcp_plug,
@@ -281,7 +281,7 @@ Socket ot_new(SockAddr addr, int port, int privport, int oobinline,
        return (Socket) ret;
     }
 
-    /* TODO: oobinline, nodelay */
+    /* TODO: oobinline, nodelay, keepalive */
 
     /*
      * Bind to local address.
index cb077fdb1f43b45ce186f2d2f3dba7d4d0747034..45742073954c8e5f1b41911523eb82f07dbdba2f 100644 (file)
--- a/network.h
+++ b/network.h
@@ -79,8 +79,8 @@ struct plug_function_table {
  * responsibility for freeing it */
 Socket new_connection(SockAddr addr, char *hostname,
                      int port, int privport,
-                     int oobinline, int nodelay, Plug plug,
-                     const Config *cfg);
+                     int oobinline, int nodelay, int keepalive,
+                     Plug plug, const Config *cfg);
 Socket new_listener(char *srcaddr, int port, Plug plug, int local_host_only,
                    const Config *cfg);
 SockAddr name_lookup(char *host, int port, char **canonicalname,
@@ -90,8 +90,8 @@ SockAddr name_lookup(char *host, int port, char **canonicalname,
 /* (same caveat about addr as new_connection()) */
 Socket platform_new_connection(SockAddr addr, char *hostname,
                               int port, int privport,
-                              int oobinline, int nodelay, Plug plug,
-                              const Config *cfg);
+                              int oobinline, int nodelay, int keepalive,
+                              Plug plug, const Config *cfg);
 
 /* socket functions */
 
@@ -111,7 +111,7 @@ void sk_addr_free(SockAddr addr);
 /* NB, control of 'addr' is passed via sk_new, which takes responsibility
  * for freeing it, as for new_connection() */
 Socket sk_new(SockAddr addr, int port, int privport, int oobinline,
-             int nodelay, Plug p);
+             int nodelay, int keepalive, Plug p);
 
 Socket sk_newlistener(char *srcaddr, int port, Plug plug, int local_host_only);
 
diff --git a/plink.c b/plink.c
index a0a9541ab91a3743793f15ea1433b4b80a07d9fa..92769e866e78e0c63551e26517cf38258a43e407 100644 (file)
--- a/plink.c
+++ b/plink.c
@@ -564,7 +564,7 @@ int main(int argc, char **argv)
            (GetFileType(GetStdHandle(STD_INPUT_HANDLE)) == FILE_TYPE_CHAR);
 
        error = back->init(NULL, &backhandle, &cfg, cfg.host, cfg.port,
-                          &realhost, nodelay);
+                          &realhost, nodelay, cfg.tcp_keepalives);
        if (error) {
            fprintf(stderr, "Unable to open connection:\n%s", error);
            return 1;
index d9941718e5a7a2dc8f69cfdd089102d0c08c17ce..b95e5acd05aacec065489c6e35bb382f275d5cf1 100644 (file)
--- a/portfwd.c
+++ b/portfwd.c
@@ -390,7 +390,7 @@ const char *pfd_newconnect(Socket *s, char *hostname, int port,
     pr->dynamic = 0;
 
     pr->s = *s = new_connection(addr, dummy_realhost, port,
-                               0, 1, 0, (Plug) pr, cfg);
+                               0, 1, 0, 0, (Plug) pr, cfg);
     if ((err = sk_socket_error(*s)) != NULL) {
        sfree(pr);
        return err;
index 5cb90162ecbf6d1f31385d430241778a524f4bbc..9c4c2d890b01f4c7277f4e13e5cdee237fde6f72 100644 (file)
--- a/pproxy.c
+++ b/pproxy.c
@@ -10,8 +10,8 @@
 
 Socket platform_new_connection(SockAddr addr, char *hostname,
                               int port, int privport,
-                              int oobinline, int nodelay, Plug plug,
-                              const Config *cfg)
+                              int oobinline, int nodelay, int keepalive,
+                              Plug plug, const Config *cfg)
 {
     return NULL;
 }
diff --git a/proxy.c b/proxy.c
index dd5c428ce0daef4f4ef3f1fdf5cd77249788845b..d3bcca69f63a7c6733ead1e65dcb4677c0021103 100644 (file)
--- a/proxy.c
+++ b/proxy.c
@@ -356,8 +356,8 @@ SockAddr name_lookup(char *host, int port, char **canonicalname,
 
 Socket new_connection(SockAddr addr, char *hostname,
                      int port, int privport,
-                     int oobinline, int nodelay, Plug plug,
-                     const Config *cfg)
+                     int oobinline, int nodelay, int keepalive,
+                     Plug plug, const Config *cfg)
 {
     static const struct socket_function_table socket_fn_table = {
        sk_proxy_plug,
@@ -388,7 +388,8 @@ Socket new_connection(SockAddr addr, char *hostname,
        Socket sret;
 
        if ((sret = platform_new_connection(addr, hostname, port, privport,
-                                           oobinline, nodelay, plug, cfg)) !=
+                                           oobinline, nodelay, keepalive,
+                                           plug, cfg)) !=
            NULL)
            return sret;
 
@@ -444,7 +445,7 @@ Socket new_connection(SockAddr addr, char *hostname,
         */
        ret->sub_socket = sk_new(proxy_addr, cfg->proxy_port,
                                 privport, oobinline,
-                                nodelay, (Plug) pplug);
+                                nodelay, keepalive, (Plug) pplug);
        if (sk_socket_error(ret->sub_socket) != NULL)
            return (Socket) ret;
 
@@ -456,7 +457,7 @@ Socket new_connection(SockAddr addr, char *hostname,
     }
 
     /* no proxy, so just return the direct socket */
-    return sk_new(addr, port, privport, oobinline, nodelay, plug);
+    return sk_new(addr, port, privport, oobinline, nodelay, keepalive, plug);
 }
 
 Socket new_listener(char *srcaddr, int port, Plug plug, int local_host_only,
diff --git a/psftp.c b/psftp.c
index b134c503f89e7e7d0c830c809d0892c71cabb6d4..10056bd5d3cd9232814cdf66e4f1e2b17202f654 100644 (file)
--- a/psftp.c
+++ b/psftp.c
@@ -1939,7 +1939,8 @@ static int psftp_connect(char *userhost, char *user, int portnumber)
 
     back = &ssh_backend;
 
-    err = back->init(NULL, &backhandle, &cfg, cfg.host, cfg.port, &realhost,0);
+    err = back->init(NULL, &backhandle, &cfg, cfg.host, cfg.port, &realhost,
+                    0, cfg.tcp_keepalives);
     if (err != NULL) {
        fprintf(stderr, "ssh_init: %s\n", err);
        return 1;
diff --git a/putty.h b/putty.h
index 723f1e6be712071f8c841c826afb731c70bd4d77..fed589bbd9e25f99b3c612cf5fa9cf66cbf925ef 100644 (file)
--- a/putty.h
+++ b/putty.h
@@ -269,7 +269,8 @@ enum {
 struct backend_tag {
     const char *(*init) (void *frontend_handle, void **backend_handle,
                         Config *cfg,
-                        char *host, int port, char **realhost, int nodelay);
+                        char *host, int port, char **realhost, int nodelay,
+                        int keepalive);
     void (*free) (void *handle);
     /* back->reconfig() passes in a replacement configuration. */
     void (*reconfig) (void *handle, Config *cfg);
@@ -329,6 +330,7 @@ struct config_tag {
     int warn_on_close;
     int ping_interval;                /* in seconds */
     int tcp_nodelay;
+    int tcp_keepalives;
     /* Proxy options */
     char proxy_exclude_list[512];
     int proxy_dns;
diff --git a/raw.c b/raw.c
index 4c9e5becd773111afcbbe3935a4cd83d80cfafe9..8c1f97fd15e8a8f6b5a800716dbe1d23b26165b8 100644 (file)
--- a/raw.c
+++ b/raw.c
@@ -69,7 +69,8 @@ static void raw_sent(Plug plug, int bufsize)
  */
 static const char *raw_init(void *frontend_handle, void **backend_handle,
                            Config *cfg,
-                           char *host, int port, char **realhost, int nodelay)
+                           char *host, int port, char **realhost, int nodelay,
+                           int keepalive)
 {
     static const struct plug_function_table fn_table = {
        raw_closing,
@@ -115,7 +116,7 @@ static const char *raw_init(void *frontend_handle, void **backend_handle,
        logevent(raw->frontend, buf);
        sfree(buf);
     }
-    raw->s = new_connection(addr, *realhost, port, 0, 1, nodelay,
+    raw->s = new_connection(addr, *realhost, port, 0, 1, nodelay, keepalive,
                            (Plug) raw, cfg);
     if ((err = sk_socket_error(raw->s)) != NULL)
        return err;
index af3bd87633b4aeee1309f72c445bef4bfe2dc5a1..f2b61d27c578f59783f3bade55526338bcc0d94a 100644 (file)
--- a/rlogin.c
+++ b/rlogin.c
@@ -100,7 +100,7 @@ static void rlogin_sent(Plug plug, int bufsize)
 static const char *rlogin_init(void *frontend_handle, void **backend_handle,
                               Config *cfg,
                               char *host, int port, char **realhost,
-                              int nodelay)
+                              int nodelay, int keepalive)
 {
     static const struct plug_function_table fn_table = {
        rlogin_closing,
@@ -149,7 +149,7 @@ static const char *rlogin_init(void *frontend_handle, void **backend_handle,
        sfree(buf);
     }
     rlogin->s = new_connection(addr, *realhost, port, 1, 0,
-                              nodelay, (Plug) rlogin, cfg);
+                              nodelay, keepalive, (Plug) rlogin, cfg);
     if ((err = sk_socket_error(rlogin->s)) != NULL)
        return err;
 
diff --git a/scp.c b/scp.c
index 06bf089316e4471a4d17a1d325d12da65d44b275..f7fa255fc16b55128d26a3a0c7489141588ff7ac 100644 (file)
--- a/scp.c
+++ b/scp.c
@@ -450,7 +450,8 @@ static void do_cmd(char *host, char *user, char *cmd)
 
     back = &ssh_backend;
 
-    err = back->init(NULL, &backhandle, &cfg, cfg.host, cfg.port, &realhost,0);
+    err = back->init(NULL, &backhandle, &cfg, cfg.host, cfg.port, &realhost, 
+                    0, cfg.tcp_keepalives);
     if (err != NULL)
        bump("ssh_init: %s", err);
     logctx = log_init(NULL, &cfg);
index 99ec7eeb87fcdc3f7b7790b45daed51624809599..a5f2e4489c2503ee5f48c486aaf3c2d04aab1ee0 100644 (file)
@@ -182,6 +182,7 @@ void save_open_settings(void *sesskey, int do_host, Config *cfg)
     write_setting_i(sesskey, "PingInterval", cfg->ping_interval / 60); /* minutes */
     write_setting_i(sesskey, "PingIntervalSecs", cfg->ping_interval % 60);     /* seconds */
     write_setting_i(sesskey, "TCPNoDelay", cfg->tcp_nodelay);
+    write_setting_i(sesskey, "TCPKeepalives", cfg->tcp_keepalives);
     write_setting_s(sesskey, "TerminalType", cfg->termtype);
     write_setting_s(sesskey, "TerminalSpeed", cfg->termspeed);
 
@@ -411,6 +412,7 @@ void load_open_settings(void *sesskey, int do_host, Config *cfg)
        cfg->ping_interval = pingmin * 60 + pingsec;
     }
     gppi(sesskey, "TCPNoDelay", 1, &cfg->tcp_nodelay);
+    gppi(sesskey, "TCPKeepalives", 0, &cfg->tcp_keepalives);
     gpps(sesskey, "TerminalType", "xterm", cfg->termtype,
         sizeof(cfg->termtype));
     gpps(sesskey, "TerminalSpeed", "38400,38400", cfg->termspeed,
diff --git a/ssh.c b/ssh.c
index dec48ce80d620e06525489b0f0ab73084e95c0f7..6c94ba490e1d58f9e17241e5e8c5cfc8e7dd292c 100644 (file)
--- a/ssh.c
+++ b/ssh.c
@@ -2128,7 +2128,7 @@ static void ssh_sent(Plug plug, int bufsize)
  * freed by the caller.
  */
 static const char *connect_to_host(Ssh ssh, char *host, int port,
-                                  char **realhost, int nodelay)
+                                  char **realhost, int nodelay, int keepalive)
 {
     static const struct plug_function_table fn_table = {
        ssh_closing,
@@ -2169,7 +2169,7 @@ static const char *connect_to_host(Ssh ssh, char *host, int port,
     }
     ssh->fn = &fn_table;
     ssh->s = new_connection(addr, *realhost, port,
-                           0, 1, nodelay, (Plug) ssh, &ssh->cfg);
+                           0, 1, nodelay, keepalive, (Plug) ssh, &ssh->cfg);
     if ((err = sk_socket_error(ssh->s)) != NULL) {
        ssh->s = NULL;
        return err;
@@ -6183,7 +6183,8 @@ static void ssh2_protocol(Ssh ssh, unsigned char *in, int inlen, int ispkt)
  */
 static const char *ssh_init(void *frontend_handle, void **backend_handle,
                            Config *cfg,
-                           char *host, int port, char **realhost, int nodelay)
+                           char *host, int port, char **realhost, int nodelay,
+                           int keepalive)
 {
     const char *p;
     Ssh ssh;
@@ -6267,7 +6268,7 @@ static const char *ssh_init(void *frontend_handle, void **backend_handle,
 
     ssh->protocol = NULL;
 
-    p = connect_to_host(ssh, host, port, realhost, nodelay);
+    p = connect_to_host(ssh, host, port, realhost, nodelay, keepalive);
     if (p != NULL)
        return p;
 
index 2edae2191e4aec0c7aeaa68e0e5df55d47cd47b1..6f4f54ca0f2d5ad91a7e475b4dbfc6507f663a02 100644 (file)
--- a/telnet.c
+++ b/telnet.c
@@ -674,7 +674,7 @@ static void telnet_sent(Plug plug, int bufsize)
 static const char *telnet_init(void *frontend_handle, void **backend_handle,
                               Config *cfg,
                               char *host, int port, char **realhost,
-                              int nodelay)
+                              int nodelay, int keepalive)
 {
     static const struct plug_function_table fn_table = {
        telnet_closing,
@@ -729,7 +729,7 @@ static const char *telnet_init(void *frontend_handle, void **backend_handle,
        sfree(buf);
     }
     telnet->s = new_connection(addr, *realhost, port, 0, 1,
-                              nodelay, (Plug) telnet, &telnet->cfg);
+                              nodelay, keepalive, (Plug) telnet, &telnet->cfg);
     if ((err = sk_socket_error(telnet->s)) != NULL)
        return err;
 
index 22860f33736adb5aedd71081719d1666ac1f1846..bc2eb31f498d2b8a26ae3b637f4b962788076770 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: testback.c,v 1.9 2003/05/10 11:57:55 ben Exp $ */
+/* $Id: testback.c,v 1.10 2004/06/20 17:07:32 jacob Exp $ */
 /*
  * Copyright (c) 1999 Simon Tatham
  * Copyright (c) 1999 Ben Harris
@@ -34,9 +34,9 @@
 #include "putty.h"
 
 static const char *null_init(void *, void **, Config *, char *, int, char **,
-                            int);
+                            int, int);
 static const char *loop_init(void *, void **, Config *, char *, int, char **,
-                            int);
+                            int, int);
 static void null_free(void *);
 static void loop_free(void *);
 static void null_reconfig(void *, Config *);
@@ -72,14 +72,14 @@ struct loop_state {
 
 static const char *null_init(void *frontend_handle, void **backend_handle,
                             Config *cfg, char *host, int port,
-                            char **realhost, int nodelay) {
+                            char **realhost, int nodelay, int keepalive) {
 
     return NULL;
 }
 
 static const char *loop_init(void *frontend_handle, void **backend_handle,
                             Config *cfg, char *host, int port,
-                            char **realhost, int nodelay) {
+                            char **realhost, int nodelay, int keepalive) {
     struct loop_state *st = snew(struct loop_state);
 
     st->term = frontend_handle;
index 87339fb46e31881e2ba30e0a271cd62e4a9314aa..8e2554d8fe9716eba0d0fa8407c6bcc1435dd95b 100644 (file)
@@ -3367,7 +3367,8 @@ int pt_main(int argc, char **argv)
 
        error = inst->back->init((void *)inst, &inst->backhandle,
                                  &inst->cfg, inst->cfg.host, inst->cfg.port,
-                                 &realhost, inst->cfg.tcp_nodelay);
+                                 &realhost, inst->cfg.tcp_nodelay,
+                                inst->cfg.tcp_keepalives);
 
        if (error) {
            char *msg = dupprintf("Unable to open connection to %s:\n%s",
index 7f46f1aa4da06916893386dbbb5e27e6d1320c40..20ddc801e98a6b97ada39b8827f07f42713cce1e 100644 (file)
@@ -486,7 +486,8 @@ static void pty_uxsel_setup(void)
  * freed by the caller.
  */
 static const char *pty_init(void *frontend, void **backend_handle, Config *cfg,
-                           char *host, int port, char **realhost, int nodelay)
+                           char *host, int port, char **realhost, int nodelay,
+                           int keepalive)
 {
     int slavefd;
     pid_t pid, pgrp;
index 1e7d51b7cb5891d1306da35a97aac724d4f3aeee..08fb4e170ebce55906be1e6a317889c3c90c4f34 100644 (file)
@@ -378,7 +378,7 @@ Socket sk_register(OSSocket sockfd, Plug plug)
 }
 
 Socket sk_new(SockAddr addr, int port, int privport, int oobinline,
-             int nodelay, Plug plug)
+             int nodelay, int keepalive, Plug plug)
 {
     int s;
 #ifdef IPV6
@@ -433,6 +433,11 @@ Socket sk_new(SockAddr addr, int port, int privport, int oobinline,
        setsockopt(s, IPPROTO_TCP, TCP_NODELAY, (void *) &b, sizeof(b));
     }
 
+    if (keepalive) {
+       int b = TRUE;
+       setsockopt(s, SOL_SOCKET, SO_KEEPALIVE, (void *) &b, sizeof(b));
+    }
+
     /*
      * Bind to local address.
      */
index e59a701bbae189df1b885e7460966e316f719b58..6bf2c85828e76dcf0046af682fd55201108ba27c 100644 (file)
@@ -557,7 +557,7 @@ int main(int argc, char **argv)
        int nodelay = cfg.tcp_nodelay && isatty(0);
 
        error = back->init(NULL, &backhandle, &cfg, cfg.host, cfg.port,
-                          &realhost, nodelay);
+                          &realhost, nodelay, cfg.tcp_keepalives);
        if (error) {
            fprintf(stderr, "Unable to open connection:\n%s\n", error);
            return 1;
index b3f75e813fabfa09fd6ff5bad6a2f984c20d6d88..1191a61ab632f7d952c3e389e7577f058433d998 100644 (file)
@@ -221,8 +221,8 @@ static int localproxy_select_result(int fd, int event)
 
 Socket platform_new_connection(SockAddr addr, char *hostname,
                               int port, int privport,
-                              int oobinline, int nodelay, Plug plug,
-                              const Config *cfg)
+                              int oobinline, int nodelay, int keepalive,
+                              Plug plug, const Config *cfg)
 {
     char *cmd;
 
index 71f30b4d45acb3b682bfc28ab4f0c7940af45d46..e720ed3c3a6b2adc6312412901e3ceadd4958bc3 100644 (file)
--- a/window.c
+++ b/window.c
@@ -611,7 +611,8 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show)
        char *realhost;
 
        error = back->init(NULL, &backhandle, &cfg,
-                          cfg.host, cfg.port, &realhost, cfg.tcp_nodelay);
+                          cfg.host, cfg.port, &realhost, cfg.tcp_nodelay,
+                          cfg.tcp_keepalives);
        back->provide_logctx(backhandle, logctx);
        if (error) {
            char *str = dupprintf("%s Error", appname);
index bbde922b4abf3243fccd62417df55e09180c4220..5271f9243d4a717e4403067dc92ba8dbb962dea7 100644 (file)
--- a/winhelp.h
+++ b/winhelp.h
@@ -63,6 +63,7 @@
 #define WINHELP_CTX_connection_username "connection.username"
 #define WINHELP_CTX_connection_keepalive "connection.keepalive"
 #define WINHELP_CTX_connection_nodelay "connection.nodelay"
+#define WINHELP_CTX_connection_tcpkeepalive "connection.tcpkeepalive"
 #define WINHELP_CTX_proxy_type "proxy.type"
 #define WINHELP_CTX_proxy_main "proxy.main"
 #define WINHELP_CTX_proxy_exclude "proxy.exclude"
index 21a2f29345a0ccdf130edb965be335fcd18cacf0..bcb22bf4bfe306d8948850542b0f849410290381 100644 (file)
--- a/winnet.c
+++ b/winnet.c
@@ -658,7 +658,7 @@ Socket sk_register(void *sock, Plug plug)
 }
 
 Socket sk_new(SockAddr addr, int port, int privport, int oobinline,
-             int nodelay, Plug plug)
+             int nodelay, int keepalive, Plug plug)
 {
     static const struct socket_function_table fn_table = {
        sk_tcp_plug,
@@ -722,6 +722,11 @@ Socket sk_new(SockAddr addr, int port, int privport, int oobinline,
        p_setsockopt(s, IPPROTO_TCP, TCP_NODELAY, (void *) &b, sizeof(b));
     }
 
+    if (keepalive) {
+       BOOL b = TRUE;
+       p_setsockopt(s, SOL_SOCKET, SO_KEEPALIVE, (void *) &b, sizeof(b));
+    }
+
     /*
      * Bind to local address.
      */
index 049381b4bacad60f4f149266e02f86c10175e046..b0b826981d7975d0c220b067803e2e73c2e00514 100644 (file)
--- a/x11fwd.c
+++ b/x11fwd.c
@@ -310,7 +310,7 @@ const char *x11_init(Socket * s, char *display, void *c, void *auth,
     pr->c = c;
 
     pr->s = *s = new_connection(addr, dummy_realhost, port,
-                               0, 1, 0, (Plug) pr, cfg);
+                               0, 1, 0, 0, (Plug) pr, cfg);
     if ((err = sk_socket_error(*s)) != NULL) {
        sfree(pr);
        return err;