websocket_server_sync_ssl.cpp 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. //
  2. // Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
  3. //
  4. // Distributed under the Boost Software License, Version 1.0. (See accompanying
  5. // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  6. //
  7. // Official repository: https://github.com/boostorg/beast
  8. //
  9. //------------------------------------------------------------------------------
  10. //
  11. // Example: WebSocket SSL server, synchronous
  12. //
  13. //------------------------------------------------------------------------------
  14. #include "example/common/server_certificate.hpp"
  15. #include <boost/beast/core.hpp>
  16. #include <boost/beast/ssl.hpp>
  17. #include <boost/beast/websocket.hpp>
  18. #include <boost/beast/websocket/ssl.hpp>
  19. #include <boost/asio/ip/tcp.hpp>
  20. #include <boost/asio/ssl/stream.hpp>
  21. #include <cstdlib>
  22. #include <functional>
  23. #include <iostream>
  24. #include <string>
  25. #include <thread>
  26. namespace beast = boost::beast; // from <boost/beast.hpp>
  27. namespace http = beast::http; // from <boost/beast/http.hpp>
  28. namespace websocket = beast::websocket; // from <boost/beast/websocket.hpp>
  29. namespace net = boost::asio; // from <boost/asio.hpp>
  30. namespace ssl = boost::asio::ssl; // from <boost/asio/ssl.hpp>
  31. using tcp = boost::asio::ip::tcp; // from <boost/asio/ip/tcp.hpp>
  32. //------------------------------------------------------------------------------
  33. // Echoes back all received WebSocket messages
  34. void
  35. do_session(tcp::socket& socket, ssl::context& ctx)
  36. {
  37. try
  38. {
  39. // Construct the websocket stream around the socket
  40. websocket::stream<beast::ssl_stream<tcp::socket&>> ws{socket, ctx};
  41. // Perform the SSL handshake
  42. ws.next_layer().handshake(ssl::stream_base::server);
  43. // Set a decorator to change the Server of the handshake
  44. ws.set_option(websocket::stream_base::decorator(
  45. [](websocket::response_type& res)
  46. {
  47. res.set(http::field::server,
  48. std::string(BOOST_BEAST_VERSION_STRING) +
  49. " websocket-server-sync-ssl");
  50. }));
  51. // Accept the websocket handshake
  52. ws.accept();
  53. for(;;)
  54. {
  55. // This buffer will hold the incoming message
  56. beast::flat_buffer buffer;
  57. // Read a message
  58. ws.read(buffer);
  59. // Echo the message back
  60. ws.text(ws.got_text());
  61. ws.write(buffer.data());
  62. }
  63. }
  64. catch(beast::system_error const& se)
  65. {
  66. // This indicates that the session was closed
  67. if(se.code() != websocket::error::closed)
  68. std::cerr << "Error: " << se.code().message() << std::endl;
  69. }
  70. catch(std::exception const& e)
  71. {
  72. std::cerr << "Error: " << e.what() << std::endl;
  73. }
  74. }
  75. //------------------------------------------------------------------------------
  76. int main(int argc, char* argv[])
  77. {
  78. try
  79. {
  80. // Check command line arguments.
  81. if (argc != 3)
  82. {
  83. std::cerr <<
  84. "Usage: websocket-server-sync-ssl <address> <port>\n" <<
  85. "Example:\n" <<
  86. " websocket-server-sync-ssl 0.0.0.0 8080\n";
  87. return EXIT_FAILURE;
  88. }
  89. auto const address = net::ip::make_address(argv[1]);
  90. auto const port = static_cast<unsigned short>(std::atoi(argv[2]));
  91. // The io_context is required for all I/O
  92. net::io_context ioc{1};
  93. // The SSL context is required, and holds certificates
  94. ssl::context ctx{ssl::context::tlsv12};
  95. // This holds the self-signed certificate used by the server
  96. load_server_certificate(ctx);
  97. // The acceptor receives incoming connections
  98. tcp::acceptor acceptor{ioc, {address, port}};
  99. for(;;)
  100. {
  101. // This will receive the new connection
  102. tcp::socket socket{ioc};
  103. // Block until we get a connection
  104. acceptor.accept(socket);
  105. // Launch the session, transferring ownership of the socket
  106. std::thread{std::bind(
  107. &do_session,
  108. std::move(socket),
  109. std::ref(ctx))}.detach();
  110. }
  111. }
  112. catch (const std::exception& e)
  113. {
  114. std::cerr << "Error: " << e.what() << std::endl;
  115. return EXIT_FAILURE;
  116. }
  117. }