Merge pull request #2204 from matt335672/trans_connect

Rework transport connect logic
This commit is contained in:
matt335672 2022-04-15 10:33:11 +01:00 committed by GitHub
commit ffc6fa66a0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 203 additions and 216 deletions

View File

@ -32,6 +32,11 @@
#define MAX_SBYTES 0
/** Time between polls of is_term when connecting */
#define CONNECT_TERM_POLL_MS 3000
/** Time we wait before another connect() attempt if one fails immediately */
#define CONNECT_DELAY_ON_FAIL_MS 2000
/*****************************************************************************/
int
trans_tls_recv(struct trans *self, char *ptr, int len)
@ -96,6 +101,7 @@ trans_create(int mode, int in_size, int out_size)
if (self != NULL)
{
self->sck = -1;
make_stream(self->in_s);
init_stream(self->in_s, in_size);
make_stream(self->out_s);
@ -129,12 +135,12 @@ trans_delete(struct trans *self)
free_stream(self->in_s);
free_stream(self->out_s);
if (self->sck > 0)
if (self->sck >= 0)
{
g_tcp_close(self->sck);
}
self->sck = 0;
self->sck = -1;
if (self->listen_filename != 0)
{
@ -671,143 +677,182 @@ trans_write_copy(struct trans *self)
}
/*****************************************************************************/
/* Shim to apply the function signature of g_tcp_connect()
* to g_tcp_local_connect()
*/
static int
local_connect_shim(int fd, const char *server, const char *port)
{
return g_tcp_local_connect(fd, port);
}
/**************************************************************************//**
* Waits for an asynchronous connect to complete.
* @param self - Transport object
* @param start_time Start time of connect (from g_time3())
* @param timeout Total wait timeout
* @return 0 - connect succeeded, 1 - Connect failed
*
* If the transport is set up for checking a termination object, this
* on a regular basis.
*/
static int
poll_for_async_connect(struct trans *self, int start_time, int timeout)
{
int rv = 1;
int ms_remaining = timeout - (g_time3() - start_time);
while (ms_remaining > 0)
{
int poll_time = ms_remaining;
/* Lower bound for waititng for a result */
if (poll_time < 100)
{
poll_time = 100;
}
/* Limit the wait time if we need to poll for termination */
if (self->is_term != NULL && poll_time > CONNECT_TERM_POLL_MS)
{
poll_time = CONNECT_TERM_POLL_MS;
}
if (g_tcp_can_send(self->sck, poll_time))
{
/* Connect has finished - return the socket status */
rv = g_sck_socket_ok(self->sck) ? 0 : 1;
break;
}
/* Check for program termination */
if (self->is_term != NULL && self->is_term())
{
break;
}
ms_remaining = timeout - (g_time3() - start_time);
}
return rv;
}
/*****************************************************************************/
int
trans_connect(struct trans *self, const char *server, const char *port,
int timeout)
{
int start_time = g_time3();
int error;
int now;
int start_time;
int ms_before_next_connect;
start_time = g_time3();
/*
* Function pointers which we use in the main loop to avoid
* having to switch on the socket mode */
int (*f_alloc_socket)(void);
int (*f_connect)(int fd, const char *server, const char *port);
if (self->sck != 0)
switch (self->mode)
{
g_tcp_close(self->sck);
self->sck = 0;
case TRANS_MODE_TCP:
f_alloc_socket = g_tcp_socket;
f_connect = g_tcp_connect;
break;
case TRANS_MODE_UNIX:
f_alloc_socket = g_tcp_local_socket;
f_connect = local_connect_shim;
break;
default:
LOG(LOG_LEVEL_ERROR, "Bad socket mode %d", self->mode);
return 1;
}
if (self->mode == TRANS_MODE_TCP) /* tcp */
while (1)
{
self->sck = g_tcp_socket();
/* Check the program isn't terminating */
if (self->is_term != NULL && self->is_term())
{
error = 1;
break;
}
/* Allocate a new socket */
if (self->sck >= 0)
{
g_tcp_close(self->sck);
}
self->sck = f_alloc_socket();
if (self->sck < 0)
{
self->status = TRANS_STATUS_DOWN;
return 1;
error = 1;
break;
}
/* Try to connect asynchronously */
g_tcp_set_non_blocking(self->sck);
while (1)
error = f_connect(self->sck, server, port);
if (error == 0)
{
error = g_tcp_connect(self->sck, server, port);
if (error == 0)
/* Connect was immediately successful */
break;
}
if (g_tcp_last_error_would_block(self->sck))
{
/* Async connect is in progress */
if (poll_for_async_connect(self, start_time, timeout) == 0)
{
/* Async connect was successful */
error = 0;
break;
}
else
/* No need to wait any more before the next connect attempt */
ms_before_next_connect = 0;
}
else
{
/* Connect failed immediately. Wait a bit before the next
* attempt */
ms_before_next_connect = CONNECT_DELAY_ON_FAIL_MS;
}
/* Have we reached the total timeout yet? */
int ms_left = timeout - (g_time3() - start_time);
if (ms_left <= 0)
{
error = 1;
break;
}
/* Sleep a bit before trying again */
if (ms_before_next_connect > 0)
{
if (ms_before_next_connect > ms_left)
{
if (timeout < 1)
{
self->status = TRANS_STATUS_DOWN;
return 1;
}
now = g_time3();
if (now - start_time < timeout)
{
g_sleep(100);
}
else
{
self->status = TRANS_STATUS_DOWN;
return 1;
}
if (self->is_term != NULL)
{
if (self->is_term())
{
self->status = TRANS_STATUS_DOWN;
return 1;
}
}
ms_before_next_connect = ms_left;
}
g_sleep(ms_before_next_connect);
}
}
else if (self->mode == TRANS_MODE_UNIX) /* unix socket */
if (error != 0)
{
self->sck = g_tcp_local_socket();
if (self->sck < 0)
if (self->sck >= 0)
{
self->status = TRANS_STATUS_DOWN;
return 1;
}
g_tcp_set_non_blocking(self->sck);
while (1)
{
error = g_tcp_local_connect(self->sck, port);
if (error == 0)
{
break;
}
else
{
if (timeout < 1)
{
self->status = TRANS_STATUS_DOWN;
return 1;
}
now = g_time3();
if (now - start_time < timeout)
{
g_sleep(100);
}
else
{
self->status = TRANS_STATUS_DOWN;
return 1;
}
if (self->is_term != NULL)
{
if (self->is_term())
{
self->status = TRANS_STATUS_DOWN;
return 1;
}
}
}
g_tcp_close(self->sck);
self->sck = -1;
}
self->status = TRANS_STATUS_DOWN;
}
else
{
self->status = TRANS_STATUS_DOWN;
return 1;
self->status = TRANS_STATUS_UP; /* ok */
self->type1 = TRANS_TYPE_CLIENT; /* client */
}
if (error == -1)
{
if (g_tcp_last_error_would_block(self->sck))
{
now = g_time3();
if (now - start_time < timeout)
{
timeout = timeout - (now - start_time);
}
else
{
timeout = 0;
}
if (g_tcp_can_send(self->sck, timeout))
{
self->status = TRANS_STATUS_UP; /* ok */
self->type1 = TRANS_TYPE_CLIENT; /* client */
return 0;
}
}
return 1;
}
self->status = TRANS_STATUS_UP; /* ok */
self->type1 = TRANS_TYPE_CLIENT; /* client */
return 0;
return error;
}
/*****************************************************************************/
@ -818,7 +863,7 @@ trans_connect(struct trans *self, const char *server, const char *port,
int
trans_listen_address(struct trans *self, const char *port, const char *address)
{
if (self->sck != 0)
if (self->sck >= 0)
{
g_tcp_close(self->sck);
}

View File

@ -147,6 +147,20 @@ int
trans_write_copy(struct trans *self);
int
trans_write_copy_s(struct trans *self, struct stream *out_s);
/**
* Connect the transport to the specified destination
*
* @param self Transport
* @param server Destination server (TCP transports only)
* @param port TCP port, or UNIX socket to connect to
* @param timeout in milli-seconds for the operation
* @return 0 for success
*
* Multiple connection attempts may be made within the timeout period.
*
* If the operation is successful, 0 is returned and self->status will
* be TRANS_STATUS_UP
*/
int
trans_connect(struct trans *self, const char *server, const char *port,
int timeout);

View File

@ -74,8 +74,6 @@ scp_connect(const char *host, const char *port,
struct trans *t;
if ((t = trans_create(TRANS_MODE_TCP, 128, 128)) != NULL)
{
int index;
if (host == NULL)
{
host = "localhost";
@ -88,18 +86,7 @@ scp_connect(const char *host, const char *port,
t->is_term = term_func;
/* try to connect up to 4 times
*
* term_func can be NULL, so check before calling it */
index = 4;
while (trans_connect(t, host, port, 3000) != 0 &&
!(term_func && term_func()) &&
--index > 0)
{
g_sleep(1000);
LOG_DEVEL(LOG_LEVEL_DEBUG, "Connect failed. Trying again...");
}
trans_connect(t, host, port, 3000);
if (t->status != TRANS_STATUS_UP)
{
trans_delete(t);

View File

@ -1383,7 +1383,7 @@ close_rdp_socket(struct xrdp_mcs *self)
{
trans_shutdown_tls_mode(self->iso_layer->trans);
g_tcp_close(self->iso_layer->trans->sck);
self->iso_layer->trans->sck = 0 ;
self->iso_layer->trans->sck = -1;
LOG_DEVEL(LOG_LEVEL_DEBUG, "xrdp_mcs_disconnect - socket closed");
return;
}

View File

@ -57,7 +57,7 @@ struct mod
int (*server_set_cursor)(struct mod *v, int x, int y, char *data, char *mask);
int (*server_palette)(struct mod *v, int *palette);
int (*server_msg)(struct mod *v, const char *msg, int code);
int (*server_is_term)(struct mod *v);
int (*server_is_term)(void);
int (*server_set_clip)(struct mod *v, int x, int y, int cx, int cy);
int (*server_reset_clip)(struct mod *v);
int (*server_set_fgcolor)(struct mod *v, int fgcolor);

View File

@ -109,7 +109,7 @@ struct mod
int (*server_set_pointer)(struct mod *v, int x, int y, char *data, char *mask);
int (*server_palette)(struct mod *v, int *palette);
int (*server_msg)(struct mod *v, const char *msg, int code);
int (*server_is_term)(struct mod *v);
int (*server_is_term)(void);
int (*server_set_clip)(struct mod *v, int x, int y, int cx, int cy);
int (*server_reset_clip)(struct mod *v);
int (*server_set_fgcolor)(struct mod *v, int fgcolor);

View File

@ -102,7 +102,7 @@ struct vnc
int (*server_set_cursor)(struct vnc *v, int x, int y, char *data, char *mask);
int (*server_palette)(struct vnc *v, int *palette);
int (*server_msg)(struct vnc *v, const char *msg, int code);
int (*server_is_term)(struct vnc *v);
int (*server_is_term)(void);
int (*server_set_clip)(struct vnc *v, int x, int y, int cx, int cy);
int (*server_reset_clip)(struct vnc *v);
int (*server_set_fgcolor)(struct vnc *v, int fgcolor);

View File

@ -477,8 +477,6 @@ server_palette(struct xrdp_mod *mod, int *palette);
int
server_msg(struct xrdp_mod *mod, const char *msg, int code);
int
server_is_term(struct xrdp_mod *mod);
int
server_set_clip(struct xrdp_mod *mod, int x, int y, int cx, int cy);
int
server_reset_clip(struct xrdp_mod *mod);

View File

@ -415,7 +415,7 @@ xrdp_mm_setup_mod1(struct xrdp_mm *self)
self->mod->server_set_pointer_ex = server_set_pointer_ex;
self->mod->server_palette = server_palette;
self->mod->server_msg = server_msg;
self->mod->server_is_term = server_is_term;
self->mod->server_is_term = g_is_term;
self->mod->server_set_clip = server_set_clip;
self->mod->server_reset_clip = server_reset_clip;
self->mod->server_set_fgcolor = server_set_fgcolor;
@ -2356,8 +2356,6 @@ xrdp_mm_sesman_connect(struct xrdp_mm *self, const char *ip)
static int
xrdp_mm_chansrv_connect(struct xrdp_mm *self, const char *ip, const char *port)
{
int index;
if (self->wm->client_info->channels_allowed == 0)
{
LOG(LOG_LEVEL_DEBUG, "%s: "
@ -2387,22 +2385,8 @@ xrdp_mm_chansrv_connect(struct xrdp_mm *self, const char *ip, const char *port)
self->chan_trans->no_stream_init_on_data_in = 1;
self->chan_trans->extra_flags = 0;
/* try to connect up to 4 times */
for (index = 0; index < 4; index++)
{
if (trans_connect(self->chan_trans, ip, port, 3000) == 0)
{
break;
}
if (g_is_term())
{
break;
}
g_sleep(1000);
LOG(LOG_LEVEL_WARNING, "xrdp_mm_chansrv_connect: connect failed "
"trying again...");
}
/* try to connect for up to 10 seconds */
trans_connect(self->chan_trans, ip, port, 10 * 1000);
if (self->chan_trans->status != TRANS_STATUS_UP)
{
LOG(LOG_LEVEL_ERROR, "xrdp_mm_chansrv_connect: error in "
@ -3368,13 +3352,6 @@ server_msg(struct xrdp_mod *mod, const char *msg, int code)
return xrdp_wm_log_msg(wm, LOG_LEVEL_DEBUG, "%s", msg);
}
/*****************************************************************************/
int
server_is_term(struct xrdp_mod *mod)
{
return g_is_term();
}
/*****************************************************************************/
int
server_set_clip(struct xrdp_mod *mod, int x, int y, int cx, int cy)

View File

@ -74,7 +74,9 @@ struct xrdp_mod
char *data, char *mask);
int (*server_palette)(struct xrdp_mod *v, int *palette);
int (*server_msg)(struct xrdp_mod *v, const char *msg, int code);
int (*server_is_term)(struct xrdp_mod *v);
/* This one can be assigned directly into the is_term member of
* a struct trans */
int (*server_is_term)(void);
int (*server_set_clip)(struct xrdp_mod *v, int x, int y, int cx, int cy);
int (*server_reset_clip)(struct xrdp_mod *v);
int (*server_set_fgcolor)(struct xrdp_mod *v, int fgcolor);

View File

@ -148,8 +148,7 @@ int
lib_mod_connect(struct mod *mod)
{
int error;
int i;
int use_uds;
int socket_mode;
struct stream *s;
char con_port[256];
@ -171,82 +170,47 @@ lib_mod_connect(struct mod *mod)
make_stream(s);
g_sprintf(con_port, "%s", mod->port);
use_uds = 0;
if (con_port[0] == '/')
{
use_uds = 1;
}
error = 0;
mod->sck_closed = 0;
i = 0;
if (use_uds)
if (con_port[0] == '/')
{
socket_mode = TRANS_MODE_UNIX;
LOG(LOG_LEVEL_INFO, "lib_mod_connect: connecting via UNIX socket");
mod->trans = trans_create(TRANS_MODE_UNIX, 8 * 8192, 8192);
if (mod->trans == 0)
{
free_stream(s);
return 1;
}
}
else
{
socket_mode = TRANS_MODE_TCP;
LOG(LOG_LEVEL_INFO, "lib_mod_connect: connecting via TCP socket");
mod->trans = trans_create(TRANS_MODE_TCP, 8 * 8192, 8192);
if (mod->trans == 0)
{
free_stream(s);
return 1;
}
}
mod->trans = trans_create(socket_mode, 8 * 8192, 8192);
if (mod->trans == 0)
{
free_stream(s);
return 1;
}
mod->trans->si = mod->si;
mod->trans->my_source = XRDP_SOURCE_MOD;
mod->trans->is_term = mod->server_is_term;
while (1)
/* Give the X server a bit of time to start */
if (trans_connect(mod->trans, mod->ip, con_port, 30 * 1000) == 0)
{
/* mod->server_msg(mod, "connecting...", 0); */
error = -1;
if (trans_connect(mod->trans, mod->ip, con_port, 3000) == 0)
{
LOG_DEVEL(LOG_LEVEL_INFO, "lib_mod_connect: connected to Xserver "
"(Xorg or X11rdp) sck %lld",
(long long) (mod->trans->sck));
error = 0;
}
if (error == 0)
{
break;
}
if (mod->server_is_term(mod))
{
break;
}
i++;
if (i >= 60)
{
mod->server_msg(mod, "connection problem, giving up", 0);
break;
}
g_sleep(500);
LOG_DEVEL(LOG_LEVEL_INFO, "lib_mod_connect: connected to Xserver "
"(Xorg or X11rdp) sck %lld",
(long long) (mod->trans->sck));
}
else
{
mod->server_msg(mod, "connection problem, giving up", 0);
error = 1;
}
if (error == 0)
if (error == 0 && socket_mode == TRANS_MODE_UNIX)
{
if (use_uds)
{
lib_mod_log_peer(mod);
}
lib_mod_log_peer(mod);
}
if (error == 0)

View File

@ -70,7 +70,7 @@ struct mod
int (*server_set_cursor)(struct mod *v, int x, int y, char *data, char *mask);
int (*server_palette)(struct mod *v, int *palette);
int (*server_msg)(struct mod *v, const char *msg, int code);
int (*server_is_term)(struct mod *v);
int (*server_is_term)(void);
int (*server_set_clip)(struct mod *v, int x, int y, int cx, int cy);
int (*server_reset_clip)(struct mod *v);
int (*server_set_fgcolor)(struct mod *v, int fgcolor);