]> git.proxmox.com Git - ceph.git/blame - ceph/src/crimson/net/Socket.h
update ceph source to reef 18.2.1
[ceph.git] / ceph / src / crimson / net / Socket.h
CommitLineData
11fdf7f2
TL
1// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2// vim: ts=8 sw=2 smarttab
3
4#pragma once
5
9f95a23c 6#include <seastar/core/gate.hh>
11fdf7f2 7#include <seastar/core/reactor.hh>
9f95a23c 8#include <seastar/core/sharded.hh>
11fdf7f2
TL
9
10#include "include/buffer.h"
11
9f95a23c
TL
12#include "crimson/common/log.h"
13#include "Errors.h"
f67539c2 14#include "Fwd.h"
9f95a23c
TL
15
16#ifdef UNIT_TESTS_BUILT
17#include "Interceptor.h"
18#endif
19
20namespace crimson::net {
21
22class Socket;
23using SocketRef = std::unique_ptr<Socket>;
aee94f69 24using SocketFRef = seastar::foreign_ptr<SocketRef>;
11fdf7f2 25
aee94f69 26class Socket {
9f95a23c
TL
27 struct construct_tag {};
28
aee94f69 29public:
f67539c2
TL
30 // if acceptor side, peer is using a different port (ephemeral_port)
31 // if connector side, I'm using a different port (ephemeral_port)
32 enum class side_t {
33 acceptor,
34 connector
35 };
aee94f69 36 Socket(seastar::connected_socket &&, side_t, uint16_t e_port, construct_tag);
f67539c2 37
aee94f69 38 ~Socket();
9f95a23c 39
11fdf7f2
TL
40 Socket(Socket&& o) = delete;
41
aee94f69
TL
42 seastar::shard_id get_shard_id() const {
43 return sid;
9f95a23c
TL
44 }
45
aee94f69
TL
46 side_t get_side() const {
47 return side;
11fdf7f2 48 }
aee94f69
TL
49
50 uint16_t get_ephemeral_port() const {
51 return ephemeral_port;
11fdf7f2 52 }
aee94f69
TL
53
54 seastar::socket_address get_local_address() const {
55 return socket.local_address();
11fdf7f2
TL
56 }
57
1e59de90 58 bool is_shutdown() const {
aee94f69 59 assert(seastar::this_shard_id() == sid);
1e59de90
TL
60 return socket_is_shutdown;
61 }
62
aee94f69
TL
63 // learn my ephemeral_port as connector.
64 // unfortunately, there's no way to identify which port I'm using as
65 // connector with current seastar interface.
66 void learn_ephemeral_port_as_connector(uint16_t port) {
67 assert(side == side_t::connector &&
68 (ephemeral_port == 0 || ephemeral_port == port));
69 ephemeral_port = port;
70 }
71
72 /// read the requested number of bytes into a bufferlist
73 seastar::future<bufferlist> read(size_t bytes);
74
75 seastar::future<bufferptr> read_exactly(size_t bytes);
76
77 seastar::future<> write(bufferlist);
78
79 seastar::future<> flush();
80
81 seastar::future<> write_flush(bufferlist);
82
9f95a23c
TL
83 // preemptively disable further reads or writes, can only be shutdown once.
84 void shutdown();
85
11fdf7f2 86 /// Socket can only be closed once.
9f95a23c
TL
87 seastar::future<> close();
88
aee94f69
TL
89 static seastar::future<SocketRef>
90 connect(const entity_addr_t& peer_addr);
1e59de90 91
aee94f69
TL
92 /*
93 * test interfaces
94 */
1e59de90
TL
95
96 // shutdown for tests
97 void force_shutdown() {
aee94f69 98 assert(seastar::this_shard_id() == sid);
1e59de90
TL
99 socket.shutdown_input();
100 socket.shutdown_output();
101 }
102
9f95a23c
TL
103 // shutdown input_stream only, for tests
104 void force_shutdown_in() {
aee94f69 105 assert(seastar::this_shard_id() == sid);
9f95a23c
TL
106 socket.shutdown_input();
107 }
108
109 // shutdown output_stream only, for tests
110 void force_shutdown_out() {
aee94f69 111 assert(seastar::this_shard_id() == sid);
9f95a23c
TL
112 socket.shutdown_output();
113 }
114
aee94f69 115private:
f67539c2
TL
116 const seastar::shard_id sid;
117 seastar::connected_socket socket;
118 seastar::input_stream<char> in;
119 seastar::output_stream<char> out;
1e59de90 120 bool socket_is_shutdown;
f67539c2
TL
121 side_t side;
122 uint16_t ephemeral_port;
123
124#ifndef NDEBUG
125 bool closed = false;
126#endif
127
128 /// buffer state for read()
129 struct {
130 bufferlist buffer;
131 size_t remaining;
132 } r;
133
9f95a23c 134#ifdef UNIT_TESTS_BUILT
aee94f69 135public:
f67539c2
TL
136 void set_trap(bp_type_t type, bp_action_t action, socket_blocker* blocker_);
137
aee94f69
TL
138private:
139 seastar::future<> try_trap_pre(bp_action_t& trap);
140
141 seastar::future<> try_trap_post(bp_action_t& trap);
142
9f95a23c
TL
143 bp_action_t next_trap_read = bp_action_t::CONTINUE;
144 bp_action_t next_trap_write = bp_action_t::CONTINUE;
145 socket_blocker* blocker = nullptr;
9f95a23c 146
9f95a23c 147#endif
aee94f69 148 friend class ShardedServerSocket;
9f95a23c
TL
149};
150
20effc67
TL
151using listen_ertr = crimson::errorator<
152 crimson::ct_error::address_in_use, // The address is already bound
153 crimson::ct_error::address_not_available // https://techoverflow.net/2021/08/06/how-i-fixed-python-oserror-errno-99-cannot-assign-requested-address/
154 >;
155
aee94f69
TL
156class ShardedServerSocket
157 : public seastar::peering_sharded_service<ShardedServerSocket> {
158 struct construct_tag {};
9f95a23c 159
aee94f69
TL
160public:
161 ShardedServerSocket(
162 seastar::shard_id sid,
163 bool dispatch_only_on_primary_sid,
164 construct_tag);
9f95a23c 165
aee94f69 166 ~ShardedServerSocket();
9f95a23c 167
aee94f69
TL
168 ShardedServerSocket(ShardedServerSocket&&) = delete;
169 ShardedServerSocket(const ShardedServerSocket&) = delete;
170 ShardedServerSocket& operator=(ShardedServerSocket&&) = delete;
171 ShardedServerSocket& operator=(const ShardedServerSocket&) = delete;
9f95a23c 172
aee94f69
TL
173 bool is_fixed_shard_dispatching() const {
174 return dispatch_only_on_primary_sid;
9f95a23c
TL
175 }
176
aee94f69 177 listen_ertr::future<> listen(entity_addr_t addr);
9f95a23c 178
aee94f69
TL
179 using accept_func_t =
180 std::function<seastar::future<>(SocketRef, entity_addr_t)>;
181 seastar::future<> accept(accept_func_t &&_fn_accept);
9f95a23c 182
aee94f69 183 seastar::future<> shutdown_destroy();
9f95a23c 184
aee94f69
TL
185 static seastar::future<ShardedServerSocket*> create(
186 bool dispatch_only_on_this_shard);
9f95a23c 187
aee94f69
TL
188private:
189 const seastar::shard_id primary_sid;
190 /// XXX: Remove once all infrastructure uses multi-core messenger
191 const bool dispatch_only_on_primary_sid;
192 entity_addr_t listen_addr;
193 std::optional<seastar::server_socket> listener;
194 seastar::gate shutdown_gate;
195 accept_func_t fn_accept;
196
197 using sharded_service_t = seastar::sharded<ShardedServerSocket>;
198 std::unique_ptr<sharded_service_t> service;
11fdf7f2
TL
199};
200
9f95a23c 201} // namespace crimson::net