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