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 238 : awaitable<io_result> ssl_socket::read_some(uint8_t buffer[], size_t max_size) {
58 : co_return co_await ssl_stream_.async_read_some(
59 : boost::asio::buffer(buffer, max_size),
60 : use_nothrow_awaitable);
61 476 : }
62 :
63 0 : awaitable<io_result> ssl_socket::read(uint8_t buffer[], size_t size) {
64 : co_return co_await boost::asio::async_read(
65 : ssl_stream_,
66 : boost::asio::buffer(buffer, size),
67 : boost::asio::transfer_exactly(size),
68 : use_nothrow_awaitable);
69 0 : }
70 :
71 0 : awaitable<io_result> ssl_socket::read(boost::asio::streambuf& buffer, size_t size) {
72 : co_return co_await boost::asio::async_read(
73 : ssl_stream_,
74 : buffer,
75 : boost::asio::transfer_exactly(size),
76 : use_nothrow_awaitable);
77 0 : }
78 :
79 0 : awaitable<io_result> ssl_socket::read_until(boost::asio::streambuf& buffer, std::string_view delim) {
80 : co_return co_await boost::asio::async_read_until(
81 : ssl_stream_,
82 : buffer,
83 : std::string(delim),
84 : use_nothrow_awaitable);
85 0 : }
86 :
87 0 : awaitable<io_result> ssl_socket::write(const uint8_t buffer[], size_t size) {
88 : co_return co_await boost::asio::async_write(
89 : ssl_stream_,
90 : boost::asio::buffer(buffer, size),
91 : use_nothrow_awaitable);
92 0 : }
93 :
94 0 : awaitable<io_result> ssl_socket::write(std::string_view str) {
95 : co_return co_await boost::asio::async_write(
96 : ssl_stream_,
97 : boost::asio::buffer(str.data(), str.size()),
98 : use_nothrow_awaitable);
99 0 : }
100 :
101 118 : awaitable<io_result> ssl_socket::write(const std::vector<boost::asio::const_buffer>& buffers) {
102 : co_return co_await boost::asio::async_write(
103 : ssl_stream_,
104 : buffers,
105 : use_nothrow_awaitable);
106 236 : }
107 :
108 130 : bool ssl_socket::is_secure() const {
109 130 : return true;
110 : }
111 :
112 : }
|