Giter VIP home page Giter VIP logo

websocket.io's Introduction

WebSocket.IO

Build Status

WebSocket.IO is an abstraction of the websocket server previously used by Socket.IO. It has the broadest support for websocket protocol/specifications and an API that allows for interoperability with higher-level frameworks such as Engine, Socket.IO's realtime core.

Features

  • Fast
  • Minimalistic
    • Offers an integration API for higher-level impls to handle authorization, routing, etc
  • Widest support of protocols
    • Draft-75
    • Draft-76
    • Draft-00
    • Protocol version 7
    • Protocol version 8
    • Protocol version 13
  • Written for Node 0.6

How to use

Server

(A) Listening on a port

var ws = require('websocket.io')
  , server = ws.listen(3000)

server.on('connection', function (socket) {
  socket.on('message', function () { });
  socket.on('close', function () { });
});

(B) Intercepting WebSocket requests for a http.Server

var ws = require('websocket.io')
  , http = require('http').createServer().listen(3000)
  , server = ws.attach(http)

server.on('connection', function (socket) {
  socket.on('message', function () { });
  socket.on('close', function () { });
});

(C) Passing in requests

var ws = require('websocket.io')
  , server = new ws.Server()

server.on('connection', function (socket) {
  socket.send('hi');
});

// …
httpServer.on('upgrade', function (req, socket, head) {
  server.handleUpgrade(req, socket, head);
});

Client-side example

var ws = new WebSocket("ws://host:port/");        

socket.onopen = function() {
 //do something when connection estabilished
};

socket.onmessage = function(message) {
 //do something when message arrives
};

socket.onclose = function() {
 //do something when connection close
};

API

Server



Top-level

These are exposed by require('websocket.io'):

Properties
  • version (String): websocket.io version
  • protocols (Object): constructors for drafts 75/76/00, protocols 7/8/13.
Methods
  • listen
    • Creates an http.Server which listens on the given port and attaches WS to it. It returns 501 Not Implemented for regular http requests.
    • Parameters
      • Number: port to listen on
      • Object: optional options object. See Server for options details.
      • Function: callback for listen
    • Returns Server
  • attach
    • Captures upgrade requests for a http.Server. In other words, makes a regular http.Server websocket-compatible.
    • Parameters
      • http.Server: server to attach to.
      • Object: optional, options object. See Server for options details.
    • Returns Server


Server

The main server/manager. Inherits from EventEmitter.

Properties
  • clients (Object): table of all connected clients. This property is not set when the Server option clientTracking is false.
  • clientsCount (Number): total count of connected clients. This property is not set when the Server option clientTracking is false.
Events
  • connection
    • Fired when a new connection is established.
    • Arguments
      • Socket: a Socket object
Methods
  • constructor
    • Initializes the server
    • Options
      • path (String): if set, server only listens to request for this path
      • clientTracking (Boolean): enables client tracking. The Server#clients property only is available when this is true (true)
  • handleUpgrade


Socket

A representation of a client. Inherits from EventEmitter.

Properties
  • req (http.ServerRequest): Request that originated the connection.
  • socket (net.Socket): Stream that originated the connection.
  • readyState (String): opening, open, closed.
  • name (String): websocket-hixie, websocket.
  • protocolVersion (String): hixie-75, hixie-76 and hybi.
Events
  • close
    • Fired when the connection is closed.
  • message/data
    • Fired when data is received
    • Arguments
      • String: utf-8 string
  • error
    • Fired when an error occurs.
    • Arguments
      • Error: error object
Methods
  • send / write
    • Sends a message.
    • Parameters
      • String: utf-8 string with outgoing data
    • Returns Socket for chaining
  • close / end
    • Closes the socket
    • Returns Socket for chaining
  • destroy
    • Forcibly closes the socket.

Support

The support channels for websocket.io are the same as socket.io:

Development

To contribute patches, run tests or benchmarks, make sure to clone the repository:

git clone git://github.com/LearnBoost/websocket.io.git

Then:

cd websocket.io
npm install

Tests

$ make test

Credits

WebSocket.IO is possible thanks to the contributions by:

License

(The MIT License)

Copyright (c) 2011 Guillermo Rauch <[email protected]>

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

websocket.io's People

Contributors

3rd-eden avatar dvv avatar einaros avatar emerleite avatar netroy avatar nicokaiser avatar rauchg avatar ruxkor avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

websocket.io's Issues

IP Adress

How to get the client's IP-Adress/Port when a client connects?
For example:

server.on('connection', function(client) {
    console.log("New Connection (" + client.getIP() + ":" + client.getPort() + ")");
});

separate servers for sub-protocols (i.e. Sec-WebSocket-Protocol)

The API allows implementing multiple sub-protocols in the socket call back using a switch on socket.ws.protocol to give the different protocols different socket event call-backs. It seems it would be nicer to make the server API look more like the browser's WS API, where the protocol is specified in the connection parameters, and you get different connection objects for different sub-protocols on the same server/port.
So:

var ws = require('websocket.io')
  , one_server = ws.listen(3000, 'one_protocol')
  , another_server = ws.listen(3000, 'another_protocol')

one_server.on('connection', function (socket) {
    socket.on('message', function () { });
    socket.on('close', function () { });
});

another_server.on('connection', function (socket) {
    socket.on('message', function () { });
    socket.on('close', function () { });
});

Instead of:

var ws = require('websocket.io')
  , server = ws.listen(3000)

server.on('connection', function (socket) {
  switch (socket.ws.protocol) {
  case ('one_protocol'):
    socket.on('message', function () { });
    socket.on('close', function () { });
    break;
  case ('another_protocol'):
    socket.on('message', function () { });
    socket.on('close', function () { });
    break;
});

Or maybe there is a better way of doing this that I've missed?
Its a fairly minor and probably mostly aesthetic issue. Still a "sanctioned" way of supporting multiple protocols on the same port should really be included in the examples, since its not obvious from the API. There are few examples of using multiple WS sub-protocols on-line at the moment other than the nice ones in the libwebsockets C library, which does a good job of highlighting their utility.

Server reference in Socket

Is the Server reference in the Socket really necessary? In the API docs it's not mentioned, and acutally it's only needed for logging (see #31).

Getting rid of the server reference in the Socket would save quite some memory (-> Socket constructor would be "Socket (req)" only).

Uses vulnerable version of ws

[email protected] is listed as having a couple of DoS security vulnerabilities on npm. Is this project still maintained?

┌───────────────┬──────────────────────────────────────────────────────────────┐
│ High          │ Denial of Service                                            │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Package       │ ws                                                           │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Patched in    │ >= 1.1.5 <2.0.0 || >=3.3.1                                   │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Dependency of │ easy-livereload                                              │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Path          │ easy-livereload > livereload-server > websocket.io > ws      │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ More info     │ https://nodesecurity.io/advisories/550                       │
└───────────────┴──────────────────────────────────────────────────────────────┘
┌───────────────┬──────────────────────────────────────────────────────────────┐
│ High          │ DoS due to excessively large websocket message               │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Package       │ ws                                                           │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Patched in    │ >=1.1.1                                                      │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Dependency of │ easy-livereload                                              │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Path          │ easy-livereload > livereload-server > websocket.io > ws      │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ More info     │ https://nodesecurity.io/advisories/120                       │
└───────────────┴──────────────────────────────────────────────────────────────┘

Client-side example needed

There doesn't seem to be a cut-n-paste example of how to use "new WebSocket()" in a web browser against this codebase. What I am trying does not appear to work in the latest versions of Firefox and Chrome (protocol version 8), however Safari does work (using "drafts" protocol).

In protocol 8 an http upgrade event occurs, but server.on('connection') is not called, and the client doesn't receive an "onopen" event.

Here's what I'm using for the server:

var ws = require('websocket.io')
, server = ws.listen(3000)
server.on('connection', function (client) {
console.log('connection');
client.send('client ping');
client.on('message', function (data) { console.log('message: '+data) });
client.on('close', function () { console.log('close') });
});

And here's my client-side HTML file:

<script>
var WS = (typeof MozWebSocket=='function')? MozWebSocket : WebSocket;
var websocket = new WS('ws://localhost:3000');
websocket.onopen = function () {
console.log('open');
websocket.send('server ping');
};
websocket.onerror = function (error) {
console.log('error '+error);
};
websocket.onmessage = function (e) {
console.log('message: '+e.data);
};
websocket.onclose = function(data) {
console.log('close');
};
</script>

Mask Send Messages

Looking at the websocket message transfer:

sudo tcpdump -A -s0 -ilo0 port 8687

I can see that my IOS app using SRWebSocket mask my messages (frames).

But node.js/websocket.io doesnt mask and send normaly.

For example, IOS to Node:

21:29:16.412636 IP localhost.52317 > localhost.8687: Flags [P.], seq 391:484, ack 130, win 9178, options [nop,nop,TS val 1143337638 ecr 1143337638], length 93
E...S.@.@............]!.T.W.......#........
D%..D%[email protected][email protected]...W.@[email protected]......

But Node to IOS:
21:29:16.418444 IP localhost.8687 > localhost.52317: Flags [P.], seq 130:229, ack 484, win 9156, options [nop,nop,TS val 1143337643 ecr 1143337638], length 99
E...AC@.@...........!..]....T.X"..#........
D%..D%...a{"type":"user","action":"reload","for_user":7}

I can see the json.

Any how to mask the messages that goes out of websocket.io ?

Thanks.

PS: BTW I saw how IOS mask the frames..

client tracking bug in handleUpgrade

Server.prototype.handleUpgrade has a nasty bug with regard to client tracking. It uses "i" which is an outside of scope variable— seems like this might be just a typo of just some late night coding.

  client.on('close', function () {
    self.clients[i] = null;
    self.clientsCount--;
  });

Since we're sure that client is inside of the clients array, a quick fix to the bug would be to do the following:

  client.on('close', function () {
    clients.splice(clients.indexOf(client),1);
    self.clientsCount--;
  });

Server crashes when a client sends exactly 2^16 bytes binary data

Is it supposed to be ">=" instead of ">" at line 189 in lib/protocols/ hybi-16.js ?

The error message that I got follows. Once I corrected the line manually in node_modules, it worked.
Thanks

assert.js:104
throw new assert.AssertionError({
^
AssertionError: value is larger than maximum value for type
at verifuint (buffer.js:821:10)
at writeUInt16 (buffer.js:859:5)
at Buffer.writeUInt16BE (buffer.js:876:3)
at WebSocket.frame (/Users/kazuyukitanimura/Documents/git/websocket.io-binaryTransferBenchmark/node_modules/websocket.io/lib/protocols/hybi-16.js:205:20)
at WebSocket.write (/Users/kazuyukitanimura/Documents/git/websocket.io-binaryTransferBenchmark/node_modules/websocket.io/lib/protocols/hybi-16.js:150:20)
at WebSocket.send (/Users/kazuyukitanimura/Documents/git/websocket.io-binaryTransferBenchmark/node_modules/websocket.io/lib/socket.js:88:8)
at WebSocket. (/Users/kazuyukitanimura/Documents/git/websocket.io-binaryTransferBenchmark/websocket.io-app.js:25:16)
at WebSocket.emit (events.js:67:17)
at WebSocket.onMessage (/Users/kazuyukitanimura/Documents/git/websocket.io-binaryTransferBenchmark/node_modules/websocket.io/lib/socket.js:76:8)
at Receiver. (/Users/kazuyukitanimura/Documents/git/websocket.io-binaryTransferBenchmark/node_modules/websocket.io/lib/protocols/hybi-16.js:43:12)

Server leaks memory (Socket objects)

The server keeps as many Socket objects as it had concurrent (!) connections. Seems like these objects are not removed properly in the Server object...

I'll try to provide a simple test for this soon.

Method writeUInt16BE missing in Node 0.4

I'm trying to run a websocket.io server on Node 0.4 (as Node 0.6 still leaks consiberable amouts of memory). However when trying to send data to a hybi-16 client, the server crashes:

TypeError: Object �~{"event":"article","data":{...}}} has no method 'writeUInt16BE'
    at WebSocket.frame (/Users/nkaiser/Sites/applications/services/webpush/node_modules/websocket.io/lib/protocols/hybi-16.js:205:20)
    at WebSocket.write (/Users/nkaiser/Sites/applications/services/webpush/node_modules/websocket.io/lib/protocols/hybi-16.js:150:20)
    at WebSocket.send (/Users/nkaiser/Sites/applications/services/webpush/node_modules/websocket.io/lib/socket.js:104:8)
    at sendObject (/Users/nkaiser/Sites/applications/services/webpush/lib/webpush-wsio.js:656:8)
    at [object Object]._broadcast (/Users/nkaiser/Sites/applications/services/webpush/lib/webpush-wsio.js:432:9)
    at Array.<anonymous> (/Users/nkaiser/Sites/applications/services/webpush/lib/webpush-wsio.js:402:10)
    at EventEmitter._tickCallback (node.js:126:26)

Seems like writeUInt16BE is missing in Node 0.4.
Is there a way to workaround this?

Node version requirements

In package.json you specify "engines": { "node": ">= 0.5.0 < 0.7.0" }
Does WebSocket.IO require Node 0.6? It seems to run fine with Node 0.4.x...

Empty/Undefined error-Events

If you try to send to an stored client-socket and the client is currently unavailable you've got an exception.

events.js:72
        throw er; // Unhandled 'error' event
          ^
Error: read ECONNRESET
    at errnoException (net.js:904:11)
    at TCP.onread (net.js:558:19)

The problem is: When the socket receive an error over socket.on('error', callback(event) and the event is empty or undefined, that breaks the complete Node.js application.

I've solved the problem but i will test it currently. I will make a pull request today.

server.clients grows over time

In server.js you constantly push new clients to self.clients, and just set the array entry to null on close.

self.clients[i] = null;

This leads to a constantly growing array which consists mostly of null (all disconnected clients). Can this be a memory problem over time?

Sub-protocol support broken

Currently the sub-protocol support is broken in websocket.io (when the hybi protocol is used). The problem is in the 'ws' package / library. It was fixed there in version 0.4.22, but websocket.io still requires 0.4.20 in its dependencies.

It should be atleast changed to 0.4.22 to support sub-protocols properly again.

Fix in 'ws' library for reference: websockets/ws@b0be70f

Error handling must be reworked

The error handling is completely broken.

I'm getting random "Error: write EPIPE" and "Error: This socket is closed." from websocket.io which completely crashes the application, even tough I have "error" handlers for wsio sockets.

node.js:201
        throw e; // process.nextTick error, or 'error' event on first tick
              ^
Error: write EPIPE
    at errnoException (net.js:670:11)
    at Object.afterWrite [as oncomplete] (net.js:503:19)
Error: This socket is closed.
    at Socket._write (net.js:474:19)
    at Socket.write (net.js:466:15)
    at WebSocket.write (/opt/services/webpush/support/webpush-engine/node_modules/websocket.io/lib/protocols/drafts.js:194:23)
    at WebSocket.send (/opt/services/webpush/support/webpush-engine/node_modules/websocket.io/lib/socket.js:104:8)
    at WebPush._doBroadcast (/opt/services/webpush/lib/webpush.js:295:34)
    at Array.0 (/opt/services/webpush/lib/webpush.js:304:12)
    at EventEmitter._tickCallback (node.js:192:40)

I cannot tell if this is emitted by ws or by the "drafts" handler, as I cannot reproduce without live clients...

Socket idle timeout problem

The connection closes at precisely two minutes of idle time at the client. I looked through the code and can't make heads or tails of where this is coming from.

tested on Chrome 15, Chrome 16, and Firefox 8.

Warning in Node 6.1.0

It seems that Node v6.1.0 marked process.EventEmitter as deprecated. It spits out this warning when loading websocket.io:

(node:272) DeprecationWarning: process.EventEmitter is deprecated. Use require('events') instead.

This project looks abandoned, but it's probably an easy fix.

inconsistency between ws.WebSocket.readyState and websocket.io/hybi/WebSocket.readyState

While testing the current master of engine.io/websocket.io we encountered the following error: [1]

I think the reason for this is an inconsistency between WebSocket objects in websocket.io and ws; the former only calls ws.write if it's readyState == 'open', and the latter throws an error if it's readyState != WebSocket.OPEN

Changing ws/WebSocket's behavior to emit instead of throwing errors (since it inherits from EventEmitter) makes the handling easier, but does, of course, not provide a remedy for this problem.

I am still trying to figure out a way to reproduce the error and will update the issue if I find something of relevance.

[1]
/my/app/node_modules/long-stack-traces/lib/long-stack-traces.js:81
                throw e;
                      ^
Error: not opened
    at WebSocket.send (/my/app/node_modules/engine.io/node_modules/websocket.io/node_modules/ws/lib/WebSocket.js:175:16)
    at WebSocket.write (/my/app/node_modules/engine.io/node_modules/websocket.io/lib/protocols/hybi.js:101:13)
    at WebSocket.send (/my/app/node_modules/engine.io/node_modules/websocket.io/lib/socket.js:105:8)
    at WebSocket.send (/my/app/node_modules/engine.io/lib/transports/websocket.js:69:17)
    at Socket.flush (/my/app/node_modules/engine.io/lib/socket.js:237:20)
    at Socket.sendPacket (/my/app/node_modules/engine.io/lib/socket.js:223:10)
    at Socket.send (/my/app/node_modules/engine.io/lib/socket.js:207:8)
    at Socket.send_ns (/my/app/node_modules/engine.ns.io-base/lib/engine.ns.io-base.coffee:38:19)
    at /my/app/server.coffee:161:27
    at Socket.get (/my/app/server.coffee:120:14)
----------------------------------------
    at EventEmitter.on
    at Object.<anonymous> (/my/app/server.coffee:150:23)
    ....

(node:6620) DeprecationWarning: process.EventEmitter is deprecated. use require('events') instead.

As a user of node module robohydra I am experiencing a warning when running on node.js v6.1.0 on windows. The error appears on start of my application, and is listed as a warning.

(node:6620) DeprecationWarning: process.EventEmitter is deprecated. use require('events') instead.

After trail and error I found that the warning disappears if the line https://github.com/LearnBoost/websocket.io/blob/master/lib/socket.js#L6 is changed from

var EventEmitter = process.EventEmitter

to

var EventEmitter = require('events')

websocket.io is used as an external dependancy to robohydra.
All features runs just fine. However no websockets are in use in our system, and I am not capable of testing this change. Please help.

ps: I have noted the maintainers of robohydra. thie issue is filed in robohydra/robohydra#24

Replace logger by debug?

In Engine.IO you are using "debug" for logging / debugging, wsio still uses the logger object. Do you plan to replace the logger by debug? That would be consistent and reduce the amount of references passed around in the socket objects... (this.server.log...)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.