]> git.proxmox.com Git - ceph.git/blob - ceph/src/seastar/src/net/native-stack-impl.hh
91203e8484257a03df58a6c690246821a12a90f0
[ceph.git] / ceph / src / seastar / src / net / native-stack-impl.hh
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/net/stack.hh>
25 #include <iostream>
26 #include <seastar/net/inet_address.hh>
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>
44 class native_server_socket_impl : public server_socket_impl {
45 typename Protocol::listener _listener;
46 public:
47 native_server_socket_impl(Protocol& proto, uint16_t port, listen_options opt);
48 virtual future<accept_result> accept() override;
49 virtual void abort_accept() override;
50 virtual socket_address local_address() const override;
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>
59 future<accept_result>
60 native_server_socket_impl<Protocol>::accept() {
61 return _listener.accept().then([] (typename Protocol::connection conn) {
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{
68 connected_socket(std::make_unique<native_connected_socket_impl<Protocol>>(make_lw_shared(std::move(conn)))),
69 make_ipv4_address(ip, port)});
70 });
71 }
72
73 template <typename Protocol>
74 void
75 native_server_socket_impl<Protocol>::abort_accept() {
76 _listener.abort_accept();
77 }
78
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
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)) {}
93 using connected_socket_impl::source;
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 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;
106 socket_address local_address() const noexcept override;
107 virtual future<> wait_input_shutdown() override;
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
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
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
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
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
274 template <typename Protocol>
275 future<> native_connected_socket_impl<Protocol>::wait_input_shutdown() {
276 return _conn->wait_input_shutdown();
277 }
278
279 }
280
281 }