• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // server.cpp
3 // ~~~~~~~~~~
4 //
5 // Copyright (c) 2003-2020 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 <functional>
13 #include <iostream>
14 #include <boost/asio.hpp>
15 #include <boost/asio/ssl.hpp>
16 
17 using boost::asio::ip::tcp;
18 
19 class session : public std::enable_shared_from_this<session>
20 {
21 public:
session(boost::asio::ssl::stream<tcp::socket> socket)22   session(boost::asio::ssl::stream<tcp::socket> socket)
23     : socket_(std::move(socket))
24   {
25   }
26 
start()27   void start()
28   {
29     do_handshake();
30   }
31 
32 private:
do_handshake()33   void do_handshake()
34   {
35     auto self(shared_from_this());
36     socket_.async_handshake(boost::asio::ssl::stream_base::server,
37         [this, self](const boost::system::error_code& error)
38         {
39           if (!error)
40           {
41             do_read();
42           }
43         });
44   }
45 
do_read()46   void do_read()
47   {
48     auto self(shared_from_this());
49     socket_.async_read_some(boost::asio::buffer(data_),
50         [this, self](const boost::system::error_code& ec, std::size_t length)
51         {
52           if (!ec)
53           {
54             do_write(length);
55           }
56         });
57   }
58 
do_write(std::size_t length)59   void do_write(std::size_t length)
60   {
61     auto self(shared_from_this());
62     boost::asio::async_write(socket_, boost::asio::buffer(data_, length),
63         [this, self](const boost::system::error_code& ec,
64           std::size_t /*length*/)
65         {
66           if (!ec)
67           {
68             do_read();
69           }
70         });
71   }
72 
73   boost::asio::ssl::stream<tcp::socket> socket_;
74   char data_[1024];
75 };
76 
77 class server
78 {
79 public:
server(boost::asio::io_context & io_context,unsigned short port)80   server(boost::asio::io_context& io_context, unsigned short port)
81     : acceptor_(io_context, tcp::endpoint(tcp::v4(), port)),
82       context_(boost::asio::ssl::context::sslv23)
83   {
84     context_.set_options(
85         boost::asio::ssl::context::default_workarounds
86         | boost::asio::ssl::context::no_sslv2
87         | boost::asio::ssl::context::single_dh_use);
88     context_.set_password_callback(std::bind(&server::get_password, this));
89     context_.use_certificate_chain_file("server.pem");
90     context_.use_private_key_file("server.pem", boost::asio::ssl::context::pem);
91     context_.use_tmp_dh_file("dh2048.pem");
92 
93     do_accept();
94   }
95 
96 private:
get_password() const97   std::string get_password() const
98   {
99     return "test";
100   }
101 
do_accept()102   void do_accept()
103   {
104     acceptor_.async_accept(
105         [this](const boost::system::error_code& error, tcp::socket socket)
106         {
107           if (!error)
108           {
109             std::make_shared<session>(
110                 boost::asio::ssl::stream<tcp::socket>(
111                   std::move(socket), context_))->start();
112           }
113 
114           do_accept();
115         });
116   }
117 
118   tcp::acceptor acceptor_;
119   boost::asio::ssl::context context_;
120 };
121 
main(int argc,char * argv[])122 int main(int argc, char* argv[])
123 {
124   try
125   {
126     if (argc != 2)
127     {
128       std::cerr << "Usage: server <port>\n";
129       return 1;
130     }
131 
132     boost::asio::io_context io_context;
133 
134     using namespace std; // For atoi.
135     server s(io_context, atoi(argv[1]));
136 
137     io_context.run();
138   }
139   catch (std::exception& e)
140   {
141     std::cerr << "Exception: " << e.what() << "\n";
142   }
143 
144   return 0;
145 }
146