@@ -47,6 +47,44 @@ const getPort = (io: Server): number => {
47
47
return io . httpServer . address ( ) . port ;
48
48
} ;
49
49
50
+ // TODO: update superagent as latest release now supports promises
51
+ const eioHandshake = ( httpServer ) : Promise < string > => {
52
+ return new Promise ( ( resolve ) => {
53
+ request ( httpServer )
54
+ . get ( "/socket.io/" )
55
+ . query ( { transport : "polling" , EIO : 4 } )
56
+ . end ( ( err , res ) => {
57
+ const sid = JSON . parse ( res . text . substring ( 1 ) ) . sid ;
58
+ resolve ( sid ) ;
59
+ } ) ;
60
+ } ) ;
61
+ } ;
62
+
63
+ const eioPush = ( httpServer , sid : string , body : string ) : Promise < void > => {
64
+ return new Promise ( ( resolve ) => {
65
+ request ( httpServer )
66
+ . post ( "/socket.io/" )
67
+ . send ( body )
68
+ . query ( { transport : "polling" , EIO : 4 , sid } )
69
+ . expect ( 200 )
70
+ . end ( ( ) => {
71
+ resolve ( ) ;
72
+ } ) ;
73
+ } ) ;
74
+ } ;
75
+
76
+ const eioPoll = ( httpServer , sid ) : Promise < string > => {
77
+ return new Promise ( ( resolve ) => {
78
+ request ( httpServer )
79
+ . get ( "/socket.io/" )
80
+ . query ( { transport : "polling" , EIO : 4 , sid } )
81
+ . expect ( 200 )
82
+ . end ( ( err , res ) => {
83
+ resolve ( res . text ) ;
84
+ } ) ;
85
+ } ) ;
86
+ } ;
87
+
50
88
describe ( "socket.io" , ( ) => {
51
89
it ( "should be the same version as client" , ( ) => {
52
90
const version = require ( "../package" ) . version ;
@@ -378,6 +416,66 @@ describe("socket.io", () => {
378
416
exec ( fixture ( "server-close.ts" ) , done ) ;
379
417
} ) ;
380
418
} ) ;
419
+
420
+ describe ( "protocol violations" , ( ) => {
421
+ it ( "should close the connection when receiving several CONNECT packets" , async ( ) => {
422
+ const httpServer = createServer ( ) ;
423
+ const io = new Server ( httpServer ) ;
424
+
425
+ httpServer . listen ( 0 ) ;
426
+
427
+ const sid = await eioHandshake ( httpServer ) ;
428
+ // send a first CONNECT packet
429
+ await eioPush ( httpServer , sid , "40" ) ;
430
+ // send another CONNECT packet
431
+ await eioPush ( httpServer , sid , "40" ) ;
432
+ // session is cleanly closed (not discarded, see 'client.close()')
433
+ // first, we receive the Socket.IO handshake response
434
+ await eioPoll ( httpServer , sid ) ;
435
+ // then a close packet
436
+ const body = await eioPoll ( httpServer , sid ) ;
437
+ expect ( body ) . to . be ( "6\u001e1" ) ;
438
+
439
+ io . close ( ) ;
440
+ } ) ;
441
+
442
+ it ( "should close the connection when receiving an EVENT packet while not connected" , async ( ) => {
443
+ const httpServer = createServer ( ) ;
444
+ const io = new Server ( httpServer ) ;
445
+
446
+ httpServer . listen ( 0 ) ;
447
+
448
+ const sid = await eioHandshake ( httpServer ) ;
449
+ // send an EVENT packet
450
+ await eioPush ( httpServer , sid , '42["some event"]' ) ;
451
+ // session is cleanly closed, we receive a close packet
452
+ const body = await eioPoll ( httpServer , sid ) ;
453
+ expect ( body ) . to . be ( "6\u001e1" ) ;
454
+
455
+ io . close ( ) ;
456
+ } ) ;
457
+
458
+ it ( "should close the connection when receiving an invalid packet" , async ( ) => {
459
+ const httpServer = createServer ( ) ;
460
+ const io = new Server ( httpServer ) ;
461
+
462
+ httpServer . listen ( 0 ) ;
463
+
464
+ const sid = await eioHandshake ( httpServer ) ;
465
+ // send a CONNECT packet
466
+ await eioPush ( httpServer , sid , "40" ) ;
467
+ // send an invalid packet
468
+ await eioPush ( httpServer , sid , "4abc" ) ;
469
+ // session is cleanly closed (not discarded, see 'client.close()')
470
+ // first, we receive the Socket.IO handshake response
471
+ await eioPoll ( httpServer , sid ) ;
472
+ // then a close packet
473
+ const body = await eioPoll ( httpServer , sid ) ;
474
+ expect ( body ) . to . be ( "6\u001e1" ) ;
475
+
476
+ io . close ( ) ;
477
+ } ) ;
478
+ } ) ;
381
479
} ) ;
382
480
383
481
describe ( "namespaces" , ( ) => {
0 commit comments