Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
431 changes: 335 additions & 96 deletions .idea/editor.xml

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions examples/cpp/uds_server/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
*build*
15 changes: 15 additions & 0 deletions examples/cpp/uds_server/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
cmake_minimum_required(VERSION 3.11)

project(netkit-example LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 23)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)

find_package(netkit)

add_executable(
netkit-example
main.cpp
)
target_link_libraries(netkit-example PRIVATE netkit::netkit)
20 changes: 20 additions & 0 deletions examples/cpp/uds_server/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#include <iostream>
#include <fstream>
#include <string_view>
#include <netkit/netkit.hpp>

int main() {
netkit::sock::addr addr("/tmp/test.sock");
netkit::sock::sync_sock sock(addr, netkit::sock::type::unix);

sock.bind();
sock.listen();

while (true) {
auto rec = sock.accept();
auto buffer = rec->recv().data;
std::cout << buffer << "\n";
}

return 0;
}
1 change: 1 addition & 0 deletions include/netkit-c/sock/sync_sock.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ 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);

Expand Down
502 changes: 254 additions & 248 deletions include/netkit/http/request_handler.hpp

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion include/netkit/sock/basic_sync_sock.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ namespace netkit::sock {
[[nodiscard]] virtual recv_result recv(int timeout_seconds, const std::string& match) = 0;
[[nodiscard]] virtual recv_result recv(int timeout_seconds, const std::string& match, size_t eof) = 0;
[[nodiscard]] virtual recv_result recv(int timeout_seconds, size_t eof) = 0;
[[nodiscard]] virtual recv_result primitive_recv() = 0;
[[nodiscard]] virtual recv_result recv() = 0;
[[nodiscard]] virtual std::string overflow_bytes() const = 0;
virtual addr& get_addr() = 0;
[[nodiscard]] virtual const addr& get_addr() const = 0;
Expand Down
7 changes: 6 additions & 1 deletion include/netkit/sock/sync_sock.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,12 @@ namespace netkit::sock {
* @return The received data as a sock_recv_result object.
*/
[[nodiscard]] recv_result recv(int timeout_seconds, const std::string& match, size_t eof) override;
[[nodiscard]] recv_result primitive_recv() override;
/**
* @brief Receive data from the server.
* @note This is a recv() implementation that behaves like a Unix recv() call would.
* @return The received data as a sock_recv_result object.
*/
[[nodiscard]] recv_result recv() override;

/* @brief Receive data from the server.
* @param timeout_seconds The timeout in seconds (-1 means wait indefinitely).
Expand Down
32 changes: 32 additions & 0 deletions src/c/sock/sync_sock.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,38 @@ extern "C" NETKIT_C_API netkit_recv_status_t netkit_sync_sock_recv(netkit_sync_s
}
}

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;
Expand Down
2 changes: 1 addition & 1 deletion src/sock/openssl/ssl_sync_sock_openssl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -345,7 +345,7 @@ void netkit::sock::ssl_sync_sock::drain_write_bio() const {
}

void netkit::sock::ssl_sync_sock::feed_read_bio_blocking() const {
auto res = underlying_sock_->primitive_recv();
auto res = underlying_sock_->recv();

if (res.status == sock::recv_status::closed) {
if (!handshake_complete_) {
Expand Down
6 changes: 3 additions & 3 deletions src/sock/sock_peer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,9 @@ netkit::sock::addr netkit::sock::get_peer(fd_t sockfd) {
inet_ntop(AF_INET, &(addr_in->sin_addr), ip_str, sizeof(ip_str));
port = ntohs(addr_in->sin_port);
} else if (addr_storage.ss_family == AF_INET6) {
auto* addr_in6 = reinterpret_cast<sockaddr_in6*>(&addr_storage);
inet_ntop(AF_INET6, &(addr_in6->sin6_addr), ip_str, sizeof(ip_str));
port = ntohs(addr_in6->sin6_port);
auto* addr_in6 = reinterpret_cast<sockaddr_in6*>(&addr_storage);
inet_ntop(AF_INET6, &(addr_in6->sin6_addr), ip_str, sizeof(ip_str));
port = ntohs(addr_in6->sin6_port);
} else {
throw ip_error("unsupported address family");
}
Expand Down
18 changes: 12 additions & 6 deletions src/sock/sync_sock.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -180,9 +180,11 @@ void netkit::sock::sync_sock::set_sock_opts(opt opts) const {
netkit::sock::sync_sock::sync_sock(const sock::addr& addr, sock::type t, opt opts) : addr_(addr), type_(t) {
this->sockfd = -1;

if (addr.get_ip().empty() && !addr.is_file_path()) {
throw socket_error("IP address/file path is empty");
}
if (!addr.is_file_path()) {
if (addr.get_ip().empty()) {
throw socket_error("IP address/file path is empty");
}
}

if (t != type::unix) {
this->sockfd = ::socket(addr.is_ipv6() ? AF_INET6 : AF_INET,
Expand Down Expand Up @@ -363,6 +365,10 @@ std::unique_ptr<netkit::sock::basic_sync_sock> netkit::sock::sync_sock::accept()
throw socket_error("failed to accept connection: " + std::string(strerror(errno)));
}

if (this->type_ == type::unix) {
return std::make_unique<sync_sock>(client_sockfd, sock::addr(reinterpret_cast<const sockaddr_un*>(&client_addr)->sun_path), this->type_);
}

auto peer = sock::get_peer(client_sockfd);

return std::make_unique<sync_sock>(client_sockfd, peer, this->type_);
Expand Down Expand Up @@ -514,7 +520,7 @@ netkit::sock::recv_result netkit::sock::sync_sock::recv(const int timeout_second
}
}

netkit::sock::recv_result netkit::sock::sync_sock::primitive_recv() {
netkit::sock::recv_result netkit::sock::sync_sock::recv() {
for (;;) {
char buf[8192];
ssize_t n = ::recv(this->sockfd, buf, sizeof(buf), 0);
Expand Down Expand Up @@ -619,7 +625,7 @@ netkit::sock::recv_result netkit::sock::sync_sock::recv(const int timeout_second
}
}

netkit::sock::recv_result netkit::sock::sync_sock::primitive_recv() {
netkit::sock::recv_result netkit::sock::sync_sock::recv() {
constexpr size_t buffer_size = 8192;
char buf[buffer_size];

Expand Down Expand Up @@ -679,4 +685,4 @@ void netkit::sock::sync_sock::close() {
#endif
[[nodiscard]] netkit::sock::addr netkit::sock::sync_sock::get_peer() const {
return netkit::sock::get_peer(this->sockfd);
}
}
44 changes: 44 additions & 0 deletions tests/test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include <catch2/catch_test_macros.hpp>
#include <set>
#include <unordered_set>
#include <thread>

TEST_CASE("Ensure addr works", "[sock_addr]") {
netkit::sock::addr addr("google.com", 443, netkit::sock::addr_type::hostname);
Expand Down Expand Up @@ -128,4 +129,47 @@ TEST_CASE("Ensure general utility functions work", "[utility]") {
REQUIRE(tokens[4] == "five");
std::string joined = netkit::utility::join(tokens, ",");
REQUIRE(joined == to_split);
}

TEST_CASE("Ensure basic sockets work", "[socket]") {
std::thread t([]() {
netkit::sock::addr addr("127.0.0.1", 1337, netkit::sock::addr_type::ipv4);
netkit::sock::sync_sock sock(addr, netkit::sock::type::tcp);

sock.bind();
sock.listen();

while (true) {
auto result = sock.recv(-1);
if (result.status != netkit::sock::recv_status::success) {
return;
}

if (result.status == netkit::sock::recv_status::success) {
std::string data = result.data;
REQUIRE(data == "Hello, World!");
sock.send("Hello, World!");
}
}

sock.unbind();
});
t.detach();

std::this_thread::sleep_for(std::chrono::milliseconds(1000));

netkit::sock::addr addr("127.0.0.1", 1337, netkit::sock::addr_type::ipv4);
netkit::sock::sync_sock sock(addr, netkit::sock::type::tcp);

sock.connect();
sock.send("Hello, World!");
auto result = sock.recv(-1);
if (result.status == netkit::sock::recv_status::success) {
std::string data = result.data;
REQUIRE(data == "Hello, World!");
} else {
REQUIRE(false); // fail the test if we didn't receive a response
}

t.join();
}
Loading