test_asgi_websockets.py (1635:97afbb6c5a15) test_asgi_websockets.py (1654:fc7d0578e124)
1import struct
2import time
3from distutils.version import LooseVersion
4
5import pytest
6
7from conftest import option
8from conftest import skip_alert
9from unit.applications.lang.python import TestApplicationPython
10from unit.applications.websockets import TestApplicationWebsocket
11
12
13class TestASGIWebsockets(TestApplicationPython):
14 prerequisites = {'modules': {'python':
15 lambda v: LooseVersion(v) >= LooseVersion('3.5')}}
16 load_module = 'asgi'
17
18 ws = TestApplicationWebsocket()
19
20 def setup_method(self):
1import struct
2import time
3from distutils.version import LooseVersion
4
5import pytest
6
7from conftest import option
8from conftest import skip_alert
9from unit.applications.lang.python import TestApplicationPython
10from unit.applications.websockets import TestApplicationWebsocket
11
12
13class TestASGIWebsockets(TestApplicationPython):
14 prerequisites = {'modules': {'python':
15 lambda v: LooseVersion(v) >= LooseVersion('3.5')}}
16 load_module = 'asgi'
17
18 ws = TestApplicationWebsocket()
19
20 def setup_method(self):
21 super().setup_method()
22
23 assert 'success' in self.conf(
24 {'http': {'websocket': {'keepalive_interval': 0}}}, 'settings'
25 ), 'clear keepalive_interval'
26
27 skip_alert(r'socket close\(\d+\) failed')
28
29 def close_connection(self, sock):
30 assert self.recvall(sock, read_timeout=0.1) == b'', 'empty soc'
31
32 self.ws.frame_write(sock, self.ws.OP_CLOSE, self.ws.serialize_close())
33
34 self.check_close(sock)
35
36 def check_close(self, sock, code=1000, no_close=False):
37 frame = self.ws.frame_read(sock)
38
39 assert frame['fin'] == True, 'close fin'
40 assert frame['opcode'] == self.ws.OP_CLOSE, 'close opcode'
41 assert frame['code'] == code, 'close code'
42
43 if not no_close:
44 sock.close()
45
46 def check_frame(self, frame, fin, opcode, payload, decode=True):
47 if opcode == self.ws.OP_BINARY or not decode:
48 data = frame['data']
49 else:
50 data = frame['data'].decode('utf-8')
51
52 assert frame['fin'] == fin, 'fin'
53 assert frame['opcode'] == opcode, 'opcode'
54 assert data == payload, 'payload'
55
56 def test_asgi_websockets_handshake(self):
57 self.load('websockets/mirror')
58
59 resp, sock, key = self.ws.upgrade()
60 sock.close()
61
62 assert resp['status'] == 101, 'status'
63 assert resp['headers']['Upgrade'] == 'websocket', 'upgrade'
64 assert resp['headers']['Connection'] == 'Upgrade', 'connection'
65 assert resp['headers']['Sec-WebSocket-Accept'] == self.ws.accept(
66 key
67 ), 'key'
68
69 def test_asgi_websockets_subprotocol(self):
70 self.load('websockets/subprotocol')
71
72 resp, sock, key = self.ws.upgrade()
73 sock.close()
74
75 assert resp['status'] == 101, 'status'
76 assert resp['headers']['x-subprotocols'] == "('chat', 'phone', 'video')", 'subprotocols'
77 assert resp['headers']['sec-websocket-protocol'] == 'chat', 'key'
78
79 def test_asgi_websockets_mirror(self):
80 self.load('websockets/mirror')
81
82 message = 'blah'
83
84 _, sock, _ = self.ws.upgrade()
85
86 self.ws.frame_write(sock, self.ws.OP_TEXT, message)
87 frame = self.ws.frame_read(sock)
88
89 assert message == frame['data'].decode('utf-8'), 'mirror'
90
91 self.ws.frame_write(sock, self.ws.OP_TEXT, message)
92 frame = self.ws.frame_read(sock)
93
94 assert message == frame['data'].decode('utf-8'), 'mirror 2'
95
96 sock.close()
97
98 def test_asgi_websockets_no_mask(self):
99 self.load('websockets/mirror')
100
101 message = 'blah'
102
103 _, sock, _ = self.ws.upgrade()
104
105 self.ws.frame_write(sock, self.ws.OP_TEXT, message, mask=False)
106
107 frame = self.ws.frame_read(sock)
108
109 assert frame['opcode'] == self.ws.OP_CLOSE, 'no mask opcode'
110 assert frame['code'] == 1002, 'no mask close code'
111
112 sock.close()
113
114 def test_asgi_websockets_fragmentation(self):
115 self.load('websockets/mirror')
116
117 message = 'blah'
118
119 _, sock, _ = self.ws.upgrade()
120
121 self.ws.frame_write(sock, self.ws.OP_TEXT, message, fin=False)
122 self.ws.frame_write(sock, self.ws.OP_CONT, ' ', fin=False)
123 self.ws.frame_write(sock, self.ws.OP_CONT, message)
124
125 frame = self.ws.frame_read(sock)
126
127 assert message + ' ' + message == frame['data'].decode(
128 'utf-8'
129 ), 'mirror framing'
130
131 sock.close()
132
133 def test_asgi_websockets_length_long(self):
134 self.load('websockets/mirror')
135
136 _, sock, _ = self.ws.upgrade()
137
138 self.ws.frame_write(sock, self.ws.OP_TEXT, 'fragment1', fin=False)
139 self.ws.frame_write(
140 sock, self.ws.OP_CONT, 'fragment2', length=2**64 - 1
141 )
142
143 self.check_close(sock, 1009) # 1009 - CLOSE_TOO_LARGE
144
145 def test_asgi_websockets_frame_fragmentation_invalid(self):
146 self.load('websockets/mirror')
147
148 message = 'blah'
149
150 _, sock, _ = self.ws.upgrade()
151
152 self.ws.frame_write(sock, self.ws.OP_PING, message, fin=False)
153
154 frame = self.ws.frame_read(sock)
155
156 frame.pop('data')
157 assert frame == {
158 'fin': True,
159 'rsv1': False,
160 'rsv2': False,
161 'rsv3': False,
162 'opcode': self.ws.OP_CLOSE,
163 'mask': 0,
164 'code': 1002,
165 'reason': 'Fragmented control frame',
166 }, 'close frame'
167
168 sock.close()
169
170 def test_asgi_websockets_large(self):
171 self.load('websockets/mirror')
172
173 message = '0123456789' * 300
174
175 _, sock, _ = self.ws.upgrade()
176
177 self.ws.frame_write(sock, self.ws.OP_TEXT, message)
178
179 frame = self.ws.frame_read(sock)
180 data = frame['data'].decode('utf-8')
181
182 frame = self.ws.frame_read(sock)
183 data += frame['data'].decode('utf-8')
184
185 assert message == data, 'large'
186
187 sock.close()
188
189 def test_asgi_websockets_two_clients(self):
190 self.load('websockets/mirror')
191
192 message1 = 'blah1'
193 message2 = 'blah2'
194
195 _, sock1, _ = self.ws.upgrade()
196 _, sock2, _ = self.ws.upgrade()
197
198 self.ws.frame_write(sock1, self.ws.OP_TEXT, message1)
199 self.ws.frame_write(sock2, self.ws.OP_TEXT, message2)
200
201 frame1 = self.ws.frame_read(sock1)
202 frame2 = self.ws.frame_read(sock2)
203
204 assert message1 == frame1['data'].decode('utf-8'), 'client 1'
205 assert message2 == frame2['data'].decode('utf-8'), 'client 2'
206
207 sock1.close()
208 sock2.close()
209
210 @pytest.mark.skip('not yet')
211 def test_asgi_websockets_handshake_upgrade_absent(
212 self
213 ): # FAIL https://tools.ietf.org/html/rfc6455#section-4.2.1
214 self.load('websockets/mirror')
215
216 resp = self.get(
217 headers={
218 'Host': 'localhost',
219 'Connection': 'Upgrade',
220 'Sec-WebSocket-Key': self.ws.key(),
221 'Sec-WebSocket-Protocol': 'chat',
222 'Sec-WebSocket-Version': 13,
223 },
224 )
225
226 assert resp['status'] == 400, 'upgrade absent'
227
228 def test_asgi_websockets_handshake_case_insensitive(self):
229 self.load('websockets/mirror')
230
231 resp, sock, _ = self.ws.upgrade(
232 headers={
233 'Host': 'localhost',
234 'Upgrade': 'WEBSOCKET',
235 'Connection': 'UPGRADE',
236 'Sec-WebSocket-Key': self.ws.key(),
237 'Sec-WebSocket-Protocol': 'chat',
238 'Sec-WebSocket-Version': 13,
239 }
240 )
241 sock.close()
242
243 assert resp['status'] == 101, 'status'
244
245 @pytest.mark.skip('not yet')
246 def test_asgi_websockets_handshake_connection_absent(self): # FAIL
247 self.load('websockets/mirror')
248
249 resp = self.get(
250 headers={
251 'Host': 'localhost',
252 'Upgrade': 'websocket',
253 'Sec-WebSocket-Key': self.ws.key(),
254 'Sec-WebSocket-Protocol': 'chat',
255 'Sec-WebSocket-Version': 13,
256 },
257 )
258
259 assert resp['status'] == 400, 'status'
260
261 def test_asgi_websockets_handshake_version_absent(self):
262 self.load('websockets/mirror')
263
264 resp = self.get(
265 headers={
266 'Host': 'localhost',
267 'Upgrade': 'websocket',
268 'Connection': 'Upgrade',
269 'Sec-WebSocket-Key': self.ws.key(),
270 'Sec-WebSocket-Protocol': 'chat',
271 },
272 )
273
274 assert resp['status'] == 426, 'status'
275
276 @pytest.mark.skip('not yet')
277 def test_asgi_websockets_handshake_key_invalid(self):
278 self.load('websockets/mirror')
279
280 resp = self.get(
281 headers={
282 'Host': 'localhost',
283 'Upgrade': 'websocket',
284 'Connection': 'Upgrade',
285 'Sec-WebSocket-Key': '!',
286 'Sec-WebSocket-Protocol': 'chat',
287 'Sec-WebSocket-Version': 13,
288 },
289 )
290
291 assert resp['status'] == 400, 'key length'
292
293 key = self.ws.key()
294 resp = self.get(
295 headers={
296 'Host': 'localhost',
297 'Upgrade': 'websocket',
298 'Connection': 'Upgrade',
299 'Sec-WebSocket-Key': [key, key],
300 'Sec-WebSocket-Protocol': 'chat',
301 'Sec-WebSocket-Version': 13,
302 },
303 )
304
305 assert resp['status'] == 400, 'key double' # FAIL https://tools.ietf.org/html/rfc6455#section-11.3.1
306
307 def test_asgi_websockets_handshake_method_invalid(self):
308 self.load('websockets/mirror')
309
310 resp = self.post(
311 headers={
312 'Host': 'localhost',
313 'Upgrade': 'websocket',
314 'Connection': 'Upgrade',
315 'Sec-WebSocket-Key': self.ws.key(),
316 'Sec-WebSocket-Protocol': 'chat',
317 'Sec-WebSocket-Version': 13,
318 },
319 )
320
321 assert resp['status'] == 400, 'status'
322
323 def test_asgi_websockets_handshake_http_10(self):
324 self.load('websockets/mirror')
325
326 resp = self.get(
327 headers={
328 'Host': 'localhost',
329 'Upgrade': 'websocket',
330 'Connection': 'Upgrade',
331 'Sec-WebSocket-Key': self.ws.key(),
332 'Sec-WebSocket-Protocol': 'chat',
333 'Sec-WebSocket-Version': 13,
334 },
335 http_10=True,
336 )
337
338 assert resp['status'] == 400, 'status'
339
340 def test_asgi_websockets_handshake_uri_invalid(self):
341 self.load('websockets/mirror')
342
343 resp = self.get(
344 headers={
345 'Host': 'localhost',
346 'Upgrade': 'websocket',
347 'Connection': 'Upgrade',
348 'Sec-WebSocket-Key': self.ws.key(),
349 'Sec-WebSocket-Protocol': 'chat',
350 'Sec-WebSocket-Version': 13,
351 },
352 url='!',
353 )
354
355 assert resp['status'] == 400, 'status'
356
357 def test_asgi_websockets_protocol_absent(self):
358 self.load('websockets/mirror')
359
360 key = self.ws.key()
361 resp, sock, _ = self.ws.upgrade(
362 headers={
363 'Host': 'localhost',
364 'Upgrade': 'websocket',
365 'Connection': 'Upgrade',
366 'Sec-WebSocket-Key': key,
367 'Sec-WebSocket-Version': 13,
368 }
369 )
370 sock.close()
371
372 assert resp['status'] == 101, 'status'
373 assert resp['headers']['Upgrade'] == 'websocket', 'upgrade'
374 assert resp['headers']['Connection'] == 'Upgrade', 'connection'
375 assert resp['headers']['Sec-WebSocket-Accept'] == self.ws.accept(
376 key
377 ), 'key'
378
379 # autobahn-testsuite
380 #
381 # Some following tests fail because of Unit does not support UTF-8
382 # validation for websocket frames. It should be implemented
383 # by application, if necessary.
384
385 def test_asgi_websockets_1_1_1__1_1_8(self):
386 self.load('websockets/mirror')
387
388 opcode = self.ws.OP_TEXT
389
390 _, sock, _ = self.ws.upgrade()
391
392 def check_length(length, chopsize=None):
393 payload = '*' * length
394
395 self.ws.frame_write(sock, opcode, payload, chopsize=chopsize)
396
397 frame = self.ws.frame_read(sock)
398 self.check_frame(frame, True, opcode, payload)
399
400 check_length(0) # 1_1_1
401 check_length(125) # 1_1_2
402 check_length(126) # 1_1_3
403 check_length(127) # 1_1_4
404 check_length(128) # 1_1_5
405 check_length(65535) # 1_1_6
406 check_length(65536) # 1_1_7
407 check_length(65536, chopsize = 997) # 1_1_8
408
409 self.close_connection(sock)
410
411 def test_asgi_websockets_1_2_1__1_2_8(self):
412 self.load('websockets/mirror')
413
414 opcode = self.ws.OP_BINARY
415
416 _, sock, _ = self.ws.upgrade()
417
418 def check_length(length, chopsize=None):
419 payload = b'\xfe' * length
420
421 self.ws.frame_write(sock, opcode, payload, chopsize=chopsize)
422 frame = self.ws.frame_read(sock)
423
424 self.check_frame(frame, True, opcode, payload)
425
426 check_length(0) # 1_2_1
427 check_length(125) # 1_2_2
428 check_length(126) # 1_2_3
429 check_length(127) # 1_2_4
430 check_length(128) # 1_2_5
431 check_length(65535) # 1_2_6
432 check_length(65536) # 1_2_7
433 check_length(65536, chopsize = 997) # 1_2_8
434
435 self.close_connection(sock)
436
437 def test_asgi_websockets_2_1__2_6(self):
438 self.load('websockets/mirror')
439
440 op_ping = self.ws.OP_PING
441 op_pong = self.ws.OP_PONG
442
443 _, sock, _ = self.ws.upgrade()
444
445 def check_ping(payload, chopsize=None, decode=True):
446 self.ws.frame_write(sock, op_ping, payload, chopsize=chopsize)
447 frame = self.ws.frame_read(sock)
448
449 self.check_frame(frame, True, op_pong, payload, decode=decode)
450
451 check_ping('') # 2_1
452 check_ping('Hello, world!') # 2_2
453 check_ping(b'\x00\xff\xfe\xfd\xfc\xfb\x00\xff', decode=False) # 2_3
454 check_ping(b'\xfe' * 125, decode=False) # 2_4
455 check_ping(b'\xfe' * 125, chopsize=1, decode=False) # 2_6
456
457 self.close_connection(sock)
458
459 # 2_5
460
461 _, sock, _ = self.ws.upgrade()
462
463 self.ws.frame_write(sock, self.ws.OP_PING, b'\xfe' * 126)
464 self.check_close(sock, 1002)
465
466 def test_asgi_websockets_2_7__2_9(self):
467 self.load('websockets/mirror')
468
469 # 2_7
470
471 _, sock, _ = self.ws.upgrade()
472
473 self.ws.frame_write(sock, self.ws.OP_PONG, '')
474 assert self.recvall(sock, read_timeout=0.1) == b'', '2_7'
475
476 # 2_8
477
478 self.ws.frame_write(sock, self.ws.OP_PONG, 'unsolicited pong payload')
479 assert self.recvall(sock, read_timeout=0.1) == b'', '2_8'
480
481 # 2_9
482
483 payload = 'ping payload'
484
485 self.ws.frame_write(sock, self.ws.OP_PONG, 'unsolicited pong payload')
486 self.ws.frame_write(sock, self.ws.OP_PING, payload)
487
488 frame = self.ws.frame_read(sock)
489 self.check_frame(frame, True, self.ws.OP_PONG, payload)
490
491 self.close_connection(sock)
492
493 def test_asgi_websockets_2_10__2_11(self):
494 self.load('websockets/mirror')
495
496 # 2_10
497
498 _, sock, _ = self.ws.upgrade()
499
500 for i in range(0, 10):
501 self.ws.frame_write(sock, self.ws.OP_PING, 'payload-%d' % i)
502
503 for i in range(0, 10):
504 frame = self.ws.frame_read(sock)
505 self.check_frame(frame, True, self.ws.OP_PONG, 'payload-%d' % i)
506
507 # 2_11
508
509 for i in range(0, 10):
510 opcode = self.ws.OP_PING
511 self.ws.frame_write(sock, opcode, 'payload-%d' % i, chopsize=1)
512
513 for i in range(0, 10):
514 frame = self.ws.frame_read(sock)
515 self.check_frame(frame, True, self.ws.OP_PONG, 'payload-%d' % i)
516
517 self.close_connection(sock)
518
519 @pytest.mark.skip('not yet')
520 def test_asgi_websockets_3_1__3_7(self):
521 self.load('websockets/mirror')
522
523 payload = 'Hello, world!'
524
525 # 3_1
526
527 _, sock, _ = self.ws.upgrade()
528
529 self.ws.frame_write(sock, self.ws.OP_TEXT, payload, rsv1=True)
530 self.check_close(sock, 1002)
531
532 # 3_2
533
534 _, sock, _ = self.ws.upgrade()
535
536 self.ws.frame_write(sock, self.ws.OP_TEXT, payload)
537 self.ws.frame_write(sock, self.ws.OP_TEXT, payload, rsv2=True)
538 self.ws.frame_write(sock, self.ws.OP_PING, '')
539
540 frame = self.ws.frame_read(sock)
541 self.check_frame(frame, True, self.ws.OP_TEXT, payload)
542
543 self.check_close(sock, 1002, no_close=True)
544
545 assert self.recvall(sock, read_timeout=0.1) == b'', 'empty 3_2'
546 sock.close()
547
548 # 3_3
549
550 _, sock, _ = self.ws.upgrade()
551
552 self.ws.frame_write(sock, self.ws.OP_TEXT, payload)
553
554 frame = self.ws.frame_read(sock)
555 self.check_frame(frame, True, self.ws.OP_TEXT, payload)
556
557 self.ws.frame_write(
558 sock, self.ws.OP_TEXT, payload, rsv1=True, rsv2=True
559 )
560
561 self.check_close(sock, 1002, no_close=True)
562
563 assert self.recvall(sock, read_timeout=0.1) == b'', 'empty 3_3'
564 sock.close()
565
566 # 3_4
567
568 _, sock, _ = self.ws.upgrade()
569
570 self.ws.frame_write(sock, self.ws.OP_TEXT, payload, chopsize=1)
571 self.ws.frame_write(
572 sock, self.ws.OP_TEXT, payload, rsv3=True, chopsize=1
573 )
574 self.ws.frame_write(sock, self.ws.OP_PING, '')
575
576 frame = self.ws.frame_read(sock)
577 self.check_frame(frame, True, self.ws.OP_TEXT, payload)
578
579 self.check_close(sock, 1002, no_close=True)
580
581 assert self.recvall(sock, read_timeout=0.1) == b'', 'empty 3_4'
582 sock.close()
583
584 # 3_5
585
586 _, sock, _ = self.ws.upgrade()
587
588 self.ws.frame_write(
589 sock,
590 self.ws.OP_BINARY,
591 b'\x00\xff\xfe\xfd\xfc\xfb\x00\xff',
592 rsv1=True,
593 rsv3=True,
594 )
595
596 self.check_close(sock, 1002)
597
598 # 3_6
599
600 _, sock, _ = self.ws.upgrade()
601
602 self.ws.frame_write(
603 sock, self.ws.OP_PING, payload, rsv2=True, rsv3=True
604 )
605
606 self.check_close(sock, 1002)
607
608 # 3_7
609
610 _, sock, _ = self.ws.upgrade()
611
612 self.ws.frame_write(
613 sock, self.ws.OP_CLOSE, payload, rsv1=True, rsv2=True, rsv3=True
614 )
615
616 self.check_close(sock, 1002)
617
618 def test_asgi_websockets_4_1_1__4_2_5(self):
619 self.load('websockets/mirror')
620
621 payload = 'Hello, world!'
622
623 # 4_1_1
624
625 _, sock, _ = self.ws.upgrade()
626
627 self.ws.frame_write(sock, 0x03, '')
628 self.check_close(sock, 1002)
629
630 # 4_1_2
631
632 _, sock, _ = self.ws.upgrade()
633
634 self.ws.frame_write(sock, 0x04, 'reserved opcode payload')
635 self.check_close(sock, 1002)
636
637 # 4_1_3
638
639 _, sock, _ = self.ws.upgrade()
640
641 self.ws.frame_write(sock, self.ws.OP_TEXT, payload)
642
643 frame = self.ws.frame_read(sock)
644 self.check_frame(frame, True, self.ws.OP_TEXT, payload)
645
646 self.ws.frame_write(sock, 0x05, '')
647 self.ws.frame_write(sock, self.ws.OP_PING, '')
648
649 self.check_close(sock, 1002)
650
651 # 4_1_4
652
653 _, sock, _ = self.ws.upgrade()
654
655 self.ws.frame_write(sock, self.ws.OP_TEXT, payload)
656
657 frame = self.ws.frame_read(sock)
658 self.check_frame(frame, True, self.ws.OP_TEXT, payload)
659
660 self.ws.frame_write(sock, 0x06, payload)
661 self.ws.frame_write(sock, self.ws.OP_PING, '')
662
663 self.check_close(sock, 1002)
664
665 # 4_1_5
666
667 _, sock, _ = self.ws.upgrade()
668
669 self.ws.frame_write(sock, self.ws.OP_TEXT, payload, chopsize=1)
670
671 frame = self.ws.frame_read(sock)
672 self.check_frame(frame, True, self.ws.OP_TEXT, payload)
673
674 self.ws.frame_write(sock, 0x07, payload, chopsize=1)
675 self.ws.frame_write(sock, self.ws.OP_PING, '')
676
677 self.check_close(sock, 1002)
678
679 # 4_2_1
680
681 _, sock, _ = self.ws.upgrade()
682
683 self.ws.frame_write(sock, 0x0B, '')
684 self.check_close(sock, 1002)
685
686 # 4_2_2
687
688 _, sock, _ = self.ws.upgrade()
689
690 self.ws.frame_write(sock, 0x0C, 'reserved opcode payload')
691 self.check_close(sock, 1002)
692
693 # 4_2_3
694
695 _, sock, _ = self.ws.upgrade()
696
697 self.ws.frame_write(sock, self.ws.OP_TEXT, payload)
698
699 frame = self.ws.frame_read(sock)
700 self.check_frame(frame, True, self.ws.OP_TEXT, payload)
701
702 self.ws.frame_write(sock, 0x0D, '')
703 self.ws.frame_write(sock, self.ws.OP_PING, '')
704
705 self.check_close(sock, 1002)
706
707 # 4_2_4
708
709 _, sock, _ = self.ws.upgrade()
710
711 self.ws.frame_write(sock, self.ws.OP_TEXT, payload)
712
713 frame = self.ws.frame_read(sock)
714 self.check_frame(frame, True, self.ws.OP_TEXT, payload)
715
716 self.ws.frame_write(sock, 0x0E, payload)
717 self.ws.frame_write(sock, self.ws.OP_PING, '')
718
719 self.check_close(sock, 1002)
720
721 # 4_2_5
722
723 _, sock, _ = self.ws.upgrade()
724
725 self.ws.frame_write(sock, self.ws.OP_TEXT, payload, chopsize=1)
726
727 frame = self.ws.frame_read(sock)
728 self.check_frame(frame, True, self.ws.OP_TEXT, payload)
729
730 self.ws.frame_write(sock, 0x0F, payload, chopsize=1)
731 self.ws.frame_write(sock, self.ws.OP_PING, '')
732
733 self.check_close(sock, 1002)
734
735 def test_asgi_websockets_5_1__5_20(self):
736 self.load('websockets/mirror')
737
738 # 5_1
739
740 _, sock, _ = self.ws.upgrade()
741
742 self.ws.frame_write(sock, self.ws.OP_PING, 'fragment1', fin=False)
743 self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment2', fin=True)
744 self.check_close(sock, 1002)
745
746 # 5_2
747
748 _, sock, _ = self.ws.upgrade()
749
750 self.ws.frame_write(sock, self.ws.OP_PONG, 'fragment1', fin=False)
751 self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment2', fin=True)
752 self.check_close(sock, 1002)
753
754 # 5_3
755
756 _, sock, _ = self.ws.upgrade()
757
758 self.ws.frame_write(sock, self.ws.OP_TEXT, 'fragment1', fin=False)
759 self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment2', fin=True)
760
761 frame = self.ws.frame_read(sock)
762 self.check_frame(frame, True, self.ws.OP_TEXT, 'fragment1fragment2')
763
764 # 5_4
765
766 self.ws.frame_write(sock, self.ws.OP_TEXT, 'fragment1', fin=False)
767 assert self.recvall(sock, read_timeout=0.1) == b'', '5_4'
768 self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment2', fin=True)
769
770 frame = self.ws.frame_read(sock)
771 self.check_frame(frame, True, self.ws.OP_TEXT, 'fragment1fragment2')
772
773 # 5_5
774
775 self.ws.frame_write(
776 sock, self.ws.OP_TEXT, 'fragment1', fin=False, chopsize=1
777 )
778 self.ws.frame_write(
779 sock, self.ws.OP_CONT, 'fragment2', fin=True, chopsize=1
780 )
781
782 frame = self.ws.frame_read(sock)
783 self.check_frame(frame, True, self.ws.OP_TEXT, 'fragment1fragment2')
784
785 # 5_6
786
787 ping_payload = 'ping payload'
788
789 self.ws.frame_write(sock, self.ws.OP_TEXT, 'fragment1', fin=False)
790 self.ws.frame_write(sock, self.ws.OP_PING, ping_payload)
791 self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment2', fin=True)
792
793 frame = self.ws.frame_read(sock)
794 self.check_frame(frame, True, self.ws.OP_PONG, ping_payload)
795
796 frame = self.ws.frame_read(sock)
797 self.check_frame(frame, True, self.ws.OP_TEXT, 'fragment1fragment2')
798
799 # 5_7
800
801 ping_payload = 'ping payload'
802
803 self.ws.frame_write(sock, self.ws.OP_TEXT, 'fragment1', fin=False)
804 assert self.recvall(sock, read_timeout=0.1) == b'', '5_7'
805
806 self.ws.frame_write(sock, self.ws.OP_PING, ping_payload)
807
808 frame = self.ws.frame_read(sock)
809 self.check_frame(frame, True, self.ws.OP_PONG, ping_payload)
810
811 self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment2', fin=True)
812
813 frame = self.ws.frame_read(sock)
814 self.check_frame(frame, True, self.ws.OP_TEXT, 'fragment1fragment2')
815
816 # 5_8
817
818 ping_payload = 'ping payload'
819
820 self.ws.frame_write(
821 sock, self.ws.OP_TEXT, 'fragment1', fin=False, chopsize=1
822 )
823 self.ws.frame_write(sock, self.ws.OP_PING, ping_payload, chopsize=1)
824 self.ws.frame_write(
825 sock, self.ws.OP_CONT, 'fragment2', fin=True, chopsize=1
826 )
827
828 frame = self.ws.frame_read(sock)
829 self.check_frame(frame, True, self.ws.OP_PONG, ping_payload)
830
831 frame = self.ws.frame_read(sock)
832 self.check_frame(frame, True, self.ws.OP_TEXT, 'fragment1fragment2')
833
834 # 5_9
835
836 self.ws.frame_write(
837 sock, self.ws.OP_CONT, 'non-continuation payload', fin=True
838 )
839 self.ws.frame_write(sock, self.ws.OP_TEXT, 'Hello, world!', fin=True)
840 self.check_close(sock, 1002)
841
842 # 5_10
843
844 _, sock, _ = self.ws.upgrade()
845
846 self.ws.frame_write(
847 sock, self.ws.OP_CONT, 'non-continuation payload', fin=True
848 )
849 self.ws.frame_write(sock, self.ws.OP_TEXT, 'Hello, world!', fin=True)
850 self.check_close(sock, 1002)
851
852 # 5_11
853
854 _, sock, _ = self.ws.upgrade()
855
856 self.ws.frame_write(
857 sock,
858 self.ws.OP_CONT,
859 'non-continuation payload',
860 fin=True,
861 chopsize=1,
862 )
863 self.ws.frame_write(
864 sock, self.ws.OP_TEXT, 'Hello, world!', fin=True, chopsize=1
865 )
866 self.check_close(sock, 1002)
867
868 # 5_12
869
870 _, sock, _ = self.ws.upgrade()
871
872 self.ws.frame_write(
873 sock, self.ws.OP_CONT, 'non-continuation payload', fin=False
874 )
875 self.ws.frame_write(sock, self.ws.OP_TEXT, 'Hello, world!', fin=True)
876 self.check_close(sock, 1002)
877
878 # 5_13
879
880 _, sock, _ = self.ws.upgrade()
881
882 self.ws.frame_write(
883 sock, self.ws.OP_CONT, 'non-continuation payload', fin=False
884 )
885 self.ws.frame_write(sock, self.ws.OP_TEXT, 'Hello, world!', fin=True)
886 self.check_close(sock, 1002)
887
888 # 5_14
889
890 _, sock, _ = self.ws.upgrade()
891
892 self.ws.frame_write(
893 sock,
894 self.ws.OP_CONT,
895 'non-continuation payload',
896 fin=False,
897 chopsize=1,
898 )
899 self.ws.frame_write(
900 sock, self.ws.OP_TEXT, 'Hello, world!', fin=True, chopsize=1
901 )
902 self.check_close(sock, 1002)
903
904 # 5_15
905
906 _, sock, _ = self.ws.upgrade()
907
908 self.ws.frame_write(sock, self.ws.OP_TEXT, 'fragment1', fin=False)
909 self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment2', fin=True)
910 self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment3', fin=False)
911 self.ws.frame_write(sock, self.ws.OP_TEXT, 'fragment4', fin=True)
912 self.check_close(sock, 1002)
913
914 # 5_16
915
916 _, sock, _ = self.ws.upgrade()
917
918 for i in range(0, 2):
919 self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment1', fin=False)
920 self.ws.frame_write(sock, self.ws.OP_TEXT, 'fragment2', fin=False)
921 self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment3', fin=True)
922 self.check_close(sock, 1002)
923
924 # 5_17
925
926 _, sock, _ = self.ws.upgrade()
927
928 for i in range(0, 2):
929 self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment1', fin=True)
930 self.ws.frame_write(sock, self.ws.OP_TEXT, 'fragment2', fin=False)
931 self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment3', fin=True)
932 self.check_close(sock, 1002)
933
934 # 5_18
935
936 _, sock, _ = self.ws.upgrade()
937
938 self.ws.frame_write(sock, self.ws.OP_TEXT, 'fragment1', fin=False)
939 self.ws.frame_write(sock, self.ws.OP_TEXT, 'fragment2')
940 self.check_close(sock, 1002)
941
942 # 5_19
943
944 _, sock, _ = self.ws.upgrade()
945
946 self.ws.frame_write(sock, self.ws.OP_TEXT, 'fragment1', fin=False)
947 self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment2', fin=False)
948 self.ws.frame_write(sock, self.ws.OP_PING, 'pongme 1!')
949
950 time.sleep(1)
951
952 self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment3', fin=False)
953 self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment4', fin=False)
954 self.ws.frame_write(sock, self.ws.OP_PING, 'pongme 2!')
955 self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment5')
956
957 frame = self.ws.frame_read(sock)
958 self.check_frame(frame, True, self.ws.OP_PONG, 'pongme 1!')
959
960 frame = self.ws.frame_read(sock)
961 self.check_frame(frame, True, self.ws.OP_PONG, 'pongme 2!')
962
963 self.check_frame(
964 self.ws.frame_read(sock),
965 True,
966 self.ws.OP_TEXT,
967 'fragment1fragment2fragment3fragment4fragment5',
968 )
969
970 # 5_20
971
972 self.ws.frame_write(sock, self.ws.OP_TEXT, 'fragment1', fin=False)
973 self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment2', fin=False)
974 self.ws.frame_write(sock, self.ws.OP_PING, 'pongme 1!')
975
976 frame = self.ws.frame_read(sock)
977 self.check_frame(frame, True, self.ws.OP_PONG, 'pongme 1!')
978
979 time.sleep(1)
980
981 self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment3', fin=False)
982 self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment4', fin=False)
983 self.ws.frame_write(sock, self.ws.OP_PING, 'pongme 2!')
984
985 frame = self.ws.frame_read(sock)
986 self.check_frame(frame, True, self.ws.OP_PONG, 'pongme 2!')
987
988 assert self.recvall(sock, read_timeout=0.1) == b'', '5_20'
989 self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment5')
990
991 self.check_frame(
992 self.ws.frame_read(sock),
993 True,
994 self.ws.OP_TEXT,
995 'fragment1fragment2fragment3fragment4fragment5',
996 )
997
998 self.close_connection(sock)
999
1000 def test_asgi_websockets_6_1_1__6_4_4(self):
1001 self.load('websockets/mirror')
1002
1003 # 6_1_1
1004
1005 _, sock, _ = self.ws.upgrade()
1006
1007 self.ws.frame_write(sock, self.ws.OP_TEXT, '')
1008 frame = self.ws.frame_read(sock)
1009 self.check_frame(frame, True, self.ws.OP_TEXT, '')
1010
1011 # 6_1_2
1012
1013 self.ws.frame_write(sock, self.ws.OP_TEXT, '', fin=False)
1014 self.ws.frame_write(sock, self.ws.OP_CONT, '', fin=False)
1015 self.ws.frame_write(sock, self.ws.OP_CONT, '')
1016
1017 frame = self.ws.frame_read(sock)
1018 self.check_frame(frame, True, self.ws.OP_TEXT, '')
1019
1020 # 6_1_3
1021
1022 payload = 'middle frame payload'
1023
1024 self.ws.frame_write(sock, self.ws.OP_TEXT, '', fin=False)
1025 self.ws.frame_write(sock, self.ws.OP_CONT, payload, fin=False)
1026 self.ws.frame_write(sock, self.ws.OP_CONT, '')
1027
1028 frame = self.ws.frame_read(sock)
1029 self.check_frame(frame, True, self.ws.OP_TEXT, payload)
1030
1031 # 6_2_1
1032
1033 payload = 'Hello-µ@ßöäüàá-UTF-8!!'
1034
1035 self.ws.frame_write(sock, self.ws.OP_TEXT, payload)
1036
1037 frame = self.ws.frame_read(sock)
1038 self.check_frame(frame, True, self.ws.OP_TEXT, payload)
1039
1040 # 6_2_2
1041
1042 self.ws.frame_write(sock, self.ws.OP_TEXT, payload[:12], fin=False)
1043 self.ws.frame_write(sock, self.ws.OP_CONT, payload[12:])
1044
1045 frame = self.ws.frame_read(sock)
1046 self.check_frame(frame, True, self.ws.OP_TEXT, payload)
1047
1048 # 6_2_3
1049
1050 self.ws.message(sock, self.ws.OP_TEXT, payload, fragmention_size=1)
1051
1052 frame = self.ws.frame_read(sock)
1053 self.check_frame(frame, True, self.ws.OP_TEXT, payload)
1054
1055 # 6_2_4
1056
1057 payload = '\xce\xba\xe1\xbd\xb9\xcf\x83\xce\xbc\xce\xb5'
1058
1059 self.ws.message(sock, self.ws.OP_TEXT, payload, fragmention_size=1)
1060
1061 frame = self.ws.frame_read(sock)
1062 self.check_frame(frame, True, self.ws.OP_TEXT, payload)
1063
1064 self.close_connection(sock)
1065
1066# Unit does not support UTF-8 validation
1067#
1068# # 6_3_1 FAIL
1069#
1070# payload_1 = '\xce\xba\xe1\xbd\xb9\xcf\x83\xce\xbc\xce\xb5'
1071# payload_2 = '\xed\xa0\x80'
1072# payload_3 = '\x65\x64\x69\x74\x65\x64'
1073#
1074# payload = payload_1 + payload_2 + payload_3
1075#
1076# self.ws.message(sock, self.ws.OP_TEXT, payload)
1077# self.check_close(sock, 1007)
1078#
1079# # 6_3_2 FAIL
1080#
1081# _, sock, _ = self.ws.upgrade()
1082#
1083# self.ws.message(sock, self.ws.OP_TEXT, payload, fragmention_size=1)
1084# self.check_close(sock, 1007)
1085#
1086# # 6_4_1 ... 6_4_4 FAIL
1087
1088 def test_asgi_websockets_7_1_1__7_5_1(self):
1089 self.load('websockets/mirror')
1090
1091 # 7_1_1
1092
1093 _, sock, _ = self.ws.upgrade()
1094
1095 payload = "Hello World!"
1096
1097 self.ws.frame_write(sock, self.ws.OP_TEXT, payload)
1098
1099 frame = self.ws.frame_read(sock)
1100 self.check_frame(frame, True, self.ws.OP_TEXT, payload)
1101
1102 self.close_connection(sock)
1103
1104 # 7_1_2
1105
1106 _, sock, _ = self.ws.upgrade()
1107
1108 self.ws.frame_write(sock, self.ws.OP_CLOSE, self.ws.serialize_close())
1109 self.ws.frame_write(sock, self.ws.OP_CLOSE, self.ws.serialize_close())
1110
1111 self.check_close(sock)
1112
1113 # 7_1_3
1114
1115 _, sock, _ = self.ws.upgrade()
1116
1117 self.ws.frame_write(sock, self.ws.OP_CLOSE, self.ws.serialize_close())
1118 self.check_close(sock, no_close=True)
1119
1120 self.ws.frame_write(sock, self.ws.OP_PING, '')
1121 assert self.recvall(sock, read_timeout=0.1) == b'', 'empty soc'
1122
1123 sock.close()
1124
1125 # 7_1_4
1126
1127 _, sock, _ = self.ws.upgrade()
1128
1129 self.ws.frame_write(sock, self.ws.OP_CLOSE, self.ws.serialize_close())
1130 self.check_close(sock, no_close=True)
1131
1132 self.ws.frame_write(sock, self.ws.OP_TEXT, payload)
1133 assert self.recvall(sock, read_timeout=0.1) == b'', 'empty soc'
1134
1135 sock.close()
1136
1137 # 7_1_5
1138
1139 _, sock, _ = self.ws.upgrade()
1140
1141 self.ws.frame_write(sock, self.ws.OP_TEXT, 'fragment1', fin=False)
1142 self.ws.frame_write(sock, self.ws.OP_CLOSE, self.ws.serialize_close())
1143 self.check_close(sock, no_close=True)
1144
1145 self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment2')
1146 assert self.recvall(sock, read_timeout=0.1) == b'', 'empty soc'
1147
1148 sock.close()
1149
1150 # 7_1_6
1151
1152 _, sock, _ = self.ws.upgrade()
1153
1154 self.ws.frame_write(sock, self.ws.OP_TEXT, 'BAsd7&jh23' * 26 * 2 ** 10)
1155 self.ws.frame_write(sock, self.ws.OP_TEXT, payload)
1156 self.ws.frame_write(sock, self.ws.OP_CLOSE, self.ws.serialize_close())
1157
1158 self.recvall(sock, read_timeout=1)
1159
1160 self.ws.frame_write(sock, self.ws.OP_PING, '')
1161 assert self.recvall(sock, read_timeout=0.1) == b'', 'empty soc'
1162
1163 sock.close()
1164
1165 # 7_3_1
1166
1167 _, sock, _ = self.ws.upgrade()
1168
1169 self.ws.frame_write(sock, self.ws.OP_CLOSE, '')
1170 self.check_close(sock)
1171
1172 # 7_3_2
1173
1174 _, sock, _ = self.ws.upgrade()
1175
1176 self.ws.frame_write(sock, self.ws.OP_CLOSE, 'a')
1177 self.check_close(sock, 1002)
1178
1179 # 7_3_3
1180
1181 _, sock, _ = self.ws.upgrade()
1182
1183 self.ws.frame_write(sock, self.ws.OP_CLOSE, self.ws.serialize_close())
1184 self.check_close(sock)
1185
1186 # 7_3_4
1187
1188 _, sock, _ = self.ws.upgrade()
1189
1190 payload = self.ws.serialize_close(reason='Hello World!')
1191
1192 self.ws.frame_write(sock, self.ws.OP_CLOSE, payload)
1193 self.check_close(sock)
1194
1195 # 7_3_5
1196
1197 _, sock, _ = self.ws.upgrade()
1198
1199 payload = self.ws.serialize_close(reason='*' * 123)
1200
1201 self.ws.frame_write(sock, self.ws.OP_CLOSE, payload)
1202 self.check_close(sock)
1203
1204 # 7_3_6
1205
1206 _, sock, _ = self.ws.upgrade()
1207
1208 payload = self.ws.serialize_close(reason='*' * 124)
1209
1210 self.ws.frame_write(sock, self.ws.OP_CLOSE, payload)
1211 self.check_close(sock, 1002)
1212
1213# # 7_5_1 FAIL Unit does not support UTF-8 validation
1214#
1215# _, sock, _ = self.ws.upgrade()
1216#
1217# payload = self.ws.serialize_close(reason = '\xce\xba\xe1\xbd\xb9\xcf' \
1218# '\x83\xce\xbc\xce\xb5\xed\xa0\x80\x65\x64\x69\x74\x65\x64')
1219#
1220# self.ws.frame_write(sock, self.ws.OP_CLOSE, payload)
1221# self.check_close(sock, 1007)
1222
1223 def test_asgi_websockets_7_7_X__7_9_X(self):
1224 self.load('websockets/mirror')
1225
1226 valid_codes = [
1227 1000,
1228 1001,
1229 1002,
1230 1003,
1231 1007,
1232 1008,
1233 1009,
1234 1010,
1235 1011,
1236 3000,
1237 3999,
1238 4000,
1239 4999,
1240 ]
1241
1242 invalid_codes = [0, 999, 1004, 1005, 1006, 1016, 1100, 2000, 2999]
1243
1244 for code in valid_codes:
1245 _, sock, _ = self.ws.upgrade()
1246
1247 payload = self.ws.serialize_close(code=code)
1248
1249 self.ws.frame_write(sock, self.ws.OP_CLOSE, payload)
1250 self.check_close(sock)
1251
1252 for code in invalid_codes:
1253 _, sock, _ = self.ws.upgrade()
1254
1255 payload = self.ws.serialize_close(code=code)
1256
1257 self.ws.frame_write(sock, self.ws.OP_CLOSE, payload)
1258 self.check_close(sock, 1002)
1259
1260 def test_asgi_websockets_7_13_1__7_13_2(self):
1261 self.load('websockets/mirror')
1262
1263 # 7_13_1
1264
1265 _, sock, _ = self.ws.upgrade()
1266
1267 payload = self.ws.serialize_close(code=5000)
1268
1269 self.ws.frame_write(sock, self.ws.OP_CLOSE, payload)
1270 self.check_close(sock, 1002)
1271
1272 # 7_13_2
1273
1274 _, sock, _ = self.ws.upgrade()
1275
1276 payload = struct.pack('!I', 65536) + ''.encode('utf-8')
1277
1278 self.ws.frame_write(sock, self.ws.OP_CLOSE, payload)
1279 self.check_close(sock, 1002)
1280
1281 def test_asgi_websockets_9_1_1__9_6_6(self, is_unsafe):
1282 if not is_unsafe:
1283 pytest.skip('unsafe, long run')
1284
1285 self.load('websockets/mirror')
1286
1287 assert 'success' in self.conf(
1288 {
1289 'http': {
1290 'websocket': {
1291 'max_frame_size': 33554432,
1292 'keepalive_interval': 0,
1293 }
1294 }
1295 },
1296 'settings',
1297 ), 'increase max_frame_size and keepalive_interval'
1298
1299 _, sock, _ = self.ws.upgrade()
1300
1301 op_text = self.ws.OP_TEXT
1302 op_binary = self.ws.OP_BINARY
1303
1304 def check_payload(opcode, length, chopsize=None):
1305 if opcode == self.ws.OP_TEXT:
1306 payload = '*' * length
1307 else:
1308 payload = b'*' * length
1309
1310 self.ws.frame_write(sock, opcode, payload, chopsize=chopsize)
1311 frame = self.ws.frame_read(sock, read_timeout=5)
1312 self.check_frame(frame, True, opcode, payload)
1313
1314 def check_message(opcode, f_size):
1315 if opcode == self.ws.OP_TEXT:
1316 payload = '*' * 4 * 2 ** 20
1317 else:
1318 payload = b'*' * 4 * 2 ** 20
1319
1320 self.ws.message(sock, opcode, payload, fragmention_size=f_size)
1321 frame = self.ws.frame_read(sock, read_timeout=5)
1322 self.check_frame(frame, True, opcode, payload)
1323
1324 check_payload(op_text, 64 * 2 ** 10) # 9_1_1
1325 check_payload(op_text, 256 * 2 ** 10) # 9_1_2
1326 check_payload(op_text, 2 ** 20) # 9_1_3
1327 check_payload(op_text, 4 * 2 ** 20) # 9_1_4
1328 check_payload(op_text, 8 * 2 ** 20) # 9_1_5
1329 check_payload(op_text, 16 * 2 ** 20) # 9_1_6
1330
1331 check_payload(op_binary, 64 * 2 ** 10) # 9_2_1
1332 check_payload(op_binary, 256 * 2 ** 10) # 9_2_2
1333 check_payload(op_binary, 2 ** 20) # 9_2_3
1334 check_payload(op_binary, 4 * 2 ** 20) # 9_2_4
1335 check_payload(op_binary, 8 * 2 ** 20) # 9_2_5
1336 check_payload(op_binary, 16 * 2 ** 20) # 9_2_6
1337
1338 if option.system != 'Darwin' and option.system != 'FreeBSD':
1339 check_message(op_text, 64) # 9_3_1
1340 check_message(op_text, 256) # 9_3_2
1341 check_message(op_text, 2 ** 10) # 9_3_3
1342 check_message(op_text, 4 * 2 ** 10) # 9_3_4
1343 check_message(op_text, 16 * 2 ** 10) # 9_3_5
1344 check_message(op_text, 64 * 2 ** 10) # 9_3_6
1345 check_message(op_text, 256 * 2 ** 10) # 9_3_7
1346 check_message(op_text, 2 ** 20) # 9_3_8
1347 check_message(op_text, 4 * 2 ** 20) # 9_3_9
1348
1349 check_message(op_binary, 64) # 9_4_1
1350 check_message(op_binary, 256) # 9_4_2
1351 check_message(op_binary, 2 ** 10) # 9_4_3
1352 check_message(op_binary, 4 * 2 ** 10) # 9_4_4
1353 check_message(op_binary, 16 * 2 ** 10) # 9_4_5
1354 check_message(op_binary, 64 * 2 ** 10) # 9_4_6
1355 check_message(op_binary, 256 * 2 ** 10) # 9_4_7
1356 check_message(op_binary, 2 ** 20) # 9_4_8
1357 check_message(op_binary, 4 * 2 ** 20) # 9_4_9
1358
1359 check_payload(op_text, 2 ** 20, chopsize=64) # 9_5_1
1360 check_payload(op_text, 2 ** 20, chopsize=128) # 9_5_2
1361 check_payload(op_text, 2 ** 20, chopsize=256) # 9_5_3
1362 check_payload(op_text, 2 ** 20, chopsize=512) # 9_5_4
1363 check_payload(op_text, 2 ** 20, chopsize=1024) # 9_5_5
1364 check_payload(op_text, 2 ** 20, chopsize=2048) # 9_5_6
1365
1366 check_payload(op_binary, 2 ** 20, chopsize=64) # 9_6_1
1367 check_payload(op_binary, 2 ** 20, chopsize=128) # 9_6_2
1368 check_payload(op_binary, 2 ** 20, chopsize=256) # 9_6_3
1369 check_payload(op_binary, 2 ** 20, chopsize=512) # 9_6_4
1370 check_payload(op_binary, 2 ** 20, chopsize=1024) # 9_6_5
1371 check_payload(op_binary, 2 ** 20, chopsize=2048) # 9_6_6
1372
1373 self.close_connection(sock)
1374
1375 def test_asgi_websockets_10_1_1(self):
1376 self.load('websockets/mirror')
1377
1378 _, sock, _ = self.ws.upgrade()
1379
1380 payload = '*' * 65536
1381
1382 self.ws.message(sock, self.ws.OP_TEXT, payload, fragmention_size=1300)
1383
1384 frame = self.ws.frame_read(sock)
1385 self.check_frame(frame, True, self.ws.OP_TEXT, payload)
1386
1387 self.close_connection(sock)
1388
1389 # settings
1390
1391 def test_asgi_websockets_max_frame_size(self):
1392 self.load('websockets/mirror')
1393
1394 assert 'success' in self.conf(
1395 {'http': {'websocket': {'max_frame_size': 100}}}, 'settings'
1396 ), 'configure max_frame_size'
1397
1398 _, sock, _ = self.ws.upgrade()
1399
1400 payload = '*' * 94
1401 opcode = self.ws.OP_TEXT
1402
1403 self.ws.frame_write(sock, opcode, payload) # frame length is 100
1404
1405 frame = self.ws.frame_read(sock)
1406 self.check_frame(frame, True, opcode, payload)
1407
1408 payload = '*' * 95
1409
1410 self.ws.frame_write(sock, opcode, payload) # frame length is 101
1411 self.check_close(sock, 1009) # 1009 - CLOSE_TOO_LARGE
1412
1413 def test_asgi_websockets_read_timeout(self):
1414 self.load('websockets/mirror')
1415
1416 assert 'success' in self.conf(
1417 {'http': {'websocket': {'read_timeout': 5}}}, 'settings'
1418 ), 'configure read_timeout'
1419
1420 _, sock, _ = self.ws.upgrade()
1421
1422 frame = self.ws.frame_to_send(self.ws.OP_TEXT, 'blah')
1423 sock.sendall(frame[:2])
1424
1425 time.sleep(2)
1426
1427 self.check_close(sock, 1001) # 1001 - CLOSE_GOING_AWAY
1428
1429 def test_asgi_websockets_keepalive_interval(self):
1430 self.load('websockets/mirror')
1431
1432 assert 'success' in self.conf(
1433 {'http': {'websocket': {'keepalive_interval': 5}}}, 'settings'
1434 ), 'configure keepalive_interval'
1435
1436 _, sock, _ = self.ws.upgrade()
1437
1438 frame = self.ws.frame_to_send(self.ws.OP_TEXT, 'blah')
1439 sock.sendall(frame[:2])
1440
1441 time.sleep(2)
1442
1443 frame = self.ws.frame_read(sock)
1444 self.check_frame(frame, True, self.ws.OP_PING, '') # PING frame
1445
1446 sock.close()
21 assert 'success' in self.conf(
22 {'http': {'websocket': {'keepalive_interval': 0}}}, 'settings'
23 ), 'clear keepalive_interval'
24
25 skip_alert(r'socket close\(\d+\) failed')
26
27 def close_connection(self, sock):
28 assert self.recvall(sock, read_timeout=0.1) == b'', 'empty soc'
29
30 self.ws.frame_write(sock, self.ws.OP_CLOSE, self.ws.serialize_close())
31
32 self.check_close(sock)
33
34 def check_close(self, sock, code=1000, no_close=False):
35 frame = self.ws.frame_read(sock)
36
37 assert frame['fin'] == True, 'close fin'
38 assert frame['opcode'] == self.ws.OP_CLOSE, 'close opcode'
39 assert frame['code'] == code, 'close code'
40
41 if not no_close:
42 sock.close()
43
44 def check_frame(self, frame, fin, opcode, payload, decode=True):
45 if opcode == self.ws.OP_BINARY or not decode:
46 data = frame['data']
47 else:
48 data = frame['data'].decode('utf-8')
49
50 assert frame['fin'] == fin, 'fin'
51 assert frame['opcode'] == opcode, 'opcode'
52 assert data == payload, 'payload'
53
54 def test_asgi_websockets_handshake(self):
55 self.load('websockets/mirror')
56
57 resp, sock, key = self.ws.upgrade()
58 sock.close()
59
60 assert resp['status'] == 101, 'status'
61 assert resp['headers']['Upgrade'] == 'websocket', 'upgrade'
62 assert resp['headers']['Connection'] == 'Upgrade', 'connection'
63 assert resp['headers']['Sec-WebSocket-Accept'] == self.ws.accept(
64 key
65 ), 'key'
66
67 def test_asgi_websockets_subprotocol(self):
68 self.load('websockets/subprotocol')
69
70 resp, sock, key = self.ws.upgrade()
71 sock.close()
72
73 assert resp['status'] == 101, 'status'
74 assert resp['headers']['x-subprotocols'] == "('chat', 'phone', 'video')", 'subprotocols'
75 assert resp['headers']['sec-websocket-protocol'] == 'chat', 'key'
76
77 def test_asgi_websockets_mirror(self):
78 self.load('websockets/mirror')
79
80 message = 'blah'
81
82 _, sock, _ = self.ws.upgrade()
83
84 self.ws.frame_write(sock, self.ws.OP_TEXT, message)
85 frame = self.ws.frame_read(sock)
86
87 assert message == frame['data'].decode('utf-8'), 'mirror'
88
89 self.ws.frame_write(sock, self.ws.OP_TEXT, message)
90 frame = self.ws.frame_read(sock)
91
92 assert message == frame['data'].decode('utf-8'), 'mirror 2'
93
94 sock.close()
95
96 def test_asgi_websockets_no_mask(self):
97 self.load('websockets/mirror')
98
99 message = 'blah'
100
101 _, sock, _ = self.ws.upgrade()
102
103 self.ws.frame_write(sock, self.ws.OP_TEXT, message, mask=False)
104
105 frame = self.ws.frame_read(sock)
106
107 assert frame['opcode'] == self.ws.OP_CLOSE, 'no mask opcode'
108 assert frame['code'] == 1002, 'no mask close code'
109
110 sock.close()
111
112 def test_asgi_websockets_fragmentation(self):
113 self.load('websockets/mirror')
114
115 message = 'blah'
116
117 _, sock, _ = self.ws.upgrade()
118
119 self.ws.frame_write(sock, self.ws.OP_TEXT, message, fin=False)
120 self.ws.frame_write(sock, self.ws.OP_CONT, ' ', fin=False)
121 self.ws.frame_write(sock, self.ws.OP_CONT, message)
122
123 frame = self.ws.frame_read(sock)
124
125 assert message + ' ' + message == frame['data'].decode(
126 'utf-8'
127 ), 'mirror framing'
128
129 sock.close()
130
131 def test_asgi_websockets_length_long(self):
132 self.load('websockets/mirror')
133
134 _, sock, _ = self.ws.upgrade()
135
136 self.ws.frame_write(sock, self.ws.OP_TEXT, 'fragment1', fin=False)
137 self.ws.frame_write(
138 sock, self.ws.OP_CONT, 'fragment2', length=2**64 - 1
139 )
140
141 self.check_close(sock, 1009) # 1009 - CLOSE_TOO_LARGE
142
143 def test_asgi_websockets_frame_fragmentation_invalid(self):
144 self.load('websockets/mirror')
145
146 message = 'blah'
147
148 _, sock, _ = self.ws.upgrade()
149
150 self.ws.frame_write(sock, self.ws.OP_PING, message, fin=False)
151
152 frame = self.ws.frame_read(sock)
153
154 frame.pop('data')
155 assert frame == {
156 'fin': True,
157 'rsv1': False,
158 'rsv2': False,
159 'rsv3': False,
160 'opcode': self.ws.OP_CLOSE,
161 'mask': 0,
162 'code': 1002,
163 'reason': 'Fragmented control frame',
164 }, 'close frame'
165
166 sock.close()
167
168 def test_asgi_websockets_large(self):
169 self.load('websockets/mirror')
170
171 message = '0123456789' * 300
172
173 _, sock, _ = self.ws.upgrade()
174
175 self.ws.frame_write(sock, self.ws.OP_TEXT, message)
176
177 frame = self.ws.frame_read(sock)
178 data = frame['data'].decode('utf-8')
179
180 frame = self.ws.frame_read(sock)
181 data += frame['data'].decode('utf-8')
182
183 assert message == data, 'large'
184
185 sock.close()
186
187 def test_asgi_websockets_two_clients(self):
188 self.load('websockets/mirror')
189
190 message1 = 'blah1'
191 message2 = 'blah2'
192
193 _, sock1, _ = self.ws.upgrade()
194 _, sock2, _ = self.ws.upgrade()
195
196 self.ws.frame_write(sock1, self.ws.OP_TEXT, message1)
197 self.ws.frame_write(sock2, self.ws.OP_TEXT, message2)
198
199 frame1 = self.ws.frame_read(sock1)
200 frame2 = self.ws.frame_read(sock2)
201
202 assert message1 == frame1['data'].decode('utf-8'), 'client 1'
203 assert message2 == frame2['data'].decode('utf-8'), 'client 2'
204
205 sock1.close()
206 sock2.close()
207
208 @pytest.mark.skip('not yet')
209 def test_asgi_websockets_handshake_upgrade_absent(
210 self
211 ): # FAIL https://tools.ietf.org/html/rfc6455#section-4.2.1
212 self.load('websockets/mirror')
213
214 resp = self.get(
215 headers={
216 'Host': 'localhost',
217 'Connection': 'Upgrade',
218 'Sec-WebSocket-Key': self.ws.key(),
219 'Sec-WebSocket-Protocol': 'chat',
220 'Sec-WebSocket-Version': 13,
221 },
222 )
223
224 assert resp['status'] == 400, 'upgrade absent'
225
226 def test_asgi_websockets_handshake_case_insensitive(self):
227 self.load('websockets/mirror')
228
229 resp, sock, _ = self.ws.upgrade(
230 headers={
231 'Host': 'localhost',
232 'Upgrade': 'WEBSOCKET',
233 'Connection': 'UPGRADE',
234 'Sec-WebSocket-Key': self.ws.key(),
235 'Sec-WebSocket-Protocol': 'chat',
236 'Sec-WebSocket-Version': 13,
237 }
238 )
239 sock.close()
240
241 assert resp['status'] == 101, 'status'
242
243 @pytest.mark.skip('not yet')
244 def test_asgi_websockets_handshake_connection_absent(self): # FAIL
245 self.load('websockets/mirror')
246
247 resp = self.get(
248 headers={
249 'Host': 'localhost',
250 'Upgrade': 'websocket',
251 'Sec-WebSocket-Key': self.ws.key(),
252 'Sec-WebSocket-Protocol': 'chat',
253 'Sec-WebSocket-Version': 13,
254 },
255 )
256
257 assert resp['status'] == 400, 'status'
258
259 def test_asgi_websockets_handshake_version_absent(self):
260 self.load('websockets/mirror')
261
262 resp = self.get(
263 headers={
264 'Host': 'localhost',
265 'Upgrade': 'websocket',
266 'Connection': 'Upgrade',
267 'Sec-WebSocket-Key': self.ws.key(),
268 'Sec-WebSocket-Protocol': 'chat',
269 },
270 )
271
272 assert resp['status'] == 426, 'status'
273
274 @pytest.mark.skip('not yet')
275 def test_asgi_websockets_handshake_key_invalid(self):
276 self.load('websockets/mirror')
277
278 resp = self.get(
279 headers={
280 'Host': 'localhost',
281 'Upgrade': 'websocket',
282 'Connection': 'Upgrade',
283 'Sec-WebSocket-Key': '!',
284 'Sec-WebSocket-Protocol': 'chat',
285 'Sec-WebSocket-Version': 13,
286 },
287 )
288
289 assert resp['status'] == 400, 'key length'
290
291 key = self.ws.key()
292 resp = self.get(
293 headers={
294 'Host': 'localhost',
295 'Upgrade': 'websocket',
296 'Connection': 'Upgrade',
297 'Sec-WebSocket-Key': [key, key],
298 'Sec-WebSocket-Protocol': 'chat',
299 'Sec-WebSocket-Version': 13,
300 },
301 )
302
303 assert resp['status'] == 400, 'key double' # FAIL https://tools.ietf.org/html/rfc6455#section-11.3.1
304
305 def test_asgi_websockets_handshake_method_invalid(self):
306 self.load('websockets/mirror')
307
308 resp = self.post(
309 headers={
310 'Host': 'localhost',
311 'Upgrade': 'websocket',
312 'Connection': 'Upgrade',
313 'Sec-WebSocket-Key': self.ws.key(),
314 'Sec-WebSocket-Protocol': 'chat',
315 'Sec-WebSocket-Version': 13,
316 },
317 )
318
319 assert resp['status'] == 400, 'status'
320
321 def test_asgi_websockets_handshake_http_10(self):
322 self.load('websockets/mirror')
323
324 resp = self.get(
325 headers={
326 'Host': 'localhost',
327 'Upgrade': 'websocket',
328 'Connection': 'Upgrade',
329 'Sec-WebSocket-Key': self.ws.key(),
330 'Sec-WebSocket-Protocol': 'chat',
331 'Sec-WebSocket-Version': 13,
332 },
333 http_10=True,
334 )
335
336 assert resp['status'] == 400, 'status'
337
338 def test_asgi_websockets_handshake_uri_invalid(self):
339 self.load('websockets/mirror')
340
341 resp = self.get(
342 headers={
343 'Host': 'localhost',
344 'Upgrade': 'websocket',
345 'Connection': 'Upgrade',
346 'Sec-WebSocket-Key': self.ws.key(),
347 'Sec-WebSocket-Protocol': 'chat',
348 'Sec-WebSocket-Version': 13,
349 },
350 url='!',
351 )
352
353 assert resp['status'] == 400, 'status'
354
355 def test_asgi_websockets_protocol_absent(self):
356 self.load('websockets/mirror')
357
358 key = self.ws.key()
359 resp, sock, _ = self.ws.upgrade(
360 headers={
361 'Host': 'localhost',
362 'Upgrade': 'websocket',
363 'Connection': 'Upgrade',
364 'Sec-WebSocket-Key': key,
365 'Sec-WebSocket-Version': 13,
366 }
367 )
368 sock.close()
369
370 assert resp['status'] == 101, 'status'
371 assert resp['headers']['Upgrade'] == 'websocket', 'upgrade'
372 assert resp['headers']['Connection'] == 'Upgrade', 'connection'
373 assert resp['headers']['Sec-WebSocket-Accept'] == self.ws.accept(
374 key
375 ), 'key'
376
377 # autobahn-testsuite
378 #
379 # Some following tests fail because of Unit does not support UTF-8
380 # validation for websocket frames. It should be implemented
381 # by application, if necessary.
382
383 def test_asgi_websockets_1_1_1__1_1_8(self):
384 self.load('websockets/mirror')
385
386 opcode = self.ws.OP_TEXT
387
388 _, sock, _ = self.ws.upgrade()
389
390 def check_length(length, chopsize=None):
391 payload = '*' * length
392
393 self.ws.frame_write(sock, opcode, payload, chopsize=chopsize)
394
395 frame = self.ws.frame_read(sock)
396 self.check_frame(frame, True, opcode, payload)
397
398 check_length(0) # 1_1_1
399 check_length(125) # 1_1_2
400 check_length(126) # 1_1_3
401 check_length(127) # 1_1_4
402 check_length(128) # 1_1_5
403 check_length(65535) # 1_1_6
404 check_length(65536) # 1_1_7
405 check_length(65536, chopsize = 997) # 1_1_8
406
407 self.close_connection(sock)
408
409 def test_asgi_websockets_1_2_1__1_2_8(self):
410 self.load('websockets/mirror')
411
412 opcode = self.ws.OP_BINARY
413
414 _, sock, _ = self.ws.upgrade()
415
416 def check_length(length, chopsize=None):
417 payload = b'\xfe' * length
418
419 self.ws.frame_write(sock, opcode, payload, chopsize=chopsize)
420 frame = self.ws.frame_read(sock)
421
422 self.check_frame(frame, True, opcode, payload)
423
424 check_length(0) # 1_2_1
425 check_length(125) # 1_2_2
426 check_length(126) # 1_2_3
427 check_length(127) # 1_2_4
428 check_length(128) # 1_2_5
429 check_length(65535) # 1_2_6
430 check_length(65536) # 1_2_7
431 check_length(65536, chopsize = 997) # 1_2_8
432
433 self.close_connection(sock)
434
435 def test_asgi_websockets_2_1__2_6(self):
436 self.load('websockets/mirror')
437
438 op_ping = self.ws.OP_PING
439 op_pong = self.ws.OP_PONG
440
441 _, sock, _ = self.ws.upgrade()
442
443 def check_ping(payload, chopsize=None, decode=True):
444 self.ws.frame_write(sock, op_ping, payload, chopsize=chopsize)
445 frame = self.ws.frame_read(sock)
446
447 self.check_frame(frame, True, op_pong, payload, decode=decode)
448
449 check_ping('') # 2_1
450 check_ping('Hello, world!') # 2_2
451 check_ping(b'\x00\xff\xfe\xfd\xfc\xfb\x00\xff', decode=False) # 2_3
452 check_ping(b'\xfe' * 125, decode=False) # 2_4
453 check_ping(b'\xfe' * 125, chopsize=1, decode=False) # 2_6
454
455 self.close_connection(sock)
456
457 # 2_5
458
459 _, sock, _ = self.ws.upgrade()
460
461 self.ws.frame_write(sock, self.ws.OP_PING, b'\xfe' * 126)
462 self.check_close(sock, 1002)
463
464 def test_asgi_websockets_2_7__2_9(self):
465 self.load('websockets/mirror')
466
467 # 2_7
468
469 _, sock, _ = self.ws.upgrade()
470
471 self.ws.frame_write(sock, self.ws.OP_PONG, '')
472 assert self.recvall(sock, read_timeout=0.1) == b'', '2_7'
473
474 # 2_8
475
476 self.ws.frame_write(sock, self.ws.OP_PONG, 'unsolicited pong payload')
477 assert self.recvall(sock, read_timeout=0.1) == b'', '2_8'
478
479 # 2_9
480
481 payload = 'ping payload'
482
483 self.ws.frame_write(sock, self.ws.OP_PONG, 'unsolicited pong payload')
484 self.ws.frame_write(sock, self.ws.OP_PING, payload)
485
486 frame = self.ws.frame_read(sock)
487 self.check_frame(frame, True, self.ws.OP_PONG, payload)
488
489 self.close_connection(sock)
490
491 def test_asgi_websockets_2_10__2_11(self):
492 self.load('websockets/mirror')
493
494 # 2_10
495
496 _, sock, _ = self.ws.upgrade()
497
498 for i in range(0, 10):
499 self.ws.frame_write(sock, self.ws.OP_PING, 'payload-%d' % i)
500
501 for i in range(0, 10):
502 frame = self.ws.frame_read(sock)
503 self.check_frame(frame, True, self.ws.OP_PONG, 'payload-%d' % i)
504
505 # 2_11
506
507 for i in range(0, 10):
508 opcode = self.ws.OP_PING
509 self.ws.frame_write(sock, opcode, 'payload-%d' % i, chopsize=1)
510
511 for i in range(0, 10):
512 frame = self.ws.frame_read(sock)
513 self.check_frame(frame, True, self.ws.OP_PONG, 'payload-%d' % i)
514
515 self.close_connection(sock)
516
517 @pytest.mark.skip('not yet')
518 def test_asgi_websockets_3_1__3_7(self):
519 self.load('websockets/mirror')
520
521 payload = 'Hello, world!'
522
523 # 3_1
524
525 _, sock, _ = self.ws.upgrade()
526
527 self.ws.frame_write(sock, self.ws.OP_TEXT, payload, rsv1=True)
528 self.check_close(sock, 1002)
529
530 # 3_2
531
532 _, sock, _ = self.ws.upgrade()
533
534 self.ws.frame_write(sock, self.ws.OP_TEXT, payload)
535 self.ws.frame_write(sock, self.ws.OP_TEXT, payload, rsv2=True)
536 self.ws.frame_write(sock, self.ws.OP_PING, '')
537
538 frame = self.ws.frame_read(sock)
539 self.check_frame(frame, True, self.ws.OP_TEXT, payload)
540
541 self.check_close(sock, 1002, no_close=True)
542
543 assert self.recvall(sock, read_timeout=0.1) == b'', 'empty 3_2'
544 sock.close()
545
546 # 3_3
547
548 _, sock, _ = self.ws.upgrade()
549
550 self.ws.frame_write(sock, self.ws.OP_TEXT, payload)
551
552 frame = self.ws.frame_read(sock)
553 self.check_frame(frame, True, self.ws.OP_TEXT, payload)
554
555 self.ws.frame_write(
556 sock, self.ws.OP_TEXT, payload, rsv1=True, rsv2=True
557 )
558
559 self.check_close(sock, 1002, no_close=True)
560
561 assert self.recvall(sock, read_timeout=0.1) == b'', 'empty 3_3'
562 sock.close()
563
564 # 3_4
565
566 _, sock, _ = self.ws.upgrade()
567
568 self.ws.frame_write(sock, self.ws.OP_TEXT, payload, chopsize=1)
569 self.ws.frame_write(
570 sock, self.ws.OP_TEXT, payload, rsv3=True, chopsize=1
571 )
572 self.ws.frame_write(sock, self.ws.OP_PING, '')
573
574 frame = self.ws.frame_read(sock)
575 self.check_frame(frame, True, self.ws.OP_TEXT, payload)
576
577 self.check_close(sock, 1002, no_close=True)
578
579 assert self.recvall(sock, read_timeout=0.1) == b'', 'empty 3_4'
580 sock.close()
581
582 # 3_5
583
584 _, sock, _ = self.ws.upgrade()
585
586 self.ws.frame_write(
587 sock,
588 self.ws.OP_BINARY,
589 b'\x00\xff\xfe\xfd\xfc\xfb\x00\xff',
590 rsv1=True,
591 rsv3=True,
592 )
593
594 self.check_close(sock, 1002)
595
596 # 3_6
597
598 _, sock, _ = self.ws.upgrade()
599
600 self.ws.frame_write(
601 sock, self.ws.OP_PING, payload, rsv2=True, rsv3=True
602 )
603
604 self.check_close(sock, 1002)
605
606 # 3_7
607
608 _, sock, _ = self.ws.upgrade()
609
610 self.ws.frame_write(
611 sock, self.ws.OP_CLOSE, payload, rsv1=True, rsv2=True, rsv3=True
612 )
613
614 self.check_close(sock, 1002)
615
616 def test_asgi_websockets_4_1_1__4_2_5(self):
617 self.load('websockets/mirror')
618
619 payload = 'Hello, world!'
620
621 # 4_1_1
622
623 _, sock, _ = self.ws.upgrade()
624
625 self.ws.frame_write(sock, 0x03, '')
626 self.check_close(sock, 1002)
627
628 # 4_1_2
629
630 _, sock, _ = self.ws.upgrade()
631
632 self.ws.frame_write(sock, 0x04, 'reserved opcode payload')
633 self.check_close(sock, 1002)
634
635 # 4_1_3
636
637 _, sock, _ = self.ws.upgrade()
638
639 self.ws.frame_write(sock, self.ws.OP_TEXT, payload)
640
641 frame = self.ws.frame_read(sock)
642 self.check_frame(frame, True, self.ws.OP_TEXT, payload)
643
644 self.ws.frame_write(sock, 0x05, '')
645 self.ws.frame_write(sock, self.ws.OP_PING, '')
646
647 self.check_close(sock, 1002)
648
649 # 4_1_4
650
651 _, sock, _ = self.ws.upgrade()
652
653 self.ws.frame_write(sock, self.ws.OP_TEXT, payload)
654
655 frame = self.ws.frame_read(sock)
656 self.check_frame(frame, True, self.ws.OP_TEXT, payload)
657
658 self.ws.frame_write(sock, 0x06, payload)
659 self.ws.frame_write(sock, self.ws.OP_PING, '')
660
661 self.check_close(sock, 1002)
662
663 # 4_1_5
664
665 _, sock, _ = self.ws.upgrade()
666
667 self.ws.frame_write(sock, self.ws.OP_TEXT, payload, chopsize=1)
668
669 frame = self.ws.frame_read(sock)
670 self.check_frame(frame, True, self.ws.OP_TEXT, payload)
671
672 self.ws.frame_write(sock, 0x07, payload, chopsize=1)
673 self.ws.frame_write(sock, self.ws.OP_PING, '')
674
675 self.check_close(sock, 1002)
676
677 # 4_2_1
678
679 _, sock, _ = self.ws.upgrade()
680
681 self.ws.frame_write(sock, 0x0B, '')
682 self.check_close(sock, 1002)
683
684 # 4_2_2
685
686 _, sock, _ = self.ws.upgrade()
687
688 self.ws.frame_write(sock, 0x0C, 'reserved opcode payload')
689 self.check_close(sock, 1002)
690
691 # 4_2_3
692
693 _, sock, _ = self.ws.upgrade()
694
695 self.ws.frame_write(sock, self.ws.OP_TEXT, payload)
696
697 frame = self.ws.frame_read(sock)
698 self.check_frame(frame, True, self.ws.OP_TEXT, payload)
699
700 self.ws.frame_write(sock, 0x0D, '')
701 self.ws.frame_write(sock, self.ws.OP_PING, '')
702
703 self.check_close(sock, 1002)
704
705 # 4_2_4
706
707 _, sock, _ = self.ws.upgrade()
708
709 self.ws.frame_write(sock, self.ws.OP_TEXT, payload)
710
711 frame = self.ws.frame_read(sock)
712 self.check_frame(frame, True, self.ws.OP_TEXT, payload)
713
714 self.ws.frame_write(sock, 0x0E, payload)
715 self.ws.frame_write(sock, self.ws.OP_PING, '')
716
717 self.check_close(sock, 1002)
718
719 # 4_2_5
720
721 _, sock, _ = self.ws.upgrade()
722
723 self.ws.frame_write(sock, self.ws.OP_TEXT, payload, chopsize=1)
724
725 frame = self.ws.frame_read(sock)
726 self.check_frame(frame, True, self.ws.OP_TEXT, payload)
727
728 self.ws.frame_write(sock, 0x0F, payload, chopsize=1)
729 self.ws.frame_write(sock, self.ws.OP_PING, '')
730
731 self.check_close(sock, 1002)
732
733 def test_asgi_websockets_5_1__5_20(self):
734 self.load('websockets/mirror')
735
736 # 5_1
737
738 _, sock, _ = self.ws.upgrade()
739
740 self.ws.frame_write(sock, self.ws.OP_PING, 'fragment1', fin=False)
741 self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment2', fin=True)
742 self.check_close(sock, 1002)
743
744 # 5_2
745
746 _, sock, _ = self.ws.upgrade()
747
748 self.ws.frame_write(sock, self.ws.OP_PONG, 'fragment1', fin=False)
749 self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment2', fin=True)
750 self.check_close(sock, 1002)
751
752 # 5_3
753
754 _, sock, _ = self.ws.upgrade()
755
756 self.ws.frame_write(sock, self.ws.OP_TEXT, 'fragment1', fin=False)
757 self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment2', fin=True)
758
759 frame = self.ws.frame_read(sock)
760 self.check_frame(frame, True, self.ws.OP_TEXT, 'fragment1fragment2')
761
762 # 5_4
763
764 self.ws.frame_write(sock, self.ws.OP_TEXT, 'fragment1', fin=False)
765 assert self.recvall(sock, read_timeout=0.1) == b'', '5_4'
766 self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment2', fin=True)
767
768 frame = self.ws.frame_read(sock)
769 self.check_frame(frame, True, self.ws.OP_TEXT, 'fragment1fragment2')
770
771 # 5_5
772
773 self.ws.frame_write(
774 sock, self.ws.OP_TEXT, 'fragment1', fin=False, chopsize=1
775 )
776 self.ws.frame_write(
777 sock, self.ws.OP_CONT, 'fragment2', fin=True, chopsize=1
778 )
779
780 frame = self.ws.frame_read(sock)
781 self.check_frame(frame, True, self.ws.OP_TEXT, 'fragment1fragment2')
782
783 # 5_6
784
785 ping_payload = 'ping payload'
786
787 self.ws.frame_write(sock, self.ws.OP_TEXT, 'fragment1', fin=False)
788 self.ws.frame_write(sock, self.ws.OP_PING, ping_payload)
789 self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment2', fin=True)
790
791 frame = self.ws.frame_read(sock)
792 self.check_frame(frame, True, self.ws.OP_PONG, ping_payload)
793
794 frame = self.ws.frame_read(sock)
795 self.check_frame(frame, True, self.ws.OP_TEXT, 'fragment1fragment2')
796
797 # 5_7
798
799 ping_payload = 'ping payload'
800
801 self.ws.frame_write(sock, self.ws.OP_TEXT, 'fragment1', fin=False)
802 assert self.recvall(sock, read_timeout=0.1) == b'', '5_7'
803
804 self.ws.frame_write(sock, self.ws.OP_PING, ping_payload)
805
806 frame = self.ws.frame_read(sock)
807 self.check_frame(frame, True, self.ws.OP_PONG, ping_payload)
808
809 self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment2', fin=True)
810
811 frame = self.ws.frame_read(sock)
812 self.check_frame(frame, True, self.ws.OP_TEXT, 'fragment1fragment2')
813
814 # 5_8
815
816 ping_payload = 'ping payload'
817
818 self.ws.frame_write(
819 sock, self.ws.OP_TEXT, 'fragment1', fin=False, chopsize=1
820 )
821 self.ws.frame_write(sock, self.ws.OP_PING, ping_payload, chopsize=1)
822 self.ws.frame_write(
823 sock, self.ws.OP_CONT, 'fragment2', fin=True, chopsize=1
824 )
825
826 frame = self.ws.frame_read(sock)
827 self.check_frame(frame, True, self.ws.OP_PONG, ping_payload)
828
829 frame = self.ws.frame_read(sock)
830 self.check_frame(frame, True, self.ws.OP_TEXT, 'fragment1fragment2')
831
832 # 5_9
833
834 self.ws.frame_write(
835 sock, self.ws.OP_CONT, 'non-continuation payload', fin=True
836 )
837 self.ws.frame_write(sock, self.ws.OP_TEXT, 'Hello, world!', fin=True)
838 self.check_close(sock, 1002)
839
840 # 5_10
841
842 _, sock, _ = self.ws.upgrade()
843
844 self.ws.frame_write(
845 sock, self.ws.OP_CONT, 'non-continuation payload', fin=True
846 )
847 self.ws.frame_write(sock, self.ws.OP_TEXT, 'Hello, world!', fin=True)
848 self.check_close(sock, 1002)
849
850 # 5_11
851
852 _, sock, _ = self.ws.upgrade()
853
854 self.ws.frame_write(
855 sock,
856 self.ws.OP_CONT,
857 'non-continuation payload',
858 fin=True,
859 chopsize=1,
860 )
861 self.ws.frame_write(
862 sock, self.ws.OP_TEXT, 'Hello, world!', fin=True, chopsize=1
863 )
864 self.check_close(sock, 1002)
865
866 # 5_12
867
868 _, sock, _ = self.ws.upgrade()
869
870 self.ws.frame_write(
871 sock, self.ws.OP_CONT, 'non-continuation payload', fin=False
872 )
873 self.ws.frame_write(sock, self.ws.OP_TEXT, 'Hello, world!', fin=True)
874 self.check_close(sock, 1002)
875
876 # 5_13
877
878 _, sock, _ = self.ws.upgrade()
879
880 self.ws.frame_write(
881 sock, self.ws.OP_CONT, 'non-continuation payload', fin=False
882 )
883 self.ws.frame_write(sock, self.ws.OP_TEXT, 'Hello, world!', fin=True)
884 self.check_close(sock, 1002)
885
886 # 5_14
887
888 _, sock, _ = self.ws.upgrade()
889
890 self.ws.frame_write(
891 sock,
892 self.ws.OP_CONT,
893 'non-continuation payload',
894 fin=False,
895 chopsize=1,
896 )
897 self.ws.frame_write(
898 sock, self.ws.OP_TEXT, 'Hello, world!', fin=True, chopsize=1
899 )
900 self.check_close(sock, 1002)
901
902 # 5_15
903
904 _, sock, _ = self.ws.upgrade()
905
906 self.ws.frame_write(sock, self.ws.OP_TEXT, 'fragment1', fin=False)
907 self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment2', fin=True)
908 self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment3', fin=False)
909 self.ws.frame_write(sock, self.ws.OP_TEXT, 'fragment4', fin=True)
910 self.check_close(sock, 1002)
911
912 # 5_16
913
914 _, sock, _ = self.ws.upgrade()
915
916 for i in range(0, 2):
917 self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment1', fin=False)
918 self.ws.frame_write(sock, self.ws.OP_TEXT, 'fragment2', fin=False)
919 self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment3', fin=True)
920 self.check_close(sock, 1002)
921
922 # 5_17
923
924 _, sock, _ = self.ws.upgrade()
925
926 for i in range(0, 2):
927 self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment1', fin=True)
928 self.ws.frame_write(sock, self.ws.OP_TEXT, 'fragment2', fin=False)
929 self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment3', fin=True)
930 self.check_close(sock, 1002)
931
932 # 5_18
933
934 _, sock, _ = self.ws.upgrade()
935
936 self.ws.frame_write(sock, self.ws.OP_TEXT, 'fragment1', fin=False)
937 self.ws.frame_write(sock, self.ws.OP_TEXT, 'fragment2')
938 self.check_close(sock, 1002)
939
940 # 5_19
941
942 _, sock, _ = self.ws.upgrade()
943
944 self.ws.frame_write(sock, self.ws.OP_TEXT, 'fragment1', fin=False)
945 self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment2', fin=False)
946 self.ws.frame_write(sock, self.ws.OP_PING, 'pongme 1!')
947
948 time.sleep(1)
949
950 self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment3', fin=False)
951 self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment4', fin=False)
952 self.ws.frame_write(sock, self.ws.OP_PING, 'pongme 2!')
953 self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment5')
954
955 frame = self.ws.frame_read(sock)
956 self.check_frame(frame, True, self.ws.OP_PONG, 'pongme 1!')
957
958 frame = self.ws.frame_read(sock)
959 self.check_frame(frame, True, self.ws.OP_PONG, 'pongme 2!')
960
961 self.check_frame(
962 self.ws.frame_read(sock),
963 True,
964 self.ws.OP_TEXT,
965 'fragment1fragment2fragment3fragment4fragment5',
966 )
967
968 # 5_20
969
970 self.ws.frame_write(sock, self.ws.OP_TEXT, 'fragment1', fin=False)
971 self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment2', fin=False)
972 self.ws.frame_write(sock, self.ws.OP_PING, 'pongme 1!')
973
974 frame = self.ws.frame_read(sock)
975 self.check_frame(frame, True, self.ws.OP_PONG, 'pongme 1!')
976
977 time.sleep(1)
978
979 self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment3', fin=False)
980 self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment4', fin=False)
981 self.ws.frame_write(sock, self.ws.OP_PING, 'pongme 2!')
982
983 frame = self.ws.frame_read(sock)
984 self.check_frame(frame, True, self.ws.OP_PONG, 'pongme 2!')
985
986 assert self.recvall(sock, read_timeout=0.1) == b'', '5_20'
987 self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment5')
988
989 self.check_frame(
990 self.ws.frame_read(sock),
991 True,
992 self.ws.OP_TEXT,
993 'fragment1fragment2fragment3fragment4fragment5',
994 )
995
996 self.close_connection(sock)
997
998 def test_asgi_websockets_6_1_1__6_4_4(self):
999 self.load('websockets/mirror')
1000
1001 # 6_1_1
1002
1003 _, sock, _ = self.ws.upgrade()
1004
1005 self.ws.frame_write(sock, self.ws.OP_TEXT, '')
1006 frame = self.ws.frame_read(sock)
1007 self.check_frame(frame, True, self.ws.OP_TEXT, '')
1008
1009 # 6_1_2
1010
1011 self.ws.frame_write(sock, self.ws.OP_TEXT, '', fin=False)
1012 self.ws.frame_write(sock, self.ws.OP_CONT, '', fin=False)
1013 self.ws.frame_write(sock, self.ws.OP_CONT, '')
1014
1015 frame = self.ws.frame_read(sock)
1016 self.check_frame(frame, True, self.ws.OP_TEXT, '')
1017
1018 # 6_1_3
1019
1020 payload = 'middle frame payload'
1021
1022 self.ws.frame_write(sock, self.ws.OP_TEXT, '', fin=False)
1023 self.ws.frame_write(sock, self.ws.OP_CONT, payload, fin=False)
1024 self.ws.frame_write(sock, self.ws.OP_CONT, '')
1025
1026 frame = self.ws.frame_read(sock)
1027 self.check_frame(frame, True, self.ws.OP_TEXT, payload)
1028
1029 # 6_2_1
1030
1031 payload = 'Hello-µ@ßöäüàá-UTF-8!!'
1032
1033 self.ws.frame_write(sock, self.ws.OP_TEXT, payload)
1034
1035 frame = self.ws.frame_read(sock)
1036 self.check_frame(frame, True, self.ws.OP_TEXT, payload)
1037
1038 # 6_2_2
1039
1040 self.ws.frame_write(sock, self.ws.OP_TEXT, payload[:12], fin=False)
1041 self.ws.frame_write(sock, self.ws.OP_CONT, payload[12:])
1042
1043 frame = self.ws.frame_read(sock)
1044 self.check_frame(frame, True, self.ws.OP_TEXT, payload)
1045
1046 # 6_2_3
1047
1048 self.ws.message(sock, self.ws.OP_TEXT, payload, fragmention_size=1)
1049
1050 frame = self.ws.frame_read(sock)
1051 self.check_frame(frame, True, self.ws.OP_TEXT, payload)
1052
1053 # 6_2_4
1054
1055 payload = '\xce\xba\xe1\xbd\xb9\xcf\x83\xce\xbc\xce\xb5'
1056
1057 self.ws.message(sock, self.ws.OP_TEXT, payload, fragmention_size=1)
1058
1059 frame = self.ws.frame_read(sock)
1060 self.check_frame(frame, True, self.ws.OP_TEXT, payload)
1061
1062 self.close_connection(sock)
1063
1064# Unit does not support UTF-8 validation
1065#
1066# # 6_3_1 FAIL
1067#
1068# payload_1 = '\xce\xba\xe1\xbd\xb9\xcf\x83\xce\xbc\xce\xb5'
1069# payload_2 = '\xed\xa0\x80'
1070# payload_3 = '\x65\x64\x69\x74\x65\x64'
1071#
1072# payload = payload_1 + payload_2 + payload_3
1073#
1074# self.ws.message(sock, self.ws.OP_TEXT, payload)
1075# self.check_close(sock, 1007)
1076#
1077# # 6_3_2 FAIL
1078#
1079# _, sock, _ = self.ws.upgrade()
1080#
1081# self.ws.message(sock, self.ws.OP_TEXT, payload, fragmention_size=1)
1082# self.check_close(sock, 1007)
1083#
1084# # 6_4_1 ... 6_4_4 FAIL
1085
1086 def test_asgi_websockets_7_1_1__7_5_1(self):
1087 self.load('websockets/mirror')
1088
1089 # 7_1_1
1090
1091 _, sock, _ = self.ws.upgrade()
1092
1093 payload = "Hello World!"
1094
1095 self.ws.frame_write(sock, self.ws.OP_TEXT, payload)
1096
1097 frame = self.ws.frame_read(sock)
1098 self.check_frame(frame, True, self.ws.OP_TEXT, payload)
1099
1100 self.close_connection(sock)
1101
1102 # 7_1_2
1103
1104 _, sock, _ = self.ws.upgrade()
1105
1106 self.ws.frame_write(sock, self.ws.OP_CLOSE, self.ws.serialize_close())
1107 self.ws.frame_write(sock, self.ws.OP_CLOSE, self.ws.serialize_close())
1108
1109 self.check_close(sock)
1110
1111 # 7_1_3
1112
1113 _, sock, _ = self.ws.upgrade()
1114
1115 self.ws.frame_write(sock, self.ws.OP_CLOSE, self.ws.serialize_close())
1116 self.check_close(sock, no_close=True)
1117
1118 self.ws.frame_write(sock, self.ws.OP_PING, '')
1119 assert self.recvall(sock, read_timeout=0.1) == b'', 'empty soc'
1120
1121 sock.close()
1122
1123 # 7_1_4
1124
1125 _, sock, _ = self.ws.upgrade()
1126
1127 self.ws.frame_write(sock, self.ws.OP_CLOSE, self.ws.serialize_close())
1128 self.check_close(sock, no_close=True)
1129
1130 self.ws.frame_write(sock, self.ws.OP_TEXT, payload)
1131 assert self.recvall(sock, read_timeout=0.1) == b'', 'empty soc'
1132
1133 sock.close()
1134
1135 # 7_1_5
1136
1137 _, sock, _ = self.ws.upgrade()
1138
1139 self.ws.frame_write(sock, self.ws.OP_TEXT, 'fragment1', fin=False)
1140 self.ws.frame_write(sock, self.ws.OP_CLOSE, self.ws.serialize_close())
1141 self.check_close(sock, no_close=True)
1142
1143 self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment2')
1144 assert self.recvall(sock, read_timeout=0.1) == b'', 'empty soc'
1145
1146 sock.close()
1147
1148 # 7_1_6
1149
1150 _, sock, _ = self.ws.upgrade()
1151
1152 self.ws.frame_write(sock, self.ws.OP_TEXT, 'BAsd7&jh23' * 26 * 2 ** 10)
1153 self.ws.frame_write(sock, self.ws.OP_TEXT, payload)
1154 self.ws.frame_write(sock, self.ws.OP_CLOSE, self.ws.serialize_close())
1155
1156 self.recvall(sock, read_timeout=1)
1157
1158 self.ws.frame_write(sock, self.ws.OP_PING, '')
1159 assert self.recvall(sock, read_timeout=0.1) == b'', 'empty soc'
1160
1161 sock.close()
1162
1163 # 7_3_1
1164
1165 _, sock, _ = self.ws.upgrade()
1166
1167 self.ws.frame_write(sock, self.ws.OP_CLOSE, '')
1168 self.check_close(sock)
1169
1170 # 7_3_2
1171
1172 _, sock, _ = self.ws.upgrade()
1173
1174 self.ws.frame_write(sock, self.ws.OP_CLOSE, 'a')
1175 self.check_close(sock, 1002)
1176
1177 # 7_3_3
1178
1179 _, sock, _ = self.ws.upgrade()
1180
1181 self.ws.frame_write(sock, self.ws.OP_CLOSE, self.ws.serialize_close())
1182 self.check_close(sock)
1183
1184 # 7_3_4
1185
1186 _, sock, _ = self.ws.upgrade()
1187
1188 payload = self.ws.serialize_close(reason='Hello World!')
1189
1190 self.ws.frame_write(sock, self.ws.OP_CLOSE, payload)
1191 self.check_close(sock)
1192
1193 # 7_3_5
1194
1195 _, sock, _ = self.ws.upgrade()
1196
1197 payload = self.ws.serialize_close(reason='*' * 123)
1198
1199 self.ws.frame_write(sock, self.ws.OP_CLOSE, payload)
1200 self.check_close(sock)
1201
1202 # 7_3_6
1203
1204 _, sock, _ = self.ws.upgrade()
1205
1206 payload = self.ws.serialize_close(reason='*' * 124)
1207
1208 self.ws.frame_write(sock, self.ws.OP_CLOSE, payload)
1209 self.check_close(sock, 1002)
1210
1211# # 7_5_1 FAIL Unit does not support UTF-8 validation
1212#
1213# _, sock, _ = self.ws.upgrade()
1214#
1215# payload = self.ws.serialize_close(reason = '\xce\xba\xe1\xbd\xb9\xcf' \
1216# '\x83\xce\xbc\xce\xb5\xed\xa0\x80\x65\x64\x69\x74\x65\x64')
1217#
1218# self.ws.frame_write(sock, self.ws.OP_CLOSE, payload)
1219# self.check_close(sock, 1007)
1220
1221 def test_asgi_websockets_7_7_X__7_9_X(self):
1222 self.load('websockets/mirror')
1223
1224 valid_codes = [
1225 1000,
1226 1001,
1227 1002,
1228 1003,
1229 1007,
1230 1008,
1231 1009,
1232 1010,
1233 1011,
1234 3000,
1235 3999,
1236 4000,
1237 4999,
1238 ]
1239
1240 invalid_codes = [0, 999, 1004, 1005, 1006, 1016, 1100, 2000, 2999]
1241
1242 for code in valid_codes:
1243 _, sock, _ = self.ws.upgrade()
1244
1245 payload = self.ws.serialize_close(code=code)
1246
1247 self.ws.frame_write(sock, self.ws.OP_CLOSE, payload)
1248 self.check_close(sock)
1249
1250 for code in invalid_codes:
1251 _, sock, _ = self.ws.upgrade()
1252
1253 payload = self.ws.serialize_close(code=code)
1254
1255 self.ws.frame_write(sock, self.ws.OP_CLOSE, payload)
1256 self.check_close(sock, 1002)
1257
1258 def test_asgi_websockets_7_13_1__7_13_2(self):
1259 self.load('websockets/mirror')
1260
1261 # 7_13_1
1262
1263 _, sock, _ = self.ws.upgrade()
1264
1265 payload = self.ws.serialize_close(code=5000)
1266
1267 self.ws.frame_write(sock, self.ws.OP_CLOSE, payload)
1268 self.check_close(sock, 1002)
1269
1270 # 7_13_2
1271
1272 _, sock, _ = self.ws.upgrade()
1273
1274 payload = struct.pack('!I', 65536) + ''.encode('utf-8')
1275
1276 self.ws.frame_write(sock, self.ws.OP_CLOSE, payload)
1277 self.check_close(sock, 1002)
1278
1279 def test_asgi_websockets_9_1_1__9_6_6(self, is_unsafe):
1280 if not is_unsafe:
1281 pytest.skip('unsafe, long run')
1282
1283 self.load('websockets/mirror')
1284
1285 assert 'success' in self.conf(
1286 {
1287 'http': {
1288 'websocket': {
1289 'max_frame_size': 33554432,
1290 'keepalive_interval': 0,
1291 }
1292 }
1293 },
1294 'settings',
1295 ), 'increase max_frame_size and keepalive_interval'
1296
1297 _, sock, _ = self.ws.upgrade()
1298
1299 op_text = self.ws.OP_TEXT
1300 op_binary = self.ws.OP_BINARY
1301
1302 def check_payload(opcode, length, chopsize=None):
1303 if opcode == self.ws.OP_TEXT:
1304 payload = '*' * length
1305 else:
1306 payload = b'*' * length
1307
1308 self.ws.frame_write(sock, opcode, payload, chopsize=chopsize)
1309 frame = self.ws.frame_read(sock, read_timeout=5)
1310 self.check_frame(frame, True, opcode, payload)
1311
1312 def check_message(opcode, f_size):
1313 if opcode == self.ws.OP_TEXT:
1314 payload = '*' * 4 * 2 ** 20
1315 else:
1316 payload = b'*' * 4 * 2 ** 20
1317
1318 self.ws.message(sock, opcode, payload, fragmention_size=f_size)
1319 frame = self.ws.frame_read(sock, read_timeout=5)
1320 self.check_frame(frame, True, opcode, payload)
1321
1322 check_payload(op_text, 64 * 2 ** 10) # 9_1_1
1323 check_payload(op_text, 256 * 2 ** 10) # 9_1_2
1324 check_payload(op_text, 2 ** 20) # 9_1_3
1325 check_payload(op_text, 4 * 2 ** 20) # 9_1_4
1326 check_payload(op_text, 8 * 2 ** 20) # 9_1_5
1327 check_payload(op_text, 16 * 2 ** 20) # 9_1_6
1328
1329 check_payload(op_binary, 64 * 2 ** 10) # 9_2_1
1330 check_payload(op_binary, 256 * 2 ** 10) # 9_2_2
1331 check_payload(op_binary, 2 ** 20) # 9_2_3
1332 check_payload(op_binary, 4 * 2 ** 20) # 9_2_4
1333 check_payload(op_binary, 8 * 2 ** 20) # 9_2_5
1334 check_payload(op_binary, 16 * 2 ** 20) # 9_2_6
1335
1336 if option.system != 'Darwin' and option.system != 'FreeBSD':
1337 check_message(op_text, 64) # 9_3_1
1338 check_message(op_text, 256) # 9_3_2
1339 check_message(op_text, 2 ** 10) # 9_3_3
1340 check_message(op_text, 4 * 2 ** 10) # 9_3_4
1341 check_message(op_text, 16 * 2 ** 10) # 9_3_5
1342 check_message(op_text, 64 * 2 ** 10) # 9_3_6
1343 check_message(op_text, 256 * 2 ** 10) # 9_3_7
1344 check_message(op_text, 2 ** 20) # 9_3_8
1345 check_message(op_text, 4 * 2 ** 20) # 9_3_9
1346
1347 check_message(op_binary, 64) # 9_4_1
1348 check_message(op_binary, 256) # 9_4_2
1349 check_message(op_binary, 2 ** 10) # 9_4_3
1350 check_message(op_binary, 4 * 2 ** 10) # 9_4_4
1351 check_message(op_binary, 16 * 2 ** 10) # 9_4_5
1352 check_message(op_binary, 64 * 2 ** 10) # 9_4_6
1353 check_message(op_binary, 256 * 2 ** 10) # 9_4_7
1354 check_message(op_binary, 2 ** 20) # 9_4_8
1355 check_message(op_binary, 4 * 2 ** 20) # 9_4_9
1356
1357 check_payload(op_text, 2 ** 20, chopsize=64) # 9_5_1
1358 check_payload(op_text, 2 ** 20, chopsize=128) # 9_5_2
1359 check_payload(op_text, 2 ** 20, chopsize=256) # 9_5_3
1360 check_payload(op_text, 2 ** 20, chopsize=512) # 9_5_4
1361 check_payload(op_text, 2 ** 20, chopsize=1024) # 9_5_5
1362 check_payload(op_text, 2 ** 20, chopsize=2048) # 9_5_6
1363
1364 check_payload(op_binary, 2 ** 20, chopsize=64) # 9_6_1
1365 check_payload(op_binary, 2 ** 20, chopsize=128) # 9_6_2
1366 check_payload(op_binary, 2 ** 20, chopsize=256) # 9_6_3
1367 check_payload(op_binary, 2 ** 20, chopsize=512) # 9_6_4
1368 check_payload(op_binary, 2 ** 20, chopsize=1024) # 9_6_5
1369 check_payload(op_binary, 2 ** 20, chopsize=2048) # 9_6_6
1370
1371 self.close_connection(sock)
1372
1373 def test_asgi_websockets_10_1_1(self):
1374 self.load('websockets/mirror')
1375
1376 _, sock, _ = self.ws.upgrade()
1377
1378 payload = '*' * 65536
1379
1380 self.ws.message(sock, self.ws.OP_TEXT, payload, fragmention_size=1300)
1381
1382 frame = self.ws.frame_read(sock)
1383 self.check_frame(frame, True, self.ws.OP_TEXT, payload)
1384
1385 self.close_connection(sock)
1386
1387 # settings
1388
1389 def test_asgi_websockets_max_frame_size(self):
1390 self.load('websockets/mirror')
1391
1392 assert 'success' in self.conf(
1393 {'http': {'websocket': {'max_frame_size': 100}}}, 'settings'
1394 ), 'configure max_frame_size'
1395
1396 _, sock, _ = self.ws.upgrade()
1397
1398 payload = '*' * 94
1399 opcode = self.ws.OP_TEXT
1400
1401 self.ws.frame_write(sock, opcode, payload) # frame length is 100
1402
1403 frame = self.ws.frame_read(sock)
1404 self.check_frame(frame, True, opcode, payload)
1405
1406 payload = '*' * 95
1407
1408 self.ws.frame_write(sock, opcode, payload) # frame length is 101
1409 self.check_close(sock, 1009) # 1009 - CLOSE_TOO_LARGE
1410
1411 def test_asgi_websockets_read_timeout(self):
1412 self.load('websockets/mirror')
1413
1414 assert 'success' in self.conf(
1415 {'http': {'websocket': {'read_timeout': 5}}}, 'settings'
1416 ), 'configure read_timeout'
1417
1418 _, sock, _ = self.ws.upgrade()
1419
1420 frame = self.ws.frame_to_send(self.ws.OP_TEXT, 'blah')
1421 sock.sendall(frame[:2])
1422
1423 time.sleep(2)
1424
1425 self.check_close(sock, 1001) # 1001 - CLOSE_GOING_AWAY
1426
1427 def test_asgi_websockets_keepalive_interval(self):
1428 self.load('websockets/mirror')
1429
1430 assert 'success' in self.conf(
1431 {'http': {'websocket': {'keepalive_interval': 5}}}, 'settings'
1432 ), 'configure keepalive_interval'
1433
1434 _, sock, _ = self.ws.upgrade()
1435
1436 frame = self.ws.frame_to_send(self.ws.OP_TEXT, 'blah')
1437 sock.sendall(frame[:2])
1438
1439 time.sleep(2)
1440
1441 frame = self.ws.frame_read(sock)
1442 self.check_frame(frame, True, self.ws.OP_PING, '') # PING frame
1443
1444 sock.close()