Loading src/crypto/aes.cpp +15 −1 Original line number Diff line number Diff line Loading @@ -28,6 +28,20 @@ #define AESNI_FUNC #endif static inline std::uint32_t byteSwap32(std::uint32_t value) noexcept { #if defined(_MSC_VER) return _byteswap_ulong(value); #elif defined(__GNUC__) || defined(__clang__) return __builtin_bswap32(value); #else return ((value & 0x000000FFu) << 24) | ((value & 0x0000FF00u) << 8) | ((value & 0x00FF0000u) >> 8) | ((value & 0xFF000000u) >> 24); #endif } // F16 (performance report): deliberately NOT switched to VAES/AVX-512 // (VAES+VPCLMULQDQ, 2-4 AES blocks per instruction instead of 1), even // though the report sees a further, significant multiple there over the Loading Loading @@ -137,7 +151,7 @@ static inline __m128i make_ctr_block(const uint8_t base[16], uint32_t counter) { // (little-endian) 32-bit lane produces exactly the big-endian byte // sequence in memory order that the stack-buffer version built by hand. __m128i blk = _mm_loadu_si128(reinterpret_cast<const __m128i*>(base)); return _mm_insert_epi32(blk, static_cast<int>(__builtin_bswap32(counter)), 3); return _mm_insert_epi32(blk, static_cast<int>(byteSwap32(counter)), 3); } // ---- PCLMULQDQ-based GCM multiplication in GF(2^128) ---- Loading test/quic_version_negotiation_test.cpp +93 −19 Original line number Diff line number Diff line Loading @@ -15,12 +15,24 @@ #include <chrono> #include <cstring> #include <cstdint> #include <stdexcept> #ifdef _WIN32 #ifndef WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN #endif #include <winsock2.h> #include <ws2tcpip.h> #ifdef _MSC_VER #pragma comment(lib, "Ws2_32.lib") #endif #else #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <unistd.h> #include <poll.h> #endif #include "connection.h" #include "eventapi.h" Loading @@ -33,6 +45,36 @@ using namespace netplus; #ifdef _WIN32 using native_socket_t = SOCKET; static constexpr native_socket_t kInvalidSocket = INVALID_SOCKET; #else using native_socket_t = int; static constexpr native_socket_t kInvalidSocket = -1; #endif static void closeNativeSocket(native_socket_t fd) noexcept { #ifdef _WIN32 if (fd != kInvalidSocket) ::closesocket(fd); #else if (fd != kInvalidSocket) ::close(fd); #endif } static bool waitForReadable(native_socket_t fd, int timeoutMs) { #ifdef _WIN32 WSAPOLLFD pfd{}; pfd.fd = fd; pfd.events = POLLRDNORM; const int rc = ::WSAPoll(&pfd, 1, timeoutMs); return rc > 0 && (pfd.revents & POLLRDNORM) != 0; #else pollfd pfd{fd, POLLIN, 0}; const int rc = ::poll(&pfd, 1, timeoutMs); return rc > 0 && (pfd.revents & POLLIN) != 0; #endif } static int g_passed = 0, g_failed = 0; static void check(bool ok, const std::string& name) { Loading Loading @@ -77,6 +119,14 @@ static void runQuicServer(std::map<std::string, ssl::CertificateBundle>& certs, } int main() { #ifdef _WIN32 WSADATA wsaData{}; const int wsaRc = ::WSAStartup(MAKEWORD(2, 2), &wsaData); if (wsaRc != 0) { std::cerr << "WSAStartup failed: " << wsaRc << std::endl; return 1; } #endif std::cout << "=== QUIC Version Negotiation Test ===" << std::endl; const int kQuicPort = 19548; Loading @@ -86,8 +136,7 @@ int main() { try { x509cert cert; if (!cert.loadFromBuffer(test_cert_der)) { std::cerr << "Failed to load certificate" << std::endl; return 1; throw std::runtime_error("failed to load certificate"); } std::map<std::string, ssl::CertificateBundle> certs; ssl::CertificateBundle bundle; Loading Loading @@ -121,25 +170,46 @@ int main() { pkt.push_back(static_cast<uint8_t>(client_scid.size())); pkt.insert(pkt.end(), client_scid.begin(), client_scid.end()); int rawfd = ::socket(AF_INET, SOCK_DGRAM, 0); check(rawfd >= 0, "raw UDP socket created"); native_socket_t rawfd = ::socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); check(rawfd != kInvalidSocket, "raw UDP socket created"); if (rawfd == kInvalidSocket) { #ifdef _WIN32 std::cerr << "socket() failed: " << ::WSAGetLastError() << std::endl; #else std::cerr << "socket() failed" << std::endl; #endif throw std::runtime_error("unable to create raw UDP socket"); } sockaddr_in serverAddr{}; serverAddr.sin_family = AF_INET; serverAddr.sin_port = htons(kQuicPort); inet_pton(AF_INET, "127.0.0.1", &serverAddr.sin_addr); ssize_t sent = ::sendto(rawfd, pkt.data(), pkt.size(), 0, reinterpret_cast<sockaddr*>(&serverAddr), sizeof(serverAddr)); check(sent == static_cast<ssize_t>(pkt.size()), "crafted Initial sent to server"); ::inet_pton(AF_INET, "127.0.0.1", &serverAddr.sin_addr); #ifdef _WIN32 const int sent = ::sendto(rawfd, reinterpret_cast<const char*>(pkt.data()), static_cast<int>(pkt.size()), 0, reinterpret_cast<const sockaddr*>(&serverAddr), static_cast<int>(sizeof(serverAddr))); #else const ssize_t sent = ::sendto(rawfd, pkt.data(), pkt.size(), 0, reinterpret_cast<const sockaddr*>(&serverAddr), sizeof(serverAddr)); #endif check(sent == static_cast<decltype(sent)>(pkt.size()), "crafted Initial sent to server"); std::vector<uint8_t> resp(2048); pollfd pfd{rawfd, POLLIN, 0}; int pr = ::poll(&pfd, 1, 5000); check(pr > 0 && (pfd.revents & POLLIN), "received a reply within 5s (not silence)"); if (pr > 0 && (pfd.revents & POLLIN)) { ssize_t n = ::recv(rawfd, resp.data(), resp.size(), 0); const bool readable = waitForReadable(rawfd, 5000); check(readable, "received a reply within 5s (not silence)"); if (readable) { #ifdef _WIN32 const int n = ::recv(rawfd, reinterpret_cast<char*>(resp.data()), static_cast<int>(resp.size()), 0); #else const ssize_t n = ::recv(rawfd, resp.data(), resp.size(), 0); #endif check(n > 0, "reply has non-zero length"); resp.resize(n > 0 ? static_cast<size_t>(n) : 0); Loading Loading @@ -193,7 +263,7 @@ int main() { check(hasV2, "supported version list includes QUICv2 (0x6b3343cf)"); } if (rawfd >= 0) ::close(rawfd); closeNativeSocket(rawfd); } catch (NetException& e) { std::cerr << "NetException: " << e.what() << std::endl; Loading @@ -212,5 +282,9 @@ int main() { std::cout << "Results: " << g_passed << " passed, " << g_failed << " failed" << std::endl; std::cout << "==============================" << std::endl; return (rc != 0 || g_failed > 0) ? 1 : 0; const int result = (rc != 0 || g_failed > 0) ? 1 : 0; #ifdef _WIN32 ::WSACleanup(); #endif return result; } No newline at end of file Loading
src/crypto/aes.cpp +15 −1 Original line number Diff line number Diff line Loading @@ -28,6 +28,20 @@ #define AESNI_FUNC #endif static inline std::uint32_t byteSwap32(std::uint32_t value) noexcept { #if defined(_MSC_VER) return _byteswap_ulong(value); #elif defined(__GNUC__) || defined(__clang__) return __builtin_bswap32(value); #else return ((value & 0x000000FFu) << 24) | ((value & 0x0000FF00u) << 8) | ((value & 0x00FF0000u) >> 8) | ((value & 0xFF000000u) >> 24); #endif } // F16 (performance report): deliberately NOT switched to VAES/AVX-512 // (VAES+VPCLMULQDQ, 2-4 AES blocks per instruction instead of 1), even // though the report sees a further, significant multiple there over the Loading Loading @@ -137,7 +151,7 @@ static inline __m128i make_ctr_block(const uint8_t base[16], uint32_t counter) { // (little-endian) 32-bit lane produces exactly the big-endian byte // sequence in memory order that the stack-buffer version built by hand. __m128i blk = _mm_loadu_si128(reinterpret_cast<const __m128i*>(base)); return _mm_insert_epi32(blk, static_cast<int>(__builtin_bswap32(counter)), 3); return _mm_insert_epi32(blk, static_cast<int>(byteSwap32(counter)), 3); } // ---- PCLMULQDQ-based GCM multiplication in GF(2^128) ---- Loading
test/quic_version_negotiation_test.cpp +93 −19 Original line number Diff line number Diff line Loading @@ -15,12 +15,24 @@ #include <chrono> #include <cstring> #include <cstdint> #include <stdexcept> #ifdef _WIN32 #ifndef WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN #endif #include <winsock2.h> #include <ws2tcpip.h> #ifdef _MSC_VER #pragma comment(lib, "Ws2_32.lib") #endif #else #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <unistd.h> #include <poll.h> #endif #include "connection.h" #include "eventapi.h" Loading @@ -33,6 +45,36 @@ using namespace netplus; #ifdef _WIN32 using native_socket_t = SOCKET; static constexpr native_socket_t kInvalidSocket = INVALID_SOCKET; #else using native_socket_t = int; static constexpr native_socket_t kInvalidSocket = -1; #endif static void closeNativeSocket(native_socket_t fd) noexcept { #ifdef _WIN32 if (fd != kInvalidSocket) ::closesocket(fd); #else if (fd != kInvalidSocket) ::close(fd); #endif } static bool waitForReadable(native_socket_t fd, int timeoutMs) { #ifdef _WIN32 WSAPOLLFD pfd{}; pfd.fd = fd; pfd.events = POLLRDNORM; const int rc = ::WSAPoll(&pfd, 1, timeoutMs); return rc > 0 && (pfd.revents & POLLRDNORM) != 0; #else pollfd pfd{fd, POLLIN, 0}; const int rc = ::poll(&pfd, 1, timeoutMs); return rc > 0 && (pfd.revents & POLLIN) != 0; #endif } static int g_passed = 0, g_failed = 0; static void check(bool ok, const std::string& name) { Loading Loading @@ -77,6 +119,14 @@ static void runQuicServer(std::map<std::string, ssl::CertificateBundle>& certs, } int main() { #ifdef _WIN32 WSADATA wsaData{}; const int wsaRc = ::WSAStartup(MAKEWORD(2, 2), &wsaData); if (wsaRc != 0) { std::cerr << "WSAStartup failed: " << wsaRc << std::endl; return 1; } #endif std::cout << "=== QUIC Version Negotiation Test ===" << std::endl; const int kQuicPort = 19548; Loading @@ -86,8 +136,7 @@ int main() { try { x509cert cert; if (!cert.loadFromBuffer(test_cert_der)) { std::cerr << "Failed to load certificate" << std::endl; return 1; throw std::runtime_error("failed to load certificate"); } std::map<std::string, ssl::CertificateBundle> certs; ssl::CertificateBundle bundle; Loading Loading @@ -121,25 +170,46 @@ int main() { pkt.push_back(static_cast<uint8_t>(client_scid.size())); pkt.insert(pkt.end(), client_scid.begin(), client_scid.end()); int rawfd = ::socket(AF_INET, SOCK_DGRAM, 0); check(rawfd >= 0, "raw UDP socket created"); native_socket_t rawfd = ::socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); check(rawfd != kInvalidSocket, "raw UDP socket created"); if (rawfd == kInvalidSocket) { #ifdef _WIN32 std::cerr << "socket() failed: " << ::WSAGetLastError() << std::endl; #else std::cerr << "socket() failed" << std::endl; #endif throw std::runtime_error("unable to create raw UDP socket"); } sockaddr_in serverAddr{}; serverAddr.sin_family = AF_INET; serverAddr.sin_port = htons(kQuicPort); inet_pton(AF_INET, "127.0.0.1", &serverAddr.sin_addr); ssize_t sent = ::sendto(rawfd, pkt.data(), pkt.size(), 0, reinterpret_cast<sockaddr*>(&serverAddr), sizeof(serverAddr)); check(sent == static_cast<ssize_t>(pkt.size()), "crafted Initial sent to server"); ::inet_pton(AF_INET, "127.0.0.1", &serverAddr.sin_addr); #ifdef _WIN32 const int sent = ::sendto(rawfd, reinterpret_cast<const char*>(pkt.data()), static_cast<int>(pkt.size()), 0, reinterpret_cast<const sockaddr*>(&serverAddr), static_cast<int>(sizeof(serverAddr))); #else const ssize_t sent = ::sendto(rawfd, pkt.data(), pkt.size(), 0, reinterpret_cast<const sockaddr*>(&serverAddr), sizeof(serverAddr)); #endif check(sent == static_cast<decltype(sent)>(pkt.size()), "crafted Initial sent to server"); std::vector<uint8_t> resp(2048); pollfd pfd{rawfd, POLLIN, 0}; int pr = ::poll(&pfd, 1, 5000); check(pr > 0 && (pfd.revents & POLLIN), "received a reply within 5s (not silence)"); if (pr > 0 && (pfd.revents & POLLIN)) { ssize_t n = ::recv(rawfd, resp.data(), resp.size(), 0); const bool readable = waitForReadable(rawfd, 5000); check(readable, "received a reply within 5s (not silence)"); if (readable) { #ifdef _WIN32 const int n = ::recv(rawfd, reinterpret_cast<char*>(resp.data()), static_cast<int>(resp.size()), 0); #else const ssize_t n = ::recv(rawfd, resp.data(), resp.size(), 0); #endif check(n > 0, "reply has non-zero length"); resp.resize(n > 0 ? static_cast<size_t>(n) : 0); Loading Loading @@ -193,7 +263,7 @@ int main() { check(hasV2, "supported version list includes QUICv2 (0x6b3343cf)"); } if (rawfd >= 0) ::close(rawfd); closeNativeSocket(rawfd); } catch (NetException& e) { std::cerr << "NetException: " << e.what() << std::endl; Loading @@ -212,5 +282,9 @@ int main() { std::cout << "Results: " << g_passed << " passed, " << g_failed << " failed" << std::endl; std::cout << "==============================" << std::endl; return (rc != 0 || g_failed > 0) ? 1 : 0; const int result = (rc != 0 || g_failed > 0) ? 1 : 0; #ifdef _WIN32 ::WSACleanup(); #endif return result; } No newline at end of file