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