diff --git a/CMakeLists.txt b/CMakeLists.txt index 7be93fd..594573c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -24,7 +24,7 @@ if(LIBUTP_STANDALONE_BUILD) endif() if(NOT CMAKE_CXX_STANDARD) - set(CMAKE_CXX_STANDARD 98) + set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_EXTENSIONS OFF) endif() diff --git a/utp_hash.cpp b/utp_hash.cpp index afceb14..e5f0b45 100644 --- a/utp_hash.cpp +++ b/utp_hash.cpp @@ -20,6 +20,8 @@ * THE SOFTWARE. */ +#include + #include "utp_hash.h" #include "utp_types.h" diff --git a/utp_internal.cpp b/utp_internal.cpp index 7ff99be..fc65b64 100644 --- a/utp_internal.cpp +++ b/utp_internal.cpp @@ -667,21 +667,22 @@ struct UTPSocket { size_t get_packet_size() const; }; -void removeSocketFromAckList(UTPSocket *conn) +static void removeSocketFromAckList(UTPSocket *conn) { - if (conn->ida >= 0) - { - UTPSocket *last = conn->ctx->ack_sockets[conn->ctx->ack_sockets.GetCount() - 1]; + auto const ida = conn->ida; + if (ida < 0) + return; - assert(last->ida < (int)(conn->ctx->ack_sockets.GetCount())); - assert(conn->ctx->ack_sockets[last->ida] == last); - last->ida = conn->ida; - conn->ctx->ack_sockets[conn->ida] = last; - conn->ida = -1; + auto& acks = conn->ctx->ack_sockets; + assert(acks[ida]->ida == ida); - // Decrease the count - conn->ctx->ack_sockets.SetCount(conn->ctx->ack_sockets.GetCount() - 1); - } + // fast-remove `conn` from acks by swapping w/last and resizing. + // update `ida` index for both swapped sockets. + // note the steps need to be safe even when conn == acks.back() + std::swap(acks[ida], acks.back()); + acks[ida]->ida = ida; + acks.resize(acks.size() - 1U); + conn->ida = -1; } static void utp_register_sent_packet(utp_context *ctx, size_t length) @@ -715,7 +716,8 @@ void UTPSocket::schedule_ack() #if UTP_DEBUG_LOGGING log(UTP_LOG_DEBUG, "schedule_ack"); #endif - ida = ctx->ack_sockets.Append(this); + ida = ctx->ack_sockets.size(); + ctx->ack_sockets.push_back(this); } else { #if UTP_DEBUG_LOGGING log(UTP_LOG_DEBUG, "schedule_ack: already in list"); @@ -2923,12 +2925,9 @@ int utp_process_udp(utp_context *ctx, const byte *buffer, size_t len, const stru if (flags != ST_SYN) { ctx->current_ms = utp_call_get_milliseconds(ctx, NULL); - for (size_t i = 0; i < ctx->rst_info.GetCount(); i++) { - if ((ctx->rst_info[i].connid == id) && - (ctx->rst_info[i].addr == addr) && - (ctx->rst_info[i].ack_nr == seq_nr)) - { - ctx->rst_info[i].timestamp = ctx->current_ms; + for (auto& info : ctx->rst_info) { + if ((info.connid == id) && (info.addr == addr) && (info.ack_nr == seq_nr)) { + info.timestamp = ctx->current_ms; #if UTP_DEBUG_LOGGING ctx->log(UTP_LOG_DEBUG, NULL, "recv not sending RST to non-SYN (stored)"); @@ -2938,7 +2937,7 @@ int utp_process_udp(utp_context *ctx, const byte *buffer, size_t len, const stru } } - if (ctx->rst_info.GetCount() > RST_INFO_LIMIT) { + if (ctx->rst_info.size() > RST_INFO_LIMIT) { #if UTP_DEBUG_LOGGING ctx->log(UTP_LOG_DEBUG, NULL, "recv not sending RST to non-SYN (limit at %u stored)", (uint)ctx->rst_info.GetCount()); @@ -2951,11 +2950,7 @@ int utp_process_udp(utp_context *ctx, const byte *buffer, size_t len, const stru ctx->log(UTP_LOG_DEBUG, NULL, "recv send RST to non-SYN (%u stored)", (uint)ctx->rst_info.GetCount()); #endif - RST_Info &r = ctx->rst_info.Append(); - r.addr = addr; - r.connid = id; - r.ack_nr = seq_nr; - r.timestamp = ctx->current_ms; + ctx->rst_info.emplace_back(addr, id, seq_nr, ctx->current_ms); UTPSocket::send_rst(ctx, addr, id, seq_nr, utp_call_get_random(ctx, NULL)); return 1; @@ -3280,7 +3275,7 @@ void utp_issue_deferred_acks(utp_context *ctx) assert(ctx); if (!ctx) return; - for (size_t i = 0; i < ctx->ack_sockets.GetCount(); i++) { + for (size_t i = 0; i < ctx->ack_sockets.size(); i++) { UTPSocket *conn = ctx->ack_sockets[i]; conn->send_ack(); i--; @@ -3300,15 +3295,16 @@ void utp_check_timeouts(utp_context *ctx) ctx->last_check = ctx->current_ms; - for (size_t i = 0; i < ctx->rst_info.GetCount(); i++) { - if ((int)(ctx->current_ms - ctx->rst_info[i].timestamp) >= RST_INFO_TIMEOUT) { - ctx->rst_info.MoveUpLast(i); + auto& infos = ctx->rst_info; + for (size_t i = 0; i < infos.size(); i++) { + if ((int)(ctx->current_ms - infos[i].timestamp) >= RST_INFO_TIMEOUT) { + // fast-remove from `infos` by swapping w/last and resizing + std::swap(infos[i], infos.back()); + infos.resize(infos.size() - 1U); i--; } } - if (ctx->rst_info.GetCount() != ctx->rst_info.GetAlloc()) { - ctx->rst_info.Compact(); - } + infos.shrink_to_fit(); utp_hash_iterator_t it; UTPSocketKeyData* keyData; diff --git a/utp_internal.h b/utp_internal.h index be74135..0bd2c06 100644 --- a/utp_internal.h +++ b/utp_internal.h @@ -28,6 +28,8 @@ #include #include +#include + #include "utp.h" #include "utp_callbacks.h" #include "utp_templates.h" @@ -59,6 +61,16 @@ enum bandwidth_type_t { #endif struct PACKED_ATTRIBUTE RST_Info { + RST_Info() = default; + + RST_Info(PackedSockAddr _addr, uint32 _connid, uint16 _ack_nr, uint64 _timestamp) + : addr{ _addr } + , connid{ _connid } + , ack_nr{ _ack_nr } + , timestamp{ _timestamp } + { + } + PackedSockAddr addr; uint32 connid; uint16 ack_nr; @@ -117,8 +129,8 @@ struct struct_utp_context { uint64 current_ms; utp_context_stats context_stats; UTPSocket *last_utp_socket; - Array ack_sockets; - Array rst_info; + std::vector ack_sockets; + std::vector rst_info; UTPSocketHT *utp_sockets; size_t target_delay; size_t opt_sndbuf; diff --git a/utp_templates.h b/utp_templates.h index 8f88f5c..500e7db 100644 --- a/utp_templates.h +++ b/utp_templates.h @@ -24,7 +24,6 @@ #define __TEMPLATES_H__ #include "utp_types.h" -#include #if defined(POSIX) /* Allow over-writing FORCEINLINE from makefile because gcc 3.4.4 for buffalo @@ -95,101 +94,4 @@ typedef big_endian uint16_big; template static inline void zeromem(T *a, size_t count = 1) { memset(a, 0, count * sizeof(T)); } -typedef int SortCompareProc(const void *, const void *); - -template static FORCEINLINE void QuickSortT(T *base, size_t num, int (*comp)(const T *, const T *)) { qsort(base, num, sizeof(T), (SortCompareProc*)comp); } - - -// WARNING: The template parameter MUST be a POD type! -template class Array { -protected: - T *mem; - size_t alloc,count; - -public: - Array(size_t init) { Init(init); } - Array() { Init(); } - ~Array() { Free(); } - - void inline Init() { mem = NULL; alloc = count = 0; } - void inline Init(size_t init) { Init(); if (init) Resize(init); } - size_t inline GetCount() const { return count; } - size_t inline GetAlloc() const { return alloc; } - void inline SetCount(size_t c) { count = c; } - - inline T& operator[](size_t offset) { assert(offset ==0 || offset(minsize, alloc * 2)); } - - inline size_t Append(const T &t) { - if (count >= alloc) Grow(); - size_t r=count++; - mem[r] = t; - return r; - } - - T inline &Append() { - if (count >= alloc) Grow(); - return mem[count++]; - } - - void inline Compact() { - Resize(count); - } - - void inline Free() { - free(mem); - Init(); - } - - void inline Clear() { - count = 0; - } - - bool inline MoveUpLast(size_t index) { - assert(index < count); - size_t c = --count; - if (index != c) { - mem[index] = mem[c]; - return true; - } - return false; - } - - bool inline MoveUpLastExist(const T &v) { - return MoveUpLast(LookupElementExist(v)); - } - - size_t inline LookupElement(const T &v) const { - for(size_t i = 0; i != count; i++) - if (mem[i] == v) - return i; - return (size_t) -1; - } - - bool inline HasElement(const T &v) const { - return LookupElement(v) != -1; - } - - typedef int SortCompareProc(const T *a, const T *b); - - void Sort(SortCompareProc* proc, size_t start, size_t end) { - QuickSortT(&mem[start], end - start, proc); - } - - void Sort(SortCompareProc* proc, size_t start) { - Sort(proc, start, count); - } - - void Sort(SortCompareProc* proc) { - Sort(proc, 0, count); - } -}; - #endif //__TEMPLATES_H__