void WTSVirtualChannelManagerGetFileDescriptor(HANDLE hServer, void** fds, int* fds_count) { void* fd; WTSVirtualChannelManager* vcm = (WTSVirtualChannelManager*) hServer; fd = GetEventWaitObject(MessageQueue_Event(vcm->queue)); if (fd) { fds[*fds_count] = fd; (*fds_count)++; } #if 0 if (vcm->drdynvc_channel) { fd = GetEventWaitObject(vcm->drdynvc_channel->receiveEvent); if (fd) { fds[*fds_count] = fd; (*fds_count)++; } } #endif }
HANDLE freerdp_channels_get_event_handle(freerdp* instance) { HANDLE event = NULL; rdpChannels* channels; channels = instance->context->channels; event = MessageQueue_Event(channels->queue); return event; }
HANDLE freerdp_get_input_queue_event_handle(freerdp* instance) { HANDLE event = NULL; if (instance->input->queue) event = MessageQueue_Event(instance->input->queue); return event; }
/** * called only from main thread */ BOOL freerdp_channels_check_fds(rdpChannels* channels, freerdp* instance) { if (WaitForSingleObject(MessageQueue_Event(channels->queue), 0) == WAIT_OBJECT_0) { freerdp_channels_process_sync(channels, instance); } return TRUE; }
void* smartcard_context_thread(SMARTCARD_CONTEXT* pContext) { DWORD nCount; DWORD status; HANDLE hEvents[2]; wMessage message; SMARTCARD_DEVICE* smartcard; SMARTCARD_OPERATION* operation; smartcard = pContext->smartcard; nCount = 0; hEvents[nCount++] = MessageQueue_Event(pContext->IrpQueue); while (1) { status = WaitForMultipleObjects(nCount, hEvents, FALSE, INFINITE); if (WaitForSingleObject(MessageQueue_Event(pContext->IrpQueue), 0) == WAIT_OBJECT_0) { if (!MessageQueue_Peek(pContext->IrpQueue, &message, TRUE)) break; if (message.id == WMQ_QUIT) break; operation = (SMARTCARD_OPERATION*) message.wParam; if (operation) { status = smartcard_irp_device_control_call(smartcard, operation); Queue_Enqueue(smartcard->CompletedIrpQueue, (void*) operation->irp); free(operation); } } } ExitThread(0); return NULL; }
HANDLE freerdp_get_message_queue_event_handle(freerdp* instance, DWORD id) { HANDLE event = NULL; wMessageQueue* queue = NULL; queue = freerdp_get_message_queue(instance, id); if (queue) event = MessageQueue_Event(queue); return event; }
int freerdp_channels_process_pending_messages(freerdp* instance) { rdpChannels* channels; channels = instance->context->channels; if (WaitForSingleObject(MessageQueue_Event(channels->queue), 0) == WAIT_OBJECT_0) { return freerdp_channels_process_sync(channels, instance); } return TRUE; }
/** * called only from main thread */ BOOL freerdp_channels_get_fds(rdpChannels* channels, freerdp* instance, void** read_fds, int* read_count, void** write_fds, int* write_count) { void* pfd; pfd = GetEventWaitObject(MessageQueue_Event(channels->queue)); if (pfd) { read_fds[*read_count] = pfd; (*read_count)++; } return TRUE; }
int freerds_client_get_event_handles(rdsBackend* backend, HANDLE* events, DWORD* nCount) { rdsBackendConnector* connector = (rdsBackendConnector*) backend; if (connector) { if (connector->ServerQueue) { events[*nCount] = MessageQueue_Event(connector->ServerQueue); (*nCount)++; } } return 0; }
int freerds_client_check_event_handles(rdsBackend* backend) { int status = 0; rdsBackendConnector* connector = (rdsBackendConnector*) backend; if (!connector) return 0; while (WaitForSingleObject(MessageQueue_Event(connector->ServerQueue), 0) == WAIT_OBJECT_0) { status = freerds_message_server_queue_process_pending_messages(connector); } return status; }
BOOL WINAPI FreeRDP_WTSVirtualChannelQuery(HANDLE hChannelHandle, WTS_VIRTUAL_CLASS WtsVirtualClass, PVOID* ppBuffer, DWORD* pBytesReturned) { void* pfd; BOOL bval; void* fds[10]; HANDLE hEvent; int fds_count = 0; BOOL status = FALSE; rdpPeerChannel* channel = (rdpPeerChannel*) hChannelHandle; ZeroMemory(fds, sizeof(fds)); hEvent = MessageQueue_Event(channel->queue); switch ((UINT32) WtsVirtualClass) { case WTSVirtualFileHandle: pfd = GetEventWaitObject(hEvent); if (pfd) { fds[fds_count] = pfd; (fds_count)++; } *ppBuffer = malloc(sizeof(void*)); CopyMemory(*ppBuffer, &fds[0], sizeof(void*)); *pBytesReturned = sizeof(void*); status = TRUE; break; case WTSVirtualEventHandle: *ppBuffer = malloc(sizeof(HANDLE)); CopyMemory(*ppBuffer, &(hEvent), sizeof(HANDLE)); *pBytesReturned = sizeof(void*); status = TRUE; break; case WTSVirtualChannelReady: if (channel->channelType == RDP_PEER_CHANNEL_TYPE_SVC) { bval = TRUE; status = TRUE; } else { switch (channel->dvc_open_state) { case DVC_OPEN_STATE_NONE: bval = FALSE; status = TRUE; break; case DVC_OPEN_STATE_SUCCEEDED: bval = TRUE; status = TRUE; break; default: bval = FALSE; status = FALSE; break; } } *ppBuffer = malloc(sizeof(BOOL)); CopyMemory(*ppBuffer, &bval, sizeof(BOOL)); *pBytesReturned = sizeof(BOOL); break; default: break; } return status; }
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 void* smartcard_thread_func(void* arg) { IRP* irp; DWORD nCount; DWORD status; HANDLE hEvents[2]; wMessage message; SMARTCARD_DEVICE* smartcard = (SMARTCARD_DEVICE*) arg; nCount = 0; hEvents[nCount++] = MessageQueue_Event(smartcard->IrpQueue); hEvents[nCount++] = Queue_Event(smartcard->CompletedIrpQueue); while (1) { status = WaitForMultipleObjects(nCount, hEvents, FALSE, INFINITE); if (WaitForSingleObject(MessageQueue_Event(smartcard->IrpQueue), 0) == WAIT_OBJECT_0) { if (!MessageQueue_Peek(smartcard->IrpQueue, &message, TRUE)) break; if (message.id == WMQ_QUIT) { while (WaitForSingleObject(Queue_Event(smartcard->CompletedIrpQueue), 0) == WAIT_OBJECT_0) { irp = (IRP*) Queue_Dequeue(smartcard->CompletedIrpQueue); if (irp) { if (irp->thread) { WaitForSingleObject(irp->thread, INFINITE); CloseHandle(irp->thread); irp->thread = NULL; } smartcard_complete_irp(smartcard, irp); } } break; } irp = (IRP*) message.wParam; if (irp) { smartcard_process_irp(smartcard, irp); } } if (WaitForSingleObject(Queue_Event(smartcard->CompletedIrpQueue), 0) == WAIT_OBJECT_0) { irp = (IRP*) Queue_Dequeue(smartcard->CompletedIrpQueue); if (irp) { if (irp->thread) { WaitForSingleObject(irp->thread, INFINITE); CloseHandle(irp->thread); irp->thread = NULL; } smartcard_complete_irp(smartcard, irp); } } } ExitThread(0); return NULL; }
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; }
HANDLE WTSVirtualChannelManagerGetEventHandle(HANDLE hServer) { WTSVirtualChannelManager* vcm = (WTSVirtualChannelManager*) hServer; return MessageQueue_Event(vcm->queue); }
void* smartcard_context_thread(SMARTCARD_CONTEXT* pContext) { DWORD nCount; LONG status = 0; DWORD waitStatus; HANDLE hEvents[2]; wMessage message; SMARTCARD_DEVICE* smartcard; SMARTCARD_OPERATION* operation; UINT error = CHANNEL_RC_OK; smartcard = pContext->smartcard; nCount = 0; hEvents[nCount++] = MessageQueue_Event(pContext->IrpQueue); while (1) { waitStatus = WaitForMultipleObjects(nCount, hEvents, FALSE, INFINITE); if (waitStatus == WAIT_FAILED) { error = GetLastError(); WLog_ERR(TAG, "WaitForMultipleObjects failed with error %lu!", error); break; } waitStatus = WaitForSingleObject(MessageQueue_Event(pContext->IrpQueue), 0); if (waitStatus == WAIT_FAILED) { error = GetLastError(); WLog_ERR(TAG, "WaitForSingleObject failed with error %lu!", error); break; } if (waitStatus == WAIT_OBJECT_0) { if (!MessageQueue_Peek(pContext->IrpQueue, &message, TRUE)) { WLog_ERR(TAG, "MessageQueue_Peek failed!"); status = ERROR_INTERNAL_ERROR; break; } if (message.id == WMQ_QUIT) break; operation = (SMARTCARD_OPERATION*) message.wParam; if (operation) { if ((status = smartcard_irp_device_control_call(smartcard, operation))) { WLog_ERR(TAG, "smartcard_irp_device_control_call failed with error %lu", status); break; } if (!Queue_Enqueue(smartcard->CompletedIrpQueue, (void*) operation->irp)) { WLog_ERR(TAG, "Queue_Enqueue failed!"); status = ERROR_INTERNAL_ERROR; break; } free(operation); } } } if (status && smartcard->rdpcontext) setChannelError(smartcard->rdpcontext, error, "smartcard_context_thread reported an error"); ExitThread((DWORD)status); return NULL; }
static void* smartcard_thread_func(void* arg) { IRP* irp; DWORD nCount; DWORD status; HANDLE hEvents[2]; wMessage message; SMARTCARD_DEVICE* smartcard = (SMARTCARD_DEVICE*) arg; UINT error = CHANNEL_RC_OK; nCount = 0; hEvents[nCount++] = MessageQueue_Event(smartcard->IrpQueue); hEvents[nCount++] = Queue_Event(smartcard->CompletedIrpQueue); while (1) { status = WaitForMultipleObjects(nCount, hEvents, FALSE, INFINITE); if (status == WAIT_FAILED) { error = GetLastError(); WLog_ERR(TAG, "WaitForMultipleObjects failed with error %lu!", error); break; } status = WaitForSingleObject(MessageQueue_Event(smartcard->IrpQueue), 0); if (status == WAIT_FAILED) { error = GetLastError(); WLog_ERR(TAG, "WaitForSingleObject failed with error %lu!", error); break; } if (status == WAIT_OBJECT_0) { if (!MessageQueue_Peek(smartcard->IrpQueue, &message, TRUE)) { WLog_ERR(TAG, "MessageQueue_Peek failed!"); error = ERROR_INTERNAL_ERROR; break; } if (message.id == WMQ_QUIT) { while (1) { status = WaitForSingleObject(Queue_Event(smartcard->CompletedIrpQueue), 0); if (status == WAIT_FAILED) { error = GetLastError(); WLog_ERR(TAG, "WaitForSingleObject failed with error %lu!", error); goto out; } if (status == WAIT_TIMEOUT) break; irp = (IRP*) Queue_Dequeue(smartcard->CompletedIrpQueue); if (irp) { if (irp->thread) { status = WaitForSingleObject(irp->thread, INFINITE); if (status == WAIT_FAILED) { error = GetLastError(); WLog_ERR(TAG, "WaitForSingleObject failed with error %lu!", error); goto out; } CloseHandle(irp->thread); irp->thread = NULL; } if ((error = smartcard_complete_irp(smartcard, irp))) { WLog_ERR(TAG, "smartcard_complete_irp failed with error %lu!", error); goto out; } } } break; } irp = (IRP*) message.wParam; if (irp) { if ((error = smartcard_process_irp(smartcard, irp))) { WLog_ERR(TAG, "smartcard_process_irp failed with error %lu!", error); goto out; } } } status = WaitForSingleObject(Queue_Event(smartcard->CompletedIrpQueue), 0); if (status == WAIT_FAILED) { error = GetLastError(); WLog_ERR(TAG, "WaitForSingleObject failed with error %lu!", error); break; } if (status == WAIT_OBJECT_0) { irp = (IRP*) Queue_Dequeue(smartcard->CompletedIrpQueue); if (irp) { if (irp->thread) { status = WaitForSingleObject(irp->thread, INFINITE); if (status == WAIT_FAILED) { error = GetLastError(); WLog_ERR(TAG, "WaitForSingleObject failed with error %lu!", error); break; } CloseHandle(irp->thread); irp->thread = NULL; } if ((error = smartcard_complete_irp(smartcard, irp))) { if (error == CHANNEL_RC_NOT_CONNECTED) { error = CHANNEL_RC_OK; goto out; } WLog_ERR(TAG, "smartcard_complete_irp failed with error %lu!", error); goto out; } } } } out: if (error && smartcard->rdpcontext) setChannelError(smartcard->rdpcontext, error, "smartcard_thread_func reported an error"); ExitThread((DWORD)error); return NULL; }
void* x11_shadow_subsystem_thread(x11ShadowSubsystem* subsystem) { XEvent xevent; DWORD status; DWORD nCount; UINT64 cTime; DWORD dwTimeout; DWORD dwInterval; UINT64 frameTime; HANDLE events[32]; wMessage message; wMessagePipe* MsgPipe; MsgPipe = subsystem->MsgPipe; nCount = 0; events[nCount++] = subsystem->event; events[nCount++] = MessageQueue_Event(MsgPipe->In); subsystem->captureFrameRate = 16; dwInterval = 1000 / subsystem->captureFrameRate; frameTime = GetTickCount64() + dwInterval; while (1) { cTime = GetTickCount64(); dwTimeout = (cTime > frameTime) ? 0 : frameTime - cTime; status = WaitForMultipleObjects(nCount, events, FALSE, dwTimeout); if (WaitForSingleObject(MessageQueue_Event(MsgPipe->In), 0) == WAIT_OBJECT_0) { if (MessageQueue_Peek(MsgPipe->In, &message, TRUE)) { if (message.id == WMQ_QUIT) break; x11_shadow_subsystem_process_message(subsystem, &message); } } if (WaitForSingleObject(subsystem->event, 0) == WAIT_OBJECT_0) { XLockDisplay(subsystem->display); if (XEventsQueued(subsystem->display, QueuedAlready)) { XNextEvent(subsystem->display, &xevent); x11_shadow_handle_xevent(subsystem, &xevent); } XUnlockDisplay(subsystem->display); } if ((status == WAIT_TIMEOUT) || (GetTickCount64() > frameTime)) { x11_shadow_check_resize(subsystem); x11_shadow_screen_grab(subsystem); x11_shadow_query_cursor(subsystem, FALSE); dwInterval = 1000 / subsystem->captureFrameRate; frameTime += dwInterval; } } ExitThread(0); 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; }