xrdp: work on trans list

This commit is contained in:
Jay Sorg 2018-05-17 23:12:47 -07:00
parent bacd76f9a2
commit d6229df5a1
3 changed files with 257 additions and 280 deletions

View File

@ -4,8 +4,18 @@ ini_version=1
; fork a new process for each incoming connection ; fork a new process for each incoming connection
fork=true fork=true
; tcp port to listen
; ports to listen on, examples
;unix://./tmp/xrdp.socket
;tcp://.:3389/ (<- Localhost 127.0.0.1:3389)
;tcp://:3389/ (<- *:3389)
;tcp://<any ipv4 format addr>:3389) (<- 192.168.1.1:3389)
;tcp6://.:3389/
;tcp6://:3389/
;tcp6://<any ipv6 format>:3389/
;vsock://<cid>:<port>/
port=3389 port=3389
; 'port' above should be connected to with vsock instead of tcp ; 'port' above should be connected to with vsock instead of tcp
use_vsock=false use_vsock=false
; regulate if the listening socket use socket option tcp_nodelay ; regulate if the listening socket use socket option tcp_nodelay

View File

@ -30,6 +30,9 @@
static tbus g_process_sem = 0; static tbus g_process_sem = 0;
static struct xrdp_process *g_process = 0; static struct xrdp_process *g_process = 0;
int
xrdp_listen_conn_in(struct trans *self, struct trans *new_self);
/*****************************************************************************/ /*****************************************************************************/
static int static int
xrdp_listen_create_pro_done(struct xrdp_listen *self) xrdp_listen_create_pro_done(struct xrdp_listen *self)
@ -150,104 +153,65 @@ xrdp_process_run(void *in_val)
/*****************************************************************************/ /*****************************************************************************/
static int static int
xrdp_listen_get_port_address(char *port, int port_bytes, xrdp_listen_get_startup_params(struct xrdp_listen *self)
char *address, int address_bytes,
int *tcp_nodelay, int *tcp_keepalive,
int *mode,
struct xrdp_startup_params *startup_param)
{ {
int fd; int fd;
int error;
int index; int index;
char *val; char *val;
struct list *names; struct list *names;
struct list *values; struct list *values;
char cfg_file[256]; char cfg_file[256];
struct xrdp_startup_params *startup_params;
/* default to port 3389 */ startup_params = self->startup_params;
g_strncpy(port, "3389", port_bytes - 1);
/* Default to all */
g_strncpy(address, "0.0.0.0", address_bytes - 1);
/* see if port or address is in xrdp.ini file */
g_snprintf(cfg_file, 255, "%s/xrdp.ini", XRDP_CFG_PATH); g_snprintf(cfg_file, 255, "%s/xrdp.ini", XRDP_CFG_PATH);
fd = g_file_open(cfg_file); fd = g_file_open(cfg_file);
*mode = TRANS_MODE_TCP;
*tcp_nodelay = 0 ;
*tcp_keepalive = 0 ;
if (fd != -1) if (fd != -1)
{ {
names = list_create(); names = list_create();
names->auto_free = 1; names->auto_free = 1;
values = list_create(); values = list_create();
values->auto_free = 1; values->auto_free = 1;
if (file_read_section(fd, "globals", names, values) == 0) if (file_read_section(fd, "globals", names, values) == 0)
{ {
for (index = 0; index < names->count; index++) for (index = 0; index < names->count; index++)
{ {
val = (char *)list_get_item(names, index); val = (char *)list_get_item(names, index);
if (val != 0) if (val != 0)
{ {
if (g_strcasecmp(val, "port") == 0) if (g_strcasecmp(val, "port") == 0)
{ {
val = (char *)list_get_item(values, index); val = (char *)list_get_item(values, index);
if (val[0] == '/') g_strncpy(startup_params->port, val, sizeof(startup_params->port) - 1);
{
g_strncpy(port, val, port_bytes - 1);
} }
else
{
error = g_atoi(val);
if ((error > 0) && (error < 65000))
{
g_strncpy(port, val, port_bytes - 1);
}
}
}
if (g_strcasecmp(val, "use_vsock") == 0)
{
val = (char *)list_get_item(values, index);
if (g_text2bool(val) == 1)
{
*mode = TRANS_MODE_VSOCK;
}
}
if (g_strcasecmp(val, "address") == 0)
{
val = (char *)list_get_item(values, index);
g_strncpy(address, val, address_bytes - 1);
}
if (g_strcasecmp(val, "fork") == 0) if (g_strcasecmp(val, "fork") == 0)
{ {
val = (char *)list_get_item(values, index); val = (char *)list_get_item(values, index);
startup_param->fork = g_text2bool(val); startup_params->fork = g_text2bool(val);
} }
if (g_strcasecmp(val, "tcp_nodelay") == 0) if (g_strcasecmp(val, "tcp_nodelay") == 0)
{ {
val = (char *)list_get_item(values, index); val = (char *)list_get_item(values, index);
*tcp_nodelay = g_text2bool(val); startup_params->tcp_nodelay = g_text2bool(val);
} }
if (g_strcasecmp(val, "tcp_keepalive") == 0) if (g_strcasecmp(val, "tcp_keepalive") == 0)
{ {
val = (char *)list_get_item(values, index); val = (char *)list_get_item(values, index);
*tcp_keepalive = g_text2bool(val); startup_params->tcp_keepalive = g_text2bool(val);
} }
if (g_strcasecmp(val, "tcp_send_buffer_bytes") == 0) if (g_strcasecmp(val, "tcp_send_buffer_bytes") == 0)
{ {
val = (char *)list_get_item(values, index); val = (char *)list_get_item(values, index);
startup_param->send_buffer_bytes = g_atoi(val); startup_params->tcp_send_buffer_bytes = g_atoi(val);
} }
if (g_strcasecmp(val, "tcp_recv_buffer_bytes") == 0) if (g_strcasecmp(val, "tcp_recv_buffer_bytes") == 0)
{ {
val = (char *)list_get_item(values, index); val = (char *)list_get_item(values, index);
startup_param->recv_buffer_bytes = g_atoi(val); startup_params->tcp_recv_buffer_bytes = g_atoi(val);
} }
} }
} }
@ -255,17 +219,137 @@ xrdp_listen_get_port_address(char *port, int port_bytes,
list_delete(names); list_delete(names);
list_delete(values); list_delete(values);
}
if (fd != -1)
g_file_close(fd); g_file_close(fd);
}
/* startup_param overrides */ return 0;
if (startup_param->port[0] != 0)
{
g_strncpy(port, startup_param->port, port_bytes - 1);
} }
/*****************************************************************************/
static int
xrdp_listen_stop_all_listen(struct xrdp_listen *self)
{
int index;
struct trans *ltrans;
for (index = 0; index < self->trans_list->count; index++)
{
ltrans = (struct trans *)
list_get_item(self->trans_list, index);
trans_delete(ltrans);
}
list_clear(self->trans_list);
return 0;
}
/*****************************************************************************/
static int
xrdp_listen_process_startup_params(struct xrdp_listen *self)
{
int mode; /* TRANS_MODE_TCP, TRANS_MODE_UNIX, TRANS_MODE_VSOCK */
int error;
int cont;
int bytes;
struct trans *ltrans;
char address[128];
char port[128];
struct xrdp_startup_params *startup_params;
startup_params = self->startup_params;
cont = 1;
while (cont)
{
cont = 0;
g_strncpy(address, "0.0.0.0", 127);
g_strncpy(port, startup_params->port, 127);
mode = TRANS_MODE_TCP;
ltrans = trans_create(mode, 16, 16);
if (ltrans == NULL)
{
log_message(LOG_LEVEL_ERROR, "trans_create failed");
xrdp_listen_stop_all_listen(self);
return 1;
}
log_message(LOG_LEVEL_INFO, "listening to port %s on %s",
port, address);
error = trans_listen_address(ltrans, port, address);
if (error != 0)
{
log_message(LOG_LEVEL_ERROR, "trans_listen_address failed");
trans_delete(ltrans);
xrdp_listen_stop_all_listen(self);
return 1;
}
if (mode == TRANS_MODE_TCP)
{
if (startup_params->tcp_nodelay)
{
if (g_tcp_set_no_delay(ltrans->sck))
{
log_message(LOG_LEVEL_ERROR, "Error setting tcp_nodelay");
}
}
if (startup_params->tcp_keepalive)
{
if (g_tcp_set_keepalive(ltrans->sck))
{
log_message(LOG_LEVEL_ERROR, "Error setting "
"tcp_keepalive");
}
}
if (startup_params->tcp_send_buffer_bytes > 0)
{
bytes = startup_params->tcp_send_buffer_bytes;
log_message(LOG_LEVEL_INFO, "setting send buffer to %d bytes",
bytes);
if (g_sck_set_send_buffer_bytes(ltrans->sck, bytes) != 0)
{
log_message(LOG_LEVEL_ERROR, "error setting send buffer");
}
else
{
if (g_sck_get_send_buffer_bytes(ltrans->sck, &bytes) != 0)
{
log_message(LOG_LEVEL_ERROR, "error getting send "
"buffer");
}
else
{
log_message(LOG_LEVEL_INFO, "send buffer set to %d "
"bytes", bytes);
}
}
}
if (startup_params->tcp_recv_buffer_bytes > 0)
{
bytes = startup_params->tcp_recv_buffer_bytes;
log_message(LOG_LEVEL_INFO, "setting recv buffer to %d bytes",
bytes);
if (g_sck_set_recv_buffer_bytes(ltrans->sck, bytes) != 0)
{
log_message(LOG_LEVEL_ERROR, "error setting recv buffer");
}
else
{
if (g_sck_get_recv_buffer_bytes(ltrans->sck, &bytes) != 0)
{
log_message(LOG_LEVEL_ERROR, "error getting recv "
"buffer");
}
else
{
log_message(LOG_LEVEL_INFO, "recv buffer set to %d "
"bytes", bytes);
}
}
}
}
ltrans->trans_conn_in = xrdp_listen_conn_in;
ltrans->callback_data = self;
list_add_item(self->trans_list, (intptr_t) ltrans);
}
return 0; return 0;
} }
@ -356,129 +440,30 @@ xrdp_listen_main_loop(struct xrdp_listen *self)
int robjs_count; int robjs_count;
int cont; int cont;
int index; int index;
int timeout = 0; int timeout;
char port[128]; intptr_t robjs[32];
char address[256]; intptr_t term_obj;
tbus robjs[8]; intptr_t sync_obj;
tbus term_obj; intptr_t done_obj;
tbus sync_obj;
tbus done_obj;
int tcp_nodelay;
int tcp_keepalive;
int bytes;
int mode;
struct trans *ltrans; struct trans *ltrans;
self->status = 1; self->status = 1;
if (xrdp_listen_get_startup_params(self) != 0)
if (xrdp_listen_get_port_address(port, sizeof(port),
address, sizeof(address),
&tcp_nodelay, &tcp_keepalive,
//&self->listen_trans[0]->mode,
&mode,
self->startup_params) != 0)
{ {
log_message(LOG_LEVEL_ERROR,"xrdp_listen_main_loop: xrdp_listen_get_port failed"); log_message(LOG_LEVEL_ERROR,"xrdp_listen_main_loop: xrdp_listen_get_port failed");
self->status = -1; self->status = -1;
return 1; return 1;
} }
if (xrdp_listen_process_startup_params(self) != 0)
if (port[0] == '/')
{ {
ltrans = trans_create(TRANS_MODE_UNIX, 16, 16); log_message(LOG_LEVEL_ERROR,"xrdp_listen_main_loop: xrdp_listen_get_port failed");
/* not valid with UDS */ self->status = -1;
tcp_nodelay = 0; return 1;
} }
else if (mode == TRANS_MODE_VSOCK)
{
ltrans = trans_create(TRANS_MODE_VSOCK, 16, 16);
/* not valid with VSOCK */
tcp_nodelay = 0;
}
else
{
ltrans = trans_create(TRANS_MODE_TCP, 16, 16);
}
/* Create socket */
error = trans_listen_address(ltrans, port, address);
if (port[0] == '/')
{
g_chmod_hex(port, 0x0666);
}
if (error == 0)
{
log_message(LOG_LEVEL_INFO, "listening to port %s on %s",
port, address);
if (tcp_nodelay)
{
if (g_tcp_set_no_delay(ltrans->sck))
{
log_message(LOG_LEVEL_ERROR,"Error setting tcp_nodelay");
}
}
if (tcp_keepalive)
{
if (g_tcp_set_keepalive(ltrans->sck))
{
log_message(LOG_LEVEL_ERROR,"Error setting tcp_keepalive");
}
}
if (self->startup_params->send_buffer_bytes > 0)
{
bytes = self->startup_params->send_buffer_bytes;
log_message(LOG_LEVEL_INFO, "setting send buffer to %d bytes",
bytes);
if (g_sck_set_send_buffer_bytes(ltrans->sck, bytes) != 0)
{
log_message(LOG_LEVEL_ERROR, "error setting send buffer");
}
else
{
if (g_sck_get_send_buffer_bytes(ltrans->sck, &bytes) != 0)
{
log_message(LOG_LEVEL_ERROR, "error getting send buffer");
}
else
{
log_message(LOG_LEVEL_INFO, "send buffer set to %d bytes", bytes);
}
}
}
if (self->startup_params->recv_buffer_bytes > 0)
{
bytes = self->startup_params->recv_buffer_bytes;
log_message(LOG_LEVEL_INFO, "setting recv buffer to %d bytes",
bytes);
if (g_sck_set_recv_buffer_bytes(ltrans->sck, bytes) != 0)
{
log_message(LOG_LEVEL_ERROR, "error setting recv buffer");
}
else
{
if (g_sck_get_recv_buffer_bytes(ltrans->sck, &bytes) != 0)
{
log_message(LOG_LEVEL_ERROR, "error getting recv buffer");
}
else
{
log_message(LOG_LEVEL_INFO, "recv buffer set to %d bytes", bytes);
}
}
}
ltrans->trans_conn_in = xrdp_listen_conn_in;
ltrans->callback_data = self;
list_add_item(self->trans_list, (intptr_t) ltrans);
term_obj = g_get_term_event(); /*Global termination event */ term_obj = g_get_term_event(); /*Global termination event */
sync_obj = g_get_sync_event(); sync_obj = g_get_sync_event();
done_obj = self->pro_done_event; done_obj = self->pro_done_event;
cont = 1; cont = 1;
while (cont) while (cont)
{ {
/* build the wait obj list */ /* build the wait obj list */
@ -547,13 +532,7 @@ xrdp_listen_main_loop(struct xrdp_listen *self)
} }
/* stop listening */ /* stop listening */
for (index = 0; index < self->trans_list->count; index++) xrdp_listen_stop_all_listen(self);
{
ltrans = (struct trans *)
list_get_item(self->trans_list, index);
trans_delete(ltrans);
}
list_clear(self->trans_list);
/* second loop to wait for all process threads to close */ /* second loop to wait for all process threads to close */
cont = 1; cont = 1;
@ -591,20 +570,6 @@ xrdp_listen_main_loop(struct xrdp_listen *self)
xrdp_listen_delete_done_pro(self); xrdp_listen_delete_done_pro(self);
} }
} }
}
else
{
trans_delete(ltrans);
log_message(LOG_LEVEL_ERROR,"xrdp_listen_main_loop: listen error, possible port "
"already in use");
#if !defined(XRDP_ENABLE_VSOCK)
if (ltrans->mode == TRANS_MODE_VSOCK)
{
log_message(LOG_LEVEL_ERROR,"xrdp_listen_main_loop: listen error, "
"vsock support not compiled and config requested");
}
#endif
}
self->status = -1; self->status = -1;
return error; return error;

View File

@ -527,14 +527,16 @@ struct xrdp_mod_data
struct xrdp_startup_params struct xrdp_startup_params
{ {
char port[128]; char port[1024];
int kill; int kill;
int no_daemon; int no_daemon;
int help; int help;
int version; int version;
int fork; int fork;
int send_buffer_bytes; int tcp_send_buffer_bytes;
int recv_buffer_bytes; int tcp_recv_buffer_bytes;
int tcp_nodelay;
int tcp_keepalive;
}; };
/* /*