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