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:
parent
43a4339ac5
commit
3270c74f9e
@ -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);
|
||||||
|
|
||||||
|
5
plink.c
5
plink.c
@ -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;
|
||||||
|
@ -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;
|
||||||
|
2
psftp.c
2
psftp.c
@ -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;
|
||||||
|
3
putty.h
3
putty.h
@ -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
4
raw.c
@ -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;
|
||||||
|
|
||||||
|
4
rlogin.c
4
rlogin.c
@ -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
2
scp.c
@ -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();
|
||||||
|
@ -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
8
ssh.c
@ -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;
|
||||||
|
|
||||||
|
4
telnet.c
4
telnet.c
@ -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;
|
||||||
|
|
||||||
|
18
windlg.c
18
windlg.c
@ -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 ||
|
||||||
|
2
window.c
2
window.c
@ -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);
|
||||||
|
7
winnet.c
7
winnet.c
@ -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.
|
||||||
*/
|
*/
|
||||||
|
2
x11fwd.c
2
x11fwd.c
@ -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;
|
||||||
|
Loading…
Reference in New Issue
Block a user