Loading src/quic.cpp +28 −7 Original line number Diff line number Diff line Loading @@ -103,6 +103,21 @@ quic::quic(const std::string& addr, int port, int maxconnections, int sockopts) ::setsockopt(_Socket, SOL_SOCKET, SO_SNDBUF, sndopt, sizeof(sndbuf)); #ifdef Windows // Disable SIO_UDP_CONNRESET: on Windows, an ICMP "port unreachable" // response causes the next recvfrom to fail with WSAECONNRESET. { BOOL bNewBehavior = FALSE; DWORD dwBytesReturned = 0; ::WSAIoctl(_Socket, SIO_UDP_CONNRESET, &bNewBehavior, sizeof(bNewBehavior), NULL, 0, &dwBytesReturned, NULL, NULL); } #endif // Set non-blocking: on Windows MSG_DONTWAIT is a no-op (defined as 0), // so the server socket must be non-blocking to prevent stalls. setNonBlock(); // Probe for UDP GSO/GRO kernel offload support probeGSOGRO(); Loading Loading @@ -148,6 +163,11 @@ quic::quic(const std::map<std::string, ssl::CertificateBundle>& certs, NULL, 0, &dwBytesReturned, NULL, NULL); #endif // Set non-blocking: on Windows MSG_DONTWAIT is a no-op (defined as 0), // so the server socket must be non-blocking to prevent recvfrom/sendto // from stalling the accept loop. setNonBlock(); // Probe for UDP GSO/GRO kernel offload support probeGSOGRO(); Loading Loading @@ -237,7 +257,6 @@ ssize_t quic::sendPacket(const uint8_t* data, size_t len) { QUIC_DBG("sendPacket: _Socket < 0, dropping %zu bytes", len); return -1; } QUIC_DBG("sendPacket: len=%zu parent=%p _Socket=%d", len, (void*)_parent, _Socket); for (int attempt = 0; attempt < 5; ++attempt) { Loading Loading @@ -2325,6 +2344,11 @@ void quic::connect(const std::string& addr, int port, bool nonblock) { if (!nonblock) { completeHandshake(); } // Switch to non-blocking after handshake: on Windows MSG_DONTWAIT is a // no-op (defined as 0), so all recv/send calls must rely on the socket // being in non-blocking mode to avoid indefinite stalls. setNonBlock(); } // ============================================================================ Loading Loading @@ -3311,9 +3335,6 @@ void quic::processStreamFrame(const uint8_t* data, size_t len, size_t& offset) { } else { stream_len = len - offset; // Rest of frame is data } QUIC_DBG("processStreamFrame: sid=%lu off=%lu len=%lu fin=%d ftype=0x%02x", (unsigned long)stream_id, (unsigned long)stream_offset, (unsigned long)stream_len, (int)has_fin, frame_type); if (offset + stream_len > len) return; Loading Loading @@ -4295,7 +4316,7 @@ void quic::processClientHello(const std::vector<uint8_t>& msg) { if (cs == 0x1301) found_aes128 = true; // TLS_AES_128_GCM_SHA256 } // Select cipher suite - prefer AES-256 with SHA-384 // Select cipher suite - prefer AES-256 if (found_aes256) { _selected_cipher = 0x1302; // TLS_AES_256_GCM_SHA384 } else if (found_aes128) { Loading src/windows/udp.cpp +6 −2 Original line number Diff line number Diff line Loading @@ -412,12 +412,16 @@ ssize_t udp::sendBatch( sockaddr_storage* dest, socklen_t dest_len) { // Fallback: send one by one // Use udp:: explicitly to avoid virtual dispatch (quic overrides sendData/sendTo) ssize_t total = 0; for (auto& [p, l] : datagrams) { buffer buf(reinterpret_cast<const char*>(p), l); try { if (dest) sendTo(buf, 0); else sendData(buf, 0); if (dest) { udp::sendTo(buf, 0); } else { udp::sendData(buf, 0); } total++; } catch (...) { break; } } Loading Loading
src/quic.cpp +28 −7 Original line number Diff line number Diff line Loading @@ -103,6 +103,21 @@ quic::quic(const std::string& addr, int port, int maxconnections, int sockopts) ::setsockopt(_Socket, SOL_SOCKET, SO_SNDBUF, sndopt, sizeof(sndbuf)); #ifdef Windows // Disable SIO_UDP_CONNRESET: on Windows, an ICMP "port unreachable" // response causes the next recvfrom to fail with WSAECONNRESET. { BOOL bNewBehavior = FALSE; DWORD dwBytesReturned = 0; ::WSAIoctl(_Socket, SIO_UDP_CONNRESET, &bNewBehavior, sizeof(bNewBehavior), NULL, 0, &dwBytesReturned, NULL, NULL); } #endif // Set non-blocking: on Windows MSG_DONTWAIT is a no-op (defined as 0), // so the server socket must be non-blocking to prevent stalls. setNonBlock(); // Probe for UDP GSO/GRO kernel offload support probeGSOGRO(); Loading Loading @@ -148,6 +163,11 @@ quic::quic(const std::map<std::string, ssl::CertificateBundle>& certs, NULL, 0, &dwBytesReturned, NULL, NULL); #endif // Set non-blocking: on Windows MSG_DONTWAIT is a no-op (defined as 0), // so the server socket must be non-blocking to prevent recvfrom/sendto // from stalling the accept loop. setNonBlock(); // Probe for UDP GSO/GRO kernel offload support probeGSOGRO(); Loading Loading @@ -237,7 +257,6 @@ ssize_t quic::sendPacket(const uint8_t* data, size_t len) { QUIC_DBG("sendPacket: _Socket < 0, dropping %zu bytes", len); return -1; } QUIC_DBG("sendPacket: len=%zu parent=%p _Socket=%d", len, (void*)_parent, _Socket); for (int attempt = 0; attempt < 5; ++attempt) { Loading Loading @@ -2325,6 +2344,11 @@ void quic::connect(const std::string& addr, int port, bool nonblock) { if (!nonblock) { completeHandshake(); } // Switch to non-blocking after handshake: on Windows MSG_DONTWAIT is a // no-op (defined as 0), so all recv/send calls must rely on the socket // being in non-blocking mode to avoid indefinite stalls. setNonBlock(); } // ============================================================================ Loading Loading @@ -3311,9 +3335,6 @@ void quic::processStreamFrame(const uint8_t* data, size_t len, size_t& offset) { } else { stream_len = len - offset; // Rest of frame is data } QUIC_DBG("processStreamFrame: sid=%lu off=%lu len=%lu fin=%d ftype=0x%02x", (unsigned long)stream_id, (unsigned long)stream_offset, (unsigned long)stream_len, (int)has_fin, frame_type); if (offset + stream_len > len) return; Loading Loading @@ -4295,7 +4316,7 @@ void quic::processClientHello(const std::vector<uint8_t>& msg) { if (cs == 0x1301) found_aes128 = true; // TLS_AES_128_GCM_SHA256 } // Select cipher suite - prefer AES-256 with SHA-384 // Select cipher suite - prefer AES-256 if (found_aes256) { _selected_cipher = 0x1302; // TLS_AES_256_GCM_SHA384 } else if (found_aes128) { Loading
src/windows/udp.cpp +6 −2 Original line number Diff line number Diff line Loading @@ -412,12 +412,16 @@ ssize_t udp::sendBatch( sockaddr_storage* dest, socklen_t dest_len) { // Fallback: send one by one // Use udp:: explicitly to avoid virtual dispatch (quic overrides sendData/sendTo) ssize_t total = 0; for (auto& [p, l] : datagrams) { buffer buf(reinterpret_cast<const char*>(p), l); try { if (dest) sendTo(buf, 0); else sendData(buf, 0); if (dest) { udp::sendTo(buf, 0); } else { udp::sendData(buf, 0); } total++; } catch (...) { break; } } Loading