FreeRDP
Loading...
Searching...
No Matches
channel_pdu_tracker.c
1
20#include <freerdp/utils/channel_pdu_tracker.h>
21
22#include <winpr/wtsapi.h>
23
24#include <freerdp/log.h>
25#define TTAG FREERDP_TAG("utils.ChannelPduTracker")
26
27struct ChannelPduTracker
28{
29 HANDLE vc;
30 wStream* currentPacket;
31 char buffer[CHANNEL_PDU_LENGTH];
32 size_t offset;
33 wLog* log;
34};
35
36wStream* ChannelPduTracker_poll(ChannelPduTracker* tracker, BOOL* ok)
37{
38 WINPR_ASSERT(tracker);
39 WINPR_ASSERT(ok);
40
41 ULONG sz = 0;
42 *ok = FALSE;
43
44 WINPR_ASSERT(tracker->offset <= CHANNEL_PDU_LENGTH);
45 const ULONG readSz = WINPR_ASSERTING_INT_CAST(ULONG, CHANNEL_PDU_LENGTH - tracker->offset);
46 if (!WTSVirtualChannelRead(tracker->vc, INFINITE, &tracker->buffer[tracker->offset], readSz,
47 &sz))
48 return nullptr;
49
50 tracker->offset += sz;
51 WINPR_ASSERT(tracker->offset <= CHANNEL_PDU_LENGTH);
52
53 const size_t recvSz = tracker->offset;
54 if (recvSz < sizeof(CHANNEL_PDU_HEADER))
55 {
56 *ok = TRUE;
57 return nullptr;
58 }
59
60 const CHANNEL_PDU_HEADER* header = (const CHANNEL_PDU_HEADER*)tracker->buffer;
61 if (header->length > CHANNEL_CHUNK_LENGTH)
62 {
63 WLog_Print(tracker->log, WLOG_ERROR, "chunk size %" PRIu32 " is too big", header->length);
64 return nullptr;
65 }
66
67 const size_t actual = recvSz - sizeof(CHANNEL_PDU_HEADER);
68 if (actual != header->length)
69 {
70 WLog_Print(tracker->log, WLOG_ERROR,
71 "Expected chunk size %" PRIu32 " does not match received data size %" PRIuz,
72 header->length, actual);
73 return nullptr;
74 }
75
76 tracker->offset = 0;
77 if ((header->flags & CHANNEL_FLAG_FIRST) != 0)
78 Stream_ResetPosition(tracker->currentPacket);
79
80 if (!Stream_EnsureRemainingCapacity(tracker->currentPacket, header->length))
81 return nullptr;
82
83 Stream_Write(tracker->currentPacket, &tracker->buffer[sizeof(CHANNEL_PDU_HEADER)],
84 header->length);
85
86 if ((header->flags & CHANNEL_FLAG_LAST) == 0)
87 {
88 *ok = TRUE;
89 return nullptr;
90 }
91
92 Stream_SealLength(tracker->currentPacket);
93 Stream_ResetPosition(tracker->currentPacket);
94 wStream* ret = tracker->currentPacket;
95
96 tracker->currentPacket = Stream_New(nullptr, 4096);
97 if (!tracker->currentPacket)
98 {
99 Stream_Release(ret);
100 WLog_Print(tracker->log, WLOG_ERROR, "error allocating new currentPacket");
101 return nullptr;
102 }
103
104 *ok = TRUE;
105 return ret;
106}
107
108void ChannelPduTracker_free(ChannelPduTracker* tracker)
109{
110 if (!tracker)
111 return;
112
113 Stream_Release(tracker->currentPacket);
114 free(tracker);
115}
116
117ChannelPduTracker* ChannelPduTracker_new(HANDLE vc)
118{
119 ChannelPduTracker* ret = calloc(1, sizeof(*ret));
120 if (!ret)
121 return nullptr;
122
123 ret->currentPacket = Stream_New(nullptr, 4096);
124 if (!ret->currentPacket)
125 goto fail;
126
127 ret->vc = vc;
128 ret->log = WLog_Get(TTAG);
129 if (!ret->log)
130 goto fail;
131 return ret;
132fail:
133 ChannelPduTracker_free(ret);
134 return nullptr;
135}