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