mirror of https://github.com/FreeRDP/FreeRDP
Merge pull request #2765 from akallabeth/connect_abort
Connect abort and unified TCP connect
This commit is contained in:
commit
d971116457
|
@ -134,7 +134,8 @@ struct rdp_context
|
|||
ALIGN64 rdpMetrics* metrics; /* 41 */
|
||||
ALIGN64 rdpCodecs* codecs; /* 42 */
|
||||
ALIGN64 rdpAutoDetect* autodetect; /* 43 */
|
||||
UINT64 paddingC[64 - 44]; /* 44 */
|
||||
ALIGN64 HANDLE abortEvent; /* 44 */
|
||||
UINT64 paddingC[64 - 45]; /* 45 */
|
||||
|
||||
UINT64 paddingD[96 - 64]; /* 64 */
|
||||
UINT64 paddingE[128 - 96]; /* 96 */
|
||||
|
@ -248,6 +249,7 @@ FREERDP_API BOOL freerdp_context_new(freerdp* instance);
|
|||
FREERDP_API void freerdp_context_free(freerdp* instance);
|
||||
|
||||
FREERDP_API BOOL freerdp_connect(freerdp* instance);
|
||||
FREERDP_API BOOL freerdp_abort_connect(freerdp* instance);
|
||||
FREERDP_API BOOL freerdp_shall_disconnect(freerdp* instance);
|
||||
FREERDP_API BOOL freerdp_disconnect(freerdp* instance);
|
||||
FREERDP_API BOOL freerdp_reconnect(freerdp* instance);
|
||||
|
|
|
@ -318,7 +318,7 @@ BOOL rdp_recv_deactivate_all(rdpRdp* rdp, wStream* s)
|
|||
if (rdp_check_fds(rdp) < 0)
|
||||
return FALSE;
|
||||
|
||||
if (rdp->disconnect)
|
||||
if (freerdp_shall_disconnect(rdp->instance))
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -3540,7 +3540,7 @@ BOOL rdp_recv_get_active_header(rdpRdp* rdp, wStream* s, UINT16* pChannelId)
|
|||
if (!rdp_read_header(rdp, s, &length, pChannelId))
|
||||
return FALSE;
|
||||
|
||||
if (rdp->disconnect)
|
||||
if (freerdp_shall_disconnect(rdp->instance))
|
||||
return TRUE;
|
||||
|
||||
if (rdp->settings->UseRdpSecurityLayer)
|
||||
|
@ -3585,7 +3585,7 @@ BOOL rdp_recv_demand_active(rdpRdp* rdp, wStream* s)
|
|||
if (!rdp_recv_get_active_header(rdp, s, &channelId))
|
||||
return FALSE;
|
||||
|
||||
if (rdp->disconnect)
|
||||
if (freerdp_shall_disconnect(rdp->instance))
|
||||
return TRUE;
|
||||
|
||||
if (!rdp_read_share_control_header(s, &pduLength, &pduType, &pduSource))
|
||||
|
|
|
@ -313,6 +313,8 @@ BOOL rdp_client_disconnect(rdpRdp* rdp)
|
|||
{
|
||||
BOOL status;
|
||||
|
||||
ResetEvent(rdp->context->abortEvent);
|
||||
|
||||
if (rdp->settingsCopy)
|
||||
{
|
||||
freerdp_settings_free(rdp->settingsCopy);
|
||||
|
@ -832,7 +834,7 @@ int rdp_client_connect_demand_active(rdpRdp* rdp, wStream* s)
|
|||
return rdp_recv_out_of_sequence_pdu(rdp, s);
|
||||
}
|
||||
|
||||
if (rdp->disconnect)
|
||||
if (freerdp_shall_disconnect(rdp->instance))
|
||||
return 0;
|
||||
|
||||
if (!rdp_send_confirm_active(rdp))
|
||||
|
|
|
@ -74,6 +74,7 @@ BOOL freerdp_connect(freerdp* instance)
|
|||
|
||||
rdp = instance->context->rdp;
|
||||
settings = instance->settings;
|
||||
|
||||
instance->context->codecs = codecs_new(instance->context);
|
||||
IFCALLRET(instance->PreConnect, status, instance);
|
||||
|
||||
|
@ -102,6 +103,9 @@ BOOL freerdp_connect(freerdp* instance)
|
|||
goto freerdp_connect_finally;
|
||||
}
|
||||
|
||||
if (!status)
|
||||
goto freerdp_connect_finally;
|
||||
|
||||
if (status)
|
||||
{
|
||||
if (instance->settings->DumpRemoteFx)
|
||||
|
@ -182,6 +186,14 @@ freerdp_connect_finally:
|
|||
return status;
|
||||
}
|
||||
|
||||
BOOL freerdp_abort_connect(freerdp* instance)
|
||||
{
|
||||
if (!instance || !instance->context)
|
||||
return FALSE;
|
||||
|
||||
return SetEvent(instance->context->abortEvent);
|
||||
}
|
||||
|
||||
BOOL freerdp_get_fds(freerdp* instance, void** rfds, int* rcount, void** wfds, int* wcount)
|
||||
{
|
||||
rdpRdp* rdp = instance->context->rdp;
|
||||
|
@ -376,7 +388,11 @@ BOOL freerdp_reconnect(freerdp* instance)
|
|||
|
||||
BOOL freerdp_shall_disconnect(freerdp* instance)
|
||||
{
|
||||
return instance->context->rdp->disconnect;
|
||||
if (!instance || !instance->context)
|
||||
return FALSE;
|
||||
if (WaitForSingleObject(instance->context->abortEvent, 0) != WAIT_OBJECT_0)
|
||||
return FALSE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
FREERDP_API BOOL freerdp_focus_required(freerdp* instance)
|
||||
|
@ -527,14 +543,22 @@ BOOL freerdp_context_new(freerdp* instance)
|
|||
|
||||
update_register_client_callbacks(rdp->update);
|
||||
|
||||
instance->context->abortEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||||
if (!instance->context->abortEvent)
|
||||
goto out_error_abort_event;
|
||||
|
||||
IFCALLRET(instance->ContextNew, ret, instance, instance->context);
|
||||
|
||||
if (ret)
|
||||
return TRUE;
|
||||
out_error_create_event:
|
||||
|
||||
CloseHandle(context->abortEvent);
|
||||
out_error_abort_event:
|
||||
CloseHandle(context->channelErrorEvent);
|
||||
out_error_description:
|
||||
out_error_create_event:
|
||||
free(context->errorDescription);
|
||||
out_error_description:
|
||||
graphics_free(context->graphics);
|
||||
out_error_graphics_new:
|
||||
rdp_free(rdp);
|
||||
out_error_rdp_new:
|
||||
|
@ -577,6 +601,9 @@ void freerdp_context_free(freerdp* instance)
|
|||
CloseHandle(instance->context->channelErrorEvent);
|
||||
free(instance->context->errorDescription);
|
||||
|
||||
CloseHandle(instance->context->abortEvent);
|
||||
instance->context->abortEvent = NULL;
|
||||
|
||||
free(instance->context);
|
||||
instance->context = NULL;
|
||||
|
||||
|
|
|
@ -899,7 +899,8 @@ BOOL rdg_tls_out_connect(rdpRdg* rdg, const char* hostname, UINT16 port, int tim
|
|||
|
||||
assert(hostname != NULL);
|
||||
|
||||
sockfd = freerdp_tcp_connect(settings, settings->GatewayHostname, settings->GatewayPort, timeout);
|
||||
sockfd = freerdp_tcp_connect(rdg->context, settings, settings->GatewayHostname,
|
||||
settings->GatewayPort, timeout);
|
||||
|
||||
if (sockfd < 1)
|
||||
{
|
||||
|
@ -955,7 +956,8 @@ BOOL rdg_tls_in_connect(rdpRdg* rdg, const char* hostname, UINT16 port, int time
|
|||
|
||||
assert(hostname != NULL);
|
||||
|
||||
sockfd = freerdp_tcp_connect(settings, settings->GatewayHostname, settings->GatewayPort, timeout);
|
||||
sockfd = freerdp_tcp_connect(rdg->context, settings, settings->GatewayHostname,
|
||||
settings->GatewayPort, timeout);
|
||||
|
||||
if (sockfd < 1)
|
||||
return FALSE;
|
||||
|
|
|
@ -760,7 +760,8 @@ int rpc_channel_tls_connect(RpcChannel* channel, int timeout)
|
|||
rdpContext* context = rpc->context;
|
||||
rdpSettings* settings = context->settings;
|
||||
|
||||
sockfd = freerdp_tcp_connect(settings, settings->GatewayHostname, settings->GatewayPort, timeout);
|
||||
sockfd = freerdp_tcp_connect(context, settings, settings->GatewayHostname,
|
||||
settings->GatewayPort, timeout);
|
||||
|
||||
if (sockfd < 1)
|
||||
return -1;
|
||||
|
|
|
@ -340,7 +340,7 @@ int rpc_client_recv_fragment(rdpRpc* rpc, wStream* fragment)
|
|||
|
||||
rpc->result = *((UINT32*) &buffer[StubOffset]);
|
||||
|
||||
rpc->context->rdp->disconnect = TRUE;
|
||||
freerdp_abort_connect(rpc->context->instance);
|
||||
rpc->transport->tsg->state = TSG_STATE_TUNNEL_CLOSE_PENDING;
|
||||
EventArgsInit(&e, "freerdp");
|
||||
e.code = 0;
|
||||
|
|
|
@ -171,8 +171,13 @@ static BOOL freerdp_listener_open(freerdp_listener* instance, const char* bind_a
|
|||
/* FIXME: these file descriptors do not work on Windows */
|
||||
|
||||
listener->sockfds[listener->num_sockfds] = sockfd;
|
||||
listener->events[listener->num_sockfds] =
|
||||
CreateFileDescriptorEvent(NULL, FALSE, FALSE, sockfd, WINPR_FD_READ);
|
||||
listener->events[listener->num_sockfds] = WSACreateEvent();
|
||||
if (!listener->events[listener->num_sockfds])
|
||||
{
|
||||
listener->num_sockfds = 0;
|
||||
break;
|
||||
}
|
||||
WSAEventSelect(sockfd, listener->events[listener->num_sockfds], FD_READ | FD_ACCEPT | FD_CLOSE);
|
||||
listener->num_sockfds++;
|
||||
|
||||
WLog_INFO(TAG, "Listening on %s:%s", addr, servname);
|
||||
|
@ -336,7 +341,7 @@ static BOOL freerdp_listener_check_fds(freerdp_listener* instance)
|
|||
void* sin_addr;
|
||||
int peer_sockfd;
|
||||
freerdp_peer* client = NULL;
|
||||
socklen_t peer_addr_size;
|
||||
int peer_addr_size;
|
||||
struct sockaddr_storage peer_addr;
|
||||
rdpListener* listener = (rdpListener*) instance->listener;
|
||||
static const BYTE localhost6_bytes[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 };
|
||||
|
@ -347,8 +352,10 @@ static BOOL freerdp_listener_check_fds(freerdp_listener* instance)
|
|||
|
||||
for (i = 0; i < listener->num_sockfds; i++)
|
||||
{
|
||||
WSAResetEvent(listener->events[i]);
|
||||
|
||||
peer_addr_size = sizeof(peer_addr);
|
||||
peer_sockfd = accept(listener->sockfds[i], (struct sockaddr*) &peer_addr, &peer_addr_size);
|
||||
peer_sockfd = _accept(listener->sockfds[i], (struct sockaddr*) &peer_addr, &peer_addr_size);
|
||||
peer_accepted = FALSE;
|
||||
|
||||
if (peer_sockfd == -1)
|
||||
|
|
|
@ -356,7 +356,7 @@ static int peer_recv_tpkt_pdu(freerdp_peer* client, wStream* s)
|
|||
return -1;
|
||||
}
|
||||
|
||||
if (rdp->disconnect)
|
||||
if (freerdp_shall_disconnect(rdp->instance))
|
||||
return 0;
|
||||
|
||||
if (rdp->settings->UseRdpSecurityLayer)
|
||||
|
|
|
@ -307,7 +307,7 @@ BOOL rdp_read_header(rdpRdp* rdp, wStream* s, UINT16* length, UINT16* channelId)
|
|||
{
|
||||
if (code == X224_TPDU_DISCONNECT_REQUEST)
|
||||
{
|
||||
rdp->disconnect = TRUE;
|
||||
freerdp_abort_connect(rdp->instance);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
@ -341,7 +341,7 @@ BOOL rdp_read_header(rdpRdp* rdp, wStream* s, UINT16* length, UINT16* channelId)
|
|||
|
||||
if (!rdp->instance)
|
||||
{
|
||||
rdp->disconnect = TRUE;
|
||||
freerdp_abort_connect(rdp->instance);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
@ -364,7 +364,7 @@ BOOL rdp_read_header(rdpRdp* rdp, wStream* s, UINT16* length, UINT16* channelId)
|
|||
}
|
||||
|
||||
WLog_ERR(TAG, "DisconnectProviderUltimatum: reason: %d", reason);
|
||||
rdp->disconnect = TRUE;
|
||||
freerdp_abort_connect(rdp->instance);
|
||||
|
||||
EventArgsInit(&e, "freerdp");
|
||||
e.code = 0;
|
||||
|
@ -1117,7 +1117,7 @@ static int rdp_recv_tpkt_pdu(rdpRdp* rdp, wStream* s)
|
|||
return -1;
|
||||
}
|
||||
|
||||
if (rdp->disconnect)
|
||||
if (freerdp_shall_disconnect(rdp->instance))
|
||||
return 0;
|
||||
|
||||
if (rdp->autodetect->bandwidthMeasureStarted)
|
||||
|
@ -1647,7 +1647,6 @@ void rdp_reset(rdpRdp* rdp)
|
|||
rdp->nego = nego_new(rdp->transport);
|
||||
rdp->mcs = mcs_new(rdp->transport);
|
||||
rdp->transport->layer = TRANSPORT_LAYER_TCP;
|
||||
rdp->disconnect = FALSE;
|
||||
rdp->errorInfo = 0;
|
||||
rdp->deactivation_reactivation = 0;
|
||||
rdp->finalize_sc_pdus = 0;
|
||||
|
|
|
@ -171,7 +171,6 @@ struct rdp_rdp
|
|||
BYTE fips_decrypt_key[24];
|
||||
UINT32 errorInfo;
|
||||
UINT32 finalize_sc_pdus;
|
||||
BOOL disconnect;
|
||||
BOOL resendFocus;
|
||||
BOOL deactivation_reactivation;
|
||||
BOOL AwaitCapabilities;
|
||||
|
|
|
@ -145,6 +145,8 @@ static int transport_bio_simple_read(BIO* bio, char* buf, int size)
|
|||
|
||||
BIO_clear_flags(bio, BIO_FLAGS_READ);
|
||||
|
||||
WSAResetEvent(ptr->hEvent);
|
||||
|
||||
status = _recv(ptr->socket, buf, size, 0);
|
||||
|
||||
if (status > 0)
|
||||
|
@ -359,20 +361,17 @@ static int transport_bio_simple_init(BIO* bio, SOCKET socket, int shutdown)
|
|||
bio->flags = BIO_FLAGS_SHOULD_RETRY;
|
||||
bio->init = 1;
|
||||
|
||||
#ifdef _WIN32
|
||||
ptr->hEvent = WSACreateEvent();
|
||||
ptr->hEvent = WSACreateEvent();
|
||||
|
||||
if (!ptr->hEvent)
|
||||
return 0;
|
||||
if (!ptr->hEvent)
|
||||
return 0;
|
||||
|
||||
/* WSAEventSelect automatically sets the socket in non-blocking mode */
|
||||
WSAEventSelect(ptr->socket, ptr->hEvent, FD_READ | FD_WRITE | FD_CLOSE);
|
||||
#else
|
||||
ptr->hEvent = CreateFileDescriptorEvent(NULL, FALSE, FALSE, (int) ptr->socket, WINPR_FD_READ);
|
||||
|
||||
if (!ptr->hEvent)
|
||||
return 0;
|
||||
#endif
|
||||
/* WSAEventSelect automatically sets the socket in non-blocking mode */
|
||||
if (WSAEventSelect(ptr->socket, ptr->hEvent, FD_READ | FD_ACCEPT | FD_CLOSE))
|
||||
{
|
||||
WLog_ERR(TAG, "WSAEventSelect returned %08X", WSAGetLastError());
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
@ -693,7 +692,7 @@ char* freerdp_tcp_get_ip_address(int sockfd)
|
|||
return _strdup(ipAddress);
|
||||
}
|
||||
|
||||
int freerdp_uds_connect(const char* path)
|
||||
static int freerdp_uds_connect(const char* path)
|
||||
{
|
||||
#ifndef _WIN32
|
||||
int status;
|
||||
|
@ -744,265 +743,82 @@ BOOL freerdp_tcp_resolve_hostname(const char* hostname)
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL freerdp_tcp_connect_timeout(int sockfd, struct sockaddr* addr, socklen_t addrlen, int timeout)
|
||||
static BOOL freerdp_tcp_connect_timeout(rdpContext* context, int sockfd,
|
||||
struct sockaddr* addr,
|
||||
socklen_t addrlen, int timeout)
|
||||
{
|
||||
int status;
|
||||
HANDLE handles[2];
|
||||
int status = 0;
|
||||
int count = 0;
|
||||
u_long arg = 0;
|
||||
DWORD tout = (timeout) ? timeout * 1000 : INFINITE;
|
||||
|
||||
#ifndef _WIN32
|
||||
int flags;
|
||||
fd_set cfds;
|
||||
socklen_t optlen;
|
||||
struct timeval tv;
|
||||
|
||||
/* set socket in non-blocking mode */
|
||||
|
||||
flags = fcntl(sockfd, F_GETFL);
|
||||
|
||||
if (flags < 0)
|
||||
handles[count] = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||||
if (!handles[count])
|
||||
return FALSE;
|
||||
|
||||
fcntl(sockfd, F_SETFL, flags | O_NONBLOCK);
|
||||
|
||||
/* non-blocking tcp connect */
|
||||
|
||||
status = connect(sockfd, addr, addrlen);
|
||||
|
||||
if (status >= 0)
|
||||
return TRUE; /* connection success */
|
||||
|
||||
if (errno != EINPROGRESS)
|
||||
status = WSAEventSelect(sockfd, handles[count++], FD_READ | FD_WRITE | FD_CONNECT | FD_CLOSE);
|
||||
if (status < 0)
|
||||
{
|
||||
WLog_ERR(TAG, "WSAEventSelect failed with %lX", WSAGetLastError());
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
FD_ZERO(&cfds);
|
||||
FD_SET(sockfd, &cfds);
|
||||
handles[count++] = context->abortEvent;
|
||||
|
||||
tv.tv_sec = timeout;
|
||||
tv.tv_usec = 0;
|
||||
status = _connect(sockfd, addr, addrlen);
|
||||
if (status < 0)
|
||||
{
|
||||
status = WSAGetLastError();
|
||||
switch(status)
|
||||
{
|
||||
case WSAEINPROGRESS:
|
||||
case WSAEWOULDBLOCK:
|
||||
break;
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
status = _select(sockfd + 1, NULL, &cfds, NULL, &tv);
|
||||
status = WaitForMultipleObjects(count, handles, FALSE, tout);
|
||||
if (WAIT_OBJECT_0 != status)
|
||||
{
|
||||
if (status == WAIT_OBJECT_0 + 1)
|
||||
freerdp_set_last_error(context, FREERDP_ERROR_CONNECT_CANCELLED);
|
||||
|
||||
if (status != 1)
|
||||
return FALSE; /* connection timeout or error */
|
||||
|
||||
status = 0;
|
||||
optlen = sizeof(status);
|
||||
|
||||
if (getsockopt(sockfd, SOL_SOCKET, SO_ERROR, (void*) &status, &optlen) < 0)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (status != 0)
|
||||
status = recv(sockfd, NULL, 0, 0);
|
||||
if (status == SOCKET_ERROR)
|
||||
{
|
||||
if (WSAGetLastError() == WSAECONNRESET)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
status = WSAEventSelect(sockfd, handles[0], 0);
|
||||
CloseHandle(handles[0]);
|
||||
|
||||
if (status < 0)
|
||||
{
|
||||
WLog_ERR(TAG, "WSAEventSelect failed with %lX", WSAGetLastError());
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* set socket in blocking mode */
|
||||
|
||||
flags = fcntl(sockfd, F_GETFL);
|
||||
|
||||
if (flags < 0)
|
||||
if (_ioctlsocket(sockfd, FIONBIO, &arg) != 0)
|
||||
return FALSE;
|
||||
|
||||
fcntl(sockfd, F_SETFL, flags & ~O_NONBLOCK);
|
||||
|
||||
#else
|
||||
status = connect(sockfd, addr, addrlen);
|
||||
|
||||
if (status >= 0)
|
||||
return TRUE;
|
||||
|
||||
return FALSE;
|
||||
#endif
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#ifndef _WIN32
|
||||
|
||||
int freerdp_tcp_connect_multi(char** hostnames, UINT32* ports, int count, int port, int timeout)
|
||||
static int freerdp_tcp_connect_multi(rdpContext* context, char** hostnames,
|
||||
UINT32* ports, int count, int port,
|
||||
int timeout)
|
||||
{
|
||||
int index;
|
||||
int sindex;
|
||||
int status;
|
||||
int flags;
|
||||
int maxfds;
|
||||
fd_set cfds;
|
||||
int sockfd = -1;
|
||||
int* sockfds;
|
||||
char port_str[16];
|
||||
socklen_t optlen;
|
||||
struct timeval tv;
|
||||
struct addrinfo hints;
|
||||
struct addrinfo* addr;
|
||||
struct addrinfo* result;
|
||||
struct addrinfo** addrs;
|
||||
struct addrinfo** results;
|
||||
|
||||
sindex = -1;
|
||||
|
||||
sprintf_s(port_str, sizeof(port_str) - 1, "%u", port);
|
||||
|
||||
sockfds = (int*) calloc(count, sizeof(int));
|
||||
addrs = (struct addrinfo**) calloc(count, sizeof(struct addrinfo*));
|
||||
results = (struct addrinfo**) calloc(count, sizeof(struct addrinfo*));
|
||||
|
||||
for (index = 0; index < count; index++)
|
||||
{
|
||||
ZeroMemory(&hints, sizeof(hints));
|
||||
hints.ai_family = AF_UNSPEC;
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
|
||||
if (ports)
|
||||
sprintf_s(port_str, sizeof(port_str) - 1, "%u", ports[index]);
|
||||
|
||||
status = getaddrinfo(hostnames[index], port_str, &hints, &result);
|
||||
|
||||
if (status)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
addr = result;
|
||||
|
||||
if ((addr->ai_family == AF_INET6) && (addr->ai_next != 0))
|
||||
{
|
||||
while ((addr = addr->ai_next))
|
||||
{
|
||||
if (addr->ai_family == AF_INET)
|
||||
break;
|
||||
}
|
||||
|
||||
if (!addr)
|
||||
addr = result;
|
||||
}
|
||||
|
||||
sockfds[index] = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol);
|
||||
|
||||
if (sockfds[index] < 0)
|
||||
{
|
||||
freeaddrinfo(result);
|
||||
sockfds[index] = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
addrs[index] = addr;
|
||||
results[index] = result;
|
||||
}
|
||||
|
||||
maxfds = 0;
|
||||
FD_ZERO(&cfds);
|
||||
|
||||
for (index = 0; index < count; index++)
|
||||
{
|
||||
if (!sockfds[index])
|
||||
continue;
|
||||
|
||||
sockfd = sockfds[index];
|
||||
addr = addrs[index];
|
||||
|
||||
/* set socket in non-blocking mode */
|
||||
|
||||
flags = fcntl(sockfd, F_GETFL);
|
||||
|
||||
if (flags < 0)
|
||||
{
|
||||
sockfds[index] = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
fcntl(sockfd, F_SETFL, flags | O_NONBLOCK);
|
||||
|
||||
/* non-blocking tcp connect */
|
||||
|
||||
status = connect(sockfd, addr->ai_addr, addr->ai_addrlen);
|
||||
|
||||
if (status >= 0)
|
||||
{
|
||||
/* connection success */
|
||||
break;
|
||||
}
|
||||
|
||||
if (errno != EINPROGRESS)
|
||||
{
|
||||
sockfds[index] = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
FD_SET(sockfd, &cfds);
|
||||
|
||||
if (sockfd > maxfds)
|
||||
maxfds = sockfd;
|
||||
}
|
||||
|
||||
tv.tv_sec = timeout;
|
||||
tv.tv_usec = 0;
|
||||
|
||||
status = _select(maxfds + 1, NULL, &cfds, NULL, &tv);
|
||||
|
||||
for (index = 0; index < count; index++)
|
||||
{
|
||||
if (!sockfds[index])
|
||||
continue;
|
||||
|
||||
sockfd = sockfds[index];
|
||||
|
||||
if (FD_ISSET(sockfd, &cfds))
|
||||
{
|
||||
status = 0;
|
||||
optlen = sizeof(status);
|
||||
|
||||
if (getsockopt(sockfd, SOL_SOCKET, SO_ERROR, (void*) &status, &optlen) < 0)
|
||||
{
|
||||
sockfds[index] = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (status != 0)
|
||||
{
|
||||
sockfds[index] = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* set socket in blocking mode */
|
||||
|
||||
flags = fcntl(sockfd, F_GETFL);
|
||||
|
||||
if (flags < 0)
|
||||
{
|
||||
sockfds[index] = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
fcntl(sockfd, F_SETFL, flags & ~O_NONBLOCK);
|
||||
|
||||
sindex = index;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (sindex >= 0)
|
||||
{
|
||||
sockfd = sockfds[sindex];
|
||||
}
|
||||
|
||||
for (index = 0; index < count; index++)
|
||||
{
|
||||
if (results[index])
|
||||
freeaddrinfo(results[index]);
|
||||
}
|
||||
|
||||
free(addrs);
|
||||
free(results);
|
||||
free(sockfds);
|
||||
|
||||
return sockfd;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
int freerdp_tcp_connect_multi(char** hostnames, UINT32* ports, int count, int port, int timeout)
|
||||
{
|
||||
int index;
|
||||
int sindex;
|
||||
int status;
|
||||
SOCKET sockfd;
|
||||
SOCKET sockfd = -1;
|
||||
SOCKET* sockfds;
|
||||
HANDLE* events;
|
||||
DWORD waitStatus;
|
||||
|
@ -1013,12 +829,10 @@ int freerdp_tcp_connect_multi(char** hostnames, UINT32* ports, int count, int po
|
|||
struct addrinfo** addrs;
|
||||
struct addrinfo** results;
|
||||
|
||||
sindex = -1;
|
||||
|
||||
sprintf_s(port_str, sizeof(port_str) - 1, "%u", port);
|
||||
|
||||
sockfds = (SOCKET*) calloc(count, sizeof(SOCKET));
|
||||
events = (HANDLE*) calloc(count, sizeof(HANDLE));
|
||||
events = (HANDLE*) calloc(count + 1, sizeof(HANDLE));
|
||||
addrs = (struct addrinfo**) calloc(count, sizeof(struct addrinfo*));
|
||||
results = (struct addrinfo**) calloc(count, sizeof(struct addrinfo*));
|
||||
|
||||
|
@ -1083,8 +897,18 @@ int freerdp_tcp_connect_multi(char** hostnames, UINT32* ports, int count, int po
|
|||
addr = addrs[index];
|
||||
|
||||
/* set socket in non-blocking mode */
|
||||
events[index] = WSACreateEvent();
|
||||
if (!events[index])
|
||||
{
|
||||
WLog_ERR(TAG, "WSACreateEvent returned %08X", WSAGetLastError());
|
||||
continue;
|
||||
}
|
||||
|
||||
WSAEventSelect(sockfd, events[index], FD_READ | FD_WRITE | FD_CONNECT | FD_CLOSE);
|
||||
if (WSAEventSelect(sockfd, events[index], FD_READ | FD_WRITE | FD_CONNECT | FD_CLOSE))
|
||||
{
|
||||
WLog_ERR(TAG, "WSAEventSelect returned %08X", WSAGetLastError());
|
||||
continue;
|
||||
}
|
||||
|
||||
/* non-blocking tcp connect */
|
||||
|
||||
|
@ -1097,31 +921,47 @@ int freerdp_tcp_connect_multi(char** hostnames, UINT32* ports, int count, int po
|
|||
}
|
||||
}
|
||||
|
||||
waitStatus = WaitForMultipleObjects(count, events, FALSE, timeout * 1000);
|
||||
events[count] = context->abortEvent;
|
||||
|
||||
waitStatus = WaitForMultipleObjects(count + 1, events, FALSE, timeout * 1000);
|
||||
|
||||
sindex = waitStatus - WAIT_OBJECT_0;
|
||||
|
||||
for (index = 0; index < count; index++)
|
||||
{
|
||||
u_long arg = 0;
|
||||
|
||||
if (!sockfds[index])
|
||||
continue;
|
||||
|
||||
sockfd = sockfds[index];
|
||||
|
||||
/* set socket in blocking mode */
|
||||
if (WSAEventSelect(sockfd, NULL, 0))
|
||||
{
|
||||
WLog_ERR(TAG, "WSAEventSelect returned %08X", WSAGetLastError());
|
||||
continue;
|
||||
}
|
||||
|
||||
WSAEventSelect(sockfd, NULL, 0);
|
||||
if (_ioctlsocket(sockfd, FIONBIO, &arg))
|
||||
{
|
||||
WLog_ERR(TAG, "_ioctlsocket failed");
|
||||
}
|
||||
}
|
||||
|
||||
if (sindex >= 0)
|
||||
if ((sindex >= 0) && (sindex < count))
|
||||
{
|
||||
sockfd = sockfds[sindex];
|
||||
}
|
||||
|
||||
if (sindex == count)
|
||||
freerdp_set_last_error(context, FREERDP_ERROR_CONNECT_CANCELLED);
|
||||
|
||||
for (index = 0; index < count; index++)
|
||||
{
|
||||
if (results[index])
|
||||
freeaddrinfo(results[index]);
|
||||
CloseHandle(events[index]);
|
||||
}
|
||||
|
||||
free(addrs);
|
||||
|
@ -1132,8 +972,6 @@ int freerdp_tcp_connect_multi(char** hostnames, UINT32* ports, int count, int po
|
|||
return sockfd;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
BOOL freerdp_tcp_set_keep_alive_mode(int sockfd)
|
||||
{
|
||||
#ifndef _WIN32
|
||||
|
@ -1201,7 +1039,8 @@ BOOL freerdp_tcp_set_keep_alive_mode(int sockfd)
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
int freerdp_tcp_connect(rdpSettings* settings, const char* hostname, int port, int timeout)
|
||||
int freerdp_tcp_connect(rdpContext* context, rdpSettings* settings,
|
||||
const char* hostname, int port, int timeout)
|
||||
{
|
||||
int status;
|
||||
int sockfd;
|
||||
|
@ -1232,8 +1071,12 @@ int freerdp_tcp_connect(rdpSettings* settings, const char* hostname, int port, i
|
|||
{
|
||||
if (settings->TargetNetAddressCount > 0)
|
||||
{
|
||||
sockfd = freerdp_tcp_connect_multi(settings->TargetNetAddresses,
|
||||
settings->TargetNetPorts, settings->TargetNetAddressCount, port, timeout);
|
||||
sockfd = freerdp_tcp_connect_multi(
|
||||
context,
|
||||
settings->TargetNetAddresses,
|
||||
settings->TargetNetPorts,
|
||||
settings->TargetNetAddressCount,
|
||||
port, timeout);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1275,13 +1118,14 @@ int freerdp_tcp_connect(rdpSettings* settings, const char* hostname, int port, i
|
|||
|
||||
sockfd = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol);
|
||||
|
||||
if (sockfd < 0)
|
||||
if (sockfd < 0)
|
||||
{
|
||||
freeaddrinfo(result);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!freerdp_tcp_connect_timeout(sockfd, addr->ai_addr, addr->ai_addrlen, timeout))
|
||||
if (!freerdp_tcp_connect_timeout(context, sockfd, addr->ai_addr,
|
||||
addr->ai_addrlen, timeout))
|
||||
{
|
||||
freeaddrinfo(result);
|
||||
close(sockfd);
|
||||
|
@ -1340,5 +1184,11 @@ int freerdp_tcp_connect(rdpSettings* settings, const char* hostname, int port, i
|
|||
}
|
||||
}
|
||||
|
||||
if (WaitForSingleObject(context->abortEvent, 0) == WAIT_OBJECT_0)
|
||||
{
|
||||
close(sockfd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return sockfd;
|
||||
}
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
|
||||
#include <freerdp/types.h>
|
||||
#include <freerdp/settings.h>
|
||||
#include <freerdp/freerdp.h>
|
||||
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/synch.h>
|
||||
|
@ -60,6 +61,7 @@
|
|||
BIO_METHOD* BIO_s_simple_socket(void);
|
||||
BIO_METHOD* BIO_s_buffered_socket(void);
|
||||
|
||||
int freerdp_tcp_connect(rdpSettings* settings, const char* hostname, int port, int timeout);
|
||||
int freerdp_tcp_connect(rdpContext* context, rdpSettings* settings,
|
||||
const char* hostname, int port, int timeout);
|
||||
|
||||
#endif /* __TCP_H */
|
||||
|
|
|
@ -8,13 +8,24 @@ set(${MODULE_PREFIX}_TESTS
|
|||
TestVersion.c
|
||||
TestSettings.c)
|
||||
|
||||
if(WITH_SAMPLE AND WITH_SERVER)
|
||||
set(${MODULE_PREFIX}_TESTS
|
||||
${${MODULE_PREFIX}_TESTS}
|
||||
TestConnect.c)
|
||||
else()
|
||||
message("Skipping connection tests, requires WITH_SAMPLE and WITH_SERVER set!")
|
||||
endif()
|
||||
|
||||
create_test_sourcelist(${MODULE_PREFIX}_SRCS
|
||||
${${MODULE_PREFIX}_DRIVER}
|
||||
${${MODULE_PREFIX}_TESTS})
|
||||
|
||||
add_executable(${MODULE_NAME} ${${MODULE_PREFIX}_SRCS})
|
||||
|
||||
target_link_libraries(${MODULE_NAME} freerdp)
|
||||
add_definitions(-DTESTING_OUTPUT_DIRECTORY="${CMAKE_BINARY_DIR}")
|
||||
add_definitions(-DTESTING_SRC_DIRECTORY="${CMAKE_SOURCE_DIR}")
|
||||
|
||||
target_link_libraries(${MODULE_NAME} freerdp-client freerdp winpr)
|
||||
|
||||
set_target_properties(${MODULE_NAME} PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${TESTING_OUTPUT_DIRECTORY}")
|
||||
|
||||
|
|
|
@ -0,0 +1,261 @@
|
|||
#include <winpr/sysinfo.h>
|
||||
#include <winpr/path.h>
|
||||
#include <freerdp/freerdp.h>
|
||||
#include <freerdp/client/cmdline.h>
|
||||
|
||||
static HANDLE s_sync = NULL;
|
||||
|
||||
static int runInstance(int argc, char* argv[], freerdp** inst)
|
||||
{
|
||||
int rc = -1;
|
||||
|
||||
freerdp* instance = freerdp_new();
|
||||
if (!instance)
|
||||
goto finish;
|
||||
|
||||
if (inst)
|
||||
*inst = instance;
|
||||
|
||||
if (!freerdp_context_new(instance))
|
||||
goto finish;
|
||||
|
||||
if (freerdp_client_settings_parse_command_line(instance->settings, argc, argv, FALSE) < 0)
|
||||
goto finish;
|
||||
|
||||
if (freerdp_client_load_addins(instance->context->channels, instance->settings) != 1)
|
||||
goto finish;
|
||||
|
||||
if (s_sync)
|
||||
{
|
||||
if (!SetEvent(s_sync))
|
||||
goto finish;
|
||||
}
|
||||
|
||||
rc = 1;
|
||||
if (!freerdp_connect(instance))
|
||||
goto finish;
|
||||
|
||||
rc = 2;
|
||||
if (!freerdp_disconnect(instance))
|
||||
goto finish;
|
||||
|
||||
rc = 0;
|
||||
|
||||
finish:
|
||||
freerdp_context_free(instance);
|
||||
freerdp_free(instance);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int testTimeout(void)
|
||||
{
|
||||
DWORD start, end, diff;
|
||||
char* argv[] =
|
||||
{
|
||||
"test",
|
||||
"/v:192.0.2.1",
|
||||
NULL
|
||||
};
|
||||
|
||||
int rc;
|
||||
|
||||
start = GetTickCount();
|
||||
rc = runInstance(2, argv, NULL);
|
||||
end = GetTickCount();
|
||||
|
||||
if (rc != 1)
|
||||
return -1;
|
||||
|
||||
diff = end - start;
|
||||
if (diff > 16000)
|
||||
return -1;
|
||||
|
||||
if (diff < 14000)
|
||||
return -1;
|
||||
|
||||
printf("%s: Success!\n", __FUNCTION__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void* testThread(void* arg)
|
||||
{
|
||||
char* argv[] =
|
||||
{
|
||||
"test",
|
||||
"/v:192.0.2.1",
|
||||
NULL
|
||||
};
|
||||
|
||||
int rc;
|
||||
|
||||
rc = runInstance(2, argv, arg);
|
||||
|
||||
if (rc != 1)
|
||||
ExitThread(-1);
|
||||
|
||||
ExitThread(0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int testAbort(void)
|
||||
{
|
||||
DWORD status;
|
||||
DWORD start, end, diff;
|
||||
HANDLE thread;
|
||||
freerdp* instance = NULL;
|
||||
|
||||
s_sync = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||||
if (!s_sync)
|
||||
return -1;
|
||||
|
||||
start = GetTickCount();
|
||||
thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)testThread,
|
||||
&instance, 0, NULL);
|
||||
if (!thread)
|
||||
{
|
||||
CloseHandle(s_sync);
|
||||
s_sync = NULL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
WaitForSingleObject(s_sync, INFINITE);
|
||||
freerdp_abort_connect(instance);
|
||||
status = WaitForSingleObject(instance->context->abortEvent, 0);
|
||||
if (status != WAIT_OBJECT_0)
|
||||
{
|
||||
CloseHandle(s_sync);
|
||||
CloseHandle(thread);
|
||||
s_sync = NULL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
status = WaitForSingleObject(thread, 20000);
|
||||
end = GetTickCount();
|
||||
|
||||
CloseHandle(s_sync);
|
||||
CloseHandle(thread);
|
||||
s_sync = NULL;
|
||||
|
||||
diff = end - start;
|
||||
if (diff > 1000)
|
||||
return -1;
|
||||
|
||||
if (WAIT_OBJECT_0 != status)
|
||||
return -1;
|
||||
|
||||
printf("%s: Success!\n", __FUNCTION__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int testSuccess(void)
|
||||
{
|
||||
int rc;
|
||||
STARTUPINFO si;
|
||||
PROCESS_INFORMATION process;
|
||||
char* argv[] =
|
||||
{
|
||||
"test",
|
||||
"/v:127.0.0.1",
|
||||
"/cert-ignore",
|
||||
"/rfx",
|
||||
NULL
|
||||
};
|
||||
int argc = 4;
|
||||
char* path = TESTING_OUTPUT_DIRECTORY;
|
||||
char* wpath = TESTING_SRC_DIRECTORY;
|
||||
char* exe = GetCombinedPath(path, "server");
|
||||
char* wexe = GetCombinedPath(wpath, "server");
|
||||
|
||||
if (!exe || !wexe)
|
||||
{
|
||||
free(exe);
|
||||
free(wexe);
|
||||
return -2;
|
||||
}
|
||||
|
||||
path = GetCombinedPath(exe, "Sample");
|
||||
wpath = GetCombinedPath(wexe, "Sample");
|
||||
free(exe);
|
||||
free(wexe);
|
||||
|
||||
if (!path || !wpath)
|
||||
{
|
||||
free(path);
|
||||
free(wpath);
|
||||
return -2;
|
||||
}
|
||||
|
||||
exe = GetCombinedPath(path, "sfreerdp-server");
|
||||
|
||||
if (!exe)
|
||||
{
|
||||
free(path);
|
||||
free(wpath);
|
||||
return -2;
|
||||
}
|
||||
|
||||
printf("Sample Server: %s\n", exe);
|
||||
printf("Workspace: %s\n", wpath);
|
||||
if (!PathFileExistsA(exe))
|
||||
{
|
||||
free(path);
|
||||
free(wpath);
|
||||
free(exe);
|
||||
return -2;
|
||||
}
|
||||
|
||||
// Start sample server locally.
|
||||
memset(&si, 0, sizeof(si));
|
||||
si.cb = sizeof(si);
|
||||
if (!CreateProcessA(exe, exe, NULL, NULL, FALSE, 0, NULL,
|
||||
wpath, &si, &process))
|
||||
{
|
||||
free(exe);
|
||||
free(path);
|
||||
free(wpath);
|
||||
return -2;
|
||||
}
|
||||
|
||||
free(exe);
|
||||
free(path);
|
||||
free(wpath);
|
||||
|
||||
Sleep(1000);
|
||||
rc = runInstance(argc, argv, NULL);
|
||||
|
||||
if (!TerminateProcess(process.hProcess, 0))
|
||||
return -2;
|
||||
|
||||
WaitForSingleObject(process.hProcess, INFINITE);
|
||||
CloseHandle(process.hProcess);
|
||||
CloseHandle(process.hThread);
|
||||
|
||||
printf("%s: returned %d!\n", __FUNCTION__, rc);
|
||||
if (rc)
|
||||
return -1;
|
||||
|
||||
printf("%s: Success!\n", __FUNCTION__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int TestConnect(int argc, char* argv[])
|
||||
{
|
||||
/* Test connect to not existing server,
|
||||
* check if timeout is honored. */
|
||||
if (testTimeout())
|
||||
return -1;
|
||||
|
||||
/* Test connect to not existing server,
|
||||
* check if connection abort is working. */
|
||||
if (testAbort())
|
||||
return -1;
|
||||
|
||||
/* Test connect to existing server,
|
||||
* check if connection is working. */
|
||||
if (testSuccess())
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -204,6 +204,7 @@ BOOL transport_connect(rdpTransport* transport, const char* hostname, UINT16 por
|
|||
int sockfd;
|
||||
BOOL status = FALSE;
|
||||
rdpSettings* settings = transport->settings;
|
||||
rdpContext* context = transport->context;
|
||||
|
||||
transport->async = settings->AsyncTransport;
|
||||
|
||||
|
@ -256,7 +257,7 @@ BOOL transport_connect(rdpTransport* transport, const char* hostname, UINT16 por
|
|||
}
|
||||
else
|
||||
{
|
||||
sockfd = freerdp_tcp_connect(settings, hostname, port, timeout);
|
||||
sockfd = freerdp_tcp_connect(context, settings, hostname, port, timeout);
|
||||
|
||||
if (sockfd < 1)
|
||||
return FALSE;
|
||||
|
@ -750,20 +751,7 @@ int transport_check_fds(rdpTransport* transport)
|
|||
if (!transport)
|
||||
return -1;
|
||||
|
||||
if (BIO_get_event(transport->frontBio, &event) != 1)
|
||||
return -1;
|
||||
|
||||
/**
|
||||
* Loop through and read all available PDUs. Since multiple
|
||||
* PDUs can exist, it's important to deliver them all before
|
||||
* returning. Otherwise we run the risk of having a thread
|
||||
* wait for a socket to get signaled that data is available
|
||||
* (which may never happen).
|
||||
*/
|
||||
#ifdef _WIN32
|
||||
ResetEvent(event);
|
||||
#endif
|
||||
for (;;)
|
||||
while(!freerdp_shall_disconnect(transport->context->instance))
|
||||
{
|
||||
/**
|
||||
* Note: transport_read_pdu tries to read one PDU from
|
||||
|
|
|
@ -630,7 +630,9 @@ BOOL WSASetEvent(HANDLE hEvent)
|
|||
|
||||
BOOL WSAResetEvent(HANDLE hEvent)
|
||||
{
|
||||
return ResetEvent(hEvent);
|
||||
/* POSIX systems auto reset the socket,
|
||||
* if no more data is available. */
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL WSACloseEvent(HANDLE hEvent)
|
||||
|
@ -647,7 +649,7 @@ BOOL WSACloseEvent(HANDLE hEvent)
|
|||
|
||||
int WSAEventSelect(SOCKET s, WSAEVENT hEventObject, LONG lNetworkEvents)
|
||||
{
|
||||
u_long arg = lNetworkEvents ? 1 : 0;
|
||||
u_long arg = 1;
|
||||
ULONG mode = 0;
|
||||
|
||||
if (_ioctlsocket(s, FIONBIO, &arg) != 0)
|
||||
|
|
Loading…
Reference in New Issue