arnaucube
arnaucube/raspberryGPIOhtmlserverPublic Self-hosted repository
raspberryGPIOhtmlserver/node_modules/ws/test/WebSocketServer.test.js
node_modules/ws/test/WebSocketServer.test.jsRaw
   1var http = require('http')
   2  , https = require('https')
   3  , WebSocket = require('../')
   4  , WebSocketServer = WebSocket.Server
   5  , fs = require('fs')
   6  , should = require('should');
   7
   8var port = 8000;
   9
  10function getArrayBuffer(buf) {
  11  var l = buf.length;
  12  var arrayBuf = new ArrayBuffer(l);
  13  for (var i = 0; i < l; ++i) {
  14    arrayBuf[i] = buf[i];
  15  }
  16  return arrayBuf;
  17}
  18
  19function areArraysEqual(x, y) {
  20  if (x.length != y.length) return false;
  21  for (var i = 0, l = x.length; i < l; ++i) {
  22    if (x[i] !== y[i]) return false;
  23  }
  24  return true;
  25}
  26
  27describe('WebSocketServer', function() {
  28  describe('#ctor', function() {
  29    it('throws an error if no option object is passed', function() {
  30      var gotException = false;
  31      try {
  32        var wss = new WebSocketServer();
  33      }
  34      catch (e) {
  35        gotException = true;
  36      }
  37      gotException.should.be.ok;
  38    });
  39
  40    it('throws an error if no port or server is specified', function() {
  41      var gotException = false;
  42      try {
  43        var wss = new WebSocketServer({});
  44      }
  45      catch (e) {
  46        gotException = true;
  47      }
  48      gotException.should.be.ok;
  49    });
  50
  51    it('does not throw an error if no port or server is specified, when the noServer option is true', function() {
  52      var gotException = false;
  53      try {
  54        var wss = new WebSocketServer({noServer: true});
  55      }
  56      catch (e) {
  57        gotException = true;
  58      }
  59      gotException.should.eql(false);
  60    });
  61
  62    it('emits an error if http server bind fails', function(done) {
  63      var wss = new WebSocketServer({port: 1});
  64      wss.on('error', function() { done(); });
  65    });
  66
  67    it('starts a server on a given port', function(done) {
  68      var wss = new WebSocketServer({port: ++port}, function() {
  69        var ws = new WebSocket('ws://localhost:' + port);
  70      });
  71      wss.on('connection', function(client) {
  72        wss.close();
  73        done();
  74      });
  75    });
  76
  77    it('uses a precreated http server', function (done) {
  78      var srv = http.createServer();
  79      srv.listen(++port, function () {
  80        var wss = new WebSocketServer({server: srv});
  81        var ws = new WebSocket('ws://localhost:' + port);
  82
  83        wss.on('connection', function(client) {
  84          wss.close();
  85          srv.close();
  86          done();
  87        });
  88      });
  89    });
  90
  91    it('uses a precreated http server listening on unix socket', function (done) {
  92      var srv = http.createServer();
  93      var sockPath = '/tmp/ws_socket_'+new Date().getTime()+'.'+Math.floor(Math.random() * 1000);
  94      srv.listen(sockPath, function () {
  95        var wss = new WebSocketServer({server: srv});
  96        var ws = new WebSocket('ws+unix://'+sockPath);
  97
  98        wss.on('connection', function(client) {
  99          wss.close();
 100          srv.close();
 101          done();
 102        });
 103      });
 104    });
 105
 106    it('emits path specific connection event', function (done) {
 107      var srv = http.createServer();
 108      srv.listen(++port, function () {
 109        var wss = new WebSocketServer({server: srv});
 110        var ws = new WebSocket('ws://localhost:' + port+'/endpointName');
 111
 112        wss.on('connection/endpointName', function(client) {
 113          wss.close();
 114          srv.close();
 115          done();
 116        });
 117      });
 118    });
 119
 120    it('can have two different instances listening on the same http server with two different paths', function(done) {
 121      var srv = http.createServer();
 122      srv.listen(++port, function () {
 123        var wss1 = new WebSocketServer({server: srv, path: '/wss1'})
 124          , wss2 = new WebSocketServer({server: srv, path: '/wss2'});
 125        var doneCount = 0;
 126        wss1.on('connection', function(client) {
 127          wss1.close();
 128          if (++doneCount == 2) {
 129            srv.close();
 130            done();
 131          }
 132        });
 133        wss2.on('connection', function(client) {
 134          wss2.close();
 135          if (++doneCount == 2) {
 136            srv.close();
 137            done();
 138          }
 139        });
 140        var ws1 = new WebSocket('ws://localhost:' + port + '/wss1');
 141        var ws2 = new WebSocket('ws://localhost:' + port + '/wss2?foo=1');
 142      });
 143    });
 144
 145    it('cannot have two different instances listening on the same http server with the same path', function(done) {
 146      var srv = http.createServer();
 147      srv.listen(++port, function () {
 148        var wss1 = new WebSocketServer({server: srv, path: '/wss1'});
 149        try {
 150          var wss2 = new WebSocketServer({server: srv, path: '/wss1'});
 151        }
 152        catch (e) {
 153          wss1.close();
 154          srv.close();
 155          done();
 156        }
 157      });
 158    });
 159  });
 160
 161  describe('#close', function() {
 162    it('will close all clients', function(done) {
 163      var wss = new WebSocketServer({port: ++port}, function() {
 164        var ws = new WebSocket('ws://localhost:' + port);
 165        ws.on('close', function() {
 166          if (++closes == 2) done();
 167        });
 168      });
 169      var closes = 0;
 170      wss.on('connection', function(client) {
 171        client.on('close', function() {
 172          if (++closes == 2) done();
 173        });
 174        wss.close();
 175      });
 176    });
 177
 178    it('does not close a precreated server', function(done) {
 179      var srv = http.createServer();
 180      var realClose = srv.close;
 181      srv.close = function() {
 182        should.fail('must not close pre-created server');
 183      }
 184      srv.listen(++port, function () {
 185        var wss = new WebSocketServer({server: srv});
 186        var ws = new WebSocket('ws://localhost:' + port);
 187        wss.on('connection', function(client) {
 188          wss.close();
 189          srv.close = realClose;
 190          srv.close();
 191          done();
 192        });
 193      });
 194    });
 195
 196    it('cleans up websocket data on a precreated server', function(done) {
 197      var srv = http.createServer();
 198      srv.listen(++port, function () {
 199        var wss1 = new WebSocketServer({server: srv, path: '/wss1'})
 200          , wss2 = new WebSocketServer({server: srv, path: '/wss2'});
 201        (typeof srv._webSocketPaths).should.eql('object');
 202        Object.keys(srv._webSocketPaths).length.should.eql(2);
 203        wss1.close();
 204        Object.keys(srv._webSocketPaths).length.should.eql(1);
 205        wss2.close();
 206        (typeof srv._webSocketPaths).should.eql('undefined');
 207        srv.close();
 208        done();
 209      });
 210    });
 211  });
 212
 213  describe('#clients', function() {
 214    it('returns a list of connected clients', function(done) {
 215      var wss = new WebSocketServer({port: ++port}, function() {
 216        wss.clients.length.should.eql(0);
 217        var ws = new WebSocket('ws://localhost:' + port);
 218      });
 219      wss.on('connection', function(client) {
 220        wss.clients.length.should.eql(1);
 221        wss.close();
 222        done();
 223      });
 224    });
 225
 226    it('can be disabled', function(done) {
 227      var wss = new WebSocketServer({port: ++port, clientTracking: false}, function() {
 228        wss.clients.length.should.eql(0);
 229        var ws = new WebSocket('ws://localhost:' + port);
 230      });
 231      wss.on('connection', function(client) {
 232        wss.clients.length.should.eql(0);
 233        wss.close();
 234        done();
 235      });
 236    });
 237
 238    it('is updated when client terminates the connection', function(done) {
 239      var ws;
 240      var wss = new WebSocketServer({port: ++port}, function() {
 241        ws = new WebSocket('ws://localhost:' + port);
 242      });
 243      wss.on('connection', function(client) {
 244        client.on('close', function() {
 245          wss.clients.length.should.eql(0);
 246          wss.close();
 247          done();
 248        });
 249        ws.terminate();
 250      });
 251    });
 252
 253    it('is updated when client closes the connection', function(done) {
 254      var ws;
 255      var wss = new WebSocketServer({port: ++port}, function() {
 256        ws = new WebSocket('ws://localhost:' + port);
 257      });
 258      wss.on('connection', function(client) {
 259        client.on('close', function() {
 260          wss.clients.length.should.eql(0);
 261          wss.close();
 262          done();
 263        });
 264        ws.close();
 265      });
 266    });
 267  });
 268
 269  describe('#options', function() {
 270    it('exposes options passed to constructor', function(done) {
 271      var wss = new WebSocketServer({port: ++port}, function() {
 272        wss.options.port.should.eql(port);
 273        wss.close();
 274        done();
 275      });
 276    });
 277  });
 278
 279  describe('#handleUpgrade', function() {
 280    it('can be used for a pre-existing server', function (done) {
 281      var srv = http.createServer();
 282      srv.listen(++port, function () {
 283        var wss = new WebSocketServer({noServer: true});
 284        srv.on('upgrade', function(req, socket, upgradeHead) {
 285          wss.handleUpgrade(req, socket, upgradeHead, function(client) {
 286            client.send('hello');
 287          });
 288        });
 289        var ws = new WebSocket('ws://localhost:' + port);
 290        ws.on('message', function(message) {
 291          message.should.eql('hello');
 292          wss.close();
 293          srv.close();
 294          done();
 295        });
 296      });
 297    });
 298  });
 299
 300  describe('hybi mode', function() {
 301    describe('connection establishing', function() {
 302      it('does not accept connections with no sec-websocket-key', function(done) {
 303        var wss = new WebSocketServer({port: ++port}, function() {
 304          var options = {
 305            port: port,
 306            host: '127.0.0.1',
 307            headers: {
 308              'Connection': 'Upgrade',
 309              'Upgrade': 'websocket'
 310            }
 311          };
 312          var req = http.request(options);
 313          req.end();
 314          req.on('response', function(res) {
 315            res.statusCode.should.eql(400);
 316            wss.close();
 317            done();
 318          });
 319        });
 320        wss.on('connection', function(ws) {
 321          done(new Error('connection must not be established'));
 322        });
 323        wss.on('error', function() {});
 324      });
 325
 326      it('does not accept connections with no sec-websocket-version', function(done) {
 327        var wss = new WebSocketServer({port: ++port}, function() {
 328          var options = {
 329            port: port,
 330            host: '127.0.0.1',
 331            headers: {
 332              'Connection': 'Upgrade',
 333              'Upgrade': 'websocket',
 334              'Sec-WebSocket-Key': 'dGhlIHNhbXBsZSBub25jZQ=='
 335            }
 336          };
 337          var req = http.request(options);
 338          req.end();
 339          req.on('response', function(res) {
 340            res.statusCode.should.eql(400);
 341            wss.close();
 342            done();
 343          });
 344        });
 345        wss.on('connection', function(ws) {
 346          done(new Error('connection must not be established'));
 347        });
 348        wss.on('error', function() {});
 349      });
 350
 351      it('does not accept connections with invalid sec-websocket-version', function(done) {
 352        var wss = new WebSocketServer({port: ++port}, function() {
 353          var options = {
 354            port: port,
 355            host: '127.0.0.1',
 356            headers: {
 357              'Connection': 'Upgrade',
 358              'Upgrade': 'websocket',
 359              'Sec-WebSocket-Key': 'dGhlIHNhbXBsZSBub25jZQ==',
 360              'Sec-WebSocket-Version': 12
 361            }
 362          };
 363          var req = http.request(options);
 364          req.end();
 365          req.on('response', function(res) {
 366            res.statusCode.should.eql(400);
 367            wss.close();
 368            done();
 369          });
 370        });
 371        wss.on('connection', function(ws) {
 372          done(new Error('connection must not be established'));
 373        });
 374        wss.on('error', function() {});
 375      });
 376
 377      it('client can be denied', function(done) {
 378        var wss = new WebSocketServer({port: ++port, verifyClient: function(o) {
 379          return false;
 380        }}, function() {
 381          var options = {
 382            port: port,
 383            host: '127.0.0.1',
 384            headers: {
 385              'Connection': 'Upgrade',
 386              'Upgrade': 'websocket',
 387              'Sec-WebSocket-Key': 'dGhlIHNhbXBsZSBub25jZQ==',
 388              'Sec-WebSocket-Version': 8,
 389              'Sec-WebSocket-Origin': 'http://foobar.com'
 390            }
 391          };
 392          var req = http.request(options);
 393          req.end();
 394          req.on('response', function(res) {
 395            res.statusCode.should.eql(401);
 396            process.nextTick(function() {
 397              wss.close();
 398              done();
 399            });
 400          });
 401        });
 402        wss.on('connection', function(ws) {
 403          done(new Error('connection must not be established'));
 404        });
 405        wss.on('error', function() {});
 406      });
 407
 408      it('client can be accepted', function(done) {
 409        var wss = new WebSocketServer({port: ++port, verifyClient: function(o) {
 410          return true;
 411        }}, function() {
 412          var options = {
 413            port: port,
 414            host: '127.0.0.1',
 415            headers: {
 416              'Connection': 'Upgrade',
 417              'Upgrade': 'websocket',
 418              'Sec-WebSocket-Key': 'dGhlIHNhbXBsZSBub25jZQ==',
 419              'Sec-WebSocket-Version': 13,
 420              'Origin': 'http://foobar.com'
 421            }
 422          };
 423          var req = http.request(options);
 424          req.end();
 425        });
 426        wss.on('connection', function(ws) {
 427          ws.terminate();
 428          wss.close();
 429          done();
 430        });
 431        wss.on('error', function() {});
 432      });
 433
 434      it('verifyClient gets client origin', function(done) {
 435        var verifyClientCalled = false;
 436        var wss = new WebSocketServer({port: ++port, verifyClient: function(info) {
 437          info.origin.should.eql('http://foobarbaz.com');
 438          verifyClientCalled = true;
 439          return false;
 440        }}, function() {
 441          var options = {
 442            port: port,
 443            host: '127.0.0.1',
 444            headers: {
 445              'Connection': 'Upgrade',
 446              'Upgrade': 'websocket',
 447              'Sec-WebSocket-Key': 'dGhlIHNhbXBsZSBub25jZQ==',
 448              'Sec-WebSocket-Version': 13,
 449              'Origin': 'http://foobarbaz.com'
 450            }
 451          };
 452          var req = http.request(options);
 453          req.end();
 454          req.on('response', function(res) {
 455            verifyClientCalled.should.be.ok;
 456            wss.close();
 457            done();
 458          });
 459        });
 460        wss.on('error', function() {});
 461      });
 462
 463      it('verifyClient gets original request', function(done) {
 464        var verifyClientCalled = false;
 465        var wss = new WebSocketServer({port: ++port, verifyClient: function(info) {
 466          info.req.headers['sec-websocket-key'].should.eql('dGhlIHNhbXBsZSBub25jZQ==');
 467          verifyClientCalled = true;
 468          return false;
 469        }}, function() {
 470          var options = {
 471            port: port,
 472            host: '127.0.0.1',
 473            headers: {
 474              'Connection': 'Upgrade',
 475              'Upgrade': 'websocket',
 476              'Sec-WebSocket-Key': 'dGhlIHNhbXBsZSBub25jZQ==',
 477              'Sec-WebSocket-Version': 13,
 478              'Origin': 'http://foobarbaz.com'
 479            }
 480          };
 481          var req = http.request(options);
 482          req.end();
 483          req.on('response', function(res) {
 484            verifyClientCalled.should.be.ok;
 485            wss.close();
 486            done();
 487          });
 488        });
 489        wss.on('error', function() {});
 490      });
 491
 492      it('verifyClient has secure:true for ssl connections', function(done) {
 493        var options = {
 494          key: fs.readFileSync('test/fixtures/key.pem'),
 495          cert: fs.readFileSync('test/fixtures/certificate.pem')
 496        };
 497        var app = https.createServer(options, function (req, res) {
 498          res.writeHead(200);
 499          res.end();
 500        });
 501        var success = false;
 502        var wss = new WebSocketServer({
 503          server: app,
 504          verifyClient: function(info) {
 505            success = info.secure === true;
 506            return true;
 507          }
 508        });
 509        app.listen(++port, function() {
 510          var ws = new WebSocket('wss://localhost:' + port);
 511        });
 512        wss.on('connection', function(ws) {
 513          app.close();
 514          ws.terminate();
 515          wss.close();
 516          success.should.be.ok;
 517          done();
 518        });
 519      });
 520
 521      it('verifyClient has secure:false for non-ssl connections', function(done) {
 522        var app = http.createServer(function (req, res) {
 523          res.writeHead(200);
 524          res.end();
 525        });
 526        var success = false;
 527        var wss = new WebSocketServer({
 528          server: app,
 529          verifyClient: function(info) {
 530            success = info.secure === false;
 531            return true;
 532          }
 533        });
 534        app.listen(++port, function() {
 535          var ws = new WebSocket('ws://localhost:' + port);
 536        });
 537        wss.on('connection', function(ws) {
 538          app.close();
 539          ws.terminate();
 540          wss.close();
 541          success.should.be.ok;
 542          done();
 543        });
 544      });
 545
 546      it('client can be denied asynchronously', function(done) {
 547        var wss = new WebSocketServer({port: ++port, verifyClient: function(o, cb) {
 548          process.nextTick(function() {
 549            cb(false);
 550          });
 551        }}, function() {
 552          var options = {
 553            port: port,
 554            host: '127.0.0.1',
 555            headers: {
 556              'Connection': 'Upgrade',
 557              'Upgrade': 'websocket',
 558              'Sec-WebSocket-Key': 'dGhlIHNhbXBsZSBub25jZQ==',
 559              'Sec-WebSocket-Version': 8,
 560              'Sec-WebSocket-Origin': 'http://foobar.com'
 561            }
 562          };
 563          var req = http.request(options);
 564          req.end();
 565          req.on('response', function(res) {
 566            res.statusCode.should.eql(401);
 567            process.nextTick(function() {
 568              wss.close();
 569              done();
 570            });
 571          });
 572        });
 573        wss.on('connection', function(ws) {
 574          done(new Error('connection must not be established'));
 575        });
 576        wss.on('error', function() {});
 577      });
 578
 579      it('client can be accepted asynchronously', function(done) {
 580        var wss = new WebSocketServer({port: ++port, verifyClient: function(o, cb) {
 581          process.nextTick(function() {
 582            cb(true);
 583          });
 584        }}, function() {
 585          var options = {
 586            port: port,
 587            host: '127.0.0.1',
 588            headers: {
 589              'Connection': 'Upgrade',
 590              'Upgrade': 'websocket',
 591              'Sec-WebSocket-Key': 'dGhlIHNhbXBsZSBub25jZQ==',
 592              'Sec-WebSocket-Version': 13,
 593              'Origin': 'http://foobar.com'
 594            }
 595          };
 596          var req = http.request(options);
 597          req.end();
 598        });
 599        wss.on('connection', function(ws) {
 600          ws.terminate();
 601          wss.close();
 602          done();
 603        });
 604        wss.on('error', function() {});
 605      });
 606
 607      it('handles messages passed along with the upgrade request (upgrade head)', function(done) {
 608        var wss = new WebSocketServer({port: ++port, verifyClient: function(o) {
 609          return true;
 610        }}, function() {
 611          var options = {
 612            port: port,
 613            host: '127.0.0.1',
 614            headers: {
 615              'Connection': 'Upgrade',
 616              'Upgrade': 'websocket',
 617              'Sec-WebSocket-Key': 'dGhlIHNhbXBsZSBub25jZQ==',
 618              'Sec-WebSocket-Version': 13,
 619              'Origin': 'http://foobar.com'
 620            }
 621          };
 622          var req = http.request(options);
 623          req.write(new Buffer([0x81, 0x05, 0x48, 0x65, 0x6c, 0x6c, 0x6f], 'binary'));
 624          req.end();
 625        });
 626        wss.on('connection', function(ws) {
 627          ws.on('message', function(data) {
 628            data.should.eql('Hello');
 629            ws.terminate();
 630            wss.close();
 631            done();
 632          });
 633        });
 634        wss.on('error', function() {});
 635      });
 636
 637      it('selects the first protocol by default', function(done) {
 638        var wss = new WebSocketServer({port: ++port}, function() {
 639          var ws = new WebSocket('ws://localhost:' + port, {protocol: 'prot1, prot2'});
 640          ws.on('open', function(client) {
 641              ws.protocol.should.eql('prot1');
 642              wss.close();
 643              done();
 644          });
 645        });
 646      });
 647
 648      it('selects the last protocol via protocol handler', function(done) {
 649        var wss = new WebSocketServer({port: ++port, handleProtocols: function(ps, cb) {
 650            cb(true, ps[ps.length-1]); }}, function() {
 651          var ws = new WebSocket('ws://localhost:' + port, {protocol: 'prot1, prot2'});
 652          ws.on('open', function(client) {
 653              ws.protocol.should.eql('prot2');
 654              wss.close();
 655              done();
 656          });
 657        });
 658      });
 659
 660      it('client detects invalid server protocol', function(done) {
 661        var wss = new WebSocketServer({port: ++port, handleProtocols: function(ps, cb) {
 662            cb(true, 'prot3'); }}, function() {
 663          var ws = new WebSocket('ws://localhost:' + port, {protocol: 'prot1, prot2'});
 664          ws.on('open', function(client) {
 665              done(new Error('connection must not be established'));
 666          });
 667          ws.on('error', function() {
 668              done();
 669          });
 670        });
 671      });
 672
 673      it('client detects no server protocol', function(done) {
 674        var wss = new WebSocketServer({port: ++port, handleProtocols: function(ps, cb) {
 675            cb(true); }}, function() {
 676          var ws = new WebSocket('ws://localhost:' + port, {protocol: 'prot1, prot2'});
 677          ws.on('open', function(client) {
 678              done(new Error('connection must not be established'));
 679          });
 680          ws.on('error', function() {
 681              done();
 682          });
 683        });
 684      });
 685
 686      it('client refuses server protocols', function(done) {
 687        var wss = new WebSocketServer({port: ++port, handleProtocols: function(ps, cb) {
 688            cb(false); }}, function() {
 689          var ws = new WebSocket('ws://localhost:' + port, {protocol: 'prot1, prot2'});
 690          ws.on('open', function(client) {
 691              done(new Error('connection must not be established'));
 692          });
 693          ws.on('error', function() {
 694              done();
 695          });
 696        });
 697      });
 698
 699      it('server detects invalid protocol handler', function(done) {
 700        var wss = new WebSocketServer({port: ++port, handleProtocols: function(ps, cb) {
 701            // not calling callback is an error and shouldn't timeout
 702        }}, function() {
 703          var options = {
 704            port: port,
 705            host: '127.0.0.1',
 706            headers: {
 707              'Connection': 'Upgrade',
 708              'Upgrade': 'websocket',
 709              'Sec-WebSocket-Key': 'dGhlIHNhbXBsZSBub25jZQ==',
 710              'Sec-WebSocket-Version': 13,
 711              'Sec-WebSocket-Origin': 'http://foobar.com'
 712            }
 713          };
 714          options.port = port;
 715          var req = http.request(options);
 716          req.end();
 717          req.on('response', function(res) {
 718            res.statusCode.should.eql(501);
 719            wss.close();
 720            done();
 721          });
 722        });
 723        wss.on('connection', function(ws) {
 724          done(new Error('connection must not be established'));
 725        });
 726        wss.on('error', function() {});
 727      });
 728    });
 729
 730    describe('messaging', function() {
 731      it('can send and receive data', function(done) {
 732        var data = new Array(65*1024);
 733        for (var i = 0; i < data.length; ++i) {
 734          data[i] = String.fromCharCode(65 + ~~(25 * Math.random()));
 735        }
 736        data = data.join('');
 737        var wss = new WebSocketServer({port: ++port}, function() {
 738          var ws = new WebSocket('ws://localhost:' + port);
 739          ws.on('message', function(message, flags) {
 740            ws.send(message);
 741          });
 742        });
 743        wss.on('connection', function(client) {
 744          client.on('message', function(message) {
 745            message.should.eql(data);
 746            wss.close();
 747            done();
 748          });
 749          client.send(data);
 750        });
 751      });
 752    });
 753  });
 754
 755  describe('hixie mode', function() {
 756    it('can be disabled', function(done) {
 757      var wss = new WebSocketServer({port: ++port, disableHixie: true}, function() {
 758        var options = {
 759          port: port,
 760          host: '127.0.0.1',
 761          headers: {
 762            'Connection': 'Upgrade',
 763            'Upgrade': 'WebSocket',
 764            'Sec-WebSocket-Key1': '3e6b263  4 17 80',
 765            'Sec-WebSocket-Key2': '17  9 G`ZD9   2 2b 7X 3 /r90'
 766          }
 767        };
 768        var req = http.request(options);
 769        req.write('WjN}|M(6');
 770        req.end();
 771        req.on('response', function(res) {
 772          res.statusCode.should.eql(401);
 773          process.nextTick(function() {
 774            wss.close();
 775            done();
 776          });
 777        });
 778      });
 779      wss.on('connection', function(ws) {
 780        done(new Error('connection must not be established'));
 781      });
 782      wss.on('error', function() {});
 783    });
 784
 785    describe('connection establishing', function() {
 786      it('does not accept connections with no sec-websocket-key1', function(done) {
 787        var wss = new WebSocketServer({port: ++port}, function() {
 788          var options = {
 789            port: port,
 790            host: '127.0.0.1',
 791            headers: {
 792              'Connection': 'Upgrade',
 793              'Upgrade': 'WebSocket',
 794              'Sec-WebSocket-Key1': '3e6b263  4 17 80'
 795            }
 796          };
 797          var req = http.request(options);
 798          req.end();
 799          req.on('response', function(res) {
 800            res.statusCode.should.eql(400);
 801            wss.close();
 802            done();
 803          });
 804        });
 805        wss.on('connection', function(ws) {
 806          done(new Error('connection must not be established'));
 807        });
 808        wss.on('error', function() {});
 809      });
 810
 811      it('does not accept connections with no sec-websocket-key2', function(done) {
 812        var wss = new WebSocketServer({port: ++port}, function() {
 813          var options = {
 814            port: port,
 815            host: '127.0.0.1',
 816            headers: {
 817              'Connection': 'Upgrade',
 818              'Upgrade': 'WebSocket',
 819              'Sec-WebSocket-Key2': '17  9 G`ZD9   2 2b 7X 3 /r90'
 820            }
 821          };
 822          var req = http.request(options);
 823          req.end();
 824          req.on('response', function(res) {
 825            res.statusCode.should.eql(400);
 826            wss.close();
 827            done();
 828          });
 829        });
 830        wss.on('connection', function(ws) {
 831          done(new Error('connection must not be established'));
 832        });
 833        wss.on('error', function() {});
 834      });
 835
 836      it('accepts connections with valid handshake', function(done) {
 837        var wss = new WebSocketServer({port: ++port}, function() {
 838          var options = {
 839            port: port,
 840            host: '127.0.0.1',
 841            headers: {
 842              'Connection': 'Upgrade',
 843              'Upgrade': 'WebSocket',
 844              'Sec-WebSocket-Key1': '3e6b263  4 17 80',
 845              'Sec-WebSocket-Key2': '17  9 G`ZD9   2 2b 7X 3 /r90'
 846            }
 847          };
 848          var req = http.request(options);
 849          req.write('WjN}|M(6');
 850          req.end();
 851        });
 852        wss.on('connection', function(ws) {
 853          ws.terminate();
 854          wss.close();
 855          done();
 856        });
 857        wss.on('error', function() {});
 858      });
 859
 860      it('client can be denied', function(done) {
 861        var wss = new WebSocketServer({port: ++port, verifyClient: function(o) {
 862          return false;
 863        }}, function() {
 864          var options = {
 865            port: port,
 866            host: '127.0.0.1',
 867            headers: {
 868              'Connection': 'Upgrade',
 869              'Upgrade': 'WebSocket',
 870              'Sec-WebSocket-Key1': '3e6b263  4 17 80',
 871              'Sec-WebSocket-Key2': '17  9 G`ZD9   2 2b 7X 3 /r90'
 872            }
 873          };
 874          var req = http.request(options);
 875          req.write('WjN}|M(6');
 876          req.end();
 877          req.on('response', function(res) {
 878            res.statusCode.should.eql(401);
 879            process.nextTick(function() {
 880              wss.close();
 881              done();
 882            });
 883          });
 884        });
 885        wss.on('connection', function(ws) {
 886          done(new Error('connection must not be established'));
 887        });
 888        wss.on('error', function() {});
 889      });
 890
 891      it('client can be accepted', function(done) {
 892        var wss = new WebSocketServer({port: ++port, verifyClient: function(o) {
 893          return true;
 894        }}, function() {
 895          var options = {
 896            port: port,
 897            host: '127.0.0.1',
 898            headers: {
 899              'Connection': 'Upgrade',
 900              'Upgrade': 'WebSocket',
 901              'Sec-WebSocket-Key1': '3e6b263  4 17 80',
 902              'Sec-WebSocket-Key2': '17  9 G`ZD9   2 2b 7X 3 /r90'
 903            }
 904          };
 905          var req = http.request(options);
 906          req.write('WjN}|M(6');
 907          req.end();
 908        });
 909        wss.on('connection', function(ws) {
 910          ws.terminate();
 911          wss.close();
 912          done();
 913        });
 914        wss.on('error', function() {});
 915      });
 916
 917      it('verifyClient gets client origin', function(done) {
 918        var verifyClientCalled = false;
 919        var wss = new WebSocketServer({port: ++port, verifyClient: function(info) {
 920          info.origin.should.eql('http://foobarbaz.com');
 921          verifyClientCalled = true;
 922          return false;
 923        }}, function() {
 924          var options = {
 925            port: port,
 926            host: '127.0.0.1',
 927            headers: {
 928              'Connection': 'Upgrade',
 929              'Upgrade': 'WebSocket',
 930              'Origin': 'http://foobarbaz.com',
 931              'Sec-WebSocket-Key1': '3e6b263  4 17 80',
 932              'Sec-WebSocket-Key2': '17  9 G`ZD9   2 2b 7X 3 /r90'
 933            }
 934          };
 935          var req = http.request(options);
 936          req.write('WjN}|M(6');
 937          req.end();
 938          req.on('response', function(res) {
 939            verifyClientCalled.should.be.ok;
 940            wss.close();
 941            done();
 942          });
 943        });
 944        wss.on('error', function() {});
 945      });
 946
 947      it('verifyClient gets original request', function(done) {
 948        var verifyClientCalled = false;
 949        var wss = new WebSocketServer({port: ++port, verifyClient: function(info) {
 950          info.req.headers['sec-websocket-key1'].should.eql('3e6b263  4 17 80');
 951          verifyClientCalled = true;
 952          return false;
 953        }}, function() {
 954          var options = {
 955            port: port,
 956            host: '127.0.0.1',
 957            headers: {
 958              'Connection': 'Upgrade',
 959              'Upgrade': 'WebSocket',
 960              'Origin': 'http://foobarbaz.com',
 961              'Sec-WebSocket-Key1': '3e6b263  4 17 80',
 962              'Sec-WebSocket-Key2': '17  9 G`ZD9   2 2b 7X 3 /r90'
 963            }
 964          };
 965          var req = http.request(options);
 966          req.write('WjN}|M(6');
 967          req.end();
 968          req.on('response', function(res) {
 969            verifyClientCalled.should.be.ok;
 970            wss.close();
 971            done();
 972          });
 973        });
 974        wss.on('error', function() {});
 975      });
 976
 977      it('client can be denied asynchronously', function(done) {
 978        var wss = new WebSocketServer({port: ++port, verifyClient: function(o, cb) {
 979          cb(false);
 980        }}, function() {
 981          var options = {
 982            port: port,
 983            host: '127.0.0.1',
 984            headers: {
 985              'Connection': 'Upgrade',
 986              'Upgrade': 'WebSocket',
 987              'Origin': 'http://foobarbaz.com',
 988              'Sec-WebSocket-Key1': '3e6b263  4 17 80',
 989              'Sec-WebSocket-Key2': '17  9 G`ZD9   2 2b 7X 3 /r90'
 990            }
 991          };
 992          var req = http.request(options);
 993          req.write('WjN}|M(6');
 994          req.end();
 995          req.on('response', function(res) {
 996            res.statusCode.should.eql(401);
 997            process.nextTick(function() {
 998              wss.close();
 999              done();
1000            });
1001          });
1002        });
1003        wss.on('connection', function(ws) {
1004          done(new Error('connection must not be established'));
1005        });
1006        wss.on('error', function() {});
1007      });
1008
1009      it('client can be accepted asynchronously', function(done) {
1010        var wss = new WebSocketServer({port: ++port, verifyClient: function(o, cb) {
1011          cb(true);
1012        }}, function() {
1013          var options = {
1014            port: port,
1015            host: '127.0.0.1',
1016            headers: {
1017              'Connection': 'Upgrade',
1018              'Upgrade': 'WebSocket',
1019              'Origin': 'http://foobarbaz.com',
1020              'Sec-WebSocket-Key1': '3e6b263  4 17 80',
1021              'Sec-WebSocket-Key2': '17  9 G`ZD9   2 2b 7X 3 /r90'
1022            }
1023          };
1024          var req = http.request(options);
1025          req.write('WjN}|M(6');
1026          req.end();
1027        });
1028        wss.on('connection', function(ws) {
1029          wss.close();
1030          done();
1031        });
1032        wss.on('error', function() {});
1033      });
1034
1035      it('handles messages passed along with the upgrade request (upgrade head)', function(done) {
1036        var wss = new WebSocketServer({port: ++port, verifyClient: function(o) {
1037          return true;
1038        }}, function() {
1039          var options = {
1040            port: port,
1041            host: '127.0.0.1',
1042            headers: {
1043              'Connection': 'Upgrade',
1044              'Upgrade': 'WebSocket',
1045              'Sec-WebSocket-Key1': '3e6b263  4 17 80',
1046              'Sec-WebSocket-Key2': '17  9 G`ZD9   2 2b 7X 3 /r90',
1047              'Origin': 'http://foobar.com'
1048            }
1049          };
1050          var req = http.request(options);
1051          req.write('WjN}|M(6');
1052          req.write(new Buffer([0x00, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0xff], 'binary'));
1053          req.end();
1054        });
1055        wss.on('connection', function(ws) {
1056          ws.on('message', function(data) {
1057            data.should.eql('Hello');
1058            ws.terminate();
1059            wss.close();
1060            done();
1061          });
1062        });
1063        wss.on('error', function() {});
1064      });
1065    });
1066  });
1067
1068  describe('client properties', function() {
1069    it('protocol is exposed', function(done) {
1070      var wss = new WebSocketServer({port: ++port}, function() {
1071        var ws = new WebSocket('ws://localhost:' + port, {protocol: 'hi'});
1072      });
1073      wss.on('connection', function(client) {
1074        client.protocol.should.eql('hi');
1075        wss.close();
1076        done();
1077      });
1078    });
1079
1080    it('protocolVersion is exposed', function(done) {
1081      var wss = new WebSocketServer({port: ++port}, function() {
1082        var ws = new WebSocket('ws://localhost:' + port, {protocolVersion: 8});
1083      });
1084      wss.on('connection', function(client) {
1085        client.protocolVersion.should.eql(8);
1086        wss.close();
1087        done();
1088      });
1089    });
1090
1091    it('upgradeReq is the original request object', function(done) {
1092      var wss = new WebSocketServer({port: ++port}, function() {
1093        var ws = new WebSocket('ws://localhost:' + port, {protocolVersion: 8});
1094      });
1095      wss.on('connection', function(client) {
1096        client.upgradeReq.httpVersion.should.eql('1.1');
1097        wss.close();
1098        done();
1099      });
1100    });
1101  });
1102
1103});