--- /dev/null
+/**
+ * FreeRDP: A Remote Desktop Protocol client.
+ * Static Virtual Channel Interface
+ *
+ * Copyright 2009-2011 Jay Sorg
+ * Copyright 2010-2011 Vic Lee
+ *
+ * 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 __SVC_PLUGIN_UTILS_H
+#define __SVC_PLUGIN_UTILS_H
+
+/* static channel plugin base implementation */
+
+#include <freerdp/svc.h>
+
+typedef struct rdp_svc_plugin_private rdpSvcPluginPrivate;
+typedef struct rdp_svc_plugin rdpSvcPlugin;
+struct rdp_svc_plugin
+{
+ CHANNEL_ENTRY_POINTS channel_entry_points;
+ CHANNEL_DEF channel_def;
+
+ void (*connect_callback)(rdpSvcPlugin* plugin);
+ void (*receive_callback)(rdpSvcPlugin* plugin, uint8* data, int size);
+ void (*terminate_callback)(rdpSvcPlugin* plugin);
+
+ rdpSvcPluginPrivate* priv;
+};
+
+void svc_plugin_init(rdpSvcPlugin* plugin);
+int svc_plugin_send(rdpSvcPlugin* plugin, uint8* data, int size);
+
+#endif /* __SVC_PLUGIN_UTILS_H */
--- /dev/null
+/**
+ * FreeRDP: A Remote Desktop Protocol client.
+ * Static Virtual Channel Interface
+ *
+ * Copyright 2009-2011 Jay Sorg
+ * Copyright 2010-2011 Vic Lee
+ *
+ * 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 "config.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <freerdp/utils/memory.h>
+#include <freerdp/utils/mutex.h>
+#include <freerdp/utils/debug.h>
+#include <freerdp/utils/svc_plugin.h>
+
+#ifdef WITH_DEBUG_SVC
+#define DEBUG_SVC(fmt, ...) DEBUG_CLASS(SVC, fmt, ## __VA_ARGS__)
+#else
+#define DEBUG_SVC(fmt, ...) DEBUG_NULL(fmt, ## __VA_ARGS__)
+#endif
+
+/* The list of all plugin instances. */
+typedef struct rdp_svc_plugin_list rdpSvcPluginList;
+struct rdp_svc_plugin_list
+{
+ rdpSvcPlugin* plugin;
+ rdpSvcPluginList* next;
+};
+
+static rdpSvcPluginList* g_svc_plugin_list = NULL;
+
+/* For locking the global resources */
+static freerdp_mutex g_mutex = NULL;
+
+struct rdp_svc_plugin_private
+{
+ void* init_handle;
+ uint32 open_handle;
+};
+
+static rdpSvcPlugin* svc_plugin_find_by_init_handle(void* init_handle)
+{
+ rdpSvcPluginList * list;
+ rdpSvcPlugin * plugin;
+
+ freerdp_mutex_lock(g_mutex);
+ for (list = g_svc_plugin_list; list; list = list->next)
+ {
+ plugin = list->plugin;
+ if (plugin->priv->init_handle == init_handle)
+ {
+ freerdp_mutex_unlock(g_mutex);
+ return plugin;
+ }
+ }
+ freerdp_mutex_unlock(g_mutex);
+ return NULL;
+}
+
+static rdpSvcPlugin* svc_plugin_find_by_open_handle(uint32 open_handle)
+{
+ rdpSvcPluginList * list;
+ rdpSvcPlugin * plugin;
+
+ freerdp_mutex_lock(g_mutex);
+ for (list = g_svc_plugin_list; list; list = list->next)
+ {
+ plugin = list->plugin;
+ if (plugin->priv->open_handle == open_handle)
+ {
+ freerdp_mutex_unlock(g_mutex);
+ return plugin;
+ }
+ }
+ freerdp_mutex_unlock(g_mutex);
+ return NULL;
+}
+
+static void svc_plugin_remove(rdpSvcPlugin* plugin)
+{
+ rdpSvcPluginList* list;
+ rdpSvcPluginList* prev;
+
+ /* Remove from global list */
+ freerdp_mutex_lock(g_mutex);
+ for (prev = NULL, list = g_svc_plugin_list; list; prev = list, list = list->next)
+ {
+ if (list->plugin == plugin)
+ break;
+ }
+ if (list)
+ {
+ if (prev)
+ prev->next = list->next;
+ else
+ g_svc_plugin_list = list->next;
+ xfree(list);
+ }
+ freerdp_mutex_unlock(g_mutex);
+}
+
+static void svc_plugin_process_received(rdpSvcPlugin* plugin, void* pData, uint32 dataLength,
+ uint32 totalLength, uint32 dataFlags)
+{
+ plugin->receive_callback(plugin, (uint8*)pData, dataLength);
+}
+
+static void svc_plugin_open_event(uint32 openHandle, uint32 event, void* pData, uint32 dataLength,
+ uint32 totalLength, uint32 dataFlags)
+{
+ rdpSvcPlugin* plugin;
+
+ DEBUG_SVC("event %d dataLength %d", event, dataLength);
+
+ plugin = (rdpSvcPlugin*)svc_plugin_find_by_open_handle(openHandle);
+ if (plugin == NULL)
+ {
+ printf("svc_plugin_open_event: error no match\n");
+ return;
+ }
+ switch (event)
+ {
+ case CHANNEL_EVENT_DATA_RECEIVED:
+ svc_plugin_process_received(plugin, pData, dataLength, totalLength, dataFlags);
+ break;
+ case CHANNEL_EVENT_WRITE_COMPLETE:
+ xfree(pData);
+ break;
+ }
+}
+
+static void svc_plugin_process_connected(rdpSvcPlugin* plugin, void* pData, uint32 dataLength)
+{
+ uint32 error;
+
+ error = plugin->channel_entry_points.pVirtualChannelOpen(plugin->priv->init_handle, &plugin->priv->open_handle,
+ plugin->channel_def.name, svc_plugin_open_event);
+ if (error != CHANNEL_RC_OK)
+ {
+ printf("svc_plugin_process_connected: open failed\n");
+ return;
+ }
+ plugin->connect_callback(plugin);
+}
+
+static void svc_plugin_process_terminated(rdpSvcPlugin* plugin)
+{
+ plugin->channel_entry_points.pVirtualChannelClose(plugin->priv->open_handle);
+ svc_plugin_remove(plugin);
+ xfree(plugin->priv);
+ plugin->priv = NULL;
+ plugin->terminate_callback(plugin);
+}
+
+static void svc_plugin_init_event(void* pInitHandle, uint32 event, void* pData, uint32 dataLength)
+{
+ rdpSvcPlugin* plugin;
+
+ DEBUG_SVC("event %d", event);
+
+ plugin = (rdpSvcPlugin*)svc_plugin_find_by_init_handle(pInitHandle);
+ if (plugin == NULL)
+ {
+ printf("svc_plugin_init_event: error no match\n");
+ return;
+ }
+ switch (event)
+ {
+ case CHANNEL_EVENT_CONNECTED:
+ svc_plugin_process_connected(plugin, pData, dataLength);
+ break;
+ case CHANNEL_EVENT_DISCONNECTED:
+ break;
+ case CHANNEL_EVENT_TERMINATED:
+ svc_plugin_process_terminated(plugin);
+ break;
+ }
+}
+
+void svc_plugin_init(rdpSvcPlugin* plugin)
+{
+ rdpSvcPluginList* list;
+
+ /**
+ * The channel manager will guarantee only one thread can call
+ * VirtualChannelInit at a time. So this should be safe.
+ */
+ if (g_mutex == NULL)
+ g_mutex = freerdp_mutex_new();
+
+ plugin->priv = (rdpSvcPluginPrivate*)xmalloc(sizeof(rdpSvcPluginPrivate));
+ memset(plugin->priv, 0, sizeof(rdpSvcPluginPrivate));
+
+ /* Add it to the global list */
+ list = (rdpSvcPluginList*)xmalloc(sizeof(rdpSvcPluginList));
+ list->plugin = plugin;
+
+ freerdp_mutex_lock(g_mutex);
+ list->next = g_svc_plugin_list;
+ g_svc_plugin_list = list;
+ freerdp_mutex_unlock(g_mutex);
+
+ plugin->channel_entry_points.pVirtualChannelInit(&plugin->priv->init_handle,
+ &plugin->channel_def, 1, VIRTUAL_CHANNEL_VERSION_WIN2000, svc_plugin_init_event);
+}
+
+int svc_plugin_send(rdpSvcPlugin* plugin, uint8* data, int size)
+{
+ uint32 error = 0;
+
+ DEBUG_SVC("size %d", size);
+
+ error = plugin->channel_entry_points.pVirtualChannelWrite(plugin->priv->open_handle,
+ data, size, data);
+ if (error != CHANNEL_RC_OK)
+ printf("svc_plugin_send: VirtualChannelWrite failed %d", error);
+
+ return error;
+}