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