diff --git a/.clang-tidy b/.clang-tidy new file mode 100644 index 0000000..07d2a77 --- /dev/null +++ b/.clang-tidy @@ -0,0 +1,57 @@ +--- +# clang-tidy configuration for netcpp +# Tuned to this project's C++20, cross-platform (Windows/Linux) code base. +# +# Run manually on a single translation unit: +# clang-tidy -p build/linux-x86_64-debug src/socket.cpp +# +# Or wire it into the build (optional): +# cmake -DCMAKE_CXX_CLANG_TIDY="clang-tidy;--warnings-as-errors=cert-*,bugfinders:*" ... +# # NOTE: only enable --warnings-as-errors once existing findings are resolved. + +Language: c++ +LanguageStandard: c++20 + +# Only lint the library's own sources/headers; skip gtest, vcpkg and system headers. +HeaderFilterRegex: '(^|[/\\])(src|include)[/\\].*$' + +Checks: |- + +bugfinders:*, + +modernize:*, + +readability:*, + +perf:*, + +portability:*, + # Naming is tuned below to the project's lowercase / snake_case convention. + -readability-identifier-naming, + # Existing style: single-statement branches omit braces, explicit socket types + # are used deliberately, and a few magic numbers remain. Silence those to keep + # the focus on real issues rather than style churn. + -readability-braces-around-statements, + -readability-inconsistent-control-flow, + -readability-magic-numbers, + -readability-non-const-parameter, + -readability-function-constant-members, + -readability-uppercase-literal-suffix, + -modernize-use-auto, + -modernize-pass-by-value + +readability-identifier-naming: + Case: linux + Class: '[a-z][a-z0-9_]*' + Struct: '[a-z][a-z0-9_]*' + EnumName: '[a-z][a-z0-9_]*' + Enumerator: '[a-z][a-z0-9_]*' + Function: '[a-z][a-z0-9_]*' + Variable: '[a-z][a-z0-9_]*' + Member: '[a-z][a-z0-9_]*' + StaticMember: '[a-z][a-z0-9_]*' + StaticVariable: '[a-z][a-z0-9_]*' + Parameter: '[a-z][a-z0-9_]*' + LocalVariable: '[a-z][a-z0-9_]*' + EnumConstantName: '[a-z][a-z0-9_]*' + Namespace: '[a-z][a-z0-9_]*' + MemberAllowedPrefixes: ['_', 'm_'] + StaticMemberAllowedPrefixes: ['_', 'm_'] + LocalVariableAllowedPrefixes: ['_', 'm_'] + +... diff --git a/.gitignore b/.gitignore index 080e999..0faf0b3 100644 --- a/.gitignore +++ b/.gitignore @@ -55,7 +55,6 @@ _deps .vs/ .idea/ -cmake-build-*/ -out/ +build/** # End of https://www.toptal.com/developers/gitignore/api/c++,cmake \ No newline at end of file diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..a0a57f3 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "vcpkg"] + path = vcpkg + url = https://github.com/microsoft/vcpkg.git diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..da19fa5 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,106 @@ +# AGENTS.md + +**netcpp** — a **simple C++20 network library** for Windows, Linux, and macOS. + +- **Repo**: (main branch: `develop`, synced with `origin/develop`) +- **Version**: `0.4` (`project(netcpp VERSION 0.4 ...)` in root `CMakeLists.txt`) +- **Distribution**: published as a [vcpkg](https://github.com/microsoft/vcpkg) port + +``` +netcpp/ +├── include/net/*.hpp # public headers (API) +├── src/*.cpp # implementation (1:1 with headers) +├── test/*.cpp # GTest unit tests (1:1 with sources + main.cpp) +├── build/ # CMake build artifacts (git-ignored) +└── vcpkg/ # vcpkg submodule (dependency manager) +``` + +- Language: **C++20** (`CMAKE_CXX_STANDARD 20`) +- Platforms: Windows (Winsock2 / ws2_32), Linux/macOS (liburing) +- Build: **CMake 3.23+**, vcpkg toolchain, environments managed via `CMakePresets.json` +- Tests: **GoogleTest** (FetchContent v1.15.2) + CTest; Linux builds collect coverage via codecov + +## Commands + +Pick a build environment (preset): `win-x86_64`, `linux-x86_64`, `mac-arm64` × `-debug` / `-release` + +```powershell +# Configure (uses a preset — applies the vcpkg toolchain automatically) +cmake --preset win-x86_64-release + +# Build +cmake --build build/win-x86_64-release --config Release + +# Run tests (via CTest) +cmake --build build/win-x86_64-release --target test +# or +ctest --test-dir build/win-x86_64-release + +# Install (for use in another project) +cmake --install build/win-x86_64-release --prefix +``` + +Key CMake options (`-D`): + +| Option | Description | +|--------|-------------| +| `NETCPP_BUILD_SHARED` | Build as a shared library (default: static) | +| `NETCPP_TEST` | Include unit tests in the build (default: `ON`) | + +Consume the library from another project: + +```cmake +find_package(netcpp CONFIG REQUIRED) +target_link_libraries(main PRIVATE netcpp::netcpp) +``` + +## Project layout & module conventions + +- **1:1 file rule**: `include/net/X.hpp` ↔ `src/X.cpp` ↔ `test/X_tests.cpp` (e.g. `socket` → `socket.cpp` → `socket_tests.cpp`). When adding a new component, add all three files together. +- **Namespace**: all code lives inside `namespace net`. +- **Public API**: keep headers under `include/net/` only, and mark them with `NETCPP_API` (export/import). +- **Platform branching**: split Windows/Linux with `#ifdef _WIN32`. Windows uses OVERLAPPED + IOCP; Linux uses io_uring. +- **Dependencies**: Windows=`ws2_32` (Winsock2), Linux/POSIX=`liburing`. Declared in the root `vcpkg.json` manifest and installed through the vcpkg toolchain (`CMAKE_TOOLCHAIN_FILE` set in `CMakePresets.json`). `liburing` is consumed via `pkg_check_modules` (the vcpkg `liburing` port ships only a pkg-config file, not a CMake config). + +## C++ style + +- Follow **C++20**. Prefer standard containers/views (`std::span`, `std::optional`, `std::function`). +- Use `#pragma once` in headers. +- Include order: standard headers → project headers (`net/...`) → platform headers. +- Mark public class members explicitly with `public:`/`private:` sections. +- **Identifier naming**: lowercase `snake_case` for functions, variables, members, enums, and namespaces. Enforced by `.clang-tidy` (`Case: linux`); member prefixes `_` / `m_` are allowed. +- **Linting**: a tuned `.clang-tidy` config exists at the repo root (C++20, cross-platform; lints only `src/` + `include/`). Run manually with `clang-tidy -p build/ src/.cpp`. There is **no `.clang-format`** yet — formatting is done manually and kept uniform. + +## Tests + +- Framework: **GoogleTest + GoogleMock**; the entry point is `test/main.cpp` (calls `net::native::initialize()` then `RUN_ALL_TESTS`). +- File naming: `test/_tests.cpp` (e.g. `socket_tests.cpp`). +- Tests are placed 1:1 with the source and only build when `NETCPP_TEST=ON`. +- Linux builds enable code coverage (`--coverage` / `-fcoverage-mapping`) and upload it to codecov. + +## CI + +- `.github/workflows/windows.yml` and `.github/workflows/linux.yml` — build + run tests on push/PR. +- `.github/workflows/cov.yml` — upload coverage to Codecov; runs on `release`, configures bare CMake with `g++-10` + `liburing-dev` (no vcpkg toolchain / preset). +- macOS is configured via presets but has **no CI** job. + +## Git + +- Commit messages are currently written in casual English (`Fix receive event bug`, `Change accpet async logic`, etc.). +- **Proposed (needs confirmation)**: adopt Conventional Commits (`feat:`, `fix:`, `docs:`, `refactor:`, `test:`). +- Branches: `develop` is the main development branch, synced with `origin/develop`. (`release` is used for coverage builds.) +- `vcpkg` is managed as a git submodule (`.gitmodules`). + +## Editor tip + +- `compile_commands.json` is generated under `build/*/`; IDE IntelliSense (e.g. CLion) reads it. +- On Windows, CLion's WSL/Remote integration applies the vcpkg toolchain automatically. + +--- + +## Open items / to confirm + +- **Formatter**: `.clang-tidy` exists, but there is still **no `.clang-format`**. Decide whether to add one (and wire `clang-format` into CI). +- **Commit convention**: still casual English — confirm whether to formalize Conventional Commits (`feat:`, `fix:`, `docs:`, `refactor:`, `test:`). +- **Minimum compiler docs**: README lists Windows = VS 2019, Linux = Clang 12 / GCC 10; CMake requires 3.23+ and CI uses `g++-10`. These are consistent axes, but keep the README in sync with the toolchains actually tested. (VS 2019's C++20 support is limited — verify it still builds, otherwise bump the stated minimum.) +- **README vs platforms**: README says "It supports windows and linux platform," but `CMakePresets.json` and the non-Windows compile path include **macOS**. Consider updating the README to list macOS. diff --git a/CMakePresets.json b/CMakePresets.json new file mode 100644 index 0000000..3e67aaa --- /dev/null +++ b/CMakePresets.json @@ -0,0 +1,71 @@ +{ + "version": 4, + "configurePresets": [ + { + "name": "win-x86_64-debug", + "displayName": "Windows x86_64 Debug", + "description": "vcpkg toolchain, x64-windows triplet", + "binaryDir": "${sourceDir}/build/${presetName}", + "cacheVariables": { + "CMAKE_TOOLCHAIN_FILE": "vcpkg/scripts/buildsystems/vcpkg.cmake", + "VCPKG_TARGET_TRIPLET": "x64-windows", + "CMAKE_BUILD_TYPE": "Debug" + } + }, + { + "name": "win-x86_64-release", + "displayName": "Windows x86_64 Release", + "description": "vcpkg toolchain, x64-windows-release triplet", + "binaryDir": "${sourceDir}/build/${presetName}", + "cacheVariables": { + "CMAKE_TOOLCHAIN_FILE": "vcpkg/scripts/buildsystems/vcpkg.cmake", + "VCPKG_TARGET_TRIPLET": "x64-windows-release", + "CMAKE_BUILD_TYPE": "Release" + } + }, + { + "name": "linux-x86_64-debug", + "displayName": "Linux x86_64 Debug", + "description": "vcpkg toolchain, x64-linux triplet", + "binaryDir": "${sourceDir}/build/${presetName}", + "cacheVariables": { + "CMAKE_TOOLCHAIN_FILE": "vcpkg/scripts/buildsystems/vcpkg.cmake", + "VCPKG_TARGET_TRIPLET": "x64-linux", + "CMAKE_BUILD_TYPE": "Debug" + } + }, + { + "name": "linux-x86_64-release", + "displayName": "Linux x86_64 Release", + "description": "vcpkg toolchain, x64-linux-release triplet", + "binaryDir": "${sourceDir}/build/${presetName}", + "cacheVariables": { + "CMAKE_TOOLCHAIN_FILE": "vcpkg/scripts/buildsystems/vcpkg.cmake", + "VCPKG_TARGET_TRIPLET": "x64-linux-release", + "CMAKE_BUILD_TYPE": "Release" + } + }, + { + "name": "mac-arm64-debug", + "displayName": "macOS arm64 Debug", + "description": "vcpkg toolchain, arm64-osx triplet", + "binaryDir": "${sourceDir}/build/${presetName}", + "cacheVariables": { + "CMAKE_TOOLCHAIN_FILE": "vcpkg/scripts/buildsystems/vcpkg.cmake", + "VCPKG_TARGET_TRIPLET": "arm64-osx", + "CMAKE_BUILD_TYPE": "Debug" + } + }, + { + "name": "mac-arm64-release", + "displayName": "macOS arm64 Release", + "description": "vcpkg toolchain, arm64-osx-release triplet", + "binaryDir": "${sourceDir}/build/${presetName}", + "cacheVariables": { + "CMAKE_TOOLCHAIN_FILE": "vcpkg/scripts/buildsystems/vcpkg.cmake", + "VCPKG_TARGET_TRIPLET": "arm64-osx-release", + "CMAKE_BUILD_TYPE": "Release" + } + } + ] +} diff --git a/README_ko_KR.md b/README.ko.md similarity index 90% rename from README_ko_KR.md rename to README.ko.md index 7b46e78..07a3335 100644 --- a/README_ko_KR.md +++ b/README.ko.md @@ -1,6 +1,6 @@ # netcpp ![windows](https://github.com/index1207/netcpp/actions/workflows/windows.yml/badge.svg) ![linux](https://github.com/index1207/netcpp/actions/workflows/linux.yml/badge.svg) [![codecov](https://codecov.io/gh/index1207/netcpp/graph/badge.svg?_token=BVVUC5S422)](https://codecov.io/gh/index1207/netcpp) ![lang](https://img.shields.io/badge/language-C++20-blue) [![Vcpkg package](https://img.shields.io/badge/vcpkg-0.5.0-yellow)](https://github.com/microsoft/vcpkg/tree/master/ports/netcpp) [![License](https://img.shields.io/github/license/index1207/netcpp.svg)](LICENSE) [[돌아가기]](https://github.com/index1207/netcpp)
-netcpp는 간단하게 사용할 수 있는 크로스플랫폼 C++ 네트워크 라이브러리로, Windows와 Linux 플랫폼을 지원합니다. +netcpp는 간단하게 사용할 수 있는 크로스플랫폼 C++ 네트워크 라이브러리로, Windows·Linux·macOS 플랫폼을 지원합니다. ## 설치 이 라이브러리는 [vcpkg](https://github.com/microsoft/vcpkg)포트를 지원합니다. 만약 이미 vcpkg가 설치되어 있다면 아래의 명령줄을 통해 설치가 가능합니다. @@ -61,7 +61,7 @@ sock.connect(&connect_ctx); // 지정된 엔드포인트에 연결 시도 - 기본 연결 ```cpp // Server -#include +#include #include int main() @@ -111,10 +111,10 @@ net::dns::get_host_entry("www.example.com") // www.example.com의 호스트 엔 ```cpp try { if (!sock.connect(ENDPOINT)) - throw net::network_exception("connect()"); + throw net::exception("connect()"); } catch(std::exception& e) { - std::cout << e.what() << std::endl; // connect(): 요청된 주소를 할당할 수 없습니다. [10049] + std::cout << e.what() << std::endl; // connect(): 요청된 주소를 할당할 수 없습니다. } ``` @@ -123,13 +123,18 @@ catch(std::exception& e) { |---------|----------| | Windows | Winsock2 | | Linux | liburing | +| macOS | liburing | ## 기여 이 레포지토리는 언제나 이슈나 PR을 환영합니다! ## 최소 컴파일러 버전 + +이 라이브러리는 **CMake 3.23+** 가 필요하며 **C++20**을 타겟으로 합니다. + - Windows - - Visual Studio 2019 + - Visual Studio 2019 16.10+ (Visual Studio 2022 권장) - Linux - - Clang 12 - - GCC 10 \ No newline at end of file + - GCC 10 / Clang 12 (CI에서는 g++-10 사용) +- macOS + - Apple Clang (Xcode 13+) \ No newline at end of file diff --git a/README.md b/README.md index ff3cea2..ff8d674 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # netcpp ![windows](https://github.com/index1207/netcpp/actions/workflows/windows.yml/badge.svg) ![linux](https://github.com/index1207/netcpp/actions/workflows/linux.yml/badge.svg) [![codecov](https://codecov.io/gh/index1207/netcpp/graph/badge.svg?_token=BVVUC5S422)](https://codecov.io/gh/index1207/netcpp) ![lang](https://img.shields.io/badge/language-C++20-blue) [![Vcpkg package](https://img.shields.io/badge/vcpkg-0.5.0-yellow)](https://github.com/microsoft/vcpkg/tree/master/ports/netcpp) [![License](https://img.shields.io/github/license/index1207/netcpp.svg)](LICENSE) -[[한국어]](README_ko_KR.md)
-netcpp is **simple** C++ network library. -It supports windows and linux platform. +[[한국어]](README.ko.md)
+netcpp is a **simple** cross-platform C++ network library. +It supports Windows, Linux, and macOS. ## Installation This library supports [vcpkg](https://github.com/microsoft/vcpkg) port. If you had already installed vcpkg, You can install this package simply with the command line below. @@ -62,7 +62,7 @@ sock.connect(&connect_ctx); // Connect to specified endpoint asynchronously. - Basic connection ```cpp // Server -#include +#include #include int main() @@ -112,10 +112,10 @@ net::dns::get_host_entry("www.example.com") // get www.example.com's host entry ```cpp try { if (!sock.connect(ENDPOINT)) - throw net::network_exception("connect()"); + throw net::exception("connect()"); } catch(std::exception& e) { - std::cout << e.what() << std::endl; // connect(): Cannot assign requested address. [10049] + std::cout << e.what() << std::endl; // connect(): Cannot assign requested address. } ``` @@ -124,13 +124,18 @@ catch(std::exception& e) { |---------|----------| | Windows | Winsock2 | | Linux | liburing | +| macOS | liburing | ## Contribute The repository is whenever welcome any issues or PRs! ## Minimum required compiler version + +The library requires **CMake 3.23+** and targets **C++20**. + - Windows - - Visual Studio 2019 + - Visual Studio 2019 16.10+ (Visual Studio 2022 recommended) - Linux - - Clang 12 - - GCC 10 \ No newline at end of file + - GCC 10 / Clang 12 (CI uses g++-10) +- macOS + - Apple Clang (Xcode 13+) \ No newline at end of file diff --git a/include/net/context.hpp b/include/net/context.hpp index 2786e15..87cdef3 100644 --- a/include/net/context.hpp +++ b/include/net/context.hpp @@ -51,6 +51,9 @@ namespace net std::vector _buffer_list; #else std::vector _buffer_list; + // Must outlive the submitted SQE: io_uring may read the msghdr after + // io_uring_submit() returns (when the request is punted to io-wq). + msghdr _msg; #endif void* _token; diff --git a/src/context.cpp b/src/context.cpp index 42f1487..51427ca 100644 --- a/src/context.cpp +++ b/src/context.cpp @@ -17,6 +17,8 @@ void context::init() { #ifdef _WIN32 ZeroMemory(this, sizeof(OVERLAPPED)); +#else + ZeroMemory(&_msg, sizeof(_msg)); #endif _io_type = io_type::none; } diff --git a/src/socket.cpp b/src/socket.cpp index a756241..f69f31e 100644 --- a/src/socket.cpp +++ b/src/socket.cpp @@ -157,9 +157,9 @@ bool socket::connect(context* context) context->_token = static_cast(this); - ip_address ipAdr = context->endpoint->get_address(); + const ip_address& ipAdr = context->endpoint->get_address(); DWORD dw; - if (!native::connect(_sock, reinterpret_cast(&ipAdr), sizeof(SOCKADDR_IN), nullptr, NULL, &dw, + if (!native::connect(_sock, reinterpret_cast(&ipAdr), sizeof(SOCKADDR_IN), nullptr, NULL, &dw, reinterpret_cast(context))) { const auto err = WSAGetLastError(); @@ -169,8 +169,10 @@ bool socket::connect(context* context) auto uring = native::get_handle(); auto sqe = io_uring_get_sqe(uring); - auto addr = context->endpoint->get_address(); - io_uring_prep_connect(sqe, get_handle(), reinterpret_cast(&addr), sizeof(sockaddr_in)); + // Bound by reference: io_uring may read the sockaddr after this function + // returns, so it must live in the context, not in this frame. + const auto& addr = context->endpoint->get_address(); + io_uring_prep_connect(sqe, get_handle(), reinterpret_cast(&addr), sizeof(sockaddr_in)); io_uring_sqe_set_data(sqe, context); io_uring_submit(uring); #endif @@ -214,7 +216,7 @@ bool socket::send(context* context) const } else { - msghdr msg {}; + auto& msg = context->_msg; msg.msg_iov = context->_buffer_list.data(); msg.msg_iovlen = context->_buffer_list.size(); io_uring_prep_sendmsg(sqe, _sock, &msg, 0); @@ -264,7 +266,7 @@ bool socket::receive(context* context) const } else { - msghdr msg {}; + auto& msg = context->_msg; msg.msg_iov = context->_buffer_list.data(); msg.msg_iovlen = context->_buffer_list.size(); io_uring_prep_recvmsg(sqe, get_handle(), &msg, 0); diff --git a/test/dns_tests.cpp b/test/dns_tests.cpp index 4256b16..3b7c1da 100644 --- a/test/dns_tests.cpp +++ b/test/dns_tests.cpp @@ -11,7 +11,7 @@ TEST(dns, get_host_entry_url) { auto youtubeEntry = net::dns::get_host_entry("www.youtube.com"); EXPECT_GT(youtubeEntry.address_list.size(), 0); - EXPECT_GT(youtubeEntry.alias_list.size(), 0); + EXPECT_NE(youtubeEntry.host_name, ""); } TEST(dns, get_host_entry_address) diff --git a/test/socket_tests.cpp b/test/socket_tests.cpp index cf012cb..13fe522 100644 --- a/test/socket_tests.cpp +++ b/test/socket_tests.cpp @@ -5,11 +5,29 @@ #include "net/context.hpp" #include +#include +#include #define TEST_ENDPOINT net::endpoint(net::ip_address::loopback, 8888) using namespace std::chrono_literals; +#ifdef _MSC_VER +#define NETCPP_NOINLINE __declspec(noinline) +#else +#define NETCPP_NOINLINE __attribute__((noinline)) +#endif + +// Overwrites the stack region a just-returned callee was using. Async backends +// keep reading caller-supplied structs (sockaddr, msghdr) after the submitting +// function returns, so anything they point at must not live in a dead frame. +NETCPP_NOINLINE static void clobber_callee_stack() +{ + volatile unsigned char scratch[1024]; + for (size_t i = 0; i < sizeof(scratch); ++i) + scratch[i] = 0xAB; +} + TEST(socket, open) { net::socket s1(net::protocol::tcp); @@ -103,6 +121,32 @@ TEST(socket, async_connect) EXPECT_EQ(flag.load(), true); } +TEST(socket, async_connect_stack_reuse) +{ + net::socket sock(net::protocol::tcp); + EXPECT_EQ(sock.is_open(), true); + + auto httpsPort = 443; + auto example = "www.example.com"; + auto entry = net::dns::get_host_entry(example); + EXPECT_GT(entry.address_list.size(), 0); + + net::endpoint endpoint(entry.address_list[0], httpsPort); + std::atomic> flag; + net::context ctx; + ctx.endpoint = endpoint; + ctx.completed = [&flag](net::context*, bool success) { + flag = success; + }; + EXPECT_EQ(sock.connect(&ctx), true); + + // The target address must survive connect() returning. + clobber_callee_stack(); + + while (!flag.load().has_value()) {} + EXPECT_EQ(flag.load(), true); +} + TEST(socket, bind) { net::socket sock(net::protocol::tcp); @@ -326,6 +370,15 @@ TEST(socket, sync_sendto) EXPECT_GE(client.send(buffer, TEST_ENDPOINT), 0); } +TEST(socket, sync_send_failure) +{ + net::socket sock; + EXPECT_EQ(sock.is_open(), false); + + char buffer[] = "Hello"; + EXPECT_EQ(sock.send(buffer), false); +} + TEST(socket, sync_receive) { auto server = std::async(std::launch::async, [] { @@ -394,6 +447,52 @@ TEST(socket, async_receive) EXPECT_EQ(client.get(), true); } +TEST(socket, async_receive_buffer_list) +{ + auto server = std::async(std::launch::async, [] { + net::socket sock(net::protocol::tcp); + EXPECT_EQ(sock.is_open(), true); + EXPECT_EQ(sock.set_reuse_address(true), true); + EXPECT_EQ(sock.bind(TEST_ENDPOINT), true); + EXPECT_EQ(sock.listen(), true); + + auto client = sock.accept(); + EXPECT_EQ(client.is_open(), true); + + std::string data = "HelloWorld"; + EXPECT_GT(client.send(data), 0); + }); + + std::this_thread::sleep_for(100ms); + + auto client = std::async(std::launch::async, [&] { + std::atomic> flag; + net::socket sock(net::protocol::tcp); + EXPECT_EQ(sock.is_open(), true); + EXPECT_EQ(sock.connect(TEST_ENDPOINT), true); + + auto ctx = new net::context; + char first[5] = { 0, }, second[5] = { 0, }; + ctx->add_data(first); + ctx->add_data(second); + ctx->completed = [&flag](net::context* ctx, bool success) { + flag = success && ctx->length > 0; + }; + EXPECT_EQ(sock.receive(ctx), true); + while (!flag.load().has_value()) {} + + // the payload has to be scattered across both buffers + EXPECT_EQ(std::string(first, 5), "Hello"); + EXPECT_EQ(std::string(second, 5), "World"); + + delete ctx; + return flag.load(); + }); + + server.get(); + EXPECT_EQ(client.get(), true); +} + TEST(socket, sync_receive_from) { auto server = std::async(std::launch::async, [] { diff --git a/vcpkg b/vcpkg new file mode 160000 index 0000000..04a9d8e --- /dev/null +++ b/vcpkg @@ -0,0 +1 @@ +Subproject commit 04a9d8e5212d01ee1dd9478eadd9caade4f8b0d4 diff --git a/vcpkg.json b/vcpkg.json new file mode 100644 index 0000000..35b972e --- /dev/null +++ b/vcpkg.json @@ -0,0 +1,13 @@ +{ + "name": "netcpp", + "version": "0.5", + "description": "A simple C++20 network library for Windows, Linux and macOS.", + "homepage": "https://github.com/index1207/netcpp", + "license": "MIT", + "dependencies": [ + { + "name": "liburing", + "platform": "!windows" + } + ] +}