~ubuntu-branches/ubuntu/vivid/freerdp/vivid

« back to all changes in this revision

Viewing changes to libfreerdp/core/gateway/rpc_client.c

  • Committer: Package Import Robot
  • Author(s): Iain Lane
  • Date: 2014-11-11 12:20:50 UTC
  • mfrom: (1.1.9) (9.1.17 sid)
  • Revision ID: package-import@ubuntu.com-20141111122050-wyr8hrnwco9fcmum
Tags: 1.1.0~git20140921.1.440916e+dfsg1-2ubuntu1
* Merge with Debian unstable, remaining changes
  - Disable ffmpeg support
* Disable gstreamer support, this relies on gstreamer 0.10 and we don't want
  to add any more deps on that.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/**
 
2
 * FreeRDP: A Remote Desktop Protocol Implementation
 
3
 * RPC Client
 
4
 *
 
5
 * Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
 
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
#ifdef HAVE_CONFIG_H
 
21
#include "config.h"
 
22
#endif
 
23
 
 
24
#include <stdio.h>
 
25
#include <stdlib.h>
 
26
#include <string.h>
 
27
 
 
28
#include <winpr/crt.h>
 
29
#include <winpr/print.h>
 
30
#include <winpr/synch.h>
 
31
#include <winpr/thread.h>
 
32
#include <winpr/stream.h>
 
33
 
 
34
#include "rpc_fault.h"
 
35
 
 
36
#include "rpc_client.h"
 
37
 
 
38
#include "../rdp.h"
 
39
 
 
40
wStream* rpc_client_fragment_pool_take(rdpRpc* rpc)
 
41
{
 
42
        wStream* fragment = NULL;
 
43
 
 
44
        if (WaitForSingleObject(Queue_Event(rpc->client->FragmentPool), 0) == WAIT_OBJECT_0)
 
45
                fragment = Queue_Dequeue(rpc->client->FragmentPool);
 
46
 
 
47
        if (!fragment)
 
48
                fragment = Stream_New(NULL, rpc->max_recv_frag);
 
49
 
 
50
        return fragment;
 
51
}
 
52
 
 
53
int rpc_client_fragment_pool_return(rdpRpc* rpc, wStream* fragment)
 
54
{
 
55
        Queue_Enqueue(rpc->client->FragmentPool, fragment);
 
56
        return 0;
 
57
}
 
58
 
 
59
RPC_PDU* rpc_client_receive_pool_take(rdpRpc* rpc)
 
60
{
 
61
        RPC_PDU* pdu = NULL;
 
62
 
 
63
        if (WaitForSingleObject(Queue_Event(rpc->client->ReceivePool), 0) == WAIT_OBJECT_0)
 
64
                pdu = Queue_Dequeue(rpc->client->ReceivePool);
 
65
 
 
66
        if (!pdu)
 
67
        {
 
68
                pdu = (RPC_PDU*) malloc(sizeof(RPC_PDU));
 
69
                pdu->s = Stream_New(NULL, rpc->max_recv_frag);
 
70
        }
 
71
 
 
72
        pdu->CallId = 0;
 
73
        pdu->Flags = 0;
 
74
 
 
75
        Stream_Length(pdu->s) = 0;
 
76
        Stream_SetPosition(pdu->s, 0);
 
77
 
 
78
        return pdu;
 
79
}
 
80
 
 
81
int rpc_client_receive_pool_return(rdpRpc* rpc, RPC_PDU* pdu)
 
82
{
 
83
        Queue_Enqueue(rpc->client->ReceivePool, pdu);
 
84
        return 0;
 
85
}
 
86
 
 
87
int rpc_client_on_fragment_received_event(rdpRpc* rpc)
 
88
{
 
89
        BYTE* buffer;
 
90
        UINT32 StubOffset;
 
91
        UINT32 StubLength;
 
92
        wStream* fragment;
 
93
        rpcconn_hdr_t* header;
 
94
        freerdp* instance;
 
95
 
 
96
        instance = (freerdp*) rpc->transport->settings->instance;
 
97
 
 
98
        if (!rpc->client->pdu)
 
99
                rpc->client->pdu = rpc_client_receive_pool_take(rpc);
 
100
 
 
101
        fragment = Queue_Dequeue(rpc->client->FragmentQueue);
 
102
 
 
103
        buffer = (BYTE*) Stream_Buffer(fragment);
 
104
        header = (rpcconn_hdr_t*) Stream_Buffer(fragment);
 
105
 
 
106
        if (rpc->State < RPC_CLIENT_STATE_CONTEXT_NEGOTIATED)
 
107
        {
 
108
                rpc->client->pdu->Flags = 0;
 
109
                rpc->client->pdu->CallId = header->common.call_id;
 
110
 
 
111
                Stream_EnsureCapacity(rpc->client->pdu->s, Stream_Length(fragment));
 
112
                Stream_Write(rpc->client->pdu->s, buffer, Stream_Length(fragment));
 
113
                Stream_Length(rpc->client->pdu->s) = Stream_GetPosition(rpc->client->pdu->s);
 
114
 
 
115
                rpc_client_fragment_pool_return(rpc, fragment);
 
116
 
 
117
                Queue_Enqueue(rpc->client->ReceiveQueue, rpc->client->pdu);
 
118
                SetEvent(rpc->transport->ReceiveEvent);
 
119
                rpc->client->pdu = NULL;
 
120
 
 
121
                return 0;
 
122
        }
 
123
 
 
124
        if (header->common.ptype == PTYPE_RTS)
 
125
        {
 
126
                if (rpc->VirtualConnection->State >= VIRTUAL_CONNECTION_STATE_OPENED)
 
127
                {
 
128
                        //fprintf(stderr, "Receiving Out-of-Sequence RTS PDU\n");
 
129
                        rts_recv_out_of_sequence_pdu(rpc, buffer, header->common.frag_length);
 
130
 
 
131
                        rpc_client_fragment_pool_return(rpc, fragment);
 
132
                }
 
133
                else
 
134
                {
 
135
                        fprintf(stderr, "warning: unhandled RTS PDU\n");
 
136
                }
 
137
 
 
138
                return 0;
 
139
        }
 
140
        else if (header->common.ptype == PTYPE_FAULT)
 
141
        {
 
142
                rpc_recv_fault_pdu(header);
 
143
                return -1;
 
144
        }
 
145
 
 
146
        if (header->common.ptype != PTYPE_RESPONSE)
 
147
        {
 
148
                fprintf(stderr, "Unexpected RPC PDU type: %d\n", header->common.ptype);
 
149
                return -1;
 
150
        }
 
151
 
 
152
        rpc->VirtualConnection->DefaultOutChannel->BytesReceived += header->common.frag_length;
 
153
        rpc->VirtualConnection->DefaultOutChannel->ReceiverAvailableWindow -= header->common.frag_length;
 
154
 
 
155
        if (!rpc_get_stub_data_info(rpc, buffer, &StubOffset, &StubLength))
 
156
        {
 
157
                fprintf(stderr, "rpc_recv_pdu_fragment: expected stub\n");
 
158
                return -1;
 
159
        }
 
160
 
 
161
        if (StubLength == 4)
 
162
        {
 
163
                //fprintf(stderr, "Ignoring TsProxySendToServer Response\n");
 
164
                printf("Got stub length 4 with flags %d and callid %d\n", header->common.pfc_flags, header->common.call_id);
 
165
 
 
166
                /* received a disconnect request from the server? */
 
167
                if ((header->common.call_id == rpc->PipeCallId) && (header->common.pfc_flags & PFC_LAST_FRAG))
 
168
                {
 
169
                        TerminateEventArgs e;
 
170
 
 
171
                        instance->context->rdp->disconnect = TRUE;
 
172
                        rpc->transport->tsg->state = TSG_STATE_TUNNEL_CLOSE_PENDING;
 
173
 
 
174
                        EventArgsInit(&e, "freerdp");
 
175
                        e.code = 0;
 
176
                        PubSub_OnTerminate(instance->context->pubSub, instance->context, &e);
 
177
                }
 
178
 
 
179
                rpc_client_fragment_pool_return(rpc, fragment);
 
180
                return 0;
 
181
        }
 
182
 
 
183
        Stream_EnsureCapacity(rpc->client->pdu->s, header->response.alloc_hint);
 
184
        buffer = (BYTE*) Stream_Buffer(fragment);
 
185
        header = (rpcconn_hdr_t*) Stream_Buffer(fragment);
 
186
 
 
187
        if (rpc->StubFragCount == 0)
 
188
                rpc->StubCallId = header->common.call_id;
 
189
 
 
190
        if (rpc->StubCallId != header->common.call_id)
 
191
        {
 
192
                fprintf(stderr, "invalid call_id: actual: %d, expected: %d, frag_count: %d\n",
 
193
                                rpc->StubCallId, header->common.call_id, rpc->StubFragCount);
 
194
        }
 
195
 
 
196
        Stream_Write(rpc->client->pdu->s, &buffer[StubOffset], StubLength);
 
197
        rpc->StubFragCount++;
 
198
 
 
199
        rpc_client_fragment_pool_return(rpc, fragment);
 
200
 
 
201
        if (rpc->VirtualConnection->DefaultOutChannel->ReceiverAvailableWindow < (rpc->ReceiveWindow / 2))
 
202
        {
 
203
                //fprintf(stderr, "Sending Flow Control Ack PDU\n");
 
204
                rts_send_flow_control_ack_pdu(rpc);
 
205
        }
 
206
 
 
207
        /**
 
208
         * If alloc_hint is set to a nonzero value and a request or a response is fragmented into multiple
 
209
         * PDUs, implementations of these extensions SHOULD set the alloc_hint field in every PDU to be the
 
210
         * combined stub data length of all remaining fragment PDUs.
 
211
         */
 
212
 
 
213
        if (header->response.alloc_hint == StubLength)
 
214
        {
 
215
                rpc->client->pdu->Flags = RPC_PDU_FLAG_STUB;
 
216
                rpc->client->pdu->CallId = rpc->StubCallId;
 
217
 
 
218
                Stream_Length(rpc->client->pdu->s) = Stream_GetPosition(rpc->client->pdu->s);
 
219
 
 
220
                rpc->StubFragCount = 0;
 
221
                rpc->StubCallId = 0;
 
222
 
 
223
                Queue_Enqueue(rpc->client->ReceiveQueue, rpc->client->pdu);
 
224
 
 
225
                rpc->client->pdu = NULL;
 
226
 
 
227
                return 0;
 
228
        }
 
229
 
 
230
        return 0;
 
231
}
 
232
 
 
233
int rpc_client_on_read_event(rdpRpc* rpc)
 
234
{
 
235
        int position;
 
236
        int status = -1;
 
237
        rpcconn_common_hdr_t* header;
 
238
 
 
239
        if (!rpc->client->RecvFrag)
 
240
                rpc->client->RecvFrag = rpc_client_fragment_pool_take(rpc);
 
241
 
 
242
        position = Stream_GetPosition(rpc->client->RecvFrag);
 
243
 
 
244
        if (Stream_GetPosition(rpc->client->RecvFrag) < RPC_COMMON_FIELDS_LENGTH)
 
245
        {
 
246
                status = rpc_out_read(rpc, Stream_Pointer(rpc->client->RecvFrag),
 
247
                                RPC_COMMON_FIELDS_LENGTH - Stream_GetPosition(rpc->client->RecvFrag));
 
248
 
 
249
                if (status < 0)
 
250
                {
 
251
                        fprintf(stderr, "rpc_client_frag_read: error reading header\n");
 
252
                        return -1;
 
253
                }
 
254
 
 
255
                Stream_Seek(rpc->client->RecvFrag, status);
 
256
        }
 
257
 
 
258
        if (Stream_GetPosition(rpc->client->RecvFrag) >= RPC_COMMON_FIELDS_LENGTH)
 
259
        {
 
260
                header = (rpcconn_common_hdr_t*) Stream_Buffer(rpc->client->RecvFrag);
 
261
 
 
262
                if (header->frag_length > rpc->max_recv_frag)
 
263
                {
 
264
                        fprintf(stderr, "rpc_client_frag_read: invalid fragment size: %d (max: %d)\n",
 
265
                                        header->frag_length, rpc->max_recv_frag);
 
266
                        winpr_HexDump(Stream_Buffer(rpc->client->RecvFrag), Stream_GetPosition(rpc->client->RecvFrag));
 
267
                        return -1;
 
268
                }
 
269
 
 
270
                if (Stream_GetPosition(rpc->client->RecvFrag) < header->frag_length)
 
271
                {
 
272
                        status = rpc_out_read(rpc, Stream_Pointer(rpc->client->RecvFrag),
 
273
                                        header->frag_length - Stream_GetPosition(rpc->client->RecvFrag));
 
274
 
 
275
                        if (status < 0)
 
276
                        {
 
277
                                fprintf(stderr, "rpc_client_frag_read: error reading fragment body\n");
 
278
                                return -1;
 
279
                        }
 
280
 
 
281
                        Stream_Seek(rpc->client->RecvFrag, status);
 
282
                }
 
283
        }
 
284
        else
 
285
        {
 
286
                return status;
 
287
        }
 
288
 
 
289
        if (status < 0)
 
290
                return -1;
 
291
 
 
292
        status = Stream_GetPosition(rpc->client->RecvFrag) - position;
 
293
 
 
294
        if (Stream_GetPosition(rpc->client->RecvFrag) >= header->frag_length)
 
295
        {
 
296
                /* complete fragment received */
 
297
 
 
298
                Stream_Length(rpc->client->RecvFrag) = Stream_GetPosition(rpc->client->RecvFrag);
 
299
                Stream_SetPosition(rpc->client->RecvFrag, 0);
 
300
 
 
301
                Queue_Enqueue(rpc->client->FragmentQueue, rpc->client->RecvFrag);
 
302
                rpc->client->RecvFrag = NULL;
 
303
 
 
304
                rpc_client_on_fragment_received_event(rpc);
 
305
        }
 
306
 
 
307
        return status;
 
308
}
 
309
 
 
310
/**
 
311
 * [MS-RPCE] Client Call:
 
312
 * http://msdn.microsoft.com/en-us/library/gg593159/
 
313
 */
 
314
 
 
315
RpcClientCall* rpc_client_call_find_by_id(rdpRpc* rpc, UINT32 CallId)
 
316
{
 
317
        int index;
 
318
        int count;
 
319
        RpcClientCall* clientCall;
 
320
 
 
321
        ArrayList_Lock(rpc->client->ClientCallList);
 
322
 
 
323
        clientCall = NULL;
 
324
        count = ArrayList_Count(rpc->client->ClientCallList);
 
325
 
 
326
        for (index = 0; index < count; index++)
 
327
        {
 
328
                clientCall = (RpcClientCall*) ArrayList_GetItem(rpc->client->ClientCallList, index);
 
329
 
 
330
                if (clientCall->CallId == CallId)
 
331
                        break;
 
332
        }
 
333
 
 
334
        ArrayList_Unlock(rpc->client->ClientCallList);
 
335
 
 
336
        return clientCall;
 
337
}
 
338
 
 
339
RpcClientCall* rpc_client_call_new(UINT32 CallId, UINT32 OpNum)
 
340
{
 
341
        RpcClientCall* clientCall;
 
342
 
 
343
        clientCall = (RpcClientCall*) malloc(sizeof(RpcClientCall));
 
344
 
 
345
        if (clientCall)
 
346
        {
 
347
                clientCall->CallId = CallId;
 
348
                clientCall->OpNum = OpNum;
 
349
                clientCall->State = RPC_CLIENT_CALL_STATE_SEND_PDUS;
 
350
        }
 
351
 
 
352
        return clientCall;
 
353
}
 
354
 
 
355
void rpc_client_call_free(RpcClientCall* clientCall)
 
356
{
 
357
        free(clientCall);
 
358
}
 
359
 
 
360
int rpc_send_enqueue_pdu(rdpRpc* rpc, BYTE* buffer, UINT32 length)
 
361
{
 
362
        RPC_PDU* pdu;
 
363
 
 
364
        pdu = (RPC_PDU*) malloc(sizeof(RPC_PDU));
 
365
        pdu->s = Stream_New(buffer, length);
 
366
 
 
367
        Queue_Enqueue(rpc->client->SendQueue, pdu);
 
368
 
 
369
        if (rpc->client->SynchronousSend)
 
370
        {
 
371
                WaitForSingleObject(rpc->client->PduSentEvent, INFINITE);
 
372
                ResetEvent(rpc->client->PduSentEvent);
 
373
        }
 
374
 
 
375
        return 0;
 
376
}
 
377
 
 
378
int rpc_send_dequeue_pdu(rdpRpc* rpc)
 
379
{
 
380
        int status;
 
381
        RPC_PDU* pdu;
 
382
        RpcClientCall* clientCall;
 
383
        rpcconn_common_hdr_t* header;
 
384
 
 
385
        pdu = (RPC_PDU*) Queue_Dequeue(rpc->client->SendQueue);
 
386
 
 
387
        if (!pdu)
 
388
                return 0;
 
389
 
 
390
        WaitForSingleObject(rpc->VirtualConnection->DefaultInChannel->Mutex, INFINITE);
 
391
 
 
392
        status = rpc_in_write(rpc, Stream_Buffer(pdu->s), Stream_Length(pdu->s));
 
393
 
 
394
        header = (rpcconn_common_hdr_t*) Stream_Buffer(pdu->s);
 
395
        clientCall = rpc_client_call_find_by_id(rpc, header->call_id);
 
396
        clientCall->State = RPC_CLIENT_CALL_STATE_DISPATCHED;
 
397
 
 
398
        ReleaseMutex(rpc->VirtualConnection->DefaultInChannel->Mutex);
 
399
 
 
400
        /*
 
401
         * This protocol specifies that only RPC PDUs are subject to the flow control abstract
 
402
         * data model. RTS PDUs and the HTTP request and response headers are not subject to flow control.
 
403
         * Implementations of this protocol MUST NOT include them when computing any of the variables
 
404
         * specified by this abstract data model.
 
405
         */
 
406
 
 
407
        if (header->ptype == PTYPE_REQUEST)
 
408
        {
 
409
                rpc->VirtualConnection->DefaultInChannel->BytesSent += status;
 
410
                rpc->VirtualConnection->DefaultInChannel->SenderAvailableWindow -= status;
 
411
        }
 
412
 
 
413
        Stream_Free(pdu->s, TRUE);
 
414
        free(pdu);
 
415
 
 
416
        if (rpc->client->SynchronousSend)
 
417
                SetEvent(rpc->client->PduSentEvent);
 
418
 
 
419
        return status;
 
420
}
 
421
 
 
422
RPC_PDU* rpc_recv_dequeue_pdu(rdpRpc* rpc)
 
423
{
 
424
        RPC_PDU* pdu;
 
425
        DWORD dwMilliseconds;
 
426
 
 
427
        pdu = NULL;
 
428
        dwMilliseconds = rpc->client->SynchronousReceive ? INFINITE : 0;
 
429
 
 
430
        if (WaitForSingleObject(Queue_Event(rpc->client->ReceiveQueue), dwMilliseconds) == WAIT_OBJECT_0)
 
431
        {
 
432
                pdu = (RPC_PDU*) Queue_Dequeue(rpc->client->ReceiveQueue);
 
433
 
 
434
#ifdef WITH_DEBUG_TSG
 
435
                if (pdu)
 
436
                {
 
437
                        fprintf(stderr, "Receiving PDU (length: %d, CallId: %d)\n", pdu->s->length, pdu->CallId);
 
438
                        winpr_HexDump(Stream_Buffer(pdu->s), Stream_Length(pdu->s));
 
439
                        fprintf(stderr, "\n");
 
440
                }
 
441
#endif
 
442
 
 
443
                return pdu;
 
444
        }
 
445
 
 
446
        return pdu;
 
447
}
 
448
 
 
449
RPC_PDU* rpc_recv_peek_pdu(rdpRpc* rpc)
 
450
{
 
451
        RPC_PDU* pdu;
 
452
        DWORD dwMilliseconds;
 
453
 
 
454
        pdu = NULL;
 
455
        dwMilliseconds = rpc->client->SynchronousReceive ? INFINITE : 0;
 
456
 
 
457
        if (WaitForSingleObject(Queue_Event(rpc->client->ReceiveQueue), dwMilliseconds) == WAIT_OBJECT_0)
 
458
        {
 
459
                pdu = (RPC_PDU*) Queue_Peek(rpc->client->ReceiveQueue);
 
460
                return pdu;
 
461
        }
 
462
 
 
463
        return pdu;
 
464
}
 
465
 
 
466
static void* rpc_client_thread(void* arg)
 
467
{
 
468
        rdpRpc* rpc;
 
469
        DWORD status;
 
470
        DWORD nCount;
 
471
        HANDLE events[3];
 
472
        HANDLE ReadEvent;
 
473
 
 
474
        rpc = (rdpRpc*) arg;
 
475
 
 
476
        ReadEvent = CreateFileDescriptorEvent(NULL, TRUE, FALSE, rpc->TlsOut->sockfd);
 
477
 
 
478
        nCount = 0;
 
479
        events[nCount++] = rpc->client->StopEvent;
 
480
        events[nCount++] = Queue_Event(rpc->client->SendQueue);
 
481
        events[nCount++] = ReadEvent;
 
482
 
 
483
        while (1)
 
484
        {
 
485
                status = WaitForMultipleObjects(nCount, events, FALSE, INFINITE);
 
486
 
 
487
                if (WaitForSingleObject(rpc->client->StopEvent, 0) == WAIT_OBJECT_0)
 
488
                {
 
489
                        break;
 
490
                }
 
491
 
 
492
                if (WaitForSingleObject(ReadEvent, 0) == WAIT_OBJECT_0)
 
493
                {
 
494
                        if (rpc_client_on_read_event(rpc) < 0)
 
495
                                break;
 
496
                }
 
497
 
 
498
                if (WaitForSingleObject(Queue_Event(rpc->client->SendQueue), 0) == WAIT_OBJECT_0)
 
499
                {
 
500
                        rpc_send_dequeue_pdu(rpc);
 
501
                }
 
502
        }
 
503
 
 
504
        CloseHandle(ReadEvent);
 
505
 
 
506
        rpc_client_free(rpc);
 
507
 
 
508
        return NULL;
 
509
}
 
510
 
 
511
static void rpc_pdu_free(RPC_PDU* pdu)
 
512
{
 
513
        Stream_Free(pdu->s, TRUE);
 
514
        free(pdu);
 
515
}
 
516
 
 
517
static void rpc_fragment_free(wStream* fragment)
 
518
{
 
519
        Stream_Free(fragment, TRUE);
 
520
}
 
521
 
 
522
int rpc_client_new(rdpRpc* rpc)
 
523
{
 
524
        RpcClient* client = NULL;
 
525
 
 
526
        client = (RpcClient*) malloc(sizeof(RpcClient));
 
527
 
 
528
        if (client)
 
529
        {
 
530
                client->Thread = CreateThread(NULL, 0,
 
531
                                (LPTHREAD_START_ROUTINE) rpc_client_thread,
 
532
                                rpc, CREATE_SUSPENDED, NULL);
 
533
 
 
534
                client->StopEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
 
535
                client->PduSentEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
 
536
 
 
537
                client->SendQueue = Queue_New(TRUE, -1, -1);
 
538
                Queue_Object(client->SendQueue)->fnObjectFree = (OBJECT_FREE_FN) rpc_pdu_free;
 
539
 
 
540
                client->pdu = NULL;
 
541
                client->ReceivePool = Queue_New(TRUE, -1, -1);
 
542
                client->ReceiveQueue = Queue_New(TRUE, -1, -1);
 
543
                Queue_Object(client->ReceivePool)->fnObjectFree = (OBJECT_FREE_FN) rpc_pdu_free;
 
544
                Queue_Object(client->ReceiveQueue)->fnObjectFree = (OBJECT_FREE_FN) rpc_pdu_free;
 
545
 
 
546
                client->RecvFrag = NULL;
 
547
                client->FragmentPool = Queue_New(TRUE, -1, -1);
 
548
                client->FragmentQueue = Queue_New(TRUE, -1, -1);
 
549
 
 
550
                Queue_Object(client->FragmentPool)->fnObjectFree = (OBJECT_FREE_FN) rpc_fragment_free;
 
551
                Queue_Object(client->FragmentQueue)->fnObjectFree = (OBJECT_FREE_FN) rpc_fragment_free;
 
552
 
 
553
                client->ClientCallList = ArrayList_New(TRUE);
 
554
                ArrayList_Object(client->ClientCallList)->fnObjectFree = (OBJECT_FREE_FN) rpc_client_call_free;
 
555
        }
 
556
 
 
557
        rpc->client = client;
 
558
 
 
559
        return 0;
 
560
}
 
561
 
 
562
int rpc_client_start(rdpRpc* rpc)
 
563
{
 
564
        ResumeThread(rpc->client->Thread);
 
565
 
 
566
        return 0;
 
567
}
 
568
 
 
569
int rpc_client_stop(rdpRpc* rpc)
 
570
{
 
571
        SetEvent(rpc->client->StopEvent);
 
572
 
 
573
        WaitForSingleObject(rpc->client->Thread, INFINITE);
 
574
 
 
575
        return 0;
 
576
}
 
577
 
 
578
int rpc_client_free(rdpRpc* rpc)
 
579
{
 
580
        RpcClient* client;
 
581
 
 
582
        client = rpc->client;
 
583
 
 
584
        if (client)
 
585
        {
 
586
                Queue_Free(client->SendQueue);
 
587
 
 
588
                if (client->RecvFrag)
 
589
                        rpc_fragment_free(client->RecvFrag);
 
590
 
 
591
                Queue_Free(client->FragmentPool);
 
592
                Queue_Free(client->FragmentQueue);
 
593
 
 
594
                if (client->pdu)
 
595
                        rpc_pdu_free(client->pdu);
 
596
 
 
597
                Queue_Free(client->ReceivePool);
 
598
                Queue_Free(client->ReceiveQueue);
 
599
 
 
600
                ArrayList_Free(client->ClientCallList);
 
601
 
 
602
                CloseHandle(client->StopEvent);
 
603
                CloseHandle(client->PduSentEvent);
 
604
 
 
605
                CloseHandle(client->Thread);
 
606
 
 
607
                free(client);
 
608
        }
 
609
 
 
610
        return 0;
 
611
}