static DWORD WINAPI wf_peer_main_loop(LPVOID lpParam) { int rcount; void* rfds[32]; wfPeerContext* context; freerdp_peer* client = (freerdp_peer*) lpParam; memset(rfds, 0, sizeof(rfds)); wf_peer_init(client); /* Initialize the real server settings here */ client->settings->cert_file = xstrdup("server.crt"); client->settings->privatekey_file = xstrdup("server.key"); client->PostConnect = wf_peer_post_connect; client->Activate = wf_peer_activate; client->input->SynchronizeEvent = wf_peer_synchronize_event; client->input->KeyboardEvent = wf_peer_keyboard_event; client->input->UnicodeKeyboardEvent = wf_peer_unicode_keyboard_event; client->input->MouseEvent = wf_peer_mouse_event; client->input->ExtendedMouseEvent = wf_peer_extended_mouse_event; client->Initialize(client); context = (wfPeerContext*) client->context; printf("We've got a client %s\n", client->local ? "(local)" : client->hostname); while (1) { rcount = 0; if (client->GetFileDescriptor(client, rfds, &rcount) != true) { printf("Failed to get FreeRDP file descriptor\n"); break; } if (client->CheckFileDescriptor(client) != true) { printf("Failed to check FreeRDP file descriptor\n"); break; } } printf("Client %s disconnected.\n", client->local ? "(local)" : client->hostname); client->Disconnect(client); freerdp_peer_context_free(client); freerdp_peer_free(client); return 0; }
DWORD WINAPI wf_peer_main_loop(LPVOID lpParam) { wfInfo* wfi; DWORD nCount; DWORD status; HANDLE handles[32]; rdpSettings* settings; wfPeerContext* context; freerdp_peer* client = (freerdp_peer*) lpParam; wf_peer_init(client); settings = client->settings; settings->RemoteFxCodec = TRUE; settings->ColorDepth = 32; settings->NSCodec = FALSE; settings->JpegCodec = FALSE; wf_peer_read_settings(client); client->PostConnect = wf_peer_post_connect; client->Activate = wf_peer_activate; client->Logon = wf_peer_logon; client->input->SynchronizeEvent = wf_peer_synchronize_event; client->input->KeyboardEvent = wf_peer_keyboard_event; client->input->UnicodeKeyboardEvent = wf_peer_unicode_keyboard_event; client->input->MouseEvent = wf_peer_mouse_event; client->input->ExtendedMouseEvent = wf_peer_extended_mouse_event; client->Initialize(client); context = (wfPeerContext*) client->context; if (context->socketClose) return 0; wfi = context->info; if (wfi->input_disabled == TRUE) { printf("client input is disabled\n"); client->input->KeyboardEvent = wf_peer_keyboard_event_dummy; client->input->UnicodeKeyboardEvent = wf_peer_unicode_keyboard_event_dummy; client->input->MouseEvent = wf_peer_mouse_event_dummy; client->input->ExtendedMouseEvent = wf_peer_extended_mouse_event_dummy; } context->socketEvent = CreateEvent(NULL, TRUE, FALSE, NULL); context->socketSemaphore = CreateSemaphore(NULL, 0, 1, NULL); context->socketThread = CreateThread(NULL, 0, wf_peer_socket_listener, client, 0, NULL); printf("We've got a client %s\n", client->local ? "(local)" : client->hostname); nCount = 0; handles[nCount++] = context->updateEvent; handles[nCount++] = context->socketEvent; while (1) { status = WaitForMultipleObjects(nCount, handles, FALSE, INFINITE); if ((status == WAIT_FAILED) || (status == WAIT_TIMEOUT)) { printf("WaitForMultipleObjects failed\n"); break; } if (WaitForSingleObject(context->updateEvent, 0) == 0) { if (client->activated) wf_update_peer_send(wfi, context); ResetEvent(context->updateEvent); ReleaseSemaphore(wfi->updateSemaphore, 1, NULL); } if (WaitForSingleObject(context->socketEvent, 0) == 0) { if (client->CheckFileDescriptor(client) != TRUE) { //printf("Failed to check peer file descriptor\n"); context->socketClose = TRUE; } ResetEvent(context->socketEvent); ReleaseSemaphore(context->socketSemaphore, 1, NULL); if (context->socketClose) break; } //force disconnect if(wfi->force_all_disconnect == TRUE) { printf("Forcing Disconnect -> "); break; } /* FIXME: we should wait on this, instead of calling it every time */ if (WTSVirtualChannelManagerCheckFileDescriptor(context->vcm) != TRUE) break; } printf("Client %s disconnected.\n", client->local ? "(local)" : client->hostname); if (WaitForSingleObject(context->updateEvent, 0) == 0) { ResetEvent(context->updateEvent); ReleaseSemaphore(wfi->updateSemaphore, 1, NULL); } wf_update_peer_deactivate(wfi, context); client->Disconnect(client); freerdp_peer_context_free(client); freerdp_peer_free(client); return 0; }
static void* test_peer_mainloop(void* arg) { int i; int fds; int max_fds; int rcount; void* rfds[32]; fd_set rfds_set; testPeerContext* context; freerdp_peer* client = (freerdp_peer*) arg; memset(rfds, 0, sizeof(rfds)); test_peer_init(client); /* Initialize the real server settings here */ client->settings->cert_file = xstrdup("server.crt"); client->settings->privatekey_file = xstrdup("server.key"); client->settings->nla_security = false; client->settings->rfx_codec = true; client->PostConnect = tf_peer_post_connect; client->Activate = tf_peer_activate; client->input->SynchronizeEvent = tf_peer_synchronize_event; client->input->KeyboardEvent = tf_peer_keyboard_event; client->input->UnicodeKeyboardEvent = tf_peer_unicode_keyboard_event; client->input->MouseEvent = tf_peer_mouse_event; client->input->ExtendedMouseEvent = tf_peer_extended_mouse_event; client->Initialize(client); context = (testPeerContext*) client->context; printf("We've got a client %s\n", client->hostname); while (1) { rcount = 0; if (client->GetFileDescriptor(client, rfds, &rcount) != true) { printf("Failed to get FreeRDP file descriptor\n"); break; } WTSVirtualChannelManagerGetFileDescriptor(context->vcm, rfds, &rcount); max_fds = 0; FD_ZERO(&rfds_set); for (i = 0; i < rcount; i++) { fds = (int)(long)(rfds[i]); if (fds > max_fds) max_fds = fds; FD_SET(fds, &rfds_set); } if (max_fds == 0) break; if (select(max_fds + 1, &rfds_set, NULL, NULL, NULL) == -1) { /* these are not really errors */ if (!((errno == EAGAIN) || (errno == EWOULDBLOCK) || (errno == EINPROGRESS) || (errno == EINTR))) /* signal occurred */ { printf("select failed\n"); break; } } if (client->CheckFileDescriptor(client) != true) break; if (WTSVirtualChannelManagerCheckFileDescriptor(context->vcm) != true) break; } printf("Client %s disconnected.\n", client->hostname); client->Disconnect(client); freerdp_peer_context_free(client); freerdp_peer_free(client); return NULL; }
static void* test_peer_mainloop(void* arg) { int i; int fds; int max_fds; int rcount; void* rfds[32]; fd_set rfds_set; testPeerContext* context; freerdp_peer* client = (freerdp_peer*) arg; test_peer_init(client); /* Initialize the real server settings here */ client->settings->CertificateFile = _strdup("server.crt"); client->settings->PrivateKeyFile = _strdup("server.key"); client->settings->NlaSecurity = FALSE; client->settings->RemoteFxCodec = TRUE; client->settings->ColorDepth = 32; client->settings->SuppressOutput = TRUE; client->settings->RefreshRect = TRUE; client->PostConnect = tf_peer_post_connect; client->Activate = tf_peer_activate; client->input->SynchronizeEvent = tf_peer_synchronize_event; client->input->KeyboardEvent = tf_peer_keyboard_event; client->input->UnicodeKeyboardEvent = tf_peer_unicode_keyboard_event; client->input->MouseEvent = tf_peer_mouse_event; client->input->ExtendedMouseEvent = tf_peer_extended_mouse_event; client->update->RefreshRect = tf_peer_refresh_rect; client->update->SuppressOutput = tf_peer_suppress_output; client->settings->MultifragMaxRequestSize = 0xFFFFFF; /* FIXME */ client->Initialize(client); context = (testPeerContext*) client->context; printf("We've got a client %s\n", client->local ? "(local)" : client->hostname); while (1) { rcount = 0; memset(rfds, 0, sizeof(rfds)); if (client->GetFileDescriptor(client, rfds, &rcount) != TRUE) { printf("Failed to get FreeRDP file descriptor\n"); break; } #ifndef _WIN32 /* winsock's select() only works with sockets ! */ WTSVirtualChannelManagerGetFileDescriptor(context->vcm, rfds, &rcount); #endif max_fds = 0; FD_ZERO(&rfds_set); for (i = 0; i < rcount; i++) { fds = (int)(long)(rfds[i]); if (fds > max_fds) max_fds = fds; FD_SET(fds, &rfds_set); } if (max_fds == 0) break; if (select(max_fds + 1, &rfds_set, NULL, NULL, NULL) == -1) { #ifdef _WIN32 /* error codes set by windows sockets are not made available through errno ! */ int wsa_error = WSAGetLastError(); if (!((wsa_error == WSAEWOULDBLOCK) || (wsa_error == WSAEINPROGRESS) || (wsa_error == WSAEINTR))) { printf("select failed (WSAGetLastError: %d)\n", wsa_error); break; } #else /* these are not really errors */ if (!((errno == EAGAIN) || (errno == EWOULDBLOCK) || (errno == EINPROGRESS) || (errno == EINTR))) /* signal occurred */ { printf("select failed (errno: %d)\n", errno); break; } #endif } if (client->CheckFileDescriptor(client) != TRUE) break; if (WTSVirtualChannelManagerCheckFileDescriptor(context->vcm) != TRUE) break; } printf("Client %s disconnected.\n", client->local ? "(local)" : client->hostname); client->Disconnect(client); freerdp_peer_context_free(client); freerdp_peer_free(client); return NULL; }
void* shadow_client_thread(rdpShadowClient* client) { DWORD status; DWORD nCount; wMessage message; wMessage pointerPositionMsg; wMessage pointerAlphaMsg; wMessage audioVolumeMsg; HANDLE events[32]; HANDLE ClientEvent; HANDLE ChannelEvent; void* UpdateSubscriber; HANDLE UpdateEvent; freerdp_peer* peer; rdpContext* context; rdpSettings* settings; rdpShadowServer* server; rdpShadowScreen* screen; rdpShadowEncoder* encoder; rdpShadowSubsystem* subsystem; wMessageQueue* MsgQueue = client->MsgQueue; server = client->server; screen = server->screen; encoder = client->encoder; subsystem = server->subsystem; context = (rdpContext*) client; peer = context->peer; settings = peer->settings; peer->Capabilities = shadow_client_capabilities; peer->PostConnect = shadow_client_post_connect; peer->Activate = shadow_client_activate; shadow_input_register_callbacks(peer->input); peer->Initialize(peer); peer->update->RefreshRect = (pRefreshRect)shadow_client_refresh_rect; peer->update->SuppressOutput = (pSuppressOutput)shadow_client_suppress_output; peer->update->SurfaceFrameAcknowledge = (pSurfaceFrameAcknowledge)shadow_client_surface_frame_acknowledge; if ((!client->vcm) || (!subsystem->updateEvent)) goto out; UpdateSubscriber = shadow_multiclient_get_subscriber(subsystem->updateEvent); if (!UpdateSubscriber) goto out; UpdateEvent = shadow_multiclient_getevent(UpdateSubscriber); ClientEvent = peer->GetEventHandle(peer); ChannelEvent = WTSVirtualChannelManagerGetEventHandle(client->vcm); while (1) { nCount = 0; events[nCount++] = UpdateEvent; events[nCount++] = ClientEvent; events[nCount++] = ChannelEvent; events[nCount++] = MessageQueue_Event(MsgQueue); status = WaitForMultipleObjects(nCount, events, FALSE, INFINITE); if (WaitForSingleObject(UpdateEvent, 0) == WAIT_OBJECT_0) { if (client->activated) { int index; int numRects = 0; const RECTANGLE_16* rects; int width, height; /* Check resize */ shadow_client_calc_desktop_size(server, &width, &height); if (settings->DesktopWidth != (UINT32)width || settings->DesktopHeight != (UINT32)height) { /* Screen size changed, do resize */ settings->DesktopWidth = width; settings->DesktopHeight = height; /** * Unset client activated flag to avoid sending update message during * resize. DesktopResize will reactive the client and * shadow_client_activate would be invoked later. */ client->activated = FALSE; /* Send Resize */ peer->update->DesktopResize(peer->update->context); // update_send_desktop_resize /* Clear my invalidRegion. shadow_client_activate refreshes fullscreen */ region16_clear(&(client->invalidRegion)); WLog_ERR(TAG, "Client from %s is resized (%dx%d@%d)", peer->hostname, settings->DesktopWidth, settings->DesktopHeight, settings->ColorDepth); } else { /* Send frame */ rects = region16_rects(&(subsystem->invalidRegion), &numRects); for (index = 0; index < numRects; index++) { region16_union_rect(&(client->invalidRegion), &(client->invalidRegion), &rects[index]); } shadow_client_send_surface_update(client); } } /* * The return value of shadow_multiclient_consume is whether or not the subscriber really consumes the event. * It's not cared currently. */ (void)shadow_multiclient_consume(UpdateSubscriber); } if (WaitForSingleObject(ClientEvent, 0) == WAIT_OBJECT_0) { if (!peer->CheckFileDescriptor(peer)) { WLog_ERR(TAG, "Failed to check FreeRDP file descriptor"); break; } } if (WaitForSingleObject(ChannelEvent, 0) == WAIT_OBJECT_0) { if (!WTSVirtualChannelManagerCheckFileDescriptor(client->vcm)) { WLog_ERR(TAG, "WTSVirtualChannelManagerCheckFileDescriptor failure"); break; } } if (WaitForSingleObject(MessageQueue_Event(MsgQueue), 0) == WAIT_OBJECT_0) { /* Drain messages. Pointer update could be accumulated. */ pointerPositionMsg.id = 0; pointerPositionMsg.Free= NULL; pointerAlphaMsg.id = 0; pointerAlphaMsg.Free = NULL; audioVolumeMsg.id = 0; audioVolumeMsg.Free = NULL; while (MessageQueue_Peek(MsgQueue, &message, TRUE)) { if (message.id == WMQ_QUIT) { break; } switch(message.id) { case SHADOW_MSG_OUT_POINTER_POSITION_UPDATE_ID: /* Abandon previous message */ shadow_client_free_queued_message(&pointerPositionMsg); CopyMemory(&pointerPositionMsg, &message, sizeof(wMessage)); break; case SHADOW_MSG_OUT_POINTER_ALPHA_UPDATE_ID: /* Abandon previous message */ shadow_client_free_queued_message(&pointerAlphaMsg); CopyMemory(&pointerAlphaMsg, &message, sizeof(wMessage)); break; case SHADOW_MSG_OUT_AUDIO_OUT_VOLUME_ID: /* Abandon previous message */ shadow_client_free_queued_message(&audioVolumeMsg); CopyMemory(&audioVolumeMsg, &message, sizeof(wMessage)); break; default: shadow_client_subsystem_process_message(client, &message); break; } } if (message.id == WMQ_QUIT) { /* Release stored message */ shadow_client_free_queued_message(&pointerPositionMsg); shadow_client_free_queued_message(&pointerAlphaMsg); shadow_client_free_queued_message(&audioVolumeMsg); break; } else { /* Process accumulated messages if needed */ if (pointerPositionMsg.id) { shadow_client_subsystem_process_message(client, &pointerPositionMsg); } if (pointerAlphaMsg.id) { shadow_client_subsystem_process_message(client, &pointerAlphaMsg); } if (audioVolumeMsg.id) { shadow_client_subsystem_process_message(client, &audioVolumeMsg); } } } } /* Free channels early because we establish channels in post connect */ shadow_client_channels_free(client); if (UpdateSubscriber) { shadow_multiclient_release_subscriber(UpdateSubscriber); UpdateSubscriber = NULL; } if (peer->connected && subsystem->ClientDisconnect) { subsystem->ClientDisconnect(subsystem, client); } out: peer->Disconnect(peer); freerdp_peer_context_free(peer); freerdp_peer_free(peer); ExitThread(0); return NULL; }
static BOOL freerdp_listener_check_fds(freerdp_listener* instance) { int i; void* sin_addr; int peer_sockfd; freerdp_peer* client = NULL; 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 }; BOOL peer_accepted; if (listener->num_sockfds < 1) return FALSE; 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_accepted = FALSE; if (peer_sockfd == -1) { #ifdef _WIN32 int wsa_error = WSAGetLastError(); /* No data available */ if (wsa_error == WSAEWOULDBLOCK) continue; #else if (errno == EAGAIN || errno == EWOULDBLOCK) continue; #endif WLog_DBG(TAG, "accept"); free(client); return FALSE; } client = freerdp_peer_new(peer_sockfd); if (!client) { closesocket((SOCKET) peer_sockfd); return FALSE; } sin_addr = NULL; if (peer_addr.ss_family == AF_INET) { sin_addr = &(((struct sockaddr_in*) &peer_addr)->sin_addr); if ((*(UINT32*) sin_addr) == 0x0100007f) client->local = TRUE; } else if (peer_addr.ss_family == AF_INET6) { sin_addr = &(((struct sockaddr_in6*) &peer_addr)->sin6_addr); if (memcmp(sin_addr, localhost6_bytes, 16) == 0) client->local = TRUE; } #ifndef _WIN32 else if (peer_addr.ss_family == AF_UNIX) client->local = TRUE; #endif if (sin_addr) inet_ntop(peer_addr.ss_family, sin_addr, client->hostname, sizeof(client->hostname)); IFCALLRET(instance->PeerAccepted, peer_accepted, instance, client); if (!peer_accepted) { WLog_ERR(TAG, "PeerAccepted callback failed"); closesocket((SOCKET) peer_sockfd); freerdp_peer_free(client); } } return TRUE; }
void* freerds_connection_main_thread(void* arg) { DWORD status; DWORD nCount; HANDLE events[32]; HANDLE ClientEvent; HANDLE ChannelEvent; HANDLE LocalTermEvent; HANDLE GlobalTermEvent; HANDLE NotificationEvent; rdsConnection* connection; rdpSettings* settings; rdsBackendConnector* connector = NULL; freerdp_peer* client = (freerdp_peer*) arg; BOOL disconnected = FALSE; #ifndef WIN32 sigset_t set; int ret; #endif fprintf(stderr, "We've got a client %s\n", client->hostname); connection = (rdsConnection*) client->context; settings = client->settings; app_context_add_connection(connection); freerds_generate_certificate(settings); settings->RdpSecurity = FALSE; settings->TlsSecurity = TRUE; /** * Disable NLA Security for now. * TODO: make this a configurable option. */ settings->NlaSecurity = FALSE; client->Capabilities = freerds_peer_capabilities; client->PostConnect = freerds_peer_post_connect; client->Activate = freerds_peer_activate; client->Initialize(client); freerds_input_register_callbacks(client->input); client->update->SurfaceFrameAcknowledge = freerds_update_frame_acknowledge; client->update->SuppressOutput = freerds_suppress_output; ClientEvent = client->GetEventHandle(client); ChannelEvent = WTSVirtualChannelManagerGetEventHandle(connection->vcm); GlobalTermEvent = g_get_term_event(); LocalTermEvent = connection->TermEvent; NotificationEvent = MessageQueue_Event(connection->notifications); #ifndef WIN32 sigemptyset(&set); sigaddset(&set, SIGPIPE); ret = pthread_sigmask(SIG_BLOCK, &set, NULL); if (0 != ret) fprintf(stderr, "couldn't block SIGPIPE\n"); #endif while (1) { nCount = 0; events[nCount++] = ClientEvent; events[nCount++] = ChannelEvent; events[nCount++] = GlobalTermEvent; events[nCount++] = LocalTermEvent; events[nCount++] = NotificationEvent; if (client->activated) { connector = (rdsBackendConnector*) connection->connector; if (connector && connector->GetEventHandles) connector->GetEventHandles((rdsBackend *)connector, events, &nCount); } status = WaitForMultipleObjects(nCount, events, FALSE, INFINITE); if (WaitForSingleObject(GlobalTermEvent, 0) == WAIT_OBJECT_0) { fprintf(stderr, "GlobalTermEvent\n"); break; } if (WaitForSingleObject(LocalTermEvent, 0) == WAIT_OBJECT_0) { fprintf(stderr, "LocalTermEvent\n"); break; } if (WaitForSingleObject(ClientEvent, 0) == WAIT_OBJECT_0) { if (client->CheckFileDescriptor(client) != TRUE) { fprintf(stderr, "Failed to check freerdp file descriptor\n"); break; } } if (WaitForSingleObject(ChannelEvent, 0) == WAIT_OBJECT_0) { if (WTSVirtualChannelManagerCheckFileDescriptor(connection->vcm) != TRUE) { fprintf(stderr, "WTSVirtualChannelManagerCheckFileDescriptor failure\n"); break; } } if (client->activated) { if (connector && connector->CheckEventHandles) { if (connector->CheckEventHandles((rdsBackend *)connector) < 0) { fprintf(stderr, "ModuleClient->CheckEventHandles failure\n"); break; } } } if (WaitForSingleObject(NotificationEvent, 0) == WAIT_OBJECT_0) { wMessage message; MessageQueue_Peek(connection->notifications, (void *)(&message), TRUE); if (!freerds_client_process_notification(connection, &message)) break; } } fprintf(stderr, "Client %s disconnected.\n", client->hostname); if (connection->connector) { freerds_connector_free(connection->connector); connection->connector = 0; freerds_icp_DisconnectUserSession(connection->id, &disconnected); } client->Disconnect(client); app_context_remove_connection(connection->id); freerdp_peer_context_free(client); freerdp_peer_free(client); return NULL; }
static void* test_peer_mainloop(void* arg) { HANDLE handles[32]; DWORD count; DWORD status; testPeerContext* context; freerdp_peer* client = (freerdp_peer*) arg; if (!test_peer_init(client)) { freerdp_peer_free(client); return NULL; } /* Initialize the real server settings here */ client->settings->CertificateFile = _strdup("server.crt"); client->settings->PrivateKeyFile = _strdup("server.key"); client->settings->RdpKeyFile = _strdup("server.key"); client->settings->RdpSecurity = TRUE; client->settings->TlsSecurity = TRUE; client->settings->NlaSecurity = FALSE; client->settings->EncryptionLevel = ENCRYPTION_LEVEL_CLIENT_COMPATIBLE; /* client->settings->EncryptionLevel = ENCRYPTION_LEVEL_HIGH; */ /* client->settings->EncryptionLevel = ENCRYPTION_LEVEL_LOW; */ /* client->settings->EncryptionLevel = ENCRYPTION_LEVEL_FIPS; */ client->settings->RemoteFxCodec = TRUE; client->settings->ColorDepth = 32; client->settings->SuppressOutput = TRUE; client->settings->RefreshRect = TRUE; client->PostConnect = tf_peer_post_connect; client->Activate = tf_peer_activate; client->input->SynchronizeEvent = tf_peer_synchronize_event; client->input->KeyboardEvent = tf_peer_keyboard_event; client->input->UnicodeKeyboardEvent = tf_peer_unicode_keyboard_event; client->input->MouseEvent = tf_peer_mouse_event; client->input->ExtendedMouseEvent = tf_peer_extended_mouse_event; client->update->RefreshRect = tf_peer_refresh_rect; client->update->SuppressOutput = tf_peer_suppress_output; client->settings->MultifragMaxRequestSize = 0xFFFFFF; /* FIXME */ client->Initialize(client); context = (testPeerContext*) client->context; WLog_INFO(TAG, "We've got a client %s", client->local ? "(local)" : client->hostname); while (1) { count = 0; handles[count++] = client->GetEventHandle(client); handles[count++] = WTSVirtualChannelManagerGetEventHandle(context->vcm); status = WaitForMultipleObjects(count, handles, FALSE, INFINITE); if (status == WAIT_FAILED) { WLog_ERR(TAG, "WaitForMultipleObjects failed (errno: %d)", errno); break; } if (client->CheckFileDescriptor(client) != TRUE) break; if (WTSVirtualChannelManagerCheckFileDescriptor(context->vcm) != TRUE) break; } WLog_INFO(TAG, "Client %s disconnected.", client->local ? "(local)" : client->hostname); client->Disconnect(client); freerdp_peer_context_free(client); freerdp_peer_free(client); return NULL; }
static void* shadow_client_thread(rdpShadowClient* client) { DWORD status; DWORD nCount; wMessage message; wMessage pointerPositionMsg; wMessage pointerAlphaMsg; wMessage audioVolumeMsg; HANDLE events[32]; HANDLE ClientEvent; HANDLE ChannelEvent; void* UpdateSubscriber; HANDLE UpdateEvent; freerdp_peer* peer; rdpContext* context; rdpSettings* settings; rdpShadowServer* server; rdpShadowScreen* screen; rdpShadowEncoder* encoder; rdpShadowSubsystem* subsystem; wMessageQueue* MsgQueue = client->MsgQueue; /* This should only be visited in client thread */ SHADOW_GFX_STATUS gfxstatus; gfxstatus.gfxOpened = FALSE; gfxstatus.gfxSurfaceCreated = FALSE; server = client->server; screen = server->screen; encoder = client->encoder; subsystem = server->subsystem; context = (rdpContext*) client; peer = context->peer; settings = peer->settings; peer->Capabilities = shadow_client_capabilities; peer->PostConnect = shadow_client_post_connect; peer->Activate = shadow_client_activate; peer->Logon = shadow_client_logon; shadow_input_register_callbacks(peer->input); peer->Initialize(peer); peer->update->RefreshRect = (pRefreshRect)shadow_client_refresh_rect; peer->update->SuppressOutput = (pSuppressOutput)shadow_client_suppress_output; peer->update->SurfaceFrameAcknowledge = (pSurfaceFrameAcknowledge)shadow_client_surface_frame_acknowledge; if ((!client->vcm) || (!subsystem->updateEvent)) goto out; UpdateSubscriber = shadow_multiclient_get_subscriber(subsystem->updateEvent); if (!UpdateSubscriber) goto out; UpdateEvent = shadow_multiclient_getevent(UpdateSubscriber); ClientEvent = peer->GetEventHandle(peer); ChannelEvent = WTSVirtualChannelManagerGetEventHandle(client->vcm); while (1) { nCount = 0; events[nCount++] = UpdateEvent; events[nCount++] = ClientEvent; events[nCount++] = ChannelEvent; events[nCount++] = MessageQueue_Event(MsgQueue); status = WaitForMultipleObjects(nCount, events, FALSE, INFINITE); if (WaitForSingleObject(UpdateEvent, 0) == WAIT_OBJECT_0) { /* The UpdateEvent means to start sending current frame. It is * triggered from subsystem implementation and it should ensure * that the screen and primary surface meta data (width, height, * scanline, invalid region, etc) is not changed until it is reset * (at shadow_multiclient_consume). As best practice, subsystem * implementation should invoke shadow_subsystem_frame_update which * triggers the event and then wait for completion */ if (client->activated && !client->suppressOutput) { /* Send screen update or resize to this client */ /* Check resize */ if (shadow_client_recalc_desktop_size(client)) { /* Screen size changed, do resize */ if (!shadow_client_send_resize(client, &gfxstatus)) { WLog_ERR(TAG, "Failed to send resize message"); break; } } else { /* Send frame */ if (!shadow_client_send_surface_update(client, &gfxstatus)) { WLog_ERR(TAG, "Failed to send surface update"); break; } } } else { /* Our client don't receive graphic updates. Just save the invalid region */ if (!shadow_client_no_surface_update(client, &gfxstatus)) { WLog_ERR(TAG, "Failed to handle surface update"); break; } } /* * The return value of shadow_multiclient_consume is whether or not * the subscriber really consumes the event. It's not cared currently. */ (void)shadow_multiclient_consume(UpdateSubscriber); } if (WaitForSingleObject(ClientEvent, 0) == WAIT_OBJECT_0) { if (!peer->CheckFileDescriptor(peer)) { WLog_ERR(TAG, "Failed to check FreeRDP file descriptor"); break; } if (WTSVirtualChannelManagerIsChannelJoined(client->vcm, "drdynvc")) { /* Dynamic channel status may have been changed after processing */ if (WTSVirtualChannelManagerGetDrdynvcState(client->vcm) == DRDYNVC_STATE_NONE) { /* Call this routine to Initialize drdynvc channel */ if (!WTSVirtualChannelManagerCheckFileDescriptor(client->vcm)) { WLog_ERR(TAG, "Failed to initialize drdynvc channel"); break; } } else if (WTSVirtualChannelManagerGetDrdynvcState(client->vcm) == DRDYNVC_STATE_READY) { /* Init RDPGFX dynamic channel */ if (settings->SupportGraphicsPipeline && client->rdpgfx && !gfxstatus.gfxOpened) { if (!client->rdpgfx->Open(client->rdpgfx)) { WLog_WARN(TAG, "Failed to open GraphicsPipeline"); settings->SupportGraphicsPipeline = FALSE; } client->rdpgfx->FrameAcknowledge = shadow_client_rdpgfx_frame_acknowledge; client->rdpgfx->QoeFrameAcknowledge = shadow_client_rdpgfx_qoe_frame_acknowledge; gfxstatus.gfxOpened = TRUE; WLog_INFO(TAG, "Gfx Pipeline Opened"); } } } } if (WaitForSingleObject(ChannelEvent, 0) == WAIT_OBJECT_0) { if (!WTSVirtualChannelManagerCheckFileDescriptor(client->vcm)) { WLog_ERR(TAG, "WTSVirtualChannelManagerCheckFileDescriptor failure"); break; } } if (WaitForSingleObject(MessageQueue_Event(MsgQueue), 0) == WAIT_OBJECT_0) { /* Drain messages. Pointer update could be accumulated. */ pointerPositionMsg.id = 0; pointerPositionMsg.Free= NULL; pointerAlphaMsg.id = 0; pointerAlphaMsg.Free = NULL; audioVolumeMsg.id = 0; audioVolumeMsg.Free = NULL; while (MessageQueue_Peek(MsgQueue, &message, TRUE)) { if (message.id == WMQ_QUIT) { break; } switch(message.id) { case SHADOW_MSG_OUT_POINTER_POSITION_UPDATE_ID: /* Abandon previous message */ shadow_client_free_queued_message(&pointerPositionMsg); CopyMemory(&pointerPositionMsg, &message, sizeof(wMessage)); break; case SHADOW_MSG_OUT_POINTER_ALPHA_UPDATE_ID: /* Abandon previous message */ shadow_client_free_queued_message(&pointerAlphaMsg); CopyMemory(&pointerAlphaMsg, &message, sizeof(wMessage)); break; case SHADOW_MSG_OUT_AUDIO_OUT_VOLUME_ID: /* Abandon previous message */ shadow_client_free_queued_message(&audioVolumeMsg); CopyMemory(&audioVolumeMsg, &message, sizeof(wMessage)); break; default: shadow_client_subsystem_process_message(client, &message); break; } } if (message.id == WMQ_QUIT) { /* Release stored message */ shadow_client_free_queued_message(&pointerPositionMsg); shadow_client_free_queued_message(&pointerAlphaMsg); shadow_client_free_queued_message(&audioVolumeMsg); break; } else { /* Process accumulated messages if needed */ if (pointerPositionMsg.id) { shadow_client_subsystem_process_message(client, &pointerPositionMsg); } if (pointerAlphaMsg.id) { shadow_client_subsystem_process_message(client, &pointerAlphaMsg); } if (audioVolumeMsg.id) { shadow_client_subsystem_process_message(client, &audioVolumeMsg); } } } } /* Free channels early because we establish channels in post connect */ if (gfxstatus.gfxOpened) { if (gfxstatus.gfxSurfaceCreated) { if (!shadow_client_rdpgfx_release_surface(client)) WLog_WARN(TAG, "GFX release surface failure!"); } (void)client->rdpgfx->Close(client->rdpgfx); } shadow_client_channels_free(client); if (UpdateSubscriber) { shadow_multiclient_release_subscriber(UpdateSubscriber); UpdateSubscriber = NULL; } if (peer->connected && subsystem->ClientDisconnect) { subsystem->ClientDisconnect(subsystem, client); } out: peer->Disconnect(peer); freerdp_peer_context_free(peer); freerdp_peer_free(peer); ExitThread(0); return NULL; }