server.cpp 3.8 KB

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