Merge pull request #26 from bradh/master
[platform/upstream/freerdp.git] / channels / drdynvc / dvcman.c
1 /**
2  * FreeRDP: A Remote Desktop Protocol client.
3  * Dynamic Virtual Channel Manager
4  *
5  * Copyright 2010-2011 Vic Lee
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *     http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  */
19
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <freerdp/utils/memory.h>
24 #include <freerdp/utils/stream.h>
25 #include <freerdp/utils/list.h>
26 #include <freerdp/utils/load_plugin.h>
27
28 #include "drdynvc_types.h"
29 #include "dvcman.h"
30
31 #define MAX_PLUGINS 10
32
33 typedef struct _DVCMAN DVCMAN;
34 struct _DVCMAN
35 {
36         IWTSVirtualChannelManager iface;
37
38         drdynvcPlugin* drdynvc;
39
40         const char* plugin_names[MAX_PLUGINS];
41         IWTSPlugin* plugins[MAX_PLUGINS];
42         int num_plugins;
43
44         IWTSListener* listeners[MAX_PLUGINS];
45         int num_listeners;
46
47         struct dvcman_channel_list* channels;
48 };
49
50 typedef struct _DVCMAN_LISTENER DVCMAN_LISTENER;
51 struct _DVCMAN_LISTENER
52 {
53         IWTSListener iface;
54
55         DVCMAN* dvcman;
56         char* channel_name;
57         uint32 flags;
58         IWTSListenerCallback* listener_callback;
59 };
60
61 typedef struct _DVCMAN_ENTRY_POINTS DVCMAN_ENTRY_POINTS;
62 struct _DVCMAN_ENTRY_POINTS
63 {
64         IDRDYNVC_ENTRY_POINTS iface;
65
66         DVCMAN* dvcman;
67         FRDP_PLUGIN_DATA* plugin_data;
68 };
69
70 typedef struct _DVCMAN_CHANNEL DVCMAN_CHANNEL;
71 struct _DVCMAN_CHANNEL
72 {
73         IWTSVirtualChannel iface;
74
75         DVCMAN* dvcman;
76         DVCMAN_CHANNEL* next;
77         uint32 channel_id;
78         IWTSVirtualChannelCallback* channel_callback;
79
80         STREAM* dvc_data;
81 };
82
83 struct dvcman_channel_list_item
84 {
85         DVCMAN_CHANNEL channel;
86 };
87
88 DEFINE_LIST_TYPE(dvcman_channel_list, dvcman_channel_list_item)
89
90 static int dvcman_get_configuration(IWTSListener* pListener,
91         void** ppPropertyBag)
92 {
93         *ppPropertyBag = NULL;
94         return 1;
95 }
96
97 static int dvcman_create_listener(IWTSVirtualChannelManager* pChannelMgr,
98         const char* pszChannelName,
99         uint32 ulFlags,
100         IWTSListenerCallback* pListenerCallback,
101         IWTSListener** ppListener)
102 {
103         DVCMAN* dvcman = (DVCMAN*)pChannelMgr;
104         DVCMAN_LISTENER* listener;
105
106         if (dvcman->num_listeners < MAX_PLUGINS)
107         {
108                 DEBUG_DVC("%d.%s.", dvcman->num_listeners, pszChannelName);
109                 listener = xnew(DVCMAN_LISTENER);
110                 listener->iface.GetConfiguration = dvcman_get_configuration;
111                 listener->dvcman = dvcman;
112                 listener->channel_name = xstrdup(pszChannelName);
113                 listener->flags = ulFlags;
114                 listener->listener_callback = pListenerCallback;
115
116                 if (ppListener)
117                         *ppListener = (IWTSListener*)listener;
118                 dvcman->listeners[dvcman->num_listeners++] = (IWTSListener*)listener;
119                 return 0;
120         }
121         else
122         {
123                 DEBUG_WARN("Maximum DVC listener number reached.");
124                 return 1;
125         }
126 }
127
128 static int dvcman_push_event(IWTSVirtualChannelManager* pChannelMgr,
129         FRDP_EVENT* pEvent)
130 {
131         DVCMAN* dvcman = (DVCMAN*)pChannelMgr;
132         int error;
133
134         error = drdynvc_push_event(dvcman->drdynvc, pEvent);
135         if (error == 0)
136         {
137                 DEBUG_DVC("event_type %d pushed.", pEvent->event_type);
138         }
139         else
140         {
141                 DEBUG_WARN("event_type %d push failed.", pEvent->event_type);
142         }
143         return error;
144 }
145
146 static int dvcman_register_plugin(IDRDYNVC_ENTRY_POINTS* pEntryPoints,
147         const char* name, IWTSPlugin* pPlugin)
148 {
149         DVCMAN* dvcman = ((DVCMAN_ENTRY_POINTS*)pEntryPoints)->dvcman;
150
151         if (dvcman->num_plugins < MAX_PLUGINS)
152         {
153                 DEBUG_DVC("num_plugins %d", dvcman->num_plugins);
154                 dvcman->plugin_names[dvcman->num_plugins] = name;
155                 dvcman->plugins[dvcman->num_plugins++] = pPlugin;
156                 return 0;
157         }
158         else
159         {
160                 DEBUG_WARN("Maximum DVC plugin number reached.");
161                 return 1;
162         }
163 }
164
165 IWTSPlugin* dvcman_get_plugin(IDRDYNVC_ENTRY_POINTS* pEntryPoints,
166         const char* name)
167 {
168         DVCMAN* dvcman = ((DVCMAN_ENTRY_POINTS*)pEntryPoints)->dvcman;
169         int i;
170
171         for (i = 0; i < dvcman->num_plugins; i++)
172         {
173                 if (dvcman->plugin_names[i] == name ||
174                         strcmp(dvcman->plugin_names[i], name) == 0)
175                 {
176                         return dvcman->plugins[i];
177                 }
178         }
179         return NULL;
180 }
181
182 FRDP_PLUGIN_DATA* dvcman_get_plugin_data(IDRDYNVC_ENTRY_POINTS* pEntryPoints)
183 {
184         return ((DVCMAN_ENTRY_POINTS*)pEntryPoints)->plugin_data;
185 }
186
187 IWTSVirtualChannelManager* dvcman_new(drdynvcPlugin* plugin)
188 {
189         DVCMAN* dvcman;
190
191         dvcman = xnew(DVCMAN);
192         dvcman->iface.CreateListener = dvcman_create_listener;
193         dvcman->iface.PushEvent = dvcman_push_event;
194         dvcman->drdynvc = plugin;
195         dvcman->channels = dvcman_channel_list_new();
196
197         return (IWTSVirtualChannelManager*)dvcman;
198 }
199
200 int dvcman_load_plugin(IWTSVirtualChannelManager* pChannelMgr, FRDP_PLUGIN_DATA* data)
201 {
202         DVCMAN_ENTRY_POINTS entryPoints;
203         PDVC_PLUGIN_ENTRY pDVCPluginEntry = NULL;
204
205         if (data != NULL)
206         {
207                 pDVCPluginEntry = freerdp_load_plugin((char*)data->data[0], "DVCPluginEntry");
208
209                 if(pDVCPluginEntry != NULL)
210                 {
211                         entryPoints.iface.RegisterPlugin = dvcman_register_plugin;
212                         entryPoints.iface.GetPlugin = dvcman_get_plugin;
213                         entryPoints.iface.GetPluginData = dvcman_get_plugin_data;
214                         entryPoints.dvcman = (DVCMAN*)pChannelMgr;
215                         entryPoints.plugin_data = data;
216                         pDVCPluginEntry((IDRDYNVC_ENTRY_POINTS*)&entryPoints);
217                 }
218         }
219
220         return 0;
221 }
222
223 void dvcman_free(IWTSVirtualChannelManager* pChannelMgr)
224 {
225         DVCMAN* dvcman = (DVCMAN*)pChannelMgr;
226         int i;
227         IWTSPlugin* pPlugin;
228         DVCMAN_LISTENER* listener;
229
230         dvcman_channel_list_free(dvcman->channels);
231         for (i = 0; i < dvcman->num_listeners; i++)
232         {
233                 listener = (DVCMAN_LISTENER*)dvcman->listeners[i];
234                 xfree(listener->channel_name);
235                 xfree(listener);
236         }
237         for (i = 0; i < dvcman->num_plugins; i++)
238         {
239                 pPlugin = dvcman->plugins[i];
240                 if (pPlugin->Terminated)
241                         pPlugin->Terminated(pPlugin);
242         }
243         xfree(dvcman);
244 }
245
246 int dvcman_init(IWTSVirtualChannelManager* pChannelMgr)
247 {
248         DVCMAN* dvcman = (DVCMAN*)pChannelMgr;
249         int i;
250         IWTSPlugin* pPlugin;
251
252         for (i = 0; i < dvcman->num_plugins; i++)
253         {
254                 pPlugin = dvcman->plugins[i];
255                 if (pPlugin->Initialize)
256                         pPlugin->Initialize(pPlugin, pChannelMgr);
257         }
258         return 0;
259 }
260
261 static int dvcman_write_channel(IWTSVirtualChannel* pChannel,
262         uint32 cbSize,
263         char* pBuffer,
264         void* pReserved)
265 {
266         DVCMAN_CHANNEL* channel = (DVCMAN_CHANNEL*)pChannel;
267
268         return drdynvc_write_data(channel->dvcman->drdynvc, channel->channel_id, pBuffer, cbSize);
269 }
270
271 static void dvcman_channel_list_item_free(struct dvcman_channel_list_item* item)
272 {
273         DVCMAN_CHANNEL* channel = (DVCMAN_CHANNEL*)item;
274
275         if (channel->channel_callback)
276                 channel->channel_callback->OnClose(channel->channel_callback);
277         xfree(item);
278 }
279
280 static int dvcman_close_channel_iface(IWTSVirtualChannel* pChannel)
281 {
282         DVCMAN_CHANNEL* channel = (DVCMAN_CHANNEL*)pChannel;
283         DVCMAN* dvcman = channel->dvcman;
284
285         DEBUG_DVC("id=%d", channel->channel_id);
286
287         if (dvcman_channel_list_remove(dvcman->channels, (struct dvcman_channel_list_item*)channel) == NULL)
288                 DEBUG_WARN("channel not found");
289         dvcman_channel_list_item_free((struct dvcman_channel_list_item*)channel);
290
291         return 1;
292 }
293
294 int dvcman_create_channel(IWTSVirtualChannelManager* pChannelMgr, uint32 ChannelId, const char* ChannelName)
295 {
296         DVCMAN* dvcman = (DVCMAN*)pChannelMgr;
297         int i;
298         DVCMAN_LISTENER* listener;
299         DVCMAN_CHANNEL* channel;
300         struct dvcman_channel_list_item* item;
301         int bAccept;
302         IWTSVirtualChannelCallback* pCallback;
303
304         for (i = 0; i < dvcman->num_listeners; i++)
305         {
306                 listener = (DVCMAN_LISTENER*)dvcman->listeners[i];
307                 if (strcmp(listener->channel_name, ChannelName) == 0)
308                 {
309                         item = dvcman_channel_list_item_new();
310                         channel = (DVCMAN_CHANNEL*)item;
311                         channel->iface.Write = dvcman_write_channel;
312                         channel->iface.Close = dvcman_close_channel_iface;
313                         channel->dvcman = dvcman;
314                         channel->channel_id = ChannelId;
315
316                         bAccept = 1;
317                         pCallback = NULL;
318                         if (listener->listener_callback->OnNewChannelConnection(listener->listener_callback,
319                                 (IWTSVirtualChannel*)channel, NULL, &bAccept, &pCallback) == 0 && bAccept == 1)
320                         {
321                                 DEBUG_DVC("listener %s created new channel %d",
322                                           listener->channel_name, channel->channel_id);
323                                 channel->channel_callback = pCallback;
324                                 dvcman_channel_list_add(dvcman->channels, item);
325                                 return 0;
326                         }
327                         else
328                         {
329                                 DEBUG_WARN("channel rejected by plugin");
330                                 dvcman_channel_list_item_free(item);
331                                 return 1;
332                         }
333                 }
334         }
335         return 1;
336 }
337
338 static DVCMAN_CHANNEL* dvcman_find_channel_by_id(IWTSVirtualChannelManager* pChannelMgr, uint32 ChannelId)
339 {
340         DVCMAN* dvcman = (DVCMAN*)pChannelMgr;
341         struct dvcman_channel_list_item* curr;
342
343         for (curr = dvcman->channels->head; curr; curr = dvcman_channel_list_item_next(curr))
344         {
345                 if (((DVCMAN_CHANNEL*)curr)->channel_id == ChannelId)
346                 {
347                         return (DVCMAN_CHANNEL*)curr;
348                 }
349         }
350         return NULL;
351 }
352
353 int dvcman_close_channel(IWTSVirtualChannelManager* pChannelMgr, uint32 ChannelId)
354 {
355         DVCMAN_CHANNEL* channel;
356         IWTSVirtualChannel* ichannel;
357
358         channel = dvcman_find_channel_by_id(pChannelMgr, ChannelId);
359         if (channel == NULL)
360         {
361                 DEBUG_WARN("ChannelId %d not found!", ChannelId);
362                 return 1;
363         }
364         if (channel->dvc_data)
365         {
366                 stream_free(channel->dvc_data);
367                 channel->dvc_data = NULL;
368         }
369         DEBUG_DVC("dvcman_close_channel: channel %d closed", ChannelId);
370         ichannel = (IWTSVirtualChannel*)channel;
371         ichannel->Close(ichannel);
372         return 0;
373 }
374
375 int dvcman_receive_channel_data_first(IWTSVirtualChannelManager* pChannelMgr, uint32 ChannelId, uint32 length)
376 {
377         DVCMAN_CHANNEL* channel;
378
379         channel = dvcman_find_channel_by_id(pChannelMgr, ChannelId);
380         if (channel == NULL)
381         {
382                 DEBUG_WARN("ChannelId %d not found!", ChannelId);
383                 return 1;
384         }
385         if (channel->dvc_data)
386                 stream_free(channel->dvc_data);
387         channel->dvc_data = stream_new(length);
388
389         return 0;
390 }
391
392 int dvcman_receive_channel_data(IWTSVirtualChannelManager* pChannelMgr, uint32 ChannelId, uint8* data, uint32 data_size)
393 {
394         DVCMAN_CHANNEL* channel;
395         int error = 0;
396
397         channel = dvcman_find_channel_by_id(pChannelMgr, ChannelId);
398         if (channel == NULL)
399         {
400                 DEBUG_WARN("ChannelId %d not found!", ChannelId);
401                 return 1;
402         }
403
404         if (channel->dvc_data)
405         {
406                 /* Fragmented data */
407                 if (stream_get_length(channel->dvc_data) + data_size > stream_get_size(channel->dvc_data))
408                 {
409                         DEBUG_WARN("data exceeding declared length!");
410                         stream_free(channel->dvc_data);
411                         channel->dvc_data = NULL;
412                         return 1;
413                 }
414                 stream_write(channel->dvc_data, data, data_size);
415                 if (stream_get_length(channel->dvc_data) >= stream_get_size(channel->dvc_data))
416                 {
417                         error = channel->channel_callback->OnDataReceived(channel->channel_callback,
418                                 stream_get_size(channel->dvc_data), stream_get_data(channel->dvc_data));
419                         stream_free(channel->dvc_data);
420                         channel->dvc_data = NULL;
421                 }
422         }
423         else
424         {
425                 error = channel->channel_callback->OnDataReceived(channel->channel_callback,
426                         data_size, data);
427         }
428
429         return error;
430 }