Merge branch 'dev'

master
Claudius Holeksa 2022-03-11 21:24:50 +01:00
commit 102bf7e174
13 changed files with 332 additions and 148 deletions

2
.gitignore vendored
View File

@ -59,7 +59,7 @@ Mkfile.old
dkms.conf
# binary files
bin/
build/
# test files
assets/
# custom build tracking

View File

@ -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')

View File

@ -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)

View File

@ -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 {

View File

@ -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);
}
};

View File

@ -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

View File

@ -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 {

View File

@ -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

View File

@ -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) {

View File

@ -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);

View File

@ -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])

View File

@ -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");
}
*/
}

View File