2 * This file is open source software, licensed to you under the terms
3 * of the Apache License, Version 2.0 (the "License"). See the NOTICE file
4 * distributed with this work for additional information regarding copyright
5 * ownership. You may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing,
12 * software distributed under the License is distributed on an
13 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 * KIND, either express or implied. See the License for the
15 * specific language governing permissions and limitations
19 * Copyright (C) 2014 Cloudius Systems, Ltd.
24 #include <seastar/core/reactor.hh>
25 #include <seastar/net/stack.hh>
32 using namespace seastar;
34 template <typename Protocol>
35 class native_server_socket_impl;
37 template <typename Protocol>
38 class native_connected_socket_impl;
40 class native_network_stack;
42 // native_server_socket_impl
43 template <typename Protocol>
44 class native_server_socket_impl : public server_socket_impl {
45 typename Protocol::listener _listener;
47 native_server_socket_impl(Protocol& proto, uint16_t port, listen_options opt);
48 virtual future<connected_socket, socket_address> accept() override;
49 virtual void abort_accept() override;
52 template <typename Protocol>
53 native_server_socket_impl<Protocol>::native_server_socket_impl(Protocol& proto, uint16_t port, listen_options opt)
54 : _listener(proto.listen(port)) {
57 template <typename Protocol>
58 future<connected_socket, socket_address>
59 native_server_socket_impl<Protocol>::accept() {
60 return _listener.accept().then([] (typename Protocol::connection conn) {
61 return make_ready_future<connected_socket, socket_address>(
62 connected_socket(std::make_unique<native_connected_socket_impl<Protocol>>(make_lw_shared(std::move(conn)))),
63 make_ipv4_address(conn.foreign_ip().ip, conn.foreign_port()));
67 template <typename Protocol>
69 native_server_socket_impl<Protocol>::abort_accept() {
70 _listener.abort_accept();
73 // native_connected_socket_impl
74 template <typename Protocol>
75 class native_connected_socket_impl : public connected_socket_impl {
76 lw_shared_ptr<typename Protocol::connection> _conn;
77 class native_data_source_impl;
78 class native_data_sink_impl;
80 explicit native_connected_socket_impl(lw_shared_ptr<typename Protocol::connection> conn)
81 : _conn(std::move(conn)) {}
82 virtual data_source source() override;
83 virtual data_sink sink() override;
84 virtual void shutdown_input() override;
85 virtual void shutdown_output() override;
86 virtual void set_nodelay(bool nodelay) override;
87 virtual bool get_nodelay() const override;
88 void set_keepalive(bool keepalive) override;
89 bool get_keepalive() const override;
90 void set_keepalive_parameters(const keepalive_params&) override;
91 keepalive_params get_keepalive_parameters() const override;
94 template <typename Protocol>
95 class native_socket_impl final : public socket_impl {
97 lw_shared_ptr<typename Protocol::connection> _conn;
99 explicit native_socket_impl(Protocol& proto)
100 : _proto(proto), _conn(nullptr) { }
102 virtual future<connected_socket> connect(socket_address sa, socket_address local, transport proto = transport::TCP) override {
103 //TODO: implement SCTP
104 assert(proto == transport::TCP);
106 // FIXME: local is ignored since native stack does not support multiple IPs yet
107 assert(sa.as_posix_sockaddr().sa_family == AF_INET);
109 _conn = make_lw_shared<typename Protocol::connection>(_proto.connect(sa));
110 return _conn->connected().then([conn = _conn]() mutable {
111 auto csi = std::make_unique<native_connected_socket_impl<Protocol>>(std::move(conn));
112 return make_ready_future<connected_socket>(connected_socket(std::move(csi)));
116 virtual void shutdown() override {
118 _conn->shutdown_connect();
123 template <typename Protocol>
124 class native_connected_socket_impl<Protocol>::native_data_source_impl final
125 : public data_source_impl {
126 typedef typename Protocol::connection connection_type;
127 lw_shared_ptr<connection_type> _conn;
128 size_t _cur_frag = 0;
132 explicit native_data_source_impl(lw_shared_ptr<connection_type> conn)
133 : _conn(std::move(conn)) {}
134 virtual future<temporary_buffer<char>> get() override {
136 return make_ready_future<temporary_buffer<char>>(temporary_buffer<char>(0));
138 if (_cur_frag != _buf.nr_frags()) {
139 auto& f = _buf.fragments()[_cur_frag++];
140 return make_ready_future<temporary_buffer<char>>(
141 temporary_buffer<char>(f.base, f.size,
142 make_deleter(deleter(), [p = _buf.share()] () mutable {})));
144 return _conn->wait_for_data().then([this] {
145 _buf = _conn->read();
151 future<> close() override {
152 _conn->close_write();
153 return make_ready_future<>();
157 template <typename Protocol>
158 class native_connected_socket_impl<Protocol>::native_data_sink_impl final
159 : public data_sink_impl {
160 typedef typename Protocol::connection connection_type;
161 lw_shared_ptr<connection_type> _conn;
163 explicit native_data_sink_impl(lw_shared_ptr<connection_type> conn)
164 : _conn(std::move(conn)) {}
165 using data_sink_impl::put;
166 virtual future<> put(packet p) override {
167 return _conn->send(std::move(p));
169 virtual future<> close() override {
170 _conn->close_write();
171 return make_ready_future<>();
175 template <typename Protocol>
176 data_source native_connected_socket_impl<Protocol>::source() {
177 return data_source(std::make_unique<native_data_source_impl>(_conn));
180 template <typename Protocol>
181 data_sink native_connected_socket_impl<Protocol>::sink() {
182 return data_sink(std::make_unique<native_data_sink_impl>(_conn));
185 template <typename Protocol>
187 native_connected_socket_impl<Protocol>::shutdown_input() {
191 template <typename Protocol>
193 native_connected_socket_impl<Protocol>::shutdown_output() {
194 _conn->close_write();
197 template <typename Protocol>
199 native_connected_socket_impl<Protocol>::set_nodelay(bool nodelay) {
203 template <typename Protocol>
205 native_connected_socket_impl<Protocol>::get_nodelay() const {
210 template <typename Protocol>
211 void native_connected_socket_impl<Protocol>::set_keepalive(bool keepalive) {
213 std::cerr << "Keepalive is not supported by native stack" << std::endl;
215 template <typename Protocol>
216 bool native_connected_socket_impl<Protocol>::get_keepalive() const {
221 template <typename Protocol>
222 void native_connected_socket_impl<Protocol>::set_keepalive_parameters(const keepalive_params&) {
224 std::cerr << "Keepalive parameters are not supported by native stack" << std::endl;
227 template <typename Protocol>
228 keepalive_params native_connected_socket_impl<Protocol>::get_keepalive_parameters() const {
230 return tcp_keepalive_params {std::chrono::seconds(0), std::chrono::seconds(0), 0};