Add socket abstraction

This commit is contained in:
Maurice Heumann
2025-03-20 15:17:43 +01:00
parent 2cb14a3555
commit 4da6642123
15 changed files with 437 additions and 71 deletions

View File

@@ -4,6 +4,8 @@
#include <gtest/gtest.h>
#include <windows_emulator.hpp>
#include "static_socket_factory.hpp"
#define ASSERT_NOT_TERMINATED(win_emu) \
do \
{ \
@@ -40,7 +42,6 @@ namespace test
struct sample_configuration
{
bool reproducible{false};
bool print_time{false};
};
@@ -53,11 +54,6 @@ namespace test
settings.arguments.emplace_back(u"-time");
}
if (config.reproducible)
{
settings.arguments.emplace_back(u"-reproducible");
}
return settings;
}
@@ -74,7 +70,6 @@ namespace test
settings.emulation_root = get_emulator_root();
settings.port_mappings[28970] = static_cast<uint16_t>(getpid());
settings.path_mappings["C:\\a.txt"] =
std::filesystem::temp_directory_path() / ("emulator-test-file-" + std::to_string(getpid()) + ".txt");
@@ -82,6 +77,9 @@ namespace test
get_sample_app_settings(config),
settings,
std::move(callbacks),
emulator_interfaces{
.socket_factory = network::create_static_socket_factory(),
},
};
}
@@ -97,7 +95,7 @@ namespace test
inline windows_emulator create_reproducible_sample_emulator()
{
return create_sample_emulator({.reproducible = true});
return create_sample_emulator();
}
inline void bisect_emulation(windows_emulator& emu)

View File

@@ -84,7 +84,13 @@ namespace test
utils::buffer_deserializer deserializer{serializer.get_buffer()};
windows_emulator new_emu{{.emulation_root = get_emulator_root(), .use_relative_time = true}};
windows_emulator new_emu{
{.emulation_root = get_emulator_root(), .use_relative_time = true},
{
.socket_factory = network::create_static_socket_factory(),
},
};
new_emu.log.disable_output(true);
new_emu.deserialize(deserializer);

View File

@@ -0,0 +1,129 @@
#include "static_socket_factory.hpp"
#include <queue>
#include <stdexcept>
#include <unordered_map>
#include <network/socket.hpp>
namespace network
{
namespace
{
struct static_socket_factory : socket_factory
{
using packet_data = std::vector<std::byte>;
using packet = std::pair<address, packet_data>;
using packet_queue = std::queue<packet>;
using packet_mapping = std::unordered_map<address, packet_queue>;
std::shared_ptr<packet_mapping> packets = std::make_shared<packet_mapping>();
uint16_t port{0};
struct static_socket : i_socket
{
int error{0};
address a{};
std::shared_ptr<packet_mapping> packets{};
static_socket(static_socket_factory& f, const int af)
: packets(f.packets)
{
if (af == AF_INET)
{
a.set_ipv4(0);
}
else if (af == AF_INET6)
{
a.set_ipv6({});
}
else
{
throw std::runtime_error("Invalid address family");
}
a.set_port(++f.port);
}
~static_socket() override = default;
void set_blocking(const bool blocking) override
{
if (blocking)
{
throw std::runtime_error("Blocking sockets not supported yet!");
}
}
int get_last_error() override
{
return this->error;
}
bool is_ready(const bool) override
{
return true;
}
bool bind(const address& addr) override
{
this->a = addr;
return true;
}
sent_size send(std::span<const std::byte>) override
{
throw std::runtime_error("Not implemented");
}
sent_size sendto(const address& destination, std::span<const std::byte> data) override
{
this->error = 0;
(*this->packets)[destination].emplace(this->a, packet_data{data.begin(), data.end()});
return static_cast<int>(data.size());
}
sent_size recv(std::span<std::byte>) override
{
throw std::runtime_error("Not implemented");
}
sent_size recvfrom(address& source, std::span<std::byte> data) override
{
this->error = 0;
auto& q = (*this->packets)[this->a];
if (q.empty())
{
this->error = SERR(EWOULDBLOCK);
return -1;
}
const auto p = std::move(q.front());
q.pop();
memcpy(data.data(), p.second.data(), std::min(data.size(), p.second.size()));
source = p.first;
return static_cast<int>(p.second.size());
}
};
std::unique_ptr<i_socket> create_socket(const int af, const int, const int) override
{
return std::make_unique<static_socket>(*this, af);
}
int poll_sockets(std::span<poll_entry>) override
{
throw std::runtime_error("Not implemented");
}
};
}
std::unique_ptr<socket_factory> create_static_socket_factory()
{
return std::make_unique<static_socket_factory>();
}
}

View File

@@ -0,0 +1,8 @@
#pragma once
#include <network/socket_factory.hpp>
namespace network
{
std::unique_ptr<socket_factory> create_static_socket_factory();
}