From 00ace94b946dd5aac658ab2679fdbce0e21666d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Mon, 10 Feb 2014 23:13:29 -0500 Subject: [PATCH] libfreerdp-channels: start consolidating channels client code with core --- channels/client/CMakeLists.txt | 8 +- channels/client/channels.c | 837 ------------------------- channels/client/channels.h | 122 ---- channels/client/init.c | 135 ---- channels/client/init.h | 28 - channels/client/open.c | 103 ---- channels/client/open.h | 30 - libfreerdp/core/channel.c | 1051 +++++++++++++++++++++++++++++++- 8 files changed, 1030 insertions(+), 1284 deletions(-) delete mode 100644 channels/client/channels.c delete mode 100644 channels/client/channels.h delete mode 100644 channels/client/init.c delete mode 100644 channels/client/init.h delete mode 100644 channels/client/open.c delete mode 100644 channels/client/open.h diff --git a/channels/client/CMakeLists.txt b/channels/client/CMakeLists.txt index fc42466bb..21c04fc1f 100644 --- a/channels/client/CMakeLists.txt +++ b/channels/client/CMakeLists.txt @@ -22,13 +22,7 @@ set(${MODULE_PREFIX}_SRCS ${CMAKE_CURRENT_BINARY_DIR}/tables.c ${CMAKE_CURRENT_SOURCE_DIR}/tables.h ${CMAKE_CURRENT_SOURCE_DIR}/addin.c - ${CMAKE_CURRENT_SOURCE_DIR}/addin.h - ${CMAKE_CURRENT_SOURCE_DIR}/init.c - ${CMAKE_CURRENT_SOURCE_DIR}/init.h - ${CMAKE_CURRENT_SOURCE_DIR}/open.c - ${CMAKE_CURRENT_SOURCE_DIR}/open.h - ${CMAKE_CURRENT_SOURCE_DIR}/channels.c - ${CMAKE_CURRENT_SOURCE_DIR}/channels.h) + ${CMAKE_CURRENT_SOURCE_DIR}/addin.h) list(REMOVE_DUPLICATES CHANNEL_STATIC_CLIENT_ENTRIES) diff --git a/channels/client/channels.c b/channels/client/channels.c deleted file mode 100644 index 4380a538c..000000000 --- a/channels/client/channels.c +++ /dev/null @@ -1,837 +0,0 @@ -/** - * FreeRDP: A Remote Desktop Protocol Implementation - * Client Channels - * - * Copyright 2009-2011 Jay Sorg - * Copyright 2010-2011 Vic Lee - * Copyright 2012 Marc-Andre Moreau - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include "addin.h" -#include "init.h" -#include "open.h" - -#include "channels.h" - -/** - * MS compatible plugin interface - * reference: - * http://msdn.microsoft.com/en-us/library/aa383580.aspx - * - * Notes on threads: - * Many virtual channel plugins are built using threads. - * Non main threads may call MyVirtualChannelOpen, - * MyVirtualChannelClose, or MyVirtualChannelWrite. - * Since the plugin's VirtualChannelEntry function is called - * from the main thread, MyVirtualChannelInit has to be called - * from the main thread. - */ - -/** - * The current channel manager reference passes from VirtualChannelEntry to - * VirtualChannelInit for the pInitHandle. - */ - -void* g_pInterface; -CHANNEL_INIT_DATA g_ChannelInitData; - -static wArrayList* g_ChannelsList = NULL; - -/* To generate unique sequence for all open handles */ -int g_open_handle_sequence = 1; - -/* For locking the global resources */ -static CRITICAL_SECTION g_channels_lock; - -rdpChannels* freerdp_channels_find_by_open_handle(int OpenHandle, int* pindex) -{ - int i, j; - BOOL found = FALSE; - rdpChannels* channels = NULL; - - ArrayList_Lock(g_ChannelsList); - - i = j = 0; - channels = (rdpChannels*) ArrayList_GetItem(g_ChannelsList, i++); - - while (channels) - { - for (j = 0; j < channels->openDataCount; j++) - { - if (channels->openDataList[j].OpenHandle == OpenHandle) - { - *pindex = j; - found = TRUE; - break; - } - } - - if (found) - break; - - channels = (rdpChannels*) ArrayList_GetItem(g_ChannelsList, i++); - } - - ArrayList_Unlock(g_ChannelsList); - - return (found) ? channels : NULL; -} - -rdpChannels* freerdp_channels_find_by_instance(freerdp* instance) -{ - int index; - BOOL found = FALSE; - rdpChannels* channels = NULL; - - ArrayList_Lock(g_ChannelsList); - - index = 0; - channels = (rdpChannels*) ArrayList_GetItem(g_ChannelsList, index++); - - while (channels) - { - if (channels->instance == instance) - { - found = TRUE; - break; - } - - channels = (rdpChannels*) ArrayList_GetItem(g_ChannelsList, index++); - } - - ArrayList_Unlock(g_ChannelsList); - - return (found) ? channels : NULL; -} - -CHANNEL_OPEN_DATA* freerdp_channels_find_channel_open_data_by_name(rdpChannels* channels, const char* channel_name) -{ - int index; - CHANNEL_OPEN_DATA* pChannelOpenData; - - for (index = 0; index < channels->openDataCount; index++) - { - pChannelOpenData = &channels->openDataList[index]; - - if (strcmp(channel_name, pChannelOpenData->name) == 0) - return pChannelOpenData; - } - - return NULL; -} - -/* returns rdpChannel for the channel id passed in */ -rdpChannel* freerdp_channels_find_channel_by_id(rdpChannels* channels, rdpSettings* settings, int channel_id, int* pindex) -{ - int index; - int count; - rdpChannel* channel; - - count = settings->ChannelCount; - - for (index = 0; index < count; index++) - { - channel = &settings->ChannelDefArray[index]; - - if (channel->ChannelId == channel_id) - { - if (pindex != 0) - *pindex = index; - - return channel; - } - } - - return NULL; -} - -/* returns rdpChannel for the channel name passed in */ -rdpChannel* freerdp_channels_find_channel_by_name(rdpChannels* channels, - rdpSettings* settings, const char* channel_name, int* pindex) -{ - int index; - int count; - rdpChannel* channel; - - count = settings->ChannelCount; - - for (index = 0; index < count; index++) - { - channel = &settings->ChannelDefArray[index]; - - if (strcmp(channel_name, channel->Name) == 0) - { - if (pindex != 0) - *pindex = index; - - return channel; - } - } - - return NULL; -} - -UINT32 FreeRDP_VirtualChannelWrite(UINT32 openHandle, void* pData, UINT32 dataLength, void* pUserData) -{ - int index; - rdpChannels* channels; - CHANNEL_OPEN_EVENT* item; - CHANNEL_OPEN_DATA* pChannelOpenData; - - channels = freerdp_channels_find_by_open_handle(openHandle, &index); - - if ((!channels) || (index < 0) || (index >= CHANNEL_MAX_COUNT)) - { - DEBUG_CHANNELS("error bad channel handle"); - return CHANNEL_RC_BAD_CHANNEL_HANDLE; - } - - if (!channels->is_connected) - { - DEBUG_CHANNELS("error not connected"); - return CHANNEL_RC_NOT_CONNECTED; - } - - if (!pData) - { - DEBUG_CHANNELS("error bad pData"); - return CHANNEL_RC_NULL_DATA; - } - - if (!dataLength) - { - DEBUG_CHANNELS("error bad dataLength"); - return CHANNEL_RC_ZERO_LENGTH; - } - - pChannelOpenData = &channels->openDataList[index]; - - if (pChannelOpenData->flags != 2) - { - DEBUG_CHANNELS("error not open"); - return CHANNEL_RC_NOT_OPEN; - } - - if (!channels->is_connected) - { - DEBUG_CHANNELS("error not connected"); - return CHANNEL_RC_NOT_CONNECTED; - } - - item = (CHANNEL_OPEN_EVENT*) malloc(sizeof(CHANNEL_OPEN_EVENT)); - item->Data = pData; - item->DataLength = dataLength; - item->UserData = pUserData; - item->Index = index; - - MessageQueue_Post(channels->MsgPipe->Out, (void*) channels, 0, (void*) item, NULL); - - return CHANNEL_RC_OK; -} - -UINT32 FreeRDP_VirtualChannelEventPush(UINT32 openHandle, wMessage* event) -{ - int index; - rdpChannels* channels; - CHANNEL_OPEN_DATA* pChannelOpenData; - - channels = freerdp_channels_find_by_open_handle(openHandle, &index); - - if ((!channels) || (index < 0) || (index >= CHANNEL_MAX_COUNT)) - { - DEBUG_CHANNELS("error bad channels handle"); - return CHANNEL_RC_BAD_CHANNEL_HANDLE; - } - - if (!channels->is_connected) - { - DEBUG_CHANNELS("error not connected"); - return CHANNEL_RC_NOT_CONNECTED; - } - - if (!event) - { - DEBUG_CHANNELS("error bad event"); - return CHANNEL_RC_NULL_DATA; - } - - pChannelOpenData = &channels->openDataList[index]; - - if (pChannelOpenData->flags != 2) - { - DEBUG_CHANNELS("error not open"); - return CHANNEL_RC_NOT_OPEN; - } - - if (!channels->is_connected) - { - DEBUG_CHANNELS("error not connected"); - return CHANNEL_RC_NOT_CONNECTED; - } - - /** - * We really intend to use the In queue for events, but we're pushing on both - * to wake up threads waiting on the out queue. Doing this cleanly would require - * breaking freerdp_pop_event() a bit too early in this refactoring. - */ - - MessageQueue_Post(channels->MsgPipe->In, (void*) channels, 1, (void*) event, NULL); - MessageQueue_Post(channels->MsgPipe->Out, (void*) channels, 1, (void*) event, NULL); - - return CHANNEL_RC_OK; -} - -/** - * this is called shortly after the application starts and - * before any other function in the file - * called only from main thread - */ -int freerdp_channels_global_init(void) -{ - if (!g_ChannelsList) - { - g_ChannelsList = ArrayList_New(TRUE); - InitializeCriticalSectionAndSpinCount(&g_channels_lock, 4000); - } - - return 0; -} - -int freerdp_channels_global_uninit(void) -{ - EnterCriticalSection(&g_channels_lock); - DeleteCriticalSection(&g_channels_lock); - - if (g_ChannelsList) - { - ArrayList_Lock(g_ChannelsList); - ArrayList_Free(g_ChannelsList); - g_ChannelsList = NULL; - } - - return 0; -} - -rdpChannels* freerdp_channels_new(void) -{ - rdpChannels* channels; - - channels = (rdpChannels*) malloc(sizeof(rdpChannels)); - ZeroMemory(channels, sizeof(rdpChannels)); - - channels->MsgPipe = MessagePipe_New(); - - ArrayList_Add(g_ChannelsList, (void*) channels); - - return channels; -} - -void freerdp_channels_free(rdpChannels* channels) -{ - MessagePipe_Free(channels->MsgPipe); - - ArrayList_Lock(g_ChannelsList); - ArrayList_Remove(g_ChannelsList, channels); - ArrayList_Unlock(g_ChannelsList); - - free(channels); -} - -int freerdp_channels_client_load(rdpChannels* channels, rdpSettings* settings, void* entry, void* data) -{ - int status; - CHANNEL_ENTRY_POINTS_EX ep; - CHANNEL_CLIENT_DATA* pChannelClientData; - - if (channels->clientDataCount + 1 >= CHANNEL_MAX_COUNT) - { - fprintf(stderr, "error: too many channels\n"); - return 1; - } - - pChannelClientData = &channels->clientDataList[channels->clientDataCount]; - pChannelClientData->entry = (PVIRTUALCHANNELENTRY) entry; - - ep.cbSize = sizeof(ep); - ep.protocolVersion = VIRTUAL_CHANNEL_VERSION_WIN2000; - ep.pVirtualChannelInit = FreeRDP_VirtualChannelInit; - ep.pVirtualChannelOpen = FreeRDP_VirtualChannelOpen; - ep.pVirtualChannelClose = FreeRDP_VirtualChannelClose; - ep.pVirtualChannelWrite = FreeRDP_VirtualChannelWrite; - - g_pInterface = NULL; - ep.MagicNumber = FREERDP_CHANNEL_MAGIC_NUMBER; - ep.ppInterface = &g_pInterface; - ep.pExtendedData = data; - ep.pVirtualChannelEventPush = FreeRDP_VirtualChannelEventPush; - - /* enable VirtualChannelInit */ - channels->can_call_init = TRUE; - channels->settings = settings; - - EnterCriticalSection(&g_channels_lock); - - g_ChannelInitData.channels = channels; - status = pChannelClientData->entry((PCHANNEL_ENTRY_POINTS) &ep); - - LeaveCriticalSection(&g_channels_lock); - - /* disable MyVirtualChannelInit */ - channels->settings = NULL; - channels->can_call_init = FALSE; - - if (!status) - { - fprintf(stderr, "error: channel export function call failed\n"); - return 1; - } - - return 0; -} - -/** - * this is called when processing the command line parameters - * called only from main thread - */ -int freerdp_channels_load_plugin(rdpChannels* channels, rdpSettings* settings, const char* name, void* data) -{ - void* entry; - - DEBUG_CHANNELS("%s", name); - - entry = (PVIRTUALCHANNELENTRY) freerdp_load_channel_addin_entry(name, NULL, NULL, FREERDP_ADDIN_CHANNEL_STATIC); - - if (!entry) - { - DEBUG_CHANNELS("failed to find export function"); - return 1; - } - - return freerdp_channels_client_load(channels, settings, entry, data); -} - -int freerdp_drdynvc_on_channel_connected(DrdynvcClientContext* context, const char* name, void* pInterface) -{ - int status = 0; - ChannelConnectedEventArgs e; - rdpChannels* channels = (rdpChannels*) context->custom; - freerdp* instance = channels->instance; - - EventArgsInit(&e, "freerdp"); - e.name = name; - e.pInterface = pInterface; - PubSub_OnChannelConnected(instance->context->pubSub, instance->context, &e); - - return status; -} - -int freerdp_drdynvc_on_channel_disconnected(DrdynvcClientContext* context, const char* name, void* pInterface) -{ - int status = 0; - ChannelDisconnectedEventArgs e; - rdpChannels* channels = (rdpChannels*) context->custom; - freerdp* instance = channels->instance; - - EventArgsInit(&e, "freerdp"); - e.name = name; - e.pInterface = pInterface; - PubSub_OnChannelDisconnected(instance->context->pubSub, instance->context, &e); - - return status; -} - -/** - * go through and inform all the libraries that we are initialized - * called only from main thread - */ -int freerdp_channels_pre_connect(rdpChannels* channels, freerdp* instance) -{ - int index; - CHANNEL_CLIENT_DATA* pChannelClientData; - - DEBUG_CHANNELS("enter"); - channels->instance = instance; - - for (index = 0; index < channels->clientDataCount; index++) - { - pChannelClientData = &channels->clientDataList[index]; - - if (pChannelClientData->pChannelInitEventProc) - pChannelClientData->pChannelInitEventProc(pChannelClientData->pInitHandle, CHANNEL_EVENT_INITIALIZED, 0, 0); - } - - return 0; -} - -/** - * go through and inform all the libraries that we are connected - * this will tell the libraries that its ok to call MyVirtualChannelOpen - * called only from main thread - */ -int freerdp_channels_post_connect(rdpChannels* channels, freerdp* instance) -{ - int index; - char* name; - char* hostname; - int hostnameLength; - CHANNEL_CLIENT_DATA* pChannelClientData; - - channels->is_connected = 1; - hostname = instance->settings->ServerHostname; - hostnameLength = (int) strlen(hostname); - - for (index = 0; index < channels->clientDataCount; index++) - { - pChannelClientData = &channels->clientDataList[index]; - - if (pChannelClientData->pChannelInitEventProc) - { - ChannelConnectedEventArgs e; - CHANNEL_OPEN_DATA* pChannelOpenData; - - pChannelOpenData = &channels->openDataList[index]; - - pChannelClientData->pChannelInitEventProc(pChannelClientData->pInitHandle, CHANNEL_EVENT_CONNECTED, hostname, hostnameLength); - - name = (char*) malloc(9); - CopyMemory(name, pChannelOpenData->name, 8); - name[8] = '\0'; - - EventArgsInit(&e, "freerdp"); - e.name = name; - e.pInterface = pChannelOpenData->pInterface; - PubSub_OnChannelConnected(instance->context->pubSub, instance->context, &e); - - free(name); - } - } - - channels->drdynvc = (DrdynvcClientContext*) freerdp_channels_get_static_channel_interface(channels, "drdynvc"); - - if (channels->drdynvc) - { - channels->drdynvc->custom = (void*) channels; - channels->drdynvc->OnChannelConnected = freerdp_drdynvc_on_channel_connected; - channels->drdynvc->OnChannelDisconnected = freerdp_drdynvc_on_channel_disconnected; - } - - return 0; -} - -/** - * data coming from the server to the client - * called only from main thread - */ -int freerdp_channels_data(freerdp* instance, int channel_id, void* data, int data_size, int flags, int total_size) -{ - int index; - rdpChannel* channel; - rdpChannels* channels; - CHANNEL_OPEN_DATA* pChannelOpenData; - - channels = freerdp_channels_find_by_instance(instance); - - if (!channels) - { - DEBUG_CHANNELS("could not find channel manager"); - return 1; - } - - channel = freerdp_channels_find_channel_by_id(channels, instance->settings, channel_id, &index); - - if (!channel) - { - DEBUG_CHANNELS("could not find channel id"); - return 1; - } - - pChannelOpenData = freerdp_channels_find_channel_open_data_by_name(channels, channel->Name); - - if (!pChannelOpenData) - { - DEBUG_CHANNELS("could not find channel name"); - return 1; - } - - if (pChannelOpenData->pChannelOpenEventProc) - { - pChannelOpenData->pChannelOpenEventProc(pChannelOpenData->OpenHandle, - CHANNEL_EVENT_DATA_RECEIVED, data, data_size, total_size, flags); - } - - return 0; -} - -/** - * Send a plugin-defined event to the plugin. - * called only from main thread - * @param channels the channel manager instance - * @param event an event object created by freerdp_event_new() - */ -FREERDP_API int freerdp_channels_send_event(rdpChannels* channels, wMessage* event) -{ - const char* name = NULL; - CHANNEL_OPEN_DATA* pChannelOpenData; - - switch (GetMessageClass(event->id)) - { - case DebugChannel_Class: - name = "rdpdbg"; - break; - - case CliprdrChannel_Class: - name = "cliprdr"; - break; - - case TsmfChannel_Class: - name = "tsmf"; - break; - - case RailChannel_Class: - name = "rail"; - break; - } - - if (!name) - { - DEBUG_CHANNELS("unknown event_class %d", GetMessageClass(event->id)); - freerdp_event_free(event); - return 1; - } - - pChannelOpenData = freerdp_channels_find_channel_open_data_by_name(channels, name); - - if (!pChannelOpenData) - { - DEBUG_CHANNELS("could not find channel name %s", name); - freerdp_event_free(event); - return 1; - } - - if (pChannelOpenData->pChannelOpenEventProc) - { - pChannelOpenData->pChannelOpenEventProc(pChannelOpenData->OpenHandle, CHANNEL_EVENT_USER, - event, sizeof(wMessage), sizeof(wMessage), 0); - } - - return 0; -} - -/** - * called only from main thread - */ -static int freerdp_channels_process_sync(rdpChannels* channels, freerdp* instance) -{ - int rc = TRUE; - wMessage message; - wMessage* event; - rdpChannel* channel; - CHANNEL_OPEN_EVENT* item; - CHANNEL_OPEN_DATA* pChannelOpenData; - - while (MessageQueue_Peek(channels->MsgPipe->Out, &message, TRUE)) - { - if (message.id == WMQ_QUIT) - { - rc = FALSE; - break; - } - - if (message.id == 0) - { - item = (CHANNEL_OPEN_EVENT*) message.wParam; - - if (!item) - break; - - pChannelOpenData = &channels->openDataList[item->Index]; - - channel = freerdp_channels_find_channel_by_name(channels, instance->settings, - pChannelOpenData->name, &item->Index); - - if (channel) - instance->SendChannelData(instance, channel->ChannelId, item->Data, item->DataLength); - - if (pChannelOpenData->pChannelOpenEventProc) - { - pChannelOpenData->pChannelOpenEventProc(pChannelOpenData->OpenHandle, - CHANNEL_EVENT_WRITE_COMPLETE, item->UserData, item->DataLength, item->DataLength, 0); - } - - free(item); - } - else if (message.id == 1) - { - event = (wMessage*) message.wParam; - - /** - * Ignore for now, the same event is being pushed on the In queue, - * and we're pushing it on the Out queue just to wake other threads - */ - } - } - - return rc; -} - -/** - * 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->MsgPipe->Out)); - - if (pfd) - { - read_fds[*read_count] = pfd; - (*read_count)++; - } - - return TRUE; -} - -void* freerdp_channels_get_static_channel_interface(rdpChannels* channels, const char* name) -{ - void* pInterface = NULL; - CHANNEL_OPEN_DATA* pChannelOpenData; - - pChannelOpenData = freerdp_channels_find_channel_open_data_by_name(channels, name); - - if (pChannelOpenData) - pInterface = pChannelOpenData->pInterface; - - return pInterface; -} - -HANDLE freerdp_channels_get_event_handle(freerdp* instance) -{ - HANDLE event = NULL; - rdpChannels* channels; - - channels = instance->context->channels; - event = MessageQueue_Event(channels->MsgPipe->Out); - - return event; -} - -int freerdp_channels_process_pending_messages(freerdp* instance) -{ - rdpChannels* channels; - - channels = instance->context->channels; - - if (WaitForSingleObject(MessageQueue_Event(channels->MsgPipe->Out), 0) == WAIT_OBJECT_0) - { - return freerdp_channels_process_sync(channels, instance); - } - - return TRUE; -} - -/** - * called only from main thread - */ -BOOL freerdp_channels_check_fds(rdpChannels* channels, freerdp* instance) -{ - if (WaitForSingleObject(MessageQueue_Event(channels->MsgPipe->Out), 0) == WAIT_OBJECT_0) - { - freerdp_channels_process_sync(channels, instance); - } - - return TRUE; -} - -wMessage* freerdp_channels_pop_event(rdpChannels* channels) -{ - wMessage message; - wMessage* event = NULL; - - if (MessageQueue_Peek(channels->MsgPipe->In, &message, TRUE)) - { - if (message.id == 1) - { - event = (wMessage*) message.wParam; - } - } - - return event; -} - -void freerdp_channels_close(rdpChannels* channels, freerdp* instance) -{ - int index; - char* name; - CHANNEL_OPEN_DATA* pChannelOpenData; - CHANNEL_CLIENT_DATA* pChannelClientData; - - DEBUG_CHANNELS("closing"); - - channels->is_connected = 0; - freerdp_channels_check_fds(channels, instance); - - /* tell all libraries we are shutting down */ - for (index = 0; index < channels->clientDataCount; index++) - { - ChannelDisconnectedEventArgs e; - - pChannelClientData = &channels->clientDataList[index]; - - if (pChannelClientData->pChannelInitEventProc) - pChannelClientData->pChannelInitEventProc(pChannelClientData->pInitHandle, CHANNEL_EVENT_TERMINATED, 0, 0); - - pChannelOpenData = &channels->openDataList[index]; - - name = (char*) malloc(9); - CopyMemory(name, pChannelOpenData->name, 8); - name[8] = '\0'; - - EventArgsInit(&e, "freerdp"); - e.name = name; - e.pInterface = pChannelOpenData->pInterface; - PubSub_OnChannelDisconnected(instance->context->pubSub, instance->context, &e); - - free(name); - } - - /* Emit a quit signal to the internal message pipe. */ - MessagePipe_PostQuit(channels->MsgPipe, 0); -} diff --git a/channels/client/channels.h b/channels/client/channels.h deleted file mode 100644 index 7e801e59b..000000000 --- a/channels/client/channels.h +++ /dev/null @@ -1,122 +0,0 @@ -/** - * FreeRDP: A Remote Desktop Protocol Implementation - * Client Channels - * - * Copyright 2013 Marc-Andre Moreau - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FREERDP_PRIVATE_CLIENT_CHANNELS -#define FREERDP_PRIVATE_CLIENT_CHANNELS - -#include -#include -#include - -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#define CHANNEL_MAX_COUNT 30 - -struct rdp_channel_client_data -{ - PVIRTUALCHANNELENTRY entry; - PCHANNEL_INIT_EVENT_FN pChannelInitEventProc; - void* pInitHandle; -}; -typedef struct rdp_channel_client_data CHANNEL_CLIENT_DATA; - -struct rdp_channel_open_data -{ - char name[8]; - int OpenHandle; - int options; - int flags; - void* pInterface; - PCHANNEL_OPEN_EVENT_FN pChannelOpenEventProc; -}; -typedef struct rdp_channel_open_data CHANNEL_OPEN_DATA; - -struct _CHANNEL_OPEN_EVENT -{ - void* Data; - UINT32 DataLength; - void* UserData; - int Index; -}; -typedef struct _CHANNEL_OPEN_EVENT CHANNEL_OPEN_EVENT; - -/** - * pInitHandle: handle that identifies the client connection - * Obtained by the client with VirtualChannelInit - * Used by the client with VirtualChannelOpen - */ - -struct rdp_channel_init_data -{ - rdpChannels* channels; - void* pInterface; -}; -typedef struct rdp_channel_init_data CHANNEL_INIT_DATA; - -struct rdp_channels -{ - /* internal */ - - int clientDataCount; - CHANNEL_CLIENT_DATA clientDataList[CHANNEL_MAX_COUNT]; - - int openDataCount; - CHANNEL_OPEN_DATA openDataList[CHANNEL_MAX_COUNT]; - - int initDataCount; - CHANNEL_INIT_DATA initDataList[CHANNEL_MAX_COUNT]; - - /* control for entry into MyVirtualChannelInit */ - int can_call_init; - rdpSettings* settings; - - /* true once freerdp_channels_post_connect is called */ - int is_connected; - - /* used for locating the channels for a given instance */ - freerdp* instance; - - wMessagePipe* MsgPipe; - - DrdynvcClientContext* drdynvc; -}; - -#ifdef WITH_DEBUG_CHANNELS -#define DEBUG_CHANNELS(fmt, ...) DEBUG_CLASS(CHANNELS, fmt, ## __VA_ARGS__) -#else -#define DEBUG_CHANNELS(fmt, ...) DEBUG_NULL(fmt, ## __VA_ARGS__) -#endif - -rdpChannels* freerdp_channels_find_by_open_handle(int open_handle, int* pindex); -CHANNEL_OPEN_DATA* freerdp_channels_find_channel_open_data_by_name(rdpChannels* channels, const char* channel_name); - -#endif /* FREERDP_PRIVATE_CLIENT_CHANNELS */ diff --git a/channels/client/init.c b/channels/client/init.c deleted file mode 100644 index f88867a6a..000000000 --- a/channels/client/init.c +++ /dev/null @@ -1,135 +0,0 @@ -/** - * FreeRDP: A Remote Desktop Protocol Implementation - * Client Channels - * - * Copyright 2013 Marc-Andre Moreau - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "channels.h" - -#include "init.h" - -extern int g_open_handle_sequence; - -extern void* g_pInterface; -extern CHANNEL_INIT_DATA g_ChannelInitData; - -UINT32 FreeRDP_VirtualChannelInit(void** ppInitHandle, PCHANNEL_DEF pChannel, - int channelCount, UINT32 versionRequested, PCHANNEL_INIT_EVENT_FN pChannelInitEventProc) -{ - int index; - void* pInterface; - rdpChannel* channel; - rdpChannels* channels; - PCHANNEL_DEF pChannelDef; - CHANNEL_INIT_DATA* pChannelInitData; - CHANNEL_OPEN_DATA* pChannelOpenData; - CHANNEL_CLIENT_DATA* pChannelClientData; - - if (!ppInitHandle) - { - DEBUG_CHANNELS("error bad init handle"); - return CHANNEL_RC_BAD_INIT_HANDLE; - } - - channels = g_ChannelInitData.channels; - pInterface = g_pInterface; - - pChannelInitData = &(channels->initDataList[channels->initDataCount]); - *ppInitHandle = pChannelInitData; - channels->initDataCount++; - - pChannelInitData->channels = channels; - pChannelInitData->pInterface = pInterface; - - DEBUG_CHANNELS("enter"); - - if (!channels->can_call_init) - { - DEBUG_CHANNELS("error not in entry"); - return CHANNEL_RC_NOT_IN_VIRTUALCHANNELENTRY; - } - - if (channels->openDataCount + channelCount >= CHANNEL_MAX_COUNT) - { - DEBUG_CHANNELS("error too many channels"); - return CHANNEL_RC_TOO_MANY_CHANNELS; - } - - if (!pChannel) - { - DEBUG_CHANNELS("error bad channel"); - return CHANNEL_RC_BAD_CHANNEL; - } - - if (channels->is_connected) - { - DEBUG_CHANNELS("error already connected"); - return CHANNEL_RC_ALREADY_CONNECTED; - } - - if (versionRequested != VIRTUAL_CHANNEL_VERSION_WIN2000) - { - DEBUG_CHANNELS("warning version"); - } - - for (index = 0; index < channelCount; index++) - { - pChannelDef = &pChannel[index]; - - if (freerdp_channels_find_channel_open_data_by_name(channels, pChannelDef->name) != 0) - { - DEBUG_CHANNELS("error channel already used"); - return CHANNEL_RC_BAD_CHANNEL; - } - } - - pChannelClientData = &channels->clientDataList[channels->clientDataCount]; - pChannelClientData->pChannelInitEventProc = pChannelInitEventProc; - pChannelClientData->pInitHandle = *ppInitHandle; - channels->clientDataCount++; - - for (index = 0; index < channelCount; index++) - { - pChannelDef = &pChannel[index]; - pChannelOpenData = &channels->openDataList[channels->openDataCount]; - - pChannelOpenData->OpenHandle = g_open_handle_sequence++; - - pChannelOpenData->flags = 1; /* init */ - strncpy(pChannelOpenData->name, pChannelDef->name, CHANNEL_NAME_LEN); - pChannelOpenData->options = pChannelDef->options; - - if (channels->settings->ChannelCount < CHANNEL_MAX_COUNT) - { - channel = channels->settings->ChannelDefArray + channels->settings->ChannelCount; - strncpy(channel->Name, pChannelDef->name, 7); - channel->options = pChannelDef->options; - channels->settings->ChannelCount++; - } - else - { - DEBUG_CHANNELS("warning more than %d channels", CHANNEL_MAX_COUNT); - } - - channels->openDataCount++; - } - - return CHANNEL_RC_OK; -} diff --git a/channels/client/init.h b/channels/client/init.h deleted file mode 100644 index a5dccc133..000000000 --- a/channels/client/init.h +++ /dev/null @@ -1,28 +0,0 @@ -/** - * FreeRDP: A Remote Desktop Protocol Implementation - * Client Channels - * - * Copyright 2013 Marc-Andre Moreau - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FREERDP_PRIVATE_CLIENT_CHANNELS_INIT -#define FREERDP_PRIVATE_CLIENT_CHANNELS_INIT - -#include "channels.h" - -UINT32 FreeRDP_VirtualChannelInit(void** ppInitHandle, PCHANNEL_DEF pChannel, - int channelCount, UINT32 versionRequested, PCHANNEL_INIT_EVENT_FN pChannelInitEventProc); - -#endif /* FREERDP_PRIVATE_CLIENT_CHANNELS_INIT */ diff --git a/channels/client/open.c b/channels/client/open.c deleted file mode 100644 index 1233fb964..000000000 --- a/channels/client/open.c +++ /dev/null @@ -1,103 +0,0 @@ -/** - * FreeRDP: A Remote Desktop Protocol Implementation - * Client Channels - * - * Copyright 2013 Marc-Andre Moreau - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "open.h" - -UINT32 FreeRDP_VirtualChannelOpen(void* pInitHandle, UINT32* pOpenHandle, - char* pChannelName, PCHANNEL_OPEN_EVENT_FN pChannelOpenEventProc) -{ - void* pInterface; - rdpChannels* channels; - CHANNEL_INIT_DATA* pChannelInitData; - CHANNEL_OPEN_DATA* pChannelOpenData; - - DEBUG_CHANNELS("enter"); - - pChannelInitData = (CHANNEL_INIT_DATA*) pInitHandle; - channels = pChannelInitData->channels; - pInterface = pChannelInitData->pInterface; - - if (!pOpenHandle) - { - DEBUG_CHANNELS("error bad channel handle"); - return CHANNEL_RC_BAD_CHANNEL_HANDLE; - } - - if (!pChannelOpenEventProc) - { - DEBUG_CHANNELS("error bad proc"); - return CHANNEL_RC_BAD_PROC; - } - - if (!channels->is_connected) - { - DEBUG_CHANNELS("error not connected"); - return CHANNEL_RC_NOT_CONNECTED; - } - - pChannelOpenData = freerdp_channels_find_channel_open_data_by_name(channels, pChannelName); - - if (!pChannelOpenData) - { - DEBUG_CHANNELS("error channel name"); - return CHANNEL_RC_UNKNOWN_CHANNEL_NAME; - } - - if (pChannelOpenData->flags == 2) - { - DEBUG_CHANNELS("error channel already open"); - return CHANNEL_RC_ALREADY_OPEN; - } - - pChannelOpenData->flags = 2; /* open */ - pChannelOpenData->pInterface = pInterface; - pChannelOpenData->pChannelOpenEventProc = pChannelOpenEventProc; - *pOpenHandle = pChannelOpenData->OpenHandle; - - return CHANNEL_RC_OK; -} - -UINT32 FreeRDP_VirtualChannelClose(UINT32 openHandle) -{ - int index; - rdpChannels* channels; - CHANNEL_OPEN_DATA* pChannelOpenData; - - DEBUG_CHANNELS("enter"); - - channels = freerdp_channels_find_by_open_handle(openHandle, &index); - - if ((channels == NULL) || (index < 0) || (index >= CHANNEL_MAX_COUNT)) - { - DEBUG_CHANNELS("error bad channels"); - return CHANNEL_RC_BAD_CHANNEL_HANDLE; - } - - pChannelOpenData = &channels->openDataList[index]; - - if (pChannelOpenData->flags != 2) - { - DEBUG_CHANNELS("error not open"); - return CHANNEL_RC_NOT_OPEN; - } - - pChannelOpenData->flags = 0; - - return CHANNEL_RC_OK; -} diff --git a/channels/client/open.h b/channels/client/open.h deleted file mode 100644 index 4bb525d53..000000000 --- a/channels/client/open.h +++ /dev/null @@ -1,30 +0,0 @@ -/** - * FreeRDP: A Remote Desktop Protocol Implementation - * Client Channels - * - * Copyright 2013 Marc-Andre Moreau - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FREERDP_PRIVATE_CLIENT_CHANNELS_OPEN -#define FREERDP_PRIVATE_CLIENT_CHANNELS_OPEN - -#include "channels.h" - -UINT32 FreeRDP_VirtualChannelOpen(void* pInitHandle, UINT32* pOpenHandle, - char* pChannelName, PCHANNEL_OPEN_EVENT_FN pChannelOpenEventProc); - -UINT32 FreeRDP_VirtualChannelClose(UINT32 openHandle); - -#endif /* FREERDP_PRIVATE_CLIENT_CHANNELS_OPEN */ diff --git a/libfreerdp/core/channel.c b/libfreerdp/core/channel.c index 8abbd50f1..5cbd5ce76 100644 --- a/libfreerdp/core/channel.c +++ b/libfreerdp/core/channel.c @@ -25,26 +25,1033 @@ #include #include -#include -#include -#include +#include #include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + #include "rdp.h" #include "channel.h" -BOOL freerdp_channel_send(rdpRdp* rdp, UINT16 channel_id, BYTE* data, int size) +/** + * Channels Client + */ + +#define CHANNEL_MAX_COUNT 30 + +struct rdp_channel_client_data +{ + PVIRTUALCHANNELENTRY entry; + PCHANNEL_INIT_EVENT_FN pChannelInitEventProc; + void* pInitHandle; +}; +typedef struct rdp_channel_client_data CHANNEL_CLIENT_DATA; + +struct rdp_channel_open_data +{ + char name[8]; + int OpenHandle; + int options; + int flags; + void* pInterface; + PCHANNEL_OPEN_EVENT_FN pChannelOpenEventProc; +}; +typedef struct rdp_channel_open_data CHANNEL_OPEN_DATA; + +struct _CHANNEL_OPEN_EVENT +{ + void* Data; + UINT32 DataLength; + void* UserData; + int Index; +}; +typedef struct _CHANNEL_OPEN_EVENT CHANNEL_OPEN_EVENT; + +/** + * pInitHandle: handle that identifies the client connection + * Obtained by the client with VirtualChannelInit + * Used by the client with VirtualChannelOpen + */ + +struct rdp_channel_init_data +{ + rdpChannels* channels; + void* pInterface; +}; +typedef struct rdp_channel_init_data CHANNEL_INIT_DATA; + +struct rdp_channels +{ + /* internal */ + + int clientDataCount; + CHANNEL_CLIENT_DATA clientDataList[CHANNEL_MAX_COUNT]; + + int openDataCount; + CHANNEL_OPEN_DATA openDataList[CHANNEL_MAX_COUNT]; + + int initDataCount; + CHANNEL_INIT_DATA initDataList[CHANNEL_MAX_COUNT]; + + /* control for entry into MyVirtualChannelInit */ + int can_call_init; + rdpSettings* settings; + + /* true once freerdp_channels_post_connect is called */ + int is_connected; + + /* used for locating the channels for a given instance */ + freerdp* instance; + + wMessagePipe* MsgPipe; + + DrdynvcClientContext* drdynvc; +}; + +static void* g_pInterface; +static CHANNEL_INIT_DATA g_ChannelInitData; + +static wArrayList* g_ChannelsList = NULL; + +/* To generate unique sequence for all open handles */ +int g_open_handle_sequence = 1; + +/* For locking the global resources */ +static CRITICAL_SECTION g_channels_lock; + +rdpChannels* freerdp_channels_find_by_open_handle(int OpenHandle, int* pindex) +{ + int i, j; + BOOL found = FALSE; + rdpChannels* channels = NULL; + + ArrayList_Lock(g_ChannelsList); + + i = j = 0; + channels = (rdpChannels*) ArrayList_GetItem(g_ChannelsList, i++); + + while (channels) + { + for (j = 0; j < channels->openDataCount; j++) + { + if (channels->openDataList[j].OpenHandle == OpenHandle) + { + *pindex = j; + found = TRUE; + break; + } + } + + if (found) + break; + + channels = (rdpChannels*) ArrayList_GetItem(g_ChannelsList, i++); + } + + ArrayList_Unlock(g_ChannelsList); + + return (found) ? channels : NULL; +} + +rdpChannels* freerdp_channels_find_by_instance(freerdp* instance) +{ + int index; + BOOL found = FALSE; + rdpChannels* channels = NULL; + + ArrayList_Lock(g_ChannelsList); + + index = 0; + channels = (rdpChannels*) ArrayList_GetItem(g_ChannelsList, index++); + + while (channels) + { + if (channels->instance == instance) + { + found = TRUE; + break; + } + + channels = (rdpChannels*) ArrayList_GetItem(g_ChannelsList, index++); + } + + ArrayList_Unlock(g_ChannelsList); + + return (found) ? channels : NULL; +} + +CHANNEL_OPEN_DATA* freerdp_channels_find_channel_open_data_by_name(rdpChannels* channels, const char* channel_name) +{ + int index; + CHANNEL_OPEN_DATA* pChannelOpenData; + + for (index = 0; index < channels->openDataCount; index++) + { + pChannelOpenData = &channels->openDataList[index]; + + if (strcmp(channel_name, pChannelOpenData->name) == 0) + return pChannelOpenData; + } + + return NULL; +} + +/* returns rdpChannel for the channel id passed in */ +rdpChannel* freerdp_channels_find_channel_by_id(rdpChannels* channels, rdpSettings* settings, int channel_id, int* pindex) +{ + int index; + int count; + rdpChannel* channel; + + count = settings->ChannelCount; + + for (index = 0; index < count; index++) + { + channel = &settings->ChannelDefArray[index]; + + if (channel->ChannelId == channel_id) + { + if (pindex != 0) + *pindex = index; + + return channel; + } + } + + return NULL; +} + +/* returns rdpChannel for the channel name passed in */ +rdpChannel* freerdp_channels_find_channel_by_name(rdpChannels* channels, + rdpSettings* settings, const char* channel_name, int* pindex) +{ + int index; + int count; + rdpChannel* channel; + + count = settings->ChannelCount; + + for (index = 0; index < count; index++) + { + channel = &settings->ChannelDefArray[index]; + + if (strcmp(channel_name, channel->Name) == 0) + { + if (pindex != 0) + *pindex = index; + + return channel; + } + } + + return NULL; +} + +UINT32 FreeRDP_VirtualChannelWrite(UINT32 openHandle, void* pData, UINT32 dataLength, void* pUserData) +{ + int index; + rdpChannels* channels; + CHANNEL_OPEN_EVENT* item; + CHANNEL_OPEN_DATA* pChannelOpenData; + + channels = freerdp_channels_find_by_open_handle(openHandle, &index); + + if ((!channels) || (index < 0) || (index >= CHANNEL_MAX_COUNT)) + { + return CHANNEL_RC_BAD_CHANNEL_HANDLE; + } + + if (!channels->is_connected) + { + return CHANNEL_RC_NOT_CONNECTED; + } + + if (!pData) + { + return CHANNEL_RC_NULL_DATA; + } + + if (!dataLength) + { + return CHANNEL_RC_ZERO_LENGTH; + } + + pChannelOpenData = &channels->openDataList[index]; + + if (pChannelOpenData->flags != 2) + { + return CHANNEL_RC_NOT_OPEN; + } + + if (!channels->is_connected) + { + return CHANNEL_RC_NOT_CONNECTED; + } + + item = (CHANNEL_OPEN_EVENT*) malloc(sizeof(CHANNEL_OPEN_EVENT)); + item->Data = pData; + item->DataLength = dataLength; + item->UserData = pUserData; + item->Index = index; + + MessageQueue_Post(channels->MsgPipe->Out, (void*) channels, 0, (void*) item, NULL); + + return CHANNEL_RC_OK; +} + +UINT32 FreeRDP_VirtualChannelEventPush(UINT32 openHandle, wMessage* event) +{ + int index; + rdpChannels* channels; + CHANNEL_OPEN_DATA* pChannelOpenData; + + channels = freerdp_channels_find_by_open_handle(openHandle, &index); + + if ((!channels) || (index < 0) || (index >= CHANNEL_MAX_COUNT)) + { + return CHANNEL_RC_BAD_CHANNEL_HANDLE; + } + + if (!channels->is_connected) + { + return CHANNEL_RC_NOT_CONNECTED; + } + + if (!event) + { + return CHANNEL_RC_NULL_DATA; + } + + pChannelOpenData = &channels->openDataList[index]; + + if (pChannelOpenData->flags != 2) + { + return CHANNEL_RC_NOT_OPEN; + } + + if (!channels->is_connected) + { + return CHANNEL_RC_NOT_CONNECTED; + } + + /** + * We really intend to use the In queue for events, but we're pushing on both + * to wake up threads waiting on the out queue. Doing this cleanly would require + * breaking freerdp_pop_event() a bit too early in this refactoring. + */ + + MessageQueue_Post(channels->MsgPipe->In, (void*) channels, 1, (void*) event, NULL); + MessageQueue_Post(channels->MsgPipe->Out, (void*) channels, 1, (void*) event, NULL); + + return CHANNEL_RC_OK; +} + +/** + * this is called shortly after the application starts and + * before any other function in the file + * called only from main thread + */ +int freerdp_channels_global_init(void) +{ + if (!g_ChannelsList) + { + g_ChannelsList = ArrayList_New(TRUE); + InitializeCriticalSectionAndSpinCount(&g_channels_lock, 4000); + } + + return 0; +} + +int freerdp_channels_global_uninit(void) +{ + EnterCriticalSection(&g_channels_lock); + DeleteCriticalSection(&g_channels_lock); + + if (g_ChannelsList) + { + ArrayList_Lock(g_ChannelsList); + ArrayList_Free(g_ChannelsList); + g_ChannelsList = NULL; + } + + return 0; +} + +rdpChannels* freerdp_channels_new(void) +{ + rdpChannels* channels; + + channels = (rdpChannels*) malloc(sizeof(rdpChannels)); + ZeroMemory(channels, sizeof(rdpChannels)); + + channels->MsgPipe = MessagePipe_New(); + + ArrayList_Add(g_ChannelsList, (void*) channels); + + return channels; +} + +void freerdp_channels_free(rdpChannels* channels) +{ + MessagePipe_Free(channels->MsgPipe); + + ArrayList_Lock(g_ChannelsList); + ArrayList_Remove(g_ChannelsList, channels); + ArrayList_Unlock(g_ChannelsList); + + free(channels); +} + +int freerdp_drdynvc_on_channel_connected(DrdynvcClientContext* context, const char* name, void* pInterface) +{ + int status = 0; + ChannelConnectedEventArgs e; + rdpChannels* channels = (rdpChannels*) context->custom; + freerdp* instance = channels->instance; + + EventArgsInit(&e, "freerdp"); + e.name = name; + e.pInterface = pInterface; + PubSub_OnChannelConnected(instance->context->pubSub, instance->context, &e); + + return status; +} + +int freerdp_drdynvc_on_channel_disconnected(DrdynvcClientContext* context, const char* name, void* pInterface) +{ + int status = 0; + ChannelDisconnectedEventArgs e; + rdpChannels* channels = (rdpChannels*) context->custom; + freerdp* instance = channels->instance; + + EventArgsInit(&e, "freerdp"); + e.name = name; + e.pInterface = pInterface; + PubSub_OnChannelDisconnected(instance->context->pubSub, instance->context, &e); + + return status; +} + +/** + * go through and inform all the libraries that we are initialized + * called only from main thread + */ +int freerdp_channels_pre_connect(rdpChannels* channels, freerdp* instance) +{ + int index; + CHANNEL_CLIENT_DATA* pChannelClientData; + + channels->instance = instance; + + for (index = 0; index < channels->clientDataCount; index++) + { + pChannelClientData = &channels->clientDataList[index]; + + if (pChannelClientData->pChannelInitEventProc) + pChannelClientData->pChannelInitEventProc(pChannelClientData->pInitHandle, CHANNEL_EVENT_INITIALIZED, 0, 0); + } + + return 0; +} + +/** + * go through and inform all the libraries that we are connected + * this will tell the libraries that its ok to call MyVirtualChannelOpen + * called only from main thread + */ +int freerdp_channels_post_connect(rdpChannels* channels, freerdp* instance) +{ + int index; + char* name; + char* hostname; + int hostnameLength; + CHANNEL_CLIENT_DATA* pChannelClientData; + + channels->is_connected = 1; + hostname = instance->settings->ServerHostname; + hostnameLength = (int) strlen(hostname); + + for (index = 0; index < channels->clientDataCount; index++) + { + pChannelClientData = &channels->clientDataList[index]; + + if (pChannelClientData->pChannelInitEventProc) + { + ChannelConnectedEventArgs e; + CHANNEL_OPEN_DATA* pChannelOpenData; + + pChannelOpenData = &channels->openDataList[index]; + + pChannelClientData->pChannelInitEventProc(pChannelClientData->pInitHandle, CHANNEL_EVENT_CONNECTED, hostname, hostnameLength); + + name = (char*) malloc(9); + CopyMemory(name, pChannelOpenData->name, 8); + name[8] = '\0'; + + EventArgsInit(&e, "freerdp"); + e.name = name; + e.pInterface = pChannelOpenData->pInterface; + PubSub_OnChannelConnected(instance->context->pubSub, instance->context, &e); + + free(name); + } + } + + channels->drdynvc = (DrdynvcClientContext*) freerdp_channels_get_static_channel_interface(channels, "drdynvc"); + + if (channels->drdynvc) + { + channels->drdynvc->custom = (void*) channels; + channels->drdynvc->OnChannelConnected = freerdp_drdynvc_on_channel_connected; + channels->drdynvc->OnChannelDisconnected = freerdp_drdynvc_on_channel_disconnected; + } + + return 0; +} + +/** + * data coming from the server to the client + * called only from main thread + */ +int freerdp_channels_data(freerdp* instance, int channel_id, void* data, int data_size, int flags, int total_size) +{ + int index; + rdpChannel* channel; + rdpChannels* channels; + CHANNEL_OPEN_DATA* pChannelOpenData; + + channels = freerdp_channels_find_by_instance(instance); + + if (!channels) + { + return 1; + } + + channel = freerdp_channels_find_channel_by_id(channels, instance->settings, channel_id, &index); + + if (!channel) + { + return 1; + } + + pChannelOpenData = freerdp_channels_find_channel_open_data_by_name(channels, channel->Name); + + if (!pChannelOpenData) + { + return 1; + } + + if (pChannelOpenData->pChannelOpenEventProc) + { + pChannelOpenData->pChannelOpenEventProc(pChannelOpenData->OpenHandle, + CHANNEL_EVENT_DATA_RECEIVED, data, data_size, total_size, flags); + } + + return 0; +} + +/** + * Send a plugin-defined event to the plugin. + * called only from main thread + * @param channels the channel manager instance + * @param event an event object created by freerdp_event_new() + */ +FREERDP_API int freerdp_channels_send_event(rdpChannels* channels, wMessage* event) +{ + const char* name = NULL; + CHANNEL_OPEN_DATA* pChannelOpenData; + + switch (GetMessageClass(event->id)) + { + case DebugChannel_Class: + name = "rdpdbg"; + break; + + case CliprdrChannel_Class: + name = "cliprdr"; + break; + + case TsmfChannel_Class: + name = "tsmf"; + break; + + case RailChannel_Class: + name = "rail"; + break; + } + + if (!name) + { + freerdp_event_free(event); + return 1; + } + + pChannelOpenData = freerdp_channels_find_channel_open_data_by_name(channels, name); + + if (!pChannelOpenData) + { + freerdp_event_free(event); + return 1; + } + + if (pChannelOpenData->pChannelOpenEventProc) + { + pChannelOpenData->pChannelOpenEventProc(pChannelOpenData->OpenHandle, CHANNEL_EVENT_USER, + event, sizeof(wMessage), sizeof(wMessage), 0); + } + + return 0; +} + +/** + * called only from main thread + */ +static int freerdp_channels_process_sync(rdpChannels* channels, freerdp* instance) +{ + int rc = TRUE; + wMessage message; + wMessage* event; + rdpChannel* channel; + CHANNEL_OPEN_EVENT* item; + CHANNEL_OPEN_DATA* pChannelOpenData; + + while (MessageQueue_Peek(channels->MsgPipe->Out, &message, TRUE)) + { + if (message.id == WMQ_QUIT) + { + rc = FALSE; + break; + } + + if (message.id == 0) + { + item = (CHANNEL_OPEN_EVENT*) message.wParam; + + if (!item) + break; + + pChannelOpenData = &channels->openDataList[item->Index]; + + channel = freerdp_channels_find_channel_by_name(channels, instance->settings, + pChannelOpenData->name, &item->Index); + + if (channel) + instance->SendChannelData(instance, channel->ChannelId, item->Data, item->DataLength); + + if (pChannelOpenData->pChannelOpenEventProc) + { + pChannelOpenData->pChannelOpenEventProc(pChannelOpenData->OpenHandle, + CHANNEL_EVENT_WRITE_COMPLETE, item->UserData, item->DataLength, item->DataLength, 0); + } + + free(item); + } + else if (message.id == 1) + { + event = (wMessage*) message.wParam; + + /** + * Ignore for now, the same event is being pushed on the In queue, + * and we're pushing it on the Out queue just to wake other threads + */ + } + } + + return rc; +} + +/** + * 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->MsgPipe->Out)); + + if (pfd) + { + read_fds[*read_count] = pfd; + (*read_count)++; + } + + return TRUE; +} + +void* freerdp_channels_get_static_channel_interface(rdpChannels* channels, const char* name) +{ + void* pInterface = NULL; + CHANNEL_OPEN_DATA* pChannelOpenData; + + pChannelOpenData = freerdp_channels_find_channel_open_data_by_name(channels, name); + + if (pChannelOpenData) + pInterface = pChannelOpenData->pInterface; + + return pInterface; +} + +HANDLE freerdp_channels_get_event_handle(freerdp* instance) +{ + HANDLE event = NULL; + rdpChannels* channels; + + channels = instance->context->channels; + event = MessageQueue_Event(channels->MsgPipe->Out); + + return event; +} + +int freerdp_channels_process_pending_messages(freerdp* instance) +{ + rdpChannels* channels; + + channels = instance->context->channels; + + if (WaitForSingleObject(MessageQueue_Event(channels->MsgPipe->Out), 0) == WAIT_OBJECT_0) + { + return freerdp_channels_process_sync(channels, instance); + } + + return TRUE; +} + +/** + * called only from main thread + */ +BOOL freerdp_channels_check_fds(rdpChannels* channels, freerdp* instance) +{ + if (WaitForSingleObject(MessageQueue_Event(channels->MsgPipe->Out), 0) == WAIT_OBJECT_0) + { + freerdp_channels_process_sync(channels, instance); + } + + return TRUE; +} + +wMessage* freerdp_channels_pop_event(rdpChannels* channels) +{ + wMessage message; + wMessage* event = NULL; + + if (MessageQueue_Peek(channels->MsgPipe->In, &message, TRUE)) + { + if (message.id == 1) + { + event = (wMessage*) message.wParam; + } + } + + return event; +} + +void freerdp_channels_close(rdpChannels* channels, freerdp* instance) +{ + int index; + char* name; + CHANNEL_OPEN_DATA* pChannelOpenData; + CHANNEL_CLIENT_DATA* pChannelClientData; + + channels->is_connected = 0; + freerdp_channels_check_fds(channels, instance); + + /* tell all libraries we are shutting down */ + for (index = 0; index < channels->clientDataCount; index++) + { + ChannelDisconnectedEventArgs e; + + pChannelClientData = &channels->clientDataList[index]; + + if (pChannelClientData->pChannelInitEventProc) + pChannelClientData->pChannelInitEventProc(pChannelClientData->pInitHandle, CHANNEL_EVENT_TERMINATED, 0, 0); + + pChannelOpenData = &channels->openDataList[index]; + + name = (char*) malloc(9); + CopyMemory(name, pChannelOpenData->name, 8); + name[8] = '\0'; + + EventArgsInit(&e, "freerdp"); + e.name = name; + e.pInterface = pChannelOpenData->pInterface; + PubSub_OnChannelDisconnected(instance->context->pubSub, instance->context, &e); + + free(name); + } + + /* Emit a quit signal to the internal message pipe. */ + MessagePipe_PostQuit(channels->MsgPipe, 0); +} + +UINT32 FreeRDP_VirtualChannelInit(void** ppInitHandle, PCHANNEL_DEF pChannel, + int channelCount, UINT32 versionRequested, PCHANNEL_INIT_EVENT_FN pChannelInitEventProc) +{ + int index; + void* pInterface; + rdpChannel* channel; + rdpChannels* channels; + PCHANNEL_DEF pChannelDef; + CHANNEL_INIT_DATA* pChannelInitData; + CHANNEL_OPEN_DATA* pChannelOpenData; + CHANNEL_CLIENT_DATA* pChannelClientData; + + if (!ppInitHandle) + { + return CHANNEL_RC_BAD_INIT_HANDLE; + } + + channels = g_ChannelInitData.channels; + pInterface = g_pInterface; + + pChannelInitData = &(channels->initDataList[channels->initDataCount]); + *ppInitHandle = pChannelInitData; + channels->initDataCount++; + + pChannelInitData->channels = channels; + pChannelInitData->pInterface = pInterface; + + if (!channels->can_call_init) + { + return CHANNEL_RC_NOT_IN_VIRTUALCHANNELENTRY; + } + + if (channels->openDataCount + channelCount >= CHANNEL_MAX_COUNT) + { + return CHANNEL_RC_TOO_MANY_CHANNELS; + } + + if (!pChannel) + { + return CHANNEL_RC_BAD_CHANNEL; + } + + if (channels->is_connected) + { + return CHANNEL_RC_ALREADY_CONNECTED; + } + + if (versionRequested != VIRTUAL_CHANNEL_VERSION_WIN2000) + { + + } + + for (index = 0; index < channelCount; index++) + { + pChannelDef = &pChannel[index]; + + if (freerdp_channels_find_channel_open_data_by_name(channels, pChannelDef->name) != 0) + { + return CHANNEL_RC_BAD_CHANNEL; + } + } + + pChannelClientData = &channels->clientDataList[channels->clientDataCount]; + pChannelClientData->pChannelInitEventProc = pChannelInitEventProc; + pChannelClientData->pInitHandle = *ppInitHandle; + channels->clientDataCount++; + + for (index = 0; index < channelCount; index++) + { + pChannelDef = &pChannel[index]; + pChannelOpenData = &channels->openDataList[channels->openDataCount]; + + pChannelOpenData->OpenHandle = g_open_handle_sequence++; + + pChannelOpenData->flags = 1; /* init */ + strncpy(pChannelOpenData->name, pChannelDef->name, CHANNEL_NAME_LEN); + pChannelOpenData->options = pChannelDef->options; + + if (channels->settings->ChannelCount < CHANNEL_MAX_COUNT) + { + channel = channels->settings->ChannelDefArray + channels->settings->ChannelCount; + strncpy(channel->Name, pChannelDef->name, 7); + channel->options = pChannelDef->options; + channels->settings->ChannelCount++; + } + else + { + + } + + channels->openDataCount++; + } + + return CHANNEL_RC_OK; +} + +UINT32 FreeRDP_VirtualChannelOpen(void* pInitHandle, UINT32* pOpenHandle, + char* pChannelName, PCHANNEL_OPEN_EVENT_FN pChannelOpenEventProc) +{ + void* pInterface; + rdpChannels* channels; + CHANNEL_INIT_DATA* pChannelInitData; + CHANNEL_OPEN_DATA* pChannelOpenData; + + pChannelInitData = (CHANNEL_INIT_DATA*) pInitHandle; + channels = pChannelInitData->channels; + pInterface = pChannelInitData->pInterface; + + if (!pOpenHandle) + { + return CHANNEL_RC_BAD_CHANNEL_HANDLE; + } + + if (!pChannelOpenEventProc) + { + return CHANNEL_RC_BAD_PROC; + } + + if (!channels->is_connected) + { + return CHANNEL_RC_NOT_CONNECTED; + } + + pChannelOpenData = freerdp_channels_find_channel_open_data_by_name(channels, pChannelName); + + if (!pChannelOpenData) + { + return CHANNEL_RC_UNKNOWN_CHANNEL_NAME; + } + + if (pChannelOpenData->flags == 2) + { + return CHANNEL_RC_ALREADY_OPEN; + } + + pChannelOpenData->flags = 2; /* open */ + pChannelOpenData->pInterface = pInterface; + pChannelOpenData->pChannelOpenEventProc = pChannelOpenEventProc; + *pOpenHandle = pChannelOpenData->OpenHandle; + + return CHANNEL_RC_OK; +} + +UINT32 FreeRDP_VirtualChannelClose(UINT32 openHandle) +{ + int index; + rdpChannels* channels; + CHANNEL_OPEN_DATA* pChannelOpenData; + + channels = freerdp_channels_find_by_open_handle(openHandle, &index); + + if ((channels == NULL) || (index < 0) || (index >= CHANNEL_MAX_COUNT)) + { + return CHANNEL_RC_BAD_CHANNEL_HANDLE; + } + + pChannelOpenData = &channels->openDataList[index]; + + if (pChannelOpenData->flags != 2) + { + return CHANNEL_RC_NOT_OPEN; + } + + pChannelOpenData->flags = 0; + + return CHANNEL_RC_OK; +} + +int freerdp_channels_client_load(rdpChannels* channels, rdpSettings* settings, void* entry, void* data) +{ + int status; + CHANNEL_ENTRY_POINTS_EX ep; + CHANNEL_CLIENT_DATA* pChannelClientData; + + if (channels->clientDataCount + 1 >= CHANNEL_MAX_COUNT) + { + fprintf(stderr, "error: too many channels\n"); + return 1; + } + + pChannelClientData = &channels->clientDataList[channels->clientDataCount]; + pChannelClientData->entry = (PVIRTUALCHANNELENTRY) entry; + + ep.cbSize = sizeof(ep); + ep.protocolVersion = VIRTUAL_CHANNEL_VERSION_WIN2000; + ep.pVirtualChannelInit = FreeRDP_VirtualChannelInit; + ep.pVirtualChannelOpen = FreeRDP_VirtualChannelOpen; + ep.pVirtualChannelClose = FreeRDP_VirtualChannelClose; + ep.pVirtualChannelWrite = FreeRDP_VirtualChannelWrite; + + g_pInterface = NULL; + ep.MagicNumber = FREERDP_CHANNEL_MAGIC_NUMBER; + ep.ppInterface = &g_pInterface; + ep.pExtendedData = data; + ep.pVirtualChannelEventPush = FreeRDP_VirtualChannelEventPush; + + /* enable VirtualChannelInit */ + channels->can_call_init = TRUE; + channels->settings = settings; + + EnterCriticalSection(&g_channels_lock); + + g_ChannelInitData.channels = channels; + status = pChannelClientData->entry((PCHANNEL_ENTRY_POINTS) &ep); + + LeaveCriticalSection(&g_channels_lock); + + /* disable MyVirtualChannelInit */ + channels->settings = NULL; + channels->can_call_init = FALSE; + + if (!status) + { + fprintf(stderr, "error: channel export function call failed\n"); + return 1; + } + + return 0; +} + +/** + * this is called when processing the command line parameters + * called only from main thread + */ +int freerdp_channels_load_plugin(rdpChannels* channels, rdpSettings* settings, const char* name, void* data) +{ + void* entry; + + entry = (PVIRTUALCHANNELENTRY) freerdp_load_channel_addin_entry(name, NULL, NULL, FREERDP_ADDIN_CHANNEL_STATIC); + + if (!entry) + { + return 1; + } + + return freerdp_channels_client_load(channels, settings, entry, data); +} + +/** + * Channels Server + */ + +/** + * Channels Common + */ + +BOOL freerdp_channel_send(rdpRdp* rdp, UINT16 channelId, BYTE* data, int size) { DWORD i; int left; wStream* s; UINT32 flags; - int chunk_size; + int chunkSize; rdpChannel* channel = NULL; for (i = 0; i < rdp->settings->ChannelCount; i++) { - if (rdp->settings->ChannelDefArray[i].ChannelId == channel_id) + if (rdp->settings->ChannelDefArray[i].ChannelId == channelId) { channel = &rdp->settings->ChannelDefArray[i]; break; @@ -53,7 +1060,7 @@ BOOL freerdp_channel_send(rdpRdp* rdp, UINT16 channel_id, BYTE* data, int size) if (!channel) { - fprintf(stderr, "freerdp_channel_send: unknown channel_id %d\n", channel_id); + fprintf(stderr, "freerdp_channel_send: unknown channel_id %d\n", channelId); return FALSE; } @@ -66,11 +1073,11 @@ BOOL freerdp_channel_send(rdpRdp* rdp, UINT16 channel_id, BYTE* data, int size) if (left > (int) rdp->settings->VirtualChannelChunkSize) { - chunk_size = rdp->settings->VirtualChannelChunkSize; + chunkSize = rdp->settings->VirtualChannelChunkSize; } else { - chunk_size = left; + chunkSize = left; flags |= CHANNEL_FLAG_LAST; } @@ -81,53 +1088,53 @@ BOOL freerdp_channel_send(rdpRdp* rdp, UINT16 channel_id, BYTE* data, int size) Stream_Write_UINT32(s, size); Stream_Write_UINT32(s, flags); - Stream_EnsureCapacity(s, chunk_size); - Stream_Write(s, data, chunk_size); + Stream_EnsureCapacity(s, chunkSize); + Stream_Write(s, data, chunkSize); - rdp_send(rdp, s, channel_id); + rdp_send(rdp, s, channelId); - data += chunk_size; - left -= chunk_size; + data += chunkSize; + left -= chunkSize; flags = 0; } return TRUE; } -BOOL freerdp_channel_process(freerdp* instance, wStream* s, UINT16 channel_id) +BOOL freerdp_channel_process(freerdp* instance, wStream* s, UINT16 channelId) { UINT32 length; UINT32 flags; - int chunk_length; + int chunkLength; if (Stream_GetRemainingLength(s) < 8) return FALSE; Stream_Read_UINT32(s, length); Stream_Read_UINT32(s, flags); - chunk_length = Stream_GetRemainingLength(s); + chunkLength = Stream_GetRemainingLength(s); IFCALL(instance->ReceiveChannelData, instance, - channel_id, Stream_Pointer(s), chunk_length, flags, length); + channelId, Stream_Pointer(s), chunkLength, flags, length); return TRUE; } -BOOL freerdp_channel_peer_process(freerdp_peer* client, wStream* s, UINT16 channel_id) +BOOL freerdp_channel_peer_process(freerdp_peer* client, wStream* s, UINT16 channelId) { UINT32 length; UINT32 flags; - int chunk_length; + int chunkLength; if (Stream_GetRemainingLength(s) < 8) return FALSE; Stream_Read_UINT32(s, length); Stream_Read_UINT32(s, flags); - chunk_length = Stream_GetRemainingLength(s); + chunkLength = Stream_GetRemainingLength(s); IFCALL(client->ReceiveChannelData, client, - channel_id, Stream_Pointer(s), chunk_length, flags, length); + channelId, Stream_Pointer(s), chunkLength, flags, length); return TRUE; }