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( 946 frame, True, self.ws.OP_TEXT, 'fragment1fragment2' 947 ) 948 frame = None 949 950 self.check_close(sock, 1002, frame=frame) 951 952 # 5_16 953 954 _, sock, _ = self.ws.upgrade() 955 956 for i in range(0, 2): 957 self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment1', fin=False) 958 self.ws.frame_write(sock, self.ws.OP_TEXT, 'fragment2', fin=False) 959 self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment3', fin=True) 960 self.check_close(sock, 1002) 961 962 # 5_17 963 964 _, sock, _ = self.ws.upgrade() 965 966 for i in range(0, 2): 967 self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment1', fin=True) 968 self.ws.frame_write(sock, self.ws.OP_TEXT, 'fragment2', fin=False) 969 self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment3', fin=True) 970 self.check_close(sock, 1002) 971 972 # 5_18 973 974 _, sock, _ = self.ws.upgrade() 975 976 self.ws.frame_write(sock, self.ws.OP_TEXT, 'fragment1', fin=False) 977 self.ws.frame_write(sock, self.ws.OP_TEXT, 'fragment2') 978 self.check_close(sock, 1002) 979 980 # 5_19 981 982 _, sock, _ = self.ws.upgrade() 983 984 self.ws.frame_write(sock, self.ws.OP_TEXT, 'fragment1', fin=False) 985 self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment2', fin=False) 986 self.ws.frame_write(sock, self.ws.OP_PING, 'pongme 1!') 987 988 time.sleep(1) 989 990 self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment3', fin=False) 991 self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment4', fin=False) 992 self.ws.frame_write(sock, self.ws.OP_PING, 'pongme 2!') 993 self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment5') 994 995 frame = self.ws.frame_read(sock) 996 self.check_frame(frame, True, self.ws.OP_PONG, 'pongme 1!') 997 998 frame = self.ws.frame_read(sock) 999 self.check_frame(frame, True, self.ws.OP_PONG, 'pongme 2!') 1000 1001 self.check_frame( 1002 self.ws.frame_read(sock), 1003 True, 1004 self.ws.OP_TEXT, 1005 'fragment1fragment2fragment3fragment4fragment5', 1006 ) 1007 1008 # 5_20 1009 1010 self.ws.frame_write(sock, self.ws.OP_TEXT, 'fragment1', fin=False) 1011 self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment2', fin=False) 1012 self.ws.frame_write(sock, self.ws.OP_PING, 'pongme 1!') 1013 1014 frame = self.ws.frame_read(sock) 1015 self.check_frame(frame, True, self.ws.OP_PONG, 'pongme 1!') 1016 1017 time.sleep(1) 1018 1019 self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment3', fin=False) 1020 self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment4', fin=False) 1021 self.ws.frame_write(sock, self.ws.OP_PING, 'pongme 2!') 1022 1023 frame = self.ws.frame_read(sock) 1024 self.check_frame(frame, True, self.ws.OP_PONG, 'pongme 2!') 1025 1026 assert self.recvall(sock, read_timeout=0.1) == b'', '5_20' 1027 self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment5') 1028 1029 self.check_frame( 1030 self.ws.frame_read(sock), 1031 True, 1032 self.ws.OP_TEXT, 1033 'fragment1fragment2fragment3fragment4fragment5', 1034 ) 1035 1036 self.close_connection(sock) 1037 1038 def test_asgi_websockets_6_1_1__6_4_4(self): 1039 self.load('websockets/mirror') 1040 1041 # 6_1_1 1042 1043 _, sock, _ = self.ws.upgrade() 1044 1045 self.ws.frame_write(sock, self.ws.OP_TEXT, '') 1046 frame = self.ws.frame_read(sock) 1047 self.check_frame(frame, True, self.ws.OP_TEXT, '') 1048 1049 # 6_1_2 1050 1051 self.ws.frame_write(sock, self.ws.OP_TEXT, '', fin=False) 1052 self.ws.frame_write(sock, self.ws.OP_CONT, '', fin=False) 1053 self.ws.frame_write(sock, self.ws.OP_CONT, '') 1054 1055 frame = self.ws.frame_read(sock) 1056 self.check_frame(frame, True, self.ws.OP_TEXT, '') 1057 1058 # 6_1_3 1059 1060 payload = 'middle frame payload' 1061 1062 self.ws.frame_write(sock, self.ws.OP_TEXT, '', fin=False) 1063 self.ws.frame_write(sock, self.ws.OP_CONT, payload, fin=False) 1064 self.ws.frame_write(sock, self.ws.OP_CONT, '') 1065 1066 frame = self.ws.frame_read(sock) 1067 self.check_frame(frame, True, self.ws.OP_TEXT, payload) 1068 1069 # 6_2_1 1070 1071 payload = 'Hello-µ@ßöäüàá-UTF-8!!' 1072 1073 self.ws.frame_write(sock, self.ws.OP_TEXT, payload) 1074 1075 frame = self.ws.frame_read(sock) 1076 self.check_frame(frame, True, self.ws.OP_TEXT, payload) 1077 1078 # 6_2_2 1079 1080 self.ws.frame_write(sock, self.ws.OP_TEXT, payload[:12], fin=False) 1081 self.ws.frame_write(sock, self.ws.OP_CONT, payload[12:]) 1082 1083 frame = self.ws.frame_read(sock) 1084 self.check_frame(frame, True, self.ws.OP_TEXT, payload) 1085 1086 # 6_2_3 1087 1088 self.ws.message(sock, self.ws.OP_TEXT, payload, fragmention_size=1) 1089 1090 frame = self.ws.frame_read(sock) 1091 self.check_frame(frame, True, self.ws.OP_TEXT, payload) 1092 1093 # 6_2_4 1094 1095 payload = '\xce\xba\xe1\xbd\xb9\xcf\x83\xce\xbc\xce\xb5' 1096 1097 self.ws.message(sock, self.ws.OP_TEXT, payload, fragmention_size=1) 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 # Unit does not support UTF-8 validation 1105 # 1106 # # 6_3_1 FAIL 1107 # 1108 # payload_1 = '\xce\xba\xe1\xbd\xb9\xcf\x83\xce\xbc\xce\xb5' 1109 # payload_2 = '\xed\xa0\x80' 1110 # payload_3 = '\x65\x64\x69\x74\x65\x64' 1111 # 1112 # payload = payload_1 + payload_2 + payload_3 1113 # 1114 # self.ws.message(sock, self.ws.OP_TEXT, payload) 1115 # self.check_close(sock, 1007) 1116 # 1117 # # 6_3_2 FAIL 1118 # 1119 # _, sock, _ = self.ws.upgrade() 1120 # 1121 # self.ws.message(sock, self.ws.OP_TEXT, payload, fragmention_size=1) 1122 # self.check_close(sock, 1007) 1123 # 1124 # # 6_4_1 ... 6_4_4 FAIL 1125 1126 def test_asgi_websockets_7_1_1__7_5_1(self): 1127 self.load('websockets/mirror') 1128 1129 # 7_1_1 1130 1131 _, sock, _ = self.ws.upgrade() 1132 1133 payload = "Hello World!" 1134 1135 self.ws.frame_write(sock, self.ws.OP_TEXT, payload) 1136 1137 frame = self.ws.frame_read(sock) 1138 self.check_frame(frame, True, self.ws.OP_TEXT, payload) 1139 1140 self.close_connection(sock) 1141 1142 # 7_1_2 1143 1144 _, sock, _ = self.ws.upgrade() 1145 1146 self.ws.frame_write(sock, self.ws.OP_CLOSE, self.ws.serialize_close()) 1147 self.ws.frame_write(sock, self.ws.OP_CLOSE, self.ws.serialize_close()) 1148 1149 self.check_close(sock) 1150 1151 # 7_1_3 1152 1153 _, sock, _ = self.ws.upgrade() 1154 1155 self.ws.frame_write(sock, self.ws.OP_CLOSE, self.ws.serialize_close()) 1156 self.check_close(sock, no_close=True) 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_1_4 1164 1165 _, sock, _ = self.ws.upgrade() 1166 1167 self.ws.frame_write(sock, self.ws.OP_CLOSE, self.ws.serialize_close()) 1168 self.check_close(sock, no_close=True) 1169 1170 self.ws.frame_write(sock, self.ws.OP_TEXT, payload) 1171 assert self.recvall(sock, read_timeout=0.1) == b'', 'empty soc' 1172 1173 sock.close() 1174 1175 # 7_1_5 1176 1177 _, sock, _ = self.ws.upgrade() 1178 1179 self.ws.frame_write(sock, self.ws.OP_TEXT, 'fragment1', fin=False) 1180 self.ws.frame_write(sock, self.ws.OP_CLOSE, self.ws.serialize_close()) 1181 self.check_close(sock, no_close=True) 1182 1183 self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment2') 1184 assert self.recvall(sock, read_timeout=0.1) == b'', 'empty soc' 1185 1186 sock.close() 1187 1188 # 7_1_6 1189 1190 _, sock, _ = self.ws.upgrade() 1191 1192 self.ws.frame_write(sock, self.ws.OP_TEXT, 'BAsd7&jh23' * 26 * 2 ** 10) 1193 self.ws.frame_write(sock, self.ws.OP_TEXT, payload) 1194 self.ws.frame_write(sock, self.ws.OP_CLOSE, self.ws.serialize_close()) 1195 1196 self.recvall(sock, read_timeout=1) 1197 1198 self.ws.frame_write(sock, self.ws.OP_PING, '') 1199 assert self.recvall(sock, read_timeout=0.1) == b'', 'empty soc' 1200 1201 sock.close() 1202 1203 # 7_3_1 1204 1205 _, sock, _ = self.ws.upgrade() 1206 1207 self.ws.frame_write(sock, self.ws.OP_CLOSE, '') 1208 self.check_close(sock) 1209 1210 # 7_3_2 1211 1212 _, sock, _ = self.ws.upgrade() 1213 1214 self.ws.frame_write(sock, self.ws.OP_CLOSE, 'a') 1215 self.check_close(sock, 1002) 1216 1217 # 7_3_3 1218 1219 _, sock, _ = self.ws.upgrade() 1220 1221 self.ws.frame_write(sock, self.ws.OP_CLOSE, self.ws.serialize_close()) 1222 self.check_close(sock) 1223 1224 # 7_3_4 1225 1226 _, sock, _ = self.ws.upgrade() 1227 1228 payload = self.ws.serialize_close(reason='Hello World!') 1229 1230 self.ws.frame_write(sock, self.ws.OP_CLOSE, payload) 1231 self.check_close(sock) 1232 1233 # 7_3_5 1234 1235 _, sock, _ = self.ws.upgrade() 1236 1237 payload = self.ws.serialize_close(reason='*' * 123) 1238 1239 self.ws.frame_write(sock, self.ws.OP_CLOSE, payload) 1240 self.check_close(sock) 1241 1242 # 7_3_6 1243 1244 _, sock, _ = self.ws.upgrade() 1245 1246 payload = self.ws.serialize_close(reason='*' * 124) 1247 1248 self.ws.frame_write(sock, self.ws.OP_CLOSE, payload) 1249 self.check_close(sock, 1002) 1250 1251 # # 7_5_1 FAIL Unit does not support UTF-8 validation 1252 # 1253 # _, sock, _ = self.ws.upgrade() 1254 # 1255 # payload = self.ws.serialize_close(reason = '\xce\xba\xe1\xbd\xb9\xcf' \ 1256 # '\x83\xce\xbc\xce\xb5\xed\xa0\x80\x65\x64\x69\x74\x65\x64') 1257 # 1258 # self.ws.frame_write(sock, self.ws.OP_CLOSE, payload) 1259 # self.check_close(sock, 1007) 1260 1261 def test_asgi_websockets_7_7_X__7_9_X(self): 1262 self.load('websockets/mirror') 1263 1264 valid_codes = [ 1265 1000, 1266 1001, 1267 1002, 1268 1003, 1269 1007, 1270 1008, 1271 1009, 1272 1010, 1273 1011, 1274 3000, 1275 3999, 1276 4000, 1277 4999, 1278 ] 1279 1280 invalid_codes = [0, 999, 1004, 1005, 1006, 1016, 1100, 2000, 2999] 1281 1282 for code in valid_codes: 1283 _, sock, _ = self.ws.upgrade() 1284 1285 payload = self.ws.serialize_close(code=code) 1286 1287 self.ws.frame_write(sock, self.ws.OP_CLOSE, payload) 1288 self.check_close(sock) 1289 1290 for code in invalid_codes: 1291 _, sock, _ = self.ws.upgrade() 1292 1293 payload = self.ws.serialize_close(code=code) 1294 1295 self.ws.frame_write(sock, self.ws.OP_CLOSE, payload) 1296 self.check_close(sock, 1002) 1297 1298 def test_asgi_websockets_7_13_1__7_13_2(self): 1299 self.load('websockets/mirror') 1300 1301 # 7_13_1 1302 1303 _, sock, _ = self.ws.upgrade() 1304 1305 payload = self.ws.serialize_close(code=5000) 1306 1307 self.ws.frame_write(sock, self.ws.OP_CLOSE, payload) 1308 self.check_close(sock, 1002) 1309 1310 # 7_13_2 1311 1312 _, sock, _ = self.ws.upgrade() 1313 1314 payload = struct.pack('!I', 65536) + ''.encode('utf-8') 1315 1316 self.ws.frame_write(sock, self.ws.OP_CLOSE, payload) 1317 self.check_close(sock, 1002) 1318 1319 def test_asgi_websockets_9_1_1__9_6_6(self, is_unsafe): 1320 if not is_unsafe: 1321 pytest.skip('unsafe, long run') 1322 1323 self.load('websockets/mirror') 1324 1325 assert 'success' in self.conf( 1326 { 1327 'http': { 1328 'websocket': { 1329 'max_frame_size': 33554432, 1330 'keepalive_interval': 0, 1331 } 1332 } 1333 }, 1334 'settings', 1335 ), 'increase max_frame_size and keepalive_interval' 1336 1337 _, sock, _ = self.ws.upgrade() 1338 1339 op_text = self.ws.OP_TEXT 1340 op_binary = self.ws.OP_BINARY 1341 1342 def check_payload(opcode, length, chopsize=None): 1343 if opcode == self.ws.OP_TEXT: 1344 payload = '*' * length 1345 else: 1346 payload = b'*' * length 1347 1348 self.ws.frame_write(sock, opcode, payload, chopsize=chopsize) 1349 frame = self.ws.frame_read(sock, read_timeout=5) 1350 self.check_frame(frame, True, opcode, payload) 1351 1352 def check_message(opcode, f_size): 1353 if opcode == self.ws.OP_TEXT: 1354 payload = '*' * 4 * 2 ** 20 1355 else: 1356 payload = b'*' * 4 * 2 ** 20 1357 1358 self.ws.message(sock, opcode, payload, fragmention_size=f_size) 1359 frame = self.ws.frame_read(sock, read_timeout=5) 1360 self.check_frame(frame, True, opcode, payload) 1361 1362 check_payload(op_text, 64 * 2 ** 10) # 9_1_1 1363 check_payload(op_text, 256 * 2 ** 10) # 9_1_2 1364 check_payload(op_text, 2 ** 20) # 9_1_3 1365 check_payload(op_text, 4 * 2 ** 20) # 9_1_4 1366 check_payload(op_text, 8 * 2 ** 20) # 9_1_5 1367 check_payload(op_text, 16 * 2 ** 20) # 9_1_6 1368 1369 check_payload(op_binary, 64 * 2 ** 10) # 9_2_1 1370 check_payload(op_binary, 256 * 2 ** 10) # 9_2_2 1371 check_payload(op_binary, 2 ** 20) # 9_2_3 1372 check_payload(op_binary, 4 * 2 ** 20) # 9_2_4 1373 check_payload(op_binary, 8 * 2 ** 20) # 9_2_5 1374 check_payload(op_binary, 16 * 2 ** 20) # 9_2_6 1375 1376 if option.system != 'Darwin' and option.system != 'FreeBSD': 1377 check_message(op_text, 64) # 9_3_1 1378 check_message(op_text, 256) # 9_3_2 1379 check_message(op_text, 2 ** 10) # 9_3_3 1380 check_message(op_text, 4 * 2 ** 10) # 9_3_4 1381 check_message(op_text, 16 * 2 ** 10) # 9_3_5 1382 check_message(op_text, 64 * 2 ** 10) # 9_3_6 1383 check_message(op_text, 256 * 2 ** 10) # 9_3_7 1384 check_message(op_text, 2 ** 20) # 9_3_8 1385 check_message(op_text, 4 * 2 ** 20) # 9_3_9 1386 1387 check_message(op_binary, 64) # 9_4_1 1388 check_message(op_binary, 256) # 9_4_2 1389 check_message(op_binary, 2 ** 10) # 9_4_3 1390 check_message(op_binary, 4 * 2 ** 10) # 9_4_4 1391 check_message(op_binary, 16 * 2 ** 10) # 9_4_5 1392 check_message(op_binary, 64 * 2 ** 10) # 9_4_6 1393 check_message(op_binary, 256 * 2 ** 10) # 9_4_7 1394 check_message(op_binary, 2 ** 20) # 9_4_8 1395 check_message(op_binary, 4 * 2 ** 20) # 9_4_9 1396 1397 check_payload(op_text, 2 ** 20, chopsize=64) # 9_5_1 1398 check_payload(op_text, 2 ** 20, chopsize=128) # 9_5_2 1399 check_payload(op_text, 2 ** 20, chopsize=256) # 9_5_3 1400 check_payload(op_text, 2 ** 20, chopsize=512) # 9_5_4 1401 check_payload(op_text, 2 ** 20, chopsize=1024) # 9_5_5 1402 check_payload(op_text, 2 ** 20, chopsize=2048) # 9_5_6 1403 1404 check_payload(op_binary, 2 ** 20, chopsize=64) # 9_6_1 1405 check_payload(op_binary, 2 ** 20, chopsize=128) # 9_6_2 1406 check_payload(op_binary, 2 ** 20, chopsize=256) # 9_6_3 1407 check_payload(op_binary, 2 ** 20, chopsize=512) # 9_6_4 1408 check_payload(op_binary, 2 ** 20, chopsize=1024) # 9_6_5 1409 check_payload(op_binary, 2 ** 20, chopsize=2048) # 9_6_6 1410 1411 self.close_connection(sock) 1412 1413 def test_asgi_websockets_10_1_1(self): 1414 self.load('websockets/mirror') 1415 1416 _, sock, _ = self.ws.upgrade() 1417 1418 payload = '*' * 65536 1419 1420 self.ws.message(sock, self.ws.OP_TEXT, payload, fragmention_size=1300) 1421 1422 frame = self.ws.frame_read(sock) 1423 self.check_frame(frame, True, self.ws.OP_TEXT, payload) 1424 1425 self.close_connection(sock) 1426 1427 # settings 1428 1429 def test_asgi_websockets_max_frame_size(self): 1430 self.load('websockets/mirror') 1431 1432 assert 'success' in self.conf( 1433 {'http': {'websocket': {'max_frame_size': 100}}}, 'settings' 1434 ), 'configure max_frame_size' 1435 1436 _, sock, _ = self.ws.upgrade() 1437 1438 payload = '*' * 94 1439 opcode = self.ws.OP_TEXT 1440 1441 self.ws.frame_write(sock, opcode, payload) # frame length is 100 1442 1443 frame = self.ws.frame_read(sock) 1444 self.check_frame(frame, True, opcode, payload) 1445 1446 payload = '*' * 95 1447 1448 self.ws.frame_write(sock, opcode, payload) # frame length is 101 1449 self.check_close(sock, 1009) # 1009 - CLOSE_TOO_LARGE 1450 1451 def test_asgi_websockets_read_timeout(self): 1452 self.load('websockets/mirror') 1453 1454 assert 'success' in self.conf( 1455 {'http': {'websocket': {'read_timeout': 5}}}, 'settings' 1456 ), 'configure read_timeout' 1457 1458 _, sock, _ = self.ws.upgrade() 1459 1460 frame = self.ws.frame_to_send(self.ws.OP_TEXT, 'blah') 1461 sock.sendall(frame[:2]) 1462 1463 time.sleep(2) 1464 1465 self.check_close(sock, 1001) # 1001 - CLOSE_GOING_AWAY 1466 1467 def test_asgi_websockets_keepalive_interval(self): 1468 self.load('websockets/mirror') 1469 1470 assert 'success' in self.conf( 1471 {'http': {'websocket': {'keepalive_interval': 5}}}, 'settings' 1472 ), 'configure keepalive_interval' 1473 1474 _, sock, _ = self.ws.upgrade() 1475 1476 frame = self.ws.frame_to_send(self.ws.OP_TEXT, 'blah') 1477 sock.sendall(frame[:2]) 1478 1479 time.sleep(2) 1480 1481 frame = self.ws.frame_read(sock) 1482 self.check_frame(frame, True, self.ws.OP_PING, '') # PING frame 1483 1484 sock.close() 1485 1486 def test_asgi_websockets_client_locks_app(self): 1487 self.load('websockets/mirror') 1488 1489 message = 'blah' 1490 1491 _, sock, _ = self.ws.upgrade() 1492 1493 assert 'success' in self.conf({}), 'remove app' 1494 1495 self.ws.frame_write(sock, self.ws.OP_TEXT, message) 1496 1497 frame = self.ws.frame_read(sock) 1498 1499 assert message == frame['data'].decode('utf-8'), 'client' 1500 1501 sock.close() 1502