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