Imported Upstream version 1.57.0
[platform/upstream/boost.git] / doc / html / boost_asio / example / cpp03 / ssl / client.cpp
1 //
2 // client.cpp
3 // ~~~~~~~~~~
4 //
5 // Copyright (c) 2003-2014 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 <iostream>
13 #include <boost/bind.hpp>
14 #include <boost/asio.hpp>
15 #include <boost/asio/ssl.hpp>
16
17 enum { max_length = 1024 };
18
19 class client
20 {
21 public:
22   client(boost::asio::io_service& io_service,
23       boost::asio::ssl::context& context,
24       boost::asio::ip::tcp::resolver::iterator endpoint_iterator)
25     : socket_(io_service, context)
26   {
27     socket_.set_verify_mode(boost::asio::ssl::verify_peer);
28     socket_.set_verify_callback(
29         boost::bind(&client::verify_certificate, this, _1, _2));
30
31     boost::asio::async_connect(socket_.lowest_layer(), endpoint_iterator,
32         boost::bind(&client::handle_connect, this,
33           boost::asio::placeholders::error));
34   }
35
36   bool verify_certificate(bool preverified,
37       boost::asio::ssl::verify_context& ctx)
38   {
39     // The verify callback can be used to check whether the certificate that is
40     // being presented is valid for the peer. For example, RFC 2818 describes
41     // the steps involved in doing this for HTTPS. Consult the OpenSSL
42     // documentation for more details. Note that the callback is called once
43     // for each certificate in the certificate chain, starting from the root
44     // certificate authority.
45
46     // In this example we will simply print the certificate's subject name.
47     char subject_name[256];
48     X509* cert = X509_STORE_CTX_get_current_cert(ctx.native_handle());
49     X509_NAME_oneline(X509_get_subject_name(cert), subject_name, 256);
50     std::cout << "Verifying " << subject_name << "\n";
51
52     return preverified;
53   }
54
55   void handle_connect(const boost::system::error_code& error)
56   {
57     if (!error)
58     {
59       socket_.async_handshake(boost::asio::ssl::stream_base::client,
60           boost::bind(&client::handle_handshake, this,
61             boost::asio::placeholders::error));
62     }
63     else
64     {
65       std::cout << "Connect failed: " << error.message() << "\n";
66     }
67   }
68
69   void handle_handshake(const boost::system::error_code& error)
70   {
71     if (!error)
72     {
73       std::cout << "Enter message: ";
74       std::cin.getline(request_, max_length);
75       size_t request_length = strlen(request_);
76
77       boost::asio::async_write(socket_,
78           boost::asio::buffer(request_, request_length),
79           boost::bind(&client::handle_write, this,
80             boost::asio::placeholders::error,
81             boost::asio::placeholders::bytes_transferred));
82     }
83     else
84     {
85       std::cout << "Handshake failed: " << error.message() << "\n";
86     }
87   }
88
89   void handle_write(const boost::system::error_code& error,
90       size_t bytes_transferred)
91   {
92     if (!error)
93     {
94       boost::asio::async_read(socket_,
95           boost::asio::buffer(reply_, bytes_transferred),
96           boost::bind(&client::handle_read, this,
97             boost::asio::placeholders::error,
98             boost::asio::placeholders::bytes_transferred));
99     }
100     else
101     {
102       std::cout << "Write failed: " << error.message() << "\n";
103     }
104   }
105
106   void handle_read(const boost::system::error_code& error,
107       size_t bytes_transferred)
108   {
109     if (!error)
110     {
111       std::cout << "Reply: ";
112       std::cout.write(reply_, bytes_transferred);
113       std::cout << "\n";
114     }
115     else
116     {
117       std::cout << "Read failed: " << error.message() << "\n";
118     }
119   }
120
121 private:
122   boost::asio::ssl::stream<boost::asio::ip::tcp::socket> socket_;
123   char request_[max_length];
124   char reply_[max_length];
125 };
126
127 int main(int argc, char* argv[])
128 {
129   try
130   {
131     if (argc != 3)
132     {
133       std::cerr << "Usage: client <host> <port>\n";
134       return 1;
135     }
136
137     boost::asio::io_service io_service;
138
139     boost::asio::ip::tcp::resolver resolver(io_service);
140     boost::asio::ip::tcp::resolver::query query(argv[1], argv[2]);
141     boost::asio::ip::tcp::resolver::iterator iterator = resolver.resolve(query);
142
143     boost::asio::ssl::context ctx(boost::asio::ssl::context::sslv23);
144     ctx.load_verify_file("ca.pem");
145
146     client c(io_service, ctx, iterator);
147
148     io_service.run();
149   }
150   catch (std::exception& e)
151   {
152     std::cerr << "Exception: " << e.what() << "\n";
153   }
154
155   return 0;
156 }