1//
2// client.cpp
3// ~~~~~~~~~~
4//
5// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com)
6//
7// Distributed under the Boost Software License, Version 1.0. (See accompanying
8// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
9//
10
11#include <cstdlib>
12#include <cstring>
13#include <functional>
14#include <iostream>
15#include <boost/asio.hpp>
16#include <boost/asio/ssl.hpp>
17
18using boost::asio::ip::tcp;
19using std::placeholders::_1;
20using std::placeholders::_2;
21
22enum { max_length = 1024 };
23
24class client
25{
26public:
27 client(boost::asio::io_context& io_context,
28 boost::asio::ssl::context& context,
29 const tcp::resolver::results_type& endpoints)
30 : socket_(io_context, context)
31 {
32 socket_.set_verify_mode(boost::asio::ssl::verify_peer);
33 socket_.set_verify_callback(
34 std::bind(f: &client::verify_certificate, args: this, args: _1, args: _2));
35
36 connect(endpoints);
37 }
38
39private:
40 bool verify_certificate(bool preverified,
41 boost::asio::ssl::verify_context& ctx)
42 {
43 // The verify callback can be used to check whether the certificate that is
44 // being presented is valid for the peer. For example, RFC 2818 describes
45 // the steps involved in doing this for HTTPS. Consult the OpenSSL
46 // documentation for more details. Note that the callback is called once
47 // for each certificate in the certificate chain, starting from the root
48 // certificate authority.
49
50 // In this example we will simply print the certificate's subject name.
51 char subject_name[256];
52 X509* cert = X509_STORE_CTX_get_current_cert(ctx: ctx.native_handle());
53 X509_NAME_oneline(a: X509_get_subject_name(a: cert), buf: subject_name, size: 256);
54 std::cout << "Verifying " << subject_name << "\n";
55
56 return preverified;
57 }
58
59 void connect(const tcp::resolver::results_type& endpoints)
60 {
61 boost::asio::async_connect(s&: socket_.lowest_layer(), endpoints,
62 token: [this](const boost::system::error_code& error,
63 const tcp::endpoint& /*endpoint*/)
64 {
65 if (!error)
66 {
67 handshake();
68 }
69 else
70 {
71 std::cout << "Connect failed: " << error.message() << "\n";
72 }
73 });
74 }
75
76 void handshake()
77 {
78 socket_.async_handshake(type: boost::asio::ssl::stream_base::client,
79 token: [this](const boost::system::error_code& error)
80 {
81 if (!error)
82 {
83 send_request();
84 }
85 else
86 {
87 std::cout << "Handshake failed: " << error.message() << "\n";
88 }
89 });
90 }
91
92 void send_request()
93 {
94 std::cout << "Enter message: ";
95 std::cin.getline(s: request_, n: max_length);
96 size_t request_length = std::strlen(s: request_);
97
98 boost::asio::async_write(s&: socket_,
99 buffers: boost::asio::buffer(data&: request_, max_size_in_bytes: request_length),
100 token: [this](const boost::system::error_code& error, std::size_t length)
101 {
102 if (!error)
103 {
104 receive_response(length);
105 }
106 else
107 {
108 std::cout << "Write failed: " << error.message() << "\n";
109 }
110 });
111 }
112
113 void receive_response(std::size_t length)
114 {
115 boost::asio::async_read(s&: socket_,
116 buffers: boost::asio::buffer(data&: reply_, max_size_in_bytes: length),
117 token: [this](const boost::system::error_code& error, std::size_t length)
118 {
119 if (!error)
120 {
121 std::cout << "Reply: ";
122 std::cout.write(s: reply_, n: length);
123 std::cout << "\n";
124 }
125 else
126 {
127 std::cout << "Read failed: " << error.message() << "\n";
128 }
129 });
130 }
131
132 boost::asio::ssl::stream<tcp::socket> socket_;
133 char request_[max_length];
134 char reply_[max_length];
135};
136
137int main(int argc, char* argv[])
138{
139 try
140 {
141 if (argc != 3)
142 {
143 std::cerr << "Usage: client <host> <port>\n";
144 return 1;
145 }
146
147 boost::asio::io_context io_context;
148
149 tcp::resolver resolver(io_context);
150 auto endpoints = resolver.resolve(host: argv[1], service: argv[2]);
151
152 boost::asio::ssl::context ctx(boost::asio::ssl::context::sslv23);
153 ctx.load_verify_file(filename: "ca.pem");
154
155 client c(io_context, ctx, endpoints);
156
157 io_context.run();
158 }
159 catch (std::exception& e)
160 {
161 std::cerr << "Exception: " << e.what() << "\n";
162 }
163
164 return 0;
165}
166

source code of boost/libs/asio/example/cpp11/ssl/client.cpp