userver: userver/engine/io/tls_wrapper.hpp Source File
Loading...
Searching...
No Matches
tls_wrapper.hpp
Go to the documentation of this file.
1#pragma once
2
3/// @file userver/engine/io/tls_wrapper.hpp
4/// @brief TLS socket wrappers
5
6#include <span>
7#include <string>
8#include <vector>
9
10#include <userver/crypto/certificate.hpp>
11#include <userver/crypto/private_key.hpp>
12#include <userver/crypto/ssl_ctx.hpp>
13#include <userver/engine/deadline.hpp>
14#include <userver/engine/io/common.hpp>
15#include <userver/engine/io/socket.hpp>
16#include <userver/utils/fast_pimpl.hpp>
17
18USERVER_NAMESPACE_BEGIN
19
20namespace engine::io {
21
22/// Class for TLS communications over a Socket.
23///
24/// Not thread safe. E.g. you MAY NOT read and write concurrently from multiple
25/// coroutines.
26///
27/// Usage example:
28/// @snippet src/engine/io/tls_wrapper_test.cpp TLS wrapper usage
29class [[nodiscard]] TlsWrapper final : public RwBase {
30public:
31 /// Starts a TLS client on an opened socket
32 static TlsWrapper StartTlsClient(Socket&& socket, const std::string& server_name, Deadline deadline);
33
34 /// Starts a TLS client with client cert on an opened socket
35 static TlsWrapper StartTlsClient(
36 Socket&& socket,
37 const std::string& server_name,
38 const crypto::Certificate& cert,
39 const crypto::PrivateKey& key,
40 Deadline deadline,
41 const std::vector<crypto::Certificate>& extra_cert_authorities = {}
42 );
43
44 /// Starts a TLS server on an opened socket
45 static TlsWrapper StartTlsServer(Socket&& socket, const crypto::SslCtx& ctx, Deadline deadline);
46
47 ~TlsWrapper() override;
48
49 TlsWrapper(const TlsWrapper&) = delete;
50 TlsWrapper(TlsWrapper&&) noexcept;
51
52 /// Whether the socket is valid.
53 explicit operator bool() const { return IsValid(); }
54
55 /// Whether the socket is valid.
56 bool IsValid() const override;
57
58 /// Suspends current task until the socket has data available.
59 /// @returns false on timeout or on task cancellations; true otherwise.
60 [[nodiscard]] bool WaitReadable(Deadline) override;
61
62 /// Suspends current task until the socket can accept more data.
63 /// @returns false on timeout or on task cancellations; true otherwise.
64 [[nodiscard]] bool WaitWriteable(Deadline) override;
65
66 /// @brief Receives at least one byte from the socket.
67 /// @returns 0 if connection is closed on one side and no data could be
68 /// received any more, received bytes count otherwise.
69 [[nodiscard]] size_t RecvSome(void* buf, size_t len, Deadline deadline);
70
71 /// @brief Receives up to len bytes from the socket
72 /// @returns
73 /// - nullopt on data absence
74 /// - optional{0} if socket is closed by peer.
75 /// - optional{data_bytes_available} otherwise,
76 /// 1 <= data_bytes_available <= len
77 [[nodiscard]] std::optional<size_t> RecvNoblock(void* buf, size_t len);
78
79 /// @brief Receives exactly len bytes from the socket.
80 /// @note Can return less than len if socket is closed by peer.
81 [[nodiscard]] size_t RecvAll(void* buf, size_t len, Deadline deadline);
82
83 /// @brief Sends exactly len bytes to the socket.
84 /// @note Can return less than len if socket is closed by peer.
85 [[nodiscard]] size_t SendAll(const void* buf, size_t len, Deadline deadline);
86
87 /// @brief Finishes TLS session and returns the socket.
88 /// @warning Wrapper becomes invalid on entry and can only be used to retry
89 /// socket extraction if interrupted.
90 [[nodiscard]] Socket StopTls(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> ReadNoblock(void* buf, size_t len) override { return RecvNoblock(buf, len); }
99
100 /// @brief Receives at least one byte from the socket.
101 /// @returns 0 if connection is closed on one side and no data could be
102 /// received any more, received bytes count otherwise.
103 [[nodiscard]] size_t ReadSome(void* buf, size_t len, Deadline deadline) override {
104 return RecvSome(buf, len, deadline);
105 }
106
107 /// @brief Receives exactly len bytes from the socket.
108 /// @note Can return less than len if socket is closed by peer.
109 [[nodiscard]] size_t ReadAll(void* buf, size_t len, Deadline deadline) override {
110 return RecvAll(buf, len, deadline);
111 }
112
113 /// @brief Writes exactly len bytes to the socket.
114 /// @note Can return less than len if socket is closed by peer.
115 [[nodiscard]] size_t WriteAll(const void* buf, size_t len, Deadline deadline) override {
116 return SendAll(buf, len, deadline);
117 }
118
119 [[nodiscard]] size_t WriteAll(std::span<const IoData> list, Deadline deadline) override;
120
121 [[nodiscard]] size_t WriteAll(std::initializer_list<IoData> list, Deadline deadline) override {
122 return WriteAll(std::span<const IoData>{list.begin(), list.size()}, deadline);
123 }
124
125 int GetRawFd();
126
127private:
128 explicit TlsWrapper(Socket&&);
129
130 void SetupContextAccessors();
131
132 class Impl;
133 class ReadContextAccessor;
134 constexpr static size_t kSize = 336;
135 constexpr static size_t kAlignment = 8;
136 utils::FastPimpl<Impl, kSize, kAlignment> impl_;
137};
138
139} // namespace engine::io
140
141USERVER_NAMESPACE_END