]>
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; | |
11fdf7f2 TL |
106 | }; |
107 | ||
108 | template <typename Protocol> | |
109 | class native_socket_impl final : public socket_impl { | |
110 | Protocol& _proto; | |
111 | lw_shared_ptr<typename Protocol::connection> _conn; | |
112 | public: | |
113 | explicit native_socket_impl(Protocol& proto) | |
114 | : _proto(proto), _conn(nullptr) { } | |
115 | ||
116 | virtual future<connected_socket> connect(socket_address sa, socket_address local, transport proto = transport::TCP) override { | |
117 | //TODO: implement SCTP | |
118 | assert(proto == transport::TCP); | |
119 | ||
120 | // FIXME: local is ignored since native stack does not support multiple IPs yet | |
121 | assert(sa.as_posix_sockaddr().sa_family == AF_INET); | |
122 | ||
123 | _conn = make_lw_shared<typename Protocol::connection>(_proto.connect(sa)); | |
124 | return _conn->connected().then([conn = _conn]() mutable { | |
125 | auto csi = std::make_unique<native_connected_socket_impl<Protocol>>(std::move(conn)); | |
126 | return make_ready_future<connected_socket>(connected_socket(std::move(csi))); | |
127 | }); | |
128 | } | |
129 | ||
9f95a23c TL |
130 | virtual void set_reuseaddr(bool reuseaddr) override { |
131 | // FIXME: implement | |
132 | std::cerr << "Reuseaddr is not supported by native stack" << std::endl; | |
133 | } | |
134 | ||
135 | virtual bool get_reuseaddr() const override { | |
136 | // FIXME: implement | |
137 | return false; | |
138 | } | |
139 | ||
11fdf7f2 TL |
140 | virtual void shutdown() override { |
141 | if (_conn) { | |
142 | _conn->shutdown_connect(); | |
143 | } | |
144 | } | |
145 | }; | |
146 | ||
147 | template <typename Protocol> | |
148 | class native_connected_socket_impl<Protocol>::native_data_source_impl final | |
149 | : public data_source_impl { | |
150 | typedef typename Protocol::connection connection_type; | |
151 | lw_shared_ptr<connection_type> _conn; | |
152 | size_t _cur_frag = 0; | |
153 | bool _eof = false; | |
154 | packet _buf; | |
155 | public: | |
156 | explicit native_data_source_impl(lw_shared_ptr<connection_type> conn) | |
157 | : _conn(std::move(conn)) {} | |
158 | virtual future<temporary_buffer<char>> get() override { | |
159 | if (_eof) { | |
160 | return make_ready_future<temporary_buffer<char>>(temporary_buffer<char>(0)); | |
161 | } | |
162 | if (_cur_frag != _buf.nr_frags()) { | |
163 | auto& f = _buf.fragments()[_cur_frag++]; | |
164 | return make_ready_future<temporary_buffer<char>>( | |
165 | temporary_buffer<char>(f.base, f.size, | |
166 | make_deleter(deleter(), [p = _buf.share()] () mutable {}))); | |
167 | } | |
168 | return _conn->wait_for_data().then([this] { | |
169 | _buf = _conn->read(); | |
170 | _cur_frag = 0; | |
171 | _eof = !_buf.len(); | |
172 | return get(); | |
173 | }); | |
174 | } | |
175 | future<> close() override { | |
176 | _conn->close_write(); | |
177 | return make_ready_future<>(); | |
178 | } | |
179 | }; | |
180 | ||
181 | template <typename Protocol> | |
182 | class native_connected_socket_impl<Protocol>::native_data_sink_impl final | |
183 | : public data_sink_impl { | |
184 | typedef typename Protocol::connection connection_type; | |
185 | lw_shared_ptr<connection_type> _conn; | |
186 | public: | |
187 | explicit native_data_sink_impl(lw_shared_ptr<connection_type> conn) | |
188 | : _conn(std::move(conn)) {} | |
189 | using data_sink_impl::put; | |
190 | virtual future<> put(packet p) override { | |
191 | return _conn->send(std::move(p)); | |
192 | } | |
193 | virtual future<> close() override { | |
194 | _conn->close_write(); | |
195 | return make_ready_future<>(); | |
196 | } | |
197 | }; | |
198 | ||
199 | template <typename Protocol> | |
200 | data_source native_connected_socket_impl<Protocol>::source() { | |
201 | return data_source(std::make_unique<native_data_source_impl>(_conn)); | |
202 | } | |
203 | ||
204 | template <typename Protocol> | |
205 | data_sink native_connected_socket_impl<Protocol>::sink() { | |
206 | return data_sink(std::make_unique<native_data_sink_impl>(_conn)); | |
207 | } | |
208 | ||
209 | template <typename Protocol> | |
210 | void | |
211 | native_connected_socket_impl<Protocol>::shutdown_input() { | |
212 | _conn->close_read(); | |
213 | } | |
214 | ||
215 | template <typename Protocol> | |
216 | void | |
217 | native_connected_socket_impl<Protocol>::shutdown_output() { | |
218 | _conn->close_write(); | |
219 | } | |
220 | ||
221 | template <typename Protocol> | |
222 | void | |
223 | native_connected_socket_impl<Protocol>::set_nodelay(bool nodelay) { | |
224 | // FIXME: implement | |
225 | } | |
226 | ||
227 | template <typename Protocol> | |
228 | bool | |
229 | native_connected_socket_impl<Protocol>::get_nodelay() const { | |
230 | // FIXME: implement | |
231 | return true; | |
232 | } | |
233 | ||
234 | template <typename Protocol> | |
235 | void native_connected_socket_impl<Protocol>::set_keepalive(bool keepalive) { | |
236 | // FIXME: implement | |
237 | std::cerr << "Keepalive is not supported by native stack" << std::endl; | |
238 | } | |
239 | template <typename Protocol> | |
240 | bool native_connected_socket_impl<Protocol>::get_keepalive() const { | |
241 | // FIXME: implement | |
242 | return false; | |
243 | } | |
244 | ||
245 | template <typename Protocol> | |
246 | void native_connected_socket_impl<Protocol>::set_keepalive_parameters(const keepalive_params&) { | |
247 | // FIXME: implement | |
248 | std::cerr << "Keepalive parameters are not supported by native stack" << std::endl; | |
249 | } | |
250 | ||
251 | template <typename Protocol> | |
252 | keepalive_params native_connected_socket_impl<Protocol>::get_keepalive_parameters() const { | |
253 | // FIXME: implement | |
254 | return tcp_keepalive_params {std::chrono::seconds(0), std::chrono::seconds(0), 0}; | |
255 | } | |
256 | ||
f67539c2 TL |
257 | template<typename Protocol> |
258 | void native_connected_socket_impl<Protocol>::set_sockopt(int level, int optname, const void* data, size_t len) { | |
259 | throw std::runtime_error("Setting custom socket options is not supported for native stack"); | |
260 | } | |
261 | ||
262 | template<typename Protocol> | |
263 | int native_connected_socket_impl<Protocol>::get_sockopt(int level, int optname, void* data, size_t len) const { | |
264 | throw std::runtime_error("Getting custom socket options is not supported for native stack"); | |
265 | } | |
266 | ||
11fdf7f2 TL |
267 | } |
268 | ||
269 | } |