Fix changelog email address
[freerdp-ubuntu-pcb-backport.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         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         RDP_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 static int dvcman_get_configuration(IWTSListener* pListener, void** ppPropertyBag)
84 {
85         *ppPropertyBag = NULL;
86         return 1;
87 }
88
89 static int dvcman_create_listener(IWTSVirtualChannelManager* pChannelMgr,
90         const char* pszChannelName, uint32 ulFlags,
91         IWTSListenerCallback* pListenerCallback, IWTSListener** ppListener)
92 {
93         DVCMAN* dvcman = (DVCMAN*)pChannelMgr;
94         DVCMAN_LISTENER* listener;
95
96         if (dvcman->num_listeners < MAX_PLUGINS)
97         {
98                 DEBUG_DVC("%d.%s.", dvcman->num_listeners, pszChannelName);
99                 listener = xnew(DVCMAN_LISTENER);
100                 listener->iface.GetConfiguration = dvcman_get_configuration;
101                 listener->dvcman = dvcman;
102                 listener->channel_name = xstrdup(pszChannelName);
103                 listener->flags = ulFlags;
104                 listener->listener_callback = pListenerCallback;
105
106                 if (ppListener)
107                         *ppListener = (IWTSListener*)listener;
108                 dvcman->listeners[dvcman->num_listeners++] = (IWTSListener*)listener;
109                 return 0;
110         }
111         else
112         {
113                 DEBUG_WARN("Maximum DVC listener number reached.");
114                 return 1;
115         }
116 }
117
118 static int dvcman_push_event(IWTSVirtualChannelManager* pChannelMgr, RDP_EVENT* pEvent)
119 {
120         int error;
121         DVCMAN* dvcman = (DVCMAN*) pChannelMgr;
122
123         error = drdynvc_push_event(dvcman->drdynvc, pEvent);
124
125         if (error == 0)
126         {
127                 DEBUG_DVC("event_type %d pushed.", pEvent->event_type);
128         }
129         else
130         {
131                 DEBUG_WARN("event_type %d push failed.", pEvent->event_type);
132         }
133
134         return error;
135 }
136
137 static int dvcman_register_plugin(IDRDYNVC_ENTRY_POINTS* pEntryPoints, const char* name, IWTSPlugin* pPlugin)
138 {
139         DVCMAN* dvcman = ((DVCMAN_ENTRY_POINTS*) pEntryPoints)->dvcman;
140
141         if (dvcman->num_plugins < MAX_PLUGINS)
142         {
143                 DEBUG_DVC("num_plugins %d", dvcman->num_plugins);
144                 dvcman->plugin_names[dvcman->num_plugins] = name;
145                 dvcman->plugins[dvcman->num_plugins++] = pPlugin;
146                 return 0;
147         }
148         else
149         {
150                 DEBUG_WARN("Maximum DVC plugin number reached.");
151                 return 1;
152         }
153 }
154
155 IWTSPlugin* dvcman_get_plugin(IDRDYNVC_ENTRY_POINTS* pEntryPoints, const char* name)
156 {
157         int i;
158         DVCMAN* dvcman = ((DVCMAN_ENTRY_POINTS*) pEntryPoints)->dvcman;
159
160         for (i = 0; i < dvcman->num_plugins; i++)
161         {
162                 if (dvcman->plugin_names[i] == name ||
163                         strcmp(dvcman->plugin_names[i], name) == 0)
164                 {
165                         return dvcman->plugins[i];
166                 }
167         }
168
169         return NULL;
170 }
171
172 RDP_PLUGIN_DATA* dvcman_get_plugin_data(IDRDYNVC_ENTRY_POINTS* pEntryPoints)
173 {
174         return ((DVCMAN_ENTRY_POINTS*) pEntryPoints)->plugin_data;
175 }
176
177 IWTSVirtualChannelManager* dvcman_new(drdynvcPlugin* plugin)
178 {
179         DVCMAN* dvcman;
180
181         dvcman = xnew(DVCMAN);
182         dvcman->iface.CreateListener = dvcman_create_listener;
183         dvcman->iface.PushEvent = dvcman_push_event;
184         dvcman->drdynvc = plugin;
185         dvcman->channels = list_new();
186
187         return (IWTSVirtualChannelManager*) dvcman;
188 }
189
190 int dvcman_load_plugin(IWTSVirtualChannelManager* pChannelMgr, RDP_PLUGIN_DATA* data)
191 {
192         DVCMAN_ENTRY_POINTS entryPoints;
193         PDVC_PLUGIN_ENTRY pDVCPluginEntry = NULL;
194
195         while (data && data->size > 0)
196         {
197                 pDVCPluginEntry = freerdp_load_plugin((char*) data->data[0], "DVCPluginEntry");
198
199                 if (pDVCPluginEntry != NULL)
200                 {
201                         entryPoints.iface.RegisterPlugin = dvcman_register_plugin;
202                         entryPoints.iface.GetPlugin = dvcman_get_plugin;
203                         entryPoints.iface.GetPluginData = dvcman_get_plugin_data;
204                         entryPoints.dvcman = (DVCMAN*) pChannelMgr;
205                         entryPoints.plugin_data = data;
206                         pDVCPluginEntry((IDRDYNVC_ENTRY_POINTS*) &entryPoints);
207                 }
208                 
209                 data = (RDP_PLUGIN_DATA*)(((void*) data) + data->size);
210         }
211
212         return 0;
213 }
214
215 static void dvcman_channel_free(DVCMAN_CHANNEL* channel)
216 {
217         if (channel->channel_callback)
218                 channel->channel_callback->OnClose(channel->channel_callback);
219
220         xfree(channel);
221 }
222
223 void dvcman_free(IWTSVirtualChannelManager* pChannelMgr)
224 {
225         int i;
226         IWTSPlugin* pPlugin;
227         DVCMAN_LISTENER* listener;
228         DVCMAN_CHANNEL* channel;
229         DVCMAN* dvcman = (DVCMAN*) pChannelMgr;
230
231         while ((channel = (DVCMAN_CHANNEL*) list_dequeue(dvcman->channels)) != NULL)
232                 dvcman_channel_free(channel);
233
234         list_free(dvcman->channels);
235
236         for (i = 0; i < dvcman->num_listeners; i++)
237         {
238                 listener = (DVCMAN_LISTENER*) dvcman->listeners[i];
239                 xfree(listener->channel_name);
240                 xfree(listener);
241         }
242
243         for (i = 0; i < dvcman->num_plugins; i++)
244         {
245                 pPlugin = dvcman->plugins[i];
246
247                 if (pPlugin->Terminated)
248                         pPlugin->Terminated(pPlugin);
249         }
250
251         xfree(dvcman);
252 }
253
254 int dvcman_init(IWTSVirtualChannelManager* pChannelMgr)
255 {
256         int i;
257         IWTSPlugin* pPlugin;
258         DVCMAN* dvcman = (DVCMAN*) pChannelMgr;
259
260         for (i = 0; i < dvcman->num_plugins; i++)
261         {
262                 pPlugin = dvcman->plugins[i];
263
264                 if (pPlugin->Initialize)
265                         pPlugin->Initialize(pPlugin, pChannelMgr);
266         }
267
268         return 0;
269 }
270
271 static int dvcman_write_channel(IWTSVirtualChannel* pChannel, uint32 cbSize, uint8* pBuffer, void* pReserved)
272 {
273         DVCMAN_CHANNEL* channel = (DVCMAN_CHANNEL*) pChannel;
274
275         return drdynvc_write_data(channel->dvcman->drdynvc, channel->channel_id, pBuffer, cbSize);
276 }
277
278 static int dvcman_close_channel_iface(IWTSVirtualChannel* pChannel)
279 {
280         DVCMAN_CHANNEL* channel = (DVCMAN_CHANNEL*) pChannel;
281         DVCMAN* dvcman = channel->dvcman;
282
283         DEBUG_DVC("id=%d", channel->channel_id);
284
285         if (list_remove(dvcman->channels, channel) == NULL)
286                 DEBUG_WARN("channel not found");
287
288         dvcman_channel_free(channel);
289
290         return 1;
291 }
292
293 int dvcman_create_channel(IWTSVirtualChannelManager* pChannelMgr, uint32 ChannelId, const char* ChannelName)
294 {
295         int i;
296         int bAccept;
297         DVCMAN_LISTENER* listener;
298         DVCMAN_CHANNEL* channel;
299         IWTSVirtualChannelCallback* pCallback;
300         DVCMAN* dvcman = (DVCMAN*) pChannelMgr;
301
302         for (i = 0; i < dvcman->num_listeners; i++)
303         {
304                 listener = (DVCMAN_LISTENER*)dvcman->listeners[i];
305
306                 if (strcmp(listener->channel_name, ChannelName) == 0)
307                 {
308                         channel = xnew(DVCMAN_CHANNEL);
309                         channel->iface.Write = dvcman_write_channel;
310                         channel->iface.Close = dvcman_close_channel_iface;
311                         channel->dvcman = dvcman;
312                         channel->channel_id = ChannelId;
313
314                         bAccept = 1;
315                         pCallback = NULL;
316
317                         if (listener->listener_callback->OnNewChannelConnection(listener->listener_callback,
318                                 (IWTSVirtualChannel*) channel, NULL, &bAccept, &pCallback) == 0 && bAccept == 1)
319                         {
320                                 DEBUG_DVC("listener %s created new channel %d",
321                                           listener->channel_name, channel->channel_id);
322                                 channel->channel_callback = pCallback;
323                                 list_add(dvcman->channels, channel);
324
325                                 return 0;
326                         }
327                         else
328                         {
329                                 DEBUG_WARN("channel rejected by plugin");
330                                 dvcman_channel_free(channel);
331                                 return 1;
332                         }
333                 }
334         }
335
336         return 1;
337 }
338
339 static DVCMAN_CHANNEL* dvcman_find_channel_by_id(IWTSVirtualChannelManager* pChannelMgr, uint32 ChannelId)
340 {
341         LIST_ITEM* curr;
342         DVCMAN* dvcman = (DVCMAN*) pChannelMgr;
343
344         for (curr = dvcman->channels->head; curr; curr = curr->next)
345         {
346                 if (((DVCMAN_CHANNEL*) curr->data)->channel_id == ChannelId)
347                 {
348                         return (DVCMAN_CHANNEL*)curr->data;
349                 }
350         }
351
352         return NULL;
353 }
354
355 int dvcman_close_channel(IWTSVirtualChannelManager* pChannelMgr, uint32 ChannelId)
356 {
357         DVCMAN_CHANNEL* channel;
358         IWTSVirtualChannel* ichannel;
359
360         channel = dvcman_find_channel_by_id(pChannelMgr, ChannelId);
361
362         if (channel == NULL)
363         {
364                 DEBUG_WARN("ChannelId %d not found!", ChannelId);
365                 return 1;
366         }
367
368         if (channel->dvc_data)
369         {
370                 stream_free(channel->dvc_data);
371                 channel->dvc_data = NULL;
372         }
373
374         DEBUG_DVC("dvcman_close_channel: channel %d closed", ChannelId);
375         ichannel = (IWTSVirtualChannel*)channel;
376         ichannel->Close(ichannel);
377
378         return 0;
379 }
380
381 int dvcman_receive_channel_data_first(IWTSVirtualChannelManager* pChannelMgr, uint32 ChannelId, uint32 length)
382 {
383         DVCMAN_CHANNEL* channel;
384
385         channel = dvcman_find_channel_by_id(pChannelMgr, ChannelId);
386
387         if (channel == NULL)
388         {
389                 DEBUG_WARN("ChannelId %d not found!", ChannelId);
390                 return 1;
391         }
392
393         if (channel->dvc_data)
394                 stream_free(channel->dvc_data);
395
396         channel->dvc_data = stream_new(length);
397
398         return 0;
399 }
400
401 int dvcman_receive_channel_data(IWTSVirtualChannelManager* pChannelMgr, uint32 ChannelId, uint8* data, uint32 data_size)
402 {
403         int error = 0;
404         DVCMAN_CHANNEL* channel;
405
406         channel = dvcman_find_channel_by_id(pChannelMgr, ChannelId);
407
408         if (channel == NULL)
409         {
410                 DEBUG_WARN("ChannelId %d not found!", ChannelId);
411                 return 1;
412         }
413
414         if (channel->dvc_data)
415         {
416                 /* Fragmented data */
417                 if (stream_get_length(channel->dvc_data) + data_size > stream_get_size(channel->dvc_data))
418                 {
419                         DEBUG_WARN("data exceeding declared length!");
420                         stream_free(channel->dvc_data);
421                         channel->dvc_data = NULL;
422                         return 1;
423                 }
424
425                 stream_write(channel->dvc_data, data, data_size);
426
427                 if (stream_get_length(channel->dvc_data) >= stream_get_size(channel->dvc_data))
428                 {
429                         error = channel->channel_callback->OnDataReceived(channel->channel_callback,
430                                 stream_get_size(channel->dvc_data), stream_get_data(channel->dvc_data));
431                         stream_free(channel->dvc_data);
432                         channel->dvc_data = NULL;
433                 }
434         }
435         else
436         {
437                 error = channel->channel_callback->OnDataReceived(channel->channel_callback, data_size, data);
438         }
439
440         return error;
441 }