]>
Commit | Line | Data |
---|---|---|
b32b8144 FG |
1 | // |
2 | // Copyright (c) 2016-2017 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 | #include <boost/beast/core.hpp> | |
11 | #include <boost/asio.hpp> | |
12 | #include <boost/asio/spawn.hpp> | |
13 | #include <boost/asio/use_future.hpp> | |
14 | #include <algorithm> | |
15 | #include <future> | |
16 | #include <iostream> | |
17 | #include <thread> | |
18 | ||
19 | //[ws_snippet_1 | |
20 | #include <boost/beast/websocket.hpp> | |
21 | using namespace boost::beast::websocket; | |
22 | //] | |
23 | ||
24 | using namespace boost::beast; | |
25 | ||
26 | namespace doc_ws_snippets { | |
27 | ||
28 | void fxx() { | |
29 | ||
92f5a8d4 TL |
30 | net::io_service ios; |
31 | net::io_service::work work{ios}; | |
b32b8144 FG |
32 | std::thread t{[&](){ ios.run(); }}; |
33 | error_code ec; | |
92f5a8d4 | 34 | net::ip::tcp::socket sock{ios}; |
b32b8144 FG |
35 | |
36 | { | |
37 | //[ws_snippet_2 | |
92f5a8d4 | 38 | stream<net::ip::tcp::socket> ws{ios}; |
b32b8144 FG |
39 | //] |
40 | } | |
41 | ||
42 | { | |
43 | //[ws_snippet_3 | |
92f5a8d4 | 44 | stream<net::ip::tcp::socket> ws{std::move(sock)}; |
b32b8144 FG |
45 | //] |
46 | } | |
47 | ||
48 | { | |
49 | //[ws_snippet_4 | |
92f5a8d4 | 50 | stream<net::ip::tcp::socket&> ws{sock}; |
b32b8144 FG |
51 | //] |
52 | ||
53 | //[ws_snippet_5 | |
92f5a8d4 | 54 | ws.next_layer().shutdown(net::ip::tcp::socket::shutdown_send); |
b32b8144 FG |
55 | //] |
56 | } | |
57 | ||
58 | { | |
59 | //[ws_snippet_6 | |
60 | std::string const host = "mywebapp.com"; | |
92f5a8d4 TL |
61 | net::ip::tcp::resolver r{ios}; |
62 | stream<net::ip::tcp::socket> ws{ios}; | |
63 | net::connect(ws.next_layer(), r.resolve({host, "ws"})); | |
b32b8144 FG |
64 | //] |
65 | } | |
66 | ||
67 | { | |
68 | //[ws_snippet_7 | |
92f5a8d4 TL |
69 | net::ip::tcp::acceptor acceptor{ios}; |
70 | stream<net::ip::tcp::socket> ws{acceptor.get_io_service()}; | |
b32b8144 FG |
71 | acceptor.accept(ws.next_layer()); |
72 | //] | |
73 | } | |
74 | ||
75 | { | |
92f5a8d4 | 76 | stream<net::ip::tcp::socket> ws{ios}; |
b32b8144 FG |
77 | //[ws_snippet_8 |
78 | ws.handshake("localhost", "/"); | |
79 | //] | |
80 | ||
81 | //[ws_snippet_9 | |
82 | ws.handshake_ex("localhost", "/", | |
83 | [](request_type& m) | |
84 | { | |
85 | m.insert(http::field::sec_websocket_protocol, "xmpp;ws-chat"); | |
86 | }); | |
87 | //] | |
88 | ||
89 | //[ws_snippet_10 | |
90 | response_type res; | |
91 | ws.handshake(res, "localhost", "/"); | |
92 | if(! res.count(http::field::sec_websocket_protocol)) | |
93 | throw std::invalid_argument("missing subprotocols"); | |
94 | //] | |
95 | ||
96 | //[ws_snippet_11 | |
97 | ws.accept(); | |
98 | //] | |
99 | ||
100 | //[ws_snippet_12 | |
101 | ws.accept_ex( | |
102 | [](response_type& m) | |
103 | { | |
104 | m.insert(http::field::server, "MyServer"); | |
105 | }); | |
106 | //] | |
107 | } | |
108 | ||
109 | { | |
110 | //[ws_snippet_13] | |
111 | // Buffer required for reading HTTP messages | |
112 | flat_buffer buffer; | |
113 | ||
114 | // Read the HTTP request ourselves | |
115 | http::request<http::string_body> req; | |
116 | http::read(sock, buffer, req); | |
117 | ||
118 | // See if its a WebSocket upgrade request | |
119 | if(websocket::is_upgrade(req)) | |
120 | { | |
121 | // Construct the stream, transferring ownership of the socket | |
92f5a8d4 | 122 | stream<net::ip::tcp::socket> ws{std::move(sock)}; |
b32b8144 FG |
123 | |
124 | // Accept the request from our message. Clients SHOULD NOT | |
125 | // begin sending WebSocket frames until the server has | |
126 | // provided a response, but just in case they did, we pass | |
127 | // any leftovers in the buffer to the accept function. | |
128 | // | |
129 | ws.accept(req, buffer.data()); | |
130 | } | |
131 | else | |
132 | { | |
133 | // Its not a WebSocket upgrade, so | |
134 | // handle it like a normal HTTP request. | |
135 | } | |
136 | //] | |
137 | } | |
138 | ||
139 | { | |
92f5a8d4 | 140 | stream<net::ip::tcp::socket> ws{ios}; |
b32b8144 FG |
141 | //[ws_snippet_14 |
142 | // Read into our buffer until we reach the end of the HTTP request. | |
143 | // No parsing takes place here, we are just accumulating data. | |
92f5a8d4 TL |
144 | net::streambuf buffer; |
145 | net::read_until(sock, buffer, "\r\n\r\n"); | |
b32b8144 FG |
146 | |
147 | // Now accept the connection, using the buffered data. | |
148 | ws.accept(buffer.data()); | |
149 | //] | |
150 | } | |
151 | { | |
92f5a8d4 | 152 | stream<net::ip::tcp::socket> ws{ios}; |
b32b8144 FG |
153 | //[ws_snippet_15 |
154 | multi_buffer buffer; | |
155 | ws.read(buffer); | |
156 | ||
157 | ws.text(ws.got_text()); | |
158 | ws.write(buffer.data()); | |
159 | buffer.consume(buffer.size()); | |
160 | //] | |
161 | } | |
162 | ||
163 | { | |
92f5a8d4 | 164 | stream<net::ip::tcp::socket> ws{ios}; |
b32b8144 FG |
165 | //[ws_snippet_16 |
166 | multi_buffer buffer; | |
167 | for(;;) | |
168 | if(ws.read_some(buffer, 0)) | |
169 | break; | |
170 | ws.binary(ws.got_binary()); | |
171 | consuming_buffers<multi_buffer::const_buffers_type> cb{buffer.data()}; | |
172 | for(;;) | |
173 | { | |
92f5a8d4 | 174 | using net::buffer_size; |
b32b8144 FG |
175 | if(buffer_size(cb) > 512) |
176 | { | |
177 | ws.write_some(false, buffer_prefix(512, cb)); | |
178 | cb.consume(512); | |
179 | } | |
180 | else | |
181 | { | |
182 | ws.write_some(true, cb); | |
183 | break; | |
184 | } | |
185 | } | |
186 | //] | |
187 | } | |
188 | ||
189 | { | |
92f5a8d4 | 190 | stream<net::ip::tcp::socket> ws{ios}; |
b32b8144 FG |
191 | //[ws_snippet_17 |
192 | auto cb = | |
193 | [](frame_type kind, string_view payload) | |
194 | { | |
195 | // Do something with the payload | |
196 | boost::ignore_unused(kind, payload); | |
197 | }; | |
198 | ws.control_callback(cb); | |
199 | //] | |
200 | ||
201 | //[ws_snippet_18 | |
202 | ws.close(close_code::normal); | |
203 | //] | |
204 | ||
205 | //[ws_snippet_19 | |
206 | ws.auto_fragment(true); | |
207 | ws.write_buffer_size(16384); | |
208 | //] | |
209 | ||
210 | //[ws_snippet_20 | |
211 | multi_buffer buffer; | |
212 | ws.async_read(buffer, | |
213 | [](error_code, std::size_t) | |
214 | { | |
215 | // Do something with the buffer | |
216 | }); | |
217 | //] | |
218 | } | |
219 | ||
220 | } // fxx() | |
221 | ||
222 | // workaround for https://github.com/chriskohlhoff/asio/issues/112 | |
223 | #ifdef BOOST_MSVC | |
224 | //[ws_snippet_21 | |
92f5a8d4 TL |
225 | void echo(stream<net::ip::tcp::socket>& ws, |
226 | multi_buffer& buffer, net::yield_context yield) | |
b32b8144 FG |
227 | { |
228 | ws.async_read(buffer, yield); | |
229 | std::future<void> fut = | |
92f5a8d4 | 230 | ws.async_write(buffer.data(), net::use_future); |
b32b8144 FG |
231 | } |
232 | //] | |
233 | #endif | |
234 | ||
235 | } // doc_ws_snippets | |
236 | ||
237 | //------------------------------------------------------------------------------ | |
238 | ||
239 | #if BOOST_BEAST_USE_OPENSSL | |
240 | ||
241 | //[wss_snippet_1 | |
242 | #include <boost/beast/websocket/ssl.hpp> | |
243 | #include <boost/asio/ssl.hpp> | |
244 | //] | |
245 | ||
246 | namespace doc_wss_snippets { | |
247 | ||
248 | void fxx() { | |
249 | ||
92f5a8d4 TL |
250 | net::io_service ios; |
251 | net::io_service::work work{ios}; | |
b32b8144 FG |
252 | std::thread t{[&](){ ios.run(); }}; |
253 | error_code ec; | |
92f5a8d4 | 254 | net::ip::tcp::socket sock{ios}; |
b32b8144 FG |
255 | |
256 | { | |
257 | //[wss_snippet_2 | |
92f5a8d4 TL |
258 | net::ssl::context ctx{net::ssl::context::tlsv12}; |
259 | stream<net::ssl::stream<net::ip::tcp::socket>> wss{ios, ctx}; | |
b32b8144 FG |
260 | //] |
261 | } | |
262 | ||
263 | { | |
264 | //[wss_snippet_3 | |
92f5a8d4 TL |
265 | net::ip::tcp::endpoint ep; |
266 | net::ssl::context ctx{net::ssl::context::tlsv12}; | |
267 | stream<net::ssl::stream<net::ip::tcp::socket>> ws{ios, ctx}; | |
b32b8144 FG |
268 | |
269 | // connect the underlying TCP/IP socket | |
270 | ws.next_layer().next_layer().connect(ep); | |
271 | ||
272 | // perform SSL handshake | |
92f5a8d4 | 273 | ws.next_layer().handshake(net::ssl::stream_base::client); |
b32b8144 FG |
274 | |
275 | // perform WebSocket handshake | |
276 | ws.handshake("localhost", "/"); | |
277 | //] | |
278 | } | |
279 | ||
280 | } // fxx() | |
281 | ||
282 | } // doc_wss_snippets | |
283 | ||
284 | #endif | |
285 |