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