Files
boost_beast/test/websocket/doc_snippets.cpp

285 lines
6.2 KiB
C++
Raw Normal View History

2017-06-07 16:30:49 -07:00
//
2017-07-24 09:42:36 -07:00
// Copyright (c) 2016-2017 Vinnie Falco (vinnie dot falco at gmail dot com)
2017-06-07 16:30:49 -07:00
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
2017-07-20 13:40:34 -07:00
// Official repository: https://github.com/boostorg/beast
//
2017-06-07 16:30:49 -07:00
2017-07-20 13:40:34 -07:00
#include <boost/beast/core.hpp>
2017-06-07 16:30:49 -07:00
#include <boost/asio.hpp>
2017-06-08 15:23:30 -07:00
#include <boost/asio/spawn.hpp>
#include <boost/asio/use_future.hpp>
#include <algorithm>
#include <future>
2017-06-07 16:30:49 -07:00
#include <iostream>
#include <thread>
//[ws_snippet_1
2017-07-20 13:40:34 -07:00
#include <boost/beast/websocket.hpp>
using namespace boost::beast::websocket;
2017-06-07 16:30:49 -07:00
//]
2017-07-20 13:40:34 -07:00
using namespace boost::beast;
2017-06-08 15:23:30 -07:00
2017-06-07 16:30:49 -07:00
namespace doc_ws_snippets {
void fxx() {
boost::asio::io_service ios;
boost::asio::io_service::work work{ios};
std::thread t{[&](){ ios.run(); }};
error_code ec;
boost::asio::ip::tcp::socket sock{ios};
{
//[ws_snippet_2
stream<boost::asio::ip::tcp::socket> ws{ios};
//]
}
{
//[ws_snippet_3
stream<boost::asio::ip::tcp::socket> ws{std::move(sock)};
//]
}
{
//[ws_snippet_4
stream<boost::asio::ip::tcp::socket&> ws{sock};
//]
//[ws_snippet_5
ws.next_layer().shutdown(boost::asio::ip::tcp::socket::shutdown_send);
//]
}
{
//[ws_snippet_6
std::string const host = "mywebapp.com";
boost::asio::ip::tcp::resolver r{ios};
stream<boost::asio::ip::tcp::socket> ws{ios};
2017-06-19 07:28:20 -07:00
boost::asio::connect(ws.next_layer(), r.resolve({host, "ws"}));
2017-06-07 16:30:49 -07:00
//]
}
{
//[ws_snippet_7
boost::asio::ip::tcp::acceptor acceptor{ios};
stream<boost::asio::ip::tcp::socket> ws{acceptor.get_io_service()};
acceptor.accept(ws.next_layer());
//]
}
2017-06-08 15:23:30 -07:00
{
stream<boost::asio::ip::tcp::socket> ws{ios};
//[ws_snippet_8
ws.handshake("localhost", "/");
//]
//[ws_snippet_9
ws.handshake_ex("localhost", "/",
2017-06-18 14:57:32 -07:00
[](request_type& m)
2017-06-08 15:23:30 -07:00
{
2017-06-18 14:57:32 -07:00
m.insert(http::field::sec_websocket_protocol, "xmpp;ws-chat");
2017-06-08 15:23:30 -07:00
});
//]
//[ws_snippet_10
response_type res;
ws.handshake(res, "localhost", "/");
if(! res.count(http::field::sec_websocket_protocol))
2017-06-08 15:23:30 -07:00
throw std::invalid_argument("missing subprotocols");
//]
//[ws_snippet_11
ws.accept();
//]
//[ws_snippet_12
ws.accept_ex(
2017-06-18 14:57:32 -07:00
[](response_type& m)
2017-06-08 15:23:30 -07:00
{
2017-06-18 14:57:32 -07:00
m.insert(http::field::server, "MyServer");
2017-06-08 15:23:30 -07:00
});
//]
}
{
//[ws_snippet_13]
// Buffer required for reading HTTP messages
flat_buffer buffer;
// Read the HTTP request ourselves
http::request<http::string_body> req;
http::read(sock, buffer, req);
// See if its a WebSocket upgrade request
if(websocket::is_upgrade(req))
{
// Construct the stream, transferring ownership of the socket
stream<boost::asio::ip::tcp::socket> ws{std::move(sock)};
// Accept the request from our message. Clients SHOULD NOT
// begin sending WebSocket frames until the server has
// provided a response, but just in case they did, we pass
// any leftovers in the buffer to the accept function.
//
ws.accept(req, buffer.data());
}
else
{
// Its not a WebSocket upgrade, so
// handle it like a normal HTTP request.
}
//]
}
{
stream<boost::asio::ip::tcp::socket> ws{ios};
//[ws_snippet_14
// Read into our buffer until we reach the end of the HTTP request.
// No parsing takes place here, we are just accumulating data.
boost::asio::streambuf buffer;
boost::asio::read_until(sock, buffer, "\r\n\r\n");
// Now accept the connection, using the buffered data.
ws.accept(buffer.data());
//]
}
{
stream<boost::asio::ip::tcp::socket> ws{ios};
//[ws_snippet_15
multi_buffer buffer;
ws.read(buffer);
2017-06-08 15:23:30 -07:00
ws.text(ws.got_text());
2017-06-08 15:23:30 -07:00
ws.write(buffer.data());
buffer.consume(buffer.size());
//]
}
{
stream<boost::asio::ip::tcp::socket> ws{ios};
//[ws_snippet_16
multi_buffer buffer;
for(;;)
if(ws.read_some(buffer, 0))
2017-06-08 15:23:30 -07:00
break;
ws.binary(ws.got_binary());
2017-06-08 15:23:30 -07:00
consuming_buffers<multi_buffer::const_buffers_type> cb{buffer.data()};
for(;;)
{
using boost::asio::buffer_size;
if(buffer_size(cb) > 512)
{
ws.write_some(false, buffer_prefix(512, cb));
2017-06-08 15:23:30 -07:00
cb.consume(512);
}
else
{
ws.write_some(true, cb);
2017-06-08 15:23:30 -07:00
break;
}
}
//]
}
{
stream<boost::asio::ip::tcp::socket> ws{ios};
//[ws_snippet_17
ws.control_callback(
[](frame_type kind, string_view payload)
2017-06-08 15:23:30 -07:00
{
// Do something with the payload
boost::ignore_unused(kind, payload);
});
2017-06-08 15:23:30 -07:00
//]
//[ws_snippet_18
ws.close(close_code::normal);
//]
//[ws_snippet_19
ws.auto_fragment(true);
ws.write_buffer_size(16384);
2017-06-08 15:23:30 -07:00
//]
//[ws_snippet_20
multi_buffer buffer;
ws.async_read(buffer,
2017-06-18 14:57:32 -07:00
[](error_code)
2017-06-08 15:23:30 -07:00
{
// Do something with the buffer
});
//]
}
2017-06-07 16:30:49 -07:00
} // fxx()
2017-06-08 22:03:58 -07:00
// workaround for https://github.com/chriskohlhoff/asio/issues/112
2017-07-07 17:47:24 -07:00
#ifdef BOOST_MSVC
2017-06-08 15:23:30 -07:00
//[ws_snippet_21
void echo(stream<boost::asio::ip::tcp::socket>& ws,
multi_buffer& buffer, boost::asio::yield_context yield)
{
ws.async_read(buffer, yield);
2017-06-08 15:23:30 -07:00
std::future<void> fut =
ws.async_write(buffer.data(), boost::asio::use_future);
}
//]
#endif
2017-06-08 15:23:30 -07:00
2017-06-07 16:30:49 -07:00
} // doc_ws_snippets
//------------------------------------------------------------------------------
2017-07-20 13:40:34 -07:00
#if BOOST_BEAST_USE_OPENSSL
//[wss_snippet_1
2017-07-20 13:40:34 -07:00
#include <boost/beast/websocket/ssl.hpp>
#include <boost/asio/ssl.hpp>
//]
namespace doc_wss_snippets {
void fxx() {
boost::asio::io_service ios;
boost::asio::io_service::work work{ios};
std::thread t{[&](){ ios.run(); }};
error_code ec;
boost::asio::ip::tcp::socket sock{ios};
{
//[wss_snippet_2
boost::asio::ssl::context ctx{boost::asio::ssl::context::sslv23};
stream<boost::asio::ssl::stream<boost::asio::ip::tcp::socket>> wss{ios, ctx};
//]
}
{
//[wss_snippet_3
boost::asio::ip::tcp::endpoint ep;
boost::asio::ssl::context ctx{boost::asio::ssl::context::sslv23};
stream<boost::asio::ssl::stream<boost::asio::ip::tcp::socket>> ws{ios, ctx};
// connect the underlying TCP/IP socket
ws.next_layer().next_layer().connect(ep);
// perform SSL handshake
ws.next_layer().handshake(boost::asio::ssl::stream_base::client);
// perform WebSocket handshake
ws.handshake("localhost", "/");
//]
}
} // fxx()
} // doc_wss_snippets
#endif