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