mirror of
https://github.com/momo5502/emulator.git
synced 2026-01-31 00:11:02 +00:00
Add socket abstraction
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
129
src/windows-emulator-test/static_socket_factory.cpp
Normal file
129
src/windows-emulator-test/static_socket_factory.cpp
Normal 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>();
|
||||
}
|
||||
}
|
||||
8
src/windows-emulator-test/static_socket_factory.hpp
Normal file
8
src/windows-emulator-test/static_socket_factory.hpp
Normal file
@@ -0,0 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#include <network/socket_factory.hpp>
|
||||
|
||||
namespace network
|
||||
{
|
||||
std::unique_ptr<socket_factory> create_static_socket_factory();
|
||||
}
|
||||
Reference in New Issue
Block a user