summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authornorrarvid <norrarvid@gmail.com>2012-06-04 10:11:11 +0200
committernorrarvid <norrarvid@gmail.com>2012-06-04 10:11:11 +0200
commite5fb05e9cba476ec67f71fee1d79ddd5cdd12f2c (patch)
tree0363a78110ffbc2ac01d35d722459fd3aff60dbf
parent60b052965634be151d88f7011149d0edc71f23d8 (diff)
downloadxrdp-proprietary-e5fb05e9cba476ec67f71fee1d79ddd5cdd12f2c.tar.gz
xrdp-proprietary-e5fb05e9cba476ec67f71fee1d79ddd5cdd12f2c.zip
Support for TCP keepalive and TCP no_delay added
-rw-r--r--common/os_calls.c52
-rw-r--r--common/os_calls.h2
-rw-r--r--xrdp/xrdp.ini6
-rw-r--r--xrdp/xrdp_listen.c43
4 files changed, 100 insertions, 3 deletions
diff --git a/common/os_calls.c b/common/os_calls.c
index 211adc82..a0a8304c 100644
--- a/common/os_calls.c
+++ b/common/os_calls.c
@@ -321,9 +321,11 @@ g_getchar(void)
}
/*****************************************************************************/
+/*Returns 0 on success*/
int APP_CC
g_tcp_set_no_delay(int sck)
{
+ int ret = 1 ; /*error*/
#if defined(_WIN32)
int option_value;
int option_len;
@@ -341,11 +343,55 @@ g_tcp_set_no_delay(int sck)
{
option_value = 1;
option_len = sizeof(option_value);
- setsockopt(sck, IPPROTO_TCP, TCP_NODELAY, (char*)&option_value,
- option_len);
+ if(setsockopt(sck, IPPROTO_TCP, TCP_NODELAY, (char*)&option_value,
+ option_len)==0)
+ {
+ ret = 0 ; /* success */
+ }
}
}
- return 0;
+ else
+ {
+ g_writeln("Error getting tcp_nodelay");
+ }
+ return ret;
+}
+
+/*****************************************************************************/
+/*Returns 0 on success*/
+int APP_CC
+g_tcp_set_keepalive(int sck)
+{
+ int ret = 1 ; /*error*/
+#if defined(_WIN32)
+ int option_value;
+ int option_len;
+#else
+ int option_value;
+ unsigned int option_len;
+#endif
+
+ option_len = sizeof(option_value);
+ /* SOL_TCP IPPROTO_TCP */
+ if (getsockopt(sck, SOL_SOCKET, SO_KEEPALIVE, (char*)&option_value,
+ &option_len) == 0)
+ {
+ if (option_value == 0)
+ {
+ option_value = 1;
+ option_len = sizeof(option_value);
+ if(setsockopt(sck, SOL_SOCKET, SO_KEEPALIVE, (char*)&option_value,
+ option_len)==0)
+ {
+ ret = 0 ; /* success */
+ }
+ }
+ }
+ else
+ {
+ g_writeln("Error getting tcp_keepalive");
+ }
+ return ret;
}
/*****************************************************************************/
diff --git a/common/os_calls.h b/common/os_calls.h
index ddcb59d8..e23550fc 100644
--- a/common/os_calls.h
+++ b/common/os_calls.h
@@ -64,6 +64,8 @@ g_getchar(void);
int APP_CC
g_tcp_set_no_delay(int sck);
int APP_CC
+g_tcp_set_keepalive(int sck);
+int APP_CC
g_tcp_socket(void);
int APP_CC
g_tcp_local_socket(void);
diff --git a/xrdp/xrdp.ini b/xrdp/xrdp.ini
index af5f2650..be59be45 100644
--- a/xrdp/xrdp.ini
+++ b/xrdp/xrdp.ini
@@ -7,6 +7,12 @@ crypt_level=low
channel_code=1
max_bpp=24
fork=yes
+# regulate if the listening socket use socket option tcp_nodelay
+# no buffering will be performed in the TCP stack
+tcp_nodelay=yes
+# regulate if the listening socket use socket option keepalive
+# if the network connection disappear without close messages the connection will be closed
+tcp_keepalive=yes
#black=000000
#grey=d6d3ce
#dark_grey=808080
diff --git a/xrdp/xrdp_listen.c b/xrdp/xrdp_listen.c
index bbdd729a..d3529ce5 100644
--- a/xrdp/xrdp_listen.c
+++ b/xrdp/xrdp_listen.c
@@ -130,6 +130,7 @@ xrdp_process_run(void* in_val)
static int
xrdp_listen_get_port_address(char* port, int port_bytes,
char* address, int address_bytes,
+ int *tcp_nodelay, int *tcp_keepalive,
struct xrdp_startup_params* startup_param)
{
int fd;
@@ -147,6 +148,8 @@ xrdp_listen_get_port_address(char* port, int port_bytes,
/* see if port or address is in xrdp.ini file */
g_snprintf(cfg_file, 255, "%s/xrdp.ini", XRDP_CFG_PATH);
fd = g_file_open(cfg_file);
+ *tcp_nodelay = 0 ;
+ *tcp_keepalive = 0 ;
if (fd > 0)
{
names = list_create();
@@ -185,6 +188,28 @@ xrdp_listen_get_port_address(char* port, int port_bytes,
startup_param->fork = 1;
}
}
+ if (g_strcasecmp(val, "tcp_nodelay") == 0)
+ {
+ val = (char*)list_get_item(values, index);
+ if ((g_strcasecmp(val, "yes") == 0) ||
+ (g_strcasecmp(val, "on") == 0) ||
+ (g_strcasecmp(val, "true") == 0) ||
+ (g_atoi(val) != 0))
+ {
+ *tcp_nodelay = 1 ;
+ }
+ }
+ if (g_strcasecmp(val, "tcp_keepalive") == 0)
+ {
+ val = (char*)list_get_item(values, index);
+ if ((g_strcasecmp(val, "yes") == 0) ||
+ (g_strcasecmp(val, "on") == 0) ||
+ (g_strcasecmp(val, "true") == 0) ||
+ (g_atoi(val) != 0))
+ {
+ *tcp_keepalive = 1 ;
+ }
+ }
}
}
}
@@ -280,19 +305,37 @@ xrdp_listen_main_loop(struct xrdp_listen* self)
tbus sync_obj;
tbus sck_obj;
tbus done_obj;
+ int tcp_nodelay;
+ int tcp_keepalive;
self->status = 1;
if (xrdp_listen_get_port_address(port, sizeof(port),
address, sizeof(address),
+ &tcp_nodelay, &tcp_keepalive,
self->startup_params) != 0)
{
g_writeln("xrdp_listen_main_loop: xrdp_listen_get_port failed");
self->status = -1;
return 1;
}
+ /*Create socket*/
error = trans_listen_address(self->listen_trans, port, address);
if (error == 0)
{
+ if(tcp_nodelay)
+ {
+ if(g_tcp_set_no_delay(self->listen_trans->sck))
+ {
+ g_writeln("Error setting tcp_nodelay");
+ }
+ }
+ if(tcp_keepalive)
+ {
+ if(g_tcp_set_keepalive(self->listen_trans->sck))
+ {
+ g_writeln("Error setting tcp_keepalive");
+ }
+ }
self->listen_trans->trans_conn_in = xrdp_listen_conn_in;
self->listen_trans->callback_data = self;
term_obj = g_get_term_event();