#pragma once #include "error.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace beast = boost::beast; // from namespace http = beast::http; // from namespace net = boost::asio; // from namespace ssl = boost::asio::ssl; // from namespace websocket = beast::websocket; using tcp = boost::asio::ip::tcp; // from class websocket_session: public std::enable_shared_from_this { websocket::stream> ws_; beast::flat_buffer buffer_; public: explicit websocket_session(beast::ssl_stream&& stream) : ws_(std::move(stream)) { } // Start the asynchronous accept operation template void do_accept(http::request> req) { // Set suggested timeout settings for the websocket ws_.set_option( websocket::stream_base::timeout::suggested( beast::role_type::server)); // Set a decorator to change the Server of the handshake ws_.set_option(websocket::stream_base::decorator( [](websocket::response_type& res) { res.set(http::field::server, std::string{"Reichwein.IT Webserver"}); })); // Accept the websocket handshake ws_.async_accept( req, beast::bind_front_handler( &websocket_session::on_accept, shared_from_this())); } private: void on_accept(beast::error_code ec) { if(ec) return fail(ec, "accept"); // Read a message do_read(); } void do_read() { // Read a message into our buffer ws_.async_read( buffer_, beast::bind_front_handler( &websocket_session::on_read, shared_from_this())); } void on_read( beast::error_code ec, std::size_t bytes_transferred) { boost::ignore_unused(bytes_transferred); // This indicates that the websocket_session was closed if(ec == websocket::error::closed) return; if(ec) fail(ec, "read"); // Echo the message ws_.text(ws_.got_text()); std::string data(boost::asio::buffers_begin(buffer_.data()), boost::asio::buffers_end(buffer_.data())); static int count{}; data += ": " + std::to_string(count++); buffer_.consume(buffer_.size()); boost::beast::ostream(buffer_) << data; ws_.async_write( buffer_.data(), beast::bind_front_handler( &websocket_session::on_write, shared_from_this())); } void on_write( beast::error_code ec, std::size_t bytes_transferred) { boost::ignore_unused(bytes_transferred); if(ec) return fail(ec, "write"); // Clear the buffer buffer_.consume(buffer_.size()); // Do another read do_read(); } };