server.cpp 3.1 KB

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