diff --git a/CMakeLists.txt b/CMakeLists.txt index 646df23..65ba70a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,10 +1,8 @@ cmake_minimum_required(VERSION 3.28) -project(netkit LANGUAGES C CXX) +project(netkit LANGUAGES CXX) option(NETKIT_ENABLE_WOLFSSL "Enable WolfSSL support in netkit" ON) option(NETKIT_ENABLE_TESTS "Enable building tests" OFF) -option(NETKIT_ENABLE_C_BINDINGS "Enable experimental C bindings for netkit" OFF) -option(NETKIT_ENABLE_C_TESTS "Enable C building tests" OFF) option(NETKIT_ENABLE_WINDOWS_CERTSTORE "Enable getting CA certificates from the Windows store" ON) option(NETKIT_ENABLE_FALLBACK_CA "Enable fallback CA certficate (required for DevkitPro)" ON) option(NETKIT_ENABLE_SOCK_CUSTOM_RESOLVER "Enable using netkit's DNS resolver instead of the system resolver" OFF) @@ -304,83 +302,6 @@ if (NETKIT_ENABLE_TESTS) catch_discover_tests(netkit-tests) endif() -if (NETKIT_ENABLE_C_BINDINGS) - message(STATUS "C bindings enabled") - add_library(netkit-c ${NETKIT_LIB_TYPE} - src/c/sock/addr.cpp - src/c/sock/sync_sock.cpp - src/c/sock/ssl_sync_sock.cpp - src/c/network/utility.cpp - ) - - set_target_properties(netkit-c PROPERTIES - EXPORT_NAME netkit-c - POSITION_INDEPENDENT_CODE ON - CXX_VISIBILITY_PRESET hidden - VISIBILITY_INLINES_HIDDEN ON - VERSION 0.1.0 - SOVERSION 1 - ) - - if (NETKIT_BUILD_SHARED) - target_compile_definitions(netkit-c PUBLIC NETKIT_C_SHARED) - endif() - - if (WIN32 AND NETKIT_BUILD_SHARED) - target_compile_definitions(netkit-c - PRIVATE NETKIT_C_BUILD_DLL - ) - endif() - - target_link_libraries(netkit-c - PUBLIC netkit - ) - - target_include_directories(netkit-c - PUBLIC - $ - $ - ) - - install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/include/netkit-c/ - DESTINATION include/netkit-c - FILES_MATCHING - PATTERN "*.h" - ) - - install(TARGETS netkit-c - EXPORT netkitTargets - RUNTIME DESTINATION bin - LIBRARY DESTINATION lib - ARCHIVE DESTINATION lib - ) - - if (NETKIT_ENABLE_C_TESTS) - message(STATUS "C API tests enabled") - - add_executable(netkit-c-tests - tests/c/test_sock_addr.c - tests/c/test_network_utility.c - tests/c/test_main.c - ) - - add_dependencies(netkit-c-tests - netkit - netkit-c - ) - - target_link_libraries(netkit-c-tests - PRIVATE netkit netkit-c - ) - - add_test(NAME netkit-c-tests COMMAND netkit-c-tests) - else() - message(STATUS "C API tests disabled") - endif() -else() - message(STATUS "C bindings disabled") -endif() - if (NETKIT_BUILD_EXAMPLES) - add_subdirectory(examples/cpp) + add_subdirectory(examples) endif() \ No newline at end of file diff --git a/README.md b/README.md index acb87b2..3f9f2d5 100644 --- a/README.md +++ b/README.md @@ -14,8 +14,8 @@ The other alternative is to use the latest release, which doesn't have a changin ## Features -- OS-independent socket abstractions, both synchronous and asynchronous -- Higher-level socket abstractions +- OS-independent socket abstractions, both synchronous and asynchronous using C++20 coroutines +- Higher-level socket abstractions, including TCP, UDP and UDS - HTTP/1.0 and HTTP/1.1 body parser, including headers and body. - IPv4 and IPv6 support - TCP and UDP support @@ -24,18 +24,11 @@ The other alternative is to use the latest release, which doesn't have a changin - Network interface enumeration - Exceptions for errors - Inheritable classes for easy extension -- Designed for C++23, with optional C bindings for use in non-C++ projects and interoperability with other programming languages entirely +- Designed for C++23 - Support for Windows, Linux, macOS and other Unix-compatible systems. - Support for DevkitPro (Wii and GameCube) - Permissive MIT license, allowing use in both open source and proprietary software. -Still missing: - -- Asynchronous I/O for non-Linux platforms - - Threaded fallback is available -- Schannel support for Windows (waste of time I reckon) -- WebSocket abstraction - ## Dependencies - WolfSSL (optional) @@ -48,8 +41,6 @@ netkit's CMakeLists.txt offers multiple options: - NETKIT_ENABLE_WOLFSSL: Enable WolfSSL-backed SSL/TLS - NETKIT_ENABLE_TESTS: Enable Catch2 tests for the main C++ library -- NETKIT_ENABLE_C_BINDINGS: Enable C bindings for netkit -- NETKIT_ENABLE_C_TESTS: Enable tests for netkit C bindings - NETKIT_ENABLE_WINDOWS_CERTSTORE: Enable getting CA certificates from the Windows store - NETKIT_ENABLE_FALLBACK_CA: Enable fallback hardcoded CA certificate (required for DevkitPro with TLS enabled) - NETKIT_WOLFSSL_DEBUG: Enable debugging for WolfSSL and netkit WolfSSL functions @@ -59,7 +50,7 @@ netkit's CMakeLists.txt offers multiple options: ```bash mkdir -p build/; cd build/ -cmake .. -DCMAKE_BUILD_TYPE=Release # if using devkitpro, -DCMAKE_TOOLCHAIN_FILE=${DEVKITPRO}/cmake/Wii.cmake +cmake .. -DCMAKE_BUILD_TYPE=Release # if using devkitpro, -DCMAKE_TOOLCHAIN_FILE=${DEVKITPRO:-/opt/devkitpro}/cmake/Wii.cmake cmake --build . cmake --install . ``` @@ -84,9 +75,7 @@ target_link_libraries(netkit-example PRIVATE ... ``` -If you wish to use the C bindings, link with `netkit::netkit-c` instead. - -See `examples/c/` and `examples/cpp/` for further examples of how to use the library. +See `examples/` for further examples of how to use the library. Netkit can also be statically linked, and for users of DevkitPro it will be automatically. diff --git a/examples/cpp/CMakeLists.txt b/examples/CMakeLists.txt similarity index 71% rename from examples/cpp/CMakeLists.txt rename to examples/CMakeLists.txt index 7dc2d6e..72a7229 100644 --- a/examples/cpp/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -1,4 +1,4 @@ -file(GLOB children RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} *) +file(GLOB children RELATIVE cpp *) foreach(child ${children}) if (IS_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/${child}) add_subdirectory(${child}) diff --git a/examples/c/socket/.gitignore b/examples/buffer_body/.gitignore similarity index 100% rename from examples/c/socket/.gitignore rename to examples/buffer_body/.gitignore diff --git a/examples/cpp/buffer_body/CMakeLists.txt b/examples/buffer_body/CMakeLists.txt similarity index 100% rename from examples/cpp/buffer_body/CMakeLists.txt rename to examples/buffer_body/CMakeLists.txt diff --git a/examples/cpp/buffer_body/main.cpp b/examples/buffer_body/main.cpp similarity index 100% rename from examples/cpp/buffer_body/main.cpp rename to examples/buffer_body/main.cpp diff --git a/examples/c/socket/CMakeLists.txt b/examples/c/socket/CMakeLists.txt deleted file mode 100644 index dc85081..0000000 --- a/examples/c/socket/CMakeLists.txt +++ /dev/null @@ -1,15 +0,0 @@ -cmake_minimum_required(VERSION 3.11) - -project(netkit-example LANGUAGES C) -set(CMAKE_C_STANDARD 99) -set(CMAKE_C_STANDARD_REQUIRED ON) -set(CMAKE_C_EXTENSIONS OFF) -set(CMAKE_EXPORT_COMPILE_COMMANDS ON) - -find_package(netkit REQUIRED) - -add_executable( - netkit-example - main.c -) -target_link_libraries(netkit-example PRIVATE netkit::netkit-c) diff --git a/examples/c/socket/main.c b/examples/c/socket/main.c deleted file mode 100644 index df4ef81..0000000 --- a/examples/c/socket/main.c +++ /dev/null @@ -1,67 +0,0 @@ -/** netkit - * C++23 cross-platform networking toolkit library providing safe Unix-style sockets and protocol abstractions. - * - * Copyright (c) 2025-2026 Jacob Nilsson - * Licensed under the MIT License. - * - * @file main.c - * @license MIT - * @note Example code using the Netkit library. - * @brief A lower-level example demonstrating the usage of sync_sock to make a simple HTTP request. - */ -#include -#include -#include -#include -#include -#include - -int main(void) { - netkit_sock_addr_t* addr = netkit_sock_addr_create("google.com", 80, SOCK_ADDR_HOSTNAME); - if (!addr) { - return 1; - } - - netkit_sync_sock_t* sock = netkit_sync_sock_create(addr, SOCK_TCP, SOCK_OPT_NONE); - if (!sock) { - fprintf(stderr, "%s\n", "Failed to create socket."); - return 1; - } - - if (netkit_sync_sock_connect(sock) != SOCK_STATUS_SUCCESS) { - fprintf(stderr, "%s\n", "Failed to connect."); - } - - char* buf = "GET / HTTP/1.1\r\nHost: google.com\r\nConnection: close\r\n\r\n"; - - if (!netkit_sync_sock_send(sock, buf, strlen(buf))) { - fprintf(stderr, "%s\n", "Failed to send."); - } - - netkit_recv_result_t* result = netkit_recv_result_create(); - if (!result) { - fprintf(stderr, "%s\n", "Failed to create recv_result"); - return 1; - } - - netkit_recv_status_t status = netkit_sync_sock_recv(sock, result, 5, "", 0); - if (status == RECV_ERROR) { - fprintf(stderr, "Error.\n"); - return 1; - } else if (status == RECV_TIMEOUT) { - fprintf(stderr, "Timeout.\n"); - return 1; - } - netkit_sync_sock_close(sock); - - if (result->data) { - fprintf(stdout, "%s\n", result->data); - } else { - fprintf(stderr, "%s\n", "result->data == NULL"); - return 1; - } - - netkit_recv_result_destroy(result); - netkit_sock_addr_destroy(addr); - netkit_sync_sock_destroy(sock); -} \ No newline at end of file diff --git a/examples/c/socket_ssl/CMakeLists.txt b/examples/c/socket_ssl/CMakeLists.txt deleted file mode 100644 index 643c8c7..0000000 --- a/examples/c/socket_ssl/CMakeLists.txt +++ /dev/null @@ -1,22 +0,0 @@ -cmake_minimum_required(VERSION 3.11) - -project(netkit-example LANGUAGES C CXX) -set(CMAKE_C_STANDARD 99) -set(CMAKE_C_STANDARD_REQUIRED ON) -set(CMAKE_C_EXTENSIONS OFF) -set(CMAKE_EXPORT_COMPILE_COMMANDS ON) - -find_package(netkit) - -add_executable( - netkit-example - main.c -) - -set_target_properties(netkit-example PROPERTIES - LINKER_LANGUAGE CXX -) - -target_link_libraries(netkit-example PRIVATE netkit::netkit-c netkit::netkit) - -ogc_create_dol(netkit-example) diff --git a/examples/c/socket_ssl/main.c b/examples/c/socket_ssl/main.c deleted file mode 100644 index fe02b16..0000000 --- a/examples/c/socket_ssl/main.c +++ /dev/null @@ -1,108 +0,0 @@ -/** netkit - * C++23 cross-platform networking toolkit library providing safe Unix-style sockets and protocol abstractions. - * - * Copyright (c) 2025-2026 Jacob Nilsson - * Licensed under the MIT License. - * - * @file main.c - * @license MIT - * @note Example code using the Netkit library. - * @brief A lower-level example demonstrating the usage of ssl_sync_sock to make a simple HTTP request with TLS/SSL support. - */ -#include -#include -#include -#include -#include -#include -#include - -#define MAX_TRIES 3 - -int main(void) { - netkit_sock_addr_t* addr = netkit_sock_addr_create("www.google.com", 443, SOCK_ADDR_HOSTNAME); - if (!addr) { - fprintf(stderr, "%s\n", "Failed to create addr"); - return 1; - } - - netkit_sync_sock_t* sock = netkit_sync_sock_create(addr, SOCK_TCP, SOCK_OPT_NONE); - if (!sock) { - fprintf(stderr, "%s\n", "Failed to create socket."); - return 1; - } - - if (netkit_sync_sock_connect(sock) != SOCK_STATUS_SUCCESS) { - fprintf(stderr, "%s\n", "Failed to connect."); - return 1; - } - - netkit_ssl_sync_sock_t* ssl_sock = netkit_ssl_sync_sock_create( - sock, - NETKIT_SSL_SYNC_SOCK_MODE_CLIENT, - NETKIT_SSL_SYNC_SOCK_VERSION_TLS_1_3, - NETKIT_SSL_SYNC_SOCK_VERIFICATION_PEER, - NULL, - NULL - ); - if (!ssl_sock) { - fprintf(stderr, "%s\n", "Failed to create SSL sync sock."); - return 1; - } - - if (netkit_ssl_sync_sock_perform_handshake(ssl_sock)) { - fprintf(stderr, "%s\n", "Failed to perform handshake."); - return 1; - } - - char* buf = "GET / HTTP/1.1\r\nHost: www.google.com\r\nConnection: close\r\n\r\n"; - - if (!netkit_ssl_sync_sock_send(ssl_sock, buf, strlen(buf))) { - fprintf(stderr, "%s\n", "Failed to send."); - return 1; - } - - netkit_recv_result_t* result = netkit_recv_result_create(); - if (!result) { - fprintf(stderr, "%s\n", "Failed to create recv_result"); - return 1; - } - - for (;;) { - netkit_recv_status_t status = netkit_ssl_sync_sock_recv(ssl_sock, result, -1, NULL, 0); - - if (status == RECV_SUCCESS) { - continue; - } - - if (status == RECV_CLOSED) { - break; - } - - if (status == RECV_TIMEOUT) { - fprintf(stderr, "timeout\n"); - break; - } - - if (status == RECV_ERROR) { - fprintf(stderr, "error\n"); - break; - } - } - - netkit_ssl_sync_sock_close(ssl_sock); - - if (result->data) { - fprintf(stdout, "%s\n", result->data); - } else { - fprintf(stderr, "%s\n", "result->data == NULL"); - return 1; - } - - netkit_recv_result_destroy(result); - netkit_sock_addr_destroy(addr); - netkit_ssl_sync_sock_destroy(ssl_sock); - netkit_sync_sock_destroy(sock); - - return 0; -} diff --git a/examples/cpp/socket_server/.gitignore b/examples/cpp/socket_server/.gitignore deleted file mode 100644 index 3c34c2f..0000000 --- a/examples/cpp/socket_server/.gitignore +++ /dev/null @@ -1 +0,0 @@ -*build* \ No newline at end of file diff --git a/examples/cpp/socket_server_async/response.txt b/examples/cpp/socket_server_async/response.txt deleted file mode 100644 index 53d06f7..0000000 --- a/examples/cpp/socket_server_async/response.txt +++ /dev/null @@ -1,19 +0,0 @@ -HTTP/1.1 301 Moved Permanently -Location: http://www.google.com/ -Content-Type: text/html; charset=UTF-8 -Content-Security-Policy-Report-Only: object-src 'none';base-uri 'self';script-src 'nonce-rtIMGGI5Lruf_cH3ypsLQQ' 'strict-dynamic' 'report-sample' 'unsafe-eval' 'unsafe-inline' https: http:;report-uri https://csp.withgoogle.com/csp/gws/other-hp -Date: Sat, 25 Jul 2026 16:31:38 GMT -Expires: Mon, 24 Aug 2026 16:31:38 GMT -Cache-Control: public, max-age=2592000 -Server: gws -Content-Length: 219 -X-XSS-Protection: 0 -X-Frame-Options: SAMEORIGIN -Connection: close - - -301 Moved -

301 Moved

-The document has moved -here. - diff --git a/examples/cpp/socket_ssl/.gitignore b/examples/cpp/socket_ssl/.gitignore deleted file mode 100644 index 3c34c2f..0000000 --- a/examples/cpp/socket_ssl/.gitignore +++ /dev/null @@ -1 +0,0 @@ -*build* \ No newline at end of file diff --git a/examples/c/socket_ssl/.gitignore b/examples/file_body/.gitignore similarity index 100% rename from examples/c/socket_ssl/.gitignore rename to examples/file_body/.gitignore diff --git a/examples/cpp/file_body/CMakeLists.txt b/examples/file_body/CMakeLists.txt similarity index 100% rename from examples/cpp/file_body/CMakeLists.txt rename to examples/file_body/CMakeLists.txt diff --git a/examples/cpp/file_body/file.txt b/examples/file_body/file.txt similarity index 100% rename from examples/cpp/file_body/file.txt rename to examples/file_body/file.txt diff --git a/examples/cpp/file_body/main.cpp b/examples/file_body/main.cpp similarity index 100% rename from examples/cpp/file_body/main.cpp rename to examples/file_body/main.cpp diff --git a/examples/cpp/buffer_body/.gitignore b/examples/http_server/.gitignore similarity index 100% rename from examples/cpp/buffer_body/.gitignore rename to examples/http_server/.gitignore diff --git a/examples/cpp/http_server/CMakeLists.txt b/examples/http_server/CMakeLists.txt similarity index 100% rename from examples/cpp/http_server/CMakeLists.txt rename to examples/http_server/CMakeLists.txt diff --git a/examples/cpp/http_server/css/index.css b/examples/http_server/css/index.css similarity index 100% rename from examples/cpp/http_server/css/index.css rename to examples/http_server/css/index.css diff --git a/examples/cpp/http_server/files/bliss.png b/examples/http_server/files/bliss.png similarity index 100% rename from examples/cpp/http_server/files/bliss.png rename to examples/http_server/files/bliss.png diff --git a/examples/cpp/http_server/index.html b/examples/http_server/index.html similarity index 100% rename from examples/cpp/http_server/index.html rename to examples/http_server/index.html diff --git a/examples/cpp/http_server/main.cpp b/examples/http_server/main.cpp similarity index 100% rename from examples/cpp/http_server/main.cpp rename to examples/http_server/main.cpp diff --git a/examples/cpp/file_body/.gitignore b/examples/multipart_parsing/.gitignore similarity index 100% rename from examples/cpp/file_body/.gitignore rename to examples/multipart_parsing/.gitignore diff --git a/examples/cpp/multipart_parsing/CMakeLists.txt b/examples/multipart_parsing/CMakeLists.txt similarity index 100% rename from examples/cpp/multipart_parsing/CMakeLists.txt rename to examples/multipart_parsing/CMakeLists.txt diff --git a/examples/cpp/multipart_parsing/main.cpp b/examples/multipart_parsing/main.cpp similarity index 100% rename from examples/cpp/multipart_parsing/main.cpp rename to examples/multipart_parsing/main.cpp diff --git a/examples/cpp/http_server/.gitignore b/examples/network_interface/.gitignore similarity index 100% rename from examples/cpp/http_server/.gitignore rename to examples/network_interface/.gitignore diff --git a/examples/cpp/network_interface/CMakeLists.txt b/examples/network_interface/CMakeLists.txt similarity index 96% rename from examples/cpp/network_interface/CMakeLists.txt rename to examples/network_interface/CMakeLists.txt index 356c9a1..0fd09df 100644 --- a/examples/cpp/network_interface/CMakeLists.txt +++ b/examples/network_interface/CMakeLists.txt @@ -1,16 +1,16 @@ -cmake_minimum_required(VERSION 3.11) - -project(network_interface LANGUAGES CXX) - -set(CMAKE_CXX_STANDARD 23) -set(CMAKE_CXX_STANDARD_REQUIRED ON) -set(CMAKE_CXX_EXTENSIONS OFF) -set(CMAKE_EXPORT_COMPILE_COMMANDS ON) - -if (NOT TARGET netkit::netkit) - find_package(netkit REQUIRED) -endif() - -add_executable(network_interface main.cpp) - +cmake_minimum_required(VERSION 3.11) + +project(network_interface LANGUAGES CXX) + +set(CMAKE_CXX_STANDARD 23) +set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_CXX_EXTENSIONS OFF) +set(CMAKE_EXPORT_COMPILE_COMMANDS ON) + +if (NOT TARGET netkit::netkit) + find_package(netkit REQUIRED) +endif() + +add_executable(network_interface main.cpp) + target_link_libraries(network_interface PRIVATE netkit::netkit) \ No newline at end of file diff --git a/examples/cpp/network_interface/main.cpp b/examples/network_interface/main.cpp similarity index 97% rename from examples/cpp/network_interface/main.cpp rename to examples/network_interface/main.cpp index 1e00573..878d58d 100644 --- a/examples/cpp/network_interface/main.cpp +++ b/examples/network_interface/main.cpp @@ -1,189 +1,189 @@ -/** netkit - * C++23 cross-platform networking toolkit library providing safe Unix-style sockets and protocol abstractions. - * - * Copyright (c) 2025-2026 Jacob Nilsson - * Licensed under the MIT License. - * - * @file main.c - * @license MIT - * @note Example code using the Netkit library. - * @brief A clone of the 'ifconfig' command that lists network interfaces and their addresses. - */ -#include -#include - -const std::string RESET = "\033[0m"; -const std::string BOLD = "\033[1m"; -const std::string GREEN = "\033[32m"; -const std::string YELLOW = "\033[33m"; -const std::string CYAN = "\033[36m"; -const std::string MAGENTA = "\033[35m"; - -int main(int argc, char** argv) { - bool use_color = true; - bool skip_v4 = false; - bool skip_v6 = false; - bool skip_inactive = false; - bool skip_broadcast = false; - bool skip_point_to_point = false; - bool skip_up = false; - bool skip_loopback = false; - bool skip_multicast = false; - bool skip_no_ipv4 = false; - bool skip_no_ipv6 = false; - bool skip_loopback_interfaces = false; - - bool is_stdout_terminal = isatty(STDOUT_FILENO); - if (!is_stdout_terminal) { - use_color = false; - } - - static const auto args = std::vector(argv, argv + argc); - for (const auto& it : args) { - if (it == "--no-color" || it == "-n") { - use_color = false; - } else if (it == "--color" || it == "-c") { - use_color = true; - } else if (it == "--skip-v4" || it == "-s4") { - skip_v4 = true; - } else if (it == "--skip-v6" || it == "-s6") { - skip_v6 = true; - } else if (it == "--skip-inactive" || it == "-si") { - skip_inactive = true; - } else if (it == "--skip-broadcast" || it == "-sb") { - skip_broadcast = true; - } else if (it == "--skip-point-to-point" || it == "-sptp") { - skip_point_to_point = true; - } else if (it == "--skip-up" || it == "-su") { - skip_up = true; - } else if (it == "--skip-loopback" || it == "-sl") { - skip_loopback = true; - } else if (it == "--skip-no-addresses" || it == "-sna") { - skip_no_ipv4 = true; - skip_no_ipv6 = true; - } else if (it == "--skip-no-ipv4" || it == "-snv4") { - skip_no_ipv4 = true; - } else if (it == "--skip-no-ipv6" || it == "-snv6") { - skip_no_ipv6 = true; - } else if (it == "--skip-loopback-interfaces" || it == "-sli") { - skip_loopback_interfaces = true; - } else if (it == "--help" || it == "-h") { - std::cout << "Usage: " << argv[0] << " [options]\n" - << "Options:\n" - << " --no-color, -n Disable colored output\n" - << " --color, -c Enable colored output (default)\n" - << " --skip-v4, -s4 Skip IPv4 addresses\n" - << " --skip-v6, -s6 Skip IPv6 addresses\n" - << " --skip-inactive, -si Skip inactive interfaces\n" - << " --skip-broadcast, -sb Skip broadcast interfaces\n" - << " --skip-point-to-point, -sptp Skip point-to-point interfaces\n" - << " --skip-up, -su Skip interfaces that are not up\n" - << " --skip-loopback, -sl Skip loopback addresses\n" - << " --skip-multicast, -sm Skip multicast addresses\n" - << " --skip-no-addresses, -sna Skip interfaces with no IPv4 or IPv6 addresses\n" - << " --skip-no-ipv4, -snv4 Skip interfaces with no IPv4 addresses\n" - << " --skip-no-ipv6, -snv6 Skip interfaces with no IPv6 addresses\n" - << " --skip-loopback-interfaces, -sli Skip loopback interfaces\n" - << " --help, -h Show this help message\n"; - return 0; - } - } - - auto list = netkit::network::get_interfaces(); - - for (const auto& iface : list) { - if (skip_inactive && !iface.is_up()) continue; - if (skip_broadcast && iface.is_broadcast()) continue; - if (skip_point_to_point && iface.is_point_to_point()) continue; - if (skip_up && !iface.is_up()) continue; - if (iface.get_ipv4_addrs().empty() && skip_no_ipv4) continue; - if (iface.get_ipv6_addrs().empty() && skip_no_ipv6) continue; - if (skip_loopback_interfaces) { - bool found = false; - for (const auto& addr : iface.get_ipv4_addrs()) { - if (addr.is_loopback()) found = true; break; - } - for (const auto& addr : iface.get_ipv6_addrs()) { - if (addr.is_loopback()) found = true; break; - } - if (found) { - continue; - } - } - - if (use_color) - std::cout << BOLD << CYAN; - std::cout << "Interface: " << iface.get_name(); - if (use_color) - std::cout << RESET; - std::cout << "\n"; - - iface.is_broadcast() ? std::cout << " Broadcast: " << (use_color ? GREEN : "") << "Yes" << (use_color ? RESET : "") << "\n" - : std::cout << " Broadcast: No\n"; - iface.is_point_to_point() ? std::cout << " Point-to-Point: " << (use_color ? GREEN : "") << "Yes" << (use_color ? RESET : "") << "\n" - : std::cout << " Point-to-Point: No\n"; - iface.is_up() ? std::cout << " Up: " << (use_color ? GREEN : "") << "Yes" << (use_color ? RESET : "") << "\n" - : std::cout << " Up: No\n"; - iface.is_running() ? std::cout << " Running: " << (use_color ? GREEN : "") << "Yes" << (use_color ? RESET : "") << "\n" - : std::cout << " Running: No\n"; - - if (!skip_v4) std::cout << " IPv4 Addresses:\n"; - if (iface.get_ipv4_addrs().empty() && !skip_v4) { - std::cout << " No IPv4 addresses found.\n"; - } - for (const auto& addr : iface.get_ipv4_addrs()) { - if (skip_inactive && !iface.is_up()) continue; - if (skip_v4) continue; - if (skip_loopback && addr.is_loopback()) continue; - if (skip_multicast && addr.is_multicast()) continue; - if (skip_broadcast && addr.get_broadcast().empty()) continue; - - if (use_color) - std::cout << YELLOW; - std::cout << " " << addr.get_ip(); - if (use_color) - std::cout << RESET; - std::cout << "\n"; - - if (addr.is_multicast()) - std::cout << " (Multicast)\n"; - if (addr.is_loopback()) - std::cout << " (Loopback)\n"; - if (!addr.get_broadcast().empty()) - std::cout << " Broadcast: " << addr.get_broadcast() << "\n"; - if (!addr.get_netmask().empty()) - std::cout << " Netmask: " << addr.get_netmask() << "\n"; - if (!addr.get_peer().empty()) - std::cout << " Peer: " << addr.get_peer() << "\n"; - } - if (!skip_v6) std::cout << " IPv6 Addresses:\n"; - if (iface.get_ipv6_addrs().empty() && !skip_v6) { - std::cout << " No IPv6 addresses found.\n"; - } - for (const auto& addr : iface.get_ipv6_addrs()) { - if (skip_v6) continue; - if (skip_loopback && addr.is_loopback()) continue; - if (skip_multicast && addr.is_multicast()) continue; - if (skip_inactive && !iface.is_up()) continue; - if (skip_broadcast && addr.get_netmask().empty()) continue; - - if (use_color) - std::cout << MAGENTA; - std::cout << " " << addr.get_ip(); - if (use_color) - std::cout << RESET; - std::cout << "\n"; - - if (addr.is_link_local()) - std::cout << " (Link Local)\n"; - if (addr.is_multicast()) - std::cout << " (Multicast)\n"; - if (addr.is_loopback()) - std::cout << " (Loopback)\n"; - if (!addr.get_scope_id().empty()) - std::cout << " Scope ID: " << addr.get_scope_id() << "\n"; - if (!addr.get_netmask().empty()) - std::cout << " Netmask: " << addr.get_netmask() << "\n"; - } - } -} +/** netkit + * C++23 cross-platform networking toolkit library providing safe Unix-style sockets and protocol abstractions. + * + * Copyright (c) 2025-2026 Jacob Nilsson + * Licensed under the MIT License. + * + * @file main.c + * @license MIT + * @note Example code using the Netkit library. + * @brief A clone of the 'ifconfig' command that lists network interfaces and their addresses. + */ +#include +#include + +const std::string RESET = "\033[0m"; +const std::string BOLD = "\033[1m"; +const std::string GREEN = "\033[32m"; +const std::string YELLOW = "\033[33m"; +const std::string CYAN = "\033[36m"; +const std::string MAGENTA = "\033[35m"; + +int main(int argc, char** argv) { + bool use_color = true; + bool skip_v4 = false; + bool skip_v6 = false; + bool skip_inactive = false; + bool skip_broadcast = false; + bool skip_point_to_point = false; + bool skip_up = false; + bool skip_loopback = false; + bool skip_multicast = false; + bool skip_no_ipv4 = false; + bool skip_no_ipv6 = false; + bool skip_loopback_interfaces = false; + + bool is_stdout_terminal = isatty(STDOUT_FILENO); + if (!is_stdout_terminal) { + use_color = false; + } + + static const auto args = std::vector(argv, argv + argc); + for (const auto& it : args) { + if (it == "--no-color" || it == "-n") { + use_color = false; + } else if (it == "--color" || it == "-c") { + use_color = true; + } else if (it == "--skip-v4" || it == "-s4") { + skip_v4 = true; + } else if (it == "--skip-v6" || it == "-s6") { + skip_v6 = true; + } else if (it == "--skip-inactive" || it == "-si") { + skip_inactive = true; + } else if (it == "--skip-broadcast" || it == "-sb") { + skip_broadcast = true; + } else if (it == "--skip-point-to-point" || it == "-sptp") { + skip_point_to_point = true; + } else if (it == "--skip-up" || it == "-su") { + skip_up = true; + } else if (it == "--skip-loopback" || it == "-sl") { + skip_loopback = true; + } else if (it == "--skip-no-addresses" || it == "-sna") { + skip_no_ipv4 = true; + skip_no_ipv6 = true; + } else if (it == "--skip-no-ipv4" || it == "-snv4") { + skip_no_ipv4 = true; + } else if (it == "--skip-no-ipv6" || it == "-snv6") { + skip_no_ipv6 = true; + } else if (it == "--skip-loopback-interfaces" || it == "-sli") { + skip_loopback_interfaces = true; + } else if (it == "--help" || it == "-h") { + std::cout << "Usage: " << argv[0] << " [options]\n" + << "Options:\n" + << " --no-color, -n Disable colored output\n" + << " --color, -c Enable colored output (default)\n" + << " --skip-v4, -s4 Skip IPv4 addresses\n" + << " --skip-v6, -s6 Skip IPv6 addresses\n" + << " --skip-inactive, -si Skip inactive interfaces\n" + << " --skip-broadcast, -sb Skip broadcast interfaces\n" + << " --skip-point-to-point, -sptp Skip point-to-point interfaces\n" + << " --skip-up, -su Skip interfaces that are not up\n" + << " --skip-loopback, -sl Skip loopback addresses\n" + << " --skip-multicast, -sm Skip multicast addresses\n" + << " --skip-no-addresses, -sna Skip interfaces with no IPv4 or IPv6 addresses\n" + << " --skip-no-ipv4, -snv4 Skip interfaces with no IPv4 addresses\n" + << " --skip-no-ipv6, -snv6 Skip interfaces with no IPv6 addresses\n" + << " --skip-loopback-interfaces, -sli Skip loopback interfaces\n" + << " --help, -h Show this help message\n"; + return 0; + } + } + + auto list = netkit::network::get_interfaces(); + + for (const auto& iface : list) { + if (skip_inactive && !iface.is_up()) continue; + if (skip_broadcast && iface.is_broadcast()) continue; + if (skip_point_to_point && iface.is_point_to_point()) continue; + if (skip_up && !iface.is_up()) continue; + if (iface.get_ipv4_addrs().empty() && skip_no_ipv4) continue; + if (iface.get_ipv6_addrs().empty() && skip_no_ipv6) continue; + if (skip_loopback_interfaces) { + bool found = false; + for (const auto& addr : iface.get_ipv4_addrs()) { + if (addr.is_loopback()) found = true; break; + } + for (const auto& addr : iface.get_ipv6_addrs()) { + if (addr.is_loopback()) found = true; break; + } + if (found) { + continue; + } + } + + if (use_color) + std::cout << BOLD << CYAN; + std::cout << "Interface: " << iface.get_name(); + if (use_color) + std::cout << RESET; + std::cout << "\n"; + + iface.is_broadcast() ? std::cout << " Broadcast: " << (use_color ? GREEN : "") << "Yes" << (use_color ? RESET : "") << "\n" + : std::cout << " Broadcast: No\n"; + iface.is_point_to_point() ? std::cout << " Point-to-Point: " << (use_color ? GREEN : "") << "Yes" << (use_color ? RESET : "") << "\n" + : std::cout << " Point-to-Point: No\n"; + iface.is_up() ? std::cout << " Up: " << (use_color ? GREEN : "") << "Yes" << (use_color ? RESET : "") << "\n" + : std::cout << " Up: No\n"; + iface.is_running() ? std::cout << " Running: " << (use_color ? GREEN : "") << "Yes" << (use_color ? RESET : "") << "\n" + : std::cout << " Running: No\n"; + + if (!skip_v4) std::cout << " IPv4 Addresses:\n"; + if (iface.get_ipv4_addrs().empty() && !skip_v4) { + std::cout << " No IPv4 addresses found.\n"; + } + for (const auto& addr : iface.get_ipv4_addrs()) { + if (skip_inactive && !iface.is_up()) continue; + if (skip_v4) continue; + if (skip_loopback && addr.is_loopback()) continue; + if (skip_multicast && addr.is_multicast()) continue; + if (skip_broadcast && addr.get_broadcast().empty()) continue; + + if (use_color) + std::cout << YELLOW; + std::cout << " " << addr.get_ip(); + if (use_color) + std::cout << RESET; + std::cout << "\n"; + + if (addr.is_multicast()) + std::cout << " (Multicast)\n"; + if (addr.is_loopback()) + std::cout << " (Loopback)\n"; + if (!addr.get_broadcast().empty()) + std::cout << " Broadcast: " << addr.get_broadcast() << "\n"; + if (!addr.get_netmask().empty()) + std::cout << " Netmask: " << addr.get_netmask() << "\n"; + if (!addr.get_peer().empty()) + std::cout << " Peer: " << addr.get_peer() << "\n"; + } + if (!skip_v6) std::cout << " IPv6 Addresses:\n"; + if (iface.get_ipv6_addrs().empty() && !skip_v6) { + std::cout << " No IPv6 addresses found.\n"; + } + for (const auto& addr : iface.get_ipv6_addrs()) { + if (skip_v6) continue; + if (skip_loopback && addr.is_loopback()) continue; + if (skip_multicast && addr.is_multicast()) continue; + if (skip_inactive && !iface.is_up()) continue; + if (skip_broadcast && addr.get_netmask().empty()) continue; + + if (use_color) + std::cout << MAGENTA; + std::cout << " " << addr.get_ip(); + if (use_color) + std::cout << RESET; + std::cout << "\n"; + + if (addr.is_link_local()) + std::cout << " (Link Local)\n"; + if (addr.is_multicast()) + std::cout << " (Multicast)\n"; + if (addr.is_loopback()) + std::cout << " (Loopback)\n"; + if (!addr.get_scope_id().empty()) + std::cout << " Scope ID: " << addr.get_scope_id() << "\n"; + if (!addr.get_netmask().empty()) + std::cout << " Netmask: " << addr.get_netmask() << "\n"; + } + } +} diff --git a/examples/cpp/multipart_parsing/.gitignore b/examples/socket/.gitignore similarity index 100% rename from examples/cpp/multipart_parsing/.gitignore rename to examples/socket/.gitignore diff --git a/examples/cpp/socket/CMakeLists.txt b/examples/socket/CMakeLists.txt similarity index 96% rename from examples/cpp/socket/CMakeLists.txt rename to examples/socket/CMakeLists.txt index 86c1cc8..f0e13cb 100644 --- a/examples/cpp/socket/CMakeLists.txt +++ b/examples/socket/CMakeLists.txt @@ -1,16 +1,16 @@ -cmake_minimum_required(VERSION 3.11) - -project(socket LANGUAGES CXX) - -set(CMAKE_CXX_STANDARD 23) -set(CMAKE_CXX_STANDARD_REQUIRED ON) -set(CMAKE_CXX_EXTENSIONS OFF) -set(CMAKE_EXPORT_COMPILE_COMMANDS ON) - -if (NOT TARGET netkit::netkit) - find_package(netkit REQUIRED) -endif() - -add_executable(socket main.cpp) - +cmake_minimum_required(VERSION 3.11) + +project(socket LANGUAGES CXX) + +set(CMAKE_CXX_STANDARD 23) +set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_CXX_EXTENSIONS OFF) +set(CMAKE_EXPORT_COMPILE_COMMANDS ON) + +if (NOT TARGET netkit::netkit) + find_package(netkit REQUIRED) +endif() + +add_executable(socket main.cpp) + target_link_libraries(socket PRIVATE netkit::netkit) \ No newline at end of file diff --git a/examples/cpp/socket/main.cpp b/examples/socket/main.cpp similarity index 96% rename from examples/cpp/socket/main.cpp rename to examples/socket/main.cpp index 2f4ac87..6d6426e 100644 --- a/examples/cpp/socket/main.cpp +++ b/examples/socket/main.cpp @@ -1,45 +1,45 @@ -/** netkit - * C++23 cross-platform networking toolkit library providing safe Unix-style sockets and protocol abstractions. - * - * Copyright (c) 2025-2026 Jacob Nilsson - * Licensed under the MIT License. - * - * @file main.cpp - * @license MIT - * @note Example code using the Netkit library. - * @note See examples/socket_ssl for a TLS/SSL version of this example. - */ -#include -#include -#include -#include - -int main() { - netkit::sock::addr addr{"google.com", 80, netkit::sock::addr_type::hostname}; - netkit::tcp::tcp_stream connector{addr}; - - connector.connect(); - - constexpr std::string_view request = "GET / HTTP/1.1\r\nHost: google.com\r\nConnection: close\r\n\r\n"; - - auto write_result = connector.write_all(request); - - if (write_result.status != netkit::stream::stream_status::success) { - throw std::runtime_error{"write failed"}; - } - - auto response = connector.read_all_string(); - - connector.close(); - - std::ofstream file("response.txt"); - - if (file.is_open()) { - file.write(response.data(), response.size()); - file.close(); - } else { - std::cerr << "Failed to open file" << std::endl; - } - - std::cout << "Response written to response.txt" << std::endl; +/** netkit + * C++23 cross-platform networking toolkit library providing safe Unix-style sockets and protocol abstractions. + * + * Copyright (c) 2025-2026 Jacob Nilsson + * Licensed under the MIT License. + * + * @file main.cpp + * @license MIT + * @note Example code using the Netkit library. + * @note See examples/socket_ssl for a TLS/SSL version of this example. + */ +#include +#include +#include +#include + +int main() { + netkit::sock::addr addr{"google.com", 80, netkit::sock::addr_type::hostname}; + netkit::tcp::tcp_stream connector{addr}; + + connector.connect(); + + constexpr std::string_view request = "GET / HTTP/1.1\r\nHost: google.com\r\nConnection: close\r\n\r\n"; + + auto write_result = connector.write_all(request); + + if (write_result.status != netkit::stream::stream_status::success) { + throw std::runtime_error{"write failed"}; + } + + auto response = connector.read_all_string(); + + connector.close(); + + std::ofstream file("response.txt"); + + if (file.is_open()) { + file.write(response.data(), response.size()); + file.close(); + } else { + std::cerr << "Failed to open file" << std::endl; + } + + std::cout << "Response written to response.txt" << std::endl; } \ No newline at end of file diff --git a/examples/cpp/socket_async/.gitignore b/examples/socket_async/.gitignore similarity index 100% rename from examples/cpp/socket_async/.gitignore rename to examples/socket_async/.gitignore diff --git a/examples/cpp/socket_async/CMakeLists.txt b/examples/socket_async/CMakeLists.txt similarity index 100% rename from examples/cpp/socket_async/CMakeLists.txt rename to examples/socket_async/CMakeLists.txt diff --git a/examples/cpp/socket_async/main.cpp b/examples/socket_async/main.cpp similarity index 100% rename from examples/cpp/socket_async/main.cpp rename to examples/socket_async/main.cpp diff --git a/examples/cpp/network_interface/.gitignore b/examples/socket_server/.gitignore similarity index 100% rename from examples/cpp/network_interface/.gitignore rename to examples/socket_server/.gitignore diff --git a/examples/cpp/socket_server/CMakeLists.txt b/examples/socket_server/CMakeLists.txt similarity index 100% rename from examples/cpp/socket_server/CMakeLists.txt rename to examples/socket_server/CMakeLists.txt diff --git a/examples/cpp/socket_server/main.cpp b/examples/socket_server/main.cpp similarity index 100% rename from examples/cpp/socket_server/main.cpp rename to examples/socket_server/main.cpp diff --git a/examples/cpp/socket_server_async/.gitignore b/examples/socket_server_async/.gitignore similarity index 100% rename from examples/cpp/socket_server_async/.gitignore rename to examples/socket_server_async/.gitignore diff --git a/examples/cpp/socket_server_async/CMakeLists.txt b/examples/socket_server_async/CMakeLists.txt similarity index 100% rename from examples/cpp/socket_server_async/CMakeLists.txt rename to examples/socket_server_async/CMakeLists.txt diff --git a/examples/cpp/socket_server_async/main.cpp b/examples/socket_server_async/main.cpp similarity index 100% rename from examples/cpp/socket_server_async/main.cpp rename to examples/socket_server_async/main.cpp diff --git a/examples/cpp/socket/.gitignore b/examples/socket_ssl/.gitignore similarity index 100% rename from examples/cpp/socket/.gitignore rename to examples/socket_ssl/.gitignore diff --git a/examples/cpp/socket_ssl/CMakeLists.txt b/examples/socket_ssl/CMakeLists.txt similarity index 100% rename from examples/cpp/socket_ssl/CMakeLists.txt rename to examples/socket_ssl/CMakeLists.txt diff --git a/examples/cpp/socket_ssl/main.cpp b/examples/socket_ssl/main.cpp similarity index 100% rename from examples/cpp/socket_ssl/main.cpp rename to examples/socket_ssl/main.cpp diff --git a/include/netkit-c/definitions.h b/include/netkit-c/definitions.h deleted file mode 100644 index ac3e65b..0000000 --- a/include/netkit-c/definitions.h +++ /dev/null @@ -1,33 +0,0 @@ -#ifndef NETKIT_DEFINITIONS_H -#define NETKIT_DEFINITIONS_H - -#if defined(__APPLE__) -#define NETKIT_MACOS 1 -#endif -#if defined(__unix__) || defined(__unix) || defined(__APPLE__) && defined(__MACH__) -#define NETKIT_UNIX 1 -#endif -#ifdef _WIN32 -#define NETKIT_WINDOWS 1 -#endif - -#ifndef NETKIT_FALLBACK_IPV4_DNS_1 -#define NETKIT_FALLBACK_IPV4_DNS_1 "8.8.8.8" -#endif -#ifndef NETKIT_FALLBACK_IPV4_DNS_2 -#define NETKIT_FALLBACK_IPV4_DNS_2 "8.8.4.4" -#endif -#ifndef NETKIT_FALLBACK_IPV6_DNS_1 -#define NETKIT_FALLBACK_IPV6_DNS_1 "2001:4860:4860::8888" -#endif -#ifndef NETKIT_FALLBACK_IPV6_DNS_2 -#define NETKIT_FALLBACK_IPV6_DNS_2 "2001:4860:4860::8844" -#endif -#ifndef NETKIT_LOCALHOST_IPV4 -#define NETKIT_LOCALHOST_IPV4 "127.0.0.1" -#endif -#ifndef NETKIT_LOCALHOST_IPV6 -#define NETKIT_LOCALHOST_IPV6 "::1" -#endif - -#endif \ No newline at end of file diff --git a/include/netkit-c/export.h b/include/netkit-c/export.h deleted file mode 100644 index df386bf..0000000 --- a/include/netkit-c/export.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef NETKIT_EXPORT_H -#define NETKIT_EXPORT_H - -#if defined(_WIN32) && defined(NETKIT_C_SHARED) -#ifdef NETKIT_C_BUILD_DLL -#define NETKIT_C_API __declspec(dllexport) -#else -#define NETKIT_C_API __declspec(dllimport) -#endif -#else -#define NETKIT_C_API __attribute__((visibility("default"))) -#endif - -#endif \ No newline at end of file diff --git a/include/netkit-c/network/utility.h b/include/netkit-c/network/utility.h deleted file mode 100644 index bdca6fe..0000000 --- a/include/netkit-c/network/utility.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef NETKIT_UTILITY_H -#define NETKIT_UTILITY_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include - -NETKIT_C_API int netkit_network_is_ipv4(const char* ip, size_t len); -NETKIT_C_API int netkit_network_is_ipv6(const char* ip, size_t len); -NETKIT_C_API int netkit_network_is_valid_port(int port); -NETKIT_C_API int netkit_network_usable_ipv6_address_exists(); - -#ifdef __cplusplus -} -#endif -#endif \ No newline at end of file diff --git a/include/netkit-c/sock/sock_addr.h b/include/netkit-c/sock/sock_addr.h deleted file mode 100644 index d5121c4..0000000 --- a/include/netkit-c/sock/sock_addr.h +++ /dev/null @@ -1,23 +0,0 @@ -#ifndef NETKIT_SOCK_ADDR_H -#define NETKIT_SOCK_ADDR_H -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include -#include - -typedef struct netkit_sock_addr netkit_sock_addr_t; - -NETKIT_C_API netkit_sock_addr_t* netkit_sock_addr_create(const char* hostname, int port, netkit_sock_addr_type_t type); -NETKIT_C_API netkit_sock_addr_t* netkit_sock_addr_create_unix(const char* file_path); -NETKIT_C_API void netkit_sock_addr_destroy(netkit_sock_addr_t* addr); -NETKIT_C_API int netkit_sock_addr_get_port(netkit_sock_addr_t* addr); -NETKIT_C_API netkit_sock_addr_type_t netkit_sock_addr_get_type(netkit_sock_addr_t* addr); -NETKIT_C_API netkit_sock_addr_status_t netkit_sock_addr_get_hostname(netkit_sock_addr_t* addr, char* hostname, size_t len, size_t* out_len); - -#ifdef __cplusplus -} -#endif -#endif diff --git a/include/netkit-c/sock/sock_addr_types.h b/include/netkit-c/sock/sock_addr_types.h deleted file mode 100644 index f90a707..0000000 --- a/include/netkit-c/sock/sock_addr_types.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef NETKIT_SOCK_ADDR_TYPES_H -#define NETKIT_SOCK_ADDR_TYPES_H - -#ifdef __cplusplus -extern "C" { -#endif - -typedef enum netkit_sock_addr_status { - SOCK_ADDR_STATUS_SUCCESS, - SOCK_ADDR_STATUS_FAILED, -} netkit_sock_addr_status_t; - -typedef enum netkit_sock_addr_type { - SOCK_ADDR_NONE = 0, - SOCK_ADDR_IPV4 = 1, - SOCK_ADDR_IPV6 = 2, - SOCK_ADDR_HOSTNAME_IPV4 = 3, - SOCK_ADDR_HOSTNAME_IPV6 = 4, - SOCK_ADDR_HOSTNAME = 5, - SOCK_ADDR_FILENAME = 6 -} netkit_sock_addr_type_t; - -#ifdef __cplusplus -} -#endif -#endif diff --git a/include/netkit-c/sock/sock_types.h b/include/netkit-c/sock/sock_types.h deleted file mode 100644 index 89cbb5f..0000000 --- a/include/netkit-c/sock/sock_types.h +++ /dev/null @@ -1,55 +0,0 @@ -#ifndef NETKIT_SOCK_TYPES_H -#define NETKIT_SOCK_TYPES_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include - -#ifndef SOCK_OPT_HAS -#define SOCK_OPT_HAS(mask, opt) (((mask) & (opt)) != 0) -#endif -#ifndef SOCK_OPT - -typedef enum netkit_sock_type { - SOCK_NONE, - SOCK_TCP, - SOCK_UDP, - SOCK_UDS -} netkit_sock_type_t; - -typedef enum netkit_sock_status { - SOCK_STATUS_FAILED = 1, - SOCK_STATUS_SUCCESS = 0, -} netkit_sock_status_t; - -typedef enum netkit_sock_opt { - SOCK_OPT_NONE = 1 << 0, - SOCK_OPT_REUSE_ADDR = 1 << 1, - SOCK_OPT_NO_REUSE_ADDR = 1 << 2, - SOCK_OPT_NO_DELAY = 1 << 3, - SOCK_OPT_KEEP_ALIVE = 1 << 4, - SOCK_OPT_NO_KEEP_ALIVE = 1 << 5, - SOCK_OPT_NON_BLOCKING = 1 << 6, - SOCK_OPT_BLOCKING = 1 << 7 -} netkit_sock_opt_t; - -typedef enum netkit_recv_status { - RECV_SUCCESS, - RECV_TIMEOUT, - RECV_CLOSED, - RECV_ERROR, -} netkit_recv_status_t; - -typedef struct netkit_recv_result { - char* data; - size_t size; -} netkit_recv_result_t; - -#ifdef __cplusplus -} -#endif -#endif -#endif diff --git a/include/netkit-c/sock/ssl_sync_sock.h b/include/netkit-c/sock/ssl_sync_sock.h deleted file mode 100644 index 2627d57..0000000 --- a/include/netkit-c/sock/ssl_sync_sock.h +++ /dev/null @@ -1,63 +0,0 @@ -#ifndef NETKIT_SSL_SYNC_SOCK_H -#define NETKIT_SSL_SYNC_SOCK_H -#include "netkit-c/sock/sync_sock.h" -#ifdef __cplusplus -extern "C" { -#endif - -#include - -#if defined(NETKIT_OPENSSL) || defined(NETKIT_WOLFSSL) - -#include -#include -#include -#include - -typedef enum netkit_ssl_sync_sock_mode { - NETKIT_SSL_SYNC_SOCK_MODE_CLIENT, - NETKIT_SSL_SYNC_SOCK_MODE_SERVER, -} netkit_ssl_sync_sock_mode_t; - -typedef enum netkit_ssl_sync_sock_version { - NETKIT_SSL_SYNC_SOCK_VERSION_TLS_1_0, - NETKIT_SSL_SYNC_SOCK_VERSION_TLS_1_1, - NETKIT_SSL_SYNC_SOCK_VERSION_TLS_1_2, - NETKIT_SSL_SYNC_SOCK_VERSION_TLS_1_3, -} netkit_ssl_sync_sock_version_t; - -typedef enum netkit_ssl_sync_sock_verification { - NETKIT_SSL_SYNC_SOCK_VERIFICATION_NONE, - NETKIT_SSL_SYNC_SOCK_VERIFICATION_PEER, -} netkit_ssl_sync_sock_verification_t; - -typedef struct netkit_ssl_sync_sock netkit_ssl_sync_sock_t; - -NETKIT_C_API netkit_ssl_sync_sock_t* netkit_ssl_sync_sock_create(netkit_sync_sock_t* sock, - netkit_ssl_sync_sock_mode_t mode, - netkit_ssl_sync_sock_version_t version, - netkit_ssl_sync_sock_verification_t verification, - const char* cert_path, - const char* key_path); -NETKIT_C_API netkit_sock_status_t netkit_ssl_sync_sock_destroy(netkit_ssl_sync_sock_t* sock); -NETKIT_C_API netkit_sock_status_t netkit_ssl_sync_sock_connect(netkit_ssl_sync_sock_t* sock); -NETKIT_C_API netkit_sock_status_t netkit_ssl_sync_sock_bind(netkit_ssl_sync_sock_t* sock); -NETKIT_C_API netkit_sock_status_t netkit_ssl_sync_sock_unbind(netkit_ssl_sync_sock_t* sock); -NETKIT_C_API netkit_sock_status_t netkit_ssl_sync_sock_listen(netkit_ssl_sync_sock_t* sock); -NETKIT_C_API netkit_sock_status_t netkit_ssl_sync_sock_listen_n(netkit_ssl_sync_sock_t* sock, int backlog); -NETKIT_C_API netkit_sock_status_t netkit_ssl_sync_sock_perform_handshake(netkit_ssl_sync_sock_t* sock); -NETKIT_C_API netkit_ssl_sync_sock_t* netkit_ssl_sync_sock_accept(netkit_ssl_sync_sock_t* sock); -NETKIT_C_API int netkit_ssl_sync_sock_send(netkit_ssl_sync_sock_t* sock, void* buf, size_t len); -NETKIT_C_API void netkit_ssl_sync_sock_overflow_bytes(netkit_ssl_sync_sock_t* sock, char* buf, size_t len, size_t* out_len); -NETKIT_C_API void netkit_ssl_sync_sock_clear_overflow_bytes(netkit_ssl_sync_sock_t* sock); - -NETKIT_C_API netkit_recv_status_t netkit_ssl_sync_sock_recv(netkit_ssl_sync_sock_t* sock, netkit_recv_result_t* out, int timeout_seconds, const char* match, size_t eof); -NETKIT_C_API void netkit_ssl_sync_sock_close(netkit_ssl_sync_sock_t* sock); -NETKIT_C_API netkit_sock_addr_t* netkit_ssl_sync_sock_get_peer(netkit_ssl_sync_sock_t* sock); - -#endif - -#ifdef __cplusplus -} -#endif -#endif diff --git a/include/netkit-c/sock/sync_sock.h b/include/netkit-c/sock/sync_sock.h deleted file mode 100644 index e0ad97e..0000000 --- a/include/netkit-c/sock/sync_sock.h +++ /dev/null @@ -1,37 +0,0 @@ -#ifndef NETKIT_SYNC_SOCK_H -#define NETKIT_SYNC_SOCK_H -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include -#include -#include - -typedef struct netkit_sync_sock netkit_sync_sock_t; - -NETKIT_C_API netkit_sync_sock_t* netkit_sync_sock_create(netkit_sock_addr_t* addr, netkit_sock_type_t type, netkit_sock_opt_t opts); -NETKIT_C_API netkit_sock_status_t netkit_sync_sock_destroy(netkit_sync_sock_t* sock); -NETKIT_C_API netkit_sock_status_t netkit_sync_sock_connect(netkit_sync_sock_t* sock); -NETKIT_C_API netkit_sock_status_t netkit_sync_sock_bind(netkit_sync_sock_t* sock); -NETKIT_C_API netkit_sock_status_t netkit_sync_sock_unbind(netkit_sync_sock_t* sock); -NETKIT_C_API netkit_sock_status_t netkit_sync_sock_listen(netkit_sync_sock_t* sock); -NETKIT_C_API netkit_sock_status_t netkit_sync_sock_listen_n(netkit_sync_sock_t* sock, int backlog); -NETKIT_C_API netkit_sync_sock_t* netkit_sync_sock_accept(netkit_sync_sock_t* sock); -NETKIT_C_API int netkit_sync_sock_send(netkit_sync_sock_t* sock, void* buf, size_t len); -NETKIT_C_API void netkit_sync_sock_overflow_bytes(netkit_sync_sock_t* sock, char* buf, size_t len, size_t* out_len); -NETKIT_C_API void netkit_sync_sock_clear_overflow_bytes(netkit_sync_sock_t* sock); - -NETKIT_C_API netkit_recv_result_t* netkit_recv_result_create(void); -NETKIT_C_API void netkit_recv_result_destroy(netkit_recv_result_t* recv_result); - -NETKIT_C_API netkit_recv_status_t netkit_sync_sock_recv(netkit_sync_sock_t* sock, netkit_recv_result_t* out, int timeout_seconds, const char* match, size_t eof); -NETKIT_C_API netkit_recv_status_t netkit_sync_sock_basic_recv(netkit_sync_sock_t* sock, netkit_recv_result_t* out); -NETKIT_C_API void netkit_sync_sock_close(netkit_sync_sock_t* sock); -NETKIT_C_API netkit_sock_addr_t* netkit_sync_sock_get_peer(netkit_sync_sock_t* sock); - -#ifdef __cplusplus -} -#endif -#endif diff --git a/src/c/network/utility.cpp b/src/c/network/utility.cpp deleted file mode 100644 index 678b2a3..0000000 --- a/src/c/network/utility.cpp +++ /dev/null @@ -1,54 +0,0 @@ -#include -#include -#include -#include - -extern "C" NETKIT_C_API int netkit_network_is_ipv4(const char* ip, size_t len) { - if (!ip || len == 0) { - return 0; - } - - try { - std::string ip_str{ip, len}; - return netkit::network::is_ipv4(ip_str) ? 1 : 0; - } catch (std::exception&) { - return 0; - } catch (...) { - return 0; - } -} - -extern "C" NETKIT_C_API int netkit_network_is_ipv6(const char* ip, size_t len) { - if (!ip || len == 0) { - return 0; - } - - try { - std::string ip_str{ip, len}; - return netkit::network::is_ipv6(ip_str) ? 1 : 0; - } catch (std::exception&) { - return 0; - } catch (...) { - return 0; - } -} - -extern "C" NETKIT_C_API int netkit_network_is_valid_port(int port) { - try { - return netkit::network::is_valid_port(port) ? 1 : 0; - } catch (std::exception&) { - return 0; - } catch (...) { - return 0; - } -} - -extern "C" NETKIT_C_API int netkit_network_usable_ipv6_address_exists() { - try { - return netkit::network::usable_ipv6_address_exists() ? 1 : 0; - } catch (std::exception&) { - return 0; - } catch (...) { - return 0; - } -} \ No newline at end of file diff --git a/src/c/sock/addr.cpp b/src/c/sock/addr.cpp deleted file mode 100644 index 3f1f72c..0000000 --- a/src/c/sock/addr.cpp +++ /dev/null @@ -1,144 +0,0 @@ -#include -#include -#include -#include - -struct netkit_sock_addr { - std::unique_ptr impl; - netkit_sock_addr_type_t impl_type = SOCK_ADDR_NONE; - - explicit netkit_sock_addr() = default; -#ifndef NETKIT_DKP - explicit netkit_sock_addr(const char* file_path) : impl_type(SOCK_ADDR_FILENAME) { - impl = std::make_unique(file_path); - } -#endif - - netkit_sock_addr(const char* hostname, int port, netkit_sock_addr_type_t type) : impl_type(type) { - netkit::sock::addr_type t; - - switch (type) { - case SOCK_ADDR_FILENAME: - t = netkit::sock::addr_type::filename; - break; - case SOCK_ADDR_HOSTNAME: - t = netkit::sock::addr_type::hostname; - break; - case SOCK_ADDR_HOSTNAME_IPV4: - t = netkit::sock::addr_type::hostname_ipv4; - break; - case SOCK_ADDR_HOSTNAME_IPV6: - t = netkit::sock::addr_type::hostname_ipv6; - break; - case SOCK_ADDR_IPV6: - t = netkit::sock::addr_type::ipv6; - break; - case SOCK_ADDR_IPV4: - t = netkit::sock::addr_type::ipv4; - break; - default: - t = netkit::sock::addr_type::hostname; - break; - } - - impl = std::make_unique(hostname, port, t); - } -}; - -#ifndef NETKIT_DKP -extern "C" NETKIT_C_API netkit_sock_addr_t* netkit_sock_addr_create_unix(const char* file_path) { - netkit_sock_addr_t* ret; - - try { - ret = new netkit_sock_addr{file_path}; - } catch (std::exception& e) { -#ifdef NETKIT_C_DEBUG - fprintf(stderr, "Exception: %s\n", e.what()); -#endif - return nullptr; - } catch (...) { -#ifdef NETKIT_C_DEBUG - fprintf(stderr, "Unknown exception\n"); -#endif - return nullptr; - } - - return ret; -} -#endif - -extern "C" NETKIT_C_API netkit_sock_addr_t* netkit_sock_addr_create(const char* hostname, int port, netkit_sock_addr_type_t type) { - netkit_sock_addr_t* ret; - - try { - ret = new netkit_sock_addr{hostname, port, type}; - } catch (std::exception& e) { -#ifdef NETKIT_C_DEBUG - fprintf(stderr, "Exception: %s\n", e.what()); -#endif - return nullptr; - } catch (...) { -#ifdef NETKIT_C_DEBUG - fprintf(stderr, "Unknown exception\n"); -#endif - return nullptr; - } - - return ret; -} - -extern "C" NETKIT_C_API void netkit_sock_addr_destroy(netkit_sock_addr_t* addr) { - if (!addr) { - return; - } - - delete addr; -} - -extern "C" NETKIT_C_API int netkit_sock_addr_get_port(netkit_sock_addr_t* addr) { - if (!addr) { - return -1; - } - - try { - return addr->impl->get_port(); - } catch (std::exception&) { - return -1; - } catch (...) { - return -1; - } -} - -extern "C" NETKIT_C_API netkit_sock_addr_type_t netkit_sock_addr_get_type(netkit_sock_addr_t* addr) { - if (!addr) { - return SOCK_ADDR_NONE; - } - - return addr->impl_type; -} - -extern "C" NETKIT_C_API netkit_sock_addr_status_t netkit_sock_addr_get_hostname(netkit_sock_addr_t* addr, char* hostname, size_t len, size_t* out_len) { - if (!addr) { - return SOCK_ADDR_STATUS_FAILED; - } - - try { - const auto& host = addr->impl->get_hostname(); - - if (out_len) { - *out_len = host.size() + 1; - } - - if (hostname) { - if (len == 0) { - return SOCK_ADDR_STATUS_FAILED; - } - - std::snprintf(hostname, len, "%s", host.c_str()); - } - - return SOCK_ADDR_STATUS_SUCCESS; - } catch (...) { - return SOCK_ADDR_STATUS_FAILED; - } -} \ No newline at end of file diff --git a/src/c/sock/ssl_sync_sock.cpp b/src/c/sock/ssl_sync_sock.cpp deleted file mode 100644 index a247c72..0000000 --- a/src/c/sock/ssl_sync_sock.cpp +++ /dev/null @@ -1,326 +0,0 @@ -#if defined(NETKIT_OPENSSL) || defined(NETKIT_WOLFSSL) - -#include -#include -#include -#include -#include -#include - -struct netkit_sync_sock { - std::unique_ptr impl; -}; - -struct netkit_ssl_sync_sock { - std::unique_ptr impl; - netkit_ssl_sync_sock() = default; - - static netkit::sock::mode to_mode(const netkit_ssl_sync_sock_mode_t mode) { - switch (mode) { - case NETKIT_SSL_SYNC_SOCK_MODE_CLIENT: return netkit::sock::mode::client; - case NETKIT_SSL_SYNC_SOCK_MODE_SERVER: return netkit::sock::mode::server; - } - - throw std::invalid_argument("invalid mode"); - } - - static netkit::sock::version to_version(const netkit_ssl_sync_sock_version_t version) { - switch (version) { - case NETKIT_SSL_SYNC_SOCK_VERSION_TLS_1_1: return netkit::sock::version::TLS_1_1; - case NETKIT_SSL_SYNC_SOCK_VERSION_TLS_1_2: return netkit::sock::version::TLS_1_2; - case NETKIT_SSL_SYNC_SOCK_VERSION_TLS_1_3: return netkit::sock::version::TLS_1_3; - } - - throw std::invalid_argument("invalid version"); - } - - static netkit::sock::verification to_verification(const netkit_ssl_sync_sock_verification_t verification) { - switch (verification) { - case NETKIT_SSL_SYNC_SOCK_VERIFICATION_NONE: return netkit::sock::verification::none; - case NETKIT_SSL_SYNC_SOCK_VERIFICATION_PEER: return netkit::sock::verification::peer; - } - - throw std::invalid_argument("invalid verification"); - } - static netkit::sock::addr_type get_addr_type(netkit_sock_addr_type_t type) { - switch (type) { - case SOCK_ADDR_FILENAME: - return netkit::sock::addr_type::filename; - case SOCK_ADDR_IPV4: - return netkit::sock::addr_type::ipv4; - case SOCK_ADDR_IPV6: - return netkit::sock::addr_type::ipv6; - case SOCK_ADDR_HOSTNAME_IPV4: - return netkit::sock::addr_type::hostname_ipv4; - case SOCK_ADDR_HOSTNAME_IPV6: - return netkit::sock::addr_type::hostname_ipv6; - default: - return netkit::sock::addr_type::hostname; - } - } - static netkit_sock_addr_type_t get_addr_type(netkit::sock::addr_type type) { - switch (type) { - case netkit::sock::addr_type::filename: - return SOCK_ADDR_FILENAME; - case netkit::sock::addr_type::ipv4: - return SOCK_ADDR_IPV4; - case netkit::sock::addr_type::ipv6: - return SOCK_ADDR_IPV6; - case netkit::sock::addr_type::hostname_ipv4: - return SOCK_ADDR_HOSTNAME_IPV4; - case netkit::sock::addr_type::hostname_ipv6: - return SOCK_ADDR_HOSTNAME_IPV6; - default: - return SOCK_ADDR_HOSTNAME; - } - } - - netkit_ssl_sync_sock(netkit_sync_sock_t* sock, - netkit_ssl_sync_sock_mode_t mode, - netkit_ssl_sync_sock_version_t version, - netkit_ssl_sync_sock_verification_t verification, - const char* cert_path, - const char* key_path) { - - if (!sock->impl) { - throw std::invalid_argument("invalid sock"); - } - - this->impl = std::make_unique( - std::move(sock->impl), - to_mode(mode), - to_version(version), - to_verification(verification), - cert_path == nullptr ? "" : cert_path, - key_path == nullptr ? "" : key_path - ); - } -}; - -netkit_ssl_sync_sock_t* from_cstyle(std::unique_ptr ptr) { - auto* sync_sock = new netkit_ssl_sync_sock(); - - sync_sock->impl = std::move(ptr); - - return sync_sock; -} - -extern "C" NETKIT_C_API netkit_ssl_sync_sock_t* netkit_ssl_sync_sock_create(netkit_sync_sock_t* sock, - netkit_ssl_sync_sock_mode_t mode, - netkit_ssl_sync_sock_version_t version, - netkit_ssl_sync_sock_verification_t verification, - const char* cert_path, - const char* key_path) { - - if (!sock) { - return nullptr; - } - - try { - return new netkit_ssl_sync_sock(sock, mode, version, verification, cert_path, key_path); - } catch (...) { - return nullptr; - } -} - -extern "C" NETKIT_C_API netkit_sock_status_t netkit_ssl_sync_sock_destroy(netkit_ssl_sync_sock_t* sock) { - if (!sock) { - return SOCK_STATUS_FAILED; - } - - try { - delete sock; - return SOCK_STATUS_SUCCESS; - } catch (...) { - } - - return SOCK_STATUS_FAILED; -} - -extern "C" NETKIT_C_API netkit_sock_status_t netkit_ssl_sync_sock_connect(netkit_ssl_sync_sock_t* sock) { - if (!sock) { - return SOCK_STATUS_FAILED; - } - - try { - sock->impl->connect(); - } catch (...) { - return SOCK_STATUS_FAILED; - } - - return SOCK_STATUS_SUCCESS; -} - -extern "C" NETKIT_C_API netkit_sock_status_t netkit_ssl_sync_sock_bind(netkit_ssl_sync_sock_t* sock) { - if (!sock) { - return SOCK_STATUS_FAILED; - } - - try { - sock->impl->bind(); - } catch (...) { - return SOCK_STATUS_FAILED; - } - - return SOCK_STATUS_SUCCESS; -} -extern "C" NETKIT_C_API netkit_sock_status_t netkit_ssl_sync_sock_unbind(netkit_ssl_sync_sock_t* sock) { - if (!sock) { - return SOCK_STATUS_FAILED; - } - - try { - sock->impl->unbind(); - } catch (...) { - return SOCK_STATUS_FAILED; - } - - return SOCK_STATUS_SUCCESS; -} -extern "C" NETKIT_C_API netkit_sock_status_t netkit_ssl_sync_sock_listen(netkit_ssl_sync_sock_t* sock) { - if (!sock) { - return SOCK_STATUS_FAILED; - } - - try { - sock->impl->listen(); - } catch (...) { - return SOCK_STATUS_FAILED; - } - - return SOCK_STATUS_SUCCESS; -} - -extern "C" NETKIT_C_API netkit_sock_status_t netkit_ssl_sync_sock_listen_n(netkit_ssl_sync_sock_t* sock, int backlog) { - if (!sock) { - return SOCK_STATUS_FAILED; - } - - try { - sock->impl->listen(backlog); - } catch (...) { - return SOCK_STATUS_FAILED; - } - - return SOCK_STATUS_SUCCESS; -} -extern "C" NETKIT_C_API netkit_ssl_sync_sock_t* netkit_ssl_sync_sock_accept(netkit_ssl_sync_sock_t* sock) { - if (!sock) { - return nullptr; - } - - try { - return from_cstyle(sock->impl->accept_explicit_ssl()); - } catch (...) { - return nullptr; - } -} -extern "C" NETKIT_C_API int netkit_ssl_sync_sock_send(netkit_ssl_sync_sock_t* sock, void* buf, size_t len) { - if (!sock) { - return -1; - } - - try { - return sock->impl->send(buf, len); - } catch (...) { - return -1; - } -} -extern "C" NETKIT_C_API void netkit_ssl_sync_sock_overflow_bytes(netkit_ssl_sync_sock_t* sock, char* buf, size_t len, size_t* out_len) { - if (!sock) { - return; - } - - try { - const auto& bytes = sock->impl->overflow_bytes(); - - if (out_len) { - *out_len = bytes.size() + 1; - } - - std::snprintf(buf, len, "%s", bytes.c_str()); - } catch (...) {} -} -extern "C" NETKIT_C_API void netkit_ssl_sync_sock_clear_overflow_bytes(netkit_ssl_sync_sock_t* sock) { - if (!sock) { - return; - } - - try { - sock->impl->clear_overflow_bytes(); - } catch (...) {} -} - -extern "C" NETKIT_C_API netkit_recv_status_t netkit_ssl_sync_sock_recv(netkit_ssl_sync_sock_t* sock, netkit_recv_result_t* out, int timeout_seconds, const char* match, size_t eof) { - if (!sock || !out) { - return RECV_ERROR; - } - - try { - auto ret = sock->impl->recv(timeout_seconds, match ? match : "", eof); - - if (!ret.data.empty()) { - delete[] out->data; - - out->size = ret.data.size(); - out->data = new char[out->size + 1]; - - std::memcpy(out->data, ret.data.data(), out->size); - out->data[out->size] = '\0'; - } - - switch (ret.status) { - case netkit::sock::recv_status::success: - return RECV_SUCCESS; - case netkit::sock::recv_status::timeout: - return RECV_TIMEOUT; - case netkit::sock::recv_status::closed: - return RECV_CLOSED; - default: - return RECV_ERROR; - } - } catch (const std::exception&) { - return RECV_ERROR; - } catch (...) { - return RECV_ERROR; - } -} - -extern "C" NETKIT_C_API void netkit_ssl_sync_sock_close(netkit_ssl_sync_sock_t* sock) { - if (!sock) { - return; - } - - try { - sock->impl->close(); - } catch (...) {} -} -extern "C" NETKIT_C_API netkit_sock_addr_t* netkit_ssl_sync_sock_get_peer(netkit_ssl_sync_sock_t* sock) { - if (!sock) { - return nullptr; - } - - try { - auto impl_peer = sock->impl->get_peer(); - return netkit_sock_addr_create(impl_peer.get_hostname().c_str(), impl_peer.get_port(), netkit_ssl_sync_sock::get_addr_type(impl_peer.get_type())); - } catch (...) { - return nullptr; - } -} - -extern "C" NETKIT_C_API netkit_sock_status_t netkit_ssl_sync_sock_perform_handshake(netkit_ssl_sync_sock_t* sock) { - if (!sock) { - return SOCK_STATUS_FAILED; - } - - try { - sock->impl->perform_handshake(); - return SOCK_STATUS_SUCCESS; - } catch (std::exception& e) { - std::cerr << e.what() << std::endl; - return SOCK_STATUS_FAILED; - } catch (...) { - return SOCK_STATUS_FAILED; - } -} -#endif \ No newline at end of file diff --git a/src/c/sock/sync_sock.cpp b/src/c/sock/sync_sock.cpp deleted file mode 100644 index 868ffbb..0000000 --- a/src/c/sock/sync_sock.cpp +++ /dev/null @@ -1,362 +0,0 @@ -#include <../../../include/netkit/socket/native/native_sync_sock.hpp> -#include -#include -#include -#include -#include - -struct netkit_sync_sock { - std::unique_ptr impl; - explicit netkit_sync_sock() = default; - static netkit::sock::type get_type(netkit_sock_type_t type) { - switch (type) { - case SOCK_UDP: - return netkit::sock::type::udp; -#ifndef NETKIT_DKP - case SOCK_UDS: - return netkit::sock::type::uds; -#endif - default: - return netkit::sock::type::tcp; - } - } - static netkit::sock::addr_type get_addr_type(netkit_sock_addr_type_t type) { - switch (type) { - case SOCK_ADDR_FILENAME: - return netkit::sock::addr_type::filename; - case SOCK_ADDR_IPV4: - return netkit::sock::addr_type::ipv4; - case SOCK_ADDR_IPV6: - return netkit::sock::addr_type::ipv6; - case SOCK_ADDR_HOSTNAME_IPV4: - return netkit::sock::addr_type::hostname_ipv4; - case SOCK_ADDR_HOSTNAME_IPV6: - return netkit::sock::addr_type::hostname_ipv6; - default: - return netkit::sock::addr_type::hostname; - } - } - static netkit_sock_addr_type_t get_addr_type(netkit::sock::addr_type type) { - switch (type) { - case netkit::sock::addr_type::filename: - return SOCK_ADDR_FILENAME; - case netkit::sock::addr_type::ipv4: - return SOCK_ADDR_IPV4; - case netkit::sock::addr_type::ipv6: - return SOCK_ADDR_IPV6; - case netkit::sock::addr_type::hostname_ipv4: - return SOCK_ADDR_HOSTNAME_IPV4; - case netkit::sock::addr_type::hostname_ipv6: - return SOCK_ADDR_HOSTNAME_IPV6; - default: - return SOCK_ADDR_HOSTNAME; - } - } - static netkit::sock::opt get_opt(netkit_sock_opt_t type) { - netkit::sock::opt opt{}; - - if (SOCK_OPT_HAS(type, SOCK_OPT_NONE)) { - return netkit::sock::opt::no_reuse_addr | netkit::sock::opt::no_delay | netkit::sock::opt::blocking; - } - - if (SOCK_OPT_HAS(type, SOCK_OPT_BLOCKING)) { - opt = opt | netkit::sock::opt::blocking; - } else if (SOCK_OPT_HAS(type, SOCK_OPT_NON_BLOCKING)) { - opt = opt | netkit::sock::opt::no_blocking; - } - if (SOCK_OPT_HAS(type, SOCK_OPT_KEEP_ALIVE)) { - opt = opt | netkit::sock::opt::keep_alive; - } else if (SOCK_OPT_HAS(type, SOCK_OPT_NO_KEEP_ALIVE)) { - opt = opt | netkit::sock::opt::no_keep_alive; - } - if (SOCK_OPT_HAS(type, SOCK_OPT_REUSE_ADDR)) { - opt = opt | netkit::sock::opt::reuse_addr; - } else if (SOCK_OPT_HAS(type, SOCK_OPT_NO_REUSE_ADDR)) { - opt = opt | netkit::sock::opt::no_reuse_addr; - } - - return opt; - } - static netkit::sock::addr get_sock_addr(netkit_sock_addr_t* addr) { - if (!addr) { - throw std::invalid_argument("invalid sock_addr"); - } - - size_t len = 0; - netkit_sock_addr_get_hostname(addr, nullptr, 0, &len); - - if (len == 0) { - throw std::runtime_error("hostname length is 0"); - } - - std::string hostname(len, '\0'); - - netkit_sock_addr_get_hostname(addr, hostname.data(), len, nullptr); - - if (!hostname.empty() && hostname.back() == '\0') { - hostname.pop_back(); - } - - return { - hostname, - netkit_sock_addr_get_port(addr), - get_addr_type(netkit_sock_addr_get_type(addr)) - }; - } - netkit_sync_sock(netkit_sock_addr_t* addr, netkit_sock_type_t type, netkit_sock_opt_t opts) { - if (!addr) { - throw std::invalid_argument("netkit_sock_addr_t* addr is null"); - } - - impl = std::make_unique(get_sock_addr(addr), get_type(type), get_opt(opts)); - } -}; - -netkit_sync_sock_t* from_cstyle(std::unique_ptr ptr) { - auto* sync_sock = new netkit_sync_sock(); - - sync_sock->impl = std::move(ptr); - - return sync_sock; -} - -extern "C" NETKIT_C_API netkit_sync_sock_t* netkit_sync_sock_create(netkit_sock_addr_t* addr, netkit_sock_type_t type, netkit_sock_opt_t opts) { - if (!addr) { - return nullptr; - } - - try { - return new netkit_sync_sock(addr, type, opts); - } catch (...) { - return nullptr; - } -} - -extern "C" NETKIT_C_API netkit_sock_status_t netkit_sync_sock_destroy(netkit_sync_sock_t* sock) { - if (!sock) { - return SOCK_STATUS_FAILED; - } - - try { - delete sock; - return SOCK_STATUS_SUCCESS; - } catch (...) { - } - - return SOCK_STATUS_FAILED; -} - -extern "C" NETKIT_C_API netkit_sock_status_t netkit_sync_sock_connect(netkit_sync_sock_t* sock) { - if (!sock) { - return SOCK_STATUS_FAILED; - } - - try { - sock->impl->connect(); - } catch (...) { - return SOCK_STATUS_FAILED; - } - - return SOCK_STATUS_SUCCESS; -} - -extern "C" NETKIT_C_API netkit_sock_status_t netkit_sync_sock_bind(netkit_sync_sock_t* sock) { - if (!sock) { - return SOCK_STATUS_FAILED; - } - - try { - sock->impl->bind(); - } catch (...) { - return SOCK_STATUS_FAILED; - } - - return SOCK_STATUS_SUCCESS; -} -extern "C" NETKIT_C_API netkit_sock_status_t netkit_sync_sock_unbind(netkit_sync_sock_t* sock) { - if (!sock) { - return SOCK_STATUS_FAILED; - } - - try { - sock->impl->unbind(); - } catch (...) { - return SOCK_STATUS_FAILED; - } - - return SOCK_STATUS_SUCCESS; -} -extern "C" NETKIT_C_API netkit_sock_status_t netkit_sync_sock_listen(netkit_sync_sock_t* sock) { - if (!sock) { - return SOCK_STATUS_FAILED; - } - - try { - sock->impl->listen(); - } catch (...) { - return SOCK_STATUS_FAILED; - } - - return SOCK_STATUS_SUCCESS; -} - -extern "C" NETKIT_C_API netkit_sock_status_t netkit_sync_sock_listen_n(netkit_sync_sock_t* sock, int backlog) { - if (!sock) { - return SOCK_STATUS_FAILED; - } - - try { - sock->impl->listen(backlog); - } catch (...) { - return SOCK_STATUS_FAILED; - } - - return SOCK_STATUS_SUCCESS; -} -extern "C" NETKIT_C_API netkit_sync_sock_t* netkit_sync_sock_accept(netkit_sync_sock_t* sock) { - if (!sock) { - return nullptr; - } - - try { - return from_cstyle(sock->impl->accept()); - } catch (...) { - return nullptr; - } -} -extern "C" NETKIT_C_API int netkit_sync_sock_send(netkit_sync_sock_t* sock, void* buf, size_t len) { - if (!sock) { - return -1; - } - - try { - return sock->impl->send(buf, len); - } catch (...) { - return -1; - } -} -extern "C" NETKIT_C_API void netkit_sync_sock_overflow_bytes(netkit_sync_sock_t* sock, char* buf, size_t len, size_t* out_len) { - if (!sock) { - return; - } - - try { - const auto& bytes = sock->impl->overflow_bytes(); - - if (out_len) { - *out_len = bytes.size() + 1; - } - - std::snprintf(buf, len, "%s", bytes.c_str()); - } catch (...) {} -} -extern "C" NETKIT_C_API void netkit_sync_sock_clear_overflow_bytes(netkit_sync_sock_t* sock) { - if (!sock) { - return; - } - - try { - sock->impl->clear_overflow_bytes(); - } catch (...) {} -} - -extern "C" NETKIT_C_API netkit_recv_result_t* netkit_recv_result_create(void) { - return new netkit_recv_result_t{nullptr, 0}; -} -extern "C" NETKIT_C_API void netkit_recv_result_destroy(netkit_recv_result_t* recv_result) { - if (!recv_result) { - return; - } - delete[] recv_result->data; - recv_result->data = nullptr; - delete recv_result; -} - -extern "C" NETKIT_C_API netkit_recv_status_t netkit_sync_sock_recv(netkit_sync_sock_t* sock, netkit_recv_result_t* out, int timeout_seconds, const char* match, size_t eof) { - if (!sock || !out) { - return RECV_ERROR; - } - - try { - auto ret = sock->impl->recv(timeout_seconds, match ? match : "", eof); - - if (!ret.data.empty()) { - delete[] out->data; - - out->size = ret.data.size(); - out->data = new char[out->size + 1]; - - std::memcpy(out->data, ret.data.data(), out->size); - out->data[out->size] = '\0'; - } - - switch (ret.status) { - case netkit::sock::recv_status::success: - return RECV_SUCCESS; - case netkit::sock::recv_status::timeout: - return RECV_TIMEOUT; - case netkit::sock::recv_status::closed: - return RECV_CLOSED; - default: - return RECV_ERROR; - } - } catch (const std::exception& e) { - return RECV_ERROR; - } catch (...) { - return RECV_ERROR; - } -} - -extern "C" NETKIT_C_API netkit_recv_status_t netkit_sync_sock_basic_recv(netkit_sync_sock_t* sock, netkit_recv_result_t* out) { - if (!sock || !out) { - return RECV_ERROR; - } - - try { - auto ret = sock->impl->recv(); - delete[] out->data; - - out->size = ret.data.size(); - out->data = new char[out->size + 1]; - - std::memcpy(out->data, ret.data.data(), out->size); - out->data[out->size] = '\0'; - - switch (ret.status) { - case netkit::sock::recv_status::success: - return RECV_SUCCESS; - case netkit::sock::recv_status::timeout: - return RECV_TIMEOUT; - case netkit::sock::recv_status::closed: - return RECV_CLOSED; - default: - return RECV_ERROR; - } - } catch (const std::exception& e) { - return RECV_ERROR; - } catch (...) { - return RECV_ERROR; - } -} - -extern "C" NETKIT_C_API void netkit_sync_sock_close(netkit_sync_sock_t* sock) { - if (!sock) { - return; - } - - try { - sock->impl->close(); - } catch (...) {} -} -extern "C" NETKIT_C_API netkit_sock_addr_t* netkit_sync_sock_get_peer(netkit_sync_sock_t* sock) { - if (!sock) { - return nullptr; - } - - try { - auto impl_peer = sock->impl->get_peer(); - return netkit_sock_addr_create(impl_peer.get_hostname().c_str(), impl_peer.get_port(), netkit_sync_sock::get_addr_type(impl_peer.get_type())); - } catch (...) { - return nullptr; - } -} diff --git a/tests/c/definitions.h b/tests/c/definitions.h deleted file mode 100644 index 8dbdc25..0000000 --- a/tests/c/definitions.h +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef DEFINITIONS_H -#define DEFINITIONS_H - -#include -#include - -#define ASSERT(expr) do { \ -if (expr) { \ -printf("[ASSERT PASS] %s:%d: %s\n", \ -__FILE__, __LINE__, #expr); \ -} else { \ -fprintf(stderr, "[ASSERT FAIL] %s:%d: %s\n", \ -__FILE__, __LINE__, #expr); \ -abort(); \ -} \ -} while(0) - -#endif // DEFINITIONS_H \ No newline at end of file diff --git a/tests/c/test_main.c b/tests/c/test_main.c deleted file mode 100644 index 1a995f1..0000000 --- a/tests/c/test_main.c +++ /dev/null @@ -1,7 +0,0 @@ -#include "test_network_utility.h" -#include "test_sock_addr.h" - -int main(void) { - test_network_utility(); - test_sock_addr(); -} \ No newline at end of file diff --git a/tests/c/test_network_utility.c b/tests/c/test_network_utility.c deleted file mode 100644 index c7fde69..0000000 --- a/tests/c/test_network_utility.c +++ /dev/null @@ -1,22 +0,0 @@ -#include -#include -#include -#include "definitions.h" - -void test_network_utility(void) { - char* ipv4 = "0.1.0.1"; - ASSERT(netkit_network_is_ipv4(ipv4, strlen(ipv4)) == 1); - - char* ipv6 = "2001:0db8:85a3:0000:0000:8a2e:0370:7334"; - ASSERT(netkit_network_is_ipv6(ipv6, strlen(ipv6)) == 1); - - char* invalid_ip = "999.999.999.999"; - ASSERT(netkit_network_is_ipv4(invalid_ip, strlen(invalid_ip)) == 0); - - char* invalid_ipv6 = "2001:0db8:85a3:0000:0000:8a2e:0370:zzzz"; - ASSERT(netkit_network_is_ipv6(invalid_ipv6, strlen(invalid_ipv6)) == 0); - - ASSERT(netkit_network_is_valid_port(8080) == 1); - ASSERT(netkit_network_is_valid_port(70000) == 0); - ASSERT(netkit_network_usable_ipv6_address_exists() == 1 || netkit_network_usable_ipv6_address_exists() == 0); -} \ No newline at end of file diff --git a/tests/c/test_network_utility.h b/tests/c/test_network_utility.h deleted file mode 100644 index bbcde48..0000000 --- a/tests/c/test_network_utility.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef TEST_NETWORK_UTILITY_H -#define TEST_NETWORK_UTILITY_H - -void test_network_utility(void); - -#endif \ No newline at end of file diff --git a/tests/c/test_sock_addr.c b/tests/c/test_sock_addr.c deleted file mode 100644 index dbb025c..0000000 --- a/tests/c/test_sock_addr.c +++ /dev/null @@ -1,33 +0,0 @@ -#include "definitions.h" - -#include -#include -#include -#include -#include - -void test_sock_addr(void) { - netkit_sock_addr_t* addr = netkit_sock_addr_create("google.com", 80, SOCK_ADDR_HOSTNAME); - - ASSERT(addr != NULL); - - size_t len; - netkit_sock_addr_get_hostname(addr, NULL, 0, &len); - - char* hostname = malloc(len); - netkit_sock_addr_get_hostname(addr, hostname, len, &len); - - ASSERT(!strncmp(hostname, "google.com", len)); - ASSERT(80 == netkit_sock_addr_get_port(addr)); - ASSERT(SOCK_ADDR_HOSTNAME == netkit_sock_addr_get_type(addr)); - - free(hostname); - netkit_sock_addr_destroy(addr); - - addr = netkit_sock_addr_create_unix("/tmp/socket"); - - ASSERT(addr != NULL); - ASSERT(netkit_sock_addr_get_type(addr) == SOCK_ADDR_FILENAME); - - netkit_sock_addr_destroy(addr); -} \ No newline at end of file diff --git a/tests/c/test_sock_addr.h b/tests/c/test_sock_addr.h deleted file mode 100644 index b89c74e..0000000 --- a/tests/c/test_sock_addr.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef TEST_SOCK_ADDR_H -#define TEST_SOCK_ADDR_H - -void test_sock_addr(void); - -#endif \ No newline at end of file