Merge branch 'dev'
commit
102bf7e174
|
@ -59,7 +59,7 @@ Mkfile.old
|
|||
dkms.conf
|
||||
|
||||
# binary files
|
||||
bin/
|
||||
build/
|
||||
# test files
|
||||
assets/
|
||||
# custom build tracking
|
||||
|
|
29
SConstruct
29
SConstruct
|
@ -29,7 +29,20 @@ def add_kel_source_files(self, sources, filetype, lib_env=None, shared=False, ta
|
|||
sources.append( self.StaticObject( target=target_name, source=path ) )
|
||||
pass
|
||||
|
||||
env=Environment(ENV=os.environ, CPPPATH=['#source/forstio','#source','#','#driver'],
|
||||
def isAbsolutePath(key, dirname, env):
|
||||
assert os.path.isabs(dirname), "%r must have absolute path syntax" % (key,)
|
||||
|
||||
env_vars = Variables(
|
||||
args=ARGUMENTS
|
||||
)
|
||||
|
||||
env_vars.Add('prefix',
|
||||
help='Installation target location of build results and headers',
|
||||
default='/usr/local/',
|
||||
validator=isAbsolutePath
|
||||
)
|
||||
|
||||
env=Environment(ENV=os.environ, variables=env_vars, CPPPATH=['#source/forstio','#source','#','#driver'],
|
||||
CXX='clang++',
|
||||
CPPDEFINES=['SAW_UNIX'],
|
||||
CXXFLAGS=['-std=c++20','-g','-Wall','-Wextra'],
|
||||
|
@ -56,11 +69,11 @@ env_library = env.Clone()
|
|||
|
||||
env.objects_shared = []
|
||||
env_library.add_source_files(env.objects_shared, env.sources + env.driver_sources + env.tls_sources, shared=True)
|
||||
env.library_shared = env_library.SharedLibrary('#bin/forstio', [env.objects_shared])
|
||||
env.library_shared = env_library.SharedLibrary('#build/forstio', [env.objects_shared])
|
||||
|
||||
env.objects_static = []
|
||||
env_library.add_source_files(env.objects_static, env.sources + env.driver_sources + env.tls_sources)
|
||||
env.library_static = env_library.StaticLibrary('#bin/forstio', [env.objects_static])
|
||||
env.library_static = env_library.StaticLibrary('#build/forstio', [env.objects_static])
|
||||
|
||||
env.Alias('library', [env.library_shared, env.library_static])
|
||||
env.Alias('library_shared', env.library_shared)
|
||||
|
@ -87,9 +100,9 @@ env.Alias('format', env.format_actions)
|
|||
|
||||
env.Alias('all', ['format', 'library_shared', 'library_static', 'test'])
|
||||
|
||||
env.Install('/usr/local/lib/', [env.library_shared, env.library_static])
|
||||
env.Install('/usr/local/include/forstio/', [env.headers])
|
||||
env.Install('/usr/local/include/forstio/tls/', [env.tls_headers])
|
||||
env.Install('$prefix/lib/', [env.library_shared, env.library_static])
|
||||
env.Install('$prefix/include/forstio/', [env.headers])
|
||||
env.Install('$prefix/include/forstio/tls/', [env.tls_headers])
|
||||
|
||||
env.Install('/usr/local/include/forstio/test/', [env.test_headers])
|
||||
env.Alias('install', '/usr/local/')
|
||||
env.Install('$prefix/include/forstio/test/', [env.test_headers])
|
||||
env.Alias('install', '$prefix')
|
||||
|
|
|
@ -124,31 +124,145 @@ void UnixServer::notify(uint32_t mask) {
|
|||
}
|
||||
}
|
||||
|
||||
UnixDatagram::UnixDatagram(UnixEventPort &event_port, int file_descriptor,
|
||||
int fd_flags)
|
||||
: IFdOwner{event_port, file_descriptor, fd_flags, EPOLLIN | EPOLLOUT} {}
|
||||
|
||||
namespace {
|
||||
ssize_t unixReadMsg(int fd, void *buffer, size_t length) {
|
||||
struct ::sockaddr_storage their_addr;
|
||||
socklen_t addr_len = sizeof(sockaddr_storage);
|
||||
return ::recvfrom(fd, buffer, length, 0,
|
||||
reinterpret_cast<struct ::sockaddr *>(&their_addr),
|
||||
&addr_len);
|
||||
}
|
||||
|
||||
ssize_t unixWriteMsg(int fd, const void *buffer, size_t length,
|
||||
::sockaddr *dest_addr, socklen_t dest_addr_len) {
|
||||
|
||||
return ::sendto(fd, buffer, length, 0, dest_addr, dest_addr_len);
|
||||
}
|
||||
} // namespace
|
||||
|
||||
ErrorOr<size_t> UnixDatagram::read(void *buffer, size_t length) {
|
||||
ssize_t read_bytes = unixReadMsg(fd(), buffer, length);
|
||||
if (read_bytes > 0) {
|
||||
return static_cast<size_t>(read_bytes);
|
||||
}
|
||||
return recoverableError("Currently busy");
|
||||
}
|
||||
|
||||
Conveyor<void> UnixDatagram::readReady() {
|
||||
auto caf = newConveyorAndFeeder<void>();
|
||||
read_ready = std::move(caf.feeder);
|
||||
return std::move(caf.conveyor);
|
||||
}
|
||||
|
||||
ErrorOr<size_t> UnixDatagram::write(const void *buffer, size_t length,
|
||||
NetworkAddress &dest) {
|
||||
UnixNetworkAddress &unix_dest = static_cast<UnixNetworkAddress &>(dest);
|
||||
SocketAddress &sock_addr = unix_dest.unixAddress();
|
||||
socklen_t sock_addr_length = sock_addr.getRawLength();
|
||||
ssize_t write_bytes = unixWriteMsg(fd(), buffer, length, sock_addr.getRaw(),
|
||||
sock_addr_length);
|
||||
if (write_bytes > 0) {
|
||||
return static_cast<size_t>(write_bytes);
|
||||
}
|
||||
return recoverableError("Currently busy");
|
||||
}
|
||||
|
||||
Conveyor<void> UnixDatagram::writeReady() {
|
||||
auto caf = newConveyorAndFeeder<void>();
|
||||
write_ready = std::move(caf.feeder);
|
||||
return std::move(caf.conveyor);
|
||||
}
|
||||
|
||||
void UnixDatagram::notify(uint32_t mask) {
|
||||
if (mask & EPOLLOUT) {
|
||||
if (write_ready) {
|
||||
write_ready->feed();
|
||||
}
|
||||
}
|
||||
|
||||
if (mask & EPOLLIN) {
|
||||
if (read_ready) {
|
||||
read_ready->feed();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
namespace {
|
||||
bool beginsWith(const std::string_view &viewed,
|
||||
const std::string_view &begins) {
|
||||
return viewed.size() >= begins.size() &&
|
||||
viewed.compare(0, begins.size(), begins) == 0;
|
||||
}
|
||||
|
||||
std::variant<UnixNetworkAddress, UnixNetworkAddress *>
|
||||
translateNetworkAddressToUnixNetworkAddress(NetworkAddress &addr) {
|
||||
auto addr_variant = addr.representation();
|
||||
std::variant<UnixNetworkAddress, UnixNetworkAddress *> os_addr = std::visit(
|
||||
[](auto &arg)
|
||||
-> std::variant<UnixNetworkAddress, UnixNetworkAddress *> {
|
||||
using T = std::decay_t<decltype(arg)>;
|
||||
|
||||
if constexpr (std::is_same_v<T, OsNetworkAddress *>) {
|
||||
return static_cast<UnixNetworkAddress *>(arg);
|
||||
}
|
||||
|
||||
auto sock_addrs = SocketAddress::parse(
|
||||
std::string_view{arg->address()}, arg->port());
|
||||
|
||||
return UnixNetworkAddress{arg->address(), arg->port(),
|
||||
std::move(sock_addrs)};
|
||||
},
|
||||
addr_variant);
|
||||
return os_addr;
|
||||
}
|
||||
|
||||
UnixNetworkAddress &translateToUnixAddressRef(
|
||||
std::variant<UnixNetworkAddress, UnixNetworkAddress *> &addr_variant) {
|
||||
return std::visit(
|
||||
[](auto &arg) -> UnixNetworkAddress & {
|
||||
using T = std::decay_t<decltype(arg)>;
|
||||
|
||||
if constexpr (std::is_same_v<T, UnixNetworkAddress>) {
|
||||
return arg;
|
||||
} else if constexpr (std::is_same_v<T, UnixNetworkAddress *>) {
|
||||
return *arg;
|
||||
} else {
|
||||
static_assert(true, "Cases exhausted");
|
||||
}
|
||||
},
|
||||
addr_variant);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
Own<Server> UnixNetworkAddress::listen() {
|
||||
assert(addresses.size() > 0);
|
||||
if (addresses.size() == 0) {
|
||||
Own<Server> UnixNetwork::listen(NetworkAddress &addr) {
|
||||
auto unix_addr_storage = translateNetworkAddressToUnixNetworkAddress(addr);
|
||||
UnixNetworkAddress &address = translateToUnixAddressRef(unix_addr_storage);
|
||||
|
||||
assert(address.unixAddressSize() > 0);
|
||||
if (address.unixAddressSize() == 0) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
int fd = addresses.front().socket(SOCK_STREAM);
|
||||
int fd = address.unixAddress(0).socket(SOCK_STREAM);
|
||||
if (fd < 0) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
int val = 1;
|
||||
int rc = ::setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val));
|
||||
if (rc < 0) {
|
||||
::close(fd);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
::setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val));
|
||||
|
||||
bool failed = addresses.front().bind(fd);
|
||||
bool failed = address.unixAddress(0).bind(fd);
|
||||
if (failed) {
|
||||
::close(fd);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
@ -157,13 +271,16 @@ Own<Server> UnixNetworkAddress::listen() {
|
|||
return heap<UnixServer>(event_port, fd, 0);
|
||||
}
|
||||
|
||||
Conveyor<Own<IoStream>> UnixNetworkAddress::connect() {
|
||||
assert(addresses.size() > 0);
|
||||
if (addresses.size() == 0) {
|
||||
Conveyor<Own<IoStream>> UnixNetwork::connect(NetworkAddress &addr) {
|
||||
auto unix_addr_storage = translateNetworkAddressToUnixNetworkAddress(addr);
|
||||
UnixNetworkAddress &address = translateToUnixAddressRef(unix_addr_storage);
|
||||
|
||||
assert(address.unixAddressSize() > 0);
|
||||
if (address.unixAddressSize() == 0) {
|
||||
return Conveyor<Own<IoStream>>{criticalError("No address found")};
|
||||
}
|
||||
|
||||
int fd = addresses.front().socket(SOCK_STREAM);
|
||||
int fd = address.unixAddress(0).socket(SOCK_STREAM);
|
||||
if (fd < 0) {
|
||||
return Conveyor<Own<IoStream>>{criticalError("Couldn't open socket")};
|
||||
}
|
||||
|
@ -172,8 +289,10 @@ Conveyor<Own<IoStream>> UnixNetworkAddress::connect() {
|
|||
heap<UnixIoStream>(event_port, fd, 0, EPOLLIN | EPOLLOUT);
|
||||
|
||||
bool success = false;
|
||||
for (auto iter = addresses.begin(); iter != addresses.end(); ++iter) {
|
||||
int status = ::connect(fd, iter->getRaw(), iter->getRawLength());
|
||||
for (size_t i = 0; i < address.unixAddressSize(); ++i) {
|
||||
SocketAddress &addr_iter = address.unixAddress(i);
|
||||
int status =
|
||||
::connect(fd, addr_iter.getRaw(), addr_iter.getRawLength());
|
||||
if (status < 0) {
|
||||
int error = errno;
|
||||
/*
|
||||
|
@ -212,22 +331,43 @@ Conveyor<Own<IoStream>> UnixNetworkAddress::connect() {
|
|||
return Conveyor<Own<IoStream>>{std::move(io_stream)};
|
||||
}
|
||||
|
||||
std::string UnixNetworkAddress::toString() const {
|
||||
try {
|
||||
std::ostringstream oss;
|
||||
oss << "Address: " << path;
|
||||
if (port_hint > 0) {
|
||||
oss << "\nPort: " << port_hint;
|
||||
}
|
||||
return oss.str();
|
||||
} catch (std::bad_alloc &) {
|
||||
return {};
|
||||
Own<Datagram> UnixNetwork::datagram(NetworkAddress &addr) {
|
||||
auto unix_addr_storage = translateNetworkAddressToUnixNetworkAddress(addr);
|
||||
UnixNetworkAddress &address = translateToUnixAddressRef(unix_addr_storage);
|
||||
|
||||
SAW_ASSERT(address.unixAddressSize() > 0) { return nullptr; }
|
||||
|
||||
int fd = address.unixAddress(0).socket(SOCK_DGRAM);
|
||||
|
||||
int optval = 1;
|
||||
int rc =
|
||||
::setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval));
|
||||
if (rc < 0) {
|
||||
::close(fd);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool failed = address.unixAddress(0).bind(fd);
|
||||
if (failed) {
|
||||
::close(fd);
|
||||
return nullptr;
|
||||
}
|
||||
/// @todo
|
||||
return heap<UnixDatagram>(event_port, fd, 0);
|
||||
}
|
||||
|
||||
const std::string &UnixNetworkAddress::address() const { return path; }
|
||||
|
||||
uint16_t UnixNetworkAddress::port() const { return port_hint; }
|
||||
|
||||
SocketAddress &UnixNetworkAddress::unixAddress(size_t i) {
|
||||
assert(i < addresses.size());
|
||||
/// @todo change from list to vector?
|
||||
return addresses.at(i);
|
||||
}
|
||||
|
||||
size_t UnixNetworkAddress::unixAddressSize() const { return addresses.size(); }
|
||||
|
||||
UnixNetwork::UnixNetwork(UnixEventPort &event) : event_port{event} {}
|
||||
|
||||
Conveyor<Own<NetworkAddress>> UnixNetwork::parseAddress(const std::string &path,
|
||||
|
@ -240,29 +380,11 @@ Conveyor<Own<NetworkAddress>> UnixNetwork::parseAddress(const std::string &path,
|
|||
}
|
||||
}
|
||||
|
||||
std::list<SocketAddress> addresses =
|
||||
std::vector<SocketAddress> addresses =
|
||||
SocketAddress::parse(addr_view, port_hint);
|
||||
|
||||
return Conveyor<Own<NetworkAddress>>{heap<UnixNetworkAddress>(
|
||||
event_port, path, port_hint, std::move(addresses))};
|
||||
}
|
||||
|
||||
ErrorOr<SocketPair> UnixNetwork::socketPair() {
|
||||
int sv[2];
|
||||
|
||||
int rc = ::socketpair(AF_LOCAL, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK,
|
||||
0, sv);
|
||||
if (rc < 0) {
|
||||
return criticalError("Failed to create socket pair");
|
||||
}
|
||||
|
||||
SocketPair socket_pair;
|
||||
socket_pair.stream[0] =
|
||||
heap<UnixIoStream>(event_port, sv[0], 0, EPOLLIN | EPOLLOUT);
|
||||
socket_pair.stream[1] =
|
||||
heap<UnixIoStream>(event_port, sv[1], 0, EPOLLIN | EPOLLOUT);
|
||||
|
||||
return socket_pair;
|
||||
return Conveyor<Own<NetworkAddress>>{
|
||||
heap<UnixNetworkAddress>(path, port_hint, std::move(addresses))};
|
||||
}
|
||||
|
||||
UnixIoProvider::UnixIoProvider(UnixEventPort &port_ref, Own<EventPort> port)
|
||||
|
|
|
@ -312,6 +312,27 @@ public:
|
|||
void notify(uint32_t mask) override;
|
||||
};
|
||||
|
||||
class UnixDatagram final : public Datagram, public IFdOwner {
|
||||
private:
|
||||
Own<ConveyorFeeder<void>> read_ready = nullptr;
|
||||
Own<ConveyorFeeder<void>> write_ready = nullptr;
|
||||
|
||||
public:
|
||||
UnixDatagram(UnixEventPort &event_port, int file_descriptor, int fd_flags);
|
||||
|
||||
ErrorOr<size_t> read(void *buffer, size_t length) override;
|
||||
Conveyor<void> readReady() override;
|
||||
|
||||
ErrorOr<size_t> write(const void *buffer, size_t length,
|
||||
NetworkAddress &dest) override;
|
||||
Conveyor<void> writeReady() override;
|
||||
|
||||
void notify(uint32_t mask) override;
|
||||
};
|
||||
|
||||
/**
|
||||
* Helper class which provides potential addresses to NetworkAddress
|
||||
*/
|
||||
class SocketAddress {
|
||||
private:
|
||||
union {
|
||||
|
@ -335,8 +356,6 @@ public:
|
|||
}
|
||||
|
||||
int socket(int type) const {
|
||||
bool is_stream = type & SOCK_STREAM;
|
||||
|
||||
type |= SOCK_NONBLOCK | SOCK_CLOEXEC;
|
||||
|
||||
int result = ::socket(address.generic.sa_family, type, 0);
|
||||
|
@ -352,13 +371,17 @@ public:
|
|||
return error < 0;
|
||||
}
|
||||
|
||||
struct ::sockaddr *getRaw() {
|
||||
return &address.generic;
|
||||
}
|
||||
|
||||
const struct ::sockaddr *getRaw() const { return &address.generic; }
|
||||
|
||||
socklen_t getRawLength() const { return address_length; }
|
||||
|
||||
static std::list<SocketAddress> parse(std::string_view str,
|
||||
uint16_t port_hint) {
|
||||
std::list<SocketAddress> results;
|
||||
static std::vector<SocketAddress> parse(std::string_view str,
|
||||
uint16_t port_hint) {
|
||||
std::vector<SocketAddress> results;
|
||||
|
||||
struct ::addrinfo *head;
|
||||
struct ::addrinfo hints;
|
||||
|
@ -387,27 +410,24 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
class UnixNetworkAddress final : public NetworkAddress {
|
||||
class UnixNetworkAddress final : public OsNetworkAddress {
|
||||
private:
|
||||
UnixEventPort &event_port;
|
||||
const std::string path;
|
||||
uint16_t port_hint;
|
||||
std::list<SocketAddress> addresses;
|
||||
std::vector<SocketAddress> addresses;
|
||||
|
||||
public:
|
||||
UnixNetworkAddress(UnixEventPort &event_port, const std::string &path,
|
||||
uint16_t port_hint, std::list<SocketAddress> &&addr)
|
||||
: event_port{event_port}, path{path}, port_hint{port_hint},
|
||||
addresses{std::move(addr)} {}
|
||||
|
||||
Own<Server> listen() override;
|
||||
Conveyor<Own<IoStream>> connect() override;
|
||||
|
||||
std::string toString() const override;
|
||||
UnixNetworkAddress(const std::string &path, uint16_t port_hint,
|
||||
std::vector<SocketAddress> &&addr)
|
||||
: path{path}, port_hint{port_hint}, addresses{std::move(addr)} {}
|
||||
|
||||
const std::string &address() const override;
|
||||
|
||||
uint16_t port() const override;
|
||||
|
||||
// Custom address info
|
||||
SocketAddress &unixAddress(size_t i = 0);
|
||||
size_t unixAddressSize() const;
|
||||
};
|
||||
|
||||
class UnixNetwork final : public Network {
|
||||
|
@ -420,7 +440,11 @@ public:
|
|||
Conveyor<Own<NetworkAddress>> parseAddress(const std::string &address,
|
||||
uint16_t port_hint = 0) override;
|
||||
|
||||
ErrorOr<SocketPair> socketPair() override;
|
||||
Own<Server> listen(NetworkAddress &addr) override;
|
||||
|
||||
Conveyor<Own<IoStream>> connect(NetworkAddress &addr) override;
|
||||
|
||||
Own<Datagram> datagram(NetworkAddress &addr) override;
|
||||
};
|
||||
|
||||
class UnixIoProvider final : public IoProvider {
|
||||
|
|
|
@ -91,11 +91,11 @@ public:
|
|||
virtual ~ErrorOrValue() = default;
|
||||
|
||||
template <typename T> ErrorOr<UnfixVoid<T>> &as() {
|
||||
return dynamic_cast<ErrorOr<UnfixVoid<T>> &>(*this);
|
||||
return static_cast<ErrorOr<UnfixVoid<T>> &>(*this);
|
||||
}
|
||||
|
||||
template <typename T> const ErrorOr<UnfixVoid<T>> &as() const {
|
||||
return dynamic_cast<const ErrorOr<UnfixVoid<T>> &>(*this);
|
||||
return static_cast<const ErrorOr<UnfixVoid<T>> &>(*this);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -58,4 +58,14 @@ Conveyor<size_t> AsyncIoStream::writeDone() {
|
|||
write_stepper.write_done = std::move(caf.feeder);
|
||||
return std::move(caf.conveyor);
|
||||
}
|
||||
} // namespace saw
|
||||
|
||||
StringNetworkAddress::StringNetworkAddress(const std::string &address,
|
||||
uint16_t port)
|
||||
: address_value{address}, port_value{port} {}
|
||||
|
||||
const std::string &StringNetworkAddress::address() const {
|
||||
return address_value;
|
||||
}
|
||||
|
||||
uint16_t StringNetworkAddress::port() const { return port_value; }
|
||||
} // namespace saw
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#include "io_helpers.h"
|
||||
|
||||
#include <string>
|
||||
#include <variant>
|
||||
|
||||
namespace saw {
|
||||
/*
|
||||
|
@ -74,7 +75,7 @@ private:
|
|||
public:
|
||||
AsyncIoStream(Own<IoStream> str);
|
||||
|
||||
void read(void *buffer, size_t min_length, size_t max_length) override;
|
||||
void read(void *buffer, size_t length, size_t max_length) override;
|
||||
|
||||
Conveyor<size_t> readDone() override;
|
||||
|
||||
|
@ -92,38 +93,85 @@ public:
|
|||
virtual Conveyor<Own<IoStream>> accept() = 0;
|
||||
};
|
||||
|
||||
class SocketPair {
|
||||
class NetworkAddress;
|
||||
/**
|
||||
* Datagram class. Bound to a local address it is able to receive inbound
|
||||
* datagram messages and send them as well as long as an address is provided as
|
||||
* well
|
||||
*/
|
||||
class Datagram {
|
||||
public:
|
||||
std::array<Own<IoStream>, 2> stream;
|
||||
virtual ~Datagram() = default;
|
||||
|
||||
virtual ErrorOr<size_t> read(void *buffer, size_t length) = 0;
|
||||
virtual Conveyor<void> readReady() = 0;
|
||||
|
||||
virtual ErrorOr<size_t> write(const void *buffer, size_t length,
|
||||
NetworkAddress &dest) = 0;
|
||||
virtual Conveyor<void> writeReady() = 0;
|
||||
};
|
||||
|
||||
class OsNetworkAddress;
|
||||
class StringNetworkAddress;
|
||||
|
||||
class NetworkAddress {
|
||||
public:
|
||||
using ChildVariant =
|
||||
std::variant<OsNetworkAddress *, StringNetworkAddress *>;
|
||||
|
||||
virtual ~NetworkAddress() = default;
|
||||
|
||||
/*
|
||||
* Listen on this address
|
||||
*/
|
||||
virtual Own<Server> listen() = 0;
|
||||
virtual Conveyor<Own<IoStream>> connect() = 0;
|
||||
|
||||
virtual std::string toString() const = 0;
|
||||
virtual NetworkAddress::ChildVariant representation() = 0;
|
||||
|
||||
virtual const std::string &address() const = 0;
|
||||
virtual uint16_t port() const = 0;
|
||||
};
|
||||
|
||||
class OsNetworkAddress : public NetworkAddress {
|
||||
public:
|
||||
virtual ~OsNetworkAddress() = default;
|
||||
|
||||
NetworkAddress::ChildVariant representation() override { return this; }
|
||||
};
|
||||
|
||||
class StringNetworkAddress final : public NetworkAddress {
|
||||
private:
|
||||
std::string address_value;
|
||||
uint16_t port_value;
|
||||
|
||||
public:
|
||||
StringNetworkAddress(const std::string &address, uint16_t port);
|
||||
|
||||
const std::string &address() const override;
|
||||
uint16_t port() const override;
|
||||
|
||||
NetworkAddress::ChildVariant representation() override { return this; }
|
||||
};
|
||||
|
||||
class Network {
|
||||
public:
|
||||
virtual ~Network() = default;
|
||||
|
||||
/**
|
||||
* Parse the provided string and uint16 to the preferred storage method
|
||||
*/
|
||||
virtual Conveyor<Own<NetworkAddress>>
|
||||
parseAddress(const std::string &addr, uint16_t port_hint = 0) = 0;
|
||||
|
||||
/**
|
||||
* Creates an unnamed pair of bidirectional fds
|
||||
* Set up a listener on this address
|
||||
*/
|
||||
virtual ErrorOr<SocketPair> socketPair() = 0;
|
||||
virtual Own<Server> listen(NetworkAddress &bind_addr) = 0;
|
||||
|
||||
/**
|
||||
* Connect to a remote address
|
||||
*/
|
||||
virtual Conveyor<Own<IoStream>> connect(NetworkAddress &address) = 0;
|
||||
|
||||
/**
|
||||
* Bind a datagram socket at this address.
|
||||
*/
|
||||
virtual Own<Datagram> datagram(NetworkAddress &address) = 0;
|
||||
};
|
||||
|
||||
class IoProvider {
|
||||
|
|
|
@ -1,25 +1,27 @@
|
|||
#pragma once
|
||||
|
||||
#include "async.h"
|
||||
#include "message.h"
|
||||
#include "io.h"
|
||||
|
||||
namespace saw {
|
||||
|
||||
template <typename Codec, typename Incoming, typename Outgoing>
|
||||
template <typename Codec, typename Incoming, typename Outgoing, class InContainer = MessageContainer<Incoming>, class OutContainer = MessageContainer<Outgoing>>
|
||||
class StreamingIoPeer {
|
||||
private:
|
||||
Codec codec;
|
||||
|
||||
Own<AsyncIoStream> io_stream;
|
||||
|
||||
Own<ConveyorFeeder<Incoming>> incoming_feeder = nullptr;
|
||||
|
||||
Own<ConveyorFeeder<HeapMessageRoot<Incoming, InContainer>>> incoming_feeder = nullptr;
|
||||
public:
|
||||
StreamingIoPeer(Own<AsyncIoStream> stream);
|
||||
|
||||
void send(Outgoing outgoing, Own<MessageBuilder> builder);
|
||||
void send(HeapMessageRoot<Outgoing, OutContainer> builder);
|
||||
|
||||
Conveyor<Incoming> startReadPump();
|
||||
Conveyor<HeapMessageRootIncoming> startReadPump();
|
||||
};
|
||||
|
||||
} // namespace saw
|
||||
|
||||
|
||||
} // namespace saw
|
||||
|
|
|
@ -155,24 +155,18 @@ public:
|
|||
};
|
||||
}
|
||||
|
||||
TlsNetworkAddress::TlsNetworkAddress(Own<NetworkAddress> net_addr, const std::string& host_name_, Tls &tls_)
|
||||
: internal{std::move(net_addr)}, host_name{host_name_}, tls{tls_} {}
|
||||
|
||||
Own<Server> TlsNetworkAddress::listen() {
|
||||
SAW_ASSERT(internal) { return nullptr; }
|
||||
return heap<TlsServer>(internal->listen());
|
||||
Own<Server> TlsNetwork::listen(NetworkAddress& address) {
|
||||
return heap<TlsServer>(internal.listen(address));
|
||||
}
|
||||
|
||||
Conveyor<Own<IoStream>> TlsNetworkAddress::connect() {
|
||||
SAW_ASSERT(internal) { return Conveyor<Own<IoStream>>{nullptr, nullptr}; }
|
||||
|
||||
Conveyor<Own<IoStream>> TlsNetwork::connect(NetworkAddress& address) {
|
||||
// Helper setups
|
||||
auto caf = newConveyorAndFeeder<Own<IoStream>>();
|
||||
Own<TlsClientStreamHelper> helper = heap<TlsClientStreamHelper>(std::move(caf.feeder));
|
||||
TlsClientStreamHelper* hlp_ptr = helper.get();
|
||||
|
||||
// Conveyor entangled structure
|
||||
auto prim_conv = internal->connect().then([this, hlp_ptr](
|
||||
auto prim_conv = internal.connect(address).then([this, hlp_ptr, addr = address.address()](
|
||||
Own<IoStream> stream) -> ErrorOr<void> {
|
||||
IoStream* inner_stream = stream.get();
|
||||
auto tls_stream = heap<TlsIoStream>(std::move(stream));
|
||||
|
@ -181,8 +175,6 @@ Conveyor<Own<IoStream>> TlsNetworkAddress::connect() {
|
|||
|
||||
gnutls_init(&session, GNUTLS_CLIENT);
|
||||
|
||||
const std::string &addr = this->address();
|
||||
|
||||
gnutls_server_name_set(session, GNUTLS_NAME_DNS, addr.c_str(),
|
||||
addr.size());
|
||||
|
||||
|
@ -209,6 +201,11 @@ Conveyor<Own<IoStream>> TlsNetworkAddress::connect() {
|
|||
return caf.conveyor.attach(std::move(helper));
|
||||
}
|
||||
|
||||
Own<Datagram> TlsNetwork::datagram(NetworkAddress& address){
|
||||
///@unimplemented
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static ssize_t forst_tls_push_func(gnutls_transport_ptr_t p, const void *data,
|
||||
size_t size) {
|
||||
IoStream *stream = reinterpret_cast<IoStream *>(p);
|
||||
|
@ -238,30 +235,13 @@ static ssize_t forst_tls_pull_func(gnutls_transport_ptr_t p, void *data, size_t
|
|||
return static_cast<ssize_t>(length.value());
|
||||
}
|
||||
|
||||
const std::string &TlsNetworkAddress::address() const {
|
||||
assert(internal);
|
||||
return internal->address();
|
||||
}
|
||||
uint16_t TlsNetworkAddress::port() const {
|
||||
assert(internal);
|
||||
return internal->port(); }
|
||||
|
||||
std::string TlsNetworkAddress::toString() const { return internal->toString(); }
|
||||
|
||||
TlsNetwork::TlsNetwork(Network &network) : internal{network} {}
|
||||
|
||||
Conveyor<Own<NetworkAddress>> TlsNetwork::parseAddress(const std::string &addr,
|
||||
uint16_t port) {
|
||||
return internal.parseAddress(addr, port)
|
||||
.then(
|
||||
[this, addr, port](Own<NetworkAddress> net) -> Own<NetworkAddress> {
|
||||
assert(net);
|
||||
return heap<TlsNetworkAddress>(std::move(net), addr, tls);
|
||||
});
|
||||
}
|
||||
|
||||
ErrorOr<SocketPair> TlsNetwork::socketPair(){
|
||||
return criticalError("Unimplemented");
|
||||
/// @todo tls server name needed. Check validity. Won't matter later on, because gnutls should fail anyway. But
|
||||
/// it's better to find the error source sooner rather than later
|
||||
return internal.parseAddress(addr, port);
|
||||
}
|
||||
|
||||
std::optional<Own<TlsNetwork>> setupTlsNetwork(Network &network) {
|
||||
|
|
|
@ -33,25 +33,6 @@ public:
|
|||
Conveyor<Own<IoStream>> accept() override;
|
||||
};
|
||||
|
||||
class TlsNetworkAddress final : public NetworkAddress {
|
||||
private:
|
||||
Own<NetworkAddress> internal;
|
||||
std::string host_name;
|
||||
Tls &tls;
|
||||
|
||||
public:
|
||||
TlsNetworkAddress(Own<NetworkAddress> net_addr, const std::string& host_name_, Tls &tls_);
|
||||
|
||||
Own<Server> listen() override;
|
||||
|
||||
Conveyor<Own<IoStream>> connect() override;
|
||||
|
||||
std::string toString() const override;
|
||||
|
||||
const std::string &address() const override;
|
||||
uint16_t port() const override;
|
||||
};
|
||||
|
||||
class TlsNetwork final : public Network {
|
||||
private:
|
||||
Tls tls;
|
||||
|
@ -60,10 +41,13 @@ private:
|
|||
public:
|
||||
TlsNetwork(Network &network);
|
||||
|
||||
Conveyor<Own<NetworkAddress>> parseAddress(const std::string &addr,
|
||||
uint16_t port = 0) override;
|
||||
Conveyor<Own<NetworkAddress>> parseAddress(const std::string &addr, uint16_t port = 0) override;
|
||||
|
||||
Own<Server> listen(NetworkAddress& address) override;
|
||||
|
||||
ErrorOr<SocketPair> socketPair() override;
|
||||
Conveyor<Own<IoStream>> connect(NetworkAddress& address) override;
|
||||
|
||||
Own<Datagram> datagram(NetworkAddress& address) override;
|
||||
};
|
||||
|
||||
std::optional<Own<TlsNetwork>> setupTlsNetwork(Network &network);
|
||||
|
|
|
@ -15,4 +15,4 @@ env.test_objects = []
|
|||
env.test_sources.append(dir_path+'/suite/suite.cpp')
|
||||
env.test_headers = [dir_path + '/suite/suite.h']
|
||||
|
||||
env.test_program = env_test.Program('#bin/test', [env.test_sources, env.library_static])
|
||||
env.test_program = env_test.Program('#build/test', [env.test_sources, env.library_static])
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#include "source/forstio/io.h"
|
||||
|
||||
namespace {
|
||||
/*
|
||||
SAW_TEST("Io Socket Pair"){
|
||||
using namespace saw;
|
||||
|
||||
|
@ -40,5 +41,5 @@ SAW_TEST("Io Socket Pair"){
|
|||
SAW_EXPECT(buffer_out[5] == 0, "Element 6 failed");
|
||||
SAW_EXPECT(buffer_out[6] == 0, "Element 7 failed");
|
||||
}
|
||||
|
||||
*/
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue