Merge pull request #2204 from matt335672/trans_connect
Rework transport connect logic
This commit is contained in:
commit
ffc6fa66a0
267
common/trans.c
267
common/trans.c
@ -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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
while (1)
|
||||
{
|
||||
/* 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 = 0;
|
||||
}
|
||||
self->sck = f_alloc_socket();
|
||||
|
||||
if (self->mode == TRANS_MODE_TCP) /* tcp */
|
||||
{
|
||||
self->sck = g_tcp_socket();
|
||||
if (self->sck < 0)
|
||||
{
|
||||
self->status = TRANS_STATUS_DOWN;
|
||||
return 1;
|
||||
}
|
||||
g_tcp_set_non_blocking(self->sck);
|
||||
while (1)
|
||||
{
|
||||
error = g_tcp_connect(self->sck, server, port);
|
||||
if (error == 0)
|
||||
{
|
||||
error = 1;
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (self->mode == TRANS_MODE_UNIX) /* unix socket */
|
||||
{
|
||||
self->sck = g_tcp_local_socket();
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
self->status = TRANS_STATUS_DOWN;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (error == -1)
|
||||
/* Try to connect asynchronously */
|
||||
g_tcp_set_non_blocking(self->sck);
|
||||
error = f_connect(self->sck, server, port);
|
||||
if (error == 0)
|
||||
{
|
||||
/* Connect was immediately successful */
|
||||
break;
|
||||
}
|
||||
|
||||
if (g_tcp_last_error_would_block(self->sck))
|
||||
{
|
||||
now = g_time3();
|
||||
if (now - start_time < timeout)
|
||||
/* Async connect is in progress */
|
||||
if (poll_for_async_connect(self, start_time, timeout) == 0)
|
||||
{
|
||||
timeout = timeout - (now - start_time);
|
||||
/* Async connect was successful */
|
||||
error = 0;
|
||||
break;
|
||||
}
|
||||
/* No need to wait any more before the next connect attempt */
|
||||
ms_before_next_connect = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
timeout = 0;
|
||||
/* Connect failed immediately. Wait a bit before the next
|
||||
* attempt */
|
||||
ms_before_next_connect = CONNECT_DELAY_ON_FAIL_MS;
|
||||
}
|
||||
if (g_tcp_can_send(self->sck, timeout))
|
||||
|
||||
/* 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)
|
||||
{
|
||||
ms_before_next_connect = ms_left;
|
||||
}
|
||||
g_sleep(ms_before_next_connect);
|
||||
}
|
||||
}
|
||||
|
||||
if (error != 0)
|
||||
{
|
||||
if (self->sck >= 0)
|
||||
{
|
||||
g_tcp_close(self->sck);
|
||||
self->sck = -1;
|
||||
}
|
||||
self->status = TRANS_STATUS_DOWN;
|
||||
}
|
||||
else
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
15
libipm/scp.c
15
libipm/scp.c
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
2
mc/mc.h
2
mc/mc.h
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
|
62
xup/xup.c
62
xup/xup.c
@ -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,83 +170,48 @@ 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);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
|
||||
/* mod->server_msg(mod, "connecting...", 0); */
|
||||
|
||||
error = -1;
|
||||
if (trans_connect(mod->trans, mod->ip, con_port, 3000) == 0)
|
||||
/* Give the X server a bit of time to start */
|
||||
if (trans_connect(mod->trans, mod->ip, con_port, 30 * 1000) == 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)
|
||||
else
|
||||
{
|
||||
mod->server_msg(mod, "connection problem, giving up", 0);
|
||||
break;
|
||||
error = 1;
|
||||
}
|
||||
|
||||
g_sleep(500);
|
||||
}
|
||||
|
||||
if (error == 0)
|
||||
{
|
||||
if (use_uds)
|
||||
if (error == 0 && socket_mode == TRANS_MODE_UNIX)
|
||||
{
|
||||
lib_mod_log_peer(mod);
|
||||
}
|
||||
}
|
||||
|
||||
if (error == 0)
|
||||
{
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user