userver: userver/engine/io/socket.hpp Source File
Loading...
Searching...
No Matches
socket.hpp
Go to the documentation of this file.
1#pragma once
2
3/// @file userver/engine/io/socket.hpp
4/// @brief @copybrief engine::io::Socket
5
6#include <sys/socket.h>
7
8#include <span>
9
10#include <userver/engine/deadline.hpp>
11#include <userver/engine/io/common.hpp>
12#include <userver/engine/io/exception.hpp>
13#include <userver/engine/io/fd_control_holder.hpp>
14#include <userver/engine/io/sockaddr.hpp>
15
16struct iovec;
17
18USERVER_NAMESPACE_BEGIN
19
20namespace engine::ev {
21class ThreadControl;
22} // namespace engine::ev
23
24namespace engine::io {
25
26/// Socket type
27enum class SocketType {
28 kStream = SOCK_STREAM, ///< Stream socket (e.g. TCP)
29 kDgram = SOCK_DGRAM, ///< Datagram socket (e.g. UDP)
30
31 kTcp = kStream,
32 kUdp = kDgram,
33};
34
35/// @brief Socket representation.
36///
37/// It is not thread-safe to concurrently read from socket. It is not
38/// thread-safe to concurrently write to socket. However it is safe to
39/// concurrently read and write into socket:
40/// @snippet src/engine/io/socket_test.cpp send self concurrent
41class [[nodiscard]] Socket final : public RwBase {
42public:
44 size_t bytes_received{0};
45 Sockaddr src_addr;
46 };
47
48 /// Constructs an invalid socket.
49 Socket() = default;
50
51 /// Constructs a socket for the address domain of specified type.
53
54 /// @brief Adopts an existing socket for specified address domain.
55 /// @note File descriptor will be silently forced to nonblocking mode.
56 explicit Socket(int fd, AddrDomain domain = AddrDomain::kUnspecified);
57
58 /// Whether the socket is valid.
59 explicit operator bool() const { return IsValid(); }
60
61 /// Whether the socket is valid.
62 bool IsValid() const override;
63
64 /// @brief Connects the socket to a specified endpoint.
65 /// @note Sockaddr domain must match the socket's domain.
66 void Connect(const Sockaddr&, Deadline);
67
68 /// @brief Binds the socket to the specified endpoint.
69 /// @note Sockaddr domain must match the socket's domain.
70 void Bind(const Sockaddr&);
71
72 /// Starts listening for connections on a specified socket (must be bound).
73 void Listen(int backlog = SOMAXCONN);
74
75 /// Suspends current task until the socket has data available.
76 /// @returns false on timeout or on task cancellations; true otherwise.
77 [[nodiscard]] bool WaitReadable(Deadline) override;
78
79 /// Suspends current task until the socket can accept more data.
80 /// @returns false on timeout or on task cancellations; true otherwise.
81 [[nodiscard]] bool WaitWriteable(Deadline) override;
82
83 /// @brief Receives at least one byte from the socket.
84 /// @returns 0 if connection is closed on one side and no data could be
85 /// received any more, received bytes count otherwise.
86 [[nodiscard]] size_t RecvSome(void* buf, size_t len, Deadline deadline);
87
88 /// @brief Receives exactly len bytes from the socket.
89 /// @note Can return less than len if socket is closed by peer.
90 [[nodiscard]] size_t RecvAll(void* buf, size_t len, Deadline deadline);
91
92 /// @brief Receives up to len bytes from the stream
93 /// @returns
94 /// - nullopt on data absence
95 /// - optional{0} if socket is closed by peer.
96 /// - optional{data_bytes_available} otherwise,
97 /// 1 <= data_bytes_available <= len
98 [[nodiscard]] std::optional<size_t> RecvNoblock(void* buf, size_t len);
99
100 /// @brief Sends a buffer vector to the socket.
101 /// @note Can return less than len if socket is closed by peer.
102 /// @snippet src/engine/io/socket_test.cpp send vector data in socket
103 [[nodiscard]] size_t SendAll(std::initializer_list<IoData> list, Deadline deadline);
104
105 [[nodiscard]] size_t SendAll(std::span<const IoData> list, Deadline deadline);
106
107 [[nodiscard]] size_t WriteAll(std::span<const IoData> list, Deadline deadline) override {
108 return SendAll(list, deadline);
109 }
110
111 /// @brief Sends exactly list_size IoData to the socket.
112 /// @note Can return less than len if socket is closed by peer.
113 [[nodiscard]] size_t SendAll(const IoData* list, std::size_t list_size, Deadline deadline);
114
115 /// @brief Sends exactly list_size iovec to the socket.
116 /// @note Can return less than len if socket is closed by peer.
117 [[nodiscard]] size_t SendAll(const struct iovec* list, std::size_t list_size, Deadline deadline);
118
119 /// @brief Sends exactly len bytes to the socket.
120 /// @note Can return less than len if socket is closed by peer.
121 [[nodiscard]] size_t SendAll(const void* buf, size_t len, Deadline deadline);
122
123 /// @brief Accepts a connection from a listening socket.
124 /// @see engine::io::Listen
125 [[nodiscard]] Socket Accept(Deadline);
126
127 /// @brief Receives at least one byte from the socket, returning source
128 /// address.
129 /// @returns 0 in bytes_sent if connection is closed on one side and no data
130 /// could be received any more, received bytes count otherwise + source
131 /// address.
132 [[nodiscard]] RecvFromResult RecvSomeFrom(void* buf, size_t len, Deadline deadline);
133
134 /// @brief Sends exactly len bytes to the specified address via the socket.
135 /// @note Can return less than len in bytes_sent if socket is closed by peer.
136 /// @note Sockaddr domain must match the socket's domain.
137 /// @note Not for SocketType::kStream connections, see `man sendto`.
138 [[nodiscard]] size_t SendAllTo(const Sockaddr& dest_addr, const void* buf, size_t len, Deadline deadline);
139
140 /// File descriptor corresponding to this socket.
141 int Fd() const;
142
143 /// Address of a remote peer.
144 const Sockaddr& Getpeername();
145
146 /// Local socket address.
147 const Sockaddr& Getsockname();
148
149 /// Releases file descriptor and invalidates the socket.
150 [[nodiscard]] int Release() && noexcept;
151
152 /// @brief Closes and invalidates the socket.
153 /// @warning You should not call Close with pending I/O. This may work okay
154 /// sometimes but it's loosely predictable.
155 void Close();
156
157 /// Retrieves a socket option.
158 int GetOption(int layer, int optname) const;
159
160 /// Sets a socket option.
161 void SetOption(int layer, int optname, int optval);
162
163 /// Sets a socket option with non-trivial optval.
164 void SetOption(int layer, int optname, const void* optval, socklen_t optlen);
165
166 /// @brief Receives at least one byte from the socket.
167 /// @returns 0 if connection is closed on one side and no data could be
168 /// received any more, received bytes count otherwise.
169 [[nodiscard]] size_t ReadSome(void* buf, size_t len, Deadline deadline) override {
170 return RecvSome(buf, len, deadline);
171 }
172
173 /// @brief Receives exactly len bytes from the socket.
174 /// @note Can return less than len if socket is closed by peer.
175 [[nodiscard]] size_t ReadAll(void* buf, size_t len, Deadline deadline) override {
176 return RecvAll(buf, len, deadline);
177 }
178
179 /// @brief Receives up to len bytes from the stream
180 /// @returns
181 /// - nullopt on data absence
182 /// - optional{0} if socket is closed by peer.
183 /// - optional{data_bytes_available} otherwise,
184 /// 1 <= data_bytes_available <= len
185 [[nodiscard]] std::optional<size_t> ReadNoblock(void* buf, size_t len) override { return RecvNoblock(buf, len); }
186
187 /// @brief Writes exactly len bytes to the socket.
188 /// @note Can return less than len if socket is closed by peer.
189 [[nodiscard]] size_t WriteAll(const void* buf, size_t len, Deadline deadline) override {
190 return SendAll(buf, len, deadline);
191 }
192
193private:
195
196 impl::FdControlHolder fd_control_;
197 Sockaddr peername_;
198 Sockaddr sockname_;
199};
200
201} // namespace engine::io
202
203USERVER_NAMESPACE_END