18#include <freerdp/config.h>
22#include <winpr/assert.h>
23#include <winpr/cast.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>
32#include <sys/socket.h>
33#include <netinet/in.h>
39typedef enum WINPR_C23_ENUM_TYPE(uint16_t)
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
53typedef enum WINPR_C23_ENUM_TYPE(uint16_t)
55 RDPUDP_VERSION_INFO_VALID = 0x0001
59typedef enum WINPR_C23_ENUM_TYPE(uint8_t)
61 DATAGRAM_RECEIVED = 0,
62 DATAGRAM_NOT_YET_RECEIVED = 3
63} RDPUDP_VECTOR_ELEMENT_STATE;
66typedef enum WINPR_C23_ENUM_TYPE(uint16_t)
70 RDPUDP2_ACKVEC = 0x008,
72 RDPUDP2_OVERHEADSIZE = 0x040,
73 RDPUDP2_DELAYACKINFO = 0x100,
78typedef enum WINPR_C23_ENUM_TYPE(uint8_t)
80 RDPUDP2_PACKET_STANDARD = 0,
81 RDPUDP2_PACKET_DUMMY = 8
85#define RDPUDP_MAX_ACK_VECTOR 2048
87#define RDPUDP_MTU 1232
88#define RDPUDP_MIN_MTU 1132
91#define RDPUDP_RECEIVE_WINDOW 64
97#define RDPUDP_RECEIVE_SLOTS 32768
98#define RDPUDP_RECEIVE_REACH 32767
101#define RDPUDP_MAX_IN_FLIGHT 64
105#define RDPUDP2_LOG_WINDOW_SIZE 15
108#define RDPUDP2_INITIAL_SEQUENCE 100
112#define RDPUDP2_DEFAULT_DELAYED_ACKS 8
113#define RDPUDP2_MAX_DELAYED_ACKS 15
117#define RDPUDP2_DATA_OVERHEAD 19
120#define RDPUDP2_DATA_ACK_ROOM 5
124#define RDPUDP_RECEIVE_BUFFER (2 * 1024 * 1024)
127#define RDPUDP2_MAX_ACKVEC 127
130#define RDPUDP_ACK_ROOM 64
136#define RDPUDP_SYN_TIMEOUT_MS 1000
137#define RDPUDP_SYN_ATTEMPTS 10
143#define RDPUDP_MAX_RTO_MS 120000
147#define RDPUDP_MAX_RETRANSMITS 5
148#define RDPUDP_KEEPALIVE_MS 5000
149#define RDPUDP_PEER_TIMEOUT_MS 65000
154#define RDPUDP2_MAX_RETRANSMITS 10
155#define RDPUDP2_KEEPALIVE_MS 4000
156#define RDPUDP2_PEER_TIMEOUT_MS 16000
160#define RDPUDP2_RESYNC_MS (2ull * RDPUDP2_KEEPALIVE_MS)
167#define RDPUDP_STALL_TIMEOUT_MS RDPUDP2_PEER_TIMEOUT_MS
205 rdpUdpReceiveFn receive;
216 rdpudp_pending pending[RDPUDP_MAX_IN_FLIGHT];
220 UINT32 initialSequence;
226 UINT16 nextChannelSeq;
231 rdpudp_slot slots[RDPUDP_RECEIVE_SLOTS];
234 UINT64 bufferingSince;
237 UINT32 peerInitialSequence;
240 UINT32 ackVectorStart;
247 BOOL v3Received[RDPUDP_RECEIVE_SLOTS];
248 UINT64 v3Arrival[RDPUDP_RECEIVE_SLOTS];
249 UINT64 v3InOrderArrival;
250 BOOL v3InOrderReceived;
251 UINT64 v3LatestArrival;
252 size_t v3MaxDelayedAcks;
253 UINT32 v3DelayedAckTimeout;
255 size_t v3UnackedPackets;
258 BOOL v3WindowPending;
262 size_t v3BehindCount;
263 UINT64 v3BehindArrival;
264 UINT16 v3NextChannel;
267 BYTE recvBuffer[0x10000];
274static inline UINT16 seq16_add(UINT16 a,
size_t n)
276 return WINPR_ASSERTING_INT_CAST(UINT16, (a + n) & 0xFFFFu);
281static inline UINT16 seq16_diff(UINT16 a, UINT16 b)
283 return WINPR_ASSERTING_INT_CAST(UINT16, ((UINT32)a - (UINT32)b) & 0xFFFFu);
287static inline UINT32 seq32_add(UINT32 a, UINT32 n)
289 return WINPR_ASSERTING_INT_CAST(UINT32, ((UINT64)a + n) & 0xFFFFFFFFull);
294static inline UINT32 seq32_diff(UINT32 a, UINT32 b)
296 return WINPR_ASSERTING_INT_CAST(UINT32, ((UINT64)a - (UINT64)b) & 0xFFFFFFFFull);
300static BOOL seq16_after(UINT16 a, UINT16 b)
302 return (a != b) && (seq16_diff(a, b) < 0x8000);
306static BOOL seq32_after(UINT32 a, UINT32 b)
308 return (a != b) && (seq32_diff(a, b) < 0x80000000u);
314static UINT16 channel_seq_next(UINT16 seq)
316 return (seq == UINT16_MAX) ? 1 : seq16_add(seq, 1);
320static void stream_write_uint24(
wStream* s, UINT32 value)
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);
330static UINT64 now_ms(
void)
332 return GetTickCount64();
336static UINT32 rto_floor(
const rdpUdp* udp)
339 return (udp->version == RDPUDP_PROTOCOL_VERSION_1) ? 500 : 300;
343static UINT32 rto_initial(
const rdpUdp* 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);
352static void chunk_free(
void* obj)
354 rdpudp_chunk* chunk = obj;
361static void slot_clear(rdpudp_slot* slot)
365 slot->data =
nullptr;
367 slot->present = FALSE;
370static void pending_clear(rdpudp_pending* p)
374 memset(p, 0,
sizeof(*p));
377static void rdpudp_fail(rdpUdp* udp,
const char* 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;
394static BOOL rdpudp_socket_error_is_transient(
int error)
405 case WSAECONNREFUSED:
410 case WSAEHOSTUNREACH:
418static BOOL rdpudp_send_raw(rdpUdp* udp,
const BYTE* data,
size_t length)
422 const int rc = _send(udp->sockfd, (
const char*)data, WINPR_ASSERTING_INT_CAST(
int, length), 0);
425 const int error = WSAGetLastError();
426 if (!rdpudp_socket_error_is_transient(error))
428 WLog_Print(udp->log, WLOG_ERROR,
"send failed with %d", error);
429 rdpudp_fail(udp,
"sending on the socket failed");
432 WLog_Print(udp->log, WLOG_DEBUG,
"send failed with %d, the datagram counts as lost", error);
435 udp->lastSent = now_ms();
444static UINT32 v3_timestamp(UINT64 ns)
447 return WINPR_ASSERTING_INT_CAST(UINT32, (ns / 4000ULL) & 0x00FFFFFFULL);
452static BYTE v3_ack_gap(UINT64 arrival, UINT64 now)
454 if ((arrival == 0) || (now < arrival))
456 const UINT64 gap = (now - arrival) / 1000000ULL;
457 return (gap > 254) ? 254 : WINPR_ASSERTING_INT_CAST(BYTE, gap);
461static BOOL v3_has_gap(
const rdpUdp* udp)
464 return udp->v3BaseKnown && seq16_after(udp->v3Highest, seq16_diff(udp->v3Expected, 1));
474static void v3_write_ack(rdpUdp* udp,
wStream* s,
size_t room)
478 const UINT64 now = winpr_GetTickCount64NS();
481 const UINT64 arrival = udp->v3InOrderReceived ? udp->v3InOrderArrival : now;
482 const UINT16 seq = seq16_diff(udp->v3Expected, 1);
484 UINT64 gaps[RDPUDP2_MAX_DELAYED_ACKS] = WINPR_C_ARRAY_INIT;
486 if (udp->v3InOrderReceived)
488 size_t limit = seq16_diff(seq, udp->v3AckedSeq);
489 limit = (limit > 0) ? limit - 1 : 0;
490 if (limit > udp->v3MaxDelayedAcks)
491 limit = udp->v3MaxDelayedAcks;
494 if (limit > RDPUDP2_MAX_DELAYED_ACKS)
495 limit = RDPUDP2_MAX_DELAYED_ACKS;
497 UINT16 current = seq;
498 UINT64 currentArrival = arrival;
499 while (count < limit)
501 const UINT16 previous = seq16_diff(current, 1);
502 const UINT64 previousArrival = udp->v3Arrival[previous % RDPUDP_RECEIVE_SLOTS];
503 if (previousArrival == 0)
506 gaps[count++] = (currentArrival > previousArrival)
507 ? (currentArrival - previousArrival) / 1000ULL
510 currentArrival = previousArrival;
516 for (
size_t x = 0; x < count; x++)
518 while ((scale < 15) && ((gaps[x] >> scale) > 255))
522 Stream_Write_UINT16(s, seq);
523 stream_write_uint24(s, v3_timestamp(arrival));
525 const BYTE gap = v3_ack_gap(arrival, now);
526 Stream_Write_UINT8(s, gap);
527 const BYTE delayed = WINPR_ASSERTING_INT_CAST(BYTE, count | ((
size_t)scale << 4));
528 Stream_Write_UINT8(s, delayed);
529 for (
size_t x = 0; x < count; x++)
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);
535 udp->v3AckedSeq = seq;
540static wStream* v3_packet_init(
wStream* buffer, BYTE* data,
size_t size, UINT16 flags)
542 WINPR_ASSERT(buffer);
544 wStream* s = Stream_StaticInit(buffer, data, size);
548 const UINT16 header = WINPR_ASSERTING_INT_CAST(UINT16, flags | (RDPUDP2_LOG_WINDOW_SIZE << 12));
549 Stream_Write_UINT16(s, header);
556static BOOL v3_send_packet(rdpUdp* udp,
wStream* s, BYTE packetType)
560 if (Stream_GetPosition(s) < 1)
562 const size_t layout = Stream_GetPosition(s) - 1;
563 BYTE shortLength = 7;
566 shortLength = WINPR_ASSERTING_INT_CAST(BYTE, layout);
567 Stream_Zero(s, 7 - layout);
569 const size_t length = Stream_GetPosition(s);
571 if (!Stream_SetPosition(s, 0))
574 WINPR_ASSERTING_INT_CAST(BYTE, (shortLength << 5) | ((packetType & 0x0F) << 1));
575 Stream_Write_UINT8(s, prefix);
578 BYTE* wire = Stream_Buffer(s);
579 const BYTE eighth = wire[7];
582 return rdpudp_send_raw(udp, wire, length);
588static BOOL v3_send_ack_vector(rdpUdp* udp, UINT16 base,
const BYTE* vec,
size_t count,
591 BYTE buffer[64 + RDPUDP2_MAX_ACKVEC] = WINPR_C_ARRAY_INIT;
592 wStream sbuffer = WINPR_C_ARRAY_INIT;
596 WINPR_ASSERT((count > 0) && (count <= RDPUDP2_MAX_ACKVEC));
598 v3_packet_init(&sbuffer, buffer,
sizeof(buffer), RDPUDP2_OVERHEADSIZE | RDPUDP2_ACKVEC);
601 const UINT64 now = winpr_GetTickCount64NS();
602 const BYTE control = WINPR_ASSERTING_INT_CAST(BYTE, 0x80 | count);
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);
607 Stream_Write_UINT16(s, base);
608 Stream_Write_UINT8(s, control);
609 stream_write_uint24(s, timestamp);
610 Stream_Write_UINT8(s, ackGap);
611 Stream_Write(s, vec, count);
612 return v3_send_packet(udp, s, RDPUDP2_PACKET_STANDARD);
616static BOOL v3_send_ack(rdpUdp* udp)
618 BYTE buffer[64] = WINPR_C_ARRAY_INIT;
619 wStream sbuffer = WINPR_C_ARRAY_INIT;
622 if (!udp->v3BaseKnown)
630 if (udp->v3BehindCount > 0)
632 BYTE vec[RDPUDP2_MAX_ACKVEC] = WINPR_C_ARRAY_INIT;
634 for (
size_t left = udp->v3BehindCount; left > 0;)
636 const size_t run = (left > 63) ? 63 : left;
637 vec[count++] = WINPR_ASSERTING_INT_CAST(BYTE, 0x80 | 0x40 | run);
640 udp->v3BehindCount = 0;
641 if (!v3_send_ack_vector(udp, udp->v3BehindBase, vec, count, udp->v3BehindArrival))
643 if (!udp->v3WindowPending)
645 udp->ackPending = FALSE;
646 udp->v3UnackedPackets = 0;
656 udp->ackPending = FALSE;
657 udp->v3UnackedPackets = 0;
662 udp->ackPending = FALSE;
663 udp->v3WindowPending = FALSE;
664 udp->v3UnackedPackets = 0;
669 const BOOL gap = v3_has_gap(udp);
670 udp->v3AckedGap = gap;
674 v3_packet_init(&sbuffer, buffer,
sizeof(buffer), RDPUDP2_OVERHEADSIZE | RDPUDP2_ACK);
677 v3_write_ack(udp, s, RDPUDP2_MAX_DELAYED_ACKS);
678 Stream_Write_UINT8(s, 10);
679 return v3_send_packet(udp, s, RDPUDP2_PACKET_STANDARD);
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;
691 BYTE vec[RDPUDP2_MAX_ACKVEC] = WINPR_C_ARRAY_INIT;
694 while ((pos < span) && (count < RDPUDP2_MAX_ACKVEC))
696 const BOOL state = udp->v3Received[seq16_add(base, pos) % RDPUDP_RECEIVE_SLOTS];
698 while ((pos + run < span) && (run < 63) &&
699 (udp->v3Received[seq16_add(base, pos + run) % RDPUDP_RECEIVE_SLOTS] == state))
703 vec[count++] = WINPR_ASSERTING_INT_CAST(BYTE, 0x80 | (state ? 0x40 : 0x00) | run);
708 for (
size_t bit = 0; (bit < 7) && (pos + bit < span); bit++)
710 if (udp->v3Received[seq16_add(base, pos + bit) % RDPUDP_RECEIVE_SLOTS])
711 bits |= WINPR_ASSERTING_INT_CAST(BYTE, 1 << bit);
718 const UINT64 highest = udp->v3Arrival[udp->v3Highest % RDPUDP_RECEIVE_SLOTS];
719 return v3_send_ack_vector(udp, base, vec, count, highest);
725static UINT32 sender_base(
const rdpUdp* udp)
728 UINT32 base = (udp->version == RDPUDP_PROTOCOL_VERSION_3) ? udp->nextCoded : udp->nextSource;
730 for (
size_t x = 0; x < RDPUDP_MAX_IN_FLIGHT; x++)
732 const rdpudp_pending* p = &udp->pending[x];
735 if (udp->version == RDPUDP_PROTOCOL_VERSION_3)
737 if (!found || seq16_after(WINPR_ASSERTING_INT_CAST(UINT16, base),
738 WINPR_ASSERTING_INT_CAST(UINT16, p->seq)))
741 else if (!found || seq32_after(base, p->seq))
751static BOOL v3_send_data(rdpUdp* udp,
const rdpudp_pending* p)
753 BYTE buffer[RDPUDP_MTU + 32] = WINPR_C_ARRAY_INIT;
754 wStream sbuffer = WINPR_C_ARRAY_INIT;
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));
766 const BOOL withAoA = !udp->aoaAnnounced || (udp->announcedAoA != base) || (p->retransmits > 0);
769 UINT16 flags = RDPUDP2_DATA | RDPUDP2_DELAYACKINFO;
770 flags |= withAck ? RDPUDP2_ACK : RDPUDP2_NOACK;
772 flags |= RDPUDP2_AOA;
774 wStream* s = v3_packet_init(&sbuffer, buffer,
sizeof(buffer), flags);
780 const size_t used = RDPUDP2_DATA_OVERHEAD + p->length;
781 v3_write_ack(udp, s, (udp->mtu > used) ? udp->mtu - used : 0);
784 udp->ackPending = FALSE;
785 udp->v3WindowPending = FALSE;
786 udp->v3UnackedPackets = 0;
788 udp->v3AckedGap = FALSE;
791 Stream_Write_UINT8(s, 1);
792 Stream_Write_UINT16(s, 20);
797 Stream_Write_UINT16(s, base);
798 udp->announcedAoA = base;
799 udp->aoaAnnounced = TRUE;
802 const UINT16 dataSeq = WINPR_ASSERTING_INT_CAST(UINT16, p->seq);
803 Stream_Write_UINT16(s, dataSeq);
804 Stream_Write_UINT16(s, p->channelSeq);
805 if (!Stream_CheckAndLogRequiredCapacityWLog(udp->log, s, p->length))
807 Stream_Write(s, p->payload, p->length);
809 return v3_send_packet(udp, s, RDPUDP2_PACKET_STANDARD);
819static void v1_write_ack_vector(
const rdpUdp* udp,
wStream* s,
size_t room)
823 if (!udp->receivedData)
825 Stream_Write_UINT16_BE(s, 0);
830 const UINT32 highest = udp->recvHighest;
831 UINT32 low = udp->ackVectorStart;
832 if (seq32_after(low, highest))
834 if (seq32_diff(highest, low) >= RDPUDP_RECEIVE_REACH)
835 low = seq32_diff(highest, RDPUDP_RECEIVE_REACH - 1);
837 BYTE elements[RDPUDP_MAX_ACK_VECTOR] = WINPR_C_ARRAY_INIT;
845 BYTE current = DATAGRAM_RECEIVED;
846 if (!seq32_after(udp->recvNext, seq))
848 const rdpudp_slot* slot = &udp->slots[seq % RDPUDP_RECEIVE_SLOTS];
849 if (!slot->present || (slot->seq != seq))
850 current = DATAGRAM_NOT_YET_RECEIVED;
853 if ((current != state) || (run == 0x40))
857 if (count >= ARRAYSIZE(elements))
859 elements[count++] = WINPR_ASSERTING_INT_CAST(BYTE, (state << 6) | (run - 1));
870 if ((run > 0) && (count < ARRAYSIZE(elements)))
871 elements[count++] = WINPR_ASSERTING_INT_CAST(BYTE, (state << 6) | (run - 1));
875 while ((2 + (count - skip) + 3) > room && (skip < count))
879 const UINT16 vectorSize = WINPR_ASSERTING_INT_CAST(UINT16, count);
880 Stream_Write_UINT16_BE(s, vectorSize);
881 Stream_Write(s, &elements[skip], count);
882 Stream_Zero(s, (4 - ((2 + count) % 4)) % 4);
886static UINT32 v1_cumulative_ack(
const rdpUdp* udp)
889 return seq32_diff(sender_base(udp), 1);
893static BOOL v1_send_packet(rdpUdp* udp,
const rdpudp_pending* p)
895 BYTE buffer[RDPUDP_MTU + 2048] = WINPR_C_ARRAY_INIT;
896 wStream sbuffer = WINPR_C_ARRAY_INIT;
899 WINPR_ASSERT(udp->mtu >= RDPUDP_MIN_MTU);
901 const UINT32 cumulative = v1_cumulative_ack(udp);
902 const BOOL withAoA = !udp->aoaAnnounced || (udp->announcedAoA != cumulative);
904 UINT16 flags = RDPUDP_FLAG_ACK;
906 flags |= RDPUDP_FLAG_ACK_OF_ACKS;
909 flags |= RDPUDP_FLAG_DATA;
912 flags |= RDPUDP_FLAG_CWR;
913 udp->cwrPending = FALSE;
917 wStream* s = Stream_StaticInit(&sbuffer, buffer,
sizeof(buffer));
922 Stream_Write_UINT32_BE(s, udp->receivedData ? udp->recvHighest
923 : udp->peerInitialSequence);
924 Stream_Write_UINT16_BE(s, RDPUDP_RECEIVE_WINDOW);
925 Stream_Write_UINT16_BE(s, flags);
928 v1_write_ack_vector(udp, s, p ? RDPUDP_ACK_ROOM - 4 : udp->mtu - 12u);
929 udp->ackPending = FALSE;
933 Stream_Write_UINT32_BE(s, cumulative);
934 udp->announcedAoA = cumulative;
935 udp->aoaAnnounced = TRUE;
941 const UINT32 snCoded = udp->nextCoded++;
942 Stream_Write_UINT32_BE(s, snCoded);
943 Stream_Write_UINT32_BE(s, p->seq);
944 if (!Stream_CheckAndLogRequiredCapacityWLog(udp->log, s, p->length))
946 Stream_Write(s, p->payload, p->length);
949 return rdpudp_send_raw(udp, Stream_Buffer(s), Stream_GetPosition(s));
953static BOOL rdpudp_send_ack(rdpUdp* udp)
956 if (udp->state != RDPUDP_STATE_ESTABLISHED)
958 if (udp->version == RDPUDP_PROTOCOL_VERSION_3)
959 return v3_send_ack(udp);
960 return v1_send_packet(udp,
nullptr);
968static BOOL v3_ack_if_due(rdpUdp* udp)
971 if ((udp->version != RDPUDP_PROTOCOL_VERSION_3) || (udp->state != RDPUDP_STATE_ESTABLISHED) ||
974 if ((v3_has_gap(udp) == udp->v3AckedGap) && (udp->v3UnackedPackets <= udp->v3MaxDelayedAcks))
976 return v3_send_ack(udp);
981static UINT32 v3_ack_delay(
const rdpUdp* udp)
984 return (udp->v3DelayedAckTimeout != UINT32_MAX) ? udp->v3DelayedAckTimeout : udp->srtt / 2;
992static BOOL ack_when_due(rdpUdp* udp)
995 if (!udp->ackPending)
997 if (udp->version == RDPUDP_PROTOCOL_VERSION_3)
999 if ((udp->state != RDPUDP_STATE_ESTABLISHED) || !udp->v3BaseKnown)
1001 const UINT64 now = now_ms();
1002 if (udp->v3AckDue == 0)
1003 udp->v3AckDue = now + v3_ack_delay(udp);
1004 if (now < udp->v3AckDue)
1007 return rdpudp_send_ack(udp);
1011static BOOL rdpudp_transmit(rdpUdp* udp,
const rdpudp_pending* p)
1015 if (udp->version == RDPUDP_PROTOCOL_VERSION_3)
1016 return v3_send_data(udp, p);
1017 return v1_send_packet(udp, p);
1025static size_t window_limit(
const rdpUdp* 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;
1037static BOOL send_chunk_now(rdpUdp* udp, BYTE* data,
size_t length)
1041 rdpudp_pending* p =
nullptr;
1042 for (
size_t x = 0; x < RDPUDP_MAX_IN_FLIGHT; x++)
1044 if (!udp->pending[x].used)
1046 p = &udp->pending[x];
1060 if (udp->version == RDPUDP_PROTOCOL_VERSION_3)
1062 const UINT16 coded = WINPR_ASSERTING_INT_CAST(UINT16, udp->nextCoded);
1064 udp->nextCoded = seq16_add(coded, 1);
1065 p->channelSeq = udp->nextChannelSeq;
1066 udp->nextChannelSeq = channel_seq_next(udp->nextChannelSeq);
1070 p->seq = udp->nextSource++;
1073 const UINT64 now = now_ms();
1075 p->rto = rto_initial(udp);
1076 p->due = now + p->rto;
1080 return rdpudp_transmit(udp, p);
1084static BOOL flush_send_queue(rdpUdp* udp)
1087 while ((udp->state == RDPUDP_STATE_ESTABLISHED) && (udp->inFlight < window_limit(udp)) &&
1088 (Queue_Count(udp->sendQueue) > 0))
1090 rdpudp_chunk* chunk = Queue_Dequeue(udp->sendQueue);
1093 BYTE* data = chunk->data;
1094 const size_t length = chunk->length;
1096 if (!send_chunk_now(udp, data, length))
1102BOOL rdpudp_send(rdpUdp* udp,
const BYTE* data,
size_t length)
1107 if ((length == 0) || (length > rdpudp_get_max_payload(udp)))
1109 if ((udp->state != RDPUDP_STATE_ESTABLISHED) && (udp->state != RDPUDP_STATE_SYN_SENT))
1112 rdpudp_chunk* chunk = calloc(1,
sizeof(rdpudp_chunk));
1115 chunk->data = malloc(length);
1121 memcpy(chunk->data, data, length);
1122 chunk->length = length;
1124 if (!Queue_Enqueue(udp->sendQueue, chunk))
1130 return flush_send_queue(udp);
1133static void sample_rtt(rdpUdp* udp,
const rdpudp_pending* p)
1138 if (p->retransmits > 0)
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)
1145 : WINPR_ASSERTING_INT_CAST(UINT32, ((UINT64)udp->srtt * 7 + sample) / 8);
1148static void acknowledge(rdpUdp* udp, rdpudp_pending* p)
1154 if (udp->inFlight > 0)
1158static void acknowledge_seq(rdpUdp* udp, UINT32 seq)
1161 for (
size_t x = 0; x < RDPUDP_MAX_IN_FLIGHT; x++)
1163 rdpudp_pending* p = &udp->pending[x];
1164 if (p->used && (p->seq == seq))
1165 acknowledge(udp, p);
1174static BOOL deliver(rdpUdp* udp,
const BYTE* data,
size_t length)
1177 udp->lastDelivery = now_ms();
1181 WINPR_ASSERT(udp->receive);
1182 if (!udp->receive(udp->custom, data, length))
1184 rdpudp_fail(udp,
"receiver rejected data");
1191static BOOL store_slot(rdpUdp* udp, UINT32 seq,
const BYTE* data,
size_t length)
1194 WINPR_ASSERT(data || (length == 0));
1195 rdpudp_slot* slot = &udp->slots[seq % RDPUDP_RECEIVE_SLOTS];
1198 if (slot->seq == seq)
1204 slot->data =
nullptr;
1207 slot->data = malloc(length);
1210 memcpy(slot->data, data, length);
1212 slot->length = length;
1214 slot->present = TRUE;
1215 if (udp->buffered++ == 0)
1216 udp->bufferingSince = now_ms();
1221static BOOL v1_receive_source(rdpUdp* udp, UINT32 seq,
const BYTE* data,
size_t length)
1224 WINPR_ASSERT(data || (length == 0));
1225 if (!udp->receivedData)
1229 if (seq == udp->peerInitialSequence)
1231 udp->recvNext = seq;
1232 udp->ackVectorStart = seq;
1234 udp->recvHighest = seq32_diff(udp->recvNext, 1);
1237 udp->ackPending = TRUE;
1239 if (seq32_after(udp->recvNext, seq))
1242 const UINT32 ahead = seq32_diff(seq, udp->recvNext);
1243 if (ahead >= RDPUDP_RECEIVE_REACH)
1246 udp->receivedData = TRUE;
1247 if (seq32_after(seq, udp->recvHighest))
1248 udp->recvHighest = seq;
1250 if (!store_slot(udp, seq, data, length))
1255 rdpudp_slot* slot = &udp->slots[udp->recvNext % RDPUDP_RECEIVE_SLOTS];
1256 if (!slot->present || (slot->seq != udp->recvNext))
1258 BYTE* chunk = slot->data;
1259 const size_t chunkLength = slot->length;
1260 slot->data =
nullptr;
1261 slot->present = FALSE;
1264 const BOOL rc = deliver(udp, chunk, chunkLength);
1273static void v1_process_ack_vector(rdpUdp* udp, UINT32 snSourceAck,
wStream* s,
size_t count)
1278 WINPR_ASSERT(count <= RDPUDP_MAX_ACK_VECTOR);
1279 const size_t start = Stream_GetPosition(s);
1281 for (
size_t x = 0; x < count; x++)
1282 total += (Stream_Get_UINT8(s) & 0x3Fu) + 1u;
1283 if ((total == 0) || !Stream_SetPosition(s, start))
1286 UINT32 seq = seq32_add(seq32_diff(snSourceAck, total), 1);
1287 for (
size_t x = 0; x < count; x++)
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++)
1294 if (state == DATAGRAM_RECEIVED)
1295 acknowledge_seq(udp, seq);
1302static BOOL v1_process_datagram(rdpUdp* udp,
const BYTE* data,
size_t length)
1304 wStream sbuffer = WINPR_C_ARRAY_INIT;
1307 wStream* s = Stream_StaticConstInit(&sbuffer, data, length);
1310 if (!Stream_CheckAndLogRequiredLengthWLog(udp->log, s, 8))
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);
1316 if (flags & RDPUDP_FLAG_SYN)
1319 udp->ackPending = TRUE;
1323 udp->peerWindow = window;
1324 if (flags & RDPUDP_FLAG_CN)
1325 udp->cwrPending = TRUE;
1327 if (flags & RDPUDP_FLAG_ACK)
1330 if (!Stream_CheckAndLogRequiredLengthWLog(udp->log, s, 2))
1332 const size_t size = Stream_Get_UINT16_BE(s);
1333 if (size > RDPUDP_MAX_ACK_VECTOR)
1335 const size_t padding = (4 - ((2 + size) % 4)) % 4;
1336 if (!Stream_CheckAndLogRequiredLengthWLog(udp->log, s, size + padding))
1338 v1_process_ack_vector(udp, snSourceAck, s, size);
1339 Stream_Seek(s, padding);
1342 if (flags & RDPUDP_FLAG_ACK_OF_ACKS)
1345 if (!Stream_CheckAndLogRequiredLengthWLog(udp->log, s, 4))
1347 const UINT32 reset = Stream_Get_UINT32_BE(s);
1349 const UINT32 start = seq32_add(reset, 1);
1350 if (seq32_after(start, udp->ackVectorStart) && !seq32_after(start, udp->recvNext))
1351 udp->ackVectorStart = start;
1354 if ((flags & RDPUDP_FLAG_CORRELATION_ID) && !Stream_SafeSeek(s, 32))
1357 if (!(flags & RDPUDP_FLAG_DATA))
1360 if (flags & RDPUDP_FLAG_FEC)
1364 if (!Stream_CheckAndLogRequiredLengthWLog(udp->log, s, 8))
1366 Stream_Seek_UINT32(s);
1367 const UINT32 snSourceStart = Stream_Get_UINT32_BE(s);
1368 return v1_receive_source(udp, snSourceStart, Stream_ConstPointer(s),
1369 Stream_GetRemainingLength(s));
1372static void v3_advance_window(rdpUdp* udp)
1375 while (udp->v3Received[udp->v3Expected % RDPUDP_RECEIVE_SLOTS])
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;
1390static void v3_resync_base(rdpUdp* udp, UINT16 base)
1393 udp->v3Resync = FALSE;
1394 if (base == udp->v3Expected)
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;
1410static void v3_note_silence(rdpUdp* udp, UINT64 now)
1413 if ((udp->version == RDPUDP_PROTOCOL_VERSION_3) && udp->v3BaseKnown &&
1414 (now - udp->lastReceived >= RDPUDP2_RESYNC_MS))
1415 udp->v3Resync = TRUE;
1418static void v3_advance_base(rdpUdp* udp, UINT16 base)
1425 if (!udp->v3BaseKnown)
1429 v3_resync_base(udp, base);
1432 if (!seq16_after(base, udp->v3Expected))
1438 while (udp->v3Expected != base)
1440 const size_t slot = udp->v3Expected % RDPUDP_RECEIVE_SLOTS;
1441 udp->v3Received[slot] = FALSE;
1442 udp->v3Arrival[slot] = 0;
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;
1454static void v3_process_ack_vector(rdpUdp* udp, UINT16 base,
wStream* s,
size_t count)
1459 for (
size_t x = 0; x < count; x++)
1461 const BYTE entry = Stream_Get_UINT8(s);
1465 const BOOL received = (entry & 0x40) != 0;
1466 const BYTE run = entry & 0x3F;
1467 for (BYTE y = 0; y < run; y++)
1470 acknowledge_seq(udp, seq);
1477 for (BYTE bit = 0; bit < 7; bit++)
1479 if (entry & (1 << bit))
1480 acknowledge_seq(udp, seq);
1487 for (
size_t x = 0; x < RDPUDP_MAX_IN_FLIGHT; x++)
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);
1495static void v3_process_ack(rdpUdp* udp, UINT16 ack)
1498 for (
size_t x = 0; x < RDPUDP_MAX_IN_FLIGHT; x++)
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);
1508static BOOL v3_deliver_ready(rdpUdp* udp)
1513 rdpudp_slot* slot = &udp->slots[udp->v3NextChannel % RDPUDP_RECEIVE_SLOTS];
1514 if (!slot->present || (slot->seq != udp->v3NextChannel))
1516 BYTE* chunk = slot->data;
1517 const size_t chunkLength = slot->length;
1518 slot->data =
nullptr;
1519 slot->present = FALSE;
1521 udp->v3NextChannel = channel_seq_next(udp->v3NextChannel);
1522 const BOOL rc = deliver(udp, chunk, chunkLength);
1531static BOOL v3_receive_channel_data(rdpUdp* udp, UINT16 channelSeq,
const BYTE* data,
size_t length)
1534 WINPR_ASSERT(data || (length == 0));
1538 const UINT16 ahead = seq16_diff(channelSeq, udp->v3NextChannel);
1539 if (ahead >= RDPUDP_RECEIVE_REACH)
1543 if ((ahead == 0) && !udp->slots[channelSeq % RDPUDP_RECEIVE_SLOTS].present)
1545 udp->v3NextChannel = channel_seq_next(udp->v3NextChannel);
1546 if (!deliver(udp, data, length))
1548 return v3_deliver_ready(udp);
1551 if (!store_slot(udp, channelSeq, data, length))
1553 return v3_deliver_ready(udp);
1557static BOOL v3_process_datagram(rdpUdp* udp, BYTE* data,
size_t length)
1566 const BYTE eighth = data[7];
1570 wStream sbuffer = WINPR_C_ARRAY_INIT;
1571 wStream* s = Stream_StaticConstInit(&sbuffer, data, length);
1573 const BYTE prefix = Stream_Get_UINT8(s);
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))
1581 if ((shortLength > 0) && (shortLength < 7) && !Stream_SetLength(s, 1ull + shortLength))
1584 if (!Stream_CheckAndLogRequiredLengthWLog(udp->log, s, 2))
1586 const UINT16 flags = Stream_Get_UINT16(s) & 0x0FFF;
1588 if ((flags & RDPUDP2_ACK) && (flags & RDPUDP2_ACKVEC))
1591 if (flags & RDPUDP2_ACK)
1593 if (!Stream_CheckAndLogRequiredLengthWLog(udp->log, s, 7))
1595 const UINT16 ack = Stream_Get_UINT16(s);
1597 const size_t delayed = Stream_Get_UINT8(s) & 0x0F;
1598 if (!Stream_SafeSeek(s, delayed))
1600 v3_process_ack(udp, ack);
1603 if ((flags & RDPUDP2_OVERHEADSIZE) && !Stream_SafeSeek(s, 1))
1606 if (flags & RDPUDP2_DELAYACKINFO)
1610 if (!Stream_CheckAndLogRequiredLengthWLog(udp->log, s, 3))
1612 const size_t maxDelayed = Stream_Get_UINT8(s);
1613 udp->v3DelayedAckTimeout = Stream_Get_UINT16(s);
1614 if (maxDelayed == 0)
1615 udp->v3MaxDelayedAcks = 1;
1616 else if (maxDelayed > RDPUDP2_MAX_DELAYED_ACKS)
1617 udp->v3MaxDelayedAcks = RDPUDP2_MAX_DELAYED_ACKS;
1619 udp->v3MaxDelayedAcks = maxDelayed;
1622 BOOL haveAoA = FALSE;
1624 if (flags & RDPUDP2_AOA)
1626 if (!Stream_CheckAndLogRequiredLengthWLog(udp->log, s, 2))
1628 aoa = Stream_Get_UINT16(s);
1632 BOOL haveData = FALSE;
1634 if (flags & RDPUDP2_DATA)
1636 if (!Stream_CheckAndLogRequiredLengthWLog(udp->log, s, 2))
1638 dataSeq = Stream_Get_UINT16(s);
1642 if (flags & RDPUDP2_ACKVEC)
1644 if (!Stream_CheckAndLogRequiredLengthWLog(udp->log, s, 3))
1646 const UINT16 base = Stream_Get_UINT16(s);
1647 const BYTE control = Stream_Get_UINT8(s);
1648 const size_t size = control & 0x7F;
1650 if ((control & 0x80) && !Stream_SafeSeek(s, 4))
1652 if (!Stream_CheckAndLogRequiredLengthWLog(udp->log, s, size))
1654 v3_process_ack_vector(udp, base, s, size);
1660 v3_advance_base(udp, aoa);
1665 udp->v3LatestArrival = winpr_GetTickCount64NS();
1666 udp->v3UnackedPackets++;
1667 udp->receivedData = TRUE;
1668 if (!udp->v3BaseKnown)
1673 UINT16 base = dataSeq;
1674 if (haveAoA && !seq16_after(aoa, dataSeq) &&
1675 (seq16_diff(dataSeq, aoa) < RDPUDP_RECEIVE_REACH))
1677 udp->v3BaseKnown = TRUE;
1678 udp->v3Expected = base;
1679 udp->v3Highest = seq16_diff(base, 1);
1680 udp->v3AckedSeq = seq16_diff(base, 1);
1683 const UINT16 ahead = seq16_diff(dataSeq, udp->v3Expected);
1688 const BOOL behind = (ahead >= 0x8000);
1693 const BOOL acknowledged = haveAoA && seq16_after(aoa, dataSeq);
1694 if (behind && !acknowledged)
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))
1704 udp->v3BehindBase = dataSeq;
1705 udp->v3BehindCount = 0;
1707 udp->v3BehindCount++;
1708 udp->v3BehindArrival = udp->v3LatestArrival;
1709 udp->ackPending = TRUE;
1713 udp->ackPending = TRUE;
1714 udp->v3WindowPending = TRUE;
1715 if (ahead >= RDPUDP_RECEIVE_REACH)
1720 const BOOL withChunk =
1721 (packetType != RDPUDP2_PACKET_DUMMY) && (Stream_GetRemainingLength(s) >= 2);
1722 UINT16 channelSeq = 0;
1727 channelSeq = Stream_Get_UINT16(s);
1728 const UINT16 chunkAhead = seq16_diff(channelSeq, udp->v3NextChannel);
1729 if ((chunkAhead >= RDPUDP_RECEIVE_REACH) && (chunkAhead < 0x8000))
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);
1744 return v3_receive_channel_data(udp, channelSeq, Stream_ConstPointer(s),
1745 Stream_GetRemainingLength(s));
1753static BOOL send_syn(rdpUdp* udp)
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));
1762 const UINT16 version = udp->offerV3 ? RDPUDP_PROTOCOL_VERSION_3 : RDPUDP_PROTOCOL_VERSION_2;
1765 Stream_Write_UINT32_BE(s, UINT32_MAX);
1766 Stream_Write_UINT16_BE(s, RDPUDP_RECEIVE_WINDOW);
1767 Stream_Write_UINT16_BE(s, RDPUDP_FLAG_SYN | RDPUDP_FLAG_SYNEX);
1770 Stream_Write_UINT32_BE(s, udp->initialSequence);
1771 Stream_Write_UINT16_BE(s, RDPUDP_MTU);
1772 Stream_Write_UINT16_BE(s, RDPUDP_MTU);
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));
1780 udp->synSent = now_ms();
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));
1788static BOOL process_syn_ack(rdpUdp* udp,
const BYTE* data,
size_t length)
1790 wStream sbuffer = WINPR_C_ARRAY_INIT;
1793 wStream* s = Stream_StaticConstInit(&sbuffer, data, length);
1796 if (!Stream_CheckAndLogRequiredLengthWLog(udp->log, s, 16))
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))
1806 if (snSourceAck != udp->initialSequence)
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);
1815 const UINT32 peerInitial = Stream_Get_UINT32_BE(s);
1816 UINT16 upMtu = Stream_Get_UINT16_BE(s);
1817 Stream_Seek_UINT16(s);
1819 if ((flags & RDPUDP_FLAG_CORRELATION_ID) && !Stream_SafeSeek(s, 32))
1823 UINT16 version = RDPUDP_PROTOCOL_VERSION_1;
1824 if ((flags & RDPUDP_FLAG_SYNEX) && (Stream_GetRemainingLength(s) >= 4))
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;
1834 case RDPUDP_PROTOCOL_VERSION_1:
1835 case RDPUDP_PROTOCOL_VERSION_2:
1837 case RDPUDP_PROTOCOL_VERSION_3:
1840 version = RDPUDP_PROTOCOL_VERSION_2;
1843 version = RDPUDP_PROTOCOL_VERSION_1;
1847 if ((upMtu < RDPUDP_MIN_MTU) || (upMtu > RDPUDP_MTU))
1848 upMtu = RDPUDP_MIN_MTU;
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;
1860 if (version == RDPUDP_PROTOCOL_VERSION_3)
1864 udp->nextCoded = RDPUDP2_INITIAL_SEQUENCE;
1865 udp->nextChannelSeq = 1;
1868 udp->v3NextChannel = 1;
1869 udp->v3MaxDelayedAcks = RDPUDP2_DEFAULT_DELAYED_ACKS;
1870 udp->v3DelayedAckTimeout = UINT32_MAX;
1874 udp->nextSource = seq32_add(udp->initialSequence, 1);
1875 udp->nextCoded = seq32_add(udp->initialSequence, 1);
1877 udp->ackPending = TRUE;
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);
1886static BOOL process_datagram(rdpUdp* udp, BYTE* data,
size_t length)
1890 const UINT64 now = now_ms();
1891 v3_note_silence(udp, now);
1892 udp->lastReceived = now;
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);
1912static BOOL run_timers(rdpUdp* udp)
1915 const UINT64 now = now_ms();
1917 if (udp->state == RDPUDP_STATE_SYN_SENT)
1919 if (now - udp->synSent < RDPUDP_SYN_TIMEOUT_MS)
1921 if (udp->synAttempts >= RDPUDP_SYN_ATTEMPTS)
1923 rdpudp_fail(udp,
"no SYN+ACK from the server");
1926 return send_syn(udp);
1929 if (udp->state != RDPUDP_STATE_ESTABLISHED)
1932 const BOOL v3 = udp->version == RDPUDP_PROTOCOL_VERSION_3;
1933 if (now - udp->lastReceived > (v3 ? RDPUDP2_PEER_TIMEOUT_MS : RDPUDP_PEER_TIMEOUT_MS))
1935 rdpudp_fail(udp, v3 ?
"nothing heard from the server for 16 seconds"
1936 :
"nothing heard from the server for 65 seconds");
1939 v3_note_silence(udp, now);
1942 const UINT64 progress =
1943 (udp->bufferingSince > udp->lastDelivery) ? udp->bufferingSince : udp->lastDelivery;
1944 if ((udp->buffered > 0) && (now - progress > RDPUDP_STALL_TIMEOUT_MS))
1946 rdpudp_fail(udp,
"the stream is stuck behind a chunk the server no longer resends");
1950 for (
size_t x = 0; x < RDPUDP_MAX_IN_FLIGHT; x++)
1952 rdpudp_pending* p = &udp->pending[x];
1953 if (!p->used || (now < p->due))
1955 if (p->retransmits >= (v3 ? RDPUDP2_MAX_RETRANSMITS : RDPUDP_MAX_RETRANSMITS))
1957 rdpudp_fail(udp,
"a datagram went unacknowledged too many times");
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)
1968 const UINT16 coded = WINPR_ASSERTING_INT_CAST(UINT16, udp->nextCoded);
1970 udp->nextCoded = seq16_add(coded, 1);
1974 udp->cwrPending = TRUE;
1976 WLog_Print(udp->log, WLOG_TRACE,
"retransmitting 0x%08" PRIx32
" (#%" PRIu32
")", p->seq,
1978 if (!rdpudp_transmit(udp, p))
1982 if (now - udp->lastSent >= (v3 ? RDPUDP2_KEEPALIVE_MS : RDPUDP_KEEPALIVE_MS))
1984 if (!rdpudp_send_ack(udp))
1986 udp->lastSent = now;
1996rdpUdp* rdpudp_new(wLog* log,
const BYTE* cookieHash, rdpUdpReceiveFn receive,
void* custom)
1999 WINPR_ASSERT(receive);
2001 rdpUdp* udp = calloc(1,
sizeof(rdpUdp));
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;
2014 memcpy(udp->cookieHash, cookieHash,
sizeof(udp->cookieHash));
2016 udp->sendQueue = Queue_New(FALSE, -1, -1);
2017 if (!udp->sendQueue)
2019 wObject* obj = Queue_Object(udp->sendQueue);
2024 if (winpr_RAND(&udp->initialSequence,
sizeof(udp->initialSequence)) < 0)
2029 WINPR_PRAGMA_DIAG_PUSH
2030 WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
2032 WINPR_PRAGMA_DIAG_POP
2036void rdpudp_free(rdpUdp* udp)
2041 if (udp->sockfd != INVALID_SOCKET)
2042 closesocket(udp->sockfd);
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]);
2052 rdpudp_chunk* chunk =
nullptr;
2053 while ((chunk = Queue_Dequeue(udp->sendQueue)))
2055 Queue_Free(udp->sendQueue);
2061static BOOL set_non_blocking(SOCKET sockfd)
2064 return _ioctlsocket(sockfd, FIONBIO, &arg) == 0;
2067BOOL rdpudp_connect(rdpUdp* udp,
const struct sockaddr* addr,
size_t addrlen)
2072 if (udp->state != RDPUDP_STATE_CLOSED)
2075 udp->sockfd = _socket(addr->sa_family, SOCK_DGRAM, IPPROTO_UDP);
2076 if (udp->sockfd == INVALID_SOCKET)
2078 WLog_Print(udp->log, WLOG_ERROR,
"failed to create the UDP socket");
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");
2089 if (_connect(udp->sockfd, addr, WINPR_ASSERTING_INT_CAST(
int, addrlen)) != 0)
2091 WLog_Print(udp->log, WLOG_ERROR,
"failed to connect the UDP socket");
2095 if (!set_non_blocking(udp->sockfd))
2098 udp->state = RDPUDP_STATE_SYN_SENT;
2099 udp->lastReceived = now_ms();
2100 return send_syn(udp);
2103SOCKET rdpudp_get_socket(
const rdpUdp* udp)
2109RDPUDP_STATE rdpudp_get_state(
const rdpUdp* udp)
2115UINT16 rdpudp_get_version(
const rdpUdp* udp)
2118 return udp->version;
2121size_t rdpudp_get_max_payload(
const rdpUdp* udp)
2125 WINPR_ASSERT(udp->mtu >= RDPUDP_MIN_MTU);
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)
2133 return udp->mtu - overhead;
2136UINT32 rdpudp_get_timeout(
const rdpUdp* udp)
2139 const UINT64 now = now_ms();
2140 UINT64 timeout = 50;
2142 if (udp->state == RDPUDP_STATE_SYN_SENT)
2144 const UINT64 due = udp->synSent + RDPUDP_SYN_TIMEOUT_MS;
2147 if (due - now < timeout)
2148 timeout = due - now;
2149 return WINPR_ASSERTING_INT_CAST(UINT32, timeout);
2152 for (
size_t x = 0; x < RDPUDP_MAX_IN_FLIGHT; x++)
2154 const rdpudp_pending* p = &udp->pending[x];
2159 if (p->due - now < timeout)
2160 timeout = p->due - now;
2164 if (udp->ackPending && (udp->v3AckDue != 0))
2166 if (udp->v3AckDue <= now)
2168 if (udp->v3AckDue - now < timeout)
2169 timeout = udp->v3AckDue - now;
2171 return WINPR_ASSERTING_INT_CAST(UINT32, timeout);
2174BOOL rdpudp_check(rdpUdp* udp)
2178 if ((udp->state == RDPUDP_STATE_FAILED) || (udp->state == RDPUDP_STATE_CLOSED))
2181 BYTE* buffer = udp->recvBuffer;
2184 const int rc = _recv(udp->sockfd, (
char*)buffer,
2185 WINPR_ASSERTING_INT_CAST(
int,
sizeof(udp->recvBuffer)), 0);
2188 const int error = WSAGetLastError();
2189 if (!rdpudp_socket_error_is_transient(error))
2191 WLog_Print(udp->log, WLOG_ERROR,
"recv failed with %d", error);
2192 rdpudp_fail(udp,
"receiving from the socket failed");
2197 if (error != WSAEWOULDBLOCK)
2198 WLog_Print(udp->log, WLOG_DEBUG,
"recv failed with %d", error);
2202 if (!process_datagram(udp, buffer, WINPR_ASSERTING_INT_CAST(
size_t, rc)))
2204 rdpudp_fail(udp,
"failed to process a datagram");
2207 if (udp->state == RDPUDP_STATE_FAILED)
2209 if (!v3_ack_if_due(udp))
2213 if (!ack_when_due(udp))
2216 if (!flush_send_queue(udp))
2219 return run_timers(udp);
This struct contains function pointer to initialize/free objects.
OBJECT_FREE_FN fnObjectFree