1*1130Szelenkov@nginx.comimport time
2*1130Szelenkov@nginx.comimport struct
3*1130Szelenkov@nginx.comimport unittest
4*1130Szelenkov@nginx.comfrom unit.applications.lang.node import TestApplicationNode
5*1130Szelenkov@nginx.comfrom unit.applications.websockets import TestApplicationWebsocket
6*1130Szelenkov@nginx.com
7*1130Szelenkov@nginx.comclass TestNodeWebsockets(TestApplicationNode):
8*1130Szelenkov@nginx.com    prerequisites = ['node']
9*1130Szelenkov@nginx.com
10*1130Szelenkov@nginx.com    ws = TestApplicationWebsocket()
11*1130Szelenkov@nginx.com
12*1130Szelenkov@nginx.com    @classmethod
13*1130Szelenkov@nginx.com    def setUpClass(cls):
14*1130Szelenkov@nginx.com        raise unittest.SkipTest('Websockets is not available')
15*1130Szelenkov@nginx.com
16*1130Szelenkov@nginx.com    def close_connection(self, sock):
17*1130Szelenkov@nginx.com        self.assertEqual(self.recvall(sock, read_timeout=1), b'', 'empty sock')
18*1130Szelenkov@nginx.com
19*1130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_CLOSE, self.ws.serialize_close())
20*1130Szelenkov@nginx.com
21*1130Szelenkov@nginx.com        self.check_close(sock)
22*1130Szelenkov@nginx.com
23*1130Szelenkov@nginx.com    def check_close(self, sock, code = 1000, no_close = False):
24*1130Szelenkov@nginx.com        frame = self.ws.frame_read(sock)
25*1130Szelenkov@nginx.com
26*1130Szelenkov@nginx.com        self.assertEqual(frame['fin'], True, 'close fin')
27*1130Szelenkov@nginx.com        self.assertEqual(frame['opcode'], self.ws.OP_CLOSE, 'close opcode')
28*1130Szelenkov@nginx.com        self.assertEqual(frame['code'], code, 'close code')
29*1130Szelenkov@nginx.com
30*1130Szelenkov@nginx.com        if not no_close:
31*1130Szelenkov@nginx.com            sock.close()
32*1130Szelenkov@nginx.com
33*1130Szelenkov@nginx.com    def check_frame(self, frame, fin, opcode, payload, decode=True):
34*1130Szelenkov@nginx.com        if opcode == self.ws.OP_BINARY or not decode:
35*1130Szelenkov@nginx.com            data = frame['data']
36*1130Szelenkov@nginx.com        else:
37*1130Szelenkov@nginx.com            data = frame['data'].decode('utf-8')
38*1130Szelenkov@nginx.com
39*1130Szelenkov@nginx.com        self.assertEqual(frame['fin'], fin, 'fin')
40*1130Szelenkov@nginx.com        self.assertEqual(frame['opcode'], opcode, 'opcode')
41*1130Szelenkov@nginx.com        self.assertEqual(data, payload, 'payload')
42*1130Szelenkov@nginx.com
43*1130Szelenkov@nginx.com    def test_node_websockets_handshake(self):
44*1130Szelenkov@nginx.com        self.load('websockets/mirror')
45*1130Szelenkov@nginx.com
46*1130Szelenkov@nginx.com        resp, sock, key = self.ws.upgrade()
47*1130Szelenkov@nginx.com        sock.close()
48*1130Szelenkov@nginx.com
49*1130Szelenkov@nginx.com        self.assertEqual(resp['status'], 101, 'status')
50*1130Szelenkov@nginx.com        self.assertEqual(
51*1130Szelenkov@nginx.com            resp['headers']['Upgrade'], 'websocket', 'upgrade'
52*1130Szelenkov@nginx.com        )
53*1130Szelenkov@nginx.com        self.assertEqual(
54*1130Szelenkov@nginx.com            resp['headers']['Connection'], 'Upgrade', 'connection'
55*1130Szelenkov@nginx.com        )
56*1130Szelenkov@nginx.com        self.assertEqual(
57*1130Szelenkov@nginx.com            resp['headers']['Sec-WebSocket-Accept'], self.ws.accept(key), 'key'
58*1130Szelenkov@nginx.com        )
59*1130Szelenkov@nginx.com
60*1130Szelenkov@nginx.com    def test_node_websockets_mirror(self):
61*1130Szelenkov@nginx.com        self.load('websockets/mirror')
62*1130Szelenkov@nginx.com
63*1130Szelenkov@nginx.com        message = 'blah'
64*1130Szelenkov@nginx.com
65*1130Szelenkov@nginx.com        _, sock, _ = self.ws.upgrade()
66*1130Szelenkov@nginx.com
67*1130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_TEXT, message)
68*1130Szelenkov@nginx.com        frame = self.ws.frame_read(sock)
69*1130Szelenkov@nginx.com
70*1130Szelenkov@nginx.com        self.assertEqual(
71*1130Szelenkov@nginx.com            message, frame['data'].decode('utf-8'), 'mirror'
72*1130Szelenkov@nginx.com        )
73*1130Szelenkov@nginx.com
74*1130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_TEXT, message)
75*1130Szelenkov@nginx.com        frame = self.ws.frame_read(sock)
76*1130Szelenkov@nginx.com
77*1130Szelenkov@nginx.com        self.assertEqual(
78*1130Szelenkov@nginx.com            message, frame['data'].decode('utf-8'), 'mirror 2'
79*1130Szelenkov@nginx.com        )
80*1130Szelenkov@nginx.com
81*1130Szelenkov@nginx.com        sock.close()
82*1130Szelenkov@nginx.com
83*1130Szelenkov@nginx.com    def test_node_websockets_no_mask(self):
84*1130Szelenkov@nginx.com        self.load('websockets/mirror')
85*1130Szelenkov@nginx.com
86*1130Szelenkov@nginx.com        message = 'blah'
87*1130Szelenkov@nginx.com
88*1130Szelenkov@nginx.com        _, sock, _ = self.ws.upgrade()
89*1130Szelenkov@nginx.com
90*1130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_TEXT, message, mask=False)
91*1130Szelenkov@nginx.com
92*1130Szelenkov@nginx.com        frame = self.ws.frame_read(sock)
93*1130Szelenkov@nginx.com
94*1130Szelenkov@nginx.com        self.assertEqual(frame['opcode'], self.ws.OP_CLOSE, 'no mask opcode')
95*1130Szelenkov@nginx.com        self.assertEqual(frame['code'], 1002, 'no mask close code')
96*1130Szelenkov@nginx.com
97*1130Szelenkov@nginx.com        sock.close()
98*1130Szelenkov@nginx.com
99*1130Szelenkov@nginx.com    def test_node_websockets_fragmentation(self):
100*1130Szelenkov@nginx.com        self.load('websockets/mirror')
101*1130Szelenkov@nginx.com
102*1130Szelenkov@nginx.com        message = 'blah'
103*1130Szelenkov@nginx.com
104*1130Szelenkov@nginx.com        _, sock, _ = self.ws.upgrade()
105*1130Szelenkov@nginx.com
106*1130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_TEXT, message, fin=False)
107*1130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_CONT, ' ', fin=False)
108*1130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_CONT, message)
109*1130Szelenkov@nginx.com
110*1130Szelenkov@nginx.com        frame = self.ws.frame_read(sock)
111*1130Szelenkov@nginx.com
112*1130Szelenkov@nginx.com        self.assertEqual(
113*1130Szelenkov@nginx.com            message + ' ' + message,
114*1130Szelenkov@nginx.com            frame['data'].decode('utf-8'),
115*1130Szelenkov@nginx.com            'mirror framing',
116*1130Szelenkov@nginx.com        )
117*1130Szelenkov@nginx.com
118*1130Szelenkov@nginx.com        sock.close()
119*1130Szelenkov@nginx.com
120*1130Szelenkov@nginx.com    def test_node_websockets_frame_fragmentation_invalid(self):
121*1130Szelenkov@nginx.com        self.load('websockets/mirror')
122*1130Szelenkov@nginx.com
123*1130Szelenkov@nginx.com        message = 'blah'
124*1130Szelenkov@nginx.com
125*1130Szelenkov@nginx.com        _, sock, _ = self.ws.upgrade()
126*1130Szelenkov@nginx.com
127*1130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_PING, message, fin=False)
128*1130Szelenkov@nginx.com
129*1130Szelenkov@nginx.com        frame = self.ws.frame_read(sock)
130*1130Szelenkov@nginx.com
131*1130Szelenkov@nginx.com        frame.pop('data')
132*1130Szelenkov@nginx.com        self.assertDictEqual(
133*1130Szelenkov@nginx.com            frame,
134*1130Szelenkov@nginx.com            {
135*1130Szelenkov@nginx.com                'fin': True,
136*1130Szelenkov@nginx.com                'rsv1': False,
137*1130Szelenkov@nginx.com                'rsv2': False,
138*1130Szelenkov@nginx.com                'rsv3': False,
139*1130Szelenkov@nginx.com                'opcode': self.ws.OP_CLOSE,
140*1130Szelenkov@nginx.com                'mask': 0,
141*1130Szelenkov@nginx.com                'code': 1002,
142*1130Szelenkov@nginx.com                'reason': 'Fragmented control frame',
143*1130Szelenkov@nginx.com            },
144*1130Szelenkov@nginx.com            'close frame',
145*1130Szelenkov@nginx.com        )
146*1130Szelenkov@nginx.com
147*1130Szelenkov@nginx.com        sock.close()
148*1130Szelenkov@nginx.com
149*1130Szelenkov@nginx.com    def test_node_websockets_partial_send(self):
150*1130Szelenkov@nginx.com        self.load('websockets/mirror')
151*1130Szelenkov@nginx.com
152*1130Szelenkov@nginx.com        message = 'blah'
153*1130Szelenkov@nginx.com
154*1130Szelenkov@nginx.com        _, sock, _ = self.ws.upgrade()
155*1130Szelenkov@nginx.com
156*1130Szelenkov@nginx.com        frame = self.ws.frame_to_send(self.ws.OP_TEXT, message)
157*1130Szelenkov@nginx.com        sock.sendall(frame[:1])
158*1130Szelenkov@nginx.com        sock.sendall(frame[1:2])
159*1130Szelenkov@nginx.com        sock.sendall(frame[2:3])
160*1130Szelenkov@nginx.com        sock.sendall(frame[3:])
161*1130Szelenkov@nginx.com
162*1130Szelenkov@nginx.com        frame = self.ws.frame_read(sock)
163*1130Szelenkov@nginx.com
164*1130Szelenkov@nginx.com        self.assertEqual(
165*1130Szelenkov@nginx.com            message,
166*1130Szelenkov@nginx.com            frame['data'].decode('utf-8'),
167*1130Szelenkov@nginx.com            'partial send',
168*1130Szelenkov@nginx.com        )
169*1130Szelenkov@nginx.com
170*1130Szelenkov@nginx.com        sock.close()
171*1130Szelenkov@nginx.com
172*1130Szelenkov@nginx.com    def test_node_websockets_large(self):
173*1130Szelenkov@nginx.com        self.load('websockets/mirror_fragmentation')
174*1130Szelenkov@nginx.com
175*1130Szelenkov@nginx.com        message = '0123456789' * 3000
176*1130Szelenkov@nginx.com
177*1130Szelenkov@nginx.com        _, sock, _ = self.ws.upgrade()
178*1130Szelenkov@nginx.com
179*1130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_TEXT, message)
180*1130Szelenkov@nginx.com
181*1130Szelenkov@nginx.com        frame = self.ws.frame_read(sock)
182*1130Szelenkov@nginx.com        data = frame['data'].decode('utf-8')
183*1130Szelenkov@nginx.com
184*1130Szelenkov@nginx.com        frame = self.ws.frame_read(sock)
185*1130Szelenkov@nginx.com        data += frame['data'].decode('utf-8')
186*1130Szelenkov@nginx.com
187*1130Szelenkov@nginx.com        self.assertEqual(message, data, 'large')
188*1130Szelenkov@nginx.com
189*1130Szelenkov@nginx.com        sock.close()
190*1130Szelenkov@nginx.com
191*1130Szelenkov@nginx.com    def test_node_websockets_frame_invalid_opcode(self):
192*1130Szelenkov@nginx.com        self.load('websockets/mirror')
193*1130Szelenkov@nginx.com
194*1130Szelenkov@nginx.com        message = 'blah'
195*1130Szelenkov@nginx.com
196*1130Szelenkov@nginx.com        _, sock, _ = self.ws.upgrade()
197*1130Szelenkov@nginx.com
198*1130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_TEXT, message, fin=False)
199*1130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_TEXT, message)
200*1130Szelenkov@nginx.com
201*1130Szelenkov@nginx.com        frame = self.ws.frame_read(sock)
202*1130Szelenkov@nginx.com
203*1130Szelenkov@nginx.com        frame.pop('data')
204*1130Szelenkov@nginx.com        frame.pop('reason')
205*1130Szelenkov@nginx.com        self.assertDictEqual(
206*1130Szelenkov@nginx.com            frame,
207*1130Szelenkov@nginx.com            {
208*1130Szelenkov@nginx.com                'fin': True,
209*1130Szelenkov@nginx.com                'rsv1': False,
210*1130Szelenkov@nginx.com                'rsv2': False,
211*1130Szelenkov@nginx.com                'rsv3': False,
212*1130Szelenkov@nginx.com                'opcode': self.ws.OP_CLOSE,
213*1130Szelenkov@nginx.com                'mask': 0,
214*1130Szelenkov@nginx.com                'code': 1002,
215*1130Szelenkov@nginx.com            },
216*1130Szelenkov@nginx.com            'close frame',
217*1130Szelenkov@nginx.com        )
218*1130Szelenkov@nginx.com
219*1130Szelenkov@nginx.com        sock.close()
220*1130Szelenkov@nginx.com
221*1130Szelenkov@nginx.com    def test_node_websockets_frame_invalid_opcode_2(self):
222*1130Szelenkov@nginx.com        self.load('websockets/mirror')
223*1130Szelenkov@nginx.com
224*1130Szelenkov@nginx.com        message = 'blah'
225*1130Szelenkov@nginx.com
226*1130Szelenkov@nginx.com        _, sock, _ = self.ws.upgrade()
227*1130Szelenkov@nginx.com
228*1130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_CONT, message)
229*1130Szelenkov@nginx.com
230*1130Szelenkov@nginx.com        frame = self.ws.frame_read(sock)
231*1130Szelenkov@nginx.com
232*1130Szelenkov@nginx.com        frame.pop('data')
233*1130Szelenkov@nginx.com        self.assertDictEqual(
234*1130Szelenkov@nginx.com            frame,
235*1130Szelenkov@nginx.com            {
236*1130Szelenkov@nginx.com                'fin': True,
237*1130Szelenkov@nginx.com                'rsv1': False,
238*1130Szelenkov@nginx.com                'rsv2': False,
239*1130Szelenkov@nginx.com                'rsv3': False,
240*1130Szelenkov@nginx.com                'opcode': self.ws.OP_CLOSE,
241*1130Szelenkov@nginx.com                'mask': 0,
242*1130Szelenkov@nginx.com                'code': 1002,
243*1130Szelenkov@nginx.com                'reason': 'Unrecognized opcode 0',
244*1130Szelenkov@nginx.com            },
245*1130Szelenkov@nginx.com            'close frame',
246*1130Szelenkov@nginx.com        )
247*1130Szelenkov@nginx.com
248*1130Szelenkov@nginx.com        sock.close()
249*1130Szelenkov@nginx.com
250*1130Szelenkov@nginx.com    def test_node_websockets_two_clients(self):
251*1130Szelenkov@nginx.com        self.load('websockets/mirror')
252*1130Szelenkov@nginx.com
253*1130Szelenkov@nginx.com        message1 = 'blah1'
254*1130Szelenkov@nginx.com        message2 = 'blah2'
255*1130Szelenkov@nginx.com
256*1130Szelenkov@nginx.com        _, sock1, _ = self.ws.upgrade()
257*1130Szelenkov@nginx.com        _, sock2, _ = self.ws.upgrade()
258*1130Szelenkov@nginx.com
259*1130Szelenkov@nginx.com        self.ws.frame_write(sock1, self.ws.OP_TEXT, message1)
260*1130Szelenkov@nginx.com        self.ws.frame_write(sock2, self.ws.OP_TEXT, message2)
261*1130Szelenkov@nginx.com
262*1130Szelenkov@nginx.com        frame1 = self.ws.frame_read(sock1)
263*1130Szelenkov@nginx.com        frame2 = self.ws.frame_read(sock2)
264*1130Szelenkov@nginx.com
265*1130Szelenkov@nginx.com        self.assertEqual(
266*1130Szelenkov@nginx.com            message1, frame1['data'].decode('utf-8'), 'client 1'
267*1130Szelenkov@nginx.com        )
268*1130Szelenkov@nginx.com        self.assertEqual(
269*1130Szelenkov@nginx.com            message2, frame2['data'].decode('utf-8'), 'client 2'
270*1130Szelenkov@nginx.com        )
271*1130Szelenkov@nginx.com
272*1130Szelenkov@nginx.com        sock1.close()
273*1130Szelenkov@nginx.com        sock2.close()
274*1130Szelenkov@nginx.com
275*1130Szelenkov@nginx.com    @unittest.skip('not yet')
276*1130Szelenkov@nginx.com    def test_node_websockets_handshake_upgrade_absent(self): # FAIL https://tools.ietf.org/html/rfc6455#section-4.2.1
277*1130Szelenkov@nginx.com        self.load('websockets/mirror')
278*1130Szelenkov@nginx.com
279*1130Szelenkov@nginx.com        key = self.ws.key()
280*1130Szelenkov@nginx.com        resp = self.get(headers={
281*1130Szelenkov@nginx.com            'Host': 'localhost',
282*1130Szelenkov@nginx.com            'Connection': 'Upgrade',
283*1130Szelenkov@nginx.com            'Sec-WebSocket-Key': key,
284*1130Szelenkov@nginx.com            'Sec-WebSocket-Protocol': 'chat',
285*1130Szelenkov@nginx.com            'Sec-WebSocket-Version': 13,
286*1130Szelenkov@nginx.com        }, read_timeout=1)
287*1130Szelenkov@nginx.com
288*1130Szelenkov@nginx.com        self.assertEqual(resp['status'], 400, 'upgrade absent')
289*1130Szelenkov@nginx.com
290*1130Szelenkov@nginx.com    def test_node_websockets_handshake_case_insensitive(self):
291*1130Szelenkov@nginx.com        self.load('websockets/mirror')
292*1130Szelenkov@nginx.com
293*1130Szelenkov@nginx.com        key = self.ws.key()
294*1130Szelenkov@nginx.com        resp = self.get(headers={
295*1130Szelenkov@nginx.com            'Host': 'localhost',
296*1130Szelenkov@nginx.com            'Upgrade': 'WEBSOCKET',
297*1130Szelenkov@nginx.com            'Connection': 'UPGRADE',
298*1130Szelenkov@nginx.com            'Sec-WebSocket-Key': key,
299*1130Szelenkov@nginx.com            'Sec-WebSocket-Protocol': 'chat',
300*1130Szelenkov@nginx.com            'Sec-WebSocket-Version': 13,
301*1130Szelenkov@nginx.com        }, read_timeout=1)
302*1130Szelenkov@nginx.com
303*1130Szelenkov@nginx.com        self.assertEqual(resp['status'], 101, 'status')
304*1130Szelenkov@nginx.com
305*1130Szelenkov@nginx.com    @unittest.skip('not yet')
306*1130Szelenkov@nginx.com    def test_node_websockets_handshake_connection_absent(self): # FAIL
307*1130Szelenkov@nginx.com        self.load('websockets/mirror')
308*1130Szelenkov@nginx.com
309*1130Szelenkov@nginx.com        key = self.ws.key()
310*1130Szelenkov@nginx.com        resp = self.get(headers={
311*1130Szelenkov@nginx.com            'Host': 'localhost',
312*1130Szelenkov@nginx.com            'Upgrade': 'websocket',
313*1130Szelenkov@nginx.com            'Sec-WebSocket-Key': key,
314*1130Szelenkov@nginx.com            'Sec-WebSocket-Protocol': 'chat',
315*1130Szelenkov@nginx.com            'Sec-WebSocket-Version': 13,
316*1130Szelenkov@nginx.com        }, read_timeout=1)
317*1130Szelenkov@nginx.com
318*1130Szelenkov@nginx.com        self.assertEqual(resp['status'], 400, 'status')
319*1130Szelenkov@nginx.com
320*1130Szelenkov@nginx.com    def test_node_websockets_handshake_version_absent(self):
321*1130Szelenkov@nginx.com        self.load('websockets/mirror')
322*1130Szelenkov@nginx.com
323*1130Szelenkov@nginx.com        key = self.ws.key()
324*1130Szelenkov@nginx.com        resp = self.get(headers={
325*1130Szelenkov@nginx.com            'Host': 'localhost',
326*1130Szelenkov@nginx.com            'Upgrade': 'websocket',
327*1130Szelenkov@nginx.com            'Connection': 'Upgrade',
328*1130Szelenkov@nginx.com            'Sec-WebSocket-Key': key,
329*1130Szelenkov@nginx.com            'Sec-WebSocket-Protocol': 'chat'
330*1130Szelenkov@nginx.com        }, read_timeout=1)
331*1130Szelenkov@nginx.com
332*1130Szelenkov@nginx.com        self.assertEqual(resp['status'], 426, 'status')
333*1130Szelenkov@nginx.com
334*1130Szelenkov@nginx.com    @unittest.skip('not yet')
335*1130Szelenkov@nginx.com    def test_node_websockets_handshake_key_invalid(self):
336*1130Szelenkov@nginx.com        self.load('websockets/mirror')
337*1130Szelenkov@nginx.com
338*1130Szelenkov@nginx.com        resp = self.get(headers={
339*1130Szelenkov@nginx.com            'Host': 'localhost',
340*1130Szelenkov@nginx.com            'Upgrade': 'websocket',
341*1130Szelenkov@nginx.com            'Connection': 'Upgrade',
342*1130Szelenkov@nginx.com            'Sec-WebSocket-Key': '!',
343*1130Szelenkov@nginx.com            'Sec-WebSocket-Protocol': 'chat',
344*1130Szelenkov@nginx.com            'Sec-WebSocket-Version': 13
345*1130Szelenkov@nginx.com        }, read_timeout=1)
346*1130Szelenkov@nginx.com
347*1130Szelenkov@nginx.com        self.assertEqual(resp['status'], 400, 'key length')
348*1130Szelenkov@nginx.com
349*1130Szelenkov@nginx.com        key = self.ws.key()
350*1130Szelenkov@nginx.com        resp = self.get(headers={
351*1130Szelenkov@nginx.com            'Host': 'localhost',
352*1130Szelenkov@nginx.com            'Upgrade': 'websocket',
353*1130Szelenkov@nginx.com            'Connection': 'Upgrade',
354*1130Szelenkov@nginx.com            'Sec-WebSocket-Key': [key, key],
355*1130Szelenkov@nginx.com            'Sec-WebSocket-Protocol': 'chat',
356*1130Szelenkov@nginx.com            'Sec-WebSocket-Version': 13
357*1130Szelenkov@nginx.com        }, read_timeout=1)
358*1130Szelenkov@nginx.com
359*1130Szelenkov@nginx.com        self.assertEqual(resp['status'], 400, 'key double') # FAIL https://tools.ietf.org/html/rfc6455#section-11.3.1
360*1130Szelenkov@nginx.com
361*1130Szelenkov@nginx.com    def test_node_websockets_handshake_method_invalid(self):
362*1130Szelenkov@nginx.com        self.load('websockets/mirror')
363*1130Szelenkov@nginx.com
364*1130Szelenkov@nginx.com        key = self.ws.key()
365*1130Szelenkov@nginx.com        resp = self.post(headers={
366*1130Szelenkov@nginx.com            'Host': 'localhost',
367*1130Szelenkov@nginx.com            'Upgrade': 'websocket',
368*1130Szelenkov@nginx.com            'Connection': 'Upgrade',
369*1130Szelenkov@nginx.com            'Sec-WebSocket-Key': key,
370*1130Szelenkov@nginx.com            'Sec-WebSocket-Protocol': 'chat',
371*1130Szelenkov@nginx.com            'Sec-WebSocket-Version': 13
372*1130Szelenkov@nginx.com        }, read_timeout=1)
373*1130Szelenkov@nginx.com
374*1130Szelenkov@nginx.com        self.assertEqual(resp['status'], 400, 'status')
375*1130Szelenkov@nginx.com
376*1130Szelenkov@nginx.com    def test_node_websockets_handshake_http_10(self):
377*1130Szelenkov@nginx.com        self.load('websockets/mirror')
378*1130Szelenkov@nginx.com
379*1130Szelenkov@nginx.com        key = self.ws.key()
380*1130Szelenkov@nginx.com        resp = self.get(headers={
381*1130Szelenkov@nginx.com            'Host': 'localhost',
382*1130Szelenkov@nginx.com            'Upgrade': 'websocket',
383*1130Szelenkov@nginx.com            'Connection': 'Upgrade',
384*1130Szelenkov@nginx.com            'Sec-WebSocket-Key': key,
385*1130Szelenkov@nginx.com            'Sec-WebSocket-Protocol': 'chat',
386*1130Szelenkov@nginx.com            'Sec-WebSocket-Version': 13
387*1130Szelenkov@nginx.com        }, http_10=True, read_timeout=1)
388*1130Szelenkov@nginx.com
389*1130Szelenkov@nginx.com        self.assertEqual(resp['status'], 400, 'status')
390*1130Szelenkov@nginx.com
391*1130Szelenkov@nginx.com    def test_node_websockets_handshake_uri_invalid(self):
392*1130Szelenkov@nginx.com        self.load('websockets/mirror')
393*1130Szelenkov@nginx.com
394*1130Szelenkov@nginx.com        key = self.ws.key()
395*1130Szelenkov@nginx.com        resp = self.get(headers={
396*1130Szelenkov@nginx.com            'Host': 'localhost',
397*1130Szelenkov@nginx.com            'Upgrade': 'websocket',
398*1130Szelenkov@nginx.com            'Connection': 'Upgrade',
399*1130Szelenkov@nginx.com            'Sec-WebSocket-Key': key,
400*1130Szelenkov@nginx.com            'Sec-WebSocket-Protocol': 'chat',
401*1130Szelenkov@nginx.com            'Sec-WebSocket-Version': 13
402*1130Szelenkov@nginx.com        }, url='!', read_timeout=1)
403*1130Szelenkov@nginx.com
404*1130Szelenkov@nginx.com        self.assertEqual(resp['status'], 400, 'status')
405*1130Szelenkov@nginx.com
406*1130Szelenkov@nginx.com    def test_node_websockets_protocol_absent(self):
407*1130Szelenkov@nginx.com        self.load('websockets/mirror')
408*1130Szelenkov@nginx.com
409*1130Szelenkov@nginx.com        key = self.ws.key()
410*1130Szelenkov@nginx.com        resp = self.get(headers={
411*1130Szelenkov@nginx.com            'Host': 'localhost',
412*1130Szelenkov@nginx.com            'Upgrade': 'websocket',
413*1130Szelenkov@nginx.com            'Connection': 'Upgrade',
414*1130Szelenkov@nginx.com            'Sec-WebSocket-Key': key,
415*1130Szelenkov@nginx.com            'Sec-WebSocket-Version': 13
416*1130Szelenkov@nginx.com        }, read_timeout=1)
417*1130Szelenkov@nginx.com
418*1130Szelenkov@nginx.com        self.assertEqual(resp['status'], 101, 'status')
419*1130Szelenkov@nginx.com        self.assertEqual(
420*1130Szelenkov@nginx.com            resp['headers']['Upgrade'], 'websocket', 'upgrade'
421*1130Szelenkov@nginx.com        )
422*1130Szelenkov@nginx.com        self.assertEqual(
423*1130Szelenkov@nginx.com            resp['headers']['Connection'], 'Upgrade', 'connection'
424*1130Szelenkov@nginx.com        )
425*1130Szelenkov@nginx.com        self.assertEqual(
426*1130Szelenkov@nginx.com            resp['headers']['Sec-WebSocket-Accept'], self.ws.accept(key), 'key'
427*1130Szelenkov@nginx.com        )
428*1130Szelenkov@nginx.com
429*1130Szelenkov@nginx.com    # autobahn-testsuite
430*1130Szelenkov@nginx.com
431*1130Szelenkov@nginx.com    # Some following tests fail because of Unit does not support UTF-8
432*1130Szelenkov@nginx.com    # validation for websocket frames.  It should be implemented
433*1130Szelenkov@nginx.com    # by application, if necessary.
434*1130Szelenkov@nginx.com
435*1130Szelenkov@nginx.com    def test_node_websockets_1_1_1__1_1_8(self):
436*1130Szelenkov@nginx.com        self.load('websockets/mirror')
437*1130Szelenkov@nginx.com
438*1130Szelenkov@nginx.com        opcode = self.ws.OP_TEXT
439*1130Szelenkov@nginx.com
440*1130Szelenkov@nginx.com        _, sock, _ = self.ws.upgrade()
441*1130Szelenkov@nginx.com
442*1130Szelenkov@nginx.com        def check_length(length, chopsize=None):
443*1130Szelenkov@nginx.com            payload = '*' * length
444*1130Szelenkov@nginx.com
445*1130Szelenkov@nginx.com            self.ws.frame_write(sock, opcode, payload, chopsize=chopsize)
446*1130Szelenkov@nginx.com
447*1130Szelenkov@nginx.com            frame = self.ws.frame_read(sock)
448*1130Szelenkov@nginx.com            self.check_frame(frame, True, opcode, payload)
449*1130Szelenkov@nginx.com
450*1130Szelenkov@nginx.com        check_length(0)                      # 1_1_1
451*1130Szelenkov@nginx.com        check_length(125)                    # 1_1_2
452*1130Szelenkov@nginx.com        check_length(126)                    # 1_1_3
453*1130Szelenkov@nginx.com        check_length(127)                    # 1_1_4
454*1130Szelenkov@nginx.com        check_length(128)                    # 1_1_5
455*1130Szelenkov@nginx.com        check_length(65535)                  # 1_1_6
456*1130Szelenkov@nginx.com        check_length(65536)                  # 1_1_7
457*1130Szelenkov@nginx.com        check_length(65536, chopsize = 997)  # 1_1_8
458*1130Szelenkov@nginx.com
459*1130Szelenkov@nginx.com        self.close_connection(sock)
460*1130Szelenkov@nginx.com
461*1130Szelenkov@nginx.com    def test_node_websockets_1_2_1__1_2_8(self):
462*1130Szelenkov@nginx.com        self.load('websockets/mirror')
463*1130Szelenkov@nginx.com
464*1130Szelenkov@nginx.com        opcode = self.ws.OP_BINARY
465*1130Szelenkov@nginx.com
466*1130Szelenkov@nginx.com        _, sock, _ = self.ws.upgrade()
467*1130Szelenkov@nginx.com
468*1130Szelenkov@nginx.com        def check_length(length, chopsize=None):
469*1130Szelenkov@nginx.com            payload = b'\xfe' * length
470*1130Szelenkov@nginx.com
471*1130Szelenkov@nginx.com            self.ws.frame_write(sock, opcode, payload, chopsize=chopsize)
472*1130Szelenkov@nginx.com            frame = self.ws.frame_read(sock)
473*1130Szelenkov@nginx.com
474*1130Szelenkov@nginx.com            self.check_frame(frame, True, opcode, payload)
475*1130Szelenkov@nginx.com
476*1130Szelenkov@nginx.com        check_length(0)                      # 1_2_1
477*1130Szelenkov@nginx.com        check_length(125)                    # 1_2_2
478*1130Szelenkov@nginx.com        check_length(126)                    # 1_2_3
479*1130Szelenkov@nginx.com        check_length(127)                    # 1_2_4
480*1130Szelenkov@nginx.com        check_length(128)                    # 1_2_5
481*1130Szelenkov@nginx.com        check_length(65535)                  # 1_2_6
482*1130Szelenkov@nginx.com        check_length(65536)                  # 1_2_7
483*1130Szelenkov@nginx.com        check_length(65536, chopsize = 997)  # 1_2_8
484*1130Szelenkov@nginx.com
485*1130Szelenkov@nginx.com        self.close_connection(sock)
486*1130Szelenkov@nginx.com
487*1130Szelenkov@nginx.com    def test_node_websockets_2_1__2_6(self):
488*1130Szelenkov@nginx.com        self.load('websockets/mirror')
489*1130Szelenkov@nginx.com
490*1130Szelenkov@nginx.com        op_ping = self.ws.OP_PING
491*1130Szelenkov@nginx.com        op_pong = self.ws.OP_PONG
492*1130Szelenkov@nginx.com
493*1130Szelenkov@nginx.com        _, sock, _ = self.ws.upgrade()
494*1130Szelenkov@nginx.com
495*1130Szelenkov@nginx.com        def check_ping(payload, chopsize=None, decode=True):
496*1130Szelenkov@nginx.com            self.ws.frame_write(sock, op_ping, payload, chopsize=chopsize)
497*1130Szelenkov@nginx.com            frame = self.ws.frame_read(sock)
498*1130Szelenkov@nginx.com
499*1130Szelenkov@nginx.com            self.check_frame(frame, True, op_pong, payload, decode=decode)
500*1130Szelenkov@nginx.com
501*1130Szelenkov@nginx.com        check_ping('')                                                 # 2_1
502*1130Szelenkov@nginx.com        check_ping('Hello, world!')                                    # 2_2
503*1130Szelenkov@nginx.com        check_ping(b'\x00\xff\xfe\xfd\xfc\xfb\x00\xff', decode=False)  # 2_3
504*1130Szelenkov@nginx.com        check_ping(b'\xfe' * 125, decode=False)                        # 2_4
505*1130Szelenkov@nginx.com        check_ping(b'\xfe' * 125, chopsize=1, decode=False)            # 2_6
506*1130Szelenkov@nginx.com
507*1130Szelenkov@nginx.com        self.close_connection(sock)
508*1130Szelenkov@nginx.com
509*1130Szelenkov@nginx.com        # 2_5
510*1130Szelenkov@nginx.com
511*1130Szelenkov@nginx.com        _, sock, _ = self.ws.upgrade()
512*1130Szelenkov@nginx.com
513*1130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_PING, b'\xfe' * 126)
514*1130Szelenkov@nginx.com        self.check_close(sock, 1002)
515*1130Szelenkov@nginx.com
516*1130Szelenkov@nginx.com    def test_node_websockets_2_7__2_9(self):
517*1130Szelenkov@nginx.com        self.load('websockets/mirror')
518*1130Szelenkov@nginx.com
519*1130Szelenkov@nginx.com        # 2_7
520*1130Szelenkov@nginx.com
521*1130Szelenkov@nginx.com        _, sock, _ = self.ws.upgrade()
522*1130Szelenkov@nginx.com
523*1130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_PONG, '')
524*1130Szelenkov@nginx.com        self.assertEqual(self.recvall(sock, read_timeout=1), b'', '2_7')
525*1130Szelenkov@nginx.com
526*1130Szelenkov@nginx.com        # 2_8
527*1130Szelenkov@nginx.com
528*1130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_PONG, 'unsolicited pong payload')
529*1130Szelenkov@nginx.com        self.assertEqual(self.recvall(sock, read_timeout=1), b'', '2_8')
530*1130Szelenkov@nginx.com
531*1130Szelenkov@nginx.com        # 2_9
532*1130Szelenkov@nginx.com
533*1130Szelenkov@nginx.com        payload = 'ping payload'
534*1130Szelenkov@nginx.com
535*1130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_PONG, 'unsolicited pong payload')
536*1130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_PING, payload)
537*1130Szelenkov@nginx.com
538*1130Szelenkov@nginx.com        frame = self.ws.frame_read(sock)
539*1130Szelenkov@nginx.com        self.check_frame(frame, True, self.ws.OP_PONG, payload)
540*1130Szelenkov@nginx.com
541*1130Szelenkov@nginx.com        self.close_connection(sock)
542*1130Szelenkov@nginx.com
543*1130Szelenkov@nginx.com    def test_node_websockets_2_10__2_11(self):
544*1130Szelenkov@nginx.com        self.load('websockets/mirror')
545*1130Szelenkov@nginx.com
546*1130Szelenkov@nginx.com        # 2_10
547*1130Szelenkov@nginx.com
548*1130Szelenkov@nginx.com        _, sock, _ = self.ws.upgrade()
549*1130Szelenkov@nginx.com
550*1130Szelenkov@nginx.com        for i in range(0, 10):
551*1130Szelenkov@nginx.com            self.ws.frame_write(sock, self.ws.OP_PING, 'payload-%d' % i)
552*1130Szelenkov@nginx.com
553*1130Szelenkov@nginx.com        for i in range(0, 10):
554*1130Szelenkov@nginx.com            frame = self.ws.frame_read(sock)
555*1130Szelenkov@nginx.com            self.check_frame(frame, True, self.ws.OP_PONG, 'payload-%d' % i)
556*1130Szelenkov@nginx.com
557*1130Szelenkov@nginx.com        # 2_11
558*1130Szelenkov@nginx.com
559*1130Szelenkov@nginx.com        for i in range(0, 10):
560*1130Szelenkov@nginx.com            opcode = self.ws.OP_PING
561*1130Szelenkov@nginx.com            self.ws.frame_write(sock, opcode, 'payload-%d' % i, chopsize=1)
562*1130Szelenkov@nginx.com
563*1130Szelenkov@nginx.com        for i in range(0, 10):
564*1130Szelenkov@nginx.com            frame = self.ws.frame_read(sock)
565*1130Szelenkov@nginx.com            self.check_frame(frame, True, self.ws.OP_PONG, 'payload-%d' % i)
566*1130Szelenkov@nginx.com
567*1130Szelenkov@nginx.com        self.close_connection(sock)
568*1130Szelenkov@nginx.com
569*1130Szelenkov@nginx.com    @unittest.skip('not yet')
570*1130Szelenkov@nginx.com    def test_node_websockets_3_1__3_7(self):
571*1130Szelenkov@nginx.com        self.load('websockets/mirror')
572*1130Szelenkov@nginx.com
573*1130Szelenkov@nginx.com        payload = 'Hello, world!'
574*1130Szelenkov@nginx.com
575*1130Szelenkov@nginx.com        # 3_1
576*1130Szelenkov@nginx.com
577*1130Szelenkov@nginx.com        _, sock, _ = self.ws.upgrade()
578*1130Szelenkov@nginx.com
579*1130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_TEXT, payload, rsv1=True)
580*1130Szelenkov@nginx.com        self.check_close(sock, 1002)
581*1130Szelenkov@nginx.com
582*1130Szelenkov@nginx.com        # 3_2
583*1130Szelenkov@nginx.com
584*1130Szelenkov@nginx.com        _, sock, _ = self.ws.upgrade()
585*1130Szelenkov@nginx.com
586*1130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_TEXT, payload)
587*1130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_TEXT, payload, rsv2=True)
588*1130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_PING, '')
589*1130Szelenkov@nginx.com
590*1130Szelenkov@nginx.com        frame = self.ws.frame_read(sock)
591*1130Szelenkov@nginx.com        self.check_frame(frame, True, self.ws.OP_TEXT, payload)
592*1130Szelenkov@nginx.com
593*1130Szelenkov@nginx.com        self.check_close(sock, 1002, no_close = True)
594*1130Szelenkov@nginx.com
595*1130Szelenkov@nginx.com        self.assertEqual(self.recvall(sock, read_timeout=1), b'', 'empty 3_2')
596*1130Szelenkov@nginx.com        sock.close()
597*1130Szelenkov@nginx.com
598*1130Szelenkov@nginx.com        # 3_3
599*1130Szelenkov@nginx.com
600*1130Szelenkov@nginx.com        _, sock, _ = self.ws.upgrade()
601*1130Szelenkov@nginx.com
602*1130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_TEXT, payload)
603*1130Szelenkov@nginx.com
604*1130Szelenkov@nginx.com        frame = self.ws.frame_read(sock)
605*1130Szelenkov@nginx.com        self.check_frame(frame, True, self.ws.OP_TEXT, payload)
606*1130Szelenkov@nginx.com
607*1130Szelenkov@nginx.com        self.ws.frame_write(
608*1130Szelenkov@nginx.com            sock,
609*1130Szelenkov@nginx.com            self.ws.OP_TEXT,
610*1130Szelenkov@nginx.com            payload,
611*1130Szelenkov@nginx.com            rsv1=True,
612*1130Szelenkov@nginx.com            rsv2=True,
613*1130Szelenkov@nginx.com        )
614*1130Szelenkov@nginx.com
615*1130Szelenkov@nginx.com        self.check_close(sock, 1002, no_close = True)
616*1130Szelenkov@nginx.com
617*1130Szelenkov@nginx.com        self.assertEqual(self.recvall(sock, read_timeout=1), b'', 'empty 3_3')
618*1130Szelenkov@nginx.com        sock.close()
619*1130Szelenkov@nginx.com
620*1130Szelenkov@nginx.com        # 3_4
621*1130Szelenkov@nginx.com
622*1130Szelenkov@nginx.com        _, sock, _ = self.ws.upgrade()
623*1130Szelenkov@nginx.com
624*1130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_TEXT, payload, chopsize=1)
625*1130Szelenkov@nginx.com        self.ws.frame_write(
626*1130Szelenkov@nginx.com            sock,
627*1130Szelenkov@nginx.com            self.ws.OP_TEXT,
628*1130Szelenkov@nginx.com            payload,
629*1130Szelenkov@nginx.com            rsv3=True,
630*1130Szelenkov@nginx.com            chopsize=1
631*1130Szelenkov@nginx.com        )
632*1130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_PING, '')
633*1130Szelenkov@nginx.com
634*1130Szelenkov@nginx.com        frame = self.ws.frame_read(sock)
635*1130Szelenkov@nginx.com        self.check_frame(frame, True, self.ws.OP_TEXT, payload)
636*1130Szelenkov@nginx.com
637*1130Szelenkov@nginx.com        self.check_close(sock, 1002, no_close = True)
638*1130Szelenkov@nginx.com
639*1130Szelenkov@nginx.com        self.assertEqual(self.recvall(sock, read_timeout=1), b'', 'empty 3_4')
640*1130Szelenkov@nginx.com        sock.close()
641*1130Szelenkov@nginx.com
642*1130Szelenkov@nginx.com        # 3_5
643*1130Szelenkov@nginx.com
644*1130Szelenkov@nginx.com        _, sock, _ = self.ws.upgrade()
645*1130Szelenkov@nginx.com
646*1130Szelenkov@nginx.com        self.ws.frame_write(
647*1130Szelenkov@nginx.com            sock,
648*1130Szelenkov@nginx.com            self.ws.OP_BINARY,
649*1130Szelenkov@nginx.com            b'\x00\xff\xfe\xfd\xfc\xfb\x00\xff',
650*1130Szelenkov@nginx.com            rsv1=True,
651*1130Szelenkov@nginx.com            rsv3=True,
652*1130Szelenkov@nginx.com        )
653*1130Szelenkov@nginx.com
654*1130Szelenkov@nginx.com        self.check_close(sock, 1002)
655*1130Szelenkov@nginx.com
656*1130Szelenkov@nginx.com        # 3_6
657*1130Szelenkov@nginx.com
658*1130Szelenkov@nginx.com        _, sock, _ = self.ws.upgrade()
659*1130Szelenkov@nginx.com
660*1130Szelenkov@nginx.com        self.ws.frame_write(
661*1130Szelenkov@nginx.com            sock,
662*1130Szelenkov@nginx.com            self.ws.OP_PING,
663*1130Szelenkov@nginx.com            payload,
664*1130Szelenkov@nginx.com            rsv2=True,
665*1130Szelenkov@nginx.com            rsv3=True,
666*1130Szelenkov@nginx.com        )
667*1130Szelenkov@nginx.com
668*1130Szelenkov@nginx.com        self.check_close(sock, 1002)
669*1130Szelenkov@nginx.com
670*1130Szelenkov@nginx.com        # 3_7
671*1130Szelenkov@nginx.com
672*1130Szelenkov@nginx.com        _, sock, _ = self.ws.upgrade()
673*1130Szelenkov@nginx.com
674*1130Szelenkov@nginx.com        self.ws.frame_write(
675*1130Szelenkov@nginx.com            sock,
676*1130Szelenkov@nginx.com            self.ws.OP_CLOSE,
677*1130Szelenkov@nginx.com            payload,
678*1130Szelenkov@nginx.com            rsv1=True,
679*1130Szelenkov@nginx.com            rsv2=True,
680*1130Szelenkov@nginx.com            rsv3=True,
681*1130Szelenkov@nginx.com        )
682*1130Szelenkov@nginx.com
683*1130Szelenkov@nginx.com        self.check_close(sock, 1002)
684*1130Szelenkov@nginx.com
685*1130Szelenkov@nginx.com    def test_node_websockets_4_1_1__4_2_5(self):
686*1130Szelenkov@nginx.com        self.load('websockets/mirror')
687*1130Szelenkov@nginx.com
688*1130Szelenkov@nginx.com        payload = 'Hello, world!'
689*1130Szelenkov@nginx.com
690*1130Szelenkov@nginx.com        # 4_1_1
691*1130Szelenkov@nginx.com
692*1130Szelenkov@nginx.com        _, sock, _ = self.ws.upgrade()
693*1130Szelenkov@nginx.com
694*1130Szelenkov@nginx.com        self.ws.frame_write(sock, 0x03, '')
695*1130Szelenkov@nginx.com        self.check_close(sock, 1002)
696*1130Szelenkov@nginx.com
697*1130Szelenkov@nginx.com        # 4_1_2
698*1130Szelenkov@nginx.com
699*1130Szelenkov@nginx.com        _, sock, _ = self.ws.upgrade()
700*1130Szelenkov@nginx.com
701*1130Szelenkov@nginx.com        self.ws.frame_write(sock, 0x04, 'reserved opcode payload')
702*1130Szelenkov@nginx.com        self.check_close(sock, 1002)
703*1130Szelenkov@nginx.com
704*1130Szelenkov@nginx.com        # 4_1_3
705*1130Szelenkov@nginx.com
706*1130Szelenkov@nginx.com        _, sock, _ = self.ws.upgrade()
707*1130Szelenkov@nginx.com
708*1130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_TEXT, payload)
709*1130Szelenkov@nginx.com
710*1130Szelenkov@nginx.com        frame = self.ws.frame_read(sock)
711*1130Szelenkov@nginx.com        self.check_frame(frame, True, self.ws.OP_TEXT, payload)
712*1130Szelenkov@nginx.com
713*1130Szelenkov@nginx.com        self.ws.frame_write(sock, 0x05, '')
714*1130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_PING, '')
715*1130Szelenkov@nginx.com
716*1130Szelenkov@nginx.com        self.check_close(sock, 1002)
717*1130Szelenkov@nginx.com
718*1130Szelenkov@nginx.com        # 4_1_4
719*1130Szelenkov@nginx.com
720*1130Szelenkov@nginx.com        _, sock, _ = self.ws.upgrade()
721*1130Szelenkov@nginx.com
722*1130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_TEXT, payload)
723*1130Szelenkov@nginx.com
724*1130Szelenkov@nginx.com        frame = self.ws.frame_read(sock)
725*1130Szelenkov@nginx.com        self.check_frame(frame, True, self.ws.OP_TEXT, payload)
726*1130Szelenkov@nginx.com
727*1130Szelenkov@nginx.com        self.ws.frame_write(sock, 0x06, payload)
728*1130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_PING, '')
729*1130Szelenkov@nginx.com
730*1130Szelenkov@nginx.com        self.check_close(sock, 1002)
731*1130Szelenkov@nginx.com
732*1130Szelenkov@nginx.com        # 4_1_5
733*1130Szelenkov@nginx.com
734*1130Szelenkov@nginx.com        _, sock, _ = self.ws.upgrade()
735*1130Szelenkov@nginx.com
736*1130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_TEXT, payload, chopsize=1)
737*1130Szelenkov@nginx.com
738*1130Szelenkov@nginx.com        frame = self.ws.frame_read(sock)
739*1130Szelenkov@nginx.com        self.check_frame(frame, True, self.ws.OP_TEXT, payload)
740*1130Szelenkov@nginx.com
741*1130Szelenkov@nginx.com        self.ws.frame_write(sock, 0x07, payload, chopsize=1)
742*1130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_PING, '')
743*1130Szelenkov@nginx.com
744*1130Szelenkov@nginx.com        self.check_close(sock, 1002)
745*1130Szelenkov@nginx.com
746*1130Szelenkov@nginx.com        # 4_2_1
747*1130Szelenkov@nginx.com
748*1130Szelenkov@nginx.com        _, sock, _ = self.ws.upgrade()
749*1130Szelenkov@nginx.com
750*1130Szelenkov@nginx.com        self.ws.frame_write(sock, 0x0B, '')
751*1130Szelenkov@nginx.com        self.check_close(sock, 1002)
752*1130Szelenkov@nginx.com
753*1130Szelenkov@nginx.com        # 4_2_2
754*1130Szelenkov@nginx.com
755*1130Szelenkov@nginx.com        _, sock, _ = self.ws.upgrade()
756*1130Szelenkov@nginx.com
757*1130Szelenkov@nginx.com        self.ws.frame_write(sock, 0x0C, 'reserved opcode payload')
758*1130Szelenkov@nginx.com        self.check_close(sock, 1002)
759*1130Szelenkov@nginx.com
760*1130Szelenkov@nginx.com        # 4_2_3
761*1130Szelenkov@nginx.com
762*1130Szelenkov@nginx.com        _, sock, _ = self.ws.upgrade()
763*1130Szelenkov@nginx.com
764*1130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_TEXT, payload)
765*1130Szelenkov@nginx.com
766*1130Szelenkov@nginx.com        frame = self.ws.frame_read(sock)
767*1130Szelenkov@nginx.com        self.check_frame(frame, True, self.ws.OP_TEXT, payload)
768*1130Szelenkov@nginx.com
769*1130Szelenkov@nginx.com        self.ws.frame_write(sock, 0x0D, '')
770*1130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_PING, '')
771*1130Szelenkov@nginx.com
772*1130Szelenkov@nginx.com        self.check_close(sock, 1002)
773*1130Szelenkov@nginx.com
774*1130Szelenkov@nginx.com        # 4_2_4
775*1130Szelenkov@nginx.com
776*1130Szelenkov@nginx.com        _, sock, _ = self.ws.upgrade()
777*1130Szelenkov@nginx.com
778*1130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_TEXT, payload)
779*1130Szelenkov@nginx.com
780*1130Szelenkov@nginx.com        frame = self.ws.frame_read(sock)
781*1130Szelenkov@nginx.com        self.check_frame(frame, True, self.ws.OP_TEXT, payload)
782*1130Szelenkov@nginx.com
783*1130Szelenkov@nginx.com        self.ws.frame_write(sock, 0x0E, payload)
784*1130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_PING, '')
785*1130Szelenkov@nginx.com
786*1130Szelenkov@nginx.com        self.check_close(sock, 1002)
787*1130Szelenkov@nginx.com
788*1130Szelenkov@nginx.com        # 4_2_5
789*1130Szelenkov@nginx.com
790*1130Szelenkov@nginx.com        _, sock, _ = self.ws.upgrade()
791*1130Szelenkov@nginx.com
792*1130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_TEXT, payload, chopsize=1)
793*1130Szelenkov@nginx.com
794*1130Szelenkov@nginx.com        frame = self.ws.frame_read(sock)
795*1130Szelenkov@nginx.com        self.check_frame(frame, True, self.ws.OP_TEXT, payload)
796*1130Szelenkov@nginx.com
797*1130Szelenkov@nginx.com        self.ws.frame_write(sock, 0x0F, payload, chopsize=1)
798*1130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_PING, '')
799*1130Szelenkov@nginx.com
800*1130Szelenkov@nginx.com        self.check_close(sock, 1002)
801*1130Szelenkov@nginx.com
802*1130Szelenkov@nginx.com    def test_node_websockets_5_1__5_20(self):
803*1130Szelenkov@nginx.com        self.load('websockets/mirror')
804*1130Szelenkov@nginx.com
805*1130Szelenkov@nginx.com        # 5_1
806*1130Szelenkov@nginx.com
807*1130Szelenkov@nginx.com        _, sock, _ = self.ws.upgrade()
808*1130Szelenkov@nginx.com
809*1130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_PING, 'fragment1', fin=False)
810*1130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment2', fin=True)
811*1130Szelenkov@nginx.com        self.check_close(sock, 1002)
812*1130Szelenkov@nginx.com
813*1130Szelenkov@nginx.com        # 5_2
814*1130Szelenkov@nginx.com
815*1130Szelenkov@nginx.com        _, sock, _ = self.ws.upgrade()
816*1130Szelenkov@nginx.com
817*1130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_PONG, 'fragment1', fin=False)
818*1130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment2', fin=True)
819*1130Szelenkov@nginx.com        self.check_close(sock, 1002)
820*1130Szelenkov@nginx.com
821*1130Szelenkov@nginx.com        # 5_3
822*1130Szelenkov@nginx.com
823*1130Szelenkov@nginx.com        _, sock, _ = self.ws.upgrade()
824*1130Szelenkov@nginx.com
825*1130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_TEXT, 'fragment1', fin=False)
826*1130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment2', fin=True)
827*1130Szelenkov@nginx.com
828*1130Szelenkov@nginx.com        frame = self.ws.frame_read(sock)
829*1130Szelenkov@nginx.com        self.check_frame(frame, True, self.ws.OP_TEXT, 'fragment1fragment2')
830*1130Szelenkov@nginx.com
831*1130Szelenkov@nginx.com        # 5_4
832*1130Szelenkov@nginx.com
833*1130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_TEXT, 'fragment1', fin=False)
834*1130Szelenkov@nginx.com        self.assertEqual(self.recvall(sock, read_timeout=1), b'', '5_4')
835*1130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment2', fin=True)
836*1130Szelenkov@nginx.com
837*1130Szelenkov@nginx.com        frame = self.ws.frame_read(sock)
838*1130Szelenkov@nginx.com        self.check_frame(frame, True, self.ws.OP_TEXT, 'fragment1fragment2')
839*1130Szelenkov@nginx.com
840*1130Szelenkov@nginx.com        # 5_5
841*1130Szelenkov@nginx.com
842*1130Szelenkov@nginx.com        self.ws.frame_write(
843*1130Szelenkov@nginx.com            sock,
844*1130Szelenkov@nginx.com            self.ws.OP_TEXT,
845*1130Szelenkov@nginx.com            'fragment1',
846*1130Szelenkov@nginx.com            fin=False,
847*1130Szelenkov@nginx.com            chopsize=1,
848*1130Szelenkov@nginx.com        )
849*1130Szelenkov@nginx.com        self.ws.frame_write(
850*1130Szelenkov@nginx.com            sock,
851*1130Szelenkov@nginx.com            self.ws.OP_CONT,
852*1130Szelenkov@nginx.com            'fragment2',
853*1130Szelenkov@nginx.com            fin=True,
854*1130Szelenkov@nginx.com            chopsize=1,
855*1130Szelenkov@nginx.com        )
856*1130Szelenkov@nginx.com
857*1130Szelenkov@nginx.com        frame = self.ws.frame_read(sock)
858*1130Szelenkov@nginx.com        self.check_frame(frame, True, self.ws.OP_TEXT, 'fragment1fragment2')
859*1130Szelenkov@nginx.com
860*1130Szelenkov@nginx.com        # 5_6
861*1130Szelenkov@nginx.com
862*1130Szelenkov@nginx.com        ping_payload = 'ping payload'
863*1130Szelenkov@nginx.com
864*1130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_TEXT, 'fragment1', fin=False)
865*1130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_PING, ping_payload)
866*1130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment2', fin=True)
867*1130Szelenkov@nginx.com
868*1130Szelenkov@nginx.com        frame = self.ws.frame_read(sock)
869*1130Szelenkov@nginx.com        self.check_frame(frame, True, self.ws.OP_PONG, ping_payload)
870*1130Szelenkov@nginx.com
871*1130Szelenkov@nginx.com        frame = self.ws.frame_read(sock)
872*1130Szelenkov@nginx.com        self.check_frame(frame, True, self.ws.OP_TEXT, 'fragment1fragment2')
873*1130Szelenkov@nginx.com
874*1130Szelenkov@nginx.com        # 5_7
875*1130Szelenkov@nginx.com
876*1130Szelenkov@nginx.com        ping_payload = 'ping payload'
877*1130Szelenkov@nginx.com
878*1130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_TEXT, 'fragment1', fin=False)
879*1130Szelenkov@nginx.com        self.assertEqual(self.recvall(sock, read_timeout=1), b'', '5_7')
880*1130Szelenkov@nginx.com
881*1130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_PING, ping_payload)
882*1130Szelenkov@nginx.com
883*1130Szelenkov@nginx.com        frame = self.ws.frame_read(sock)
884*1130Szelenkov@nginx.com        self.check_frame(frame, True, self.ws.OP_PONG, ping_payload)
885*1130Szelenkov@nginx.com
886*1130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment2', fin=True)
887*1130Szelenkov@nginx.com
888*1130Szelenkov@nginx.com        frame = self.ws.frame_read(sock)
889*1130Szelenkov@nginx.com        self.check_frame(frame, True, self.ws.OP_TEXT, 'fragment1fragment2')
890*1130Szelenkov@nginx.com
891*1130Szelenkov@nginx.com        # 5_8
892*1130Szelenkov@nginx.com
893*1130Szelenkov@nginx.com        ping_payload = 'ping payload'
894*1130Szelenkov@nginx.com
895*1130Szelenkov@nginx.com        self.ws.frame_write(
896*1130Szelenkov@nginx.com            sock,
897*1130Szelenkov@nginx.com            self.ws.OP_TEXT,
898*1130Szelenkov@nginx.com            'fragment1',
899*1130Szelenkov@nginx.com            fin=False,
900*1130Szelenkov@nginx.com            chopsize=1,
901*1130Szelenkov@nginx.com        )
902*1130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_PING, ping_payload, chopsize=1)
903*1130Szelenkov@nginx.com        self.ws.frame_write(
904*1130Szelenkov@nginx.com            sock,
905*1130Szelenkov@nginx.com            self.ws.OP_CONT,
906*1130Szelenkov@nginx.com            'fragment2',
907*1130Szelenkov@nginx.com            fin=True,
908*1130Szelenkov@nginx.com            chopsize=1,
909*1130Szelenkov@nginx.com        )
910*1130Szelenkov@nginx.com
911*1130Szelenkov@nginx.com        frame = self.ws.frame_read(sock)
912*1130Szelenkov@nginx.com        self.check_frame(frame, True, self.ws.OP_PONG, ping_payload)
913*1130Szelenkov@nginx.com
914*1130Szelenkov@nginx.com        frame = self.ws.frame_read(sock)
915*1130Szelenkov@nginx.com        self.check_frame(frame, True, self.ws.OP_TEXT, 'fragment1fragment2')
916*1130Szelenkov@nginx.com
917*1130Szelenkov@nginx.com        # 5_9
918*1130Szelenkov@nginx.com
919*1130Szelenkov@nginx.com        self.ws.frame_write(
920*1130Szelenkov@nginx.com            sock,
921*1130Szelenkov@nginx.com            self.ws.OP_CONT,
922*1130Szelenkov@nginx.com            'non-continuation payload',
923*1130Szelenkov@nginx.com            fin=True,
924*1130Szelenkov@nginx.com        )
925*1130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_TEXT, 'Hello, world!', fin=True)
926*1130Szelenkov@nginx.com        self.check_close(sock, 1002)
927*1130Szelenkov@nginx.com
928*1130Szelenkov@nginx.com        # 5_10
929*1130Szelenkov@nginx.com
930*1130Szelenkov@nginx.com        _, sock, _ = self.ws.upgrade()
931*1130Szelenkov@nginx.com
932*1130Szelenkov@nginx.com        self.ws.frame_write(
933*1130Szelenkov@nginx.com            sock,
934*1130Szelenkov@nginx.com            self.ws.OP_CONT,
935*1130Szelenkov@nginx.com            'non-continuation payload',
936*1130Szelenkov@nginx.com            fin=True,
937*1130Szelenkov@nginx.com        )
938*1130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_TEXT, 'Hello, world!', fin=True)
939*1130Szelenkov@nginx.com        self.check_close(sock, 1002)
940*1130Szelenkov@nginx.com
941*1130Szelenkov@nginx.com        # 5_11
942*1130Szelenkov@nginx.com
943*1130Szelenkov@nginx.com        _, sock, _ = self.ws.upgrade()
944*1130Szelenkov@nginx.com
945*1130Szelenkov@nginx.com        self.ws.frame_write(
946*1130Szelenkov@nginx.com            sock,
947*1130Szelenkov@nginx.com            self.ws.OP_CONT,
948*1130Szelenkov@nginx.com            'non-continuation payload',
949*1130Szelenkov@nginx.com            fin=True,
950*1130Szelenkov@nginx.com            chopsize=1,
951*1130Szelenkov@nginx.com        )
952*1130Szelenkov@nginx.com        self.ws.frame_write(
953*1130Szelenkov@nginx.com            sock,
954*1130Szelenkov@nginx.com            self.ws.OP_TEXT,
955*1130Szelenkov@nginx.com            'Hello, world!',
956*1130Szelenkov@nginx.com            fin=True,
957*1130Szelenkov@nginx.com            chopsize=1,
958*1130Szelenkov@nginx.com        )
959*1130Szelenkov@nginx.com        self.check_close(sock, 1002)
960*1130Szelenkov@nginx.com
961*1130Szelenkov@nginx.com        # 5_12
962*1130Szelenkov@nginx.com
963*1130Szelenkov@nginx.com        _, sock, _ = self.ws.upgrade()
964*1130Szelenkov@nginx.com
965*1130Szelenkov@nginx.com        self.ws.frame_write(
966*1130Szelenkov@nginx.com            sock,
967*1130Szelenkov@nginx.com            self.ws.OP_CONT,
968*1130Szelenkov@nginx.com            'non-continuation payload',
969*1130Szelenkov@nginx.com            fin=False,
970*1130Szelenkov@nginx.com        )
971*1130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_TEXT, 'Hello, world!', fin=True)
972*1130Szelenkov@nginx.com        self.check_close(sock, 1002)
973*1130Szelenkov@nginx.com
974*1130Szelenkov@nginx.com        # 5_13
975*1130Szelenkov@nginx.com
976*1130Szelenkov@nginx.com        _, sock, _ = self.ws.upgrade()
977*1130Szelenkov@nginx.com
978*1130Szelenkov@nginx.com        self.ws.frame_write(
979*1130Szelenkov@nginx.com            sock,
980*1130Szelenkov@nginx.com            self.ws.OP_CONT,
981*1130Szelenkov@nginx.com            'non-continuation payload',
982*1130Szelenkov@nginx.com            fin=False,
983*1130Szelenkov@nginx.com        )
984*1130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_TEXT, 'Hello, world!', fin=True)
985*1130Szelenkov@nginx.com        self.check_close(sock, 1002)
986*1130Szelenkov@nginx.com
987*1130Szelenkov@nginx.com        # 5_14
988*1130Szelenkov@nginx.com
989*1130Szelenkov@nginx.com        _, sock, _ = self.ws.upgrade()
990*1130Szelenkov@nginx.com
991*1130Szelenkov@nginx.com        self.ws.frame_write(
992*1130Szelenkov@nginx.com            sock,
993*1130Szelenkov@nginx.com            self.ws.OP_CONT,
994*1130Szelenkov@nginx.com            'non-continuation payload',
995*1130Szelenkov@nginx.com            fin=False,
996*1130Szelenkov@nginx.com            chopsize=1,
997*1130Szelenkov@nginx.com        )
998*1130Szelenkov@nginx.com        self.ws.frame_write(
999*1130Szelenkov@nginx.com            sock,
1000*1130Szelenkov@nginx.com            self.ws.OP_TEXT,
1001*1130Szelenkov@nginx.com            'Hello, world!',
1002*1130Szelenkov@nginx.com            fin=True,
1003*1130Szelenkov@nginx.com            chopsize=1,
1004*1130Szelenkov@nginx.com        )
1005*1130Szelenkov@nginx.com        self.check_close(sock, 1002)
1006*1130Szelenkov@nginx.com
1007*1130Szelenkov@nginx.com        # 5_15
1008*1130Szelenkov@nginx.com
1009*1130Szelenkov@nginx.com        _, sock, _ = self.ws.upgrade()
1010*1130Szelenkov@nginx.com
1011*1130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_TEXT, 'fragment1', fin=False)
1012*1130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment2', fin=True)
1013*1130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment3', fin=False)
1014*1130Szelenkov@nginx.com        self.ws.frame_write(sock, self.ws.OP_TEXT, 'fragment4', fin=True)
1015*1130Szelenkov@nginx.com        self.check_close(sock, 1002)
1016*1130Szelenkov@nginx.com
1017*1130Szelenkov@nginx.com        # 5_16
1018*1130Szelenkov@nginx.com
1019*1130Szelenkov@nginx.com        _, sock, _ = self.ws.upgrade()
1020*1130Szelenkov@nginx.com
1021*1130Szelenkov@nginx.com        for i in range(0, 2):
1022*1130Szelenkov@nginx.com            self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment1', fin=False)
1023*1130Szelenkov@nginx.com            self.ws.frame_write(sock, self.ws.OP_TEXT, 'fragment2', fin=False)
1024*1130Szelenkov@nginx.com            self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment3', fin=True)
1025*1130Szelenkov@nginx.com        self.check_close(sock, 1002)
1026*1130Szelenkov@nginx.com
1027*1130Szelenkov@nginx.com        # 5_17
1028