11625Smax.romanov@nginx.comimport struct 21625Smax.romanov@nginx.comimport time 31625Smax.romanov@nginx.com 41635Szelenkov@nginx.comimport pytest 52066Szelenkov@nginx.comfrom packaging import version 61625Smax.romanov@nginx.comfrom unit.applications.lang.python import TestApplicationPython 71625Smax.romanov@nginx.comfrom unit.applications.websockets import TestApplicationWebsocket 81730Szelenkov@nginx.comfrom unit.option import option 91625Smax.romanov@nginx.com 101625Smax.romanov@nginx.com 111625Smax.romanov@nginx.comclass TestASGIWebsockets(TestApplicationPython): 121848Szelenkov@nginx.com prerequisites = { 132066Szelenkov@nginx.com 'modules': { 142066Szelenkov@nginx.com 'python': lambda v: version.parse(v) >= version.parse('3.5') 152066Szelenkov@nginx.com } 161848Szelenkov@nginx.com } 171625Smax.romanov@nginx.com load_module = 'asgi' 181625Smax.romanov@nginx.com 191625Smax.romanov@nginx.com ws = TestApplicationWebsocket() 201625Smax.romanov@nginx.com 211736Szelenkov@nginx.com @pytest.fixture(autouse=True) 221736Szelenkov@nginx.com def setup_method_fixture(self, request, skip_alert): 231625Smax.romanov@nginx.com assert 'success' in self.conf( 241625Smax.romanov@nginx.com {'http': {'websocket': {'keepalive_interval': 0}}}, 'settings' 251625Smax.romanov@nginx.com ), 'clear keepalive_interval' 261625Smax.romanov@nginx.com 271625Smax.romanov@nginx.com skip_alert(r'socket close\(\d+\) failed') 281625Smax.romanov@nginx.com 291625Smax.romanov@nginx.com def close_connection(self, sock): 301625Smax.romanov@nginx.com assert self.recvall(sock, read_timeout=0.1) == b'', 'empty soc' 311625Smax.romanov@nginx.com 321625Smax.romanov@nginx.com self.ws.frame_write(sock, self.ws.OP_CLOSE, self.ws.serialize_close()) 331625Smax.romanov@nginx.com 341625Smax.romanov@nginx.com self.check_close(sock) 351625Smax.romanov@nginx.com 361819Smax.romanov@nginx.com def check_close(self, sock, code=1000, no_close=False, frame=None): 371819Smax.romanov@nginx.com if frame == None: 381819Smax.romanov@nginx.com frame = self.ws.frame_read(sock) 391625Smax.romanov@nginx.com 401625Smax.romanov@nginx.com assert frame['fin'] == True, 'close fin' 411625Smax.romanov@nginx.com assert frame['opcode'] == self.ws.OP_CLOSE, 'close opcode' 421625Smax.romanov@nginx.com assert frame['code'] == code, 'close code' 431625Smax.romanov@nginx.com 441625Smax.romanov@nginx.com if not no_close: 451625Smax.romanov@nginx.com sock.close() 461625Smax.romanov@nginx.com 471625Smax.romanov@nginx.com def check_frame(self, frame, fin, opcode, payload, decode=True): 481625Smax.romanov@nginx.com if opcode == self.ws.OP_BINARY or not decode: 491625Smax.romanov@nginx.com data = frame['data'] 501625Smax.romanov@nginx.com else: 511625Smax.romanov@nginx.com data = frame['data'].decode('utf-8') 521625Smax.romanov@nginx.com 531625Smax.romanov@nginx.com assert frame['fin'] == fin, 'fin' 541625Smax.romanov@nginx.com assert frame['opcode'] == opcode, 'opcode' 551625Smax.romanov@nginx.com assert data == payload, 'payload' 561625Smax.romanov@nginx.com 571625Smax.romanov@nginx.com def test_asgi_websockets_handshake(self): 581625Smax.romanov@nginx.com self.load('websockets/mirror') 591625Smax.romanov@nginx.com 601625Smax.romanov@nginx.com resp, sock, key = self.ws.upgrade() 611625Smax.romanov@nginx.com sock.close() 621625Smax.romanov@nginx.com 631625Smax.romanov@nginx.com assert resp['status'] == 101, 'status' 641625Smax.romanov@nginx.com assert resp['headers']['Upgrade'] == 'websocket', 'upgrade' 651625Smax.romanov@nginx.com assert resp['headers']['Connection'] == 'Upgrade', 'connection' 661625Smax.romanov@nginx.com assert resp['headers']['Sec-WebSocket-Accept'] == self.ws.accept( 671625Smax.romanov@nginx.com key 681625Smax.romanov@nginx.com ), 'key' 691625Smax.romanov@nginx.com 701780Smax.romanov@nginx.com # remove "mirror" application 711780Smax.romanov@nginx.com self.load('websockets/subprotocol') 721780Smax.romanov@nginx.com 731625Smax.romanov@nginx.com def test_asgi_websockets_subprotocol(self): 741625Smax.romanov@nginx.com self.load('websockets/subprotocol') 751625Smax.romanov@nginx.com 761625Smax.romanov@nginx.com resp, sock, key = self.ws.upgrade() 771625Smax.romanov@nginx.com sock.close() 781625Smax.romanov@nginx.com 791625Smax.romanov@nginx.com assert resp['status'] == 101, 'status' 801848Szelenkov@nginx.com assert ( 811848Szelenkov@nginx.com resp['headers']['x-subprotocols'] == "('chat', 'phone', 'video')" 821848Szelenkov@nginx.com ), 'subprotocols' 831625Smax.romanov@nginx.com assert resp['headers']['sec-websocket-protocol'] == 'chat', 'key' 841625Smax.romanov@nginx.com 851625Smax.romanov@nginx.com def test_asgi_websockets_mirror(self): 861625Smax.romanov@nginx.com self.load('websockets/mirror') 871625Smax.romanov@nginx.com 881625Smax.romanov@nginx.com message = 'blah' 891625Smax.romanov@nginx.com 901625Smax.romanov@nginx.com _, sock, _ = self.ws.upgrade() 911625Smax.romanov@nginx.com 921625Smax.romanov@nginx.com self.ws.frame_write(sock, self.ws.OP_TEXT, message) 931625Smax.romanov@nginx.com frame = self.ws.frame_read(sock) 941625Smax.romanov@nginx.com 951625Smax.romanov@nginx.com assert message == frame['data'].decode('utf-8'), 'mirror' 961625Smax.romanov@nginx.com 971625Smax.romanov@nginx.com self.ws.frame_write(sock, self.ws.OP_TEXT, message) 981625Smax.romanov@nginx.com frame = self.ws.frame_read(sock) 991625Smax.romanov@nginx.com 1001625Smax.romanov@nginx.com assert message == frame['data'].decode('utf-8'), 'mirror 2' 1011625Smax.romanov@nginx.com 1021625Smax.romanov@nginx.com sock.close() 1031625Smax.romanov@nginx.com 1041780Smax.romanov@nginx.com def test_asgi_websockets_mirror_app_change(self): 1051780Smax.romanov@nginx.com self.load('websockets/mirror') 1061780Smax.romanov@nginx.com 1071780Smax.romanov@nginx.com message = 'blah' 1081780Smax.romanov@nginx.com 1091780Smax.romanov@nginx.com _, sock, _ = self.ws.upgrade() 1101780Smax.romanov@nginx.com 1111780Smax.romanov@nginx.com self.ws.frame_write(sock, self.ws.OP_TEXT, message) 1121780Smax.romanov@nginx.com frame = self.ws.frame_read(sock) 1131780Smax.romanov@nginx.com 1141780Smax.romanov@nginx.com assert message == frame['data'].decode('utf-8'), 'mirror' 1151780Smax.romanov@nginx.com 1161780Smax.romanov@nginx.com self.load('websockets/subprotocol') 1171780Smax.romanov@nginx.com 1181780Smax.romanov@nginx.com self.ws.frame_write(sock, self.ws.OP_TEXT, message) 1191780Smax.romanov@nginx.com frame = self.ws.frame_read(sock) 1201780Smax.romanov@nginx.com 1211780Smax.romanov@nginx.com assert message == frame['data'].decode('utf-8'), 'mirror 2' 1221780Smax.romanov@nginx.com 1231780Smax.romanov@nginx.com sock.close() 1241780Smax.romanov@nginx.com 1251625Smax.romanov@nginx.com def test_asgi_websockets_no_mask(self): 1261625Smax.romanov@nginx.com self.load('websockets/mirror') 1271625Smax.romanov@nginx.com 1281625Smax.romanov@nginx.com message = 'blah' 1291625Smax.romanov@nginx.com 1301625Smax.romanov@nginx.com _, sock, _ = self.ws.upgrade() 1311625Smax.romanov@nginx.com 1321625Smax.romanov@nginx.com self.ws.frame_write(sock, self.ws.OP_TEXT, message, mask=False) 1331625Smax.romanov@nginx.com 1341625Smax.romanov@nginx.com frame = self.ws.frame_read(sock) 1351625Smax.romanov@nginx.com 1361625Smax.romanov@nginx.com assert frame['opcode'] == self.ws.OP_CLOSE, 'no mask opcode' 1371625Smax.romanov@nginx.com assert frame['code'] == 1002, 'no mask close code' 1381625Smax.romanov@nginx.com 1391625Smax.romanov@nginx.com sock.close() 1401625Smax.romanov@nginx.com 1411625Smax.romanov@nginx.com def test_asgi_websockets_fragmentation(self): 1421625Smax.romanov@nginx.com self.load('websockets/mirror') 1431625Smax.romanov@nginx.com 1441625Smax.romanov@nginx.com message = 'blah' 1451625Smax.romanov@nginx.com 1461625Smax.romanov@nginx.com _, sock, _ = self.ws.upgrade() 1471625Smax.romanov@nginx.com 1481625Smax.romanov@nginx.com self.ws.frame_write(sock, self.ws.OP_TEXT, message, fin=False) 1491625Smax.romanov@nginx.com self.ws.frame_write(sock, self.ws.OP_CONT, ' ', fin=False) 1501625Smax.romanov@nginx.com self.ws.frame_write(sock, self.ws.OP_CONT, message) 1511625Smax.romanov@nginx.com 1521625Smax.romanov@nginx.com frame = self.ws.frame_read(sock) 1531625Smax.romanov@nginx.com 1541625Smax.romanov@nginx.com assert message + ' ' + message == frame['data'].decode( 1551625Smax.romanov@nginx.com 'utf-8' 1561625Smax.romanov@nginx.com ), 'mirror framing' 1571625Smax.romanov@nginx.com 1581625Smax.romanov@nginx.com sock.close() 1591625Smax.romanov@nginx.com 1601629Szelenkov@nginx.com def test_asgi_websockets_length_long(self): 1611629Szelenkov@nginx.com self.load('websockets/mirror') 1621629Szelenkov@nginx.com 1631629Szelenkov@nginx.com _, sock, _ = self.ws.upgrade() 1641629Szelenkov@nginx.com 1651629Szelenkov@nginx.com self.ws.frame_write(sock, self.ws.OP_TEXT, 'fragment1', fin=False) 1661629Szelenkov@nginx.com self.ws.frame_write( 167*2073Szelenkov@nginx.com sock, self.ws.OP_CONT, 'fragment2', length=2**64 - 1 1681629Szelenkov@nginx.com ) 1691629Szelenkov@nginx.com 1701629Szelenkov@nginx.com self.check_close(sock, 1009) # 1009 - CLOSE_TOO_LARGE 1711629Szelenkov@nginx.com 1721625Smax.romanov@nginx.com def test_asgi_websockets_frame_fragmentation_invalid(self): 1731625Smax.romanov@nginx.com self.load('websockets/mirror') 1741625Smax.romanov@nginx.com 1751625Smax.romanov@nginx.com message = 'blah' 1761625Smax.romanov@nginx.com 1771625Smax.romanov@nginx.com _, sock, _ = self.ws.upgrade() 1781625Smax.romanov@nginx.com 1791625Smax.romanov@nginx.com self.ws.frame_write(sock, self.ws.OP_PING, message, fin=False) 1801625Smax.romanov@nginx.com 1811625Smax.romanov@nginx.com frame = self.ws.frame_read(sock) 1821625Smax.romanov@nginx.com 1831625Smax.romanov@nginx.com frame.pop('data') 1841625Smax.romanov@nginx.com assert frame == { 1851625Smax.romanov@nginx.com 'fin': True, 1861625Smax.romanov@nginx.com 'rsv1': False, 1871625Smax.romanov@nginx.com 'rsv2': False, 1881625Smax.romanov@nginx.com 'rsv3': False, 1891625Smax.romanov@nginx.com 'opcode': self.ws.OP_CLOSE, 1901625Smax.romanov@nginx.com 'mask': 0, 1911625Smax.romanov@nginx.com 'code': 1002, 1921625Smax.romanov@nginx.com 'reason': 'Fragmented control frame', 1931625Smax.romanov@nginx.com }, 'close frame' 1941625Smax.romanov@nginx.com 1951625Smax.romanov@nginx.com sock.close() 1961625Smax.romanov@nginx.com 1971625Smax.romanov@nginx.com def test_asgi_websockets_large(self): 1981625Smax.romanov@nginx.com self.load('websockets/mirror') 1991625Smax.romanov@nginx.com 2001625Smax.romanov@nginx.com message = '0123456789' * 300 2011625Smax.romanov@nginx.com 2021625Smax.romanov@nginx.com _, sock, _ = self.ws.upgrade() 2031625Smax.romanov@nginx.com 2041625Smax.romanov@nginx.com self.ws.frame_write(sock, self.ws.OP_TEXT, message) 2051625Smax.romanov@nginx.com 2061625Smax.romanov@nginx.com frame = self.ws.frame_read(sock) 2071625Smax.romanov@nginx.com data = frame['data'].decode('utf-8') 2081625Smax.romanov@nginx.com 2091625Smax.romanov@nginx.com frame = self.ws.frame_read(sock) 2101625Smax.romanov@nginx.com data += frame['data'].decode('utf-8') 2111625Smax.romanov@nginx.com 2121625Smax.romanov@nginx.com assert message == data, 'large' 2131625Smax.romanov@nginx.com 2141625Smax.romanov@nginx.com sock.close() 2151625Smax.romanov@nginx.com 2161625Smax.romanov@nginx.com def test_asgi_websockets_two_clients(self): 2171625Smax.romanov@nginx.com self.load('websockets/mirror') 2181625Smax.romanov@nginx.com 2191625Smax.romanov@nginx.com message1 = 'blah1' 2201625Smax.romanov@nginx.com message2 = 'blah2' 2211625Smax.romanov@nginx.com 2221625Smax.romanov@nginx.com _, sock1, _ = self.ws.upgrade() 2231625Smax.romanov@nginx.com _, sock2, _ = self.ws.upgrade() 2241625Smax.romanov@nginx.com 2251625Smax.romanov@nginx.com self.ws.frame_write(sock1, self.ws.OP_TEXT, message1) 2261625Smax.romanov@nginx.com self.ws.frame_write(sock2, self.ws.OP_TEXT, message2) 2271625Smax.romanov@nginx.com 2281625Smax.romanov@nginx.com frame1 = self.ws.frame_read(sock1) 2291625Smax.romanov@nginx.com frame2 = self.ws.frame_read(sock2) 2301625Smax.romanov@nginx.com 2311625Smax.romanov@nginx.com assert message1 == frame1['data'].decode('utf-8'), 'client 1' 2321625Smax.romanov@nginx.com assert message2 == frame2['data'].decode('utf-8'), 'client 2' 2331625Smax.romanov@nginx.com 2341625Smax.romanov@nginx.com sock1.close() 2351625Smax.romanov@nginx.com sock2.close() 2361625Smax.romanov@nginx.com 2371625Smax.romanov@nginx.com @pytest.mark.skip('not yet') 2381625Smax.romanov@nginx.com def test_asgi_websockets_handshake_upgrade_absent( 2391848Szelenkov@nginx.com self, 2401625Smax.romanov@nginx.com ): # FAIL https://tools.ietf.org/html/rfc6455#section-4.2.1 2411625Smax.romanov@nginx.com self.load('websockets/mirror') 2421625Smax.romanov@nginx.com 2431625Smax.romanov@nginx.com resp = self.get( 2441625Smax.romanov@nginx.com headers={ 2451625Smax.romanov@nginx.com 'Host': 'localhost', 2461625Smax.romanov@nginx.com 'Connection': 'Upgrade', 2471625Smax.romanov@nginx.com 'Sec-WebSocket-Key': self.ws.key(), 2481625Smax.romanov@nginx.com 'Sec-WebSocket-Protocol': 'chat', 2491625Smax.romanov@nginx.com 'Sec-WebSocket-Version': 13, 2501625Smax.romanov@nginx.com }, 2511625Smax.romanov@nginx.com ) 2521625Smax.romanov@nginx.com 2531625Smax.romanov@nginx.com assert resp['status'] == 400, 'upgrade absent' 2541625Smax.romanov@nginx.com 2551625Smax.romanov@nginx.com def test_asgi_websockets_handshake_case_insensitive(self): 2561625Smax.romanov@nginx.com self.load('websockets/mirror') 2571625Smax.romanov@nginx.com 2581625Smax.romanov@nginx.com resp, sock, _ = self.ws.upgrade( 2591625Smax.romanov@nginx.com headers={ 2601625Smax.romanov@nginx.com 'Host': 'localhost', 2611625Smax.romanov@nginx.com 'Upgrade': 'WEBSOCKET', 2621625Smax.romanov@nginx.com 'Connection': 'UPGRADE', 2631625Smax.romanov@nginx.com 'Sec-WebSocket-Key': self.ws.key(), 2641625Smax.romanov@nginx.com 'Sec-WebSocket-Protocol': 'chat', 2651625Smax.romanov@nginx.com 'Sec-WebSocket-Version': 13, 2661625Smax.romanov@nginx.com } 2671625Smax.romanov@nginx.com ) 2681625Smax.romanov@nginx.com sock.close() 2691625Smax.romanov@nginx.com 2701625Smax.romanov@nginx.com assert resp['status'] == 101, 'status' 2711625Smax.romanov@nginx.com 2721625Smax.romanov@nginx.com @pytest.mark.skip('not yet') 2731625Smax.romanov@nginx.com def test_asgi_websockets_handshake_connection_absent(self): # FAIL 2741625Smax.romanov@nginx.com self.load('websockets/mirror') 2751625Smax.romanov@nginx.com 2761625Smax.romanov@nginx.com resp = self.get( 2771625Smax.romanov@nginx.com headers={ 2781625Smax.romanov@nginx.com 'Host': 'localhost', 2791625Smax.romanov@nginx.com 'Upgrade': 'websocket', 2801625Smax.romanov@nginx.com 'Sec-WebSocket-Key': self.ws.key(), 2811625Smax.romanov@nginx.com 'Sec-WebSocket-Protocol': 'chat', 2821625Smax.romanov@nginx.com 'Sec-WebSocket-Version': 13, 2831625Smax.romanov@nginx.com }, 2841625Smax.romanov@nginx.com ) 2851625Smax.romanov@nginx.com 2861625Smax.romanov@nginx.com assert resp['status'] == 400, 'status' 2871625Smax.romanov@nginx.com 2881625Smax.romanov@nginx.com def test_asgi_websockets_handshake_version_absent(self): 2891625Smax.romanov@nginx.com self.load('websockets/mirror') 2901625Smax.romanov@nginx.com 2911625Smax.romanov@nginx.com resp = self.get( 2921625Smax.romanov@nginx.com headers={ 2931625Smax.romanov@nginx.com 'Host': 'localhost', 2941625Smax.romanov@nginx.com 'Upgrade': 'websocket', 2951625Smax.romanov@nginx.com 'Connection': 'Upgrade', 2961625Smax.romanov@nginx.com 'Sec-WebSocket-Key': self.ws.key(), 2971625Smax.romanov@nginx.com 'Sec-WebSocket-Protocol': 'chat', 2981625Smax.romanov@nginx.com }, 2991625Smax.romanov@nginx.com ) 3001625Smax.romanov@nginx.com 3011625Smax.romanov@nginx.com assert resp['status'] == 426, 'status' 3021625Smax.romanov@nginx.com 3031625Smax.romanov@nginx.com @pytest.mark.skip('not yet') 3041625Smax.romanov@nginx.com def test_asgi_websockets_handshake_key_invalid(self): 3051625Smax.romanov@nginx.com self.load('websockets/mirror') 3061625Smax.romanov@nginx.com 3071625Smax.romanov@nginx.com resp = self.get( 3081625Smax.romanov@nginx.com headers={ 3091625Smax.romanov@nginx.com 'Host': 'localhost', 3101625Smax.romanov@nginx.com 'Upgrade': 'websocket', 3111625Smax.romanov@nginx.com 'Connection': 'Upgrade', 3121625Smax.romanov@nginx.com 'Sec-WebSocket-Key': '!', 3131625Smax.romanov@nginx.com 'Sec-WebSocket-Protocol': 'chat', 3141625Smax.romanov@nginx.com 'Sec-WebSocket-Version': 13, 3151625Smax.romanov@nginx.com }, 3161625Smax.romanov@nginx.com ) 3171625Smax.romanov@nginx.com 3181625Smax.romanov@nginx.com assert resp['status'] == 400, 'key length' 3191625Smax.romanov@nginx.com 3201625Smax.romanov@nginx.com key = self.ws.key() 3211625Smax.romanov@nginx.com resp = self.get( 3221625Smax.romanov@nginx.com headers={ 3231625Smax.romanov@nginx.com 'Host': 'localhost', 3241625Smax.romanov@nginx.com 'Upgrade': 'websocket', 3251625Smax.romanov@nginx.com 'Connection': 'Upgrade', 3261625Smax.romanov@nginx.com 'Sec-WebSocket-Key': [key, key], 3271625Smax.romanov@nginx.com 'Sec-WebSocket-Protocol': 'chat', 3281625Smax.romanov@nginx.com 'Sec-WebSocket-Version': 13, 3291625Smax.romanov@nginx.com }, 3301625Smax.romanov@nginx.com ) 3311625Smax.romanov@nginx.com 3321848Szelenkov@nginx.com assert ( 3331848Szelenkov@nginx.com resp['status'] == 400 3341848Szelenkov@nginx.com ), 'key double' # FAIL https://tools.ietf.org/html/rfc6455#section-11.3.1 3351625Smax.romanov@nginx.com 3361625Smax.romanov@nginx.com def test_asgi_websockets_handshake_method_invalid(self): 3371625Smax.romanov@nginx.com self.load('websockets/mirror') 3381625Smax.romanov@nginx.com 3391625Smax.romanov@nginx.com resp = self.post( 3401625Smax.romanov@nginx.com headers={ 3411625Smax.romanov@nginx.com 'Host': 'localhost', 3421625Smax.romanov@nginx.com 'Upgrade': 'websocket', 3431625Smax.romanov@nginx.com 'Connection': 'Upgrade', 3441625Smax.romanov@nginx.com 'Sec-WebSocket-Key': self.ws.key(), 3451625Smax.romanov@nginx.com 'Sec-WebSocket-Protocol': 'chat', 3461625Smax.romanov@nginx.com 'Sec-WebSocket-Version': 13, 3471625Smax.romanov@nginx.com }, 3481625Smax.romanov@nginx.com ) 3491625Smax.romanov@nginx.com 3501625Smax.romanov@nginx.com assert resp['status'] == 400, 'status' 3511625Smax.romanov@nginx.com 3521625Smax.romanov@nginx.com def test_asgi_websockets_handshake_http_10(self): 3531625Smax.romanov@nginx.com self.load('websockets/mirror') 3541625Smax.romanov@nginx.com 3551625Smax.romanov@nginx.com resp = self.get( 3561625Smax.romanov@nginx.com headers={ 3571625Smax.romanov@nginx.com 'Host': 'localhost', 3581625Smax.romanov@nginx.com 'Upgrade': 'websocket', 3591625Smax.romanov@nginx.com 'Connection': 'Upgrade', 3601625Smax.romanov@nginx.com 'Sec-WebSocket-Key': self.ws.key(), 3611625Smax.romanov@nginx.com 'Sec-WebSocket-Protocol': 'chat', 3621625Smax.romanov@nginx.com 'Sec-WebSocket-Version': 13, 3631625Smax.romanov@nginx.com }, 3641625Smax.romanov@nginx.com http_10=True, 3651625Smax.romanov@nginx.com ) 3661625Smax.romanov@nginx.com 3671625Smax.romanov@nginx.com assert resp['status'] == 400, 'status' 3681625Smax.romanov@nginx.com 3691625Smax.romanov@nginx.com def test_asgi_websockets_handshake_uri_invalid(self): 3701625Smax.romanov@nginx.com self.load('websockets/mirror') 3711625Smax.romanov@nginx.com 3721625Smax.romanov@nginx.com resp = self.get( 3731625Smax.romanov@nginx.com headers={ 3741625Smax.romanov@nginx.com 'Host': 'localhost', 3751625Smax.romanov@nginx.com 'Upgrade': 'websocket', 3761625Smax.romanov@nginx.com 'Connection': 'Upgrade', 3771625Smax.romanov@nginx.com 'Sec-WebSocket-Key': self.ws.key(), 3781625Smax.romanov@nginx.com 'Sec-WebSocket-Protocol': 'chat', 3791625Smax.romanov@nginx.com 'Sec-WebSocket-Version': 13, 3801625Smax.romanov@nginx.com }, 3811625Smax.romanov@nginx.com url='!', 3821625Smax.romanov@nginx.com ) 3831625Smax.romanov@nginx.com 3841625Smax.romanov@nginx.com assert resp['status'] == 400, 'status' 3851625Smax.romanov@nginx.com 3861625Smax.romanov@nginx.com def test_asgi_websockets_protocol_absent(self): 3871625Smax.romanov@nginx.com self.load('websockets/mirror') 3881625Smax.romanov@nginx.com 3891625Smax.romanov@nginx.com key = self.ws.key() 3901625Smax.romanov@nginx.com resp, sock, _ = self.ws.upgrade( 3911625Smax.romanov@nginx.com headers={ 3921625Smax.romanov@nginx.com 'Host': 'localhost', 3931625Smax.romanov@nginx.com 'Upgrade': 'websocket', 3941625Smax.romanov@nginx.com 'Connection': 'Upgrade', 3951625Smax.romanov@nginx.com 'Sec-WebSocket-Key': key, 3961625Smax.romanov@nginx.com 'Sec-WebSocket-Version': 13, 3971625Smax.romanov@nginx.com } 3981625Smax.romanov@nginx.com ) 3991625Smax.romanov@nginx.com sock.close() 4001625Smax.romanov@nginx.com 4011625Smax.romanov@nginx.com assert resp['status'] == 101, 'status' 4021625Smax.romanov@nginx.com assert resp['headers']['Upgrade'] == 'websocket', 'upgrade' 4031625Smax.romanov@nginx.com assert resp['headers']['Connection'] == 'Upgrade', 'connection' 4041625Smax.romanov@nginx.com assert resp['headers']['Sec-WebSocket-Accept'] == self.ws.accept( 4051625Smax.romanov@nginx.com key 4061625Smax.romanov@nginx.com ), 'key' 4071625Smax.romanov@nginx.com 4081625Smax.romanov@nginx.com # autobahn-testsuite 4091625Smax.romanov@nginx.com # 4101625Smax.romanov@nginx.com # Some following tests fail because of Unit does not support UTF-8 4111625Smax.romanov@nginx.com # validation for websocket frames. It should be implemented 4121625Smax.romanov@nginx.com # by application, if necessary. 4131625Smax.romanov@nginx.com 4141625Smax.romanov@nginx.com def test_asgi_websockets_1_1_1__1_1_8(self): 4151625Smax.romanov@nginx.com self.load('websockets/mirror') 4161625Smax.romanov@nginx.com 4171625Smax.romanov@nginx.com opcode = self.ws.OP_TEXT 4181625Smax.romanov@nginx.com 4191625Smax.romanov@nginx.com _, sock, _ = self.ws.upgrade() 4201625Smax.romanov@nginx.com 4211625Smax.romanov@nginx.com def check_length(length, chopsize=None): 4221625Smax.romanov@nginx.com payload = '*' * length 4231625Smax.romanov@nginx.com 4241625Smax.romanov@nginx.com self.ws.frame_write(sock, opcode, payload, chopsize=chopsize) 4251625Smax.romanov@nginx.com 4261625Smax.romanov@nginx.com frame = self.ws.frame_read(sock) 4271625Smax.romanov@nginx.com self.check_frame(frame, True, opcode, payload) 4281625Smax.romanov@nginx.com 4291848Szelenkov@nginx.com check_length(0) # 1_1_1 4301848Szelenkov@nginx.com check_length(125) # 1_1_2 4311848Szelenkov@nginx.com check_length(126) # 1_1_3 4321848Szelenkov@nginx.com check_length(127) # 1_1_4 4331848Szelenkov@nginx.com check_length(128) # 1_1_5 4341848Szelenkov@nginx.com check_length(65535) # 1_1_6 4351848Szelenkov@nginx.com check_length(65536) # 1_1_7 4361848Szelenkov@nginx.com check_length(65536, chopsize=997) # 1_1_8 4371625Smax.romanov@nginx.com 4381625Smax.romanov@nginx.com self.close_connection(sock) 4391625Smax.romanov@nginx.com 4401625Smax.romanov@nginx.com def test_asgi_websockets_1_2_1__1_2_8(self): 4411625Smax.romanov@nginx.com self.load('websockets/mirror') 4421625Smax.romanov@nginx.com 4431625Smax.romanov@nginx.com opcode = self.ws.OP_BINARY 4441625Smax.romanov@nginx.com 4451625Smax.romanov@nginx.com _, sock, _ = self.ws.upgrade() 4461625Smax.romanov@nginx.com 4471625Smax.romanov@nginx.com def check_length(length, chopsize=None): 4481625Smax.romanov@nginx.com payload = b'\xfe' * length 4491625Smax.romanov@nginx.com 4501625Smax.romanov@nginx.com self.ws.frame_write(sock, opcode, payload, chopsize=chopsize) 4511625Smax.romanov@nginx.com frame = self.ws.frame_read(sock) 4521625Smax.romanov@nginx.com 4531625Smax.romanov@nginx.com self.check_frame(frame, True, opcode, payload) 4541625Smax.romanov@nginx.com 4551848Szelenkov@nginx.com check_length(0) # 1_2_1 4561848Szelenkov@nginx.com check_length(125) # 1_2_2 4571848Szelenkov@nginx.com check_length(126) # 1_2_3 4581848Szelenkov@nginx.com check_length(127) # 1_2_4 4591848Szelenkov@nginx.com check_length(128) # 1_2_5 4601848Szelenkov@nginx.com check_length(65535) # 1_2_6 4611848Szelenkov@nginx.com check_length(65536) # 1_2_7 4621848Szelenkov@nginx.com check_length(65536, chopsize=997) # 1_2_8 4631625Smax.romanov@nginx.com 4641625Smax.romanov@nginx.com self.close_connection(sock) 4651625Smax.romanov@nginx.com 4661625Smax.romanov@nginx.com def test_asgi_websockets_2_1__2_6(self): 4671625Smax.romanov@nginx.com self.load('websockets/mirror') 4681625Smax.romanov@nginx.com 4691625Smax.romanov@nginx.com op_ping = self.ws.OP_PING 4701625Smax.romanov@nginx.com op_pong = self.ws.OP_PONG 4711625Smax.romanov@nginx.com 4721625Smax.romanov@nginx.com _, sock, _ = self.ws.upgrade() 4731625Smax.romanov@nginx.com 4741625Smax.romanov@nginx.com def check_ping(payload, chopsize=None, decode=True): 4751625Smax.romanov@nginx.com self.ws.frame_write(sock, op_ping, payload, chopsize=chopsize) 4761625Smax.romanov@nginx.com frame = self.ws.frame_read(sock) 4771625Smax.romanov@nginx.com 4781625Smax.romanov@nginx.com self.check_frame(frame, True, op_pong, payload, decode=decode) 4791625Smax.romanov@nginx.com 4801848Szelenkov@nginx.com check_ping('') # 2_1 4811848Szelenkov@nginx.com check_ping('Hello, world!') # 2_2 4821625Smax.romanov@nginx.com check_ping(b'\x00\xff\xfe\xfd\xfc\xfb\x00\xff', decode=False) # 2_3 4831848Szelenkov@nginx.com check_ping(b'\xfe' * 125, decode=False) # 2_4 4841848Szelenkov@nginx.com check_ping(b'\xfe' * 125, chopsize=1, decode=False) # 2_6 4851625Smax.romanov@nginx.com 4861625Smax.romanov@nginx.com self.close_connection(sock) 4871625Smax.romanov@nginx.com 4881625Smax.romanov@nginx.com # 2_5 4891625Smax.romanov@nginx.com 4901625Smax.romanov@nginx.com _, sock, _ = self.ws.upgrade() 4911625Smax.romanov@nginx.com 4921625Smax.romanov@nginx.com self.ws.frame_write(sock, self.ws.OP_PING, b'\xfe' * 126) 4931625Smax.romanov@nginx.com self.check_close(sock, 1002) 4941625Smax.romanov@nginx.com 4951625Smax.romanov@nginx.com def test_asgi_websockets_2_7__2_9(self): 4961625Smax.romanov@nginx.com self.load('websockets/mirror') 4971625Smax.romanov@nginx.com 4981625Smax.romanov@nginx.com # 2_7 4991625Smax.romanov@nginx.com 5001625Smax.romanov@nginx.com _, sock, _ = self.ws.upgrade() 5011625Smax.romanov@nginx.com 5021625Smax.romanov@nginx.com self.ws.frame_write(sock, self.ws.OP_PONG, '') 5031625Smax.romanov@nginx.com assert self.recvall(sock, read_timeout=0.1) == b'', '2_7' 5041625Smax.romanov@nginx.com 5051625Smax.romanov@nginx.com # 2_8 5061625Smax.romanov@nginx.com 5071625Smax.romanov@nginx.com self.ws.frame_write(sock, self.ws.OP_PONG, 'unsolicited pong payload') 5081625Smax.romanov@nginx.com assert self.recvall(sock, read_timeout=0.1) == b'', '2_8' 5091625Smax.romanov@nginx.com 5101625Smax.romanov@nginx.com # 2_9 5111625Smax.romanov@nginx.com 5121625Smax.romanov@nginx.com payload = 'ping payload' 5131625Smax.romanov@nginx.com 5141625Smax.romanov@nginx.com self.ws.frame_write(sock, self.ws.OP_PONG, 'unsolicited pong payload') 5151625Smax.romanov@nginx.com self.ws.frame_write(sock, self.ws.OP_PING, payload) 5161625Smax.romanov@nginx.com 5171625Smax.romanov@nginx.com frame = self.ws.frame_read(sock) 5181625Smax.romanov@nginx.com self.check_frame(frame, True, self.ws.OP_PONG, payload) 5191625Smax.romanov@nginx.com 5201625Smax.romanov@nginx.com self.close_connection(sock) 5211625Smax.romanov@nginx.com 5221625Smax.romanov@nginx.com def test_asgi_websockets_2_10__2_11(self): 5231625Smax.romanov@nginx.com self.load('websockets/mirror') 5241625Smax.romanov@nginx.com 5251625Smax.romanov@nginx.com # 2_10 5261625Smax.romanov@nginx.com 5271625Smax.romanov@nginx.com _, sock, _ = self.ws.upgrade() 5281625Smax.romanov@nginx.com 5291625Smax.romanov@nginx.com for i in range(0, 10): 5301625Smax.romanov@nginx.com self.ws.frame_write(sock, self.ws.OP_PING, 'payload-%d' % i) 5311625Smax.romanov@nginx.com 5321625Smax.romanov@nginx.com for i in range(0, 10): 5331625Smax.romanov@nginx.com frame = self.ws.frame_read(sock) 5341625Smax.romanov@nginx.com self.check_frame(frame, True, self.ws.OP_PONG, 'payload-%d' % i) 5351625Smax.romanov@nginx.com 5361625Smax.romanov@nginx.com # 2_11 5371625Smax.romanov@nginx.com 5381625Smax.romanov@nginx.com for i in range(0, 10): 5391625Smax.romanov@nginx.com opcode = self.ws.OP_PING 5401625Smax.romanov@nginx.com self.ws.frame_write(sock, opcode, 'payload-%d' % i, chopsize=1) 5411625Smax.romanov@nginx.com 5421625Smax.romanov@nginx.com for i in range(0, 10): 5431625Smax.romanov@nginx.com frame = self.ws.frame_read(sock) 5441625Smax.romanov@nginx.com self.check_frame(frame, True, self.ws.OP_PONG, 'payload-%d' % i) 5451625Smax.romanov@nginx.com 5461625Smax.romanov@nginx.com self.close_connection(sock) 5471625Smax.romanov@nginx.com 5481625Smax.romanov@nginx.com @pytest.mark.skip('not yet') 5491625Smax.romanov@nginx.com def test_asgi_websockets_3_1__3_7(self): 5501625Smax.romanov@nginx.com self.load('websockets/mirror') 5511625Smax.romanov@nginx.com 5521625Smax.romanov@nginx.com payload = 'Hello, world!' 5531625Smax.romanov@nginx.com 5541625Smax.romanov@nginx.com # 3_1 5551625Smax.romanov@nginx.com 5561625Smax.romanov@nginx.com _, sock, _ = self.ws.upgrade() 5571625Smax.romanov@nginx.com 5581625Smax.romanov@nginx.com self.ws.frame_write(sock, self.ws.OP_TEXT, payload, rsv1=True) 5591625Smax.romanov@nginx.com self.check_close(sock, 1002) 5601625Smax.romanov@nginx.com 5611625Smax.romanov@nginx.com # 3_2 5621625Smax.romanov@nginx.com 5631625Smax.romanov@nginx.com _, sock, _ = self.ws.upgrade() 5641625Smax.romanov@nginx.com 5651625Smax.romanov@nginx.com self.ws.frame_write(sock, self.ws.OP_TEXT, payload) 5661625Smax.romanov@nginx.com self.ws.frame_write(sock, self.ws.OP_TEXT, payload, rsv2=True) 5671625Smax.romanov@nginx.com self.ws.frame_write(sock, self.ws.OP_PING, '') 5681625Smax.romanov@nginx.com 5691625Smax.romanov@nginx.com frame = self.ws.frame_read(sock) 5701625Smax.romanov@nginx.com self.check_frame(frame, True, self.ws.OP_TEXT, payload) 5711625Smax.romanov@nginx.com 5721625Smax.romanov@nginx.com self.check_close(sock, 1002, no_close=True) 5731625Smax.romanov@nginx.com 5741625Smax.romanov@nginx.com assert self.recvall(sock, read_timeout=0.1) == b'', 'empty 3_2' 5751625Smax.romanov@nginx.com sock.close() 5761625Smax.romanov@nginx.com 5771625Smax.romanov@nginx.com # 3_3 5781625Smax.romanov@nginx.com 5791625Smax.romanov@nginx.com _, sock, _ = self.ws.upgrade() 5801625Smax.romanov@nginx.com 5811625Smax.romanov@nginx.com self.ws.frame_write(sock, self.ws.OP_TEXT, payload) 5821625Smax.romanov@nginx.com 5831625Smax.romanov@nginx.com frame = self.ws.frame_read(sock) 5841625Smax.romanov@nginx.com self.check_frame(frame, True, self.ws.OP_TEXT, payload) 5851625Smax.romanov@nginx.com 5861625Smax.romanov@nginx.com self.ws.frame_write( 5871625Smax.romanov@nginx.com sock, self.ws.OP_TEXT, payload, rsv1=True, rsv2=True 5881625Smax.romanov@nginx.com ) 5891625Smax.romanov@nginx.com 5901625Smax.romanov@nginx.com self.check_close(sock, 1002, no_close=True) 5911625Smax.romanov@nginx.com 5921625Smax.romanov@nginx.com assert self.recvall(sock, read_timeout=0.1) == b'', 'empty 3_3' 5931625Smax.romanov@nginx.com sock.close() 5941625Smax.romanov@nginx.com 5951625Smax.romanov@nginx.com # 3_4 5961625Smax.romanov@nginx.com 5971625Smax.romanov@nginx.com _, sock, _ = self.ws.upgrade() 5981625Smax.romanov@nginx.com 5991625Smax.romanov@nginx.com self.ws.frame_write(sock, self.ws.OP_TEXT, payload, chopsize=1) 6001625Smax.romanov@nginx.com self.ws.frame_write( 6011625Smax.romanov@nginx.com sock, self.ws.OP_TEXT, payload, rsv3=True, chopsize=1 6021625Smax.romanov@nginx.com ) 6031625Smax.romanov@nginx.com self.ws.frame_write(sock, self.ws.OP_PING, '') 6041625Smax.romanov@nginx.com 6051625Smax.romanov@nginx.com frame = self.ws.frame_read(sock) 6061625Smax.romanov@nginx.com self.check_frame(frame, True, self.ws.OP_TEXT, payload) 6071625Smax.romanov@nginx.com 6081625Smax.romanov@nginx.com self.check_close(sock, 1002, no_close=True) 6091625Smax.romanov@nginx.com 6101625Smax.romanov@nginx.com assert self.recvall(sock, read_timeout=0.1) == b'', 'empty 3_4' 6111625Smax.romanov@nginx.com sock.close() 6121625Smax.romanov@nginx.com 6131625Smax.romanov@nginx.com # 3_5 6141625Smax.romanov@nginx.com 6151625Smax.romanov@nginx.com _, sock, _ = self.ws.upgrade() 6161625Smax.romanov@nginx.com 6171625Smax.romanov@nginx.com self.ws.frame_write( 6181625Smax.romanov@nginx.com sock, 6191625Smax.romanov@nginx.com self.ws.OP_BINARY, 6201625Smax.romanov@nginx.com b'\x00\xff\xfe\xfd\xfc\xfb\x00\xff', 6211625Smax.romanov@nginx.com rsv1=True, 6221625Smax.romanov@nginx.com rsv3=True, 6231625Smax.romanov@nginx.com ) 6241625Smax.romanov@nginx.com 6251625Smax.romanov@nginx.com self.check_close(sock, 1002) 6261625Smax.romanov@nginx.com 6271625Smax.romanov@nginx.com # 3_6 6281625Smax.romanov@nginx.com 6291625Smax.romanov@nginx.com _, sock, _ = self.ws.upgrade() 6301625Smax.romanov@nginx.com 6311625Smax.romanov@nginx.com self.ws.frame_write( 6321625Smax.romanov@nginx.com sock, self.ws.OP_PING, payload, rsv2=True, rsv3=True 6331625Smax.romanov@nginx.com ) 6341625Smax.romanov@nginx.com 6351625Smax.romanov@nginx.com self.check_close(sock, 1002) 6361625Smax.romanov@nginx.com 6371625Smax.romanov@nginx.com # 3_7 6381625Smax.romanov@nginx.com 6391625Smax.romanov@nginx.com _, sock, _ = self.ws.upgrade() 6401625Smax.romanov@nginx.com 6411625Smax.romanov@nginx.com self.ws.frame_write( 6421625Smax.romanov@nginx.com sock, self.ws.OP_CLOSE, payload, rsv1=True, rsv2=True, rsv3=True 6431625Smax.romanov@nginx.com ) 6441625Smax.romanov@nginx.com 6451625Smax.romanov@nginx.com self.check_close(sock, 1002) 6461625Smax.romanov@nginx.com 6471625Smax.romanov@nginx.com def test_asgi_websockets_4_1_1__4_2_5(self): 6481625Smax.romanov@nginx.com self.load('websockets/mirror') 6491625Smax.romanov@nginx.com 6501625Smax.romanov@nginx.com payload = 'Hello, world!' 6511625Smax.romanov@nginx.com 6521625Smax.romanov@nginx.com # 4_1_1 6531625Smax.romanov@nginx.com 6541625Smax.romanov@nginx.com _, sock, _ = self.ws.upgrade() 6551625Smax.romanov@nginx.com 6561625Smax.romanov@nginx.com self.ws.frame_write(sock, 0x03, '') 6571625Smax.romanov@nginx.com self.check_close(sock, 1002) 6581625Smax.romanov@nginx.com 6591625Smax.romanov@nginx.com # 4_1_2 6601625Smax.romanov@nginx.com 6611625Smax.romanov@nginx.com _, sock, _ = self.ws.upgrade() 6621625Smax.romanov@nginx.com 6631625Smax.romanov@nginx.com self.ws.frame_write(sock, 0x04, 'reserved opcode payload') 6641625Smax.romanov@nginx.com self.check_close(sock, 1002) 6651625Smax.romanov@nginx.com 6661625Smax.romanov@nginx.com # 4_1_3 6671625Smax.romanov@nginx.com 6681625Smax.romanov@nginx.com _, sock, _ = self.ws.upgrade() 6691625Smax.romanov@nginx.com 6701625Smax.romanov@nginx.com self.ws.frame_write(sock, self.ws.OP_TEXT, payload) 6711625Smax.romanov@nginx.com 6721625Smax.romanov@nginx.com frame = self.ws.frame_read(sock) 6731625Smax.romanov@nginx.com self.check_frame(frame, True, self.ws.OP_TEXT, payload) 6741625Smax.romanov@nginx.com 6751625Smax.romanov@nginx.com self.ws.frame_write(sock, 0x05, '') 6761625Smax.romanov@nginx.com self.ws.frame_write(sock, self.ws.OP_PING, '') 6771625Smax.romanov@nginx.com 6781625Smax.romanov@nginx.com self.check_close(sock, 1002) 6791625Smax.romanov@nginx.com 6801625Smax.romanov@nginx.com # 4_1_4 6811625Smax.romanov@nginx.com 6821625Smax.romanov@nginx.com _, sock, _ = self.ws.upgrade() 6831625Smax.romanov@nginx.com 6841625Smax.romanov@nginx.com self.ws.frame_write(sock, self.ws.OP_TEXT, payload) 6851625Smax.romanov@nginx.com 6861625Smax.romanov@nginx.com frame = self.ws.frame_read(sock) 6871625Smax.romanov@nginx.com self.check_frame(frame, True, self.ws.OP_TEXT, payload) 6881625Smax.romanov@nginx.com 6891625Smax.romanov@nginx.com self.ws.frame_write(sock, 0x06, payload) 6901625Smax.romanov@nginx.com self.ws.frame_write(sock, self.ws.OP_PING, '') 6911625Smax.romanov@nginx.com 6921625Smax.romanov@nginx.com self.check_close(sock, 1002) 6931625Smax.romanov@nginx.com 6941625Smax.romanov@nginx.com # 4_1_5 6951625Smax.romanov@nginx.com 6961625Smax.romanov@nginx.com _, sock, _ = self.ws.upgrade() 6971625Smax.romanov@nginx.com 6981625Smax.romanov@nginx.com self.ws.frame_write(sock, self.ws.OP_TEXT, payload, chopsize=1) 6991625Smax.romanov@nginx.com 7001625Smax.romanov@nginx.com frame = self.ws.frame_read(sock) 7011625Smax.romanov@nginx.com self.check_frame(frame, True, self.ws.OP_TEXT, payload) 7021625Smax.romanov@nginx.com 7031625Smax.romanov@nginx.com self.ws.frame_write(sock, 0x07, payload, chopsize=1) 7041625Smax.romanov@nginx.com self.ws.frame_write(sock, self.ws.OP_PING, '') 7051625Smax.romanov@nginx.com 7061625Smax.romanov@nginx.com self.check_close(sock, 1002) 7071625Smax.romanov@nginx.com 7081625Smax.romanov@nginx.com # 4_2_1 7091625Smax.romanov@nginx.com 7101625Smax.romanov@nginx.com _, sock, _ = self.ws.upgrade() 7111625Smax.romanov@nginx.com 7121625Smax.romanov@nginx.com self.ws.frame_write(sock, 0x0B, '') 7131625Smax.romanov@nginx.com self.check_close(sock, 1002) 7141625Smax.romanov@nginx.com 7151625Smax.romanov@nginx.com # 4_2_2 7161625Smax.romanov@nginx.com 7171625Smax.romanov@nginx.com _, sock, _ = self.ws.upgrade() 7181625Smax.romanov@nginx.com 7191625Smax.romanov@nginx.com self.ws.frame_write(sock, 0x0C, 'reserved opcode payload') 7201625Smax.romanov@nginx.com self.check_close(sock, 1002) 7211625Smax.romanov@nginx.com 7221625Smax.romanov@nginx.com # 4_2_3 7231625Smax.romanov@nginx.com 7241625Smax.romanov@nginx.com _, sock, _ = self.ws.upgrade() 7251625Smax.romanov@nginx.com 7261625Smax.romanov@nginx.com self.ws.frame_write(sock, self.ws.OP_TEXT, payload) 7271625Smax.romanov@nginx.com 7281625Smax.romanov@nginx.com frame = self.ws.frame_read(sock) 7291625Smax.romanov@nginx.com self.check_frame(frame, True, self.ws.OP_TEXT, payload) 7301625Smax.romanov@nginx.com 7311625Smax.romanov@nginx.com self.ws.frame_write(sock, 0x0D, '') 7321625Smax.romanov@nginx.com self.ws.frame_write(sock, self.ws.OP_PING, '') 7331625Smax.romanov@nginx.com 7341625Smax.romanov@nginx.com self.check_close(sock, 1002) 7351625Smax.romanov@nginx.com 7361625Smax.romanov@nginx.com # 4_2_4 7371625Smax.romanov@nginx.com 7381625Smax.romanov@nginx.com _, sock, _ = self.ws.upgrade() 7391625Smax.romanov@nginx.com 7401625Smax.romanov@nginx.com self.ws.frame_write(sock, self.ws.OP_TEXT, payload) 7411625Smax.romanov@nginx.com 7421625Smax.romanov@nginx.com frame = self.ws.frame_read(sock) 7431625Smax.romanov@nginx.com self.check_frame(frame, True, self.ws.OP_TEXT, payload) 7441625Smax.romanov@nginx.com 7451625Smax.romanov@nginx.com self.ws.frame_write(sock, 0x0E, payload) 7461625Smax.romanov@nginx.com self.ws.frame_write(sock, self.ws.OP_PING, '') 7471625Smax.romanov@nginx.com 7481625Smax.romanov@nginx.com self.check_close(sock, 1002) 7491625Smax.romanov@nginx.com 7501625Smax.romanov@nginx.com # 4_2_5 7511625Smax.romanov@nginx.com 7521625Smax.romanov@nginx.com _, sock, _ = self.ws.upgrade() 7531625Smax.romanov@nginx.com 7541625Smax.romanov@nginx.com self.ws.frame_write(sock, self.ws.OP_TEXT, payload, chopsize=1) 7551625Smax.romanov@nginx.com 7561625Smax.romanov@nginx.com frame = self.ws.frame_read(sock) 7571625Smax.romanov@nginx.com self.check_frame(frame, True, self.ws.OP_TEXT, payload) 7581625Smax.romanov@nginx.com 7591625Smax.romanov@nginx.com self.ws.frame_write(sock, 0x0F, payload, chopsize=1) 7601625Smax.romanov@nginx.com self.ws.frame_write(sock, self.ws.OP_PING, '') 7611625Smax.romanov@nginx.com 7621625Smax.romanov@nginx.com self.check_close(sock, 1002) 7631625Smax.romanov@nginx.com 7641625Smax.romanov@nginx.com def test_asgi_websockets_5_1__5_20(self): 7651625Smax.romanov@nginx.com self.load('websockets/mirror') 7661625Smax.romanov@nginx.com 7671625Smax.romanov@nginx.com # 5_1 7681625Smax.romanov@nginx.com 7691625Smax.romanov@nginx.com _, sock, _ = self.ws.upgrade() 7701625Smax.romanov@nginx.com 7711625Smax.romanov@nginx.com self.ws.frame_write(sock, self.ws.OP_PING, 'fragment1', fin=False) 7721625Smax.romanov@nginx.com self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment2', fin=True) 7731625Smax.romanov@nginx.com self.check_close(sock, 1002) 7741625Smax.romanov@nginx.com 7751625Smax.romanov@nginx.com # 5_2 7761625Smax.romanov@nginx.com 7771625Smax.romanov@nginx.com _, sock, _ = self.ws.upgrade() 7781625Smax.romanov@nginx.com 7791625Smax.romanov@nginx.com self.ws.frame_write(sock, self.ws.OP_PONG, 'fragment1', fin=False) 7801625Smax.romanov@nginx.com self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment2', fin=True) 7811625Smax.romanov@nginx.com self.check_close(sock, 1002) 7821625Smax.romanov@nginx.com 7831625Smax.romanov@nginx.com # 5_3 7841625Smax.romanov@nginx.com 7851625Smax.romanov@nginx.com _, sock, _ = self.ws.upgrade() 7861625Smax.romanov@nginx.com 7871625Smax.romanov@nginx.com self.ws.frame_write(sock, self.ws.OP_TEXT, 'fragment1', fin=False) 7881625Smax.romanov@nginx.com self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment2', fin=True) 7891625Smax.romanov@nginx.com 7901625Smax.romanov@nginx.com frame = self.ws.frame_read(sock) 7911625Smax.romanov@nginx.com self.check_frame(frame, True, self.ws.OP_TEXT, 'fragment1fragment2') 7921625Smax.romanov@nginx.com 7931625Smax.romanov@nginx.com # 5_4 7941625Smax.romanov@nginx.com 7951625Smax.romanov@nginx.com self.ws.frame_write(sock, self.ws.OP_TEXT, 'fragment1', fin=False) 7961625Smax.romanov@nginx.com assert self.recvall(sock, read_timeout=0.1) == b'', '5_4' 7971625Smax.romanov@nginx.com self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment2', fin=True) 7981625Smax.romanov@nginx.com 7991625Smax.romanov@nginx.com frame = self.ws.frame_read(sock) 8001625Smax.romanov@nginx.com self.check_frame(frame, True, self.ws.OP_TEXT, 'fragment1fragment2') 8011625Smax.romanov@nginx.com 8021625Smax.romanov@nginx.com # 5_5 8031625Smax.romanov@nginx.com 8041625Smax.romanov@nginx.com self.ws.frame_write( 8051625Smax.romanov@nginx.com sock, self.ws.OP_TEXT, 'fragment1', fin=False, chopsize=1 8061625Smax.romanov@nginx.com ) 8071625Smax.romanov@nginx.com self.ws.frame_write( 8081625Smax.romanov@nginx.com sock, self.ws.OP_CONT, 'fragment2', fin=True, chopsize=1 8091625Smax.romanov@nginx.com ) 8101625Smax.romanov@nginx.com 8111625Smax.romanov@nginx.com frame = self.ws.frame_read(sock) 8121625Smax.romanov@nginx.com self.check_frame(frame, True, self.ws.OP_TEXT, 'fragment1fragment2') 8131625Smax.romanov@nginx.com 8141625Smax.romanov@nginx.com # 5_6 8151625Smax.romanov@nginx.com 8161625Smax.romanov@nginx.com ping_payload = 'ping payload' 8171625Smax.romanov@nginx.com 8181625Smax.romanov@nginx.com self.ws.frame_write(sock, self.ws.OP_TEXT, 'fragment1', fin=False) 8191625Smax.romanov@nginx.com self.ws.frame_write(sock, self.ws.OP_PING, ping_payload) 8201625Smax.romanov@nginx.com self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment2', fin=True) 8211625Smax.romanov@nginx.com 8221625Smax.romanov@nginx.com frame = self.ws.frame_read(sock) 8231625Smax.romanov@nginx.com self.check_frame(frame, True, self.ws.OP_PONG, ping_payload) 8241625Smax.romanov@nginx.com 8251625Smax.romanov@nginx.com frame = self.ws.frame_read(sock) 8261625Smax.romanov@nginx.com self.check_frame(frame, True, self.ws.OP_TEXT, 'fragment1fragment2') 8271625Smax.romanov@nginx.com 8281625Smax.romanov@nginx.com # 5_7 8291625Smax.romanov@nginx.com 8301625Smax.romanov@nginx.com ping_payload = 'ping payload' 8311625Smax.romanov@nginx.com 8321625Smax.romanov@nginx.com self.ws.frame_write(sock, self.ws.OP_TEXT, 'fragment1', fin=False) 8331625Smax.romanov@nginx.com assert self.recvall(sock, read_timeout=0.1) == b'', '5_7' 8341625Smax.romanov@nginx.com 8351625Smax.romanov@nginx.com self.ws.frame_write(sock, self.ws.OP_PING, ping_payload) 8361625Smax.romanov@nginx.com 8371625Smax.romanov@nginx.com frame = self.ws.frame_read(sock) 8381625Smax.romanov@nginx.com self.check_frame(frame, True, self.ws.OP_PONG, ping_payload) 8391625Smax.romanov@nginx.com 8401625Smax.romanov@nginx.com self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment2', fin=True) 8411625Smax.romanov@nginx.com 8421625Smax.romanov@nginx.com frame = self.ws.frame_read(sock) 8431625Smax.romanov@nginx.com self.check_frame(frame, True, self.ws.OP_TEXT, 'fragment1fragment2') 8441625Smax.romanov@nginx.com 8451625Smax.romanov@nginx.com # 5_8 8461625Smax.romanov@nginx.com 8471625Smax.romanov@nginx.com ping_payload = 'ping payload' 8481625Smax.romanov@nginx.com 8491625Smax.romanov@nginx.com self.ws.frame_write( 8501625Smax.romanov@nginx.com sock, self.ws.OP_TEXT, 'fragment1', fin=False, chopsize=1 8511625Smax.romanov@nginx.com ) 8521625Smax.romanov@nginx.com self.ws.frame_write(sock, self.ws.OP_PING, ping_payload, chopsize=1) 8531625Smax.romanov@nginx.com self.ws.frame_write( 8541625Smax.romanov@nginx.com sock, self.ws.OP_CONT, 'fragment2', fin=True, chopsize=1 8551625Smax.romanov@nginx.com ) 8561625Smax.romanov@nginx.com 8571625Smax.romanov@nginx.com frame = self.ws.frame_read(sock) 8581625Smax.romanov@nginx.com self.check_frame(frame, True, self.ws.OP_PONG, ping_payload) 8591625Smax.romanov@nginx.com 8601625Smax.romanov@nginx.com frame = self.ws.frame_read(sock) 8611625Smax.romanov@nginx.com self.check_frame(frame, True, self.ws.OP_TEXT, 'fragment1fragment2') 8621625Smax.romanov@nginx.com 8631625Smax.romanov@nginx.com # 5_9 8641625Smax.romanov@nginx.com 8651625Smax.romanov@nginx.com self.ws.frame_write( 8661625Smax.romanov@nginx.com sock, self.ws.OP_CONT, 'non-continuation payload', fin=True 8671625Smax.romanov@nginx.com ) 8681625Smax.romanov@nginx.com self.ws.frame_write(sock, self.ws.OP_TEXT, 'Hello, world!', fin=True) 8691625Smax.romanov@nginx.com self.check_close(sock, 1002) 8701625Smax.romanov@nginx.com 8711625Smax.romanov@nginx.com # 5_10 8721625Smax.romanov@nginx.com 8731625Smax.romanov@nginx.com _, sock, _ = self.ws.upgrade() 8741625Smax.romanov@nginx.com 8751625Smax.romanov@nginx.com self.ws.frame_write( 8761625Smax.romanov@nginx.com sock, self.ws.OP_CONT, 'non-continuation payload', fin=True 8771625Smax.romanov@nginx.com ) 8781625Smax.romanov@nginx.com self.ws.frame_write(sock, self.ws.OP_TEXT, 'Hello, world!', fin=True) 8791625Smax.romanov@nginx.com self.check_close(sock, 1002) 8801625Smax.romanov@nginx.com 8811625Smax.romanov@nginx.com # 5_11 8821625Smax.romanov@nginx.com 8831625Smax.romanov@nginx.com _, sock, _ = self.ws.upgrade() 8841625Smax.romanov@nginx.com 8851625Smax.romanov@nginx.com self.ws.frame_write( 8861625Smax.romanov@nginx.com sock, 8871625Smax.romanov@nginx.com self.ws.OP_CONT, 8881625Smax.romanov@nginx.com 'non-continuation payload', 8891625Smax.romanov@nginx.com fin=True, 8901625Smax.romanov@nginx.com chopsize=1, 8911625Smax.romanov@nginx.com ) 8921625Smax.romanov@nginx.com self.ws.frame_write( 8931625Smax.romanov@nginx.com sock, self.ws.OP_TEXT, 'Hello, world!', fin=True, chopsize=1 8941625Smax.romanov@nginx.com ) 8951625Smax.romanov@nginx.com self.check_close(sock, 1002) 8961625Smax.romanov@nginx.com 8971625Smax.romanov@nginx.com # 5_12 8981625Smax.romanov@nginx.com 8991625Smax.romanov@nginx.com _, sock, _ = self.ws.upgrade() 9001625Smax.romanov@nginx.com 9011625Smax.romanov@nginx.com self.ws.frame_write( 9021625Smax.romanov@nginx.com sock, self.ws.OP_CONT, 'non-continuation payload', fin=False 9031625Smax.romanov@nginx.com ) 9041625Smax.romanov@nginx.com self.ws.frame_write(sock, self.ws.OP_TEXT, 'Hello, world!', fin=True) 9051625Smax.romanov@nginx.com self.check_close(sock, 1002) 9061625Smax.romanov@nginx.com 9071625Smax.romanov@nginx.com # 5_13 9081625Smax.romanov@nginx.com 9091625Smax.romanov@nginx.com _, sock, _ = self.ws.upgrade() 9101625Smax.romanov@nginx.com 9111625Smax.romanov@nginx.com self.ws.frame_write( 9121625Smax.romanov@nginx.com sock, self.ws.OP_CONT, 'non-continuation payload', fin=False 9131625Smax.romanov@nginx.com ) 9141625Smax.romanov@nginx.com self.ws.frame_write(sock, self.ws.OP_TEXT, 'Hello, world!', fin=True) 9151625Smax.romanov@nginx.com self.check_close(sock, 1002) 9161625Smax.romanov@nginx.com 9171625Smax.romanov@nginx.com # 5_14 9181625Smax.romanov@nginx.com 9191625Smax.romanov@nginx.com _, sock, _ = self.ws.upgrade() 9201625Smax.romanov@nginx.com 9211625Smax.romanov@nginx.com self.ws.frame_write( 9221625Smax.romanov@nginx.com sock, 9231625Smax.romanov@nginx.com self.ws.OP_CONT, 9241625Smax.romanov@nginx.com 'non-continuation payload', 9251625Smax.romanov@nginx.com fin=False, 9261625Smax.romanov@nginx.com chopsize=1, 9271625Smax.romanov@nginx.com ) 9281625Smax.romanov@nginx.com self.ws.frame_write( 9291625Smax.romanov@nginx.com sock, self.ws.OP_TEXT, 'Hello, world!', fin=True, chopsize=1 9301625Smax.romanov@nginx.com ) 9311625Smax.romanov@nginx.com self.check_close(sock, 1002) 9321625Smax.romanov@nginx.com 9331625Smax.romanov@nginx.com # 5_15 9341625Smax.romanov@nginx.com 9351625Smax.romanov@nginx.com _, sock, _ = self.ws.upgrade() 9361625Smax.romanov@nginx.com 9371625Smax.romanov@nginx.com self.ws.frame_write(sock, self.ws.OP_TEXT, 'fragment1', fin=False) 9381625Smax.romanov@nginx.com self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment2', fin=True) 9391625Smax.romanov@nginx.com self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment3', fin=False) 9401625Smax.romanov@nginx.com self.ws.frame_write(sock, self.ws.OP_TEXT, 'fragment4', fin=True) 9411819Smax.romanov@nginx.com 9421819Smax.romanov@nginx.com frame = self.ws.frame_read(sock) 9431819Smax.romanov@nginx.com 9441819Smax.romanov@nginx.com if frame['opcode'] == self.ws.OP_TEXT: 945*2073Szelenkov@nginx.com self.check_frame(frame, True, self.ws.OP_TEXT, 'fragment1fragment2') 9461819Smax.romanov@nginx.com frame = None 9471819Smax.romanov@nginx.com 9481819Smax.romanov@nginx.com self.check_close(sock, 1002, frame=frame) 9491625Smax.romanov@nginx.com 9501625Smax.romanov@nginx.com # 5_16 9511625Smax.romanov@nginx.com 9521625Smax.romanov@nginx.com _, sock, _ = self.ws.upgrade() 9531625Smax.romanov@nginx.com 9541625Smax.romanov@nginx.com for i in range(0, 2): 9551625Smax.romanov@nginx.com self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment1', fin=False) 9561625Smax.romanov@nginx.com self.ws.frame_write(sock, self.ws.OP_TEXT, 'fragment2', fin=False) 9571625Smax.romanov@nginx.com self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment3', fin=True) 9581625Smax.romanov@nginx.com self.check_close(sock, 1002) 9591625Smax.romanov@nginx.com 9601625Smax.romanov@nginx.com # 5_17 9611625Smax.romanov@nginx.com 9621625Smax.romanov@nginx.com _, sock, _ = self.ws.upgrade() 9631625Smax.romanov@nginx.com 9641625Smax.romanov@nginx.com for i in range(0, 2): 9651625Smax.romanov@nginx.com self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment1', fin=True) 9661625Smax.romanov@nginx.com self.ws.frame_write(sock, self.ws.OP_TEXT, 'fragment2', fin=False) 9671625Smax.romanov@nginx.com self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment3', fin=True) 9681625Smax.romanov@nginx.com self.check_close(sock, 1002) 9691625Smax.romanov@nginx.com 9701625Smax.romanov@nginx.com # 5_18 9711625Smax.romanov@nginx.com 9721625Smax.romanov@nginx.com _, sock, _ = self.ws.upgrade() 9731625Smax.romanov@nginx.com 9741625Smax.romanov@nginx.com self.ws.frame_write(sock, self.ws.OP_TEXT, 'fragment1', fin=False) 9751625Smax.romanov@nginx.com self.ws.frame_write(sock, self.ws.OP_TEXT, 'fragment2') 9761625Smax.romanov@nginx.com self.check_close(sock, 1002) 9771625Smax.romanov@nginx.com 9781625Smax.romanov@nginx.com # 5_19 9791625Smax.romanov@nginx.com 9801625Smax.romanov@nginx.com _, sock, _ = self.ws.upgrade() 9811625Smax.romanov@nginx.com 9821625Smax.romanov@nginx.com self.ws.frame_write(sock, self.ws.OP_TEXT, 'fragment1', fin=False) 9831625Smax.romanov@nginx.com self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment2', fin=False) 9841625Smax.romanov@nginx.com self.ws.frame_write(sock, self.ws.OP_PING, 'pongme 1!') 9851625Smax.romanov@nginx.com 9861625Smax.romanov@nginx.com time.sleep(1) 9871625Smax.romanov@nginx.com 9881625Smax.romanov@nginx.com self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment3', fin=False) 9891625Smax.romanov@nginx.com self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment4', fin=False) 9901625Smax.romanov@nginx.com self.ws.frame_write(sock, self.ws.OP_PING, 'pongme 2!') 9911625Smax.romanov@nginx.com self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment5') 9921625Smax.romanov@nginx.com 9931625Smax.romanov@nginx.com frame = self.ws.frame_read(sock) 9941625Smax.romanov@nginx.com self.check_frame(frame, True, self.ws.OP_PONG, 'pongme 1!') 9951625Smax.romanov@nginx.com 9961625Smax.romanov@nginx.com frame = self.ws.frame_read(sock) 9971625Smax.romanov@nginx.com self.check_frame(frame, True, self.ws.OP_PONG, 'pongme 2!') 9981625Smax.romanov@nginx.com 9991625Smax.romanov@nginx.com self.check_frame( 10001625Smax.romanov@nginx.com self.ws.frame_read(sock), 10011625Smax.romanov@nginx.com True, 10021625Smax.romanov@nginx.com self.ws.OP_TEXT, 10031625Smax.romanov@nginx.com 'fragment1fragment2fragment3fragment4fragment5', 10041625Smax.romanov@nginx.com ) 10051625Smax.romanov@nginx.com 10061625Smax.romanov@nginx.com # 5_20 10071625Smax.romanov@nginx.com 10081625Smax.romanov@nginx.com self.ws.frame_write(sock, self.ws.OP_TEXT, 'fragment1', fin=False) 10091625Smax.romanov@nginx.com self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment2', fin=False) 10101625Smax.romanov@nginx.com self.ws.frame_write(sock, self.ws.OP_PING, 'pongme 1!') 10111625Smax.romanov@nginx.com 10121625Smax.romanov@nginx.com frame = self.ws.frame_read(sock) 10131625Smax.romanov@nginx.com self.check_frame(frame, True, self.ws.OP_PONG, 'pongme 1!') 10141625Smax.romanov@nginx.com 10151625Smax.romanov@nginx.com time.sleep(1) 10161625Smax.romanov@nginx.com 10171625Smax.romanov@nginx.com self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment3', fin=False) 10181625Smax.romanov@nginx.com self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment4', fin=False) 10191625Smax.romanov@nginx.com self.ws.frame_write(sock, self.ws.OP_PING, 'pongme 2!') 10201625Smax.romanov@nginx.com 10211625Smax.romanov@nginx.com frame = self.ws.frame_read(sock) 10221625Smax.romanov@nginx.com self.check_frame(frame, True, self.ws.OP_PONG, 'pongme 2!') 10231625Smax.romanov@nginx.com 10241625Smax.romanov@nginx.com assert self.recvall(sock, read_timeout=0.1) == b'', '5_20' 10251625Smax.romanov@nginx.com self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment5') 10261625Smax.romanov@nginx.com 10271625Smax.romanov@nginx.com self.check_frame( 10281625Smax.romanov@nginx.com