11625Smax.romanov@nginx.comimport struct
21625Smax.romanov@nginx.comimport time
31625Smax.romanov@nginx.comfrom distutils.version import LooseVersion
41625Smax.romanov@nginx.com
51635Szelenkov@nginx.comimport pytest
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):
121625Smax.romanov@nginx.com    prerequisites = {'modules': {'python':
131625Smax.romanov@nginx.com                            lambda v: LooseVersion(v) >= LooseVersion('3.5')}}
141625Smax.romanov@nginx.com    load_module = 'asgi'
151625Smax.romanov@nginx.com
161625Smax.romanov@nginx.com    ws = TestApplicationWebsocket()
171625Smax.romanov@nginx.com
181736Szelenkov@nginx.com    @pytest.fixture(autouse=True)
191736Szelenkov@nginx.com    def setup_method_fixture(self, request, skip_alert):
201625Smax.romanov@nginx.com        assert 'success' in self.conf(
211625Smax.romanov@nginx.com            {'http': {'websocket': {'keepalive_interval': 0}}}, 'settings'
221625Smax.romanov@nginx.com        ), 'clear keepalive_interval'
231625Smax.romanov@nginx.com
241625Smax.romanov@nginx.com        skip_alert(r'socket close\(\d+\) failed')
251625Smax.romanov@nginx.com
261625Smax.romanov@nginx.com    def close_connection(self, sock):
271625Smax.romanov@nginx.com        assert self.recvall(sock, read_timeout=0.1) == b'', 'empty soc'
281625Smax.romanov@nginx.com
291625Smax.romanov@nginx.com        self.ws.frame_write(sock, self.ws.OP_CLOSE, self.ws.serialize_close())
301625Smax.romanov@nginx.com
311625Smax.romanov@nginx.com        self.check_close(sock)
321625Smax.romanov@nginx.com
331625Smax.romanov@nginx.com    def check_close(self, sock, code=1000, no_close=False):
341625Smax.romanov@nginx.com        frame = self.ws.frame_read(sock)
351625Smax.romanov@nginx.com
361625Smax.romanov@nginx.com        assert frame['fin'] == True, 'close fin'
371625Smax.romanov@nginx.com        assert frame['opcode'] == self.ws.OP_CLOSE, 'close opcode'
381625Smax.romanov@nginx.com        assert frame['code'] == code, 'close code'
391625Smax.romanov@nginx.com
401625Smax.romanov@nginx.com        if not no_close:
411625Smax.romanov@nginx.com            sock.close()
421625Smax.romanov@nginx.com
431625Smax.romanov@nginx.com    def check_frame(self, frame, fin, opcode, payload, decode=True):
441625Smax.romanov@nginx.com        if opcode == self.ws.OP_BINARY or not decode:
451625Smax.romanov@nginx.com            data = frame['data']
461625Smax.romanov@nginx.com        else:
471625Smax.romanov@nginx.com            data = frame['data'].decode('utf-8')
481625Smax.romanov@nginx.com
491625Smax.romanov@nginx.com        assert frame['fin'] == fin, 'fin'
501625Smax.romanov@nginx.com        assert frame['opcode'] == opcode, 'opcode'
511625Smax.romanov@nginx.com        assert data == payload, 'payload'
521625Smax.romanov@nginx.com
531625Smax.romanov@nginx.com    def test_asgi_websockets_handshake(self):
541625Smax.romanov@nginx.com        self.load('websockets/mirror')
551625Smax.romanov@nginx.com
561625Smax.romanov@nginx.com        resp, sock, key = self.ws.upgrade()
571625Smax.romanov@nginx.com        sock.close()
581625Smax.romanov@nginx.com
591625Smax.romanov@nginx.com        assert resp['status'] == 101, 'status'
601625Smax.romanov@nginx.com        assert resp['headers']['Upgrade'] == 'websocket', 'upgrade'
611625Smax.romanov@nginx.com        assert resp['headers']['Connection'] == 'Upgrade', 'connection'
621625Smax.romanov@nginx.com        assert resp['headers']['Sec-WebSocket-Accept'] == self.ws.accept(
631625Smax.romanov@nginx.com            key
641625Smax.romanov@nginx.com        ), 'key'
651625Smax.romanov@nginx.com
66*1780Smax.romanov@nginx.com        # remove "mirror" application
67*1780Smax.romanov@nginx.com        self.load('websockets/subprotocol')
68*1780Smax.romanov@nginx.com
691625Smax.romanov@nginx.com    def test_asgi_websockets_subprotocol(self):
701625Smax.romanov@nginx.com        self.load('websockets/subprotocol')
711625Smax.romanov@nginx.com
721625Smax.romanov@nginx.com        resp, sock, key = self.ws.upgrade()
731625Smax.romanov@nginx.com        sock.close()
741625Smax.romanov@nginx.com
751625Smax.romanov@nginx.com        assert resp['status'] == 101, 'status'
761625Smax.romanov@nginx.com        assert resp['headers']['x-subprotocols'] == "('chat', 'phone', 'video')", 'subprotocols'
771625Smax.romanov@nginx.com        assert resp['headers']['sec-websocket-protocol'] == 'chat', 'key'
781625Smax.romanov@nginx.com
791625Smax.romanov@nginx.com    def test_asgi_websockets_mirror(self):
801625Smax.romanov@nginx.com        self.load('websockets/mirror')
811625Smax.romanov@nginx.com
821625Smax.romanov@nginx.com        message = 'blah'
831625Smax.romanov@nginx.com
841625Smax.romanov@nginx.com        _, sock, _ = self.ws.upgrade()
851625Smax.romanov@nginx.com
861625Smax.romanov@nginx.com        self.ws.frame_write(sock, self.ws.OP_TEXT, message)
871625Smax.romanov@nginx.com        frame = self.ws.frame_read(sock)
881625Smax.romanov@nginx.com
891625Smax.romanov@nginx.com        assert message == frame['data'].decode('utf-8'), 'mirror'
901625Smax.romanov@nginx.com
911625Smax.romanov@nginx.com        self.ws.frame_write(sock, self.ws.OP_TEXT, message)
921625Smax.romanov@nginx.com        frame = self.ws.frame_read(sock)
931625Smax.romanov@nginx.com
941625Smax.romanov@nginx.com        assert message == frame['data'].decode('utf-8'), 'mirror 2'
951625Smax.romanov@nginx.com
961625Smax.romanov@nginx.com        sock.close()
971625Smax.romanov@nginx.com
98*1780Smax.romanov@nginx.com    def test_asgi_websockets_mirror_app_change(self):
99*1780Smax.romanov@nginx.com        self.load('websockets/mirror')
100*1780Smax.romanov@nginx.com
101*1780Smax.romanov@nginx.com        message = 'blah'
102*1780Smax.romanov@nginx.com
103*1780Smax.romanov@nginx.com        _, sock, _ = self.ws.upgrade()
104*1780Smax.romanov@nginx.com
105*1780Smax.romanov@nginx.com        self.ws.frame_write(sock, self.ws.OP_TEXT, message)
106*1780Smax.romanov@nginx.com        frame = self.ws.frame_read(sock)
107*1780Smax.romanov@nginx.com
108*1780Smax.romanov@nginx.com        assert message == frame['data'].decode('utf-8'), 'mirror'
109*1780Smax.romanov@nginx.com
110*1780Smax.romanov@nginx.com        self.load('websockets/subprotocol')
111*1780Smax.romanov@nginx.com
112*1780Smax.romanov@nginx.com        self.ws.frame_write(sock, self.ws.OP_TEXT, message)
113*1780Smax.romanov@nginx.com        frame = self.ws.frame_read(sock)
114*1780Smax.romanov@nginx.com
115*1780Smax.romanov@nginx.com        assert message == frame['data'].decode('utf-8'), 'mirror 2'
116*1780Smax.romanov@nginx.com
117*1780Smax.romanov@nginx.com        sock.close()
118*1780Smax.romanov@nginx.com
1191625Smax.romanov@nginx.com    def test_asgi_websockets_no_mask(self):
1201625Smax.romanov@nginx.com        self.load('websockets/mirror')
1211625Smax.romanov@nginx.com
1221625Smax.romanov@nginx.com        message = 'blah'
1231625Smax.romanov@nginx.com
1241625Smax.romanov@nginx.com        _, sock, _ = self.ws.upgrade()
1251625Smax.romanov@nginx.com
1261625Smax.romanov@nginx.com        self.ws.frame_write(sock, self.ws.OP_TEXT, message, mask=False)
1271625Smax.romanov@nginx.com
1281625Smax.romanov@nginx.com        frame = self.ws.frame_read(sock)
1291625Smax.romanov@nginx.com
1301625Smax.romanov@nginx.com        assert frame['opcode'] == self.ws.OP_CLOSE, 'no mask opcode'
1311625Smax.romanov@nginx.com        assert frame['code'] == 1002, 'no mask close code'
1321625Smax.romanov@nginx.com
1331625Smax.romanov@nginx.com        sock.close()
1341625Smax.romanov@nginx.com
1351625Smax.romanov@nginx.com    def test_asgi_websockets_fragmentation(self):
1361625Smax.romanov@nginx.com        self.load('websockets/mirror')
1371625Smax.romanov@nginx.com
1381625Smax.romanov@nginx.com        message = 'blah'
1391625Smax.romanov@nginx.com
1401625Smax.romanov@nginx.com        _, sock, _ = self.ws.upgrade()
1411625Smax.romanov@nginx.com
1421625Smax.romanov@nginx.com        self.ws.frame_write(sock, self.ws.OP_TEXT, message, fin=False)
1431625Smax.romanov@nginx.com        self.ws.frame_write(sock, self.ws.OP_CONT, ' ', fin=False)
1441625Smax.romanov@nginx.com        self.ws.frame_write(sock, self.ws.OP_CONT, message)
1451625Smax.romanov@nginx.com
1461625Smax.romanov@nginx.com        frame = self.ws.frame_read(sock)
1471625Smax.romanov@nginx.com
1481625Smax.romanov@nginx.com        assert message + ' ' + message == frame['data'].decode(
1491625Smax.romanov@nginx.com            'utf-8'
1501625Smax.romanov@nginx.com        ), 'mirror framing'
1511625Smax.romanov@nginx.com
1521625Smax.romanov@nginx.com        sock.close()
1531625Smax.romanov@nginx.com
1541629Szelenkov@nginx.com    def test_asgi_websockets_length_long(self):
1551629Szelenkov@nginx.com        self.load('websockets/mirror')
1561629Szelenkov@nginx.com
1571629Szelenkov@nginx.com        _, sock, _ = self.ws.upgrade()
1581629Szelenkov@nginx.com
1591629Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_TEXT, 'fragment1', fin=False)
1601629Szelenkov@nginx.com        self.ws.frame_write(
1611629Szelenkov@nginx.com            sock, self.ws.OP_CONT, 'fragment2', length=2**64 - 1
1621629Szelenkov@nginx.com        )
1631629Szelenkov@nginx.com
1641629Szelenkov@nginx.com        self.check_close(sock, 1009)  # 1009 - CLOSE_TOO_LARGE
1651629Szelenkov@nginx.com
1661625Smax.romanov@nginx.com    def test_asgi_websockets_frame_fragmentation_invalid(self):
1671625Smax.romanov@nginx.com        self.load('websockets/mirror')
1681625Smax.romanov@nginx.com
1691625Smax.romanov@nginx.com        message = 'blah'
1701625Smax.romanov@nginx.com
1711625Smax.romanov@nginx.com        _, sock, _ = self.ws.upgrade()
1721625Smax.romanov@nginx.com
1731625Smax.romanov@nginx.com        self.ws.frame_write(sock, self.ws.OP_PING, message, fin=False)
1741625Smax.romanov@nginx.com
1751625Smax.romanov@nginx.com        frame = self.ws.frame_read(sock)
1761625Smax.romanov@nginx.com
1771625Smax.romanov@nginx.com        frame.pop('data')
1781625Smax.romanov@nginx.com        assert frame == {
1791625Smax.romanov@nginx.com            'fin': True,
1801625Smax.romanov@nginx.com            'rsv1': False,
1811625Smax.romanov@nginx.com            'rsv2': False,
1821625Smax.romanov@nginx.com            'rsv3': False,
1831625Smax.romanov@nginx.com            'opcode': self.ws.OP_CLOSE,
1841625Smax.romanov@nginx.com            'mask': 0,
1851625Smax.romanov@nginx.com            'code': 1002,
1861625Smax.romanov@nginx.com            'reason': 'Fragmented control frame',
1871625Smax.romanov@nginx.com        }, 'close frame'
1881625Smax.romanov@nginx.com
1891625Smax.romanov@nginx.com        sock.close()
1901625Smax.romanov@nginx.com
1911625Smax.romanov@nginx.com    def test_asgi_websockets_large(self):
1921625Smax.romanov@nginx.com        self.load('websockets/mirror')
1931625Smax.romanov@nginx.com
1941625Smax.romanov@nginx.com        message = '0123456789' * 300
1951625Smax.romanov@nginx.com
1961625Smax.romanov@nginx.com        _, sock, _ = self.ws.upgrade()
1971625Smax.romanov@nginx.com
1981625Smax.romanov@nginx.com        self.ws.frame_write(sock, self.ws.OP_TEXT, message)
1991625Smax.romanov@nginx.com
2001625Smax.romanov@nginx.com        frame = self.ws.frame_read(sock)
2011625Smax.romanov@nginx.com        data = frame['data'].decode('utf-8')
2021625Smax.romanov@nginx.com
2031625Smax.romanov@nginx.com        frame = self.ws.frame_read(sock)
2041625Smax.romanov@nginx.com        data += frame['data'].decode('utf-8')
2051625Smax.romanov@nginx.com
2061625Smax.romanov@nginx.com        assert message == data, 'large'
2071625Smax.romanov@nginx.com
2081625Smax.romanov@nginx.com        sock.close()
2091625Smax.romanov@nginx.com
2101625Smax.romanov@nginx.com    def test_asgi_websockets_two_clients(self):
2111625Smax.romanov@nginx.com        self.load('websockets/mirror')
2121625Smax.romanov@nginx.com
2131625Smax.romanov@nginx.com        message1 = 'blah1'
2141625Smax.romanov@nginx.com        message2 = 'blah2'
2151625Smax.romanov@nginx.com
2161625Smax.romanov@nginx.com        _, sock1, _ = self.ws.upgrade()
2171625Smax.romanov@nginx.com        _, sock2, _ = self.ws.upgrade()
2181625Smax.romanov@nginx.com
2191625Smax.romanov@nginx.com        self.ws.frame_write(sock1, self.ws.OP_TEXT, message1)
2201625Smax.romanov@nginx.com        self.ws.frame_write(sock2, self.ws.OP_TEXT, message2)
2211625Smax.romanov@nginx.com
2221625Smax.romanov@nginx.com        frame1 = self.ws.frame_read(sock1)
2231625Smax.romanov@nginx.com        frame2 = self.ws.frame_read(sock2)
2241625Smax.romanov@nginx.com
2251625Smax.romanov@nginx.com        assert message1 == frame1['data'].decode('utf-8'), 'client 1'
2261625Smax.romanov@nginx.com        assert message2 == frame2['data'].decode('utf-8'), 'client 2'
2271625Smax.romanov@nginx.com
2281625Smax.romanov@nginx.com        sock1.close()
2291625Smax.romanov@nginx.com        sock2.close()
2301625Smax.romanov@nginx.com
2311625Smax.romanov@nginx.com    @pytest.mark.skip('not yet')
2321625Smax.romanov@nginx.com    def test_asgi_websockets_handshake_upgrade_absent(
2331625Smax.romanov@nginx.com        self
2341625Smax.romanov@nginx.com    ):  # FAIL https://tools.ietf.org/html/rfc6455#section-4.2.1
2351625Smax.romanov@nginx.com        self.load('websockets/mirror')
2361625Smax.romanov@nginx.com
2371625Smax.romanov@nginx.com        resp = self.get(
2381625Smax.romanov@nginx.com            headers={
2391625Smax.romanov@nginx.com                'Host': 'localhost',
2401625Smax.romanov@nginx.com                'Connection': 'Upgrade',
2411625Smax.romanov@nginx.com                'Sec-WebSocket-Key': self.ws.key(),
2421625Smax.romanov@nginx.com                'Sec-WebSocket-Protocol': 'chat',
2431625Smax.romanov@nginx.com                'Sec-WebSocket-Version': 13,
2441625Smax.romanov@nginx.com            },
2451625Smax.romanov@nginx.com        )
2461625Smax.romanov@nginx.com
2471625Smax.romanov@nginx.com        assert resp['status'] == 400, 'upgrade absent'
2481625Smax.romanov@nginx.com
2491625Smax.romanov@nginx.com    def test_asgi_websockets_handshake_case_insensitive(self):
2501625Smax.romanov@nginx.com        self.load('websockets/mirror')
2511625Smax.romanov@nginx.com
2521625Smax.romanov@nginx.com        resp, sock, _ = self.ws.upgrade(
2531625Smax.romanov@nginx.com            headers={
2541625Smax.romanov@nginx.com                'Host': 'localhost',
2551625Smax.romanov@nginx.com                'Upgrade': 'WEBSOCKET',
2561625Smax.romanov@nginx.com                'Connection': 'UPGRADE',
2571625Smax.romanov@nginx.com                'Sec-WebSocket-Key': self.ws.key(),
2581625Smax.romanov@nginx.com                'Sec-WebSocket-Protocol': 'chat',
2591625Smax.romanov@nginx.com                'Sec-WebSocket-Version': 13,
2601625Smax.romanov@nginx.com            }
2611625Smax.romanov@nginx.com        )
2621625Smax.romanov@nginx.com        sock.close()
2631625Smax.romanov@nginx.com
2641625Smax.romanov@nginx.com        assert resp['status'] == 101, 'status'
2651625Smax.romanov@nginx.com
2661625Smax.romanov@nginx.com    @pytest.mark.skip('not yet')
2671625Smax.romanov@nginx.com    def test_asgi_websockets_handshake_connection_absent(self):  # FAIL
2681625Smax.romanov@nginx.com        self.load('websockets/mirror')
2691625Smax.romanov@nginx.com
2701625Smax.romanov@nginx.com        resp = self.get(
2711625Smax.romanov@nginx.com            headers={
2721625Smax.romanov@nginx.com                'Host': 'localhost',
2731625Smax.romanov@nginx.com                'Upgrade': 'websocket',
2741625Smax.romanov@nginx.com                'Sec-WebSocket-Key': self.ws.key(),
2751625Smax.romanov@nginx.com                'Sec-WebSocket-Protocol': 'chat',
2761625Smax.romanov@nginx.com                'Sec-WebSocket-Version': 13,
2771625Smax.romanov@nginx.com            },
2781625Smax.romanov@nginx.com        )
2791625Smax.romanov@nginx.com
2801625Smax.romanov@nginx.com        assert resp['status'] == 400, 'status'
2811625Smax.romanov@nginx.com
2821625Smax.romanov@nginx.com    def test_asgi_websockets_handshake_version_absent(self):
2831625Smax.romanov@nginx.com        self.load('websockets/mirror')
2841625Smax.romanov@nginx.com
2851625Smax.romanov@nginx.com        resp = self.get(
2861625Smax.romanov@nginx.com            headers={
2871625Smax.romanov@nginx.com                'Host': 'localhost',
2881625Smax.romanov@nginx.com                'Upgrade': 'websocket',
2891625Smax.romanov@nginx.com                'Connection': 'Upgrade',
2901625Smax.romanov@nginx.com                'Sec-WebSocket-Key': self.ws.key(),
2911625Smax.romanov@nginx.com                'Sec-WebSocket-Protocol': 'chat',
2921625Smax.romanov@nginx.com            },
2931625Smax.romanov@nginx.com        )
2941625Smax.romanov@nginx.com
2951625Smax.romanov@nginx.com        assert resp['status'] == 426, 'status'
2961625Smax.romanov@nginx.com
2971625Smax.romanov@nginx.com    @pytest.mark.skip('not yet')
2981625Smax.romanov@nginx.com    def test_asgi_websockets_handshake_key_invalid(self):
2991625Smax.romanov@nginx.com        self.load('websockets/mirror')
3001625Smax.romanov@nginx.com
3011625Smax.romanov@nginx.com        resp = self.get(
3021625Smax.romanov@nginx.com            headers={
3031625Smax.romanov@nginx.com                'Host': 'localhost',
3041625Smax.romanov@nginx.com                'Upgrade': 'websocket',
3051625Smax.romanov@nginx.com                'Connection': 'Upgrade',
3061625Smax.romanov@nginx.com                'Sec-WebSocket-Key': '!',
3071625Smax.romanov@nginx.com                'Sec-WebSocket-Protocol': 'chat',
3081625Smax.romanov@nginx.com                'Sec-WebSocket-Version': 13,
3091625Smax.romanov@nginx.com            },
3101625Smax.romanov@nginx.com        )
3111625Smax.romanov@nginx.com
3121625Smax.romanov@nginx.com        assert resp['status'] == 400, 'key length'
3131625Smax.romanov@nginx.com
3141625Smax.romanov@nginx.com        key = self.ws.key()
3151625Smax.romanov@nginx.com        resp = self.get(
3161625Smax.romanov@nginx.com            headers={
3171625Smax.romanov@nginx.com                'Host': 'localhost',
3181625Smax.romanov@nginx.com                'Upgrade': 'websocket',
3191625Smax.romanov@nginx.com                'Connection': 'Upgrade',
3201625Smax.romanov@nginx.com                'Sec-WebSocket-Key': [key, key],
3211625Smax.romanov@nginx.com                'Sec-WebSocket-Protocol': 'chat',
3221625Smax.romanov@nginx.com                'Sec-WebSocket-Version': 13,
3231625Smax.romanov@nginx.com            },
3241625Smax.romanov@nginx.com        )
3251625Smax.romanov@nginx.com
3261625Smax.romanov@nginx.com        assert resp['status'] == 400, 'key double'  # FAIL https://tools.ietf.org/html/rfc6455#section-11.3.1
3271625Smax.romanov@nginx.com
3281625Smax.romanov@nginx.com    def test_asgi_websockets_handshake_method_invalid(self):
3291625Smax.romanov@nginx.com        self.load('websockets/mirror')
3301625Smax.romanov@nginx.com
3311625Smax.romanov@nginx.com        resp = self.post(
3321625Smax.romanov@nginx.com            headers={
3331625Smax.romanov@nginx.com                'Host': 'localhost',
3341625Smax.romanov@nginx.com                'Upgrade': 'websocket',
3351625Smax.romanov@nginx.com                'Connection': 'Upgrade',
3361625Smax.romanov@nginx.com                'Sec-WebSocket-Key': self.ws.key(),
3371625Smax.romanov@nginx.com                'Sec-WebSocket-Protocol': 'chat',
3381625Smax.romanov@nginx.com                'Sec-WebSocket-Version': 13,
3391625Smax.romanov@nginx.com            },
3401625Smax.romanov@nginx.com        )
3411625Smax.romanov@nginx.com
3421625Smax.romanov@nginx.com        assert resp['status'] == 400, 'status'
3431625Smax.romanov@nginx.com
3441625Smax.romanov@nginx.com    def test_asgi_websockets_handshake_http_10(self):
3451625Smax.romanov@nginx.com        self.load('websockets/mirror')
3461625Smax.romanov@nginx.com
3471625Smax.romanov@nginx.com        resp = self.get(
3481625Smax.romanov@nginx.com            headers={
3491625Smax.romanov@nginx.com                'Host': 'localhost',
3501625Smax.romanov@nginx.com                'Upgrade': 'websocket',
3511625Smax.romanov@nginx.com                'Connection': 'Upgrade',
3521625Smax.romanov@nginx.com                'Sec-WebSocket-Key': self.ws.key(),
3531625Smax.romanov@nginx.com                'Sec-WebSocket-Protocol': 'chat',
3541625Smax.romanov@nginx.com                'Sec-WebSocket-Version': 13,
3551625Smax.romanov@nginx.com            },
3561625Smax.romanov@nginx.com            http_10=True,
3571625Smax.romanov@nginx.com        )
3581625Smax.romanov@nginx.com
3591625Smax.romanov@nginx.com        assert resp['status'] == 400, 'status'
3601625Smax.romanov@nginx.com
3611625Smax.romanov@nginx.com    def test_asgi_websockets_handshake_uri_invalid(self):
3621625Smax.romanov@nginx.com        self.load('websockets/mirror')
3631625Smax.romanov@nginx.com
3641625Smax.romanov@nginx.com        resp = self.get(
3651625Smax.romanov@nginx.com            headers={
3661625Smax.romanov@nginx.com                'Host': 'localhost',
3671625Smax.romanov@nginx.com                'Upgrade': 'websocket',
3681625Smax.romanov@nginx.com                'Connection': 'Upgrade',
3691625Smax.romanov@nginx.com                'Sec-WebSocket-Key': self.ws.key(),
3701625Smax.romanov@nginx.com                'Sec-WebSocket-Protocol': 'chat',
3711625Smax.romanov@nginx.com                'Sec-WebSocket-Version': 13,
3721625Smax.romanov@nginx.com            },
3731625Smax.romanov@nginx.com            url='!',
3741625Smax.romanov@nginx.com        )
3751625Smax.romanov@nginx.com
3761625Smax.romanov@nginx.com        assert resp['status'] == 400, 'status'
3771625Smax.romanov@nginx.com
3781625Smax.romanov@nginx.com    def test_asgi_websockets_protocol_absent(self):
3791625Smax.romanov@nginx.com        self.load('websockets/mirror')
3801625Smax.romanov@nginx.com
3811625Smax.romanov@nginx.com        key = self.ws.key()
3821625Smax.romanov@nginx.com        resp, sock, _ = self.ws.upgrade(
3831625Smax.romanov@nginx.com            headers={
3841625Smax.romanov@nginx.com                'Host': 'localhost',
3851625Smax.romanov@nginx.com                'Upgrade': 'websocket',
3861625Smax.romanov@nginx.com                'Connection': 'Upgrade',
3871625Smax.romanov@nginx.com                'Sec-WebSocket-Key': key,
3881625Smax.romanov@nginx.com                'Sec-WebSocket-Version': 13,
3891625Smax.romanov@nginx.com            }
3901625Smax.romanov@nginx.com        )
3911625Smax.romanov@nginx.com        sock.close()
3921625Smax.romanov@nginx.com
3931625Smax.romanov@nginx.com        assert resp['status'] == 101, 'status'
3941625Smax.romanov@nginx.com        assert resp['headers']['Upgrade'] == 'websocket', 'upgrade'
3951625Smax.romanov@nginx.com        assert resp['headers']['Connection'] == 'Upgrade', 'connection'
3961625Smax.romanov@nginx.com        assert resp['headers']['Sec-WebSocket-Accept'] == self.ws.accept(
3971625Smax.romanov@nginx.com            key
3981625Smax.romanov@nginx.com        ), 'key'
3991625Smax.romanov@nginx.com
4001625Smax.romanov@nginx.com    # autobahn-testsuite
4011625Smax.romanov@nginx.com    #
4021625Smax.romanov@nginx.com    # Some following tests fail because of Unit does not support UTF-8
4031625Smax.romanov@nginx.com    # validation for websocket frames.  It should be implemented
4041625Smax.romanov@nginx.com    # by application, if necessary.
4051625Smax.romanov@nginx.com
4061625Smax.romanov@nginx.com    def test_asgi_websockets_1_1_1__1_1_8(self):
4071625Smax.romanov@nginx.com        self.load('websockets/mirror')
4081625Smax.romanov@nginx.com
4091625Smax.romanov@nginx.com        opcode = self.ws.OP_TEXT
4101625Smax.romanov@nginx.com
4111625Smax.romanov@nginx.com        _, sock, _ = self.ws.upgrade()
4121625Smax.romanov@nginx.com
4131625Smax.romanov@nginx.com        def check_length(length, chopsize=None):
4141625Smax.romanov@nginx.com            payload = '*' * length
4151625Smax.romanov@nginx.com
4161625Smax.romanov@nginx.com            self.ws.frame_write(sock, opcode, payload, chopsize=chopsize)
4171625Smax.romanov@nginx.com
4181625Smax.romanov@nginx.com            frame = self.ws.frame_read(sock)
4191625Smax.romanov@nginx.com            self.check_frame(frame, True, opcode, payload)
4201625Smax.romanov@nginx.com
4211625Smax.romanov@nginx.com        check_length(0)                      # 1_1_1
4221625Smax.romanov@nginx.com        check_length(125)                    # 1_1_2
4231625Smax.romanov@nginx.com        check_length(126)                    # 1_1_3
4241625Smax.romanov@nginx.com        check_length(127)                    # 1_1_4
4251625Smax.romanov@nginx.com        check_length(128)                    # 1_1_5
4261625Smax.romanov@nginx.com        check_length(65535)                  # 1_1_6
4271625Smax.romanov@nginx.com        check_length(65536)                  # 1_1_7
4281625Smax.romanov@nginx.com        check_length(65536, chopsize = 997)  # 1_1_8
4291625Smax.romanov@nginx.com
4301625Smax.romanov@nginx.com        self.close_connection(sock)
4311625Smax.romanov@nginx.com
4321625Smax.romanov@nginx.com    def test_asgi_websockets_1_2_1__1_2_8(self):
4331625Smax.romanov@nginx.com        self.load('websockets/mirror')
4341625Smax.romanov@nginx.com
4351625Smax.romanov@nginx.com        opcode = self.ws.OP_BINARY
4361625Smax.romanov@nginx.com
4371625Smax.romanov@nginx.com        _, sock, _ = self.ws.upgrade()
4381625Smax.romanov@nginx.com
4391625Smax.romanov@nginx.com        def check_length(length, chopsize=None):
4401625Smax.romanov@nginx.com            payload = b'\xfe' * length
4411625Smax.romanov@nginx.com
4421625Smax.romanov@nginx.com            self.ws.frame_write(sock, opcode, payload, chopsize=chopsize)
4431625Smax.romanov@nginx.com            frame = self.ws.frame_read(sock)
4441625Smax.romanov@nginx.com
4451625Smax.romanov@nginx.com            self.check_frame(frame, True, opcode, payload)
4461625Smax.romanov@nginx.com
4471625Smax.romanov@nginx.com        check_length(0)                      # 1_2_1
4481625Smax.romanov@nginx.com        check_length(125)                    # 1_2_2
4491625Smax.romanov@nginx.com        check_length(126)                    # 1_2_3
4501625Smax.romanov@nginx.com        check_length(127)                    # 1_2_4
4511625Smax.romanov@nginx.com        check_length(128)                    # 1_2_5
4521625Smax.romanov@nginx.com        check_length(65535)                  # 1_2_6
4531625Smax.romanov@nginx.com        check_length(65536)                  # 1_2_7
4541625Smax.romanov@nginx.com        check_length(65536, chopsize = 997)  # 1_2_8
4551625Smax.romanov@nginx.com
4561625Smax.romanov@nginx.com        self.close_connection(sock)
4571625Smax.romanov@nginx.com
4581625Smax.romanov@nginx.com    def test_asgi_websockets_2_1__2_6(self):
4591625Smax.romanov@nginx.com        self.load('websockets/mirror')
4601625Smax.romanov@nginx.com
4611625Smax.romanov@nginx.com        op_ping = self.ws.OP_PING
4621625Smax.romanov@nginx.com        op_pong = self.ws.OP_PONG
4631625Smax.romanov@nginx.com
4641625Smax.romanov@nginx.com        _, sock, _ = self.ws.upgrade()
4651625Smax.romanov@nginx.com
4661625Smax.romanov@nginx.com        def check_ping(payload, chopsize=None, decode=True):
4671625Smax.romanov@nginx.com            self.ws.frame_write(sock, op_ping, payload, chopsize=chopsize)
4681625Smax.romanov@nginx.com            frame = self.ws.frame_read(sock)
4691625Smax.romanov@nginx.com
4701625Smax.romanov@nginx.com            self.check_frame(frame, True, op_pong, payload, decode=decode)
4711625Smax.romanov@nginx.com
4721625Smax.romanov@nginx.com        check_ping('')                                                 # 2_1
4731625Smax.romanov@nginx.com        check_ping('Hello, world!')                                    # 2_2
4741625Smax.romanov@nginx.com        check_ping(b'\x00\xff\xfe\xfd\xfc\xfb\x00\xff', decode=False)  # 2_3
4751625Smax.romanov@nginx.com        check_ping(b'\xfe' * 125, decode=False)                        # 2_4
4761625Smax.romanov@nginx.com        check_ping(b'\xfe' * 125, chopsize=1, decode=False)            # 2_6
4771625Smax.romanov@nginx.com
4781625Smax.romanov@nginx.com        self.close_connection(sock)
4791625Smax.romanov@nginx.com
4801625Smax.romanov@nginx.com        # 2_5
4811625Smax.romanov@nginx.com
4821625Smax.romanov@nginx.com        _, sock, _ = self.ws.upgrade()
4831625Smax.romanov@nginx.com
4841625Smax.romanov@nginx.com        self.ws.frame_write(sock, self.ws.OP_PING, b'\xfe' * 126)
4851625Smax.romanov@nginx.com        self.check_close(sock, 1002)
4861625Smax.romanov@nginx.com
4871625Smax.romanov@nginx.com    def test_asgi_websockets_2_7__2_9(self):
4881625Smax.romanov@nginx.com        self.load('websockets/mirror')
4891625Smax.romanov@nginx.com
4901625Smax.romanov@nginx.com        # 2_7
4911625Smax.romanov@nginx.com
4921625Smax.romanov@nginx.com        _, sock, _ = self.ws.upgrade()
4931625Smax.romanov@nginx.com
4941625Smax.romanov@nginx.com        self.ws.frame_write(sock, self.ws.OP_PONG, '')
4951625Smax.romanov@nginx.com        assert self.recvall(sock, read_timeout=0.1) == b'', '2_7'
4961625Smax.romanov@nginx.com
4971625Smax.romanov@nginx.com        # 2_8
4981625Smax.romanov@nginx.com
4991625Smax.romanov@nginx.com        self.ws.frame_write(sock, self.ws.OP_PONG, 'unsolicited pong payload')
5001625Smax.romanov@nginx.com        assert self.recvall(sock, read_timeout=0.1) == b'', '2_8'
5011625Smax.romanov@nginx.com
5021625Smax.romanov@nginx.com        # 2_9
5031625Smax.romanov@nginx.com
5041625Smax.romanov@nginx.com        payload = 'ping payload'
5051625Smax.romanov@nginx.com
5061625Smax.romanov@nginx.com        self.ws.frame_write(sock, self.ws.OP_PONG, 'unsolicited pong payload')
5071625Smax.romanov@nginx.com        self.ws.frame_write(sock, self.ws.OP_PING, payload)
5081625Smax.romanov@nginx.com
5091625Smax.romanov@nginx.com        frame = self.ws.frame_read(sock)
5101625Smax.romanov@nginx.com        self.check_frame(frame, True, self.ws.OP_PONG, payload)
5111625Smax.romanov@nginx.com
5121625Smax.romanov@nginx.com        self.close_connection(sock)
5131625Smax.romanov@nginx.com
5141625Smax.romanov@nginx.com    def test_asgi_websockets_2_10__2_11(self):
5151625Smax.romanov@nginx.com        self.load('websockets/mirror')
5161625Smax.romanov@nginx.com
5171625Smax.romanov@nginx.com        # 2_10
5181625Smax.romanov@nginx.com
5191625Smax.romanov@nginx.com        _, sock, _ = self.ws.upgrade()
5201625Smax.romanov@nginx.com
5211625Smax.romanov@nginx.com        for i in range(0, 10):
5221625Smax.romanov@nginx.com            self.ws.frame_write(sock, self.ws.OP_PING, 'payload-%d' % i)
5231625Smax.romanov@nginx.com
5241625Smax.romanov@nginx.com        for i in range(0, 10):
5251625Smax.romanov@nginx.com            frame = self.ws.frame_read(sock)
5261625Smax.romanov@nginx.com            self.check_frame(frame, True, self.ws.OP_PONG, 'payload-%d' % i)
5271625Smax.romanov@nginx.com
5281625Smax.romanov@nginx.com        # 2_11
5291625Smax.romanov@nginx.com
5301625Smax.romanov@nginx.com        for i in range(0, 10):
5311625Smax.romanov@nginx.com            opcode = self.ws.OP_PING
5321625Smax.romanov@nginx.com            self.ws.frame_write(sock, opcode, 'payload-%d' % i, chopsize=1)
5331625Smax.romanov@nginx.com
5341625Smax.romanov@nginx.com        for i in range(0, 10):
5351625Smax.romanov@nginx.com            frame = self.ws.frame_read(sock)
5361625Smax.romanov@nginx.com            self.check_frame(frame, True, self.ws.OP_PONG, 'payload-%d' % i)
5371625Smax.romanov@nginx.com
5381625Smax.romanov@nginx.com        self.close_connection(sock)
5391625Smax.romanov@nginx.com
5401625Smax.romanov@nginx.com    @pytest.mark.skip('not yet')
5411625Smax.romanov@nginx.com    def test_asgi_websockets_3_1__3_7(self):
5421625Smax.romanov@nginx.com        self.load('websockets/mirror')
5431625Smax.romanov@nginx.com
5441625Smax.romanov@nginx.com        payload = 'Hello, world!'
5451625Smax.romanov@nginx.com
5461625Smax.romanov@nginx.com        # 3_1
5471625Smax.romanov@nginx.com
5481625Smax.romanov@nginx.com        _, sock, _ = self.ws.upgrade()
5491625Smax.romanov@nginx.com
5501625Smax.romanov@nginx.com        self.ws.frame_write(sock, self.ws.OP_TEXT, payload, rsv1=True)
5511625Smax.romanov@nginx.com        self.check_close(sock, 1002)
5521625Smax.romanov@nginx.com
5531625Smax.romanov@nginx.com        # 3_2
5541625Smax.romanov@nginx.com
5551625Smax.romanov@nginx.com        _, sock, _ = self.ws.upgrade()
5561625Smax.romanov@nginx.com
5571625Smax.romanov@nginx.com        self.ws.frame_write(sock, self.ws.OP_TEXT, payload)
5581625Smax.romanov@nginx.com        self.ws.frame_write(sock, self.ws.OP_TEXT, payload, rsv2=True)
5591625Smax.romanov@nginx.com        self.ws.frame_write(sock, self.ws.OP_PING, '')
5601625Smax.romanov@nginx.com
5611625Smax.romanov@nginx.com        frame = self.ws.frame_read(sock)
5621625Smax.romanov@nginx.com        self.check_frame(frame, True, self.ws.OP_TEXT, payload)
5631625Smax.romanov@nginx.com
5641625Smax.romanov@nginx.com        self.check_close(sock, 1002, no_close=True)
5651625Smax.romanov@nginx.com
5661625Smax.romanov@nginx.com        assert self.recvall(sock, read_timeout=0.1) == b'', 'empty 3_2'
5671625Smax.romanov@nginx.com        sock.close()
5681625Smax.romanov@nginx.com
5691625Smax.romanov@nginx.com        # 3_3
5701625Smax.romanov@nginx.com
5711625Smax.romanov@nginx.com        _, sock, _ = self.ws.upgrade()
5721625Smax.romanov@nginx.com
5731625Smax.romanov@nginx.com        self.ws.frame_write(sock, self.ws.OP_TEXT, payload)
5741625Smax.romanov@nginx.com
5751625Smax.romanov@nginx.com        frame = self.ws.frame_read(sock)
5761625Smax.romanov@nginx.com        self.check_frame(frame, True, self.ws.OP_TEXT, payload)
5771625Smax.romanov@nginx.com
5781625Smax.romanov@nginx.com        self.ws.frame_write(
5791625Smax.romanov@nginx.com            sock, self.ws.OP_TEXT, payload, rsv1=True, rsv2=True
5801625Smax.romanov@nginx.com        )
5811625Smax.romanov@nginx.com
5821625Smax.romanov@nginx.com        self.check_close(sock, 1002, no_close=True)
5831625Smax.romanov@nginx.com
5841625Smax.romanov@nginx.com        assert self.recvall(sock, read_timeout=0.1) == b'', 'empty 3_3'
5851625Smax.romanov@nginx.com        sock.close()
5861625Smax.romanov@nginx.com
5871625Smax.romanov@nginx.com        # 3_4
5881625Smax.romanov@nginx.com
5891625Smax.romanov@nginx.com        _, sock, _ = self.ws.upgrade()
5901625Smax.romanov@nginx.com
5911625Smax.romanov@nginx.com        self.ws.frame_write(sock, self.ws.OP_TEXT, payload, chopsize=1)
5921625Smax.romanov@nginx.com        self.ws.frame_write(
5931625Smax.romanov@nginx.com            sock, self.ws.OP_TEXT, payload, rsv3=True, chopsize=1
5941625Smax.romanov@nginx.com        )
5951625Smax.romanov@nginx.com        self.ws.frame_write(sock, self.ws.OP_PING, '')
5961625Smax.romanov@nginx.com
5971625Smax.romanov@nginx.com        frame = self.ws.frame_read(sock)
5981625Smax.romanov@nginx.com        self.check_frame(frame, True, self.ws.OP_TEXT, payload)
5991625Smax.romanov@nginx.com
6001625Smax.romanov@nginx.com        self.check_close(sock, 1002, no_close=True)
6011625Smax.romanov@nginx.com
6021625Smax.romanov@nginx.com        assert self.recvall(sock, read_timeout=0.1) == b'', 'empty 3_4'
6031625Smax.romanov@nginx.com        sock.close()
6041625Smax.romanov@nginx.com
6051625Smax.romanov@nginx.com        # 3_5
6061625Smax.romanov@nginx.com
6071625Smax.romanov@nginx.com        _, sock, _ = self.ws.upgrade()
6081625Smax.romanov@nginx.com
6091625Smax.romanov@nginx.com        self.ws.frame_write(
6101625Smax.romanov@nginx.com            sock,
6111625Smax.romanov@nginx.com            self.ws.OP_BINARY,
6121625Smax.romanov@nginx.com            b'\x00\xff\xfe\xfd\xfc\xfb\x00\xff',
6131625Smax.romanov@nginx.com            rsv1=True,
6141625Smax.romanov@nginx.com            rsv3=True,
6151625Smax.romanov@nginx.com        )
6161625Smax.romanov@nginx.com
6171625Smax.romanov@nginx.com        self.check_close(sock, 1002)
6181625Smax.romanov@nginx.com
6191625Smax.romanov@nginx.com        # 3_6
6201625Smax.romanov@nginx.com
6211625Smax.romanov@nginx.com        _, sock, _ = self.ws.upgrade()
6221625Smax.romanov@nginx.com
6231625Smax.romanov@nginx.com        self.ws.frame_write(
6241625Smax.romanov@nginx.com            sock, self.ws.OP_PING, payload, rsv2=True, rsv3=True
6251625Smax.romanov@nginx.com        )
6261625Smax.romanov@nginx.com
6271625Smax.romanov@nginx.com        self.check_close(sock, 1002)
6281625Smax.romanov@nginx.com
6291625Smax.romanov@nginx.com        # 3_7
6301625Smax.romanov@nginx.com
6311625Smax.romanov@nginx.com        _, sock, _ = self.ws.upgrade()
6321625Smax.romanov@nginx.com
6331625Smax.romanov@nginx.com        self.ws.frame_write(
6341625Smax.romanov@nginx.com            sock, self.ws.OP_CLOSE, payload, rsv1=True, rsv2=True, rsv3=True
6351625Smax.romanov@nginx.com        )
6361625Smax.romanov@nginx.com
6371625Smax.romanov@nginx.com        self.check_close(sock, 1002)
6381625Smax.romanov@nginx.com
6391625Smax.romanov@nginx.com    def test_asgi_websockets_4_1_1__4_2_5(self):
6401625Smax.romanov@nginx.com        self.load('websockets/mirror')
6411625Smax.romanov@nginx.com
6421625Smax.romanov@nginx.com        payload = 'Hello, world!'
6431625Smax.romanov@nginx.com
6441625Smax.romanov@nginx.com        # 4_1_1
6451625Smax.romanov@nginx.com
6461625Smax.romanov@nginx.com        _, sock, _ = self.ws.upgrade()
6471625Smax.romanov@nginx.com
6481625Smax.romanov@nginx.com        self.ws.frame_write(sock, 0x03, '')
6491625Smax.romanov@nginx.com        self.check_close(sock, 1002)
6501625Smax.romanov@nginx.com
6511625Smax.romanov@nginx.com        # 4_1_2
6521625Smax.romanov@nginx.com
6531625Smax.romanov@nginx.com        _, sock, _ = self.ws.upgrade()
6541625Smax.romanov@nginx.com
6551625Smax.romanov@nginx.com        self.ws.frame_write(sock, 0x04, 'reserved opcode payload')
6561625Smax.romanov@nginx.com        self.check_close(sock, 1002)
6571625Smax.romanov@nginx.com
6581625Smax.romanov@nginx.com        # 4_1_3
6591625Smax.romanov@nginx.com
6601625Smax.romanov@nginx.com        _, sock, _ = self.ws.upgrade()
6611625Smax.romanov@nginx.com
6621625Smax.romanov@nginx.com        self.ws.frame_write(sock, self.ws.OP_TEXT, payload)
6631625Smax.romanov@nginx.com
6641625Smax.romanov@nginx.com        frame = self.ws.frame_read(sock)
6651625Smax.romanov@nginx.com        self.check_frame(frame, True, self.ws.OP_TEXT, payload)
6661625Smax.romanov@nginx.com
6671625Smax.romanov@nginx.com        self.ws.frame_write(sock, 0x05, '')
6681625Smax.romanov@nginx.com        self.ws.frame_write(sock, self.ws.OP_PING, '')
6691625Smax.romanov@nginx.com
6701625Smax.romanov@nginx.com        self.check_close(sock, 1002)
6711625Smax.romanov@nginx.com
6721625Smax.romanov@nginx.com        # 4_1_4
6731625Smax.romanov@nginx.com
6741625Smax.romanov@nginx.com        _, sock, _ = self.ws.upgrade()
6751625Smax.romanov@nginx.com
6761625Smax.romanov@nginx.com        self.ws.frame_write(sock, self.ws.OP_TEXT, payload)
6771625Smax.romanov@nginx.com
6781625Smax.romanov@nginx.com        frame = self.ws.frame_read(sock)
6791625Smax.romanov@nginx.com        self.check_frame(frame, True, self.ws.OP_TEXT, payload)
6801625Smax.romanov@nginx.com
6811625Smax.romanov@nginx.com        self.ws.frame_write(sock, 0x06, payload)
6821625Smax.romanov@nginx.com        self.ws.frame_write(sock, self.ws.OP_PING, '')
6831625Smax.romanov@nginx.com
6841625Smax.romanov@nginx.com        self.check_close(sock, 1002)
6851625Smax.romanov@nginx.com
6861625Smax.romanov@nginx.com        # 4_1_5
6871625Smax.romanov@nginx.com
6881625Smax.romanov@nginx.com        _, sock, _ = self.ws.upgrade()
6891625Smax.romanov@nginx.com
6901625Smax.romanov@nginx.com        self.ws.frame_write(sock, self.ws.OP_TEXT, payload, chopsize=1)
6911625Smax.romanov@nginx.com
6921625Smax.romanov@nginx.com        frame = self.ws.frame_read(sock)
6931625Smax.romanov@nginx.com        self.check_frame(frame, True, self.ws.OP_TEXT, payload)
6941625Smax.romanov@nginx.com
6951625Smax.romanov@nginx.com        self.ws.frame_write(sock, 0x07, payload, chopsize=1)
6961625Smax.romanov@nginx.com        self.ws.frame_write(sock, self.ws.OP_PING, '')
6971625Smax.romanov@nginx.com
6981625Smax.romanov@nginx.com        self.check_close(sock, 1002)
6991625Smax.romanov@nginx.com
7001625Smax.romanov@nginx.com        # 4_2_1
7011625Smax.romanov@nginx.com
7021625Smax.romanov@nginx.com        _, sock, _ = self.ws.upgrade()
7031625Smax.romanov@nginx.com
7041625Smax.romanov@nginx.com        self.ws.frame_write(sock, 0x0B, '')
7051625Smax.romanov@nginx.com        self.check_close(sock, 1002)
7061625Smax.romanov@nginx.com
7071625Smax.romanov@nginx.com        # 4_2_2
7081625Smax.romanov@nginx.com
7091625Smax.romanov@nginx.com        _, sock, _ = self.ws.upgrade()
7101625Smax.romanov@nginx.com
7111625Smax.romanov@nginx.com        self.ws.frame_write(sock, 0x0C, 'reserved opcode payload')
7121625Smax.romanov@nginx.com        self.check_close(sock, 1002)
7131625Smax.romanov@nginx.com
7141625Smax.romanov@nginx.com        # 4_2_3
7151625Smax.romanov@nginx.com
7161625Smax.romanov@nginx.com        _, sock, _ = self.ws.upgrade()
7171625Smax.romanov@nginx.com
7181625Smax.romanov@nginx.com        self.ws.frame_write(sock, self.ws.OP_TEXT, payload)
7191625Smax.romanov@nginx.com
7201625Smax.romanov@nginx.com        frame = self.ws.frame_read(sock)
7211625Smax.romanov@nginx.com        self.check_frame(frame, True, self.ws.OP_TEXT, payload)
7221625Smax.romanov@nginx.com
7231625Smax.romanov@nginx.com        self.ws.frame_write(sock, 0x0D, '')
7241625Smax.romanov@nginx.com        self.ws.frame_write(sock, self.ws.OP_PING, '')
7251625Smax.romanov@nginx.com
7261625Smax.romanov@nginx.com        self.check_close(sock, 1002)
7271625Smax.romanov@nginx.com
7281625Smax.romanov@nginx.com        # 4_2_4
7291625Smax.romanov@nginx.com
7301625Smax.romanov@nginx.com        _, sock, _ = self.ws.upgrade()
7311625Smax.romanov@nginx.com
7321625Smax.romanov@nginx.com        self.ws.frame_write(sock, self.ws.OP_TEXT, payload)
7331625Smax.romanov@nginx.com
7341625Smax.romanov@nginx.com        frame = self.ws.frame_read(sock)
7351625Smax.romanov@nginx.com        self.check_frame(frame, True, self.ws.OP_TEXT, payload)
7361625Smax.romanov@nginx.com
7371625Smax.romanov@nginx.com        self.ws.frame_write(sock, 0x0E, payload)
7381625Smax.romanov@nginx.com        self.ws.frame_write(sock, self.ws.OP_PING, '')
7391625Smax.romanov@nginx.com
7401625Smax.romanov@nginx.com        self.check_close(sock, 1002)
7411625Smax.romanov@nginx.com
7421625Smax.romanov@nginx.com        # 4_2_5
7431625Smax.romanov@nginx.com
7441625Smax.romanov@nginx.com        _, sock, _ = self.ws.upgrade()
7451625Smax.romanov@nginx.com
7461625Smax.romanov@nginx.com        self.ws.frame_write(sock, self.ws.OP_TEXT, payload, chopsize=1)
7471625Smax.romanov@nginx.com
7481625Smax.romanov@nginx.com        frame = self.ws.frame_read(sock)
7491625Smax.romanov@nginx.com        self.check_frame(frame, True, self.ws.OP_TEXT, payload)
7501625Smax.romanov@nginx.com
7511625Smax.romanov@nginx.com        self.ws.frame_write(sock, 0x0F, payload, chopsize=1)
7521625Smax.romanov@nginx.com        self.ws.frame_write(sock, self.ws.OP_PING, '')
7531625Smax.romanov@nginx.com
7541625Smax.romanov@nginx.com        self.check_close(sock, 1002)
7551625Smax.romanov@nginx.com
7561625Smax.romanov@nginx.com    def test_asgi_websockets_5_1__5_20(self):
7571625Smax.romanov@nginx.com        self.load('websockets/mirror')
7581625Smax.romanov@nginx.com
7591625Smax.romanov@nginx.com        # 5_1
7601625Smax.romanov@nginx.com
7611625Smax.romanov@nginx.com        _, sock, _ = self.ws.upgrade()
7621625Smax.romanov@nginx.com
7631625Smax.romanov@nginx.com        self.ws.frame_write(sock, self.ws.OP_PING, 'fragment1', fin=False)
7641625Smax.romanov@nginx.com        self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment2', fin=True)
7651625Smax.romanov@nginx.com        self.check_close(sock, 1002)
7661625Smax.romanov@nginx.com
7671625Smax.romanov@nginx.com        # 5_2
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_PONG, '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_3
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_TEXT, 'fragment1', fin=False)
7801625Smax.romanov@nginx.com        self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment2', fin=True)
7811625Smax.romanov@nginx.com
7821625Smax.romanov@nginx.com        frame = self.ws.frame_read(sock)
7831625Smax.romanov@nginx.com        self.check_frame(frame, True, self.ws.OP_TEXT, 'fragment1fragment2')
7841625Smax.romanov@nginx.com
7851625Smax.romanov@nginx.com        # 5_4
7861625Smax.romanov@nginx.com
7871625Smax.romanov@nginx.com        self.ws.frame_write(sock, self.ws.OP_TEXT, 'fragment1', fin=False)
7881625Smax.romanov@nginx.com        assert self.recvall(sock, read_timeout=0.1) == b'', '5_4'
7891625Smax.romanov@nginx.com        self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment2', fin=True)
7901625Smax.romanov@nginx.com
7911625Smax.romanov@nginx.com        frame = self.ws.frame_read(sock)
7921625Smax.romanov@nginx.com        self.check_frame(frame, True, self.ws.OP_TEXT, 'fragment1fragment2')
7931625Smax.romanov@nginx.com
7941625Smax.romanov@nginx.com        # 5_5
7951625Smax.romanov@nginx.com
7961625Smax.romanov@nginx.com        self.ws.frame_write(
7971625Smax.romanov@nginx.com            sock, self.ws.OP_TEXT, 'fragment1', fin=False, chopsize=1
7981625Smax.romanov@nginx.com        )
7991625Smax.romanov@nginx.com        self.ws.frame_write(
8001625Smax.romanov@nginx.com            sock, self.ws.OP_CONT, 'fragment2', fin=True, chopsize=1
8011625Smax.romanov@nginx.com        )
8021625Smax.romanov@nginx.com
8031625Smax.romanov@nginx.com        frame = self.ws.frame_read(sock)
8041625Smax.romanov@nginx.com        self.check_frame(frame, True, self.ws.OP_TEXT, 'fragment1fragment2')
8051625Smax.romanov@nginx.com
8061625Smax.romanov@nginx.com        # 5_6
8071625Smax.romanov@nginx.com
8081625Smax.romanov@nginx.com        ping_payload = 'ping payload'
8091625Smax.romanov@nginx.com
8101625Smax.romanov@nginx.com        self.ws.frame_write(sock, self.ws.OP_TEXT, 'fragment1', fin=False)
8111625Smax.romanov@nginx.com        self.ws.frame_write(sock, self.ws.OP_PING, ping_payload)
8121625Smax.romanov@nginx.com        self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment2', fin=True)
8131625Smax.romanov@nginx.com
8141625Smax.romanov@nginx.com        frame = self.ws.frame_read(sock)
8151625Smax.romanov@nginx.com        self.check_frame(frame, True, self.ws.OP_PONG, ping_payload)
8161625Smax.romanov@nginx.com
8171625Smax.romanov@nginx.com        frame = self.ws.frame_read(sock)
8181625Smax.romanov@nginx.com        self.check_frame(frame, True, self.ws.OP_TEXT, 'fragment1fragment2')
8191625Smax.romanov@nginx.com
8201625Smax.romanov@nginx.com        # 5_7
8211625Smax.romanov@nginx.com
8221625Smax.romanov@nginx.com        ping_payload = 'ping payload'
8231625Smax.romanov@nginx.com
8241625Smax.romanov@nginx.com        self.ws.frame_write(sock, self.ws.OP_TEXT, 'fragment1', fin=False)
8251625Smax.romanov@nginx.com        assert self.recvall(sock, read_timeout=0.1) == b'', '5_7'
8261625Smax.romanov@nginx.com
8271625Smax.romanov@nginx.com        self.ws.frame_write(sock, self.ws.OP_PING, ping_payload)
8281625Smax.romanov@nginx.com
8291625Smax.romanov@nginx.com        frame = self.ws.frame_read(sock)
8301625Smax.romanov@nginx.com        self.check_frame(frame, True, self.ws.OP_PONG, ping_payload)
8311625Smax.romanov@nginx.com
8321625Smax.romanov@nginx.com        self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment2', fin=True)
8331625Smax.romanov@nginx.com
8341625Smax.romanov@nginx.com        frame = self.ws.frame_read(sock)
8351625Smax.romanov@nginx.com        self.check_frame(frame, True, self.ws.OP_TEXT, 'fragment1fragment2')
8361625Smax.romanov@nginx.com
8371625Smax.romanov@nginx.com        # 5_8
8381625Smax.romanov@nginx.com
8391625Smax.romanov@nginx.com        ping_payload = 'ping payload'
8401625Smax.romanov@nginx.com
8411625Smax.romanov@nginx.com        self.ws.frame_write(
8421625Smax.romanov@nginx.com            sock, self.ws.OP_TEXT, 'fragment1', fin=False, chopsize=1
8431625Smax.romanov@nginx.com        )
8441625Smax.romanov@nginx.com        self.ws.frame_write(sock, self.ws.OP_PING, ping_payload, chopsize=1)
8451625Smax.romanov@nginx.com        self.ws.frame_write(
8461625Smax.romanov@nginx.com            sock, self.ws.OP_CONT, 'fragment2', fin=True, chopsize=1
8471625Smax.romanov@nginx.com        )
8481625Smax.romanov@nginx.com
8491625Smax.romanov@nginx.com        frame = self.ws.frame_read(sock)
8501625Smax.romanov@nginx.com        self.check_frame(frame, True, self.ws.OP_PONG, ping_payload)
8511625Smax.romanov@nginx.com
8521625Smax.romanov@nginx.com        frame = self.ws.frame_read(sock)
8531625Smax.romanov@nginx.com        self.check_frame(frame, True, self.ws.OP_TEXT, 'fragment1fragment2')
8541625Smax.romanov@nginx.com
8551625Smax.romanov@nginx.com        # 5_9
8561625Smax.romanov@nginx.com
8571625Smax.romanov@nginx.com        self.ws.frame_write(
8581625Smax.romanov@nginx.com            sock, self.ws.OP_CONT, 'non-continuation payload', fin=True
8591625Smax.romanov@nginx.com        )
8601625Smax.romanov@nginx.com        self.ws.frame_write(sock, self.ws.OP_TEXT, 'Hello, world!', fin=True)
8611625Smax.romanov@nginx.com        self.check_close(sock, 1002)
8621625Smax.romanov@nginx.com
8631625Smax.romanov@nginx.com        # 5_10
8641625Smax.romanov@nginx.com
8651625Smax.romanov@nginx.com        _, sock, _ = self.ws.upgrade()
8661625Smax.romanov@nginx.com
8671625Smax.romanov@nginx.com        self.ws.frame_write(
8681625Smax.romanov@nginx.com            sock, self.ws.OP_CONT, 'non-continuation payload', fin=True
8691625Smax.romanov@nginx.com        )
8701625Smax.romanov@nginx.com        self.ws.frame_write(sock, self.ws.OP_TEXT, 'Hello, world!', fin=True)
8711625Smax.romanov@nginx.com        self.check_close(sock, 1002)
8721625Smax.romanov@nginx.com
8731625Smax.romanov@nginx.com        # 5_11
8741625Smax.romanov@nginx.com
8751625Smax.romanov@nginx.com        _, sock, _ = self.ws.upgrade()
8761625Smax.romanov@nginx.com
8771625Smax.romanov@nginx.com        self.ws.frame_write(
8781625Smax.romanov@nginx.com            sock,
8791625Smax.romanov@nginx.com            self.ws.OP_CONT,
8801625Smax.romanov@nginx.com            'non-continuation payload',
8811625Smax.romanov@nginx.com            fin=True,
8821625Smax.romanov@nginx.com            chopsize=1,
8831625Smax.romanov@nginx.com        )
8841625Smax.romanov@nginx.com        self.ws.frame_write(
8851625Smax.romanov@nginx.com            sock, self.ws.OP_TEXT, 'Hello, world!', fin=True, chopsize=1
8861625Smax.romanov@nginx.com        )
8871625Smax.romanov@nginx.com        self.check_close(sock, 1002)
8881625Smax.romanov@nginx.com
8891625Smax.romanov@nginx.com        # 5_12
8901625Smax.romanov@nginx.com
8911625Smax.romanov@nginx.com        _, sock, _ = self.ws.upgrade()
8921625Smax.romanov@nginx.com
8931625Smax.romanov@nginx.com        self.ws.frame_write(
8941625Smax.romanov@nginx.com            sock, self.ws.OP_CONT, 'non-continuation payload', fin=False
8951625Smax.romanov@nginx.com        )
8961625Smax.romanov@nginx.com        self.ws.frame_write(sock, self.ws.OP_TEXT, 'Hello, world!', fin=True)
8971625Smax.romanov@nginx.com        self.check_close(sock, 1002)
8981625Smax.romanov@nginx.com
8991625Smax.romanov@nginx.com        # 5_13
9001625Smax.romanov@nginx.com
9011625Smax.romanov@nginx.com        _, sock, _ = self.ws.upgrade()
9021625Smax.romanov@nginx.com
9031625Smax.romanov@nginx.com        self.ws.frame_write(
9041625Smax.romanov@nginx.com            sock, self.ws.OP_CONT, 'non-continuation payload', fin=False
9051625Smax.romanov@nginx.com        )
9061625Smax.romanov@nginx.com        self.ws.frame_write(sock, self.ws.OP_TEXT, 'Hello, world!', fin=True)
9071625Smax.romanov@nginx.com        self.check_close(sock, 1002)
9081625Smax.romanov@nginx.com
9091625Smax.romanov@nginx.com        # 5_14
9101625Smax.romanov@nginx.com
9111625Smax.romanov@nginx.com        _, sock, _ = self.ws.upgrade()
9121625Smax.romanov@nginx.com
9131625Smax.romanov@nginx.com        self.ws.frame_write(
9141625Smax.romanov@nginx.com            sock,
9151625Smax.romanov@nginx.com            self.ws.OP_CONT,
9161625Smax.romanov@nginx.com            'non-continuation payload',
9171625Smax.romanov@nginx.com            fin=False,
9181625Smax.romanov@nginx.com            chopsize=1,
9191625Smax.romanov@nginx.com        )
9201625Smax.romanov@nginx.com        self.ws.frame_write(
9211625Smax.romanov@nginx.com            sock, self.ws.OP_TEXT, 'Hello, world!', fin=True, chopsize=1
9221625Smax.romanov@nginx.com        )
9231625Smax.romanov@nginx.com        self.check_close(sock, 1002)
9241625Smax.romanov@nginx.com
9251625Smax.romanov@nginx.com        # 5_15
9261625Smax.romanov@nginx.com
9271625Smax.romanov@nginx.com        _, sock, _ = self.ws.upgrade()
9281625Smax.romanov@nginx.com
9291625Smax.romanov@nginx.com        self.ws.frame_write(sock, self.ws.OP_TEXT, 'fragment1', fin=False)
9301625Smax.romanov@nginx.com        self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment2', fin=True)
9311625Smax.romanov@nginx.com        self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment3', fin=False)
9321625Smax.romanov@nginx.com        self.ws.frame_write(sock, self.ws.OP_TEXT, 'fragment4', fin=True)
9331625Smax.romanov@nginx.com        self.check_close(sock, 1002)
9341625Smax.romanov@nginx.com
9351625Smax.romanov@nginx.com        # 5_16
9361625Smax.romanov@nginx.com
9371625Smax.romanov@nginx.com        _, sock, _ = self.ws.upgrade()
9381625Smax.romanov@nginx.com
9391625Smax.romanov@nginx.com        for i in range(0, 2):
9401625Smax.romanov@nginx.com            self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment1', fin=False)
9411625Smax.romanov@nginx.com            self.ws.frame_write(sock, self.ws.OP_TEXT, 'fragment2', fin=False)
9421625Smax.romanov@nginx.com            self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment3', fin=True)
9431625Smax.romanov@nginx.com        self.check_close(sock, 1002)
9441625Smax.romanov@nginx.com
9451625Smax.romanov@nginx.com        # 5_17
9461625Smax.romanov@nginx.com
9471625Smax.romanov@nginx.com        _, sock, _ = self.ws.upgrade()
9481625Smax.romanov@nginx.com
9491625Smax.romanov@nginx.com        for i in range(0, 2):
9501625Smax.romanov@nginx.com            self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment1', fin=True)
9511625Smax.romanov@nginx.com            self.ws.frame_write(sock, self.ws.OP_TEXT, 'fragment2', fin=False)
9521625Smax.romanov@nginx.com            self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment3', fin=True)
9531625Smax.romanov@nginx.com        self.check_close(sock, 1002)
9541625Smax.romanov@nginx.com
9551625Smax.romanov@nginx.com        # 5_18
9561625Smax.romanov@nginx.com
9571625Smax.romanov@nginx.com        _, sock, _ = self.ws.upgrade()
9581625Smax.romanov@nginx.com
9591625Smax.romanov@nginx.com        self.ws.frame_write(sock, self.ws.OP_TEXT, 'fragment1', fin=False)
9601625Smax.romanov@nginx.com        self.ws.frame_write(sock, self.ws.OP_TEXT, 'fragment2')
9611625Smax.romanov@nginx.com        self.check_close(sock, 1002)
9621625Smax.romanov@nginx.com
9631625Smax.romanov@nginx.com        # 5_19
9641625Smax.romanov@nginx.com
9651625Smax.romanov@nginx.com        _, sock, _ = self.ws.upgrade()
9661625Smax.romanov@nginx.com
9671625Smax.romanov@nginx.com        self.ws.frame_write(sock, self.ws.OP_TEXT, 'fragment1', fin=False)
9681625Smax.romanov@nginx.com        self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment2', fin=False)
9691625Smax.romanov@nginx.com        self.ws.frame_write(sock, self.ws.OP_PING, 'pongme 1!')
9701625Smax.romanov@nginx.com
9711625Smax.romanov@nginx.com        time.sleep(1)
9721625Smax.romanov@nginx.com
9731625Smax.romanov@nginx.com        self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment3', fin=False)
9741625Smax.romanov@nginx.com        self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment4', fin=False)
9751625Smax.romanov@nginx.com        self.ws.frame_write(sock, self.ws.OP_PING, 'pongme 2!')
9761625Smax.romanov@nginx.com        self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment5')
9771625Smax.romanov@nginx.com
9781625Smax.romanov@nginx.com        frame = self.ws.frame_read(sock)
9791625Smax.romanov@nginx.com        self.check_frame(frame, True, self.ws.OP_PONG, 'pongme 1!')
9801625Smax.romanov@nginx.com
9811625Smax.romanov@nginx.com        frame = self.ws.frame_read(sock)
9821625Smax.romanov@nginx.com        self.check_frame(frame, True, self.ws.OP_PONG, 'pongme 2!')
9831625Smax.romanov@nginx.com
9841625Smax.romanov@nginx.com        self.check_frame(
9851625Smax.romanov@nginx.com            self.ws.frame_read(sock),
9861625Smax.romanov@nginx.com            True,
9871625Smax.romanov@nginx.com            self.ws.OP_TEXT,
9881625Smax.romanov@nginx.com            'fragment1fragment2fragment3fragment4fragment5',
9891625Smax.romanov@nginx.com        )
9901625Smax.romanov@nginx.com
9911625Smax.romanov@nginx.com        # 5_20
9921625Smax.romanov@nginx.com
9931625Smax.romanov@nginx.com        self.ws.frame_write(sock, self.ws.OP_TEXT, 'fragment1', fin=False)
9941625Smax.romanov@nginx.com        self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment2', fin=False)
9951625Smax.romanov@nginx.com        self.ws.frame_write(sock, self.ws.OP_PING, 'pongme 1!')
9961625Smax.romanov@nginx.com
9971625Smax.romanov@nginx.com        frame = self.ws.frame_read(sock)
9981625Smax.romanov@nginx.com        self.check_frame(frame, True, self.ws.OP_PONG, 'pongme 1!')
9991625Smax.romanov@nginx.com
10001625Smax.romanov@nginx.com        time.sleep(1)
10011625Smax.romanov@nginx.com
10021625Smax.romanov@nginx.com        self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment3', fin=False)
10031625Smax.romanov@nginx.com        self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment4', fin=False)
10041625Smax.romanov@nginx.com        self.ws.frame_write(sock, self.ws.OP_PING, 'pongme 2!')
10051625Smax.romanov@nginx.com
10061625Smax.romanov@nginx.com        frame = self.ws.frame_read(sock)
10071625Smax.romanov@nginx.com        self.check_frame(frame, True, self.ws.OP_PONG, 'pongme 2!')
10081625Smax.romanov@nginx.com
10091625Smax.romanov@nginx.com        assert self.recvall(sock, read_timeout=0.1) == b'', '5_20'
10101625Smax.romanov@nginx.com        self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment5')
10111625Smax.romanov@nginx.com
10121625Smax.romanov@nginx.com        self.check_frame(
10131625Smax.romanov@nginx.com            self.ws.frame_read(sock),
10141625Smax.romanov@nginx.com            True,
10151625Smax.romanov@nginx.com            self.ws.OP_TEXT,
10161625Smax.romanov@nginx.com            'fragment1fragment2fragment3fragment4fragment5',
10171625Smax.romanov@nginx.com        )
10181625Smax.romanov@nginx.com
10191625Smax.romanov@nginx.com        self.close_connection(sock)
10201625Smax.romanov@nginx.com
10211625Smax.romanov@nginx.com    def test_asgi_websockets_6_1_1__6_4_4(self):
10221625Smax.romanov@nginx.com        self.load('websockets/mirror')
10231625Smax.romanov@nginx.com
10241625Smax.romanov@nginx.com        # 6_1_1
10251625Smax.romanov@nginx.com
10261625Smax.romanov@nginx.com        _, sock, _ = self.ws.upgrade()
10271625Smax.romanov@nginx.com
10281625Smax.romanov@nginx.com        self.ws.frame_write(sock, self.ws.OP_TEXT, '')
10291625Smax.romanov@nginx.com        frame = self.ws.frame_read(sock)
10301625Smax.romanov@nginx.com        self.check_frame(frame, True, self.ws.OP_TEXT, '')
10311625Smax.romanov@nginx.com
10321625Smax.romanov@nginx.com        # 6_1_2
10331625Smax.romanov@nginx.com
10341625Smax.romanov@nginx.com        self.ws.frame_write(sock, self.ws.OP_TEXT, '', fin=False)
10351625Smax.romanov@nginx.com        self.ws.frame_write(sock, self.ws.OP_CONT, '', fin=False)
10361625Smax.romanov@nginx.com        self.ws.frame_write(sock, self.ws.OP_CONT, '')
10371625Smax.romanov@nginx.com
10381625Smax.romanov@nginx.com        frame = self.ws.frame_read(sock)
10391625Smax.romanov@nginx.com        self.check_frame(frame, True, self.ws.OP_TEXT, '')
10401625Smax.romanov@nginx.com
10411625Smax.romanov@nginx.com        # 6_1_3
10421625Smax.romanov@nginx.com
10431625Smax.romanov@nginx.com        payload = 'middle frame payload'
10441625Smax.romanov@nginx.com
10451625Smax.romanov@nginx.com        self.ws.frame_write(sock, self.ws.OP_TEXT, '', fin=False)
10461625Smax.romanov@nginx.com        self.ws.frame_write(sock, self.ws.OP_CONT, payload, fin=False)
10471625Smax.romanov@nginx.com        self.ws.frame_write(sock, self.ws.OP_CONT, '')
10481625Smax.romanov@nginx.com
10491625Smax.romanov@nginx.com        frame = self.ws.frame_read(sock)
10501625Smax.romanov@nginx.com        self.check_frame(frame, True, self.ws.OP_TEXT, payload)
10511625Smax.romanov@nginx.com
10521625Smax.romanov@nginx.com        # 6_2_1
10531625Smax.romanov@nginx.com
10541625Smax.romanov@nginx.com        payload = 'Hello-µ@ßöäüàá-UTF-8!!'
10551625Smax.romanov@nginx.com
10561625Smax.romanov@nginx.com        self.ws.frame_write(sock, self.ws.OP_TEXT, payload)
10571625Smax.romanov@nginx.com
10581625Smax.romanov@nginx.com        frame = self.ws.frame_read(sock)
10591625Smax.romanov@nginx.com        self.check_frame(frame, True, self.ws.OP_TEXT, payload)
10601625Smax.romanov@nginx.com
10611625Smax.romanov@nginx.com        # 6_2_2
10621625Smax.romanov@nginx.com
10631625Smax.romanov@nginx.com        self.ws.frame_write(sock, self.ws.OP_TEXT, payload[:12], fin=False)
10641625Smax.romanov@nginx.com        self.ws.frame_write(sock, self.ws.OP_CONT, payload[12:])
10651625Smax.romanov@nginx.com
10661625Smax.romanov@nginx.com        frame = self.ws.frame_read(sock)
10671625Smax.romanov@nginx.com        self.check_frame(frame, True, self.ws.OP_TEXT, payload)
10681625Smax.romanov@nginx.com
10691625Smax.romanov@nginx.com        # 6_2_3
10701625Smax.romanov@nginx.com
10711625Smax.romanov@nginx.com        self.ws.message(sock, self.ws.OP_TEXT, payload, fragmention_size=1)
10721625Smax.romanov@nginx.com
10731625Smax.romanov@nginx.com        frame = self.ws.frame_read(sock)
10741625Smax.romanov@nginx.com        self.check_frame(frame, True, self.ws.OP_TEXT, payload)
10751625Smax.romanov@nginx.com
10761625Smax.romanov@nginx.com        # 6_2_4
10771625Smax.romanov@nginx.com
10781625Smax.romanov@nginx.com        payload = '\xce\xba\xe1\xbd\xb9\xcf\x83\xce\xbc\xce\xb5'
10791625Smax.romanov@nginx.com
10801625Smax.romanov@nginx.com        self.ws.message(sock, self.ws.OP_TEXT, payload, fragmention_size=1)
10811625Smax.romanov@nginx.com
10821625Smax.romanov@nginx.com        frame = self.ws.frame_read(sock)
10831625Smax.romanov@nginx.com        self.check_frame(frame, True, self.ws.OP_TEXT, payload)
10841625Smax.romanov@nginx.com
10851625Smax.romanov@nginx.com        self.close_connection(sock)
10861625Smax.romanov@nginx.com
10871625Smax.romanov@nginx.com#        Unit does not support UTF-8 validation
10881625Smax.romanov@nginx.com#
10891625Smax.romanov@nginx.com#        # 6_3_1 FAIL
10901625Smax.romanov@nginx.com#
10911625Smax.romanov@nginx.com#        payload_1 = '\xce\xba\xe1\xbd\xb9\xcf\x83\xce\xbc\xce\xb5'
10921625Smax.romanov@nginx.com#        payload_2 = '\xed\xa0\x80'
10931625Smax.romanov@nginx.com#        payload_3 = '\x65\x64\x69\x74\x65\x64'
10941625Smax.romanov@nginx.com#
10951625Smax.romanov@nginx.com#        payload = payload_1 + payload_2 + payload_3
10961625Smax.romanov@nginx.com#
10971625Smax.romanov@nginx.com#        self.ws.message(sock, self.ws.OP_TEXT, payload)
10981625Smax.romanov@nginx.com#        self.check_close(sock, 1007)
10991625Smax.romanov@nginx.com#
11001625Smax.romanov@nginx.com#        # 6_3_2 FAIL
11011625Smax.romanov@nginx.com#
11021625Smax.romanov@nginx.com#        _, sock, _ = self.ws.upgrade()
11031625Smax.romanov@nginx.com#
11041625Smax.romanov@nginx.com#        self.ws.message(sock, self.ws.OP_TEXT, payload, fragmention_size=1)
11051625Smax.romanov@nginx.com#        self.check_close(sock, 1007)
11061625Smax.romanov@nginx.com#
11071625Smax.romanov@nginx.com#        # 6_4_1 ... 6_4_4 FAIL
11081625Smax.romanov@nginx.com
11091625Smax.romanov@nginx.com    def test_asgi_websockets_7_1_1__7_5_1(self):
11101625Smax.romanov@nginx.com        self.load('websockets/mirror')
11111625Smax.romanov@nginx.com
11121625Smax.romanov@nginx.com        # 7_1_1
11131625Smax.romanov@nginx.com
11141625Smax.romanov@nginx.com        _, sock, _ = self.ws.upgrade()
11151625Smax.romanov@nginx.com
11161625Smax.romanov@nginx.com        payload = "Hello World!"
11171625Smax.romanov@nginx.com
11181625Smax.romanov@nginx.com        self.ws.frame_write(sock, self.ws.OP_TEXT, payload)
11191625Smax.romanov@nginx.com
11201625Smax.romanov@nginx.com        frame = self.ws.frame_read(sock)
11211625Smax.romanov@nginx.com        self.check_frame(frame, True, self.ws.OP_TEXT, payload)
11221625Smax.romanov@nginx.com
11231625Smax.romanov@nginx.com        self.close_connection(sock)
11241625Smax.romanov@nginx.com
11251625Smax.romanov@nginx.com        # 7_1_2
11261625Smax.romanov@nginx.com
11271625Smax.romanov@nginx.com        _, sock, _ = self.ws.upgrade()
11281625Smax.romanov@nginx.com
11291625Smax.romanov@nginx.com        self.ws.frame_write(sock, self.ws.OP_CLOSE, self.ws.serialize_close())
11301625Smax.romanov@nginx.com        self.ws.frame_write(sock, self.ws.OP_CLOSE, self.ws.serialize_close())
11311625Smax.romanov@nginx.com
11321625Smax.romanov@nginx.com        self.check_close(sock)
11331625Smax.romanov@nginx.com
11341625Smax.romanov@nginx.com        # 7_1_3
11351625Smax.romanov@nginx.com
11361625Smax.romanov@nginx.com        _, sock, _ = self.ws.upgrade()
11371625Smax.romanov@nginx.com
11381625Smax.romanov@nginx.com        self.ws.frame_write(sock, self.ws.OP_CLOSE, self.ws.serialize_close())
11391625Smax.romanov@nginx.com        self.check_close(sock, no_close=True)
11401625Smax.romanov@nginx.com
11411625Smax.romanov@nginx.com        self.ws.frame_write(sock, self.ws.OP_PING, '')
11421625Smax.romanov@nginx.com        assert self.recvall(sock, read_timeout=0.1) == b'', 'empty soc'
11431625Smax.romanov@nginx.com
11441625Smax.romanov@nginx.com        sock.close()
11451625Smax.romanov@nginx.com
11461625Smax.romanov@nginx.com        # 7_1_4
11471625Smax.romanov@nginx.com
11481625Smax.romanov@nginx.com        _, sock, _ = self.ws.upgrade()
11491625Smax.romanov@nginx.com
11501625Smax.romanov@nginx.com        self.ws.frame_write(sock, self.ws.OP_CLOSE, self.ws.serialize_close())
11511625Smax.romanov@nginx.com        self.check_close(sock, no_close=True)
11521625Smax.romanov@nginx.com
11531625Smax.romanov@nginx.com        self.ws.frame_write(sock, self.ws.OP_TEXT, payload)
11541625Smax.romanov@nginx.com        assert self.recvall(sock, read_timeout=0.1) == b'', 'empty soc'
11551625Smax.romanov@nginx.com
11561625Smax.romanov@nginx.com        sock.close()
11571625Smax.romanov@nginx.com
11581625Smax.romanov@nginx.com        # 7_1_5
11591625Smax.romanov@nginx.com
11601625Smax.romanov@nginx.com        _, sock, _ = self.ws.upgrade()
11611625Smax.romanov@nginx.com
11621625Smax.romanov@nginx.com        self.ws.frame_write(sock, self.ws.OP_TEXT, 'fragment1', fin=False)
11631625Smax.romanov@nginx.com        self.ws.frame_write(sock, self.ws.OP_CLOSE, self.ws.serialize_close())
11641625Smax.romanov@nginx.com        self.check_close(sock, no_close=True)
11651625Smax.romanov@nginx.com
11661625Smax.romanov@nginx.com        self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment2')
11671625Smax.romanov@nginx.com        assert self.recvall(sock, read_timeout=0.1) == b'', 'empty soc'
11681625Smax.romanov@nginx.com
11691625Smax.romanov@nginx.com        sock.close()
11701625Smax.romanov@nginx.com
11711625Smax.romanov@nginx.com        # 7_1_6
11721625Smax.romanov@nginx.com
11731625Smax.romanov@nginx.com        _, sock, _ = self.ws.upgrade()
11741625Smax.romanov@nginx.com
11751625Smax.romanov@nginx.com        self.ws.frame_write(sock, self.ws.OP_TEXT, 'BAsd7&jh23' * 26 * 2 ** 10)
11761625Smax.romanov@nginx.com        self.ws.frame_write(sock, self.ws.OP_TEXT, payload)
11771625Smax.romanov@nginx.com        self.ws.frame_write(sock, self.ws.OP_CLOSE, self.ws.serialize_close())
11781625Smax.romanov@nginx.com
11791625Smax.romanov@nginx.com        self.recvall(sock, read_timeout=1)
11801625Smax.romanov@nginx.com
11811625Smax.romanov@nginx.com        self.ws.frame_write(sock, self.ws.OP_PING, '')
11821625Smax.romanov@nginx.com        assert self.recvall(sock, read_timeout=0.1) == b'', 'empty soc'
11831625Smax.romanov@nginx.com
11841625Smax.romanov@nginx.com        sock.close()
11851625Smax.romanov@nginx.com
11861625Smax.romanov@nginx.com        # 7_3_1
11871625Smax.romanov@nginx.com
11881625Smax.romanov@nginx.com        _, sock, _ = self.ws.upgrade()
11891625Smax.romanov@nginx.com
11901625Smax.romanov@nginx.com        self.ws.frame_write(sock, self.ws.OP_CLOSE, '')
11911625Smax.romanov@nginx.com        self.check_close(sock)
11921625Smax.romanov@nginx.com
11931625Smax.romanov@nginx.com        # 7_3_2
11941625Smax.romanov@nginx.com
11951625Smax.romanov@nginx.com        _, sock, _ = self.ws.upgrade()
11961625Smax.romanov@nginx.com
11971625Smax.romanov@nginx.com        self.ws.frame_write(sock, self.ws.OP_CLOSE, 'a')
11981625Smax.romanov@nginx.com        self.check_close(sock, 1002)
11991625Smax.romanov@nginx.com
12001625Smax.romanov@nginx.com        # 7_3_3
12011625Smax.romanov@nginx.com
12021625Smax.romanov@nginx.com        _, sock, _ = self.ws.upgrade()
12031625Smax.romanov@nginx.com
12041625Smax.romanov@nginx.com        self.ws.frame_write(sock, self.ws.OP_CLOSE, self.ws.serialize_close())
12051625Smax.romanov@nginx.com        self.check_close(sock)
12061625Smax.romanov@nginx.com
12071625Smax.romanov@nginx.com        # 7_3_4
12081625Smax.romanov@nginx.com
12091625Smax.romanov@nginx.com        _, sock, _ = self.ws.upgrade()
12101625Smax.romanov@nginx.com
12111625Smax.romanov@nginx.com        payload = self.ws.serialize_close(reason='Hello World!')
12121625Smax.romanov@nginx.com
12131625Smax.romanov@nginx.com        self.ws.frame_write(sock, self.ws.OP_CLOSE, payload)
12141625Smax.romanov@nginx.com        self.check_close(sock)
12151625Smax.romanov@nginx.com
12161625Smax.romanov@nginx.com        # 7_3_5
12171625Smax.romanov@nginx.com
12181625Smax.romanov@nginx.com        _, sock, _ = self.ws.upgrade()
12191625Smax.romanov@nginx.com
12201625Smax.romanov@nginx.com        payload = self.ws.serialize_close(reason='*' * 123)
12211625Smax.romanov@nginx.com
12221625Smax.romanov@nginx.com        self.ws.frame_write(sock, self.ws.OP_CLOSE, payload)
12231625Smax.romanov@nginx.com        self.check_close(sock)
12241625Smax.romanov@nginx.com
12251625Smax.romanov@nginx.com        # 7_3_6
12261625Smax.romanov@nginx.com
12271625Smax.romanov@nginx.com        _, sock, _ = self.ws.upgrade()
12281625Smax.romanov@nginx.com
12291625Smax.romanov@nginx.com        payload = self.ws.serialize_close(reason='*' * 124)
12301625Smax.romanov@nginx.com
12311625Smax.romanov@nginx.com        self.ws.frame_write(sock, self.ws.OP_CLOSE, payload)
12321625Smax.romanov@nginx.com        self.check_close(sock, 1002)
12331625Smax.romanov@nginx.com
12341625Smax.romanov@nginx.com#        # 7_5_1 FAIL Unit does not support UTF-8 validation
12351625Smax.romanov@nginx.com#
12361625Smax.romanov@nginx.com#        _, sock, _ = self.ws.upgrade()
12371625Smax.romanov@nginx.com#
12381625Smax.romanov@nginx.com#        payload = self.ws.serialize_close(reason = '\xce\xba\xe1\xbd\xb9\xcf' \
12391625Smax.romanov@nginx.com#            '\x83\xce\xbc\xce\xb5\xed\xa0\x80\x65\x64\x69\x74\x65\x64')
12401625Smax.romanov@nginx.com#
12411625Smax.romanov@nginx.com#        self.ws.frame_write(sock, self.ws.OP_CLOSE, payload)
12421625Smax.romanov@nginx.com#        self.check_close(sock, 1007)
12431625Smax.romanov@nginx.com
12441625Smax.romanov@nginx.com    def test_asgi_websockets_7_7_X__7_9_X(self):
12451625Smax.romanov@nginx.com        self.load('websockets/mirror')
12461625Smax.romanov@nginx.com
12471625Smax.romanov@nginx.com        valid_codes = [
12481625Smax.romanov@nginx.com            1000,
12491625Smax.romanov@nginx.com            1001,
12501625Smax.romanov@nginx.com            1002,
12511625Smax.romanov@nginx.com            1003,
12521625Smax.romanov@nginx.com            1007,
12531625Smax.romanov@nginx.com            1008,
12541625Smax.romanov@nginx.com            1009,
12551625Smax.romanov@nginx.com            1010,
12561625Smax.romanov@nginx.com            1011,
12571625Smax.romanov@nginx.com            3000,
12581625Smax.romanov@nginx.com            3999,
12591625Smax.romanov@nginx.com            4000,
12601625Smax.romanov@nginx.com            4999,
12611625Smax.romanov@nginx.com        ]
12621625Smax.romanov@nginx.com
12631625Smax.romanov@nginx.com        invalid_codes = [0, 999, 1004, 1005, 1006, 1016, 1100, 2000, 2999]
12641625Smax.romanov@nginx.com
12651625Smax.romanov@nginx.com        for code in valid_codes:
12661625Smax.romanov@nginx.com            _, sock, _ = self.ws.upgrade()
12671625Smax.romanov@nginx.com
12681625Smax.romanov@nginx.com            payload = self.ws.serialize_close(code=code)
12691625Smax.romanov@nginx.com
12701625Smax.romanov@nginx.com            self.ws.frame_write(sock, self.ws.OP_CLOSE, payload)
12711625Smax.romanov@nginx.com            self.check_close(sock)
12721625Smax.romanov@nginx.com
12731625Smax.romanov@nginx.com        for code in invalid_codes:
12741625Smax.romanov@nginx.com            _, sock, _ = self.ws.upgrade()
12751625Smax.romanov@nginx.com
12761625Smax.romanov@nginx.com            payload = self.ws.serialize_close(code=code)
12771625Smax.romanov@nginx.com
12781625Smax.romanov@nginx.com            self.ws.frame_write(sock, self.ws.OP_CLOSE, payload)
12791625Smax.romanov@nginx.com            self.check_close(sock, 1002)
12801625Smax.romanov@nginx.com
12811625Smax.romanov@nginx.com    def test_asgi_websockets_7_13_1__7_13_2(self):
12821625Smax.romanov@nginx.com        self.load('websockets/mirror')
12831625Smax.romanov@nginx.com
12841625Smax.romanov@nginx.com        # 7_13_1
12851625Smax.romanov@nginx.com
12861625Smax.romanov@nginx.com        _, sock, _ = self.ws.upgrade()
12871625Smax.romanov@nginx.com
12881625Smax.romanov@nginx.com        payload = self.ws.serialize_close(code=5000)
12891625Smax.romanov@nginx.com
12901625Smax.romanov@nginx.com        self.ws.frame_write(sock, self.ws.OP_CLOSE, payload)
12911625Smax.romanov@nginx.com        self.check_close(sock, 1002)
12921625Smax.romanov@nginx.com
12931625Smax.romanov@nginx.com        # 7_13_2
12941625Smax.romanov@nginx.com
12951625Smax.romanov@nginx.com        _, sock, _ = self.ws.upgrade()
12961625Smax.romanov@nginx.com
12971625Smax.romanov@nginx.com        payload = struct.pack('!I', 65536) + ''.encode('utf-8')
12981625Smax.romanov@nginx.com
12991625Smax.romanov@nginx.com        self.ws.frame_write(sock, self.ws.OP_CLOSE, payload)
13001625Smax.romanov@nginx.com        self.check_close(sock, 1002)
13011625Smax.romanov@nginx.com
13021625Smax.romanov@nginx.com    def test_asgi_websockets_9_1_1__9_6_6(self, is_unsafe):
13031625Smax.romanov@nginx.com        if not is_unsafe:
13041625Smax.romanov@nginx.com            pytest.skip('unsafe, long run')
13051625Smax.romanov@nginx.com
13061625Smax.romanov@nginx.com        self.load('websockets/mirror')
13071625Smax.romanov@nginx.com
13081625Smax.romanov@nginx.com        assert 'success' in self.conf(
13091625Smax.romanov@nginx.com            {
13101625Smax.romanov@nginx.com                'http': {
13111625Smax.romanov@nginx.com                    'websocket': {
13121625Smax.romanov@nginx.com                        'max_frame_size': 33554432,
13131625Smax.romanov@nginx.com                        'keepalive_interval': 0,
13141625Smax.romanov@nginx.com                    }
13151625Smax.romanov@nginx.com                }
13161625Smax.romanov@nginx.com            },
13171625Smax.romanov@nginx.com            'settings',
13181625Smax.romanov@nginx.com        ), 'increase max_frame_size and keepalive_interval'
13191625Smax.romanov@nginx.com
13201625Smax.romanov@nginx.com        _, sock, _ = self.ws.upgrade()
13211625Smax.romanov@nginx.com
13221625Smax.romanov@nginx.com        op_text = self.ws.OP_TEXT
13231625Smax.romanov@nginx.com        op_binary = self.ws.OP_BINARY
13241625Smax.romanov@nginx.com
13251625Smax.romanov@nginx.com        def check_payload(opcode, length, chopsize=None):
13261625Smax.romanov@nginx.com            if opcode == self.ws.OP_TEXT:
13271625Smax.romanov@nginx.com                payload = '*' * length
13281625Smax.romanov@nginx.com            else:
13291625Smax.romanov@nginx.com                payload = b'*' * length
13301625Smax.romanov@nginx.com
13311625Smax.romanov@nginx.com            self.ws.frame_write(sock, opcode, payload, chopsize=chopsize)
13321625Smax.romanov@nginx.com            frame = self.ws.frame_read(sock, read_timeout=5)
13331625Smax.romanov@nginx.com            self.check_frame(frame, True, opcode, payload)
13341625Smax.romanov@nginx.com
13351625Smax.romanov@nginx.com        def check_message(opcode, f_size):
13361625Smax.romanov@nginx.com            if opcode == self.ws.OP_TEXT:
13371625Smax.romanov@nginx.com                payload = '*' * 4 * 2 ** 20
13381625Smax.romanov@nginx.com            else:
13391625Smax.romanov@nginx.com                payload = b'*' * 4 * 2 ** 20
13401625Smax.romanov@nginx.com
13411625Smax.romanov@nginx.com            self.ws.message(sock, opcode, payload, fragmention_size=f_size)
13421625Smax.romanov@nginx.com            frame = self.ws.frame_read(sock, read_timeout=5)
13431625Smax.romanov@nginx.com            self.check_frame(frame, True, opcode, payload)
13441625Smax.romanov@nginx.com
13451625Smax.romanov@nginx.com        check_payload(op_text, 64 * 2 ** 10)              # 9_1_1
13461625Smax.romanov@nginx.com        check_payload(op_text, 256 * 2 ** 10)             # 9_1_2
13471625Smax.romanov@nginx.com        check_payload(op_text, 2 ** 20)                   # 9_1_3
13481625Smax.romanov@nginx.com        check_payload(op_text, 4 * 2 ** 20)               # 9_1_4
13491625Smax.romanov@nginx.com        check_payload(op_text, 8 * 2 ** 20)               # 9_1_5
13501625Smax.romanov@nginx.com        check_payload(op_text, 16 * 2 ** 20)              # 9_1_6
13511625Smax.romanov@nginx.com
13521625Smax.romanov@nginx.com        check_payload(op_binary, 64 * 2 ** 10)            # 9_2_1
13531625Smax.romanov@nginx.com        check_payload(op_binary, 256 * 2 ** 10)           # 9_2_2
13541625Smax.romanov@nginx.com        check_payload(op_binary, 2 ** 20)                 # 9_2_3
13551625Smax.romanov@nginx.com        check_payload(op_binary, 4 * 2 ** 20)             # 9_2_4
13561625Smax.romanov@nginx.com        check_payload(op_binary, 8 * 2 ** 20)             # 9_2_5
13571625Smax.romanov@nginx.com        check_payload(op_binary, 16 * 2 ** 20)            # 9_2_6
13581625Smax.romanov@nginx.com
13591625Smax.romanov@nginx.com        if option.system != 'Darwin' and option.system != 'FreeBSD':
13601625Smax.romanov@nginx.com            check_message(op_text, 64)                    # 9_3_1
13611625Smax.romanov@nginx.com            check_message(op_text, 256)                   # 9_3_2
13621625Smax.romanov@nginx.com            check_message(op_text, 2 ** 10)               # 9_3_3
13631625Smax.romanov@nginx.com            check_message(op_text, 4 * 2 ** 10)           # 9_3_4
13641625Smax.romanov@nginx.com            check_message(op_text, 16 * 2 ** 10)          # 9_3_5
13651625Smax.romanov@nginx.com            check_message(op_text, 64 * 2 ** 10)          # 9_3_6
13661625Smax.romanov@nginx.com            check_message(op_text, 256 * 2 ** 10)         # 9_3_7
13671625Smax.romanov@nginx.com            check_message(op_text, 2 ** 20)               # 9_3_8
13681625Smax.romanov@nginx.com            check_message(op_text, 4 * 2 ** 20)           # 9_3_9
13691625Smax.romanov@nginx.com
13701625Smax.romanov@nginx.com            check_message(op_binary, 64)                  # 9_4_1
13711625Smax.romanov@nginx.com            check_message(op_binary, 256)                 # 9_4_2
13721625Smax.romanov@nginx.com            check_message(op_binary, 2 ** 10)             # 9_4_3
13731625Smax.romanov@nginx.com            check_message(op_binary, 4 * 2 ** 10)         # 9_4_4
13741625Smax.romanov@nginx.com            check_message(op_binary, 16 * 2 ** 10)        # 9_4_5
13751625Smax.romanov@nginx.com            check_message(op_binary, 64 * 2 ** 10)        # 9_4_6
13761625Smax.romanov@nginx.com            check_message(op_binary, 256 * 2 ** 10)       # 9_4_7
13771625Smax.romanov@nginx.com            check_message(op_binary, 2 ** 20)             # 9_4_8
13781625Smax.romanov@nginx.com            check_message(op_binary, 4 * 2 ** 20)         # 9_4_9
13791625Smax.romanov@nginx.com
13801625Smax.romanov@nginx.com        check_payload(op_text, 2 ** 20, chopsize=64)      # 9_5_1
13811625Smax.romanov@nginx.com        check_payload(op_text, 2 ** 20, chopsize=128)     # 9_5_2
13821625Smax.romanov@nginx.com        check_payload(op_text, 2 ** 20, chopsize=256)     # 9_5_3
13831625Smax.romanov@nginx.com        check_payload(op_text, 2 ** 20, chopsize=512)     # 9_5_4
13841625Smax.romanov@nginx.com        check_payload(op_text, 2 ** 20, chopsize=1024)    # 9_5_5
13851625Smax.romanov@nginx.com        check_payload(op_text, 2 ** 20, chopsize=2048)    # 9_5_6
13861625Smax.romanov@nginx.com
13871625Smax.romanov@nginx.com        check_payload(op_binary, 2 ** 20, chopsize=64)    # 9_6_1
13881625Smax.romanov@nginx.com        check_payload(op_binary, 2 ** 20, chopsize=128)   # 9_6_2
13891625Smax.romanov@nginx.com        check_payload(op_binary, 2 ** 20, chopsize=256)   # 9_6_3
13901625Smax.romanov@nginx.com        check_payload(op_binary, 2 ** 20, chopsize=512)   # 9_6_4
13911625Smax.romanov@nginx.com        check_payload(op_binary, 2 ** 20, chopsize=1024)  # 9_6_5
13921625Smax.romanov@nginx.com        check_payload(op_binary, 2 ** 20, chopsize=2048)  # 9_6_6
13931625Smax.romanov@nginx.com
13941625Smax.romanov@nginx.com        self.close_connection(sock)
13951625Smax.romanov@nginx.com
13961625Smax.romanov@nginx.com    def test_asgi_websockets_10_1_1(self):
13971625Smax.romanov@nginx.com        self.load('websockets/mirror')
13981625Smax.romanov@nginx.com
13991625Smax.romanov@nginx.com        _, sock, _ = self.ws.upgrade()
14001625Smax.romanov@nginx.com
14011625Smax.romanov@nginx.com        payload = '*' * 65536
14021625Smax.romanov@nginx.com
14031625Smax.romanov@nginx.com        self.ws.message(sock, self.ws.OP_TEXT, payload, fragmention_size=1300)
14041625Smax.romanov@nginx.com
14051625Smax.romanov@nginx.com        frame = self.ws.frame_read(sock)
14061625Smax.romanov@nginx.com        self.check_frame(frame, True, self.ws.OP_TEXT, payload)
14071625Smax.romanov@nginx.com
14081625Smax.romanov@nginx.com        self.close_connection(sock)
14091625Smax.romanov@nginx.com
14101625Smax.romanov@nginx.com    # settings
14111625Smax.romanov@nginx.com
14121625Smax.romanov@nginx.com    def test_asgi_websockets_max_frame_size(self):
14131625Smax.romanov@nginx.com        self.load('websockets/mirror')
14141625Smax.romanov@nginx.com
14151625Smax.romanov@nginx.com        assert 'success' in self.conf(
14161625Smax.romanov@nginx.com            {'http': {'websocket': {'max_frame_size': 100}}}, 'settings'
14171625Smax.romanov@nginx.com        ), 'configure max_frame_size'
14181625Smax.romanov@nginx.com
14191625Smax.romanov@nginx.com        _, sock, _ = self.ws.upgrade()
14201625Smax.romanov@nginx.com
14211625Smax.romanov@nginx.com        payload = '*' * 94
14221625Smax.romanov@nginx.com        opcode = self.ws.OP_TEXT
14231625Smax.romanov@nginx.com
14241625Smax.romanov@nginx.com        self.ws.frame_write(sock, opcode, payload)  # frame length is 100
14251625Smax.romanov@nginx.com
14261625Smax.romanov@nginx.com        frame = self.ws.frame_read(sock)
14271625Smax.romanov@nginx.com        self.check_frame(frame, True, opcode, payload)
14281625Smax.romanov@nginx.com
14291625Smax.romanov@nginx.com        payload = '*' * 95
14301625Smax.romanov@nginx.com
14311625Smax.romanov@nginx.com        self.ws.frame_write(sock, opcode, payload)  # frame length is 101
14321625Smax.romanov@nginx.com        self.check_close(sock, 1009)  # 1009 - CLOSE_TOO_LARGE
14331625Smax.romanov@nginx.com
14341625Smax.romanov@nginx.com    def test_asgi_websockets_read_timeout(self):
14351625Smax.romanov@nginx.com        self.load('websockets/mirror')
14361625Smax.romanov@nginx.com
14371625Smax.romanov@nginx.com        assert 'success' in self.conf(
14381625Smax.romanov@nginx.com            {'http': {'websocket': {'read_timeout': 5}}}, 'settings'
14391625Smax.romanov@nginx.com        ), 'configure read_timeout'
14401625Smax.romanov@nginx.com
14411625Smax.romanov@nginx.com        _, sock, _ = self.ws.upgrade()
14421625Smax.romanov@nginx.com
14431625Smax.romanov@nginx.com        frame = self.ws.frame_to_send(self.ws.OP_TEXT, 'blah')
14441625Smax.romanov@nginx.com        sock.sendall(frame[:2])
14451625Smax.romanov@nginx.com
14461625Smax.romanov@nginx.com        time.sleep(2)
14471625Smax.romanov@nginx.com
14481625Smax.romanov@nginx.com        self.check_close(sock, 1001)  # 1001 - CLOSE_GOING_AWAY
14491625Smax.romanov@nginx.com
14501625Smax.romanov@nginx.com    def test_asgi_websockets_keepalive_interval(self):
14511625Smax.romanov@nginx.com        self.load('websockets/mirror')
14521625Smax.romanov@nginx.com
14531625Smax.romanov@nginx.com        assert 'success' in self.conf(
14541625Smax.romanov@nginx.com            {'http': {'websocket': {'keepalive_interval': 5}}}, 'settings'
14551625Smax.romanov@nginx.com        ), 'configure keepalive_interval'
14561625Smax.romanov@nginx.com
14571625Smax.romanov@nginx.com        _, sock, _ = self.ws.upgrade()
14581625Smax.romanov@nginx.com
14591625Smax.romanov@nginx.com        frame = self.ws.frame_to_send(self.ws.OP_TEXT, 'blah')
14601625Smax.romanov@nginx.com        sock.sendall(frame[:2])
14611625Smax.romanov@nginx.com
14621625Smax.romanov@nginx.com        time.sleep(2)
14631625Smax.romanov@nginx.com
14641625Smax.romanov@nginx.com        frame = self.ws.frame_read(sock)
14651625Smax.romanov@nginx.com        self.check_frame(frame, True, self.ws.OP_PING, '')  # PING frame
14661625Smax.romanov@nginx.com
14671625Smax.romanov@nginx.com        sock.close()
1468