1
0
mirror of https://git.tartarus.org/simon/putty.git synced 2025-01-25 01:02:24 +00:00

Configurable TCP_NODELAY option on network connections

[originally from svn r1428]
This commit is contained in:
Simon Tatham 2001-11-29 21:47:11 +00:00
parent 43a4339ac5
commit 3270c74f9e
15 changed files with 47 additions and 20 deletions

View File

@ -68,7 +68,7 @@ void sk_getaddr(SockAddr addr, char *buf, int buflen);
void sk_addr_free(SockAddr addr); void sk_addr_free(SockAddr addr);
Socket sk_new(SockAddr addr, int port, int privport, int oobinline, Socket sk_new(SockAddr addr, int port, int privport, int oobinline,
Plug p); int nodelay, Plug p);
Socket sk_newlistener(int port, Plug plug, int local_host_only); Socket sk_newlistener(int port, Plug plug, int local_host_only);

View File

@ -735,8 +735,11 @@ int main(int argc, char **argv)
{ {
char *error; char *error;
char *realhost; char *realhost;
/* nodelay is only useful if stdin is a character device (console) */
int nodelay = cfg.tcp_nodelay &&
(GetFileType(GetStdHandle(STD_INPUT_HANDLE)) == FILE_TYPE_CHAR);
error = back->init(cfg.host, cfg.port, &realhost); error = back->init(cfg.host, cfg.port, &realhost, nodelay);
if (error) { if (error) {
fprintf(stderr, "Unable to open connection:\n%s", error); fprintf(stderr, "Unable to open connection:\n%s", error);
return 1; return 1;

View File

@ -138,7 +138,7 @@ char *pfd_newconnect(Socket *s, char *hostname, int port, void *c)
pr->ready = 1; pr->ready = 1;
pr->c = c; pr->c = c;
pr->s = *s = sk_new(addr, port, 0, 1, (Plug) pr); pr->s = *s = sk_new(addr, port, 0, 1, 0, (Plug) pr);
if ((err = sk_socket_error(*s))) { if ((err = sk_socket_error(*s))) {
sfree(pr); sfree(pr);
return err; return err;

View File

@ -1820,7 +1820,7 @@ int main(int argc, char *argv[])
back = &ssh_backend; back = &ssh_backend;
err = back->init(cfg.host, cfg.port, &realhost); err = back->init(cfg.host, cfg.port, &realhost, 0);
if (err != NULL) { if (err != NULL) {
fprintf(stderr, "ssh_init: %s", err); fprintf(stderr, "ssh_init: %s", err);
return 1; return 1;

View File

@ -202,7 +202,7 @@ enum {
}; };
typedef struct { typedef struct {
char *(*init) (char *host, int port, char **realhost); char *(*init) (char *host, int port, char **realhost, int nodelay);
/* back->send() returns the current amount of buffered data. */ /* back->send() returns the current amount of buffered data. */
int (*send) (char *buf, int len); int (*send) (char *buf, int len);
/* back->sendbuffer() does the same thing but without attempting a send */ /* back->sendbuffer() does the same thing but without attempting a send */
@ -236,6 +236,7 @@ typedef struct {
int close_on_exit; int close_on_exit;
int warn_on_close; int warn_on_close;
int ping_interval; /* in seconds */ int ping_interval; /* in seconds */
int tcp_nodelay;
/* SSH options */ /* SSH options */
char remote_cmd[512]; char remote_cmd[512];
char remote_cmd2[512]; /* fallback if the first fails char remote_cmd2[512]; /* fallback if the first fails

4
raw.c
View File

@ -57,7 +57,7 @@ static void raw_sent(Plug plug, int bufsize)
* Also places the canonical host name into `realhost'. It must be * Also places the canonical host name into `realhost'. It must be
* freed by the caller. * freed by the caller.
*/ */
static char *raw_init(char *host, int port, char **realhost) static char *raw_init(char *host, int port, char **realhost, int nodelay)
{ {
static struct plug_function_table fn_table = { static struct plug_function_table fn_table = {
raw_closing, raw_closing,
@ -92,7 +92,7 @@ static char *raw_init(char *host, int port, char **realhost)
sprintf(buf, "Connecting to %.100s port %d", addrbuf, port); sprintf(buf, "Connecting to %.100s port %d", addrbuf, port);
logevent(buf); logevent(buf);
} }
s = sk_new(addr, port, 0, 1, &fn_table_ptr); s = sk_new(addr, port, 0, 1, nodelay, &fn_table_ptr);
if ((err = sk_socket_error(s))) if ((err = sk_socket_error(s)))
return err; return err;

View File

@ -86,7 +86,7 @@ static void rlogin_sent(Plug plug, int bufsize)
* Also places the canonical host name into `realhost'. It must be * Also places the canonical host name into `realhost'. It must be
* freed by the caller. * freed by the caller.
*/ */
static char *rlogin_init(char *host, int port, char **realhost) static char *rlogin_init(char *host, int port, char **realhost, int nodelay)
{ {
static struct plug_function_table fn_table = { static struct plug_function_table fn_table = {
rlogin_closing, rlogin_closing,
@ -121,7 +121,7 @@ static char *rlogin_init(char *host, int port, char **realhost)
sprintf(buf, "Connecting to %.100s port %d", addrbuf, port); sprintf(buf, "Connecting to %.100s port %d", addrbuf, port);
logevent(buf); logevent(buf);
} }
s = sk_new(addr, port, 1, 0, &fn_table_ptr); s = sk_new(addr, port, 1, 0, nodelay, &fn_table_ptr);
if ((err = sk_socket_error(s))) if ((err = sk_socket_error(s)))
return err; return err;

2
scp.c
View File

@ -689,7 +689,7 @@ static void do_cmd(char *host, char *user, char *cmd)
back = &ssh_backend; back = &ssh_backend;
err = back->init(cfg.host, cfg.port, &realhost); err = back->init(cfg.host, cfg.port, &realhost, 0);
if (err != NULL) if (err != NULL)
bump("ssh_init: %s", err); bump("ssh_init: %s", err);
ssh_scp_init(); ssh_scp_init();

View File

@ -145,6 +145,7 @@ void save_settings(char *section, int do_host, Config * cfg)
write_setting_i(sesskey, "WarnOnClose", !!cfg->warn_on_close); write_setting_i(sesskey, "WarnOnClose", !!cfg->warn_on_close);
write_setting_i(sesskey, "PingInterval", cfg->ping_interval / 60); /* minutes */ write_setting_i(sesskey, "PingInterval", cfg->ping_interval / 60); /* minutes */
write_setting_i(sesskey, "PingIntervalSecs", cfg->ping_interval % 60); /* seconds */ write_setting_i(sesskey, "PingIntervalSecs", cfg->ping_interval % 60); /* seconds */
write_setting_i(sesskey, "TCPNoDelay", cfg->tcp_nodelay);
write_setting_s(sesskey, "TerminalType", cfg->termtype); write_setting_s(sesskey, "TerminalType", cfg->termtype);
write_setting_s(sesskey, "TerminalSpeed", cfg->termspeed); write_setting_s(sesskey, "TerminalSpeed", cfg->termspeed);
{ {
@ -326,6 +327,7 @@ void load_settings(char *section, int do_host, Config * cfg)
gppi(sesskey, "PingIntervalSecs", 0, &pingsec); gppi(sesskey, "PingIntervalSecs", 0, &pingsec);
cfg->ping_interval = pingmin * 60 + pingsec; cfg->ping_interval = pingmin * 60 + pingsec;
} }
gppi(sesskey, "TCPNoDelay", 1, &cfg->tcp_nodelay);
gpps(sesskey, "TerminalType", "xterm", cfg->termtype, gpps(sesskey, "TerminalType", "xterm", cfg->termtype,
sizeof(cfg->termtype)); sizeof(cfg->termtype));
gpps(sesskey, "TerminalSpeed", "38400,38400", cfg->termspeed, gpps(sesskey, "TerminalSpeed", "38400,38400", cfg->termspeed,

8
ssh.c
View File

@ -1657,7 +1657,7 @@ static void ssh_sent(Plug plug, int bufsize)
* Also places the canonical host name into `realhost'. It must be * Also places the canonical host name into `realhost'. It must be
* freed by the caller. * freed by the caller.
*/ */
static char *connect_to_host(char *host, int port, char **realhost) static char *connect_to_host(char *host, int port, char **realhost, int nodelay)
{ {
static struct plug_function_table fn_table = { static struct plug_function_table fn_table = {
ssh_closing, ssh_closing,
@ -1714,7 +1714,7 @@ static char *connect_to_host(char *host, int port, char **realhost)
sprintf(buf, "Connecting to %.100s port %d", addrbuf, port); sprintf(buf, "Connecting to %.100s port %d", addrbuf, port);
logevent(buf); logevent(buf);
} }
s = sk_new(addr, port, 0, 1, &fn_table_ptr); s = sk_new(addr, port, 0, 1, nodelay, &fn_table_ptr);
if ((err = sk_socket_error(s))) if ((err = sk_socket_error(s)))
return err; return err;
@ -5109,7 +5109,7 @@ static void ssh2_protocol(unsigned char *in, int inlen, int ispkt)
* *
* Returns an error message, or NULL on success. * Returns an error message, or NULL on success.
*/ */
static char *ssh_init(char *host, int port, char **realhost) static char *ssh_init(char *host, int port, char **realhost, int nodelay)
{ {
char *p; char *p;
@ -5125,7 +5125,7 @@ static char *ssh_init(char *host, int port, char **realhost)
ssh_overall_bufsize = 0; ssh_overall_bufsize = 0;
ssh_fallback_cmd = 0; ssh_fallback_cmd = 0;
p = connect_to_host(host, port, realhost); p = connect_to_host(host, port, realhost, nodelay);
if (p != NULL) if (p != NULL)
return p; return p;

View File

@ -601,7 +601,7 @@ static void telnet_sent(Plug plug, int bufsize)
* Also places the canonical host name into `realhost'. It must be * Also places the canonical host name into `realhost'. It must be
* freed by the caller. * freed by the caller.
*/ */
static char *telnet_init(char *host, int port, char **realhost) static char *telnet_init(char *host, int port, char **realhost, int nodelay)
{ {
static struct plug_function_table fn_table = { static struct plug_function_table fn_table = {
telnet_closing, telnet_closing,
@ -636,7 +636,7 @@ static char *telnet_init(char *host, int port, char **realhost)
sprintf(buf, "Connecting to %.100s port %d", addrbuf, port); sprintf(buf, "Connecting to %.100s port %d", addrbuf, port);
logevent(buf); logevent(buf);
} }
s = sk_new(addr, port, 0, 1, &fn_table_ptr); s = sk_new(addr, port, 0, 1, nodelay, &fn_table_ptr);
if ((err = sk_socket_error(s))) if ((err = sk_socket_error(s)))
return err; return err;

View File

@ -405,12 +405,14 @@ enum { IDCX_ABOUT =
IDC_TITLE_CONNECTION, IDC_TITLE_CONNECTION,
IDC_BOX_CONNECTION1, IDC_BOX_CONNECTION1,
IDC_BOX_CONNECTION2, IDC_BOX_CONNECTION2,
IDC_BOX_CONNECTION3,
IDC_TTSTATIC, IDC_TTSTATIC,
IDC_TTEDIT, IDC_TTEDIT,
IDC_LOGSTATIC, IDC_LOGSTATIC,
IDC_LOGEDIT, IDC_LOGEDIT,
IDC_PINGSTATIC, IDC_PINGSTATIC,
IDC_PINGEDIT, IDC_PINGEDIT,
IDC_NODELAY,
connectionpanelend, connectionpanelend,
telnetpanelstart, telnetpanelstart,
@ -612,6 +614,7 @@ static void init_dlg_ctrls(HWND hwnd, int keepsess)
cfg.protocol == cfg.protocol ==
PROT_RLOGIN ? IDC_PROTRLOGIN : IDC_PROTRAW); PROT_RLOGIN ? IDC_PROTRLOGIN : IDC_PROTRAW);
SetDlgItemInt(hwnd, IDC_PINGEDIT, cfg.ping_interval, FALSE); SetDlgItemInt(hwnd, IDC_PINGEDIT, cfg.ping_interval, FALSE);
CheckDlgButton(hwnd, IDC_NODELAY, cfg.tcp_nodelay);
CheckRadioButton(hwnd, IDC_DEL008, IDC_DEL127, CheckRadioButton(hwnd, IDC_DEL008, IDC_DEL127,
cfg.bksp_is_delete ? IDC_DEL127 : IDC_DEL008); cfg.bksp_is_delete ? IDC_DEL127 : IDC_DEL008);
@ -1224,7 +1227,7 @@ static void create_controls(HWND hwnd, int dlgtype, int panel)
} }
if (panel == connectionpanelstart) { if (panel == connectionpanelstart) {
/* The Connection panel. Accelerators used: [acgo] tuk */ /* The Connection panel. Accelerators used: [acgo] tukn */
struct ctlpos cp; struct ctlpos cp;
ctlposinit(&cp, hwnd, 80, 3, 13); ctlposinit(&cp, hwnd, 80, 3, 13);
bartitle(&cp, "Options controlling the connection", bartitle(&cp, "Options controlling the connection",
@ -1248,6 +1251,13 @@ static void create_controls(HWND hwnd, int dlgtype, int panel)
staticedit(&cp, "Seconds between &keepalives (0 to turn off)", staticedit(&cp, "Seconds between &keepalives (0 to turn off)",
IDC_PINGSTATIC, IDC_PINGEDIT, 20); IDC_PINGSTATIC, IDC_PINGEDIT, 20);
endbox(&cp); endbox(&cp);
if (dlgtype == 0) {
beginbox(&cp, "Low-level TCP connection options",
IDC_BOX_CONNECTION3);
checkbox(&cp, "Disable &Nagle's algorithm (TCP_NODELAY option)",
IDC_NODELAY);
endbox(&cp);
}
} }
if (panel == telnetpanelstart) { if (panel == telnetpanelstart) {
@ -1777,6 +1787,12 @@ static int GenericMainDlgProc(HWND hwnd, UINT msg,
MyGetDlgItemInt(hwnd, IDC_PINGEDIT, MyGetDlgItemInt(hwnd, IDC_PINGEDIT,
&cfg.ping_interval); &cfg.ping_interval);
break; break;
case IDC_NODELAY:
if (HIWORD(wParam) == BN_CLICKED ||
HIWORD(wParam) == BN_DOUBLECLICKED)
cfg.tcp_nodelay =
IsDlgButtonChecked(hwnd, IDC_NODELAY);
break;
case IDC_DEL008: case IDC_DEL008:
case IDC_DEL127: case IDC_DEL127:
if (HIWORD(wParam) == BN_CLICKED || if (HIWORD(wParam) == BN_CLICKED ||

View File

@ -508,7 +508,7 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show)
char msg[1024], *title; char msg[1024], *title;
char *realhost; char *realhost;
error = back->init(cfg.host, cfg.port, &realhost); error = back->init(cfg.host, cfg.port, &realhost, cfg.tcp_nodelay);
if (error) { if (error) {
sprintf(msg, "Unable to open connection to\n" sprintf(msg, "Unable to open connection to\n"
"%.800s\n" "%s", cfg.host, error); "%.800s\n" "%s", cfg.host, error);

View File

@ -439,7 +439,7 @@ Socket sk_register(void *sock, Plug plug)
} }
Socket sk_new(SockAddr addr, int port, int privport, int oobinline, Socket sk_new(SockAddr addr, int port, int privport, int oobinline,
Plug plug) int nodelay, Plug plug)
{ {
static struct socket_function_table fn_table = { static struct socket_function_table fn_table = {
sk_tcp_plug, sk_tcp_plug,
@ -494,6 +494,11 @@ Socket sk_new(SockAddr addr, int port, int privport, int oobinline,
setsockopt(s, SOL_SOCKET, SO_OOBINLINE, (void *) &b, sizeof(b)); setsockopt(s, SOL_SOCKET, SO_OOBINLINE, (void *) &b, sizeof(b));
} }
if (nodelay) {
BOOL b = TRUE;
setsockopt(s, IPPROTO_TCP, TCP_NODELAY, (void *) &b, sizeof(b));
}
/* /*
* Bind to local address. * Bind to local address.
*/ */

View File

@ -195,7 +195,7 @@ char *x11_init(Socket * s, char *display, void *c)
pr->throttled = pr->throttle_override = 0; pr->throttled = pr->throttle_override = 0;
pr->c = c; pr->c = c;
pr->s = *s = sk_new(addr, port, 0, 1, (Plug) pr); pr->s = *s = sk_new(addr, port, 0, 1, 0, (Plug) pr);
if ((err = sk_socket_error(*s))) { if ((err = sk_socket_error(*s))) {
sfree(pr); sfree(pr);
return err; return err;