Line data Source code
1 : #include "ssl_socket.hpp"
2 :
3 : namespace thinger::asio {
4 :
5 199 : ssl_socket::ssl_socket(const std::string& context, boost::asio::io_context& io_context,
6 199 : const std::shared_ptr<boost::asio::ssl::context>& ssl_context)
7 : : tcp_socket(context, io_context)
8 199 : , ssl_stream_(socket_, *ssl_context)
9 398 : , ssl_context_(ssl_context) {
10 199 : }
11 :
12 0 : ssl_socket::ssl_socket(const std::string& context, const std::shared_ptr<tcp_socket>& socket,
13 0 : const std::shared_ptr<boost::asio::ssl::context>& ssl_context)
14 : : tcp_socket(context, socket)
15 0 : , ssl_stream_(socket_, *ssl_context)
16 0 : , ssl_context_(ssl_context) {
17 0 : }
18 :
19 199 : ssl_socket::~ssl_socket() {
20 199 : LOG_TRACE("releasing ssl connection");
21 199 : }
22 :
23 67 : void ssl_socket::close() {
24 : // close underlying TCP socket
25 67 : tcp_socket::close();
26 :
27 : // clear ssl session to allow reusing socket (if necessary)
28 : // From SSL_clear: If a session is still open, it is considered bad and will be removed
29 : // from the session cache, as required by RFC2246
30 67 : SSL_clear(ssl_stream_.native_handle());
31 67 : }
32 :
33 110 : bool ssl_socket::requires_handshake() const {
34 110 : return true;
35 : }
36 :
37 104 : awaitable<boost::system::error_code> ssl_socket::handshake(const std::string& host) {
38 : if (!host.empty()) {
39 : // add support for SNI
40 : if (!SSL_set_tlsext_host_name(ssl_stream_.native_handle(), host.c_str())) {
41 : LOG_ERROR("SSL_set_tlsext_host_name failed. SNI will fail");
42 : }
43 : // client handshake
44 : auto [ec] = co_await ssl_stream_.async_handshake(
45 : boost::asio::ssl::stream_base::client,
46 : use_nothrow_awaitable);
47 : co_return ec;
48 : } else {
49 : // server handshake
50 : auto [ec] = co_await ssl_stream_.async_handshake(
51 : boost::asio::ssl::stream_base::server,
52 : use_nothrow_awaitable);
53 : co_return ec;
54 : }
55 208 : }
56 :
57 290 : awaitable<size_t> ssl_socket::read_some(uint8_t buffer[], size_t max_size) {
58 : auto [ec, bytes] = co_await ssl_stream_.async_read_some(
59 : boost::asio::buffer(buffer, max_size),
60 : use_nothrow_awaitable);
61 : if (ec) co_return 0;
62 : co_return bytes;
63 580 : }
64 :
65 0 : awaitable<size_t> ssl_socket::read(uint8_t buffer[], size_t size) {
66 : auto [ec, bytes] = co_await boost::asio::async_read(
67 : ssl_stream_,
68 : boost::asio::buffer(buffer, size),
69 : boost::asio::transfer_exactly(size),
70 : use_nothrow_awaitable);
71 : if (ec) co_return 0;
72 : co_return bytes;
73 0 : }
74 :
75 0 : awaitable<size_t> ssl_socket::read(boost::asio::streambuf& buffer, size_t size) {
76 : auto [ec, bytes] = co_await boost::asio::async_read(
77 : ssl_stream_,
78 : buffer,
79 : boost::asio::transfer_exactly(size),
80 : use_nothrow_awaitable);
81 : if (ec) co_return 0;
82 : co_return bytes;
83 0 : }
84 :
85 0 : awaitable<size_t> ssl_socket::read_until(boost::asio::streambuf& buffer, std::string_view delim) {
86 : auto [ec, bytes] = co_await boost::asio::async_read_until(
87 : ssl_stream_,
88 : buffer,
89 : std::string(delim),
90 : use_nothrow_awaitable);
91 : if (ec) co_return 0;
92 : co_return bytes;
93 0 : }
94 :
95 0 : awaitable<size_t> ssl_socket::write(const uint8_t buffer[], size_t size) {
96 : auto [ec, bytes] = co_await boost::asio::async_write(
97 : ssl_stream_,
98 : boost::asio::buffer(buffer, size),
99 : use_nothrow_awaitable);
100 : if (ec) co_return 0;
101 : co_return bytes;
102 0 : }
103 :
104 0 : awaitable<size_t> ssl_socket::write(std::string_view str) {
105 : auto [ec, bytes] = co_await boost::asio::async_write(
106 : ssl_stream_,
107 : boost::asio::buffer(str.data(), str.size()),
108 : use_nothrow_awaitable);
109 : if (ec) co_return 0;
110 : co_return bytes;
111 0 : }
112 :
113 118 : awaitable<size_t> ssl_socket::write(const std::vector<boost::asio::const_buffer>& buffers) {
114 : auto [ec, bytes] = co_await boost::asio::async_write(
115 : ssl_stream_,
116 : buffers,
117 : use_nothrow_awaitable);
118 : if (ec) co_return 0;
119 : co_return bytes;
120 236 : }
121 :
122 130 : bool ssl_socket::is_secure() const {
123 130 : return true;
124 : }
125 :
126 : }
|