FreeRDP
Loading...
Searching...
No Matches
rdpudp.c
1
18#include <freerdp/config.h>
19
20#include <string.h>
21
22#include <winpr/assert.h>
23#include <winpr/cast.h>
24#include <winpr/crt.h>
25#include <winpr/crypto.h>
26#include <winpr/sysinfo.h>
27#include <winpr/collections.h>
28#include <winpr/stream.h>
29#include <winpr/winsock.h>
30
31#if !defined(_WIN32)
32#include <sys/socket.h>
33#include <netinet/in.h>
34#endif
35
36#include "rdpudp.h"
37
38/* [MS-RDPEUDP] 2.2.2.1 RDPUDP_FEC_HEADER uFlags */
39typedef enum WINPR_C23_ENUM_TYPE(uint16_t)
40{
41 RDPUDP_FLAG_SYN = 0x0001,
42 RDPUDP_FLAG_ACK = 0x0004,
43 RDPUDP_FLAG_DATA = 0x0008,
44 RDPUDP_FLAG_FEC = 0x0010,
45 RDPUDP_FLAG_CN = 0x0020,
46 RDPUDP_FLAG_CWR = 0x0040,
47 RDPUDP_FLAG_ACK_OF_ACKS = 0x0100,
48 RDPUDP_FLAG_CORRELATION_ID = 0x0800,
49 RDPUDP_FLAG_SYNEX = 0x1000
50} RDPUDP_FLAGS;
51
52/* [MS-RDPEUDP] 2.2.2.9 RDPUDP_SYNDATAEX_PAYLOAD uSynExFlags */
53typedef enum WINPR_C23_ENUM_TYPE(uint16_t)
54{
55 RDPUDP_VERSION_INFO_VALID = 0x0001
56} RDPUDP_SYNEX_FLAGS;
57
58/* [MS-RDPEUDP] 2.2.1.1 VECTOR_ELEMENT_STATE */
59typedef enum WINPR_C23_ENUM_TYPE(uint8_t)
60{
61 DATAGRAM_RECEIVED = 0,
62 DATAGRAM_NOT_YET_RECEIVED = 3
63} RDPUDP_VECTOR_ELEMENT_STATE;
64
65/* [MS-RDPEUDP2] 2.2.1.1 RDPUDP2_PACKET_HEADER Flags */
66typedef enum WINPR_C23_ENUM_TYPE(uint16_t)
67{
68 RDPUDP2_ACK = 0x001,
69 RDPUDP2_DATA = 0x004,
70 RDPUDP2_ACKVEC = 0x008,
71 RDPUDP2_AOA = 0x010,
72 RDPUDP2_OVERHEADSIZE = 0x040,
73 RDPUDP2_DELAYACKINFO = 0x100,
74 RDPUDP2_NOACK = 0x200
75} RDPUDP2_FLAGS;
76
77/* [MS-RDPEUDP2] 2.2.1 packet type index of the prefix byte */
78typedef enum WINPR_C23_ENUM_TYPE(uint8_t)
79{
80 RDPUDP2_PACKET_STANDARD = 0,
81 RDPUDP2_PACKET_DUMMY = 8
82} RDPUDP2_PACKET_TYPE;
83
84/* [MS-RDPEUDP] 2.2.2.1: the ACK vector holds at most 2048 elements */
85#define RDPUDP_MAX_ACK_VECTOR 2048
86
87#define RDPUDP_MTU 1232
88#define RDPUDP_MIN_MTU 1132
89
90/* What this side advertises in uReceiveWindowSize (versions 1 and 2). */
91#define RDPUDP_RECEIVE_WINDOW 64
92
93/* Out of order data held while waiting for a gap to fill, a slot per sequence number. RDP-UDP2
94 * numbers are 16 bit, serial arithmetic tells at most 32767 ahead from behind, and the peer may
95 * get that far: Windows ignores the uReceiveWindowSize of versions 1 and 2 there, and had 5751
96 * chunks outstanding after a 2 second outage. */
97#define RDPUDP_RECEIVE_SLOTS 32768
98#define RDPUDP_RECEIVE_REACH 32767
99
100/* Datagrams of ours that may be unacknowledged at once. */
101#define RDPUDP_MAX_IN_FLIGHT 64
102
103/* [MS-RDPEUDP2] LogWindowSize. Windows always advertises the largest window (2^15 * MTU), a
104 * smaller value throttles the server's sender for no benefit. */
105#define RDPUDP2_LOG_WINDOW_SIZE 15
106
107/* Both Windows endpoints start the RDP-UDP2 data sequence space at 100. */
108#define RDPUDP2_INITIAL_SEQUENCE 100
109
110/* [MS-RDPEUDP2] 3.1.5.2: a receiver acknowledges at least every 8 data packets until the peer's
111 * DelayAckInfo says otherwise, which allows at most 15. */
112#define RDPUDP2_DEFAULT_DELAYED_ACKS 8
113#define RDPUDP2_MAX_DELAYED_ACKS 15
114
115/* What an RDP-UDP2 DATA datagram carries besides its payload: prefix, header, an ACK without
116 * delayed acknowledgements, DelayAckInfo, AckOfAcks, DataHeader and channel sequence number. */
117#define RDPUDP2_DATA_OVERHEAD 19
118
119/* Room kept in a full DATA datagram for the arrival gaps of the ACK it carries. */
120#define RDPUDP2_DATA_ACK_ROOM 5
121
122/* Asked for as the socket receive buffer. A redraw arrives as a burst of hundreds of datagrams,
123 * more than the default buffer holds, and a datagram that does not fit waits for a resend. */
124#define RDPUDP_RECEIVE_BUFFER (2 * 1024 * 1024)
125
126/* RDPUDP2 ACK vectors hold at most 127 state map bytes of 7 packets each. */
127#define RDPUDP2_MAX_ACKVEC 127
128
129/* Room left in every version 1/2 data datagram for the ACK vector and AckOfAcks. */
130#define RDPUDP_ACK_ROOM 64
131
132/* SYN and SYN+ACK are padded to the MTU ([MS-RDPEUDP] 3.1.5.1.1), so a line that drops large
133 * datagrams drops them first: with 4 attempts the tunnel was not set up on a line losing 43% of
134 * them. Ten, a second apart, stay well inside the setup time of the tunnel
135 * (RDPEMT_SETUP_TIMEOUT_MS). */
136#define RDPUDP_SYN_TIMEOUT_MS 1000
137#define RDPUDP_SYN_ATTEMPTS 10
138
139/* [MS-RDPEUDP] 3.1.6.1: the retransmit timeout is twice the round trip, at least the version's
140 * minimum, and doubles with every resend of the same datagram. Windows lets it grow to 120
141 * seconds (note <8>). Below the round trip, every datagram is resent before its acknowledgement
142 * can arrive. */
143#define RDPUDP_MAX_RTO_MS 120000
144
145/* [MS-RDPEUDP] 3.1.5.4: a datagram retransmitted three to five times without a response ends
146 * the connection, and so does 65 seconds without any datagram from the peer (3.1.1.9). */
147#define RDPUDP_MAX_RETRANSMITS 5
148#define RDPUDP_KEEPALIVE_MS 5000
149#define RDPUDP_PEER_TIMEOUT_MS 65000
150
151/* [MS-RDPEUDP2] 3.1.1.3: both ends send at least every 16 seconds, Windows every 4, and 16
152 * seconds without a datagram mean the peer is gone. The retransmit limit is left to the sender,
153 * the peer timeout already bounds how long a dead connection goes unnoticed. */
154#define RDPUDP2_MAX_RETRANSMITS 10
155#define RDPUDP2_KEEPALIVE_MS 4000
156#define RDPUDP2_PEER_TIMEOUT_MS 16000
157
158/* Silence after which the peer may have moved more than half the sequence space on, see
159 * v3_resync_base. Two keepalive intervals, an idle tunnel never gets there. */
160#define RDPUDP2_RESYNC_MS (2ull * RDPUDP2_KEEPALIVE_MS)
161
162/* [MS-RDPEUDP2] 3.1.5.1.3: the peer resends a lost chunk under a new data sequence number, and
163 * the receiver has no way to ask for it. A stream stuck behind a missing chunk for as long as the
164 * peer timeout is no better than a peer that is gone: the tunnel fails, ending the connection like
165 * a broken transport, instead of leaving the session frozen while the peer's keepalives keep it
166 * alive. */
167#define RDPUDP_STALL_TIMEOUT_MS RDPUDP2_PEER_TIMEOUT_MS
168
169typedef struct
170{
171 BOOL used;
172 UINT32 seq; /* source sequence (v1/v2) or data sequence (v3) */
173 UINT16 channelSeq;
174 BYTE* payload;
175 size_t length;
176 UINT64 sent;
177 UINT64 due;
178 UINT32 rto;
179 UINT32 retransmits;
180} rdpudp_pending;
181
182typedef struct
183{
184 BOOL present;
185 UINT32 seq;
186 BYTE* data;
187 size_t length;
188} rdpudp_slot;
189
190typedef struct
191{
192 BYTE* data;
193 size_t length;
194} rdpudp_chunk;
195
196struct rdp_udp
197{
198 wLog* log;
199 SOCKET sockfd;
200 RDPUDP_STATE state;
201 UINT16 version;
202 BOOL offerV3;
203 BYTE cookieHash[32];
204
205 rdpUdpReceiveFn receive;
206 void* custom;
207
208 UINT16 mtu;
209 UINT32 synAttempts;
210 UINT64 synSent;
211 UINT64 lastSent;
212 UINT64 lastReceived;
213 UINT32 srtt;
214
215 /* sending side */
216 rdpudp_pending pending[RDPUDP_MAX_IN_FLIGHT];
217 size_t inFlight;
218 UINT32 peerWindow;
219 wQueue* sendQueue;
220 UINT32 initialSequence;
221 UINT32 nextSource;
222 UINT32 nextCoded;
223 BOOL cwrPending;
224 UINT32 announcedAoA;
225 BOOL aoaAnnounced;
226 UINT16 nextChannelSeq;
227
228 /* receiving side */
229 BOOL ackPending;
230 BOOL receivedData;
231 rdpudp_slot slots[RDPUDP_RECEIVE_SLOTS];
232 size_t buffered;
233 UINT64 lastDelivery;
234 UINT64 bufferingSince;
235
236 /* receiving, versions 1 and 2 */
237 UINT32 peerInitialSequence;
238 UINT32 recvNext;
239 UINT32 recvHighest;
240 UINT32 ackVectorStart;
241
242 /* receiving, version 3 */
243 BOOL v3BaseKnown;
244 BOOL v3Resync; /* silent for RDPUDP2_RESYNC_MS: no ACK until an AckOfAcks sets the base */
245 UINT16 v3Expected;
246 UINT16 v3Highest;
247 BOOL v3Received[RDPUDP_RECEIVE_SLOTS];
248 UINT64 v3Arrival[RDPUDP_RECEIVE_SLOTS]; /* when each data sequence arrived, in ns */
249 UINT64 v3InOrderArrival; /* when data sequence v3Expected - 1 arrived */
250 BOOL v3InOrderReceived; /* FALSE while v3Expected - 1 is one AckOfAcks gave up on */
251 UINT64 v3LatestArrival; /* when the latest data packet arrived */
252 size_t v3MaxDelayedAcks;
253 UINT32 v3DelayedAckTimeout; /* in ms, UINT32_MAX until the peer's DelayAckInfo sets it */
254 UINT64 v3AckDue; /* in ms, when what waits for our acknowledgement must get it; 0: nothing */
255 size_t v3UnackedPackets; /* data packets received since our last acknowledgement */
256 UINT16 v3AckedSeq; /* the SeqNum of our last ACK payload */
257 BOOL v3AckedGap; /* whether our last acknowledgement reported a missing packet */
258 BOOL v3WindowPending; /* the window has news for an acknowledgement */
259 /* data packets behind the window, acknowledged on their own, see v3_send_ack: a run of
260 * consecutive sequence numbers from v3BehindBase, and when the newest of them arrived */
261 UINT16 v3BehindBase;
262 size_t v3BehindCount;
263 UINT64 v3BehindArrival;
264 UINT16 v3NextChannel;
265
266 /* One received datagram. Kept here rather than on the stack, rdpudp_check is not reentrant. */
267 BYTE recvBuffer[0x10000];
268};
269
270/* RDP-UDP sequence numbers are 16 (RDPUDP2) or 32 (RDPUDP) bit counters that wrap around, they
271 * are compared and advanced with RFC 1982 serial number arithmetic. The wrap in the helpers
272 * below is intentional, they mask to the counter width before the checked conversion. */
273WINPR_ATTR_NODISCARD
274static inline UINT16 seq16_add(UINT16 a, size_t n)
275{
276 return WINPR_ASSERTING_INT_CAST(UINT16, (a + n) & 0xFFFFu);
277}
278
279/* a - b modulo 2^16 */
280WINPR_ATTR_NODISCARD
281static inline UINT16 seq16_diff(UINT16 a, UINT16 b)
282{
283 return WINPR_ASSERTING_INT_CAST(UINT16, ((UINT32)a - (UINT32)b) & 0xFFFFu);
284}
285
286WINPR_ATTR_NODISCARD
287static inline UINT32 seq32_add(UINT32 a, UINT32 n)
288{
289 return WINPR_ASSERTING_INT_CAST(UINT32, ((UINT64)a + n) & 0xFFFFFFFFull);
290}
291
292/* a - b modulo 2^32 */
293WINPR_ATTR_NODISCARD
294static inline UINT32 seq32_diff(UINT32 a, UINT32 b)
295{
296 return WINPR_ASSERTING_INT_CAST(UINT32, ((UINT64)a - (UINT64)b) & 0xFFFFFFFFull);
297}
298
299WINPR_ATTR_NODISCARD
300static BOOL seq16_after(UINT16 a, UINT16 b)
301{
302 return (a != b) && (seq16_diff(a, b) < 0x8000);
303}
304
305WINPR_ATTR_NODISCARD
306static BOOL seq32_after(UINT32 a, UINT32 b)
307{
308 return (a != b) && (seq32_diff(a, b) < 0x80000000u);
309}
310
311/* Channel sequence numbers start at 1 and Windows wraps 65535 to 1, never using 0. Ours do the
312 * same, both sending and receiving. */
313WINPR_ATTR_NODISCARD
314static UINT16 channel_seq_next(UINT16 seq)
315{
316 return (seq == UINT16_MAX) ? 1 : seq16_add(seq, 1);
317}
318
319/* [MS-RDPEUDP2] has 24 bit little endian fields, wStream has no helper for those */
320static void stream_write_uint24(wStream* s, UINT32 value)
321{
322 WINPR_ASSERT(s);
323 const UINT16 low = WINPR_ASSERTING_INT_CAST(UINT16, value & 0xFFFF);
324 const BYTE high = WINPR_ASSERTING_INT_CAST(BYTE, (value >> 16) & 0xFF);
325 Stream_Write_UINT16(s, low);
326 Stream_Write_UINT8(s, high);
327}
328
329WINPR_ATTR_NODISCARD
330static UINT64 now_ms(void)
331{
332 return GetTickCount64();
333}
334
335WINPR_ATTR_NODISCARD
336static UINT32 rto_floor(const rdpUdp* udp)
337{
338 WINPR_ASSERT(udp);
339 return (udp->version == RDPUDP_PROTOCOL_VERSION_1) ? 500 : 300;
340}
341
342WINPR_ATTR_NODISCARD
343static UINT32 rto_initial(const rdpUdp* udp)
344{
345 WINPR_ASSERT(udp);
346 const UINT32 floor = rto_floor(udp);
347 const UINT64 rtt2 = (UINT64)udp->srtt * 2ull;
348 const UINT64 rto = (rtt2 > floor) ? rtt2 : floor;
349 return (rto > RDPUDP_MAX_RTO_MS) ? RDPUDP_MAX_RTO_MS : WINPR_ASSERTING_INT_CAST(UINT32, rto);
350}
351
352static void chunk_free(void* obj)
353{
354 rdpudp_chunk* chunk = obj;
355 if (!chunk)
356 return;
357 free(chunk->data);
358 free(chunk);
359}
360
361static void slot_clear(rdpudp_slot* slot)
362{
363 WINPR_ASSERT(slot);
364 free(slot->data);
365 slot->data = nullptr;
366 slot->length = 0;
367 slot->present = FALSE;
368}
369
370static void pending_clear(rdpudp_pending* p)
371{
372 WINPR_ASSERT(p);
373 free(p->payload);
374 memset(p, 0, sizeof(*p));
375}
376
377static void rdpudp_fail(rdpUdp* udp, const char* why)
378{
379 WINPR_ASSERT(udp);
380 WINPR_ASSERT(why);
381 if (udp->state != RDPUDP_STATE_FAILED)
382 WLog_Print(udp->log, WLOG_WARN, "RDP-UDP connection failed: %s", why);
383 udp->state = RDPUDP_STATE_FAILED;
384}
385
386/* Socket errors are handled as on the TCP transport (transport_bio_simple_read and
387 * transport_bio_simple_write): a wait condition is retried and anything else fails. A datagram
388 * socket adds the conditions of the path, an ICMP error for an earlier datagram, a full buffer,
389 * a network that is down or unreachable for a moment: they cost the one datagram, which the
390 * retransmit timer recovers, and the peer timeout ends a path that stays broken. A firewall rule
391 * that drops the datagram is one of them, send() fails with EPERM then, which WinPR does not map
392 * and reports as 0; TCP never sees an error for that, it retransmits. */
393WINPR_ATTR_NODISCARD
394static BOOL rdpudp_socket_error_is_transient(int error)
395{
396 switch (error)
397 {
398 case 0:
399 case WSAEWOULDBLOCK:
400 case WSAEINTR:
401 case WSAEINPROGRESS:
402 case WSAEALREADY:
403 case WSAENOBUFS:
404 case WSAECONNRESET:
405 case WSAECONNREFUSED:
406 case WSAENETRESET:
407 case WSAENETDOWN:
408 case WSAENETUNREACH:
409 case WSAEHOSTDOWN:
410 case WSAEHOSTUNREACH:
411 return TRUE;
412 default:
413 return FALSE;
414 }
415}
416
417WINPR_ATTR_NODISCARD
418static BOOL rdpudp_send_raw(rdpUdp* udp, const BYTE* data, size_t length)
419{
420 WINPR_ASSERT(udp);
421 WINPR_ASSERT(data);
422 const int rc = _send(udp->sockfd, (const char*)data, WINPR_ASSERTING_INT_CAST(int, length), 0);
423 if (rc < 0)
424 {
425 const int error = WSAGetLastError();
426 if (!rdpudp_socket_error_is_transient(error))
427 {
428 WLog_Print(udp->log, WLOG_ERROR, "send failed with %d", error);
429 rdpudp_fail(udp, "sending on the socket failed");
430 return FALSE;
431 }
432 WLog_Print(udp->log, WLOG_DEBUG, "send failed with %d, the datagram counts as lost", error);
433 return TRUE;
434 }
435 udp->lastSent = now_ms();
436 return TRUE;
437}
438
439/* ------------------------------------------------------------------------------------------ */
440/* [MS-RDPEUDP2] encoding */
441/* ------------------------------------------------------------------------------------------ */
442
443WINPR_ATTR_NODISCARD
444static UINT32 v3_timestamp(UINT64 ns)
445{
446 /* [MS-RDPEUDP2] 3.1.1.1.4: 24 bits in units of 4 microseconds */
447 return WINPR_ASSERTING_INT_CAST(UINT32, (ns / 4000ULL) & 0x00FFFFFFULL);
448}
449
450/* Milliseconds an acknowledgement waited after the packet it reports arrived. */
451WINPR_ATTR_NODISCARD
452static BYTE v3_ack_gap(UINT64 arrival, UINT64 now)
453{
454 if ((arrival == 0) || (now < arrival))
455 return 0;
456 const UINT64 gap = (now - arrival) / 1000000ULL;
457 return (gap > 254) ? 254 : WINPR_ASSERTING_INT_CAST(BYTE, gap); /* 255 means invalid */
458}
459
460WINPR_ATTR_NODISCARD
461static BOOL v3_has_gap(const rdpUdp* udp)
462{
463 WINPR_ASSERT(udp);
464 return udp->v3BaseKnown && seq16_after(udp->v3Highest, seq16_diff(udp->v3Expected, 1));
465}
466
467/* [MS-RDPEUDP2] 2.2.1.2.1 ACK payload. receivedTS is when the acknowledged packet arrived and
468 * sendAckTimeGap how long the acknowledgement waited after that. The peer measures the path from
469 * both, a send time in receivedTS would make the time spent here look like network delay.
470 *
471 * The packets acknowledged along with SeqNum since our previous ACK follow as delayed
472 * acknowledgements, at most room of them (3.1.5.6): the gaps between their arrivals, newest
473 * first. The peer estimates the bandwidth of the path from these, mstsc sends them. */
474static void v3_write_ack(rdpUdp* udp, wStream* s, size_t room)
475{
476 WINPR_ASSERT(udp);
477 WINPR_ASSERT(s);
478 const UINT64 now = winpr_GetTickCount64NS();
479 /* A sequence number the peer gave up on never arrived. An older packet's arrival time would
480 * place its receipt before it was sent, so it is reported as received now. */
481 const UINT64 arrival = udp->v3InOrderReceived ? udp->v3InOrderArrival : now;
482 const UINT16 seq = seq16_diff(udp->v3Expected, 1);
483
484 UINT64 gaps[RDPUDP2_MAX_DELAYED_ACKS] = WINPR_C_ARRAY_INIT; /* microseconds, newest first */
485 size_t count = 0;
486 if (udp->v3InOrderReceived)
487 {
488 size_t limit = seq16_diff(seq, udp->v3AckedSeq); /* packets acknowledged, SeqNum included */
489 limit = (limit > 0) ? limit - 1 : 0;
490 if (limit > udp->v3MaxDelayedAcks)
491 limit = udp->v3MaxDelayedAcks;
492 if (limit > room)
493 limit = room;
494 if (limit > RDPUDP2_MAX_DELAYED_ACKS)
495 limit = RDPUDP2_MAX_DELAYED_ACKS;
496
497 UINT16 current = seq;
498 UINT64 currentArrival = arrival;
499 while (count < limit)
500 {
501 const UINT16 previous = seq16_diff(current, 1);
502 const UINT64 previousArrival = udp->v3Arrival[previous % RDPUDP_RECEIVE_SLOTS];
503 if (previousArrival == 0)
504 break; /* given up on by AckOfAcks, it never arrived */
505 /* packets that overtook each other count as arriving together */
506 gaps[count++] = (currentArrival > previousArrival)
507 ? (currentArrival - previousArrival) / 1000ULL
508 : 0;
509 current = previous;
510 currentArrival = previousArrival;
511 }
512 }
513
514 /* each gap has to fit a byte in units of (1 << scale) microseconds */
515 BYTE scale = 0;
516 for (size_t x = 0; x < count; x++)
517 {
518 while ((scale < 15) && ((gaps[x] >> scale) > 255))
519 scale++;
520 }
521
522 Stream_Write_UINT16(s, seq); /* SeqNum */
523 stream_write_uint24(s, v3_timestamp(arrival)); /* receivedTS */
524 /* the Stream_Write macros evaluate their value more than once */
525 const BYTE gap = v3_ack_gap(arrival, now);
526 Stream_Write_UINT8(s, gap); /* sendAckTimeGapInMs */
527 const BYTE delayed = WINPR_ASSERTING_INT_CAST(BYTE, count | ((size_t)scale << 4));
528 Stream_Write_UINT8(s, delayed); /* numDelayedAcks, delayAckTimeScale */
529 for (size_t x = 0; x < count; x++)
530 {
531 const UINT64 scaled = gaps[x] >> scale;
532 const BYTE addition = (scaled > 255) ? 255 : WINPR_ASSERTING_INT_CAST(BYTE, scaled);
533 Stream_Write_UINT8(s, addition); /* delayAckTimeAdditions */
534 }
535 udp->v3AckedSeq = seq;
536}
537
538/* Starts a packet: one byte is left free for the prefix, then the header. */
539WINPR_ATTR_NODISCARD
540static wStream* v3_packet_init(wStream* buffer, BYTE* data, size_t size, UINT16 flags)
541{
542 WINPR_ASSERT(buffer);
543 WINPR_ASSERT(data);
544 wStream* s = Stream_StaticInit(buffer, data, size);
545 if (!s)
546 return nullptr;
547 Stream_Seek(s, 1);
548 const UINT16 header = WINPR_ASSERTING_INT_CAST(UINT16, flags | (RDPUDP2_LOG_WINDOW_SIZE << 12));
549 Stream_Write_UINT16(s, header);
550 return s;
551}
552
553/* Finishes a packet into its on-wire form and sends it ([MS-RDPEUDP2] 2.2.1): the prefix byte
554 * goes in front, a short packet is padded, and the first and eighth byte trade places. */
555WINPR_ATTR_NODISCARD
556static BOOL v3_send_packet(rdpUdp* udp, wStream* s, BYTE packetType)
557{
558 WINPR_ASSERT(udp);
559 WINPR_ASSERT(s);
560 if (Stream_GetPosition(s) < 1)
561 return FALSE;
562 const size_t layout = Stream_GetPosition(s) - 1;
563 BYTE shortLength = 7;
564 if (layout < 7)
565 {
566 shortLength = WINPR_ASSERTING_INT_CAST(BYTE, layout);
567 Stream_Zero(s, 7 - layout);
568 }
569 const size_t length = Stream_GetPosition(s);
570
571 if (!Stream_SetPosition(s, 0))
572 return FALSE;
573 const BYTE prefix =
574 WINPR_ASSERTING_INT_CAST(BYTE, (shortLength << 5) | ((packetType & 0x0F) << 1));
575 Stream_Write_UINT8(s, prefix);
576
577 /* the swap scrambles the finished datagram, it is not a field of it */
578 BYTE* wire = Stream_Buffer(s);
579 const BYTE eighth = wire[7];
580 wire[7] = wire[0];
581 wire[0] = eighth;
582 return rdpudp_send_raw(udp, wire, length);
583}
584
585/* [MS-RDPEUDP2] 2.2.1.2.6 ACK vector payload. TimeStamp is when the newest packet it reports
586 * arrived, SendAckTimeGapInMs the time since the latest data packet arrived. */
587WINPR_ATTR_NODISCARD
588static BOOL v3_send_ack_vector(rdpUdp* udp, UINT16 base, const BYTE* vec, size_t count,
589 UINT64 arrival)
590{
591 BYTE buffer[64 + RDPUDP2_MAX_ACKVEC] = WINPR_C_ARRAY_INIT;
592 wStream sbuffer = WINPR_C_ARRAY_INIT;
593
594 WINPR_ASSERT(udp);
595 WINPR_ASSERT(vec);
596 WINPR_ASSERT((count > 0) && (count <= RDPUDP2_MAX_ACKVEC));
597 wStream* s =
598 v3_packet_init(&sbuffer, buffer, sizeof(buffer), RDPUDP2_OVERHEADSIZE | RDPUDP2_ACKVEC);
599 if (!s)
600 return FALSE;
601 const UINT64 now = winpr_GetTickCount64NS();
602 const BYTE control = WINPR_ASSERTING_INT_CAST(BYTE, 0x80 | count);
603 /* the Stream_Write macros evaluate their value more than once */
604 const BYTE ackGap = v3_ack_gap(udp->v3LatestArrival, now);
605 const UINT32 timestamp = v3_timestamp((arrival != 0) ? arrival : now);
606 Stream_Write_UINT8(s, 10); /* OverheadSize */
607 Stream_Write_UINT16(s, base); /* BaseSeqNum */
608 Stream_Write_UINT8(s, control); /* TimeStampPresent, codedAckVecSize */
609 stream_write_uint24(s, timestamp); /* TimeStamp */
610 Stream_Write_UINT8(s, ackGap); /* SendAckTimeGapInMs */
611 Stream_Write(s, vec, count); /* codedAckVector */
612 return v3_send_packet(udp, s, RDPUDP2_PACKET_STANDARD);
613}
614
615WINPR_ATTR_NODISCARD
616static BOOL v3_send_ack(rdpUdp* udp)
617{
618 BYTE buffer[64] = WINPR_C_ARRAY_INIT;
619 wStream sbuffer = WINPR_C_ARRAY_INIT;
620
621 WINPR_ASSERT(udp);
622 if (!udp->v3BaseKnown)
623 return TRUE;
624
625 /* Data packets behind our window, see v3_process_datagram, go in an ACK vector of their own:
626 * received, as runs of up to 63. A cumulative ACK would name our own position, which after a
627 * short outage at a high rate can lie ahead of what the peer has sent, and Windows ends the
628 * connection for that. It would also mark everything below it received ([MS-RDPEUDP2] 4.1.3).
629 * The vector reports what arrived and nothing more (4.2.2). */
630 if (udp->v3BehindCount > 0)
631 {
632 BYTE vec[RDPUDP2_MAX_ACKVEC] = WINPR_C_ARRAY_INIT;
633 size_t count = 0;
634 for (size_t left = udp->v3BehindCount; left > 0;)
635 {
636 const size_t run = (left > 63) ? 63 : left;
637 vec[count++] = WINPR_ASSERTING_INT_CAST(BYTE, 0x80 | 0x40 | run);
638 left -= run;
639 }
640 udp->v3BehindCount = 0;
641 if (!v3_send_ack_vector(udp, udp->v3BehindBase, vec, count, udp->v3BehindArrival))
642 return FALSE;
643 if (!udp->v3WindowPending)
644 {
645 udp->ackPending = FALSE;
646 udp->v3UnackedPackets = 0;
647 udp->v3AckDue = 0;
648 return TRUE;
649 }
650 }
651
652 /* After a silence our position may be ahead of the peer's numbers (v3_resync_base): no ACK
653 * until its next AckOfAcks. Nothing stays due meanwhile, or the tunnel thread would spin. */
654 if (udp->v3Resync)
655 {
656 udp->ackPending = FALSE;
657 udp->v3UnackedPackets = 0;
658 udp->v3AckDue = 0;
659 return TRUE;
660 }
661
662 udp->ackPending = FALSE;
663 udp->v3WindowPending = FALSE;
664 udp->v3UnackedPackets = 0;
665 udp->v3AckDue = 0;
666
667 /* A cumulative ACK cannot describe a hole, the ACK vector reports the exact window so only
668 * what is missing gets resent. ACK and ACKVEC are mutually exclusive. */
669 const BOOL gap = v3_has_gap(udp);
670 udp->v3AckedGap = gap;
671 if (!gap)
672 {
673 wStream* s =
674 v3_packet_init(&sbuffer, buffer, sizeof(buffer), RDPUDP2_OVERHEADSIZE | RDPUDP2_ACK);
675 if (!s)
676 return FALSE;
677 v3_write_ack(udp, s, RDPUDP2_MAX_DELAYED_ACKS);
678 Stream_Write_UINT8(s, 10); /* OverheadSize */
679 return v3_send_packet(udp, s, RDPUDP2_PACKET_STANDARD);
680 }
681
682 const UINT16 base = udp->v3Expected;
683 size_t span = (size_t)seq16_diff(udp->v3Highest, base) + 1;
684 if (span > RDPUDP_RECEIVE_REACH)
685 span = RDPUDP_RECEIVE_REACH;
686
687 /* [MS-RDPEUDP2] 2.2.1.2.6 ACK vector payload. Runs of seven or more packets in the same
688 * state go in run-length mode (up to 63 per byte), the rest in 7 bit state maps: with state
689 * maps only, 127 bytes cover 889 packets, ~70 ms behind a hole at 130 Mbit/s, and everything
690 * past that would stay unacknowledged until the hole is filled. */
691 BYTE vec[RDPUDP2_MAX_ACKVEC] = WINPR_C_ARRAY_INIT;
692 size_t count = 0;
693 size_t pos = 0;
694 while ((pos < span) && (count < RDPUDP2_MAX_ACKVEC))
695 {
696 const BOOL state = udp->v3Received[seq16_add(base, pos) % RDPUDP_RECEIVE_SLOTS];
697 size_t run = 1;
698 while ((pos + run < span) && (run < 63) &&
699 (udp->v3Received[seq16_add(base, pos + run) % RDPUDP_RECEIVE_SLOTS] == state))
700 run++;
701 if (run >= 7)
702 {
703 vec[count++] = WINPR_ASSERTING_INT_CAST(BYTE, 0x80 | (state ? 0x40 : 0x00) | run);
704 pos += run;
705 continue;
706 }
707 BYTE bits = 0;
708 for (size_t bit = 0; (bit < 7) && (pos + bit < span); bit++)
709 {
710 if (udp->v3Received[seq16_add(base, pos + bit) % RDPUDP_RECEIVE_SLOTS])
711 bits |= WINPR_ASSERTING_INT_CAST(BYTE, 1 << bit);
712 }
713 vec[count++] = bits; /* state map, bit 0 first */
714 pos += 7;
715 }
716
717 /* when the highest sequence number received arrived */
718 const UINT64 highest = udp->v3Arrival[udp->v3Highest % RDPUDP_RECEIVE_SLOTS];
719 return v3_send_ack_vector(udp, base, vec, count, highest);
720}
721
722/* The lowest data sequence number of ours still awaiting acknowledgement, which is what
723 * AckOfAcks tells the peer ([MS-RDPEUDP2] 2.2.1.2.4). */
724WINPR_ATTR_NODISCARD
725static UINT32 sender_base(const rdpUdp* udp)
726{
727 WINPR_ASSERT(udp);
728 UINT32 base = (udp->version == RDPUDP_PROTOCOL_VERSION_3) ? udp->nextCoded : udp->nextSource;
729 BOOL found = FALSE;
730 for (size_t x = 0; x < RDPUDP_MAX_IN_FLIGHT; x++)
731 {
732 const rdpudp_pending* p = &udp->pending[x];
733 if (!p->used)
734 continue;
735 if (udp->version == RDPUDP_PROTOCOL_VERSION_3)
736 {
737 if (!found || seq16_after(WINPR_ASSERTING_INT_CAST(UINT16, base),
738 WINPR_ASSERTING_INT_CAST(UINT16, p->seq)))
739 base = p->seq;
740 }
741 else if (!found || seq32_after(base, p->seq))
742 {
743 base = p->seq;
744 }
745 found = TRUE;
746 }
747 return base;
748}
749
750WINPR_ATTR_NODISCARD
751static BOOL v3_send_data(rdpUdp* udp, const rdpudp_pending* p)
752{
753 BYTE buffer[RDPUDP_MTU + 32] = WINPR_C_ARRAY_INIT;
754 wStream sbuffer = WINPR_C_ARRAY_INIT;
755
756 WINPR_ASSERT(udp);
757 WINPR_ASSERT(p);
758
759 /* Not while packets behind the window wait for their ACK vector: the ACK here would clear
760 * ackPending, and nothing would send the vector until the next standalone ACK. Not after a
761 * silence either, our position may lie ahead of the peer's numbers then (v3_resync_base). */
762 const BOOL withAck = udp->ackPending && udp->v3BaseKnown && !v3_has_gap(udp) &&
763 (udp->v3BehindCount == 0) && !udp->v3Resync;
764 const UINT16 base = WINPR_ASSERTING_INT_CAST(UINT16, sender_base(udp));
765 /* repeated on a resend, the first announcement may have been lost with it */
766 const BOOL withAoA = !udp->aoaAnnounced || (udp->announcedAoA != base) || (p->retransmits > 0);
767
768 /* Windows sets NOACK on every DATA packet without an ACK */
769 UINT16 flags = RDPUDP2_DATA | RDPUDP2_DELAYACKINFO;
770 flags |= withAck ? RDPUDP2_ACK : RDPUDP2_NOACK;
771 if (withAoA)
772 flags |= RDPUDP2_AOA;
773
774 wStream* s = v3_packet_init(&sbuffer, buffer, sizeof(buffer), flags);
775 if (!s)
776 return FALSE;
777 if (withAck)
778 {
779 /* arrival gaps only where the payload leaves room in the datagram */
780 const size_t used = RDPUDP2_DATA_OVERHEAD + p->length;
781 v3_write_ack(udp, s, (udp->mtu > used) ? udp->mtu - used : 0);
782 /* left pending, a later ACK would repeat this position, which after a jump of the
783 * peer's numbers names a packet it did not send */
784 udp->ackPending = FALSE;
785 udp->v3WindowPending = FALSE;
786 udp->v3UnackedPackets = 0;
787 udp->v3AckDue = 0;
788 udp->v3AckedGap = FALSE;
789 }
790
791 Stream_Write_UINT8(s, 1); /* MaxDelayedAcks */
792 Stream_Write_UINT16(s, 20); /* DelayedAckTimeoutInMs */
793
794 if (withAoA)
795 {
796 /* AckOfAcks: the lowest sequence number still awaiting acknowledgement */
797 Stream_Write_UINT16(s, base);
798 udp->announcedAoA = base;
799 udp->aoaAnnounced = TRUE;
800 }
801
802 const UINT16 dataSeq = WINPR_ASSERTING_INT_CAST(UINT16, p->seq);
803 Stream_Write_UINT16(s, dataSeq); /* DataSeqNum */
804 Stream_Write_UINT16(s, p->channelSeq); /* ChannelSeqNum */
805 if (!Stream_CheckAndLogRequiredCapacityWLog(udp->log, s, p->length))
806 return FALSE;
807 Stream_Write(s, p->payload, p->length);
808
809 return v3_send_packet(udp, s, RDPUDP2_PACKET_STANDARD);
810}
811
812/* ------------------------------------------------------------------------------------------ */
813/* [MS-RDPEUDP] version 1 and 2 encoding */
814/* ------------------------------------------------------------------------------------------ */
815
816/* Writes an RDPUDP_ACK_VECTOR_HEADER covering the peer's packets up to the highest one seen,
817 * using at most room bytes. Windows encodes a run of n datagrams as n - 1 in an element, so a run
818 * holds 1 to 64 datagrams; before the peer's first data packet the vector is empty. */
819static void v1_write_ack_vector(const rdpUdp* udp, wStream* s, size_t room)
820{
821 WINPR_ASSERT(udp);
822 WINPR_ASSERT(s);
823 if (!udp->receivedData)
824 {
825 Stream_Write_UINT16_BE(s, 0); /* uAckVectorSize */
826 Stream_Zero(s, 2); /* pad to a DWORD boundary */
827 return;
828 }
829
830 const UINT32 highest = udp->recvHighest;
831 UINT32 low = udp->ackVectorStart;
832 if (seq32_after(low, highest))
833 low = highest;
834 if (seq32_diff(highest, low) >= RDPUDP_RECEIVE_REACH)
835 low = seq32_diff(highest, RDPUDP_RECEIVE_REACH - 1);
836
837 BYTE elements[RDPUDP_MAX_ACK_VECTOR] = WINPR_C_ARRAY_INIT;
838 size_t count = 0;
839 BYTE state = 0xFF;
840 BYTE run = 0;
841
842 UINT32 seq = low;
843 while (TRUE)
844 {
845 BYTE current = DATAGRAM_RECEIVED;
846 if (!seq32_after(udp->recvNext, seq))
847 {
848 const rdpudp_slot* slot = &udp->slots[seq % RDPUDP_RECEIVE_SLOTS];
849 if (!slot->present || (slot->seq != seq))
850 current = DATAGRAM_NOT_YET_RECEIVED;
851 }
852
853 if ((current != state) || (run == 0x40))
854 {
855 if (run > 0)
856 {
857 if (count >= ARRAYSIZE(elements))
858 break;
859 elements[count++] = WINPR_ASSERTING_INT_CAST(BYTE, (state << 6) | (run - 1));
860 }
861 state = current;
862 run = 0;
863 }
864 run++;
865
866 if (seq == highest)
867 break;
868 seq++;
869 }
870 if ((run > 0) && (count < ARRAYSIZE(elements)))
871 elements[count++] = WINPR_ASSERTING_INT_CAST(BYTE, (state << 6) | (run - 1));
872
873 /* Too long to fit: keep the newest part, the older part has been reported before. */
874 size_t skip = 0;
875 while ((2 + (count - skip) + 3) > room && (skip < count))
876 skip++;
877 count -= skip;
878
879 const UINT16 vectorSize = WINPR_ASSERTING_INT_CAST(UINT16, count);
880 Stream_Write_UINT16_BE(s, vectorSize); /* uAckVectorSize */
881 Stream_Write(s, &elements[skip], count); /* AckVector */
882 Stream_Zero(s, (4 - ((2 + count) % 4)) % 4); /* pad to a DWORD boundary */
883}
884
885WINPR_ATTR_NODISCARD
886static UINT32 v1_cumulative_ack(const rdpUdp* udp)
887{
888 WINPR_ASSERT(udp);
889 return seq32_diff(sender_base(udp), 1);
890}
891
892WINPR_ATTR_NODISCARD
893static BOOL v1_send_packet(rdpUdp* udp, const rdpudp_pending* p)
894{
895 BYTE buffer[RDPUDP_MTU + 2048] = WINPR_C_ARRAY_INIT;
896 wStream sbuffer = WINPR_C_ARRAY_INIT;
897
898 WINPR_ASSERT(udp);
899 WINPR_ASSERT(udp->mtu >= RDPUDP_MIN_MTU);
900
901 const UINT32 cumulative = v1_cumulative_ack(udp);
902 const BOOL withAoA = !udp->aoaAnnounced || (udp->announcedAoA != cumulative);
903
904 UINT16 flags = RDPUDP_FLAG_ACK;
905 if (withAoA)
906 flags |= RDPUDP_FLAG_ACK_OF_ACKS;
907 if (p)
908 {
909 flags |= RDPUDP_FLAG_DATA;
910 if (udp->cwrPending)
911 {
912 flags |= RDPUDP_FLAG_CWR;
913 udp->cwrPending = FALSE;
914 }
915 }
916
917 wStream* s = Stream_StaticInit(&sbuffer, buffer, sizeof(buffer));
918 if (!s)
919 return FALSE;
920
921 /* RDPUDP_FEC_HEADER */
922 Stream_Write_UINT32_BE(s, udp->receivedData ? udp->recvHighest
923 : udp->peerInitialSequence); /* snSourceAck */
924 Stream_Write_UINT16_BE(s, RDPUDP_RECEIVE_WINDOW); /* uReceiveWindowSize */
925 Stream_Write_UINT16_BE(s, flags); /* uFlags */
926
927 /* an ACK-only datagram must stay within the MTU too: header, vector, AckOfAcks */
928 v1_write_ack_vector(udp, s, p ? RDPUDP_ACK_ROOM - 4 : udp->mtu - 12u);
929 udp->ackPending = FALSE;
930
931 if (withAoA)
932 {
933 Stream_Write_UINT32_BE(s, cumulative); /* snResetSeqNum */
934 udp->announcedAoA = cumulative;
935 udp->aoaAnnounced = TRUE;
936 }
937
938 if (p)
939 {
940 /* RDPUDP_SOURCE_PAYLOAD_HEADER, a retransmission gets a new coded sequence number */
941 const UINT32 snCoded = udp->nextCoded++;
942 Stream_Write_UINT32_BE(s, snCoded); /* snCoded */
943 Stream_Write_UINT32_BE(s, p->seq); /* snSourceStart */
944 if (!Stream_CheckAndLogRequiredCapacityWLog(udp->log, s, p->length))
945 return FALSE;
946 Stream_Write(s, p->payload, p->length);
947 }
948
949 return rdpudp_send_raw(udp, Stream_Buffer(s), Stream_GetPosition(s));
950}
951
952WINPR_ATTR_NODISCARD
953static BOOL rdpudp_send_ack(rdpUdp* udp)
954{
955 WINPR_ASSERT(udp);
956 if (udp->state != RDPUDP_STATE_ESTABLISHED)
957 return TRUE;
958 if (udp->version == RDPUDP_PROTOCOL_VERSION_3)
959 return v3_send_ack(udp);
960 return v1_send_packet(udp, nullptr);
961}
962
963/* [MS-RDPEUDP2] 3.1.5.2 and 4.2: a receiver acknowledges once MaxDelayedAcks + 1 data packets
964 * wait, the most one ACK can describe, and at once when a packet goes missing or a missing one
965 * turns up. Checked after every datagram, so a burst is acknowledged while it is still arriving
966 * rather than when it ended. Fewer packets wait for ack_when_due. */
967WINPR_ATTR_NODISCARD
968static BOOL v3_ack_if_due(rdpUdp* udp)
969{
970 WINPR_ASSERT(udp);
971 if ((udp->version != RDPUDP_PROTOCOL_VERSION_3) || (udp->state != RDPUDP_STATE_ESTABLISHED) ||
972 !udp->ackPending)
973 return TRUE;
974 if ((v3_has_gap(udp) == udp->v3AckedGap) && (udp->v3UnackedPackets <= udp->v3MaxDelayedAcks))
975 return TRUE;
976 return v3_send_ack(udp);
977}
978
979/* [MS-RDPEUDP2] 3.1.5.2: half the round trip time until the peer's DelayAckInfo says otherwise */
980WINPR_ATTR_NODISCARD
981static UINT32 v3_ack_delay(const rdpUdp* udp)
982{
983 WINPR_ASSERT(udp);
984 return (udp->v3DelayedAckTimeout != UINT32_MAX) ? udp->v3DelayedAckTimeout : udp->srtt / 2;
985}
986
987/* Runs at the end of every receive round. Versions 1 and 2 acknowledge everything that arrived in
988 * one go, unless a data packet carried the ACK already. [MS-RDPEUDP2] 2.2.1.2.3: version 3 lets
989 * an acknowledgement wait DelayedAckTimeoutInMs, so that one ACK covers what arrives meanwhile.
990 * A receive round can be a single datagram, a burst has not ended with it. */
991WINPR_ATTR_NODISCARD
992static BOOL ack_when_due(rdpUdp* udp)
993{
994 WINPR_ASSERT(udp);
995 if (!udp->ackPending)
996 return TRUE;
997 if (udp->version == RDPUDP_PROTOCOL_VERSION_3)
998 {
999 if ((udp->state != RDPUDP_STATE_ESTABLISHED) || !udp->v3BaseKnown)
1000 return TRUE;
1001 const UINT64 now = now_ms();
1002 if (udp->v3AckDue == 0)
1003 udp->v3AckDue = now + v3_ack_delay(udp);
1004 if (now < udp->v3AckDue)
1005 return TRUE;
1006 }
1007 return rdpudp_send_ack(udp);
1008}
1009
1010WINPR_ATTR_NODISCARD
1011static BOOL rdpudp_transmit(rdpUdp* udp, const rdpudp_pending* p)
1012{
1013 WINPR_ASSERT(udp);
1014 WINPR_ASSERT(p);
1015 if (udp->version == RDPUDP_PROTOCOL_VERSION_3)
1016 return v3_send_data(udp, p);
1017 return v1_send_packet(udp, p);
1018}
1019
1020/* ------------------------------------------------------------------------------------------ */
1021/* Sending */
1022/* ------------------------------------------------------------------------------------------ */
1023
1024WINPR_ATTR_NODISCARD
1025static size_t window_limit(const rdpUdp* udp)
1026{
1027 WINPR_ASSERT(udp);
1028 size_t limit = RDPUDP_MAX_IN_FLIGHT;
1029 if ((udp->version != RDPUDP_PROTOCOL_VERSION_3) && (udp->peerWindow > 0) &&
1030 (udp->peerWindow < limit))
1031 limit = udp->peerWindow;
1032 return limit;
1033}
1034
1035/* Takes ownership of data, also when it fails. */
1036WINPR_ATTR_NODISCARD
1037static BOOL send_chunk_now(rdpUdp* udp, BYTE* data, size_t length)
1038{
1039 WINPR_ASSERT(udp);
1040 WINPR_ASSERT(data);
1041 rdpudp_pending* p = nullptr;
1042 for (size_t x = 0; x < RDPUDP_MAX_IN_FLIGHT; x++)
1043 {
1044 if (!udp->pending[x].used)
1045 {
1046 p = &udp->pending[x];
1047 break;
1048 }
1049 }
1050 if (!p)
1051 {
1052 free(data);
1053 return FALSE;
1054 }
1055
1056 /* the pending slot owns the payload from here, pending_clear frees it */
1057 p->used = TRUE;
1058 p->payload = data;
1059 p->length = length;
1060 if (udp->version == RDPUDP_PROTOCOL_VERSION_3)
1061 {
1062 const UINT16 coded = WINPR_ASSERTING_INT_CAST(UINT16, udp->nextCoded);
1063 p->seq = coded;
1064 udp->nextCoded = seq16_add(coded, 1);
1065 p->channelSeq = udp->nextChannelSeq;
1066 udp->nextChannelSeq = channel_seq_next(udp->nextChannelSeq);
1067 }
1068 else
1069 {
1070 p->seq = udp->nextSource++;
1071 }
1072
1073 const UINT64 now = now_ms();
1074 p->sent = now;
1075 p->rto = rto_initial(udp);
1076 p->due = now + p->rto;
1077 p->retransmits = 0;
1078 udp->inFlight++;
1079
1080 return rdpudp_transmit(udp, p);
1081}
1082
1083WINPR_ATTR_NODISCARD
1084static BOOL flush_send_queue(rdpUdp* udp)
1085{
1086 WINPR_ASSERT(udp);
1087 while ((udp->state == RDPUDP_STATE_ESTABLISHED) && (udp->inFlight < window_limit(udp)) &&
1088 (Queue_Count(udp->sendQueue) > 0))
1089 {
1090 rdpudp_chunk* chunk = Queue_Dequeue(udp->sendQueue);
1091 if (!chunk)
1092 break;
1093 BYTE* data = chunk->data;
1094 const size_t length = chunk->length;
1095 free(chunk);
1096 if (!send_chunk_now(udp, data, length))
1097 return FALSE;
1098 }
1099 return TRUE;
1100}
1101
1102BOOL rdpudp_send(rdpUdp* udp, const BYTE* data, size_t length)
1103{
1104 WINPR_ASSERT(udp);
1105 WINPR_ASSERT(data);
1106
1107 if ((length == 0) || (length > rdpudp_get_max_payload(udp)))
1108 return FALSE;
1109 if ((udp->state != RDPUDP_STATE_ESTABLISHED) && (udp->state != RDPUDP_STATE_SYN_SENT))
1110 return FALSE;
1111
1112 rdpudp_chunk* chunk = calloc(1, sizeof(rdpudp_chunk));
1113 if (!chunk)
1114 return FALSE;
1115 chunk->data = malloc(length);
1116 if (!chunk->data)
1117 {
1118 free(chunk);
1119 return FALSE;
1120 }
1121 memcpy(chunk->data, data, length);
1122 chunk->length = length;
1123
1124 if (!Queue_Enqueue(udp->sendQueue, chunk))
1125 {
1126 chunk_free(chunk);
1127 return FALSE;
1128 }
1129 // NOLINTNEXTLINE(clang-analyzer-unix.Malloc): Queue_Enqueue takes ownership of chunk
1130 return flush_send_queue(udp);
1131}
1132
1133static void sample_rtt(rdpUdp* udp, const rdpudp_pending* p)
1134{
1135 WINPR_ASSERT(udp);
1136 WINPR_ASSERT(p);
1137 /* Karn: a retransmitted packet says nothing reliable about the round trip */
1138 if (p->retransmits > 0)
1139 return;
1140 const UINT64 sample64 = now_ms() - p->sent;
1141 const UINT32 sample =
1142 (sample64 > UINT32_MAX) ? UINT32_MAX : WINPR_ASSERTING_INT_CAST(UINT32, sample64);
1143 udp->srtt = (udp->srtt == 0)
1144 ? sample
1145 : WINPR_ASSERTING_INT_CAST(UINT32, ((UINT64)udp->srtt * 7 + sample) / 8);
1146}
1147
1148static void acknowledge(rdpUdp* udp, rdpudp_pending* p)
1149{
1150 WINPR_ASSERT(udp);
1151 WINPR_ASSERT(p);
1152 sample_rtt(udp, p);
1153 pending_clear(p);
1154 if (udp->inFlight > 0)
1155 udp->inFlight--;
1156}
1157
1158static void acknowledge_seq(rdpUdp* udp, UINT32 seq)
1159{
1160 WINPR_ASSERT(udp);
1161 for (size_t x = 0; x < RDPUDP_MAX_IN_FLIGHT; x++)
1162 {
1163 rdpudp_pending* p = &udp->pending[x];
1164 if (p->used && (p->seq == seq))
1165 acknowledge(udp, p);
1166 }
1167}
1168
1169/* ------------------------------------------------------------------------------------------ */
1170/* Receiving */
1171/* ------------------------------------------------------------------------------------------ */
1172
1173WINPR_ATTR_NODISCARD
1174static BOOL deliver(rdpUdp* udp, const BYTE* data, size_t length)
1175{
1176 WINPR_ASSERT(udp);
1177 udp->lastDelivery = now_ms();
1178 if (length == 0)
1179 return TRUE;
1180 WINPR_ASSERT(data);
1181 WINPR_ASSERT(udp->receive);
1182 if (!udp->receive(udp->custom, data, length))
1183 {
1184 rdpudp_fail(udp, "receiver rejected data");
1185 return FALSE;
1186 }
1187 return TRUE;
1188}
1189
1190WINPR_ATTR_NODISCARD
1191static BOOL store_slot(rdpUdp* udp, UINT32 seq, const BYTE* data, size_t length)
1192{
1193 WINPR_ASSERT(udp);
1194 WINPR_ASSERT(data || (length == 0));
1195 rdpudp_slot* slot = &udp->slots[seq % RDPUDP_RECEIVE_SLOTS];
1196 if (slot->present)
1197 {
1198 if (slot->seq == seq)
1199 return TRUE; /* duplicate */
1200 slot_clear(slot);
1201 udp->buffered--;
1202 }
1203
1204 slot->data = nullptr;
1205 if (length > 0)
1206 {
1207 slot->data = malloc(length);
1208 if (!slot->data)
1209 return FALSE;
1210 memcpy(slot->data, data, length);
1211 }
1212 slot->length = length;
1213 slot->seq = seq;
1214 slot->present = TRUE;
1215 if (udp->buffered++ == 0)
1216 udp->bufferingSince = now_ms();
1217 return TRUE;
1218}
1219
1220WINPR_ATTR_NODISCARD
1221static BOOL v1_receive_source(rdpUdp* udp, UINT32 seq, const BYTE* data, size_t length)
1222{
1223 WINPR_ASSERT(udp);
1224 WINPR_ASSERT(data || (length == 0));
1225 if (!udp->receivedData)
1226 {
1227 /* [MS-RDPEUDP] puts the first source packet at the initial sequence number plus one,
1228 * an implementation that uses the initial sequence number itself is accepted too. */
1229 if (seq == udp->peerInitialSequence)
1230 {
1231 udp->recvNext = seq;
1232 udp->ackVectorStart = seq;
1233 }
1234 udp->recvHighest = seq32_diff(udp->recvNext, 1);
1235 }
1236
1237 udp->ackPending = TRUE;
1238
1239 if (seq32_after(udp->recvNext, seq))
1240 return TRUE; /* already delivered, the ACK above tells the peer again */
1241
1242 const UINT32 ahead = seq32_diff(seq, udp->recvNext);
1243 if (ahead >= RDPUDP_RECEIVE_REACH)
1244 return TRUE;
1245
1246 udp->receivedData = TRUE;
1247 if (seq32_after(seq, udp->recvHighest))
1248 udp->recvHighest = seq;
1249
1250 if (!store_slot(udp, seq, data, length))
1251 return FALSE;
1252
1253 while (TRUE)
1254 {
1255 rdpudp_slot* slot = &udp->slots[udp->recvNext % RDPUDP_RECEIVE_SLOTS];
1256 if (!slot->present || (slot->seq != udp->recvNext))
1257 break;
1258 BYTE* chunk = slot->data;
1259 const size_t chunkLength = slot->length;
1260 slot->data = nullptr;
1261 slot->present = FALSE;
1262 udp->buffered--;
1263 udp->recvNext++;
1264 const BOOL rc = deliver(udp, chunk, chunkLength);
1265 free(chunk);
1266 if (!rc)
1267 return FALSE;
1268 }
1269 return TRUE;
1270}
1271
1272/* Applies the peer's ACK vector, which ends at its snSourceAck, to our own packets. */
1273static void v1_process_ack_vector(rdpUdp* udp, UINT32 snSourceAck, wStream* s, size_t count)
1274{
1275 WINPR_ASSERT(udp);
1276 WINPR_ASSERT(s);
1277 /* count comes from the wire, v1_process_datagram bounds it */
1278 WINPR_ASSERT(count <= RDPUDP_MAX_ACK_VECTOR);
1279 const size_t start = Stream_GetPosition(s);
1280 UINT32 total = 0;
1281 for (size_t x = 0; x < count; x++)
1282 total += (Stream_Get_UINT8(s) & 0x3Fu) + 1u; /* a run of n datagrams is sent as n - 1 */
1283 if ((total == 0) || !Stream_SetPosition(s, start))
1284 return;
1285
1286 UINT32 seq = seq32_add(seq32_diff(snSourceAck, total), 1);
1287 for (size_t x = 0; x < count; x++)
1288 {
1289 const BYTE element = Stream_Get_UINT8(s);
1290 const BYTE state = WINPR_ASSERTING_INT_CAST(BYTE, element >> 6);
1291 const BYTE run = WINPR_ASSERTING_INT_CAST(BYTE, (element & 0x3F) + 1);
1292 for (BYTE y = 0; y < run; y++)
1293 {
1294 if (state == DATAGRAM_RECEIVED)
1295 acknowledge_seq(udp, seq);
1296 seq++;
1297 }
1298 }
1299}
1300
1301WINPR_ATTR_NODISCARD
1302static BOOL v1_process_datagram(rdpUdp* udp, const BYTE* data, size_t length)
1303{
1304 wStream sbuffer = WINPR_C_ARRAY_INIT;
1305 WINPR_ASSERT(udp);
1306 WINPR_ASSERT(data);
1307 wStream* s = Stream_StaticConstInit(&sbuffer, data, length);
1308
1309 /* RDPUDP_FEC_HEADER */
1310 if (!Stream_CheckAndLogRequiredLengthWLog(udp->log, s, 8))
1311 return TRUE;
1312 const UINT32 snSourceAck = Stream_Get_UINT32_BE(s);
1313 const UINT16 window = Stream_Get_UINT16_BE(s);
1314 const UINT16 flags = Stream_Get_UINT16_BE(s);
1315
1316 if (flags & RDPUDP_FLAG_SYN)
1317 {
1318 /* a repeated SYN+ACK: our acknowledgement of it got lost */
1319 udp->ackPending = TRUE;
1320 return TRUE;
1321 }
1322
1323 udp->peerWindow = window;
1324 if (flags & RDPUDP_FLAG_CN)
1325 udp->cwrPending = TRUE;
1326
1327 if (flags & RDPUDP_FLAG_ACK)
1328 {
1329 /* RDPUDP_ACK_VECTOR_HEADER */
1330 if (!Stream_CheckAndLogRequiredLengthWLog(udp->log, s, 2))
1331 return TRUE;
1332 const size_t size = Stream_Get_UINT16_BE(s);
1333 if (size > RDPUDP_MAX_ACK_VECTOR)
1334 return TRUE; /* [MS-RDPEUDP] 2.2.2.7: more than 2048 elements is invalid, drop */
1335 const size_t padding = (4 - ((2 + size) % 4)) % 4;
1336 if (!Stream_CheckAndLogRequiredLengthWLog(udp->log, s, size + padding))
1337 return TRUE;
1338 v1_process_ack_vector(udp, snSourceAck, s, size);
1339 Stream_Seek(s, padding);
1340 }
1341
1342 if (flags & RDPUDP_FLAG_ACK_OF_ACKS)
1343 {
1344 /* RDPUDP_ACK_OF_ACKVECTOR_HEADER */
1345 if (!Stream_CheckAndLogRequiredLengthWLog(udp->log, s, 4))
1346 return TRUE;
1347 const UINT32 reset = Stream_Get_UINT32_BE(s);
1348 /* the peer has seen our acknowledgements up to here, the ACK vector can start later */
1349 const UINT32 start = seq32_add(reset, 1);
1350 if (seq32_after(start, udp->ackVectorStart) && !seq32_after(start, udp->recvNext))
1351 udp->ackVectorStart = start;
1352 }
1353
1354 if ((flags & RDPUDP_FLAG_CORRELATION_ID) && !Stream_SafeSeek(s, 32))
1355 return TRUE;
1356
1357 if (!(flags & RDPUDP_FLAG_DATA))
1358 return TRUE;
1359
1360 if (flags & RDPUDP_FLAG_FEC)
1361 return TRUE; /* FEC packets are not acknowledged, losses are recovered by resending */
1362
1363 /* RDPUDP_SOURCE_PAYLOAD_HEADER */
1364 if (!Stream_CheckAndLogRequiredLengthWLog(udp->log, s, 8))
1365 return TRUE;
1366 Stream_Seek_UINT32(s); /* snCoded */
1367 const UINT32 snSourceStart = Stream_Get_UINT32_BE(s);
1368 return v1_receive_source(udp, snSourceStart, Stream_ConstPointer(s),
1369 Stream_GetRemainingLength(s));
1370}
1371
1372static void v3_advance_window(rdpUdp* udp)
1373{
1374 WINPR_ASSERT(udp);
1375 while (udp->v3Received[udp->v3Expected % RDPUDP_RECEIVE_SLOTS])
1376 {
1377 const size_t slot = udp->v3Expected % RDPUDP_RECEIVE_SLOTS;
1378 udp->v3InOrderArrival = udp->v3Arrival[slot];
1379 udp->v3InOrderReceived = TRUE;
1380 udp->v3Received[slot] = FALSE;
1381 udp->v3Expected++;
1382 }
1383}
1384
1385/* After a silence the peer may have moved more than half the 16 bit sequence space on: through
1386 * an outage it resends its window again and again under new numbers, Windows used about 45000 in
1387 * 25 s. Serial arithmetic then takes its numbers for old ones, and acknowledging our old position
1388 * names numbers it has not sent, for which Windows resets the connection. So after a silence the
1389 * peer's next AckOfAcks becomes the base, whichever way it moves it. */
1390static void v3_resync_base(rdpUdp* udp, UINT16 base)
1391{
1392 WINPR_ASSERT(udp);
1393 udp->v3Resync = FALSE;
1394 if (base == udp->v3Expected)
1395 return;
1396
1397 WLog_Print(udp->log, WLOG_DEBUG,
1398 "heard from the peer again, its AckOfAcks 0x%04" PRIx16 " replaces 0x%04" PRIx16,
1399 base, udp->v3Expected);
1400 memset(udp->v3Received, 0, sizeof(udp->v3Received));
1401 memset(udp->v3Arrival, 0, sizeof(udp->v3Arrival));
1402 udp->v3Expected = base;
1403 udp->v3Highest = seq16_diff(base, 1);
1404 udp->v3InOrderReceived = FALSE;
1405 udp->ackPending = TRUE;
1406 udp->v3WindowPending = TRUE;
1407}
1408
1409/* Marks a silence of RDPUDP2_RESYNC_MS, see v3_resync_base. */
1410static void v3_note_silence(rdpUdp* udp, UINT64 now)
1411{
1412 WINPR_ASSERT(udp);
1413 if ((udp->version == RDPUDP_PROTOCOL_VERSION_3) && udp->v3BaseKnown &&
1414 (now - udp->lastReceived >= RDPUDP2_RESYNC_MS))
1415 udp->v3Resync = TRUE;
1416}
1417
1418static void v3_advance_base(rdpUdp* udp, UINT16 base)
1419{
1420 WINPR_ASSERT(udp);
1421 /* However far ahead: through an outage the peer resends its window again and again, each
1422 * time under new sequence numbers, and Windows moved almost 5000 ahead in a 2 second outage.
1423 * Only its AckOfAcks brings this side along, data that far ahead is out of reach. seq16_after
1424 * limits the jump to half the sequence space, v3_resync_base goes further after a silence. */
1425 if (!udp->v3BaseKnown)
1426 return;
1427 if (udp->v3Resync)
1428 {
1429 v3_resync_base(udp, base);
1430 return;
1431 }
1432 if (!seq16_after(base, udp->v3Expected))
1433 return;
1434
1435 /* The peer stopped resending everything below base. This only gives up transport sequence
1436 * numbers: a chunk of the stream sent there comes back under a later one, with its channel
1437 * sequence number unchanged. */
1438 while (udp->v3Expected != base)
1439 {
1440 const size_t slot = udp->v3Expected % RDPUDP_RECEIVE_SLOTS;
1441 udp->v3Received[slot] = FALSE;
1442 udp->v3Arrival[slot] = 0; /* never arrived, no arrival gap to report for it */
1443 udp->v3Expected++;
1444 }
1445 udp->v3InOrderReceived = FALSE;
1446 const UINT16 last = seq16_diff(base, 1);
1447 if (seq16_after(last, udp->v3Highest))
1448 udp->v3Highest = last;
1449 v3_advance_window(udp);
1450 udp->ackPending = TRUE;
1451 udp->v3WindowPending = TRUE;
1452}
1453
1454static void v3_process_ack_vector(rdpUdp* udp, UINT16 base, wStream* s, size_t count)
1455{
1456 WINPR_ASSERT(udp);
1457 WINPR_ASSERT(s);
1458 UINT16 seq = base;
1459 for (size_t x = 0; x < count; x++)
1460 {
1461 const BYTE entry = Stream_Get_UINT8(s);
1462 if (entry & 0x80)
1463 {
1464 /* run length: received flag and length */
1465 const BOOL received = (entry & 0x40) != 0;
1466 const BYTE run = entry & 0x3F;
1467 for (BYTE y = 0; y < run; y++)
1468 {
1469 if (received)
1470 acknowledge_seq(udp, seq);
1471 seq++;
1472 }
1473 }
1474 else
1475 {
1476 /* state map of 7 packets, bit 0 first */
1477 for (BYTE bit = 0; bit < 7; bit++)
1478 {
1479 if (entry & (1 << bit))
1480 acknowledge_seq(udp, seq);
1481 seq++;
1482 }
1483 }
1484 }
1485
1486 /* everything below the base has been received */
1487 for (size_t x = 0; x < RDPUDP_MAX_IN_FLIGHT; x++)
1488 {
1489 rdpudp_pending* p = &udp->pending[x];
1490 if (p->used && seq16_after(base, WINPR_ASSERTING_INT_CAST(UINT16, p->seq)))
1491 acknowledge(udp, p);
1492 }
1493}
1494
1495static void v3_process_ack(rdpUdp* udp, UINT16 ack)
1496{
1497 WINPR_ASSERT(udp);
1498 for (size_t x = 0; x < RDPUDP_MAX_IN_FLIGHT; x++)
1499 {
1500 rdpudp_pending* p = &udp->pending[x];
1501 if (p->used && !seq16_after(WINPR_ASSERTING_INT_CAST(UINT16, p->seq), ack))
1502 acknowledge(udp, p);
1503 }
1504}
1505
1506/* Hands up the chunks that are next in the stream, in channel sequence order. */
1507WINPR_ATTR_NODISCARD
1508static BOOL v3_deliver_ready(rdpUdp* udp)
1509{
1510 WINPR_ASSERT(udp);
1511 while (TRUE)
1512 {
1513 rdpudp_slot* slot = &udp->slots[udp->v3NextChannel % RDPUDP_RECEIVE_SLOTS];
1514 if (!slot->present || (slot->seq != udp->v3NextChannel))
1515 break;
1516 BYTE* chunk = slot->data;
1517 const size_t chunkLength = slot->length;
1518 slot->data = nullptr;
1519 slot->present = FALSE;
1520 udp->buffered--;
1521 udp->v3NextChannel = channel_seq_next(udp->v3NextChannel);
1522 const BOOL rc = deliver(udp, chunk, chunkLength);
1523 free(chunk);
1524 if (!rc)
1525 return FALSE;
1526 }
1527 return TRUE;
1528}
1529
1530WINPR_ATTR_NODISCARD
1531static BOOL v3_receive_channel_data(rdpUdp* udp, UINT16 channelSeq, const BYTE* data, size_t length)
1532{
1533 WINPR_ASSERT(udp);
1534 WINPR_ASSERT(data || (length == 0));
1535 /* A retransmission travels under a new data sequence number with its original channel
1536 * sequence, so the channel sequence alone says where a chunk belongs and whether it has
1537 * been handed up already. */
1538 const UINT16 ahead = seq16_diff(channelSeq, udp->v3NextChannel);
1539 if (ahead >= RDPUDP_RECEIVE_REACH)
1540 return TRUE;
1541
1542 /* The chunk next in line goes up straight from the datagram, without a copy in a slot. */
1543 if ((ahead == 0) && !udp->slots[channelSeq % RDPUDP_RECEIVE_SLOTS].present)
1544 {
1545 udp->v3NextChannel = channel_seq_next(udp->v3NextChannel);
1546 if (!deliver(udp, data, length))
1547 return FALSE;
1548 return v3_deliver_ready(udp);
1549 }
1550
1551 if (!store_slot(udp, channelSeq, data, length))
1552 return FALSE;
1553 return v3_deliver_ready(udp);
1554}
1555
1556WINPR_ATTR_NODISCARD
1557static BOOL v3_process_datagram(rdpUdp* udp, BYTE* data, size_t length)
1558{
1559 WINPR_ASSERT(udp);
1560 WINPR_ASSERT(data);
1561 if (length < 8)
1562 return TRUE;
1563
1564 /* undo the swap of the first and eighth byte ([MS-RDPEUDP2] 2.2.1). In place: with only
1565 * DATA set the chunk starts at the eighth byte, so a copy of the header would not do. */
1566 const BYTE eighth = data[7];
1567 data[7] = data[0];
1568 data[0] = eighth;
1569
1570 wStream sbuffer = WINPR_C_ARRAY_INIT;
1571 wStream* s = Stream_StaticConstInit(&sbuffer, data, length);
1572
1573 const BYTE prefix = Stream_Get_UINT8(s);
1574 if (prefix & 0x01)
1575 return TRUE;
1576 const BYTE shortLength = WINPR_ASSERTING_INT_CAST(BYTE, prefix >> 5);
1577 const BYTE packetType = WINPR_ASSERTING_INT_CAST(BYTE, (prefix >> 1) & 0x0F);
1578 if ((packetType != RDPUDP2_PACKET_STANDARD) && (packetType != RDPUDP2_PACKET_DUMMY))
1579 return TRUE;
1580 /* a packet shorter than 7 bytes was padded, its real length is in the prefix */
1581 if ((shortLength > 0) && (shortLength < 7) && !Stream_SetLength(s, 1ull + shortLength))
1582 return TRUE;
1583
1584 if (!Stream_CheckAndLogRequiredLengthWLog(udp->log, s, 2))
1585 return TRUE;
1586 const UINT16 flags = Stream_Get_UINT16(s) & 0x0FFF;
1587
1588 if ((flags & RDPUDP2_ACK) && (flags & RDPUDP2_ACKVEC))
1589 return TRUE;
1590
1591 if (flags & RDPUDP2_ACK)
1592 {
1593 if (!Stream_CheckAndLogRequiredLengthWLog(udp->log, s, 7))
1594 return TRUE;
1595 const UINT16 ack = Stream_Get_UINT16(s); /* SeqNum */
1596 Stream_Seek(s, 4); /* receivedTS, sendAckTimeGapInMs */
1597 const size_t delayed = Stream_Get_UINT8(s) & 0x0F; /* numDelayedAcks */
1598 if (!Stream_SafeSeek(s, delayed)) /* DelayAckTimeAdditions */
1599 return TRUE;
1600 v3_process_ack(udp, ack);
1601 }
1602
1603 if ((flags & RDPUDP2_OVERHEADSIZE) && !Stream_SafeSeek(s, 1))
1604 return TRUE;
1605
1606 if (flags & RDPUDP2_DELAYACKINFO)
1607 {
1608 /* [MS-RDPEUDP2] 2.2.1.2.3: how many data packets the peer lets us acknowledge at once,
1609 * and how long an acknowledgement may wait */
1610 if (!Stream_CheckAndLogRequiredLengthWLog(udp->log, s, 3))
1611 return TRUE;
1612 const size_t maxDelayed = Stream_Get_UINT8(s); /* MaxDelayedAcks */
1613 udp->v3DelayedAckTimeout = Stream_Get_UINT16(s); /* DelayedAckTimeoutInMs */
1614 if (maxDelayed == 0)
1615 udp->v3MaxDelayedAcks = 1;
1616 else if (maxDelayed > RDPUDP2_MAX_DELAYED_ACKS)
1617 udp->v3MaxDelayedAcks = RDPUDP2_MAX_DELAYED_ACKS;
1618 else
1619 udp->v3MaxDelayedAcks = maxDelayed;
1620 }
1621
1622 BOOL haveAoA = FALSE;
1623 UINT16 aoa = 0;
1624 if (flags & RDPUDP2_AOA)
1625 {
1626 if (!Stream_CheckAndLogRequiredLengthWLog(udp->log, s, 2))
1627 return TRUE;
1628 aoa = Stream_Get_UINT16(s);
1629 haveAoA = TRUE;
1630 }
1631
1632 BOOL haveData = FALSE;
1633 UINT16 dataSeq = 0;
1634 if (flags & RDPUDP2_DATA)
1635 {
1636 if (!Stream_CheckAndLogRequiredLengthWLog(udp->log, s, 2))
1637 return TRUE;
1638 dataSeq = Stream_Get_UINT16(s);
1639 haveData = TRUE;
1640 }
1641
1642 if (flags & RDPUDP2_ACKVEC)
1643 {
1644 if (!Stream_CheckAndLogRequiredLengthWLog(udp->log, s, 3))
1645 return TRUE;
1646 const UINT16 base = Stream_Get_UINT16(s); /* BaseSeqNum */
1647 const BYTE control = Stream_Get_UINT8(s);
1648 const size_t size = control & 0x7F; /* codedAckVecSize */
1649 /* TimeStamp, SendAckTimeGapInMs */
1650 if ((control & 0x80) && !Stream_SafeSeek(s, 4))
1651 return TRUE;
1652 if (!Stream_CheckAndLogRequiredLengthWLog(udp->log, s, size))
1653 return TRUE;
1654 v3_process_ack_vector(udp, base, s, size);
1655 }
1656
1657 /* AckOfAcks moves the lower edge of our receive window. It is the only way past a lost
1658 * dummy packet, those are never resent. */
1659 if (haveAoA)
1660 v3_advance_base(udp, aoa);
1661
1662 if (!haveData)
1663 return TRUE;
1664
1665 udp->v3LatestArrival = winpr_GetTickCount64NS();
1666 udp->v3UnackedPackets++;
1667 udp->receivedData = TRUE;
1668 if (!udp->v3BaseKnown)
1669 {
1670 /* Windows announces where its sequence space starts in the AckOfAcks of its first
1671 * DATA packets. Taking the base from that, rather than from whichever packet arrives
1672 * first, keeps a lost or late first packet from being acknowledged unseen. */
1673 UINT16 base = dataSeq;
1674 if (haveAoA && !seq16_after(aoa, dataSeq) &&
1675 (seq16_diff(dataSeq, aoa) < RDPUDP_RECEIVE_REACH))
1676 base = aoa;
1677 udp->v3BaseKnown = TRUE;
1678 udp->v3Expected = base;
1679 udp->v3Highest = seq16_diff(base, 1);
1680 udp->v3AckedSeq = seq16_diff(base, 1);
1681 }
1682
1683 const UINT16 ahead = seq16_diff(dataSeq, udp->v3Expected);
1684 /* Behind the window: resent because our ACK got lost, given up by an AckOfAcks, or ahead of
1685 * a position of ours the peer's numbers wrapped past. The window only tracks acknowledgements
1686 * ([MS-RDPEUDP2] 3.1.1.2.2): the packet is acknowledged on its own, and its chunk still goes
1687 * to the channel sequence, which drops it if it was handed up already (3.1.1.2.4.2). */
1688 const BOOL behind = (ahead >= 0x8000);
1689 /* Windows at times puts the next sequence number in the AckOfAcks of a data packet, past the
1690 * packet itself. The peer has the acknowledgments for everything below its AckOfAcks, the
1691 * receiver does not report those again (2.2.1.2.4), and Windows ends the connection on an ACK
1692 * vector for such a packet. Only its chunk counts. */
1693 const BOOL acknowledged = haveAoA && seq16_after(aoa, dataSeq);
1694 if (behind && !acknowledged)
1695 {
1696 /* a run of consecutive ones goes in one ACK vector, see v3_send_ack */
1697 const BOOL extends = (udp->v3BehindCount > 0) &&
1698 (dataSeq == seq16_add(udp->v3BehindBase, udp->v3BehindCount)) &&
1699 (udp->v3BehindCount < 63ull * RDPUDP2_MAX_ACKVEC);
1700 if ((udp->v3BehindCount > 0) && !extends && !v3_send_ack(udp))
1701 return FALSE;
1702 if (!extends)
1703 {
1704 udp->v3BehindBase = dataSeq;
1705 udp->v3BehindCount = 0;
1706 }
1707 udp->v3BehindCount++;
1708 udp->v3BehindArrival = udp->v3LatestArrival;
1709 udp->ackPending = TRUE;
1710 }
1711 else if (!behind)
1712 {
1713 udp->ackPending = TRUE;
1714 udp->v3WindowPending = TRUE;
1715 if (ahead >= RDPUDP_RECEIVE_REACH)
1716 return TRUE;
1717 }
1718
1719 /* A dummy packet occupies a sequence number but its body means nothing. */
1720 const BOOL withChunk =
1721 (packetType != RDPUDP2_PACKET_DUMMY) && (Stream_GetRemainingLength(s) >= 2);
1722 UINT16 channelSeq = 0;
1723 if (withChunk)
1724 {
1725 /* A chunk out of reach cannot be kept. Its packet stays unacknowledged then, so the
1726 * peer sends it again: acknowledged, it would be gone for good. */
1727 channelSeq = Stream_Get_UINT16(s); /* ChannelSeqNum */
1728 const UINT16 chunkAhead = seq16_diff(channelSeq, udp->v3NextChannel);
1729 if ((chunkAhead >= RDPUDP_RECEIVE_REACH) && (chunkAhead < 0x8000))
1730 return TRUE;
1731 }
1732
1733 if (!behind)
1734 {
1735 if (seq16_after(dataSeq, udp->v3Highest))
1736 udp->v3Highest = dataSeq;
1737 udp->v3Received[dataSeq % RDPUDP_RECEIVE_SLOTS] = TRUE;
1738 udp->v3Arrival[dataSeq % RDPUDP_RECEIVE_SLOTS] = udp->v3LatestArrival;
1739 v3_advance_window(udp);
1740 }
1741
1742 if (!withChunk)
1743 return TRUE;
1744 return v3_receive_channel_data(udp, channelSeq, Stream_ConstPointer(s),
1745 Stream_GetRemainingLength(s));
1746}
1747
1748/* ------------------------------------------------------------------------------------------ */
1749/* Connection setup */
1750/* ------------------------------------------------------------------------------------------ */
1751
1752WINPR_ATTR_NODISCARD
1753static BOOL send_syn(rdpUdp* udp)
1754{
1755 WINPR_ASSERT(udp);
1756 /* [MS-RDPEUDP] 3.1.5.1.1: zero padded to the MTU, which validates the path MTU */
1757 BYTE syn[RDPUDP_MTU] = WINPR_C_ARRAY_INIT;
1758 wStream sbuffer = WINPR_C_ARRAY_INIT;
1759 wStream* s = Stream_StaticInit(&sbuffer, syn, sizeof(syn));
1760 if (!s)
1761 return FALSE;
1762 const UINT16 version = udp->offerV3 ? RDPUDP_PROTOCOL_VERSION_3 : RDPUDP_PROTOCOL_VERSION_2;
1763
1764 /* RDPUDP_FEC_HEADER */
1765 Stream_Write_UINT32_BE(s, UINT32_MAX); /* snSourceAck: -1 */
1766 Stream_Write_UINT16_BE(s, RDPUDP_RECEIVE_WINDOW);
1767 Stream_Write_UINT16_BE(s, RDPUDP_FLAG_SYN | RDPUDP_FLAG_SYNEX);
1768
1769 /* RDPUDP_SYNDATA_PAYLOAD */
1770 Stream_Write_UINT32_BE(s, udp->initialSequence);
1771 Stream_Write_UINT16_BE(s, RDPUDP_MTU); /* uUpStreamMtu */
1772 Stream_Write_UINT16_BE(s, RDPUDP_MTU); /* uDownStreamMtu */
1773
1774 /* RDPUDP_SYNDATAEX_PAYLOAD */
1775 Stream_Write_UINT16_BE(s, RDPUDP_VERSION_INFO_VALID);
1776 Stream_Write_UINT16_BE(s, version);
1777 if (version == RDPUDP_PROTOCOL_VERSION_3)
1778 Stream_Write(s, udp->cookieHash, sizeof(udp->cookieHash));
1779
1780 udp->synSent = now_ms();
1781 udp->synAttempts++;
1782 WLog_Print(udp->log, WLOG_DEBUG, "sending SYN #%" PRIu32 " offering version 0x%04" PRIx16,
1783 udp->synAttempts, version);
1784 return rdpudp_send_raw(udp, syn, sizeof(syn));
1785}
1786
1787WINPR_ATTR_NODISCARD
1788static BOOL process_syn_ack(rdpUdp* udp, const BYTE* data, size_t length)
1789{
1790 wStream sbuffer = WINPR_C_ARRAY_INIT;
1791 WINPR_ASSERT(udp);
1792 WINPR_ASSERT(data);
1793 wStream* s = Stream_StaticConstInit(&sbuffer, data, length);
1794
1795 /* RDPUDP_FEC_HEADER and RDPUDP_SYNDATA_PAYLOAD */
1796 if (!Stream_CheckAndLogRequiredLengthWLog(udp->log, s, 16))
1797 return TRUE;
1798 const UINT32 snSourceAck = Stream_Get_UINT32_BE(s);
1799 const UINT16 window = Stream_Get_UINT16_BE(s);
1800 const UINT16 flags = Stream_Get_UINT16_BE(s);
1801 if ((flags & (RDPUDP_FLAG_SYN | RDPUDP_FLAG_ACK)) != (RDPUDP_FLAG_SYN | RDPUDP_FLAG_ACK))
1802 return TRUE;
1803 /* The server's answer acknowledges the random snInitialSequenceNumber of our SYN. One that
1804 * does not was not sent in answer to it and is dropped, so a third party that spoofs the
1805 * server's address has to guess that number to set up the connection. */
1806 if (snSourceAck != udp->initialSequence)
1807 {
1808 WLog_Print(udp->log, WLOG_WARN,
1809 "dropping a SYN+ACK that acknowledges 0x%08" PRIx32
1810 ", the SYN carried 0x%08" PRIx32,
1811 snSourceAck, udp->initialSequence);
1812 return TRUE;
1813 }
1814
1815 const UINT32 peerInitial = Stream_Get_UINT32_BE(s); /* snInitialSequenceNumber */
1816 UINT16 upMtu = Stream_Get_UINT16_BE(s); /* uUpStreamMtu */
1817 Stream_Seek_UINT16(s); /* uDownStreamMtu */
1818
1819 if ((flags & RDPUDP_FLAG_CORRELATION_ID) && !Stream_SafeSeek(s, 32))
1820 return TRUE;
1821
1822 /* RDPUDP_SYNDATAEX_PAYLOAD, without it the peer only speaks version 1 */
1823 UINT16 version = RDPUDP_PROTOCOL_VERSION_1;
1824 if ((flags & RDPUDP_FLAG_SYNEX) && (Stream_GetRemainingLength(s) >= 4))
1825 {
1826 const UINT16 synExFlags = Stream_Get_UINT16_BE(s);
1827 const UINT16 udpVersion = Stream_Get_UINT16_BE(s);
1828 if (synExFlags & RDPUDP_VERSION_INFO_VALID)
1829 version = udpVersion;
1830 }
1831
1832 switch (version)
1833 {
1834 case RDPUDP_PROTOCOL_VERSION_1:
1835 case RDPUDP_PROTOCOL_VERSION_2:
1836 break;
1837 case RDPUDP_PROTOCOL_VERSION_3:
1838 /* a server that rejected the cookie hash answers with version 2 */
1839 if (!udp->offerV3)
1840 version = RDPUDP_PROTOCOL_VERSION_2;
1841 break;
1842 default:
1843 version = RDPUDP_PROTOCOL_VERSION_1;
1844 break;
1845 }
1846
1847 if ((upMtu < RDPUDP_MIN_MTU) || (upMtu > RDPUDP_MTU))
1848 upMtu = RDPUDP_MIN_MTU;
1849
1850 udp->mtu = upMtu;
1851 udp->version = version;
1852 udp->peerWindow = window;
1853 udp->peerInitialSequence = peerInitial;
1854 udp->recvNext = seq32_add(peerInitial, 1);
1855 udp->recvHighest = peerInitial;
1856 udp->ackVectorStart = seq32_add(peerInitial, 1);
1857 udp->lastDelivery = now_ms();
1858 udp->state = RDPUDP_STATE_ESTABLISHED;
1859
1860 if (version == RDPUDP_PROTOCOL_VERSION_3)
1861 {
1862 /* The 32 bit sequence numbers of the SYN exchange only exist for versions 1 and 2. The
1863 * peer's RDP-UDP2 sequence space is learned from its first DATA packet. */
1864 udp->nextCoded = RDPUDP2_INITIAL_SEQUENCE;
1865 udp->nextChannelSeq = 1;
1866 /* The peer's stream starts at channel sequence 1 too. Taking the start from whichever
1867 * chunk arrives first would throw away an earlier one that it overtook. */
1868 udp->v3NextChannel = 1;
1869 udp->v3MaxDelayedAcks = RDPUDP2_DEFAULT_DELAYED_ACKS;
1870 udp->v3DelayedAckTimeout = UINT32_MAX;
1871 }
1872 else
1873 {
1874 udp->nextSource = seq32_add(udp->initialSequence, 1);
1875 udp->nextCoded = seq32_add(udp->initialSequence, 1);
1876 /* the client completes the three way handshake by acknowledging the SYN+ACK */
1877 udp->ackPending = TRUE;
1878 }
1879
1880 WLog_Print(udp->log, WLOG_INFO,
1881 "RDP-UDP connected, protocol version 0x%04" PRIx16 ", MTU %" PRIu16, version, upMtu);
1882 return flush_send_queue(udp);
1883}
1884
1885WINPR_ATTR_NODISCARD
1886static BOOL process_datagram(rdpUdp* udp, BYTE* data, size_t length)
1887{
1888 WINPR_ASSERT(udp);
1889 WINPR_ASSERT(data);
1890 const UINT64 now = now_ms();
1891 v3_note_silence(udp, now);
1892 udp->lastReceived = now;
1893
1894 switch (udp->state)
1895 {
1896 case RDPUDP_STATE_SYN_SENT:
1897 return process_syn_ack(udp, data, length);
1898 case RDPUDP_STATE_ESTABLISHED:
1899 if (udp->version == RDPUDP_PROTOCOL_VERSION_3)
1900 return v3_process_datagram(udp, data, length);
1901 return v1_process_datagram(udp, data, length);
1902 default:
1903 return TRUE;
1904 }
1905}
1906
1907/* ------------------------------------------------------------------------------------------ */
1908/* Timers */
1909/* ------------------------------------------------------------------------------------------ */
1910
1911WINPR_ATTR_NODISCARD
1912static BOOL run_timers(rdpUdp* udp)
1913{
1914 WINPR_ASSERT(udp);
1915 const UINT64 now = now_ms();
1916
1917 if (udp->state == RDPUDP_STATE_SYN_SENT)
1918 {
1919 if (now - udp->synSent < RDPUDP_SYN_TIMEOUT_MS)
1920 return TRUE;
1921 if (udp->synAttempts >= RDPUDP_SYN_ATTEMPTS)
1922 {
1923 rdpudp_fail(udp, "no SYN+ACK from the server");
1924 return FALSE;
1925 }
1926 return send_syn(udp);
1927 }
1928
1929 if (udp->state != RDPUDP_STATE_ESTABLISHED)
1930 return FALSE;
1931
1932 const BOOL v3 = udp->version == RDPUDP_PROTOCOL_VERSION_3;
1933 if (now - udp->lastReceived > (v3 ? RDPUDP2_PEER_TIMEOUT_MS : RDPUDP_PEER_TIMEOUT_MS))
1934 {
1935 rdpudp_fail(udp, v3 ? "nothing heard from the server for 16 seconds"
1936 : "nothing heard from the server for 65 seconds");
1937 return FALSE;
1938 }
1939 v3_note_silence(udp, now);
1940
1941 /* stuck: chunks have been waiting behind a hole, and nothing moved, for the whole timeout */
1942 const UINT64 progress =
1943 (udp->bufferingSince > udp->lastDelivery) ? udp->bufferingSince : udp->lastDelivery;
1944 if ((udp->buffered > 0) && (now - progress > RDPUDP_STALL_TIMEOUT_MS))
1945 {
1946 rdpudp_fail(udp, "the stream is stuck behind a chunk the server no longer resends");
1947 return FALSE;
1948 }
1949
1950 for (size_t x = 0; x < RDPUDP_MAX_IN_FLIGHT; x++)
1951 {
1952 rdpudp_pending* p = &udp->pending[x];
1953 if (!p->used || (now < p->due))
1954 continue;
1955 if (p->retransmits >= (v3 ? RDPUDP2_MAX_RETRANSMITS : RDPUDP_MAX_RETRANSMITS))
1956 {
1957 rdpudp_fail(udp, "a datagram went unacknowledged too many times");
1958 return FALSE;
1959 }
1960 p->retransmits++;
1961 p->rto = (p->rto * 2 > RDPUDP_MAX_RTO_MS) ? RDPUDP_MAX_RTO_MS : p->rto * 2;
1962 p->due = now + p->rto;
1963 if (udp->version == RDPUDP_PROTOCOL_VERSION_3)
1964 {
1965 /* [MS-RDPEUDP2] 3.1.5.1.3: a lost packet is resent under a new data sequence
1966 * number, the channel sequence number stays. The AckOfAcks then moves past the
1967 * old one, so the peer stops waiting for it. */
1968 const UINT16 coded = WINPR_ASSERTING_INT_CAST(UINT16, udp->nextCoded);
1969 p->seq = coded;
1970 udp->nextCoded = seq16_add(coded, 1);
1971 }
1972 else
1973 {
1974 udp->cwrPending = TRUE;
1975 }
1976 WLog_Print(udp->log, WLOG_TRACE, "retransmitting 0x%08" PRIx32 " (#%" PRIu32 ")", p->seq,
1977 p->retransmits);
1978 if (!rdpudp_transmit(udp, p))
1979 return FALSE;
1980 }
1981
1982 if (now - udp->lastSent >= (v3 ? RDPUDP2_KEEPALIVE_MS : RDPUDP_KEEPALIVE_MS))
1983 {
1984 if (!rdpudp_send_ack(udp))
1985 return FALSE;
1986 udp->lastSent = now;
1987 }
1988
1989 return TRUE;
1990}
1991
1992/* ------------------------------------------------------------------------------------------ */
1993/* Public interface */
1994/* ------------------------------------------------------------------------------------------ */
1995
1996rdpUdp* rdpudp_new(wLog* log, const BYTE* cookieHash, rdpUdpReceiveFn receive, void* custom)
1997{
1998 WINPR_ASSERT(log);
1999 WINPR_ASSERT(receive);
2000
2001 rdpUdp* udp = calloc(1, sizeof(rdpUdp));
2002 if (!udp)
2003 return nullptr;
2004
2005 udp->log = log;
2006 udp->sockfd = INVALID_SOCKET;
2007 udp->state = RDPUDP_STATE_CLOSED;
2008 udp->receive = receive;
2009 udp->custom = custom;
2010 udp->mtu = RDPUDP_MTU;
2011 udp->offerV3 = (cookieHash != nullptr);
2012 udp->version = udp->offerV3 ? RDPUDP_PROTOCOL_VERSION_3 : RDPUDP_PROTOCOL_VERSION_2;
2013 if (cookieHash)
2014 memcpy(udp->cookieHash, cookieHash, sizeof(udp->cookieHash));
2015
2016 udp->sendQueue = Queue_New(FALSE, -1, -1);
2017 if (!udp->sendQueue)
2018 goto fail;
2019 wObject* obj = Queue_Object(udp->sendQueue);
2020 if (!obj)
2021 goto fail;
2022 obj->fnObjectFree = chunk_free;
2023
2024 if (winpr_RAND(&udp->initialSequence, sizeof(udp->initialSequence)) < 0)
2025 goto fail;
2026
2027 return udp;
2028fail:
2029 WINPR_PRAGMA_DIAG_PUSH
2030 WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
2031 rdpudp_free(udp);
2032 WINPR_PRAGMA_DIAG_POP
2033 return nullptr;
2034}
2035
2036void rdpudp_free(rdpUdp* udp)
2037{
2038 if (!udp)
2039 return;
2040
2041 if (udp->sockfd != INVALID_SOCKET)
2042 closesocket(udp->sockfd);
2043
2044 for (size_t x = 0; x < RDPUDP_MAX_IN_FLIGHT; x++)
2045 pending_clear(&udp->pending[x]);
2046 for (size_t x = 0; x < RDPUDP_RECEIVE_SLOTS; x++)
2047 slot_clear(&udp->slots[x]);
2048 if (udp->sendQueue)
2049 {
2050 /* Queue_Free() misses the chunks of a queue that is exactly full, so they are taken out
2051 * first */
2052 rdpudp_chunk* chunk = nullptr;
2053 while ((chunk = Queue_Dequeue(udp->sendQueue)))
2054 chunk_free(chunk);
2055 Queue_Free(udp->sendQueue);
2056 }
2057 free(udp);
2058}
2059
2060WINPR_ATTR_NODISCARD
2061static BOOL set_non_blocking(SOCKET sockfd)
2062{
2063 u_long arg = 1;
2064 return _ioctlsocket(sockfd, FIONBIO, &arg) == 0;
2065}
2066
2067BOOL rdpudp_connect(rdpUdp* udp, const struct sockaddr* addr, size_t addrlen)
2068{
2069 WINPR_ASSERT(udp);
2070 WINPR_ASSERT(addr);
2071
2072 if (udp->state != RDPUDP_STATE_CLOSED)
2073 return FALSE;
2074
2075 udp->sockfd = _socket(addr->sa_family, SOCK_DGRAM, IPPROTO_UDP);
2076 if (udp->sockfd == INVALID_SOCKET)
2077 {
2078 WLog_Print(udp->log, WLOG_ERROR, "failed to create the UDP socket");
2079 return FALSE;
2080 }
2081
2082 /* The system can grant less than asked, Linux caps it at net.core.rmem_max. A smaller buffer
2083 * only costs resends, so a failure is not fatal. */
2084 const UINT32 optval = RDPUDP_RECEIVE_BUFFER;
2085 if (_setsockopt(udp->sockfd, SOL_SOCKET, SO_RCVBUF, (const char*)&optval,
2086 WINPR_ASSERTING_INT_CAST(int, sizeof(optval))) != 0)
2087 WLog_Print(udp->log, WLOG_WARN, "setsockopt() SOL_SOCKET, SO_RCVBUF failed");
2088
2089 if (_connect(udp->sockfd, addr, WINPR_ASSERTING_INT_CAST(int, addrlen)) != 0)
2090 {
2091 WLog_Print(udp->log, WLOG_ERROR, "failed to connect the UDP socket");
2092 return FALSE;
2093 }
2094
2095 if (!set_non_blocking(udp->sockfd))
2096 return FALSE;
2097
2098 udp->state = RDPUDP_STATE_SYN_SENT;
2099 udp->lastReceived = now_ms();
2100 return send_syn(udp);
2101}
2102
2103SOCKET rdpudp_get_socket(const rdpUdp* udp)
2104{
2105 WINPR_ASSERT(udp);
2106 return udp->sockfd;
2107}
2108
2109RDPUDP_STATE rdpudp_get_state(const rdpUdp* udp)
2110{
2111 WINPR_ASSERT(udp);
2112 return udp->state;
2113}
2114
2115UINT16 rdpudp_get_version(const rdpUdp* udp)
2116{
2117 WINPR_ASSERT(udp);
2118 return udp->version;
2119}
2120
2121size_t rdpudp_get_max_payload(const rdpUdp* udp)
2122{
2123 WINPR_ASSERT(udp);
2124 /* the MTU is clamped to [RDPUDP_MIN_MTU, RDPUDP_MTU] when the connection is set up */
2125 WINPR_ASSERT(udp->mtu >= RDPUDP_MIN_MTU);
2126 /* v3: the DATA datagram fields and room for some arrival gaps of the ACK it carries.
2127 * v1/v2: header, room for the ACK vector and AckOfAcks, source payload header. */
2128 const size_t overhead = (udp->version == RDPUDP_PROTOCOL_VERSION_3)
2129 ? (RDPUDP2_DATA_OVERHEAD + RDPUDP2_DATA_ACK_ROOM)
2130 : (8u + RDPUDP_ACK_ROOM + 8u);
2131 if (udp->mtu <= overhead)
2132 return 0;
2133 return udp->mtu - overhead;
2134}
2135
2136UINT32 rdpudp_get_timeout(const rdpUdp* udp)
2137{
2138 WINPR_ASSERT(udp);
2139 const UINT64 now = now_ms();
2140 UINT64 timeout = 50;
2141
2142 if (udp->state == RDPUDP_STATE_SYN_SENT)
2143 {
2144 const UINT64 due = udp->synSent + RDPUDP_SYN_TIMEOUT_MS;
2145 if (due <= now)
2146 return 0;
2147 if (due - now < timeout)
2148 timeout = due - now;
2149 return WINPR_ASSERTING_INT_CAST(UINT32, timeout);
2150 }
2151
2152 for (size_t x = 0; x < RDPUDP_MAX_IN_FLIGHT; x++)
2153 {
2154 const rdpudp_pending* p = &udp->pending[x];
2155 if (!p->used)
2156 continue;
2157 if (p->due <= now)
2158 return 0;
2159 if (p->due - now < timeout)
2160 timeout = p->due - now;
2161 }
2162
2163 /* an acknowledgement that waits, see ack_when_due */
2164 if (udp->ackPending && (udp->v3AckDue != 0))
2165 {
2166 if (udp->v3AckDue <= now)
2167 return 0;
2168 if (udp->v3AckDue - now < timeout)
2169 timeout = udp->v3AckDue - now;
2170 }
2171 return WINPR_ASSERTING_INT_CAST(UINT32, timeout);
2172}
2173
2174BOOL rdpudp_check(rdpUdp* udp)
2175{
2176 WINPR_ASSERT(udp);
2177
2178 if ((udp->state == RDPUDP_STATE_FAILED) || (udp->state == RDPUDP_STATE_CLOSED))
2179 return FALSE;
2180
2181 BYTE* buffer = udp->recvBuffer;
2182 while (TRUE)
2183 {
2184 const int rc = _recv(udp->sockfd, (char*)buffer,
2185 WINPR_ASSERTING_INT_CAST(int, sizeof(udp->recvBuffer)), 0);
2186 if (rc < 0)
2187 {
2188 const int error = WSAGetLastError();
2189 if (!rdpudp_socket_error_is_transient(error))
2190 {
2191 WLog_Print(udp->log, WLOG_ERROR, "recv failed with %d", error);
2192 rdpudp_fail(udp, "receiving from the socket failed");
2193 return FALSE;
2194 }
2195 /* Nothing left to read, or an ICMP error for an earlier datagram. Anything still
2196 * queued keeps the socket readable and is read on the next round. */
2197 if (error != WSAEWOULDBLOCK)
2198 WLog_Print(udp->log, WLOG_DEBUG, "recv failed with %d", error);
2199 break;
2200 }
2201
2202 if (!process_datagram(udp, buffer, WINPR_ASSERTING_INT_CAST(size_t, rc)))
2203 {
2204 rdpudp_fail(udp, "failed to process a datagram");
2205 return FALSE;
2206 }
2207 if (udp->state == RDPUDP_STATE_FAILED)
2208 return FALSE;
2209 if (!v3_ack_if_due(udp))
2210 return FALSE;
2211 }
2212
2213 if (!ack_when_due(udp))
2214 return FALSE;
2215
2216 if (!flush_send_queue(udp))
2217 return FALSE;
2218
2219 return run_timers(udp);
2220}
This struct contains function pointer to initialize/free objects.
Definition collections.h:52
OBJECT_FREE_FN fnObjectFree
Definition collections.h:59