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