From 5630f636cd35e60eff3a49afd91ecf22111eee89 Mon Sep 17 00:00:00 2001 From: Avi Kivity Date: Wed, 10 Sep 2014 10:42:21 +0300 Subject: [PATCH] net: add protcol stack adapter for native stack This defines adapter classes for converting from the tcp<> class to the abstractions that applications use. Still very inefficient due to impedance mismatch between the data types used. --- net/stack.cc | 139 +++++++++++++++++++++++++++++++++++++++++++++++++++ net/stack.hh | 17 +++++++ 2 files changed, 156 insertions(+) create mode 100644 net/stack.cc create mode 100644 net/stack.hh diff --git a/net/stack.cc b/net/stack.cc new file mode 100644 index 0000000000..aa838b00e7 --- /dev/null +++ b/net/stack.cc @@ -0,0 +1,139 @@ +/* + * Copyright (C) 2014 Cloudius Systems, Ltd. + */ + +#include "stack.hh" +#include "net.hh" +#include "ip.hh" +#include "tcp.hh" +#include +#include + +namespace net { + +class native_networking_stack; + +template +class native_server_socket_impl; + +template +class native_connected_socket_impl; + +template +class native_connected_socket_impl : public connected_socket_impl { + typename Protocol::connection _conn; + class native_data_source_impl; + class native_data_sink_impl; +public: + explicit native_connected_socket_impl(typename Protocol::connection conn) + : _conn(std::move(conn)) {} + virtual input_stream input() override; + virtual output_stream output() override; +}; + +template +class native_server_socket_impl : public server_socket_impl { + Protocol& _proto; + uint16_t _port; +public: + native_server_socket_impl(Protocol& proto, uint16_t port, listen_options opt); + virtual future accept() override; +}; + +class native_networking_stack : public networking_stack { + static std::unique_ptr _s; + interface _netif; + ipv4 _inet; + using tcp4 = tcp; +public: + explicit native_networking_stack(std::unique_ptr dev); + virtual server_socket listen(socket_address sa, listen_options opt) override; + friend class native_server_socket_impl; +}; + +native_networking_stack::native_networking_stack(std::unique_ptr dev) + : _netif(std::move(dev)) + , _inet(&_netif) { +} + +template +native_server_socket_impl::native_server_socket_impl(Protocol& proto, uint16_t port, listen_options opt) + : _proto(proto), _port(port) { +} + +template +future +native_server_socket_impl::accept() { + return _proto.listen(_port).then([this] (typename Protocol::connection conn) { + return make_ready_future( + connected_socket(std::make_unique>(std::move(conn))), + socket_address()); // FIXME: don't fake it + }); +} + +server_socket +native_networking_stack::listen(socket_address sa, listen_options opts) { + assert(sa.as_posix_sockaddr().sa_family == AF_INET); + return server_socket(std::make_unique>( + _inet.get_tcp(), sa.as_posix_sockaddr_in().sin_port, opts)); +} + +template +class native_connected_socket_impl::native_data_source_impl final + : public data_source_impl { + typename Protocol::connection& _conn; + size_t _cur_frag = 0; + packet _buf; +public: + explicit native_data_source_impl(typename Protocol::connection& conn) + : _conn(conn) {} + virtual future> get() override { + if (_cur_frag != _buf.fragments.size()) { + auto& f = _buf.fragments[_cur_frag++]; + return make_ready_future>( + temporary_buffer(f.base, f.size, + make_deleter(nullptr, [p = _buf.share()] () mutable {}))); + } + return _conn.wait_for_data().then([this] { + _buf = _conn.read(); + _cur_frag = 0; + return get(); + }); + } +}; + +template +class native_connected_socket_impl::native_data_sink_impl final + : public data_sink_impl { + typename Protocol::connection& _conn; +public: + explicit native_data_sink_impl(typename Protocol::connection& conn) + : _conn(conn) {} + virtual future<> put(std::vector> data) override { + std::vector frags; + frags.reserve(data.size()); + for (auto& e : data) { + frags.push_back(fragment{e.get_write(), e.size()}); + } + return _conn.send(packet(std::move(frags), [tmp = std::move(data)] () mutable {})); + } +}; + +template +input_stream +native_connected_socket_impl::input() { + data_source ds(std::make_unique(_conn)); + return input_stream(std::move(ds)); +} + +template +output_stream +native_connected_socket_impl::output() { + data_sink ds(std::make_unique(_conn)); + return output_stream(std::move(ds), 8192); +} + + +std::unique_ptr native_networking_stack::_s; + +} diff --git a/net/stack.hh b/net/stack.hh new file mode 100644 index 0000000000..5976f4bd57 --- /dev/null +++ b/net/stack.hh @@ -0,0 +1,17 @@ +/* + * Copyright (C) 2014 Cloudius Systems, Ltd. + */ + +#ifndef STACK_HH_ +#define STACK_HH_ + +#include "core/reactor.hh" + +namespace net { + +std::unique_ptr +create_native_networking_stack(); + +} + +#endif /* STACK_HH_ */