From 79bf227ba7ba02e32ac710621b672e2789f9ef50 Mon Sep 17 00:00:00 2001 From: jacob Date: Sun, 20 Jun 2004 17:07:38 +0000 Subject: [PATCH] Add a configuration option for TCP keepalives (SO_KEEPALIVE), default off. 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. git-svn-id: svn://svn.tartarus.org/sgt/putty@4309 cda61777-01e9-0310-a592-d414129be87e --- config.c | 4 ++++ doc/config.but | 33 +++++++++++++++++++++++++++++++-- mac/macnet.c | 7 ++++--- mac/macterm.c | 5 +++-- mac/mtcpnet.c | 2 +- mac/otnet.c | 4 ++-- network.h | 10 +++++----- plink.c | 2 +- portfwd.c | 2 +- pproxy.c | 4 ++-- proxy.c | 11 ++++++----- psftp.c | 3 ++- putty.h | 4 +++- raw.c | 5 +++-- rlogin.c | 4 ++-- scp.c | 3 ++- settings.c | 2 ++ ssh.c | 9 +++++---- telnet.c | 4 ++-- testback.c | 10 +++++----- unix/pterm.c | 3 ++- unix/pty.c | 3 ++- unix/uxnet.c | 7 ++++++- unix/uxplink.c | 2 +- unix/uxproxy.c | 4 ++-- window.c | 3 ++- winhelp.h | 1 + winnet.c | 7 ++++++- x11fwd.c | 2 +- 29 files changed, 109 insertions(+), 51 deletions(-) diff --git a/config.c b/config.c index 50548eee..d3d76f57 100644 --- 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))); } } diff --git a/doc/config.but b/doc/config.but index 7572a779..2279db58 100644 --- a/doc/config.but +++ b/doc/config.but @@ -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} diff --git a/mac/macnet.c b/mac/macnet.c index 106a6315..9fab15bc 100644 --- a/mac/macnet.c +++ b/mac/macnet.c @@ -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; } diff --git a/mac/macterm.c b/mac/macterm.c index 88eb2668..7766c7b9 100644 --- a/mac/macterm.c +++ b/mac/macterm.c @@ -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); diff --git a/mac/mtcpnet.c b/mac/mtcpnet.c index a8404b7a..791557d2 100644 --- a/mac/mtcpnet.c +++ b/mac/mtcpnet.c @@ -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, diff --git a/mac/otnet.c b/mac/otnet.c index 7881e02a..35d3b16c 100644 --- a/mac/otnet.c +++ b/mac/otnet.c @@ -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. diff --git a/network.h b/network.h index cb077fdb..45742073 100644 --- 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 a0a9541a..92769e86 100644 --- 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; diff --git a/portfwd.c b/portfwd.c index d9941718..b95e5acd 100644 --- 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; diff --git a/pproxy.c b/pproxy.c index 5cb90162..9c4c2d89 100644 --- 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 dd5c428c..d3bcca69 100644 --- 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 b134c503..10056bd5 100644 --- 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 723f1e6b..fed589bb 100644 --- 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 4c9e5bec..8c1f97fd 100644 --- 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; diff --git a/rlogin.c b/rlogin.c index af3bd876..f2b61d27 100644 --- 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 06bf0893..f7fa255f 100644 --- 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); diff --git a/settings.c b/settings.c index 99ec7eeb..a5f2e448 100644 --- a/settings.c +++ b/settings.c @@ -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 dec48ce8..6c94ba49 100644 --- 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; diff --git a/telnet.c b/telnet.c index 2edae219..6f4f54ca 100644 --- 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; diff --git a/testback.c b/testback.c index 22860f33..bc2eb31f 100644 --- a/testback.c +++ b/testback.c @@ -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; diff --git a/unix/pterm.c b/unix/pterm.c index 87339fb4..8e2554d8 100644 --- a/unix/pterm.c +++ b/unix/pterm.c @@ -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", diff --git a/unix/pty.c b/unix/pty.c index 7f46f1aa..20ddc801 100644 --- a/unix/pty.c +++ b/unix/pty.c @@ -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; diff --git a/unix/uxnet.c b/unix/uxnet.c index 1e7d51b7..08fb4e17 100644 --- a/unix/uxnet.c +++ b/unix/uxnet.c @@ -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. */ diff --git a/unix/uxplink.c b/unix/uxplink.c index e59a701b..6bf2c858 100644 --- a/unix/uxplink.c +++ b/unix/uxplink.c @@ -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; diff --git a/unix/uxproxy.c b/unix/uxproxy.c index b3f75e81..1191a61a 100644 --- a/unix/uxproxy.c +++ b/unix/uxproxy.c @@ -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; diff --git a/window.c b/window.c index 71f30b4d..e720ed3c 100644 --- 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); diff --git a/winhelp.h b/winhelp.h index bbde922b..5271f924 100644 --- 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" diff --git a/winnet.c b/winnet.c index 21a2f293..bcb22bf4 100644 --- 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. */ diff --git a/x11fwd.c b/x11fwd.c index 049381b4..b0b82698 100644 --- 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; -- 2.11.0