2 * FreeRDP: A Remote Desktop Protocol client.
3 * Server Virtual Channel Interface
5 * Copyright 2011-2012 Vic Lee
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
11 * http://www.apache.org/licenses/LICENSE-2.0
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.
24 #include <freerdp/constants.h>
25 #include <freerdp/utils/memory.h>
29 typedef struct wts_data_item
36 static void wts_data_item_free(wts_data_item* item)
42 static void WTSProcessChannelData(rdpPeerChannel* channel, int channelId, uint8* data, int size, int flags, int total_size)
46 if (flags & CHANNEL_FLAG_FIRST)
48 stream_set_pos(channel->receive_data, 0);
51 stream_check_size(channel->receive_data, size);
52 stream_write(channel->receive_data, data, size);
54 if (flags & CHANNEL_FLAG_LAST)
56 if (stream_get_length(channel->receive_data) != total_size)
58 printf("WTSProcessChannelData: read error\n");
60 if (channel->channel_type == RDP_PEER_CHANNEL_TYPE_DVC)
62 /* TODO: Receive DVC channel data */
66 item = xnew(wts_data_item);
67 item->length = stream_get_length(channel->receive_data);
68 item->buffer = xmalloc(item->length);
69 memcpy(item->buffer, stream_get_head(channel->receive_data), item->length);
71 freerdp_mutex_lock(channel->mutex);
72 list_enqueue(channel->receive_queue, item);
73 freerdp_mutex_unlock(channel->mutex);
75 wait_obj_set(channel->receive_event);
77 stream_set_pos(channel->receive_data, 0);
81 static int WTSReceiveChannelData(freerdp_peer* client, int channelId, uint8* data, int size, int flags, int total_size)
84 boolean result = false;
85 rdpPeerChannel* channel;
87 for (i = 0; i < client->settings->num_channels; i++)
89 if (client->settings->channels[i].channel_id == channelId)
92 if (i < client->settings->num_channels)
94 channel = (rdpPeerChannel*) client->settings->channels[i].handle;
97 WTSProcessChannelData(channel, channelId, data, size, flags, total_size);
105 WTSVirtualChannelManager* WTSCreateVirtualChannelManager(freerdp_peer* client)
107 WTSVirtualChannelManager* vcm;
109 vcm = xnew(WTSVirtualChannelManager);
112 vcm->client = client;
113 vcm->send_event = wait_obj_new();
114 vcm->send_queue = list_new();
115 vcm->mutex = freerdp_mutex_new();
117 client->ReceiveChannelData = WTSReceiveChannelData;
123 void WTSDestroyVirtualChannelManager(WTSVirtualChannelManager* vcm)
129 if (vcm->drdynvc_channel != NULL)
131 WTSVirtualChannelClose(vcm->drdynvc_channel);
132 vcm->drdynvc_channel = NULL;
135 wait_obj_free(vcm->send_event);
136 while ((item = (wts_data_item*) list_dequeue(vcm->send_queue)) != NULL)
138 wts_data_item_free(item);
140 list_free(vcm->send_queue);
141 freerdp_mutex_free(vcm->mutex);
146 void WTSVirtualChannelManagerGetFileDescriptor(WTSVirtualChannelManager* vcm,
147 void** fds, int* fds_count)
149 wait_obj_get_fds(vcm->send_event, fds, fds_count);
152 boolean WTSVirtualChannelManagerCheckFileDescriptor(WTSVirtualChannelManager* vcm)
154 boolean result = true;
157 wait_obj_clear(vcm->send_event);
159 freerdp_mutex_lock(vcm->mutex);
160 while ((item = (wts_data_item*) list_dequeue(vcm->send_queue)) != NULL)
162 if (vcm->client->SendChannelData(vcm->client, item->channel_id, item->buffer, item->length) == false)
166 wts_data_item_free(item);
170 freerdp_mutex_unlock(vcm->mutex);
175 void* WTSVirtualChannelOpenEx(
176 /* __in */ WTSVirtualChannelManager* vcm,
177 /* __in */ const char* pVirtualName,
178 /* __in */ uint32 flags)
182 rdpPeerChannel* channel;
183 const char* channel_name;
184 freerdp_peer* client = vcm->client;
186 channel_name = ((flags & WTS_CHANNEL_OPTION_DYNAMIC) != 0 ? "drdynvc" : pVirtualName);
188 len = strlen(channel_name);
192 for (i = 0; i < client->settings->num_channels; i++)
194 if (client->settings->channels[i].joined &&
195 strncmp(client->settings->channels[i].name, channel_name, len) == 0)
200 if (i >= client->settings->num_channels)
203 channel = (rdpPeerChannel*) client->settings->channels[i].handle;
206 channel = xnew(rdpPeerChannel);
208 channel->client = client;
209 channel->channel_id = client->settings->channels[i].channel_id;
211 channel->receive_data = stream_new(client->settings->vc_chunk_size);
212 if ((flags & WTS_CHANNEL_OPTION_DYNAMIC) != 0)
214 channel->channel_type = RDP_PEER_CHANNEL_TYPE_DVC;
215 vcm->drdynvc_channel = channel;
219 channel->channel_type = RDP_PEER_CHANNEL_TYPE_SVC;
220 channel->receive_event = wait_obj_new();
221 channel->receive_queue = list_new();
222 channel->mutex = freerdp_mutex_new();
225 client->settings->channels[i].handle = channel;
227 if (channel->channel_type == RDP_PEER_CHANNEL_TYPE_DVC)
229 /* TODO: do DVC channel initialization here using pVirtualName */
230 /* A sub-channel should be created and returned, instead of using the main drdynvc channel */
231 /* Set channel->index to num_channels */
237 boolean WTSVirtualChannelQuery(
238 /* __in */ void* hChannelHandle,
239 /* __in */ WTS_VIRTUAL_CLASS WtsVirtualClass,
240 /* __out */ void** ppBuffer,
241 /* __out */ uint32* pBytesReturned)
245 boolean result = false;
246 rdpPeerChannel* channel = (rdpPeerChannel*) hChannelHandle;
248 switch (WtsVirtualClass)
250 case WTSVirtualFileHandle:
251 wait_obj_get_fds(channel->receive_event, fds, &fds_count);
252 *ppBuffer = xmalloc(sizeof(void*));
253 memcpy(*ppBuffer, &fds[0], sizeof(void*));
254 *pBytesReturned = sizeof(void*);
265 /* __in */ void* pMemory)
270 boolean WTSVirtualChannelRead(
271 /* __in */ void* hChannelHandle,
272 /* __in */ uint32 TimeOut,
273 /* __out */ uint8* Buffer,
274 /* __in */ uint32 BufferSize,
275 /* __out */ uint32* pBytesRead)
278 rdpPeerChannel* channel = (rdpPeerChannel*) hChannelHandle;
280 item = (wts_data_item*) list_peek(channel->receive_queue);
283 wait_obj_clear(channel->receive_event);
287 *pBytesRead = item->length;
288 if (item->length > BufferSize)
291 /* remove the first element (same as what we just peek) */
292 freerdp_mutex_lock(channel->mutex);
293 list_dequeue(channel->receive_queue);
294 if (channel->receive_queue->head == NULL)
295 wait_obj_clear(channel->receive_event);
296 freerdp_mutex_unlock(channel->mutex);
298 memcpy(Buffer, item->buffer, item->length);
303 boolean WTSVirtualChannelWrite(
304 /* __in */ void* hChannelHandle,
305 /* __in */ uint8* Buffer,
306 /* __in */ uint32 Length,
307 /* __out */ uint32* pBytesWritten)
311 boolean result = false;
312 rdpPeerChannel* channel = (rdpPeerChannel*) hChannelHandle;
313 WTSVirtualChannelManager* vcm = channel->vcm;
318 if (channel->channel_type == RDP_PEER_CHANNEL_TYPE_SVC)
320 item = xnew(wts_data_item);
321 item->channel_id = channel->channel_id;
322 item->buffer = xmalloc(Length);
323 item->length = Length;
324 memcpy(item->buffer, Buffer, Length);
326 freerdp_mutex_lock(vcm->mutex);
327 list_enqueue(vcm->send_queue, item);
328 freerdp_mutex_unlock(vcm->mutex);
330 wait_obj_set(vcm->send_event);
337 /* TODO: Send to DVC channel */
340 if (pBytesWritten != NULL)
341 *pBytesWritten = written;
345 boolean WTSVirtualChannelClose(
346 /* __in */ void* hChannelHandle)
349 rdpPeerChannel* channel = (rdpPeerChannel*) hChannelHandle;
353 if (channel->index < channel->client->settings->num_channels)
354 channel->client->settings->channels[channel->index].handle = NULL;
355 stream_free(channel->receive_data);
356 if (channel->receive_event)
357 wait_obj_free(channel->receive_event);
358 if (channel->receive_queue)
360 while ((item = (wts_data_item*) list_dequeue(channel->receive_queue)) != NULL)
362 wts_data_item_free(item);
364 list_free(channel->receive_queue);
367 freerdp_mutex_free(channel->mutex);