Seastar
High performance C++ framework for concurrent servers
api.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#ifndef SEASTAR_MODULE
25#include <chrono>
26#include <memory>
27#include <vector>
28#include <cstring>
29#include <sys/types.h>
30#endif
31
32#include <seastar/core/future.hh>
33#include <seastar/net/byteorder.hh>
34#include <seastar/net/socket_defs.hh>
35#include <seastar/net/packet.hh>
36#include <seastar/core/internal/api-level.hh>
37#include <seastar/core/temporary_buffer.hh>
38#include <seastar/core/file-types.hh>
39#include <seastar/core/iostream.hh>
40#include <seastar/util/std-compat.hh>
41#include <seastar/util/program-options.hh>
42#include <seastar/util/modules.hh>
43
44namespace seastar {
45
46inline
47bool is_ip_unspecified(const ipv4_addr& addr) noexcept {
48 return addr.is_ip_unspecified();
49}
50
51inline
52bool is_port_unspecified(const ipv4_addr& addr) noexcept {
53 return addr.is_port_unspecified();
54}
55
56inline
57socket_address make_ipv4_address(const ipv4_addr& addr) noexcept {
58 return socket_address(addr);
59}
60
61inline
62socket_address make_ipv4_address(uint32_t ip, uint16_t port) noexcept {
63 return make_ipv4_address(ipv4_addr(ip, port));
64}
65
66namespace net {
67
68// see linux tcp(7) for parameter explanation
70 std::chrono::seconds idle; // TCP_KEEPIDLE
71 std::chrono::seconds interval; // TCP_KEEPINTVL
72 unsigned count; // TCP_KEEPCNT
73};
74
75// see linux sctp(7) for parameter explanation
77 std::chrono::seconds interval; // spp_hbinterval
78 unsigned count; // spp_pathmaxrt
79};
80
81using keepalive_params = std::variant<tcp_keepalive_params, sctp_keepalive_params>;
82
84class connected_socket_impl;
85class socket_impl;
86
87class server_socket_impl;
88class datagram_channel_impl;
89class get_impl;
91
93public:
94 virtual ~datagram_impl() {};
95 virtual socket_address get_src() = 0;
96 virtual socket_address get_dst() = 0;
97 virtual uint16_t get_dst_port() = 0;
98 virtual packet& get_data() = 0;
99};
100
102
103class datagram final {
104private:
105 std::unique_ptr<datagram_impl> _impl;
106public:
107 datagram(std::unique_ptr<datagram_impl>&& impl) noexcept : _impl(std::move(impl)) {};
108 socket_address get_src() { return _impl->get_src(); }
109 socket_address get_dst() { return _impl->get_dst(); }
110 uint16_t get_dst_port() { return _impl->get_dst_port(); }
111 packet& get_data() { return _impl->get_data(); }
112};
113
114using udp_datagram = datagram;
115
117private:
118 std::unique_ptr<datagram_channel_impl> _impl;
119public:
120 datagram_channel() noexcept;
121 datagram_channel(std::unique_ptr<datagram_channel_impl>) noexcept;
123
125 datagram_channel& operator=(datagram_channel&&) noexcept;
126
127 socket_address local_address() const;
128
129 future<datagram> receive();
130 future<> send(const socket_address& dst, const char* msg);
131 future<> send(const socket_address& dst, packet p);
132 bool is_closed() const;
142 void close();
143};
144
146
147class network_interface_impl;
148
149} /* namespace net */
150
153
162 unsigned buffer_size = 8192;
166 unsigned min_buffer_size = 512;
170 unsigned max_buffer_size = 128 * 1024;
171};
172
175 sstring subject;
176 sstring issuer;
177};
178
184 friend class net::get_impl;
185 std::unique_ptr<net::connected_socket_impl> _csi;
186public:
190
192 explicit connected_socket(std::unique_ptr<net::connected_socket_impl> csi) noexcept;
197 connected_socket& operator=(connected_socket&& cs) noexcept;
208 output_stream<char> output(size_t buffer_size = 8192);
210 void set_nodelay(bool nodelay);
214 bool get_nodelay() const;
216 void set_keepalive(bool keepalive);
219 bool get_keepalive() const;
221 void set_keepalive_parameters(const net::keepalive_params& p);
223 net::keepalive_params get_keepalive_parameters() const;
227 void set_sockopt(int level, int optname, const void* data, size_t len);
231 int get_sockopt(int level, int optname, void* data, size_t len) const;
236
257 explicit operator bool() const noexcept {
258 return static_cast<bool>(_csi);
259 }
273};
275
278
283class socket {
284 std::unique_ptr<net::socket_impl> _si;
285public:
286 socket() noexcept = default;
287 ~socket();
288
290 explicit socket(std::unique_ptr<net::socket_impl> si) noexcept;
293 socket(socket&&) noexcept;
295 socket& operator=(socket&&) noexcept;
296
300 future<connected_socket> connect(socket_address sa, socket_address local = {}, transport proto = transport::TCP);
301
303 void set_reuseaddr(bool reuseaddr);
306 bool get_reuseaddr() const;
311 void shutdown();
312};
313
315
318
323};
324
327 std::unique_ptr<net::server_socket_impl> _ssi;
328 bool _aborted = false;
329public:
330 enum class load_balancing_algorithm {
331 // This algorithm tries to distribute all connections equally between all shards.
332 // It does this by sending new connections to a shard with smallest amount of connections.
333 connection_distribution,
334 // This algorithm distributes new connection based on peer's tcp port. Destination shard
335 // is calculated as a port number modulo number of shards. This allows a client to connect
336 // to a specific shard in a server given it knows how many shards server has by choosing
337 // src port number accordingly.
338 port,
339 // This algorithm distributes all new connections to listen_options::fixed_cpu shard only.
340 fixed,
341 default_ = connection_distribution
342 };
344 server_socket() noexcept;
346 explicit server_socket(std::unique_ptr<net::server_socket_impl> ssi) noexcept;
350 ~server_socket();
352 server_socket& operator=(server_socket&& cs) noexcept;
353
362
368
377
385 explicit operator bool() const noexcept {
386 return static_cast<bool>(_ssi);
387 }
388};
389
391
393 bool reuse_address = false;
394 server_socket::load_balancing_algorithm lba = server_socket::load_balancing_algorithm::default_;
395 transport proto = transport::TCP;
396 int listen_backlog = 100;
397 unsigned fixed_cpu = 0u;
398 std::optional<file_permissions> unix_domain_socket_permissions;
399 void set_fixed_cpu(unsigned cpu) {
400 lba = server_socket::load_balancing_algorithm::fixed;
401 fixed_cpu = cpu;
402 }
403};
404
406private:
408public:
409 network_interface() = delete;
412
413 network_interface& operator=(network_interface&&) noexcept;
414
415 uint32_t index() const;
416 uint32_t mtu() const;
417
418 const sstring& name() const;
419 const sstring& display_name() const;
420 const std::vector<net::inet_address>& addresses() const;
421 const std::vector<uint8_t> hardware_address() const;
422
423 bool is_loopback() const;
424 bool is_virtual() const;
425 bool is_up() const;
426 bool supports_ipv6() const;
427};
428
430public:
431 virtual ~network_stack() {}
432 virtual server_socket listen(socket_address sa, listen_options opts) = 0;
433 // FIXME: local parameter assumes ipv4 for now, fix when adding other AF
434 future<connected_socket> connect(socket_address sa, socket_address = {}, transport proto = transport::TCP);
435 virtual ::seastar::socket socket() = 0;
436
437 [[deprecated("Use `make_[un]bound_datagram_channel` instead")]]
438 virtual net::udp_channel make_udp_channel(const socket_address& = {}) = 0;
439
440 virtual net::datagram_channel make_unbound_datagram_channel(sa_family_t) = 0;
441 virtual net::datagram_channel make_bound_datagram_channel(const socket_address& local) = 0;
442 virtual future<> initialize() {
443 return make_ready_future();
444 }
445 virtual bool has_per_core_namespace() = 0;
446 // NOTE: this is not a correct query approach.
447 // This question should be per NIC, but we have no such
448 // abstraction, so for now this is "stack-wide"
449 virtual bool supports_ipv6() const {
450 return false;
451 }
452
458 virtual std::vector<network_interface> network_interfaces();
459};
460
463
464 sstring name;
465 std::unique_ptr<program_options::option_group> opts;
466 factory_func factory;
467 bool is_default;
468};
469
470}
Definition: api.hh:183
output_stream< char > output(size_t buffer_size=8192)
void set_keepalive(bool keepalive)
Sets SO_KEEPALIVE option (enable keepalive timer on a socket)
input_stream< char > input(connected_socket_input_stream_config csisc={})
void set_keepalive_parameters(const net::keepalive_params &p)
Sets TCP keepalive parameters.
socket_address local_address() const noexcept
Local address of the socket.
int get_sockopt(int level, int optname, void *data, size_t len) const
void set_sockopt(int level, int optname, const void *data, size_t len)
void set_nodelay(bool nodelay)
Sets the TCP_NODELAY option (disabling Nagle's algorithm)
socket_address remote_address() const noexcept
Remote address of the socket.
connected_socket() noexcept
Constructs a connected_socket not corresponding to a connection.
net::keepalive_params get_keepalive_parameters() const
Get TCP keepalive parameters.
A representation of a possibly not-yet-computed value.
Definition: future.hh:1240
Definition: iostream.hh:280
Definition: api.hh:116
void shutdown_output()
Causes a pending send() to complete (possibly with an exception)
void shutdown_input()
Causes a pending receive() to complete (possibly with an exception)
Definition: api.hh:92
Definition: api.hh:103
Definition: packet.hh:87
Definition: api.hh:405
Definition: api.hh:429
virtual std::vector< network_interface > network_interfaces()
Definition: program-options.hh:292
A listening socket, waiting to accept incoming network connections.
Definition: api.hh:326
socket_address local_address() const noexcept
future< accept_result > accept()
server_socket() noexcept
Constructs a server_socket without being bound to any address.
Definition: socket_defs.hh:47
Definition: api.hh:283
future< connected_socket > connect(socket_address sa, socket_address local={}, transport proto=transport::TCP)
socket(socket &&) noexcept
Moves a seastar::socket object.
void set_reuseaddr(bool reuseaddr)
Sets SO_REUSEADDR option (enable reuseaddr option on a socket)
bool get_reuseaddr() const
future< T > make_ready_future(A &&... value) noexcept
Creates a future in an available, value state.
Definition: future.hh:1943
unsigned min_buffer_size
Definition: api.hh:166
unsigned max_buffer_size
Definition: api.hh:170
socket_address remote_address
The address of the peer that connected to us.
Definition: api.hh:322
connected_socket connection
The newly-accepted connection.
Definition: api.hh:321
unsigned buffer_size
Initial buffer size to use for input buffering.
Definition: api.hh:162
The result of an server_socket::accept() call.
Definition: api.hh:320
Distinguished name.
Definition: api.hh:174
holds the implementation parts of the metrics layer, do not use directly.
Seastar API namespace.
Definition: abort_on_ebadf.hh:26
Definition: noncopyable_function.hh:37
Definition: api.hh:461
STL namespace.
Definition: api.hh:392