]>
Commit | Line | Data |
---|---|---|
11fdf7f2 TL |
1 | /* |
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. | |
6 | * | |
7 | * You may obtain a copy of the License at | |
8 | * | |
9 | * http://www.apache.org/licenses/LICENSE-2.0 | |
10 | * | |
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 | |
16 | * under the License. | |
17 | */ | |
18 | /* | |
19 | * Copyright (C) 2014 Cloudius Systems, Ltd. | |
20 | */ | |
21 | ||
22 | #pragma once | |
23 | ||
11fdf7f2 TL |
24 | #include <seastar/net/stack.hh> |
25 | #include <iostream> | |
9f95a23c | 26 | #include <seastar/net/inet_address.hh> |
11fdf7f2 TL |
27 | |
28 | namespace seastar { | |
29 | ||
30 | namespace net { | |
31 | ||
32 | using namespace seastar; | |
33 | ||
34 | template <typename Protocol> | |
35 | class native_server_socket_impl; | |
36 | ||
37 | template <typename Protocol> | |
38 | class native_connected_socket_impl; | |
39 | ||
40 | class native_network_stack; | |
41 | ||
42 | // native_server_socket_impl | |
43 | template <typename Protocol> | |
f67539c2 | 44 | class native_server_socket_impl : public server_socket_impl { |
11fdf7f2 TL |
45 | typename Protocol::listener _listener; |
46 | public: | |
47 | native_server_socket_impl(Protocol& proto, uint16_t port, listen_options opt); | |
9f95a23c | 48 | virtual future<accept_result> accept() override; |
11fdf7f2 | 49 | virtual void abort_accept() override; |
9f95a23c | 50 | virtual socket_address local_address() const override; |
11fdf7f2 TL |
51 | }; |
52 | ||
53 | template <typename Protocol> | |
54 | native_server_socket_impl<Protocol>::native_server_socket_impl(Protocol& proto, uint16_t port, listen_options opt) | |
55 | : _listener(proto.listen(port)) { | |
56 | } | |
57 | ||
58 | template <typename Protocol> | |
9f95a23c | 59 | future<accept_result> |
11fdf7f2 TL |
60 | native_server_socket_impl<Protocol>::accept() { |
61 | return _listener.accept().then([] (typename Protocol::connection conn) { | |
9f95a23c TL |
62 | // Save "conn" contents before call below function |
63 | // "conn" is moved in 1st argument, and used in 2nd argument | |
64 | // It causes trouble on Arm which passes arguments from left to right | |
65 | auto ip = conn.foreign_ip().ip; | |
66 | auto port = conn.foreign_port(); | |
67 | return make_ready_future<accept_result>(accept_result{ | |
11fdf7f2 | 68 | connected_socket(std::make_unique<native_connected_socket_impl<Protocol>>(make_lw_shared(std::move(conn)))), |
9f95a23c | 69 | make_ipv4_address(ip, port)}); |
11fdf7f2 TL |
70 | }); |
71 | } | |
72 | ||
73 | template <typename Protocol> | |
74 | void | |
75 | native_server_socket_impl<Protocol>::abort_accept() { | |
76 | _listener.abort_accept(); | |
77 | } | |
78 | ||
9f95a23c TL |
79 | template <typename Protocol> |
80 | socket_address native_server_socket_impl<Protocol>::local_address() const { | |
81 | return socket_address(_listener.get_tcp().inet().inet().host_address(), _listener.port()); | |
82 | } | |
83 | ||
11fdf7f2 TL |
84 | // native_connected_socket_impl |
85 | template <typename Protocol> | |
86 | class native_connected_socket_impl : public connected_socket_impl { | |
87 | lw_shared_ptr<typename Protocol::connection> _conn; | |
88 | class native_data_source_impl; | |
89 | class native_data_sink_impl; | |
90 | public: | |
91 | explicit native_connected_socket_impl(lw_shared_ptr<typename Protocol::connection> conn) | |
92 | : _conn(std::move(conn)) {} | |
f67539c2 | 93 | using connected_socket_impl::source; |
11fdf7f2 TL |
94 | virtual data_source source() override; |
95 | virtual data_sink sink() override; | |
96 | virtual void shutdown_input() override; | |
97 | virtual void shutdown_output() override; | |
98 | virtual void set_nodelay(bool nodelay) override; | |
99 | virtual bool get_nodelay() const override; | |
100 | void set_keepalive(bool keepalive) override; | |
101 | bool get_keepalive() const override; | |
102 | void set_keepalive_parameters(const keepalive_params&) override; | |
103 | keepalive_params get_keepalive_parameters() const override; | |
f67539c2 TL |
104 | int get_sockopt(int level, int optname, void* data, size_t len) const override; |
105 | void set_sockopt(int level, int optname, const void* data, size_t len) override; | |
20effc67 | 106 | socket_address local_address() const noexcept override; |
1e59de90 | 107 | virtual future<> wait_input_shutdown() override; |
11fdf7f2 TL |
108 | }; |
109 | ||
110 | template <typename Protocol> | |
111 | class native_socket_impl final : public socket_impl { | |
112 | Protocol& _proto; | |
113 | lw_shared_ptr<typename Protocol::connection> _conn; | |
114 | public: | |
115 | explicit native_socket_impl(Protocol& proto) | |
116 | : _proto(proto), _conn(nullptr) { } | |
117 | ||
118 | virtual future<connected_socket> connect(socket_address sa, socket_address local, transport proto = transport::TCP) override { | |
119 | //TODO: implement SCTP | |
120 | assert(proto == transport::TCP); | |
121 | ||
122 | // FIXME: local is ignored since native stack does not support multiple IPs yet | |
123 | assert(sa.as_posix_sockaddr().sa_family == AF_INET); | |
124 | ||
125 | _conn = make_lw_shared<typename Protocol::connection>(_proto.connect(sa)); | |
126 | return _conn->connected().then([conn = _conn]() mutable { | |
127 | auto csi = std::make_unique<native_connected_socket_impl<Protocol>>(std::move(conn)); | |
128 | return make_ready_future<connected_socket>(connected_socket(std::move(csi))); | |
129 | }); | |
130 | } | |
131 | ||
9f95a23c TL |
132 | virtual void set_reuseaddr(bool reuseaddr) override { |
133 | // FIXME: implement | |
134 | std::cerr << "Reuseaddr is not supported by native stack" << std::endl; | |
135 | } | |
136 | ||
137 | virtual bool get_reuseaddr() const override { | |
138 | // FIXME: implement | |
139 | return false; | |
140 | } | |
141 | ||
11fdf7f2 TL |
142 | virtual void shutdown() override { |
143 | if (_conn) { | |
144 | _conn->shutdown_connect(); | |
145 | } | |
146 | } | |
147 | }; | |
148 | ||
149 | template <typename Protocol> | |
150 | class native_connected_socket_impl<Protocol>::native_data_source_impl final | |
151 | : public data_source_impl { | |
152 | typedef typename Protocol::connection connection_type; | |
153 | lw_shared_ptr<connection_type> _conn; | |
154 | size_t _cur_frag = 0; | |
155 | bool _eof = false; | |
156 | packet _buf; | |
157 | public: | |
158 | explicit native_data_source_impl(lw_shared_ptr<connection_type> conn) | |
159 | : _conn(std::move(conn)) {} | |
160 | virtual future<temporary_buffer<char>> get() override { | |
161 | if (_eof) { | |
162 | return make_ready_future<temporary_buffer<char>>(temporary_buffer<char>(0)); | |
163 | } | |
164 | if (_cur_frag != _buf.nr_frags()) { | |
165 | auto& f = _buf.fragments()[_cur_frag++]; | |
166 | return make_ready_future<temporary_buffer<char>>( | |
167 | temporary_buffer<char>(f.base, f.size, | |
168 | make_deleter(deleter(), [p = _buf.share()] () mutable {}))); | |
169 | } | |
170 | return _conn->wait_for_data().then([this] { | |
171 | _buf = _conn->read(); | |
172 | _cur_frag = 0; | |
173 | _eof = !_buf.len(); | |
174 | return get(); | |
175 | }); | |
176 | } | |
177 | future<> close() override { | |
178 | _conn->close_write(); | |
179 | return make_ready_future<>(); | |
180 | } | |
181 | }; | |
182 | ||
183 | template <typename Protocol> | |
184 | class native_connected_socket_impl<Protocol>::native_data_sink_impl final | |
185 | : public data_sink_impl { | |
186 | typedef typename Protocol::connection connection_type; | |
187 | lw_shared_ptr<connection_type> _conn; | |
188 | public: | |
189 | explicit native_data_sink_impl(lw_shared_ptr<connection_type> conn) | |
190 | : _conn(std::move(conn)) {} | |
191 | using data_sink_impl::put; | |
192 | virtual future<> put(packet p) override { | |
193 | return _conn->send(std::move(p)); | |
194 | } | |
195 | virtual future<> close() override { | |
196 | _conn->close_write(); | |
197 | return make_ready_future<>(); | |
198 | } | |
199 | }; | |
200 | ||
201 | template <typename Protocol> | |
202 | data_source native_connected_socket_impl<Protocol>::source() { | |
203 | return data_source(std::make_unique<native_data_source_impl>(_conn)); | |
204 | } | |
205 | ||
206 | template <typename Protocol> | |
207 | data_sink native_connected_socket_impl<Protocol>::sink() { | |
208 | return data_sink(std::make_unique<native_data_sink_impl>(_conn)); | |
209 | } | |
210 | ||
211 | template <typename Protocol> | |
212 | void | |
213 | native_connected_socket_impl<Protocol>::shutdown_input() { | |
214 | _conn->close_read(); | |
215 | } | |
216 | ||
217 | template <typename Protocol> | |
218 | void | |
219 | native_connected_socket_impl<Protocol>::shutdown_output() { | |
220 | _conn->close_write(); | |
221 | } | |
222 | ||
223 | template <typename Protocol> | |
224 | void | |
225 | native_connected_socket_impl<Protocol>::set_nodelay(bool nodelay) { | |
226 | // FIXME: implement | |
227 | } | |
228 | ||
229 | template <typename Protocol> | |
230 | bool | |
231 | native_connected_socket_impl<Protocol>::get_nodelay() const { | |
232 | // FIXME: implement | |
233 | return true; | |
234 | } | |
235 | ||
236 | template <typename Protocol> | |
237 | void native_connected_socket_impl<Protocol>::set_keepalive(bool keepalive) { | |
238 | // FIXME: implement | |
239 | std::cerr << "Keepalive is not supported by native stack" << std::endl; | |
240 | } | |
241 | template <typename Protocol> | |
242 | bool native_connected_socket_impl<Protocol>::get_keepalive() const { | |
243 | // FIXME: implement | |
244 | return false; | |
245 | } | |
246 | ||
247 | template <typename Protocol> | |
248 | void native_connected_socket_impl<Protocol>::set_keepalive_parameters(const keepalive_params&) { | |
249 | // FIXME: implement | |
250 | std::cerr << "Keepalive parameters are not supported by native stack" << std::endl; | |
251 | } | |
252 | ||
253 | template <typename Protocol> | |
254 | keepalive_params native_connected_socket_impl<Protocol>::get_keepalive_parameters() const { | |
255 | // FIXME: implement | |
256 | return tcp_keepalive_params {std::chrono::seconds(0), std::chrono::seconds(0), 0}; | |
257 | } | |
258 | ||
f67539c2 TL |
259 | template<typename Protocol> |
260 | void native_connected_socket_impl<Protocol>::set_sockopt(int level, int optname, const void* data, size_t len) { | |
261 | throw std::runtime_error("Setting custom socket options is not supported for native stack"); | |
262 | } | |
263 | ||
264 | template<typename Protocol> | |
265 | int native_connected_socket_impl<Protocol>::get_sockopt(int level, int optname, void* data, size_t len) const { | |
266 | throw std::runtime_error("Getting custom socket options is not supported for native stack"); | |
267 | } | |
268 | ||
20effc67 TL |
269 | template<typename Protocol> |
270 | socket_address native_connected_socket_impl<Protocol>::local_address() const noexcept { | |
271 | return {_conn->local_ip(), _conn->local_port()}; | |
272 | } | |
273 | ||
1e59de90 TL |
274 | template <typename Protocol> |
275 | future<> native_connected_socket_impl<Protocol>::wait_input_shutdown() { | |
276 | return _conn->wait_input_shutdown(); | |
277 | } | |
278 | ||
11fdf7f2 TL |
279 | } |
280 | ||
281 | } |