if(ENABLE_UTP)
tr_add_external_auto_library(UTP utp
PATCH_COMMAND "${CMAKE_COMMAND}" -E copy "${THIRD_PARTY_DIR}/utp.cmake" "<SOURCE_DIR>/CMakeLists.txt"
- COMMAND "${CMAKE_COMMAND}" -E copy "${THIRD_PARTY_DIR}/utp_config.h" "<SOURCE_DIR>/utp_config.h")
+ COMMAND "${CMAKE_COMMAND}" -E copy "${THIRD_PARTY_DIR}/utp_config.h" "<SOURCE_DIR>/utp_config.h"
+ COMMAND "${CMAKE_COMMAND}" -E chdir "<SOURCE_DIR>" patch -p1 --binary -i "${THIRD_PARTY_DIR}/utp-01-ticket-5002.patch")
endif()
tr_add_external_auto_library(B64 b64
--- /dev/null
+diff --git a/utp.cpp b/utp.cpp
+--- a/utp.cpp
++++ b/utp.cpp
+@@ -1487,6 +1487,8 @@
+ return acked_bytes;\r
+ }\r
+ \r
++enum { MAX_EACK = 128 };\r
++\r
+ void UTPSocket::selective_ack(uint base, const byte *mask, byte len)\r
+ {\r
+ if (cur_window_packets == 0) return;\r
+@@ -1499,7 +1501,7 @@
+ // resends is a stack of sequence numbers we need to resend. Since we\r
+ // iterate in reverse over the acked packets, at the end, the top packets\r
+ // are the ones we want to resend\r
+- int resends[32];\r
++ int resends[MAX_EACK];\r
+ int nr = 0;\r
+ \r
+ LOG_UTPV("0x%08x: Got EACK [%032b] base:%u", this, *(uint32*)mask, base);\r
+@@ -1572,6 +1574,12 @@
+ if (((v - fast_resend_seq_nr) & ACK_NR_MASK) <= OUTGOING_BUFFER_MAX_SIZE &&\r
+ count >= DUPLICATE_ACKS_BEFORE_RESEND &&\r
+ duplicate_ack < DUPLICATE_ACKS_BEFORE_RESEND) {\r
++ // resends is a stack, and we're mostly interested in the top of it\r
++ // if we're full, just throw away the lower half\r
++ if (nr >= MAX_EACK - 2) {\r
++ memmove(resends, &resends[MAX_EACK/2], MAX_EACK/2 * sizeof(resends[0]));\r
++ nr -= MAX_EACK / 2;\r
++ }\r
+ resends[nr++] = v;\r
+ LOG_UTPV("0x%08x: no ack for %u", this, v);\r
+ } else {\r
+@@ -1580,13 +1588,12 @@
+ }\r
+ } while (--bits >= -1);\r
+ \r
+- if (((base - 1 - fast_resend_seq_nr) & ACK_NR_MASK) < 256 &&\r
+- count >= DUPLICATE_ACKS_BEFORE_RESEND &&\r
+- duplicate_ack < DUPLICATE_ACKS_BEFORE_RESEND) {\r
++ if (((base - 1 - fast_resend_seq_nr) & ACK_NR_MASK) <= OUTGOING_BUFFER_MAX_SIZE &&\r
++ count >= DUPLICATE_ACKS_BEFORE_RESEND) {\r
+ // if we get enough duplicate acks to start\r
+ // resending, the first packet we should resend\r
+ // is base-1\r
+- resends[nr++] = base - 1;\r
++ resends[nr++] = (base - 1) & ACK_NR_MASK;\r
+ } else {\r
+ LOG_UTPV("0x%08x: not resending %u count:%d dup_ack:%u fast_resend_seq_nr:%u",\r
+ this, base - 1, count, duplicate_ack, fast_resend_seq_nr);\r
+\r