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