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/iostream.hh>
39 #include <seastar/util/std-compat.hh>
40 #include <seastar/util/program-options.hh>
41 #include <seastar/util/modules.hh>
42 
43 namespace seastar {
44 
45 inline
46 bool is_ip_unspecified(const ipv4_addr& addr) noexcept {
47  return addr.is_ip_unspecified();
48 }
49 
50 inline
51 bool is_port_unspecified(const ipv4_addr& addr) noexcept {
52  return addr.is_port_unspecified();
53 }
54 
55 inline
56 socket_address make_ipv4_address(const ipv4_addr& addr) noexcept {
57  return socket_address(addr);
58 }
59 
60 inline
61 socket_address make_ipv4_address(uint32_t ip, uint16_t port) noexcept {
62  return make_ipv4_address(ipv4_addr(ip, port));
63 }
64 
65 namespace net {
66 
67 // see linux tcp(7) for parameter explanation
69  std::chrono::seconds idle; // TCP_KEEPIDLE
70  std::chrono::seconds interval; // TCP_KEEPINTVL
71  unsigned count; // TCP_KEEPCNT
72 };
73 
74 // see linux sctp(7) for parameter explanation
76  std::chrono::seconds interval; // spp_hbinterval
77  unsigned count; // spp_pathmaxrt
78 };
79 
80 using keepalive_params = std::variant<tcp_keepalive_params, sctp_keepalive_params>;
81 
83 class connected_socket_impl;
84 class socket_impl;
85 
86 class server_socket_impl;
87 class datagram_channel_impl;
88 class get_impl;
90 
92 public:
93  virtual ~datagram_impl() {};
94  virtual socket_address get_src() = 0;
95  virtual socket_address get_dst() = 0;
96  virtual uint16_t get_dst_port() = 0;
97  virtual packet& get_data() = 0;
98 };
99 
101 
102 class datagram final {
103 private:
104  std::unique_ptr<datagram_impl> _impl;
105 public:
106  datagram(std::unique_ptr<datagram_impl>&& impl) noexcept : _impl(std::move(impl)) {};
107  socket_address get_src() { return _impl->get_src(); }
108  socket_address get_dst() { return _impl->get_dst(); }
109  uint16_t get_dst_port() { return _impl->get_dst_port(); }
110  packet& get_data() { return _impl->get_data(); }
111 };
112 
113 using udp_datagram = datagram;
114 
116 private:
117  std::unique_ptr<datagram_channel_impl> _impl;
118 public:
119  datagram_channel() noexcept;
120  datagram_channel(std::unique_ptr<datagram_channel_impl>) noexcept;
121  ~datagram_channel();
122 
124  datagram_channel& operator=(datagram_channel&&) noexcept;
125 
126  socket_address local_address() const;
127 
128  future<datagram> receive();
129  future<> send(const socket_address& dst, const char* msg);
130  future<> send(const socket_address& dst, packet p);
131  bool is_closed() const;
141  void close();
142 };
143 
144 using udp_channel = datagram_channel;
145 
146 class network_interface_impl;
147 
148 } /* namespace net */
149 
152 
161  unsigned buffer_size = 8192;
165  unsigned min_buffer_size = 512;
169  unsigned max_buffer_size = 128 * 1024;
170 };
171 
173 struct session_dn {
174  sstring subject;
175  sstring issuer;
176 };
177 
183  friend class net::get_impl;
184  std::unique_ptr<net::connected_socket_impl> _csi;
185 public:
187  connected_socket() noexcept;
188  ~connected_socket();
189 
191  explicit connected_socket(std::unique_ptr<net::connected_socket_impl> csi) noexcept;
196  connected_socket& operator=(connected_socket&& cs) noexcept;
207  output_stream<char> output(size_t buffer_size = 8192);
209  void set_nodelay(bool nodelay);
213  bool get_nodelay() const;
215  void set_keepalive(bool keepalive);
218  bool get_keepalive() const;
220  void set_keepalive_parameters(const net::keepalive_params& p);
222  net::keepalive_params get_keepalive_parameters() const;
226  void set_sockopt(int level, int optname, const void* data, size_t len);
230  int get_sockopt(int level, int optname, void* data, size_t len) const;
232  socket_address local_address() const noexcept;
234  socket_address remote_address() const noexcept;
235 
256  explicit operator bool() const noexcept {
257  return static_cast<bool>(_csi);
258  }
272 };
274 
277 
282 class socket {
283  std::unique_ptr<net::socket_impl> _si;
284 public:
285  socket() noexcept = default;
286  ~socket();
287 
289  explicit socket(std::unique_ptr<net::socket_impl> si) noexcept;
292  socket(socket&&) noexcept;
294  socket& operator=(socket&&) noexcept;
295 
299  future<connected_socket> connect(socket_address sa, socket_address local = {}, transport proto = transport::TCP);
300 
302  void set_reuseaddr(bool reuseaddr);
305  bool get_reuseaddr() const;
310  void shutdown();
311 };
312 
314 
317 
322 };
323 
326  std::unique_ptr<net::server_socket_impl> _ssi;
327  bool _aborted = false;
328 public:
329  enum class load_balancing_algorithm {
330  // This algorithm tries to distribute all connections equally between all shards.
331  // It does this by sending new connections to a shard with smallest amount of connections.
332  connection_distribution,
333  // This algorithm distributes new connection based on peer's tcp port. Destination shard
334  // is calculated as a port number modulo number of shards. This allows a client to connect
335  // to a specific shard in a server given it knows how many shards server has by choosing
336  // src port number accordingly.
337  port,
338  // This algorithm distributes all new connections to listen_options::fixed_cpu shard only.
339  fixed,
340  default_ = connection_distribution
341  };
343  server_socket() noexcept;
345  explicit server_socket(std::unique_ptr<net::server_socket_impl> ssi) noexcept;
348  server_socket(server_socket&& ss) noexcept;
349  ~server_socket();
351  server_socket& operator=(server_socket&& cs) noexcept;
352 
361 
366  void abort_accept();
367 
375  socket_address local_address() const noexcept;
376 
384  explicit operator bool() const noexcept {
385  return static_cast<bool>(_ssi);
386  }
387 };
388 
390 
392  bool reuse_address = false;
393  server_socket::load_balancing_algorithm lba = server_socket::load_balancing_algorithm::default_;
394  transport proto = transport::TCP;
395  int listen_backlog = 100;
396  unsigned fixed_cpu = 0u;
397  void set_fixed_cpu(unsigned cpu) {
398  lba = server_socket::load_balancing_algorithm::fixed;
399  fixed_cpu = cpu;
400  }
401 };
402 
404 private:
406 public:
407  network_interface() = delete;
410 
411  network_interface& operator=(network_interface&&) noexcept;
412 
413  uint32_t index() const;
414  uint32_t mtu() const;
415 
416  const sstring& name() const;
417  const sstring& display_name() const;
418  const std::vector<net::inet_address>& addresses() const;
419  const std::vector<uint8_t> hardware_address() const;
420 
421  bool is_loopback() const;
422  bool is_virtual() const;
423  bool is_up() const;
424  bool supports_ipv6() const;
425 };
426 
428 public:
429  virtual ~network_stack() {}
430  virtual server_socket listen(socket_address sa, listen_options opts) = 0;
431  // FIXME: local parameter assumes ipv4 for now, fix when adding other AF
432  future<connected_socket> connect(socket_address sa, socket_address = {}, transport proto = transport::TCP);
433  virtual ::seastar::socket socket() = 0;
434 
435  [[deprecated("Use `make_[un]bound_datagram_channel` instead")]]
436  virtual net::udp_channel make_udp_channel(const socket_address& = {}) = 0;
437 
438  virtual net::datagram_channel make_unbound_datagram_channel(sa_family_t) = 0;
439  virtual net::datagram_channel make_bound_datagram_channel(const socket_address& local) = 0;
440  virtual future<> initialize() {
441  return make_ready_future();
442  }
443  virtual bool has_per_core_namespace() = 0;
444  // NOTE: this is not a correct query approach.
445  // This question should be per NIC, but we have no such
446  // abstraction, so for now this is "stack-wide"
447  virtual bool supports_ipv6() const {
448  return false;
449  }
450 
456  virtual std::vector<network_interface> network_interfaces();
457 };
458 
461 
462  sstring name;
463  std::unique_ptr<program_options::option_group> opts;
464  factory_func factory;
465  bool is_default;
466 };
467 
468 }
Definition: api.hh:182
void set_keepalive(bool keepalive)
Sets SO_KEEPALIVE option (enable keepalive timer on a socket)
output_stream< char > output(size_t buffer_size=8192)
void set_keepalive_parameters(const net::keepalive_params &p)
Sets TCP keepalive parameters.
socket_address local_address() const noexcept
Local address of the socket.
input_stream< char > input(connected_socket_input_stream_config csisc={})
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:1238
Definition: iostream.hh:281
Definition: api.hh:115
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:91
Definition: api.hh:102
Definition: packet.hh:87
Definition: api.hh:403
Definition: api.hh:427
virtual std::vector< network_interface > network_interfaces()
Definition: program-options.hh:290
A listening socket, waiting to accept incoming network connections.
Definition: api.hh:325
socket_address local_address() const noexcept
server_socket() noexcept
Constructs a server_socket without being bound to any address.
future< accept_result > accept()
Definition: socket_defs.hh:47
Definition: api.hh:282
socket(socket &&) noexcept
Moves a seastar::socket object.
future< connected_socket > connect(socket_address sa, socket_address local={}, transport proto=transport::TCP)
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:1934
unsigned min_buffer_size
Definition: api.hh:165
unsigned max_buffer_size
Definition: api.hh:169
socket_address remote_address
The address of the peer that connected to us.
Definition: api.hh:321
connected_socket connection
The newly-accepted connection.
Definition: api.hh:320
unsigned buffer_size
Initial buffer size to use for input buffering.
Definition: api.hh:161
The result of an server_socket::accept() call.
Definition: api.hh:319
Distinguished name.
Definition: api.hh:173
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:459
Definition: api.hh:391