]>
Commit | Line | Data |
---|---|---|
b32b8144 | 1 | // |
92f5a8d4 | 2 | // Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com) |
b32b8144 FG |
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 | // Test that header file is self-contained. | |
11 | #include <boost/beast/websocket/stream.hpp> | |
12 | ||
92f5a8d4 TL |
13 | #include <boost/beast/_experimental/test/stream.hpp> |
14 | #include <boost/beast/_experimental/test/tcp.hpp> | |
15 | #include <boost/beast/_experimental/unit_test/suite.hpp> | |
b32b8144 FG |
16 | #include "test.hpp" |
17 | ||
18 | namespace boost { | |
19 | namespace beast { | |
20 | namespace websocket { | |
21 | ||
92f5a8d4 | 22 | class accept_test : public unit_test::suite //: public websocket_test_suite |
b32b8144 FG |
23 | { |
24 | public: | |
92f5a8d4 | 25 | class res_decorator |
b32b8144 | 26 | { |
92f5a8d4 TL |
27 | bool& b_; |
28 | ||
29 | public: | |
30 | res_decorator(res_decorator const&) = default; | |
31 | ||
32 | explicit | |
33 | res_decorator(bool& b) | |
34 | : b_(b) | |
b32b8144 | 35 | { |
92f5a8d4 | 36 | } |
b32b8144 | 37 | |
92f5a8d4 TL |
38 | void |
39 | operator()(response_type&) const | |
40 | { | |
41 | this->b_ = true; | |
42 | } | |
43 | }; | |
44 | ||
45 | template<std::size_t N> | |
46 | static | |
47 | net::const_buffer | |
48 | sbuf(const char (&s)[N]) | |
49 | { | |
50 | return net::const_buffer(&s[0], N-1); | |
51 | } | |
b32b8144 | 52 | |
92f5a8d4 TL |
53 | static |
54 | void | |
55 | fail_loop( | |
56 | std::function<void(stream<test::stream>&)> f, | |
57 | std::chrono::steady_clock::duration amount = | |
58 | std::chrono::seconds(5)) | |
59 | { | |
60 | using clock_type = std::chrono::steady_clock; | |
61 | auto const expires_at = | |
62 | clock_type::now() + amount; | |
63 | net::io_context ioc; | |
64 | for(std::size_t n = 0;;++n) | |
65 | { | |
66 | test::fail_count fc(n); | |
67 | try | |
b32b8144 | 68 | { |
92f5a8d4 TL |
69 | stream<test::stream> ws(ioc, fc); |
70 | auto tr = connect(ws.next_layer()); | |
71 | f(ws); | |
72 | break; | |
b32b8144 | 73 | } |
92f5a8d4 | 74 | catch(system_error const& se) |
b32b8144 | 75 | { |
92f5a8d4 TL |
76 | // VFALCO Commented this out after the short |
77 | // read change, because it converts test_failure | |
78 | // into http::partial_message | |
79 | // | |
80 | boost::ignore_unused(se); | |
81 | #if 0 | |
82 | if(! BEAST_EXPECTS( | |
83 | se.code() == test::error::test_failure, | |
84 | se.code().message())) | |
85 | throw; | |
86 | #endif | |
87 | if(! BEAST_EXPECTS( | |
88 | clock_type::now() < expires_at, | |
89 | "a test timeout occurred")) | |
90 | break; | |
b32b8144 | 91 | } |
92f5a8d4 TL |
92 | } |
93 | } | |
b32b8144 | 94 | |
92f5a8d4 TL |
95 | template<class Api> |
96 | void | |
97 | testMatrix(Api api) | |
98 | { | |
99 | net::io_context ioc; | |
b32b8144 FG |
100 | |
101 | // request in stream | |
92f5a8d4 | 102 | fail_loop([&](stream<test::stream>& ws) |
b32b8144 | 103 | { |
92f5a8d4 | 104 | ws.next_layer().append( |
b32b8144 FG |
105 | "GET / HTTP/1.1\r\n" |
106 | "Host: localhost\r\n" | |
107 | "Upgrade: websocket\r\n" | |
108 | "Connection: upgrade\r\n" | |
109 | "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n" | |
110 | "Sec-WebSocket-Version: 13\r\n" | |
111 | "\r\n"); | |
92f5a8d4 TL |
112 | ws.next_layer().read_size(20); |
113 | api.accept(ws); | |
b32b8144 FG |
114 | }); |
115 | ||
92f5a8d4 TL |
116 | // request in stream, decorator |
117 | fail_loop([&](stream<test::stream>& ws) | |
b32b8144 | 118 | { |
92f5a8d4 | 119 | ws.next_layer().append( |
b32b8144 FG |
120 | "GET / HTTP/1.1\r\n" |
121 | "Host: localhost\r\n" | |
122 | "Upgrade: websocket\r\n" | |
123 | "Connection: upgrade\r\n" | |
124 | "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n" | |
125 | "Sec-WebSocket-Version: 13\r\n" | |
92f5a8d4 TL |
126 | "\r\n"); |
127 | ws.next_layer().read_size(20); | |
128 | bool called = false; | |
129 | ws.set_option(stream_base::decorator( | |
130 | res_decorator{called})); | |
131 | api.accept(ws); | |
132 | BEAST_EXPECT(called); | |
133 | }); | |
b32b8144 | 134 | |
92f5a8d4 TL |
135 | // request in buffers |
136 | fail_loop([&](stream<test::stream>& ws) | |
b32b8144 | 137 | { |
92f5a8d4 TL |
138 | api.accept(ws, sbuf( |
139 | "GET / HTTP/1.1\r\n" | |
140 | "Host: localhost\r\n" | |
141 | "Upgrade: websocket\r\n" | |
142 | "Connection: upgrade\r\n" | |
143 | "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n" | |
144 | "Sec-WebSocket-Version: 13\r\n" | |
145 | "\r\n" | |
146 | )); | |
147 | }); | |
148 | ||
149 | // request in buffers, decorator | |
150 | fail_loop([&](stream<test::stream>& ws) | |
151 | { | |
152 | bool called = false; | |
153 | ws.set_option(stream_base::decorator( | |
154 | res_decorator{called})); | |
155 | api.accept(ws, sbuf( | |
156 | "GET / HTTP/1.1\r\n" | |
157 | "Host: localhost\r\n" | |
158 | "Upgrade: websocket\r\n" | |
159 | "Connection: upgrade\r\n" | |
160 | "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n" | |
161 | "Sec-WebSocket-Version: 13\r\n" | |
162 | "\r\n")); | |
163 | BEAST_EXPECT(called); | |
164 | }); | |
165 | ||
166 | // request in buffers and stream | |
167 | fail_loop([&](stream<test::stream>& ws) | |
168 | { | |
169 | ws.next_layer().append( | |
170 | "Connection: upgrade\r\n" | |
171 | "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n" | |
172 | "Sec-WebSocket-Version: 13\r\n" | |
173 | "\r\n"); | |
174 | ws.next_layer().read_size(16); | |
175 | api.accept(ws, sbuf( | |
b32b8144 FG |
176 | "GET / HTTP/1.1\r\n" |
177 | "Host: localhost\r\n" | |
178 | "Upgrade: websocket\r\n" | |
92f5a8d4 TL |
179 | )); |
180 | // VFALCO validate contents of ws.next_layer().str? | |
181 | }); | |
182 | ||
183 | // request in buffers and stream, decorator | |
184 | fail_loop([&](stream<test::stream>& ws) | |
185 | { | |
186 | ws.next_layer().append( | |
b32b8144 FG |
187 | "Connection: upgrade\r\n" |
188 | "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n" | |
189 | "Sec-WebSocket-Version: 13\r\n" | |
190 | "\r\n"); | |
92f5a8d4 | 191 | ws.next_layer().read_size(16); |
b32b8144 | 192 | bool called = false; |
92f5a8d4 TL |
193 | ws.set_option(stream_base::decorator( |
194 | res_decorator{called})); | |
195 | api.accept(ws, sbuf( | |
196 | "GET / HTTP/1.1\r\n" | |
197 | "Host: localhost\r\n" | |
198 | "Upgrade: websocket\r\n")); | |
b32b8144 FG |
199 | BEAST_EXPECT(called); |
200 | }); | |
201 | ||
92f5a8d4 TL |
202 | // request in message |
203 | { | |
204 | request_type req; | |
205 | req.method(http::verb::get); | |
206 | req.target("/"); | |
207 | req.version(11); | |
208 | req.insert(http::field::host, "localhost"); | |
209 | req.insert(http::field::upgrade, "websocket"); | |
210 | req.insert(http::field::connection, "upgrade"); | |
211 | req.insert(http::field::sec_websocket_key, "dGhlIHNhbXBsZSBub25jZQ=="); | |
212 | req.insert(http::field::sec_websocket_version, "13"); | |
213 | ||
214 | fail_loop([&](stream<test::stream>& ws) | |
215 | { | |
216 | api.accept(ws, req); | |
217 | }); | |
218 | } | |
219 | ||
220 | // request in message, decorator | |
221 | { | |
222 | request_type req; | |
223 | req.method(http::verb::get); | |
224 | req.target("/"); | |
225 | req.version(11); | |
226 | req.insert(http::field::host, "localhost"); | |
227 | req.insert(http::field::upgrade, "websocket"); | |
228 | req.insert(http::field::connection, "upgrade"); | |
229 | req.insert(http::field::sec_websocket_key, "dGhlIHNhbXBsZSBub25jZQ=="); | |
230 | req.insert(http::field::sec_websocket_version, "13"); | |
231 | ||
232 | fail_loop([&](stream<test::stream>& ws) | |
233 | { | |
234 | bool called = false; | |
235 | ws.set_option(stream_base::decorator( | |
236 | res_decorator{called})); | |
237 | api.accept(ws, req); | |
238 | BEAST_EXPECT(called); | |
239 | }); | |
240 | } | |
241 | ||
242 | // request in message, close frame in stream | |
243 | { | |
244 | request_type req; | |
245 | req.method(http::verb::get); | |
246 | req.target("/"); | |
247 | req.version(11); | |
248 | req.insert(http::field::host, "localhost"); | |
249 | req.insert(http::field::upgrade, "websocket"); | |
250 | req.insert(http::field::connection, "upgrade"); | |
251 | req.insert(http::field::sec_websocket_key, "dGhlIHNhbXBsZSBub25jZQ=="); | |
252 | req.insert(http::field::sec_websocket_version, "13"); | |
253 | ||
254 | fail_loop([&](stream<test::stream>& ws) | |
255 | { | |
256 | ws.next_layer().append("\x88\x82\xff\xff\xff\xff\xfc\x17"); | |
257 | api.accept(ws, req); | |
258 | try | |
259 | { | |
260 | static_buffer<1> b; | |
261 | api.read(ws, b); | |
262 | fail("success", __FILE__, __LINE__); | |
263 | } | |
264 | catch(system_error const& e) | |
265 | { | |
266 | if(e.code() != websocket::error::closed) | |
267 | throw; | |
268 | } | |
269 | }); | |
270 | } | |
271 | ||
272 | // failed handshake (missing Sec-WebSocket-Key) | |
273 | fail_loop([&](stream<test::stream>& ws) | |
274 | { | |
275 | ws.next_layer().append( | |
276 | "GET / HTTP/1.1\r\n" | |
277 | "Host: localhost\r\n" | |
278 | "Upgrade: websocket\r\n" | |
279 | "Connection: upgrade\r\n" | |
280 | "Sec-WebSocket-Version: 13\r\n" | |
281 | "\r\n"); | |
282 | ws.next_layer().read_size(20); | |
283 | try | |
284 | { | |
285 | api.accept(ws); | |
286 | BEAST_FAIL(); | |
287 | } | |
288 | catch(system_error const& e) | |
289 | { | |
290 | if( e.code() != websocket::error::no_sec_key && | |
291 | e.code() != net::error::eof) | |
292 | throw; | |
293 | } | |
294 | }); | |
295 | } | |
296 | ||
297 | template<class Api> | |
298 | void | |
299 | testOversized(Api const& api) | |
300 | { | |
301 | net::io_context ioc; | |
302 | ||
303 | auto const big = [] | |
304 | { | |
305 | std::string s; | |
306 | s += "X1: " + std::string(2000, '*') + "\r\n"; | |
307 | return s; | |
308 | }(); | |
309 | ||
310 | // request in stream | |
b32b8144 | 311 | { |
92f5a8d4 | 312 | stream<test::stream> ws{ioc, |
b32b8144 FG |
313 | "GET / HTTP/1.1\r\n" |
314 | "Host: localhost\r\n" | |
315 | "Upgrade: websocket\r\n" | |
316 | "Connection: upgrade\r\n" | |
317 | "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n" | |
318 | "Sec-WebSocket-Version: 13\r\n" | |
319 | + big + | |
320 | "\r\n"}; | |
321 | auto tr = connect(ws.next_layer()); | |
322 | try | |
323 | { | |
92f5a8d4 TL |
324 | api.accept(ws); |
325 | BEAST_FAIL(); | |
b32b8144 FG |
326 | } |
327 | catch(system_error const& se) | |
328 | { | |
329 | // VFALCO Its the http error category... | |
330 | BEAST_EXPECTS( | |
331 | se.code() == http::error::buffer_overflow, | |
332 | se.code().message()); | |
333 | } | |
334 | } | |
335 | ||
92f5a8d4 | 336 | // request in stream, decorator |
b32b8144 | 337 | { |
92f5a8d4 | 338 | stream<test::stream> ws{ioc, |
b32b8144 FG |
339 | "GET / HTTP/1.1\r\n" |
340 | "Host: localhost\r\n" | |
341 | "Upgrade: websocket\r\n" | |
342 | "Connection: upgrade\r\n" | |
343 | "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n" | |
344 | "Sec-WebSocket-Version: 13\r\n" | |
92f5a8d4 TL |
345 | + big + |
346 | "\r\n"}; | |
347 | auto tr = connect(ws.next_layer()); | |
348 | try | |
349 | { | |
350 | bool called = false; | |
351 | ws.set_option(stream_base::decorator( | |
352 | res_decorator{called})); | |
353 | api.accept(ws); | |
354 | BEAST_FAIL(); | |
355 | } | |
356 | catch(system_error const& se) | |
357 | { | |
358 | // VFALCO Its the http error category... | |
359 | BEAST_EXPECTS( | |
360 | se.code() == http::error::buffer_overflow, | |
361 | se.code().message()); | |
362 | } | |
363 | } | |
b32b8144 | 364 | |
92f5a8d4 | 365 | // request in buffers |
b32b8144 | 366 | { |
92f5a8d4 | 367 | stream<test::stream> ws{ioc}; |
b32b8144 FG |
368 | auto tr = connect(ws.next_layer()); |
369 | try | |
370 | { | |
92f5a8d4 | 371 | api.accept(ws, net::buffer( |
b32b8144 FG |
372 | "GET / HTTP/1.1\r\n" |
373 | "Host: localhost\r\n" | |
374 | "Upgrade: websocket\r\n" | |
375 | "Connection: upgrade\r\n" | |
376 | "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n" | |
377 | "Sec-WebSocket-Version: 13\r\n" | |
378 | + big + | |
379 | "\r\n" | |
380 | )); | |
92f5a8d4 | 381 | BEAST_FAIL(); |
b32b8144 FG |
382 | } |
383 | catch(system_error const& se) | |
384 | { | |
385 | BEAST_EXPECTS( | |
386 | se.code() == error::buffer_overflow, | |
387 | se.code().message()); | |
388 | } | |
389 | } | |
390 | ||
391 | // request in buffers, decorator | |
b32b8144 | 392 | { |
92f5a8d4 | 393 | stream<test::stream> ws{ioc}; |
b32b8144 FG |
394 | auto tr = connect(ws.next_layer()); |
395 | try | |
396 | { | |
397 | bool called = false; | |
92f5a8d4 TL |
398 | ws.set_option(stream_base::decorator( |
399 | res_decorator{called})); | |
400 | api.accept(ws, net::buffer( | |
b32b8144 FG |
401 | "GET / HTTP/1.1\r\n" |
402 | "Host: localhost\r\n" | |
403 | "Upgrade: websocket\r\n" | |
404 | "Connection: upgrade\r\n" | |
405 | "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n" | |
406 | "Sec-WebSocket-Version: 13\r\n" | |
407 | + big + | |
92f5a8d4 TL |
408 | "\r\n")); |
409 | BEAST_FAIL(); | |
b32b8144 FG |
410 | } |
411 | catch(system_error const& se) | |
412 | { | |
413 | BEAST_EXPECTS( | |
414 | se.code() == error::buffer_overflow, | |
415 | se.code().message()); | |
416 | } | |
417 | } | |
418 | ||
419 | // request in buffers and stream | |
b32b8144 | 420 | { |
92f5a8d4 | 421 | stream<test::stream> ws{ioc, |
b32b8144 FG |
422 | "Connection: upgrade\r\n" |
423 | "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n" | |
424 | "Sec-WebSocket-Version: 13\r\n" | |
425 | + big + | |
426 | "\r\n"}; | |
427 | auto tr = connect(ws.next_layer()); | |
428 | try | |
429 | { | |
92f5a8d4 | 430 | api.accept(ws, websocket_test_suite::sbuf( |
b32b8144 FG |
431 | "GET / HTTP/1.1\r\n" |
432 | "Host: localhost\r\n" | |
433 | "Upgrade: websocket\r\n" | |
434 | )); | |
92f5a8d4 | 435 | BEAST_FAIL(); |
b32b8144 FG |
436 | } |
437 | catch(system_error const& se) | |
438 | { | |
439 | BEAST_EXPECTS( | |
440 | se.code() == http::error::buffer_overflow, | |
441 | se.code().message()); | |
442 | } | |
443 | } | |
444 | ||
445 | // request in buffers and stream, decorator | |
b32b8144 | 446 | { |
92f5a8d4 | 447 | stream<test::stream> ws{ioc, |
b32b8144 FG |
448 | "Connection: upgrade\r\n" |
449 | "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n" | |
450 | "Sec-WebSocket-Version: 13\r\n" | |
451 | + big + | |
452 | "\r\n"}; | |
453 | auto tr = connect(ws.next_layer()); | |
454 | try | |
455 | { | |
456 | bool called = false; | |
92f5a8d4 TL |
457 | ws.set_option(stream_base::decorator( |
458 | res_decorator{called})); | |
459 | api.accept(ws, websocket_test_suite::sbuf( | |
b32b8144 FG |
460 | "GET / HTTP/1.1\r\n" |
461 | "Host: localhost\r\n" | |
92f5a8d4 TL |
462 | "Upgrade: websocket\r\n")); |
463 | BEAST_FAIL(); | |
b32b8144 FG |
464 | } |
465 | catch(system_error const& se) | |
466 | { | |
467 | BEAST_EXPECTS( | |
468 | se.code() == http::error::buffer_overflow, | |
469 | se.code().message()); | |
470 | } | |
471 | } | |
b32b8144 FG |
472 | } |
473 | ||
474 | void | |
92f5a8d4 | 475 | testInvalidInputs() |
b32b8144 | 476 | { |
92f5a8d4 | 477 | net::io_context ioc; |
b32b8144 FG |
478 | |
479 | auto const check = | |
92f5a8d4 | 480 | [&](error_code ev, string_view s) |
b32b8144 FG |
481 | { |
482 | for(int i = 0; i < 3; ++i) | |
483 | { | |
484 | std::size_t n; | |
485 | switch(i) | |
486 | { | |
487 | default: | |
488 | case 0: | |
489 | n = 1; | |
490 | break; | |
491 | case 1: | |
492 | n = s.size() / 2; | |
493 | break; | |
494 | case 2: | |
495 | n = s.size() - 1; | |
496 | break; | |
497 | } | |
92f5a8d4 | 498 | stream<test::stream> ws(ioc); |
b32b8144 FG |
499 | auto tr = connect(ws.next_layer()); |
500 | ws.next_layer().append( | |
501 | s.substr(n, s.size() - n)); | |
92f5a8d4 | 502 | tr.close(); |
b32b8144 FG |
503 | try |
504 | { | |
92f5a8d4 | 505 | ws.accept(net::buffer(s.data(), n)); |
b32b8144 FG |
506 | BEAST_EXPECTS(! ev, ev.message()); |
507 | } | |
508 | catch(system_error const& se) | |
509 | { | |
510 | BEAST_EXPECTS(se.code() == ev, se.what()); | |
511 | } | |
512 | } | |
513 | }; | |
514 | ||
11fdf7f2 TL |
515 | // bad version |
516 | check(error::bad_http_version, | |
b32b8144 FG |
517 | "GET / HTTP/1.0\r\n" |
518 | "Host: localhost:80\r\n" | |
519 | "Upgrade: WebSocket\r\n" | |
520 | "Connection: keep-alive,upgrade\r\n" | |
521 | "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n" | |
522 | "Sec-WebSocket-Version: 13\r\n" | |
523 | "\r\n" | |
524 | ); | |
92f5a8d4 | 525 | |
11fdf7f2 TL |
526 | // bad method |
527 | check(error::bad_method, | |
b32b8144 FG |
528 | "POST / HTTP/1.1\r\n" |
529 | "Host: localhost:80\r\n" | |
530 | "Upgrade: WebSocket\r\n" | |
531 | "Connection: keep-alive,upgrade\r\n" | |
532 | "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n" | |
533 | "Sec-WebSocket-Version: 13\r\n" | |
534 | "\r\n" | |
535 | ); | |
92f5a8d4 | 536 | |
11fdf7f2 TL |
537 | // no Host |
538 | check(error::no_host, | |
b32b8144 FG |
539 | "GET / HTTP/1.1\r\n" |
540 | "Upgrade: WebSocket\r\n" | |
541 | "Connection: keep-alive,upgrade\r\n" | |
542 | "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n" | |
543 | "Sec-WebSocket-Version: 13\r\n" | |
544 | "\r\n" | |
545 | ); | |
92f5a8d4 | 546 | |
11fdf7f2 TL |
547 | // no Connection |
548 | check(error::no_connection, | |
b32b8144 FG |
549 | "GET / HTTP/1.1\r\n" |
550 | "Host: localhost:80\r\n" | |
551 | "Upgrade: WebSocket\r\n" | |
11fdf7f2 | 552 | "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n" |
b32b8144 FG |
553 | "Sec-WebSocket-Version: 13\r\n" |
554 | "\r\n" | |
555 | ); | |
92f5a8d4 | 556 | |
11fdf7f2 TL |
557 | // no Connection upgrade |
558 | check(error::no_connection_upgrade, | |
b32b8144 FG |
559 | "GET / HTTP/1.1\r\n" |
560 | "Host: localhost:80\r\n" | |
561 | "Upgrade: WebSocket\r\n" | |
11fdf7f2 | 562 | "Connection: keep-alive\r\n" |
b32b8144 | 563 | "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n" |
11fdf7f2 | 564 | "Sec-WebSocket-Version: 13\r\n" |
b32b8144 FG |
565 | "\r\n" |
566 | ); | |
92f5a8d4 | 567 | |
11fdf7f2 TL |
568 | // no Upgrade |
569 | check(error::no_upgrade, | |
b32b8144 FG |
570 | "GET / HTTP/1.1\r\n" |
571 | "Host: localhost:80\r\n" | |
11fdf7f2 | 572 | "Connection: upgrade\r\n" |
b32b8144 | 573 | "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n" |
11fdf7f2 | 574 | "Sec-WebSocket-Version: 13\r\n" |
b32b8144 FG |
575 | "\r\n" |
576 | ); | |
92f5a8d4 | 577 | |
11fdf7f2 TL |
578 | // no Upgrade websocket |
579 | check(error::no_upgrade_websocket, | |
b32b8144 FG |
580 | "GET / HTTP/1.1\r\n" |
581 | "Host: localhost:80\r\n" | |
582 | "Upgrade: HTTP/2\r\n" | |
583 | "Connection: upgrade\r\n" | |
584 | "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n" | |
585 | "Sec-WebSocket-Version: 13\r\n" | |
586 | "\r\n" | |
587 | ); | |
92f5a8d4 | 588 | |
11fdf7f2 TL |
589 | // no Sec-WebSocket-Key |
590 | check(error::no_sec_key, | |
b32b8144 FG |
591 | "GET / HTTP/1.1\r\n" |
592 | "Host: localhost:80\r\n" | |
593 | "Upgrade: WebSocket\r\n" | |
11fdf7f2 | 594 | "Connection: keep-alive,upgrade\r\n" |
b32b8144 FG |
595 | "Sec-WebSocket-Version: 13\r\n" |
596 | "\r\n" | |
597 | ); | |
92f5a8d4 | 598 | |
11fdf7f2 TL |
599 | // bad Sec-WebSocket-Key |
600 | check(error::bad_sec_key, | |
b32b8144 FG |
601 | "GET / HTTP/1.1\r\n" |
602 | "Host: localhost:80\r\n" | |
603 | "Upgrade: WebSocket\r\n" | |
604 | "Connection: upgrade\r\n" | |
605 | "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQdGhlIHNhbXBsZSBub25jZQ==\r\n" | |
606 | "Sec-WebSocket-Version: 13\r\n" | |
607 | "\r\n" | |
608 | ); | |
92f5a8d4 | 609 | |
11fdf7f2 TL |
610 | // no Sec-WebSocket-Version |
611 | check(error::no_sec_version, | |
b32b8144 FG |
612 | "GET / HTTP/1.1\r\n" |
613 | "Host: localhost:80\r\n" | |
614 | "Upgrade: WebSocket\r\n" | |
11fdf7f2 | 615 | "Connection: keep-alive,upgrade\r\n" |
b32b8144 | 616 | "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n" |
b32b8144 FG |
617 | "\r\n" |
618 | ); | |
92f5a8d4 | 619 | |
11fdf7f2 TL |
620 | // bad Sec-WebSocket-Version |
621 | check(error::bad_sec_version, | |
622 | "GET / HTTP/1.1\r\n" | |
623 | "Host: localhost:80\r\n" | |
624 | "Upgrade: WebSocket\r\n" | |
625 | "Connection: keep-alive,upgrade\r\n" | |
626 | "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n" | |
627 | "Sec-WebSocket-Version: 1\r\n" | |
628 | "\r\n" | |
629 | ); | |
92f5a8d4 | 630 | |
11fdf7f2 TL |
631 | // bad Sec-WebSocket-Version |
632 | check(error::bad_sec_version, | |
b32b8144 FG |
633 | "GET / HTTP/1.1\r\n" |
634 | "Host: localhost:80\r\n" | |
635 | "Upgrade: WebSocket\r\n" | |
636 | "Connection: upgrade\r\n" | |
637 | "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n" | |
11fdf7f2 | 638 | "Sec-WebSocket-Version: 12\r\n" |
b32b8144 FG |
639 | "\r\n" |
640 | ); | |
92f5a8d4 | 641 | |
b32b8144 FG |
642 | // valid request |
643 | check({}, | |
644 | "GET / HTTP/1.1\r\n" | |
645 | "Host: localhost:80\r\n" | |
646 | "Upgrade: WebSocket\r\n" | |
647 | "Connection: upgrade\r\n" | |
648 | "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n" | |
649 | "Sec-WebSocket-Version: 13\r\n" | |
650 | "\r\n" | |
651 | ); | |
652 | } | |
653 | ||
11fdf7f2 | 654 | void |
92f5a8d4 | 655 | testEndOfStream() |
11fdf7f2 | 656 | { |
92f5a8d4 TL |
657 | net::io_context ioc; |
658 | { | |
659 | stream<test::stream> ws(ioc); | |
660 | auto tr = connect(ws.next_layer()); | |
661 | tr.close(); | |
662 | try | |
663 | { | |
664 | test_sync_api api; | |
665 | api.accept(ws, net::const_buffer{}); | |
666 | BEAST_FAIL(); | |
667 | } | |
668 | catch(system_error const& se) | |
669 | { | |
670 | BEAST_EXPECTS( | |
671 | se.code() == error::closed, | |
672 | se.code().message()); | |
673 | } | |
674 | } | |
675 | { | |
676 | stream<test::stream> ws(ioc); | |
677 | auto tr = connect(ws.next_layer()); | |
678 | tr.close(); | |
679 | try | |
680 | { | |
681 | test_async_api api; | |
682 | api.accept(ws, net::const_buffer{}); | |
683 | BEAST_FAIL(); | |
684 | } | |
685 | catch(system_error const& se) | |
686 | { | |
687 | BEAST_EXPECTS( | |
688 | se.code() == error::closed, | |
689 | se.code().message()); | |
690 | } | |
691 | } | |
11fdf7f2 TL |
692 | } |
693 | ||
92f5a8d4 TL |
694 | void |
695 | testAsync() | |
11fdf7f2 | 696 | { |
92f5a8d4 TL |
697 | using tcp = net::ip::tcp; |
698 | ||
699 | net::io_context ioc; | |
700 | ||
701 | // success, no timeout | |
702 | ||
11fdf7f2 | 703 | { |
92f5a8d4 TL |
704 | stream<tcp::socket> ws1(ioc); |
705 | stream<tcp::socket> ws2(ioc); | |
706 | test::connect(ws1.next_layer(), ws2.next_layer()); | |
707 | ||
708 | ws1.async_handshake("test", "/", test::success_handler()); | |
709 | ws2.async_accept(test::success_handler()); | |
710 | test::run_for(ioc, std::chrono::seconds(1)); | |
11fdf7f2 | 711 | } |
11fdf7f2 | 712 | |
92f5a8d4 TL |
713 | { |
714 | stream<test::stream> ws1(ioc); | |
715 | stream<test::stream> ws2(ioc); | |
716 | test::connect(ws1.next_layer(), ws2.next_layer()); | |
717 | ||
718 | ws1.async_handshake("test", "/", test::success_handler()); | |
719 | ws2.async_accept(test::success_handler()); | |
720 | test::run_for(ioc, std::chrono::seconds(1)); | |
721 | } | |
722 | ||
723 | // success, timeout enabled | |
724 | ||
725 | { | |
726 | stream<tcp::socket> ws1(ioc); | |
727 | stream<tcp::socket> ws2(ioc); | |
728 | test::connect(ws1.next_layer(), ws2.next_layer()); | |
729 | ||
730 | ws1.set_option(stream_base::timeout{ | |
731 | std::chrono::milliseconds(50), | |
732 | stream_base::none(), | |
733 | false}); | |
734 | ws1.async_accept(test::success_handler()); | |
735 | ws2.async_handshake("test", "/", test::success_handler()); | |
736 | test::run_for(ioc, std::chrono::seconds(1)); | |
737 | } | |
738 | ||
739 | { | |
740 | stream<test::stream> ws1(ioc); | |
741 | stream<test::stream> ws2(ioc); | |
742 | test::connect(ws1.next_layer(), ws2.next_layer()); | |
743 | ||
744 | ws1.set_option(stream_base::timeout{ | |
745 | std::chrono::milliseconds(50), | |
746 | stream_base::none(), | |
747 | false}); | |
748 | ws1.async_accept(test::success_handler()); | |
749 | ws2.async_handshake("test", "/", test::success_handler()); | |
750 | test::run_for(ioc, std::chrono::seconds(1)); | |
751 | } | |
752 | ||
753 | // timeout | |
754 | ||
755 | { | |
756 | stream<tcp::socket> ws1(ioc); | |
757 | stream<tcp::socket> ws2(ioc); | |
758 | test::connect(ws1.next_layer(), ws2.next_layer()); | |
759 | ||
760 | ws1.set_option(stream_base::timeout{ | |
761 | std::chrono::milliseconds(50), | |
762 | stream_base::none(), | |
763 | false}); | |
764 | ws1.async_accept(test::fail_handler(beast::error::timeout)); | |
765 | test::run_for(ioc, std::chrono::seconds(1)); | |
766 | } | |
767 | ||
768 | { | |
769 | stream<test::stream> ws1(ioc); | |
770 | stream<test::stream> ws2(ioc); | |
771 | test::connect(ws1.next_layer(), ws2.next_layer()); | |
772 | ||
773 | ws1.set_option(stream_base::timeout{ | |
774 | std::chrono::milliseconds(50), | |
775 | stream_base::none(), | |
776 | false}); | |
777 | ws1.async_accept(test::fail_handler(beast::error::timeout)); | |
778 | test::run_for(ioc, std::chrono::seconds(1)); | |
779 | } | |
780 | ||
781 | // abandoned operation | |
782 | ||
783 | { | |
784 | { | |
785 | stream<tcp::socket> ws1(ioc); | |
786 | ws1.async_accept(test::fail_handler( | |
787 | net::error::operation_aborted)); | |
788 | } | |
789 | test::run(ioc); | |
790 | } | |
791 | ||
792 | { | |
793 | { | |
794 | stream<tcp::socket> ws1(ioc); | |
795 | string_view s = | |
796 | "GET / HTTP/1.1\r\n" | |
797 | "Host: localhost\r\n" | |
798 | "Upgrade: websocket\r\n" | |
799 | "Connection: upgrade\r\n" | |
800 | "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n" | |
801 | "Sec-WebSocket-Version: 13\r\n" | |
802 | "\r\n"; | |
803 | error_code ec; | |
804 | http::request_parser<http::empty_body> p; | |
805 | p.put(net::const_buffer(s.data(), s.size()), ec); | |
806 | ws1.async_accept(p.get(), test::fail_handler( | |
807 | net::error::operation_aborted)); | |
808 | } | |
809 | test::run(ioc); | |
810 | } | |
11fdf7f2 TL |
811 | } |
812 | ||
b32b8144 FG |
813 | void |
814 | run() override | |
815 | { | |
92f5a8d4 TL |
816 | testMatrix(test_sync_api{}); |
817 | testMatrix(test_async_api{}); | |
818 | testOversized(test_sync_api{}); | |
819 | testOversized(test_async_api{}); | |
820 | testInvalidInputs(); | |
821 | testEndOfStream(); | |
822 | testAsync(); | |
b32b8144 FG |
823 | } |
824 | }; | |
825 | ||
826 | BEAST_DEFINE_TESTSUITE(beast,websocket,accept); | |
827 | ||
828 | } // websocket | |
829 | } // beast | |
830 | } // boost |