Giter Site home page Giter Site logo

websockets / ws Goto Github PK

View Code? Open in Web Editor NEW
21.1K 377.0 2.3K 10.99 MB

Simple to use, blazing fast and thoroughly tested WebSocket client and server for Node.js

License: MIT License

JavaScript 100.00%
websocket javascript websocket-client websocket-server rfc-6455 real-time nodejs node websocket-compression

ws's People

Contributors

3rd-eden avatar aklaswad avatar arlolra avatar darrachequesne avatar davedoesdev avatar defunctzombie avatar download13 avatar einaros avatar greenkeeper[bot] avatar ide avatar jacksontian avatar jcrugzz avatar kkoopa avatar lordmajestros avatar lpinca avatar machenmusik avatar mmalecki avatar nicokaiser avatar nkzawa avatar pimterry avatar pskocik avatar pyrtsa avatar saschagehlich avatar seapunk avatar sebpiq avatar strml avatar timjrobinson avatar tootallnate avatar tricknotes avatar yaworsw 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  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

ws's Issues

Crash when connection is closed before firstHandler is called

TypeError: Cannot call method 'add' of null
    at Array.firstHandler [as 2] (/opt/services/webpush/support/webpush-engine/node_modules/ws/lib/WebSocket.js:488:16)
    at EventEmitter._tickCallback (node.js:192:40)

Sometimes, the connection is closed by the client immediately after opening. In establishConnection there is process.nextTick(firstHandler), which adds data to the receiver. However, if in the meantime (before nextTick!) the connection was closed, the receiver is set to null and data cannot be added.

This results in the crash described above.

=> firstHandler should check if the connection is still WebSocket.OPEN.

(This is no problem in realHandler which is called only on data event - and after close there is no data)

Fragmented sending not possible via WebSocket.send()

When using Websocket.send(), it is not possible to send fragments of data (with fin flag === false).
This is because Websocket.send() sets the fin flag to true in any case.
Suggested fix:
Take over the fin flag from the options, set to true if it is not present.

Many connections left in readyState 2

After running for some hours, there are quite some connections with readyState 2 (WebSocket.CLOSING). They are never closed, even after some minutes (socket timeouts).

This may be the result of a client never reacting to close packets.

I agree that socket.end is nicer than socket.destroy, but there must be some kind of timer that destroys a connection that is CLOSING for too long. This gets even worse when the connection is ended because of handshake failures – then, the connection is invisible for the application (not emitted as connection event) and dangling around forever.

bad dependency

ws depends on exactly commander 0.5.0 version but this version does not yet officially include node 0.7.x support.

I think this should be in package.json (0.5.x instead of 0.5.0):

  "dependencies": {
    "commander": "0.5.x",
    "options": "latest"
  },

Implement proper sub-protocol support

The protocol header can include multiple sub-protocol values in the request. In order to properly support sub-protocols, there needs to be some way for the server to select the protocol from the list that it supports (because the response needs to have only one).

This may require a separate callback handler so that the server using 'ws' has the opportunity to select the one it wants to use before the connection is fully established (i.e. on-connection is too).

Sender.Hixie ignores the fin flag

The Sender.Hixie's send() method simply ignores the fin flag.
This leads to incomplete frames when using Websockets.stream() or send() with a read stream.
Suggested fix:
Write the final FF byte only when fin === true, write the initial 00 byte only when the last frame was terminated.

Error: This socket is closed.

I just got this crash:

node.js:201
        throw e; // process.nextTick error, or 'error' event on first tick
              ^
Error: This socket is closed.
    at Socket._write (net.js:474:19)
    at Socket.write (net.js:466:15)
    at WebSocketServer.<anonymous> (/home/wwwdocs/applications/services/webpush/node_modules/ws/lib/WebSocketServer.js:292:16)
    at /home/wwwdocs/applications/services/webpush/node_modules/ws/lib/WebSocketServer.js:321:25
    at WebSocketServer.handleHixieUpgrade (/home/wwwdocs/applications/services/webpush/node_modules/ws/lib/WebSocketServer.js:368:3)
    at WebSocketServer.handleUpgrade (/home/wwwdocs/applications/services/webpush/node_modules/ws/lib/WebSocketServer.js:141:61)
    at Server.handleUpgrade (/home/wwwdocs/applications/services/webpush/lib/engine/lib/server.js:70:11)
    at Server.<anonymous> (/home/wwwdocs/applications/services/webpush/lib/engine/lib/webpush-engine.js:47:12)
    at Server.emit (events.js:88:20)
    at Socket.<anonymous> (http.js:1483:14)

node.js 0.6.17, ws 0.4.15.

I think (!) this has nothing to do with the latest update of WebSocketServer.js – and I wonder why this error was not caught by the try/catch (maybe this is a deferred thing again, and you have to check if the socket is open before the writes).

In windows VS2005

In windows, how to use VS2005 compile bufferutil.cc,
I want to use windows "WS"。

Error: Cannot find module '../build/default/bufferutil'

Getting this error after building

node.js:201
throw e; // process.nextTick error, or 'error' event on first tick
^
Error: Cannot find module '../build/default/bufferutil'
at Function._resolveFilename (module.js:332:11)
at Function._load (module.js:279:25)
at Module.require (module.js:354:17)
at require (module.js:370:17)
at Object. (..../savant-demo/node_modules/ws/lib/BufferUtil.js:14:20)

I clearly have the files ... but I am not sure what is going on

http://i.imgur.com/zq8Cx.png

how to handle binary data on server side

I'm trying to implement a simple c/s example,client is like this:
var WebSocket = require('ws'),
ws = new WebSocket('ws://127.0.0.1:8888');
ws.on('open', function() {
console.log('connected');
var array = new Float32Array(5);
for(var i = 0; i < array.length; ++i)
array[i] = i/2;
console.log(array);
ws.send(array, {binary:true, mask:true});
});

ws.on('close', function() {
console.log('disconnected');
});
And on the server side :
var WebSocketServer = require('ws').Server,
wss = new WebSocketServer({host:'0.0.0.0', port:8888});
wss.on('connection', function(ws) {
console.log('connected');
ws.on('message', function(message, flags) {
console.log(flags.binary, flags.masked);
var buf = new Buffer(message, 'binary');
console.log(buf.toString());
});

ws.on('close', function() {
    console.log('close connection');
});
ws.on('error', function(e) {
    console.log('error:' + e.message);
});

});
and my output on the serverside is:
true true
?????@

what's wrong with my code?

Close Specified Client Failed?

Here is my code

var wss = new WebsocketServer({port:8100});
wss.on("connection", function(client){
client.on("close",function(){
console.log("colse");
})

client.on("error",function(){
     console.log("error");
 })

client.on("message", function(msg){
    if( ! isValide(msg)){
          client.close();
    }
})

}

When I send Some Error Msg To The Sever.
I Think The Client Shoud Be Closed.
But It Just Output The Message "error" , which the client.on("error") was fired, and the client can still sending messages.
How Can I close the client on the server side?
Thanks!

Make it possible to listen on multiple http/https servers

The reason for this is to be able to run a single ws on a single Expressjs/Connect http server abstraction, which works on top of one http sever, and one https server, or possibly even more servers connected to various ports.

So that this setup is possible:

var express = require('express');
var app = express.createServer();
var ws = require('ws');

var httpsOptions = { key: ..., crt: ... };

var httpServer = http.createServer(app.handle.bind(app)).listen(port);
var httpsServer = https.createServer(httpsOptions, app.handle.bind(app))
    .listen(httpsPort);

// the server could optionally take an array of servers to listen on:
var wss = new ws.Server({ server: [ httpServer, httpsServer ] });

// configure your "app", not having to deal with both 
// http and https version separately:
app.get('/', function(req, res, next) { ... });

Currently, I'm working around this like this:

var ServerHub = function(servers) {
    var self = this;
    var events = [ 'upgrade', 'error' ];
    for(var s in servers) {
        for(var e in events) {
            (function(server, event) {
                server.on(event, function() {
                    var args = Array.prototype.slice.call(arguments);
                    args.unshift(event);
                    self.emit.apply(self, args);
                });
            })(servers[s], events[e]);
        }
    }
};
util.inherits(ServerHub, events.EventEmitter);

wss = new ws.Server({ server: new ServerHub([ httpServer, httpsServer ]) });

Can't Install on Snow Leopard without Xcode 4.0+

Can't Install on Snow Leopard without Xcode 4.0+.

You run into the following error:

[1/4] cxx: src/validation.cc -> build/Release/src/validation_1.o
[2/4] cxx: src/bufferutil.cc -> build/Release/src/bufferutil_2.o
cc1plus: error: unrecognized command line option "-arch"
cc1plus: error: unrecognized command line option "-arch"

This is fixed with XCode 4.0+. However, there is no way to get XCode 4.0+ for Snow Leopard.

W3C API compatibility

I'm writing a library on top of your excellent library that I'd like to use both on Node.js and in browsers. I have ran into a couple of issues with API incompatibility. The W3C API allows these two variants:

ws.onmessage = function(e) {
    var payload = e.data;
};

ws.addEventListener('message', function(e) {
    var payload = e.data;
});

Your implementation allows:

ws.on('message', function(payload){
});

I'm proposing 3 changes:

  • Deliver messages in an Event object with a data attribute
  • Allow ws.addEventListener(eventName, Function)
  • Allow ws.onmessage = Function

This would break the current API, but it would also make it follow the official API more closely. Would you be interested in a patch for this?

Aslak

'error' event should be handled

In WebSocketServer.js, strange errors occur:

node.js:201
        throw e; // process.nextTick error, or 'error' event on first tick
              ^
Error: This socket is closed.
    at Socket._write (net.js:474:19)
    at Socket.write (net.js:466:15)
    at WebSocketServer.<anonymous> (/opt/services/webpush/support/webpush-engine/node_modules/ws/lib/WebSocketServer.js:297:16)
    at /opt/services/webpush/support/webpush-engine/node_modules/ws/lib/WebSocketServer.js:326:25
    at WebSocketServer.handleHixieUpgrade (/opt/services/webpush/support/webpush-engine/node_modules/ws/lib/WebSocketServer.js:372:3)
    at WebSocketServer.handleUpgrade (/opt/services/webpush/support/webpush-engine/node_modules/ws/lib/WebSocketServer.js:147:61)
    at Server.handleUpgrade (/opt/services/webpush/support/webpush-engine/lib/server.js:66:11)
    at Server.<anonymous> (/opt/services/webpush/support/webpush-engine/lib/webpush-engine.js:47:12)
    at Server.emit (events.js:88:20)
    at Socket.<anonymous> (http.js:1425:14)

At the time the 'write' happens, there is no 'error' handler for the socket, that may be why the exception is not caught by the try/catch.

Socket.io 0.9.0 + WebSocket.prototype.close

I'm running socket.io 0.9.0 that's currently shipping with ws 0.4.0, but I've tested it with ws 0.4.7 too. I'm running socket.io-client (0.9.0) on the server side and sometimes the client disconnects (not sure why but that's not the problem here), when it does the socket.io-client service crashed with the following error:

ws 0.4.0:
/node_modules/socket.io-client/node_modules/ws/lib/WebSocket.js:215
if (this._state != 'connected') throw new Error('not connected');

ws 0.4.7:
/node_modules/socket.io-client/node_modules/ws/lib/WebSocket.js:104
if (this.readyState != WebSocket.OPEN) throw new Error('not opened');

It's not that big of a problem because forever will restart the service and it will reconnect to my socket.io server, but just a heads up..

Can't listen to the same port with different paths

Following code fails:

var WebSocketServer = require('ws').Server,
    a = new WebSocketServer({port:8080, path:'/a'}), 
    b = new WebSocketServer({port:8080, path:'/b'});
return;

I receive error as follows:

node.js:201
        throw e; // process.nextTick error, or 'error' event on first tick
              ^
Error: listen EADDRINUSE
    at errnoException (net.js:632:11)
    at Array.1 (net.js:733:26)
    at EventEmitter._tickCallback (node.js:192:40)

on node.js 0.6.6 with latest ws.

Broadcast / client id

Do you have a concept of a unique client id built in? I wonder how I'd address certain clients and send them messages. For a broadcast I can iterate over wss.clients. But I wonder what's the best way to pick individual ones. What does actually happen if a client disconnects. It just gets removed from the wss.clients list? I guess the best way to do it is keeping track of clients manually, once they connect.

Something like that:

wss.on('connection', function(ws) {
  // Register client
  clients[numClients++] = ws;
});

Would that make sense?

I like that the lib is very low level and doesn't introduce much magic, but some recipes on how to do A or B would be nice to have. :)

Socket is not terminated on close with broken clients

The general behavior with broken WebSocket clients is not perfect yet.

In WebSocket.prototype.terminate, you call "socket.end()", however this should be "socket.destroy()"?

In this example I use "websocket-client" (which generates a strange "Client error: payload must start with 0x00 byte" error after close by the way), and this leads to socket.end not closing the socket.

var WebSocket = require('websocket-client').WebSocket;

var ws = new WebSocket('ws://localhost:3000/');
ws.on('open', function() {
    ws.send('Hello World');
    setTimeout(function() {
        ws.close();
    }, 1000);
});

If you add "setTimeout(function() {}, 10000);" after "ws.close()" you can see the connection stays open forever (until the client script terminates).

"install WS with blazing fast native extensions" via package.json

This --ws:native option is not deployment friendly and doesn't work when ws is installed as a dependecy down in the tree.

In my setup, socket.io depends on ws and is installed via package.json - how can I use the native extensions with this setup?

$ uname -a
Darwin leos-imac.fritz.box 11.3.0 Darwin Kernel Version 11.3.0: Thu Jan 12 18:47:41 PST 2012; root:xnu-1699.24.23~1/RELEASE_X86_64 x86_64
$ node -v
v0.6.17

wscat uses port 80 for wss:// by default

alexo@codedot:~$ wscat -c ws://localhost/

connected (press CTRL+C to quit)

< socket.send("Hello World!");

Hello World!

< alert("Hello World!");

alexo@codedot:~$ wscat -c wss://localhost/

error: Error: socket hang up undefined

alexo@codedot:$ wscat -c wss://localhost:443/
connected (press CTRL+C to quit)
< socket.send("Hello World!");
Hello World!
< alert("Hello World!");
alexo@codedot:
$

Allow to configure handshake request headers

It would be very helpful if ws.WebSocket implementation would allow to override/append HTTP request headers for handshake. For example, client may want to set custom headers with implementation-specific values, instead of sending them after handshake.

The RFC-6455 doesn't restrict this.

new WebSocket(
    'ws://example.com',
    {...
        headers: {
            'User-Agent': 'Node v0.7.7',
            'X-Custom-Authentication-Header': 'qwerty'
        }
    }
);

Error installing 'ws' via npm.

sankaran@ubuntu:$ npm install ws
node-waf configure build
Checking for program g++ or c++ : /usr/bin/g++
Checking for program cpp : /usr/bin/cpp
Checking for program ar : /usr/bin/ar
Checking for program ranlib : /usr/bin/ranlib
Checking for g++ : ok
Checking for node path : ok /home/sankaran/.node_libraries
Checking for node prefix : ok /usr
'configure' finished successfully (0.032s)
Waf: Entering directory /home/sankaran/.node_libraries/.npm/ws/0.4.12/package/build' [1/4] cxx: src/validation.cc -> build/default/src/validation_1.o [2/4] cxx: src/bufferutil.cc -> build/default/src/bufferutil_2.o [3/4] cxx_link: build/default/src/validation_1.o -> build/default/validation.node [4/4] cxx_link: build/default/src/bufferutil_2.o -> build/default/bufferutil.node Waf: Leaving directory/home/sankaran/.node_libraries/.npm/ws/0.4.12/package/build'
'build' finished successfully (0.630s)
npm ERR! install failed Error: Required package: options(latest) not found. (Found: ["0.0.3"])
npm ERR! install failed (required by: [email protected])
npm ERR! install failed at /usr/share/npm/lib/build.js:192:19
npm ERR! install failed at cb (/usr/share/npm/lib/utils/graceful-fs.js:32:9)
npm ERR! Error: Required package: options(latest) not found. (Found: ["0.0.3"])
npm ERR! (required by: [email protected])
npm ERR! at /usr/share/npm/lib/build.js:192:19
npm ERR! at cb (/usr/share/npm/lib/utils/graceful-fs.js:32:9)
npm ERR! Report this entire log at http://github.com/isaacs/npm/issues
npm ERR! or email it to [email protected]
npm ERR! Just tweeting a tiny part of the error will not be helpful.
npm not ok
sankaran@ubuntu:
$

Simple Test case crashes server

Server code

var WebSocketServer = require('ws').Server
, wss = new WebSocketServer({port: 1337});

wss.on('connection', function(ws) {
ws.on('message', function(message) {
console.log('received: %s', message);
});

});

Code from Mozilla scratchpad

var ws = new MozWebSocket("ws://localhost:1337");
ws.onopen = function()
{

for(var i = 0; i < 10000;i++)
{
    ws.send("<mary>had a little lamb</mary>");
}

};

No such file or directory: '/Users/einaros/code/ws/build'

I'm not sure how to configure to the correct directory.

Here is the error output:

npm http GET https://registry.npmjs.org/ws
npm http 304 https://registry.npmjs.org/ws
Checking for program g++ or c++ : /usr/bin/g++
Checking for program cpp : /usr/bin/cpp
Checking for program ar : /usr/bin/ar
Checking for program ranlib : /usr/bin/ranlib
Checking for g++ : ok
Checking for node path : not found
Checking for node prefix : ok /usr/local
'configure' finished successfully (0.040s)
Waf: Entering directory /Users/einaros/code/ws/build' Waf: Leaving directory/Users/einaros/code/ws/build'
Traceback (most recent call last):
File "/usr/local/bin/node-waf", line 16, in
Scripting.prepare(t, os.getcwd(), VERSION, wafdir)
File "/usr/local/bin/../lib/node/wafadmin/Scripting.py", line 145, in prepare
prepare_impl(t, cwd, ver, wafdir)
File "/usr/local/bin/../lib/node/wafadmin/Scripting.py", line 135, in prepare_impl
main()
File "/usr/local/bin/../lib/node/wafadmin/Scripting.py", line 188, in main
fun(ctx)
File "/usr/local/bin/../lib/node/wafadmin/Scripting.py", line 386, in build
return build_impl(bld)
File "/usr/local/bin/../lib/node/wafadmin/Scripting.py", line 405, in build_impl
bld.compile()
File "/usr/local/bin/../lib/node/wafadmin/Build.py", line 268, in compile
os.chdir(self.bldnode.abspath())
OSError: [Errno 2] No such file or directory: '/Users/einaros/code/ws/build'
make: *** [all] Error 1
npm ERR! error installing [email protected]

npm ERR! [email protected] preinstall: make
npm ERR! sh "-c" "make" failed with 2
npm ERR!
npm ERR! Failed at the [email protected] preinstall script.
npm ERR! This is most likely a problem with the ws package,
npm ERR! not with npm itself.
npm ERR! Tell the author that this fails on your system:
npm ERR! make
npm ERR! You can get their info via:
npm ERR! npm owner ls ws
npm ERR! There is likely additional logging output above.
npm ERR!
npm ERR! System Linux 3.0.0-12-generic
npm ERR! command "node" "/usr/local/bin/npm" "install" "ws"
npm ERR! cwd /home/absynce/dev/zombietest
npm ERR! node -v v0.6.6
npm ERR! npm -v 1.1.0-2
npm ERR! code ELIFECYCLE
npm ERR! message [email protected] preinstall: make
npm ERR! message sh "-c" "make" failed with 2
npm ERR! errno {}
npm ERR!
npm ERR! Additional logging details can be found in:
npm ERR! /home/absynce/dev/zombietest/npm-debug.log
npm not ok

Accept connections other than localhost

Hello,
I am using your library, but when running to accept other connections than localhost, it seems not to work.
As far as I know, "listen(port, address, callback)" provided by Node.js for an http server tells us that if address is set to 127.0.0., we could just connect from this one. If we want all addresses, we have to remove the "address" argument.
I have seen that you call the "listen" function with 127.0.0.1 in WebSocketServer.js, so does it work for you ?
If not, maybe we could use the options to pass it.
Thanks,

Alex

Add bandwidth indication for clients

This will have to be an inspectable property, which exposes a sampling of the current throughput, on the client object. It must be based on actual socket data, rather than entire messages, so that throughput can be measured even before a full message has been delivered.

make fails on Windows when PATH doesn't include '.'

The 'make.bat' script doesn't intercept the 'preinstall' call to 'make' if the PATH doesn't include '.'

     [exec] > [email protected] preinstall C:\code\msg\sandbox\users\martin\msgwebrtcapi\node_modules\ws
     [exec] > make
     [exec] CreateProcessW: The system cannot find the file specified.
     [exec] npm ERR! [email protected] preinstall: `make`
     [exec] npm ERR! `cmd "/c" "make"` failed with 127

streaming readable streams - backpressure

Hi,

Sorry if my question is stupid, but I'll ask anyway:)

How ws library handles situations of slow users when sending readable strems trough it? Does it read as fast as it can and queue in memory? or is is optimized somehow to pause stream when user is slow?

Receiver allocates 1024 bytes of Buffers

In the Receiver module, 1024 bytes of BufferPool are allocated, no matter how big the message is. On each received (complete) message, the underlying Buffer (at least 1024 bytes) is discarded (hopefully freed by V8) and another new Buffer is allocated.

Given the client sends only small messages, this leads to many unnecessary big Buffers being allocated, and – if no message is received – even to completely unnecessary allocations (new BufferPool() does not allocate a Buffer until needed, while new BufferPool(1024, ...) allocates 1024 bytes no matter what will happen).

Running bench/speed.js shows that there is no significant advantage for big BufferPools for small messages (up to 1 MB), it's even slower when BufferPool is initialized with no arguments (then, by default the Buffer size is determined by the first message chunk and a quite conservative grow/shrink strategy is applied) ("allocate only as much as I need now")).

Maybe it would be better to use new BufferPool() by default and alloe different settings for edge cases for where big BufferPools really make sense?

Or did I miss an important use case?

Missing 'close' event when using WebSocket as a client

Based on the WebSocket spec, section Feedback from the protocol, the last part reads:

"When the WebSocket connection is closed, ...
2. ... fire a simple event named error ...
3. Create an event ... with the event named close ... and dispatch the event"

Now, when using the WebSocket object to initiate a connection to a remote WebSocket server, in multiple cases only the error event is emitted, but no close event.

I have mapped the cases and the relevant source locations. So, this happens:

  1. When the server closes the connection, the listeners are cleaned from the WebSocket too early, and the close event is not delivered, see here, line 485 (perhaps it's OK to leave the listeners there, for either the user or the GC to clean them)
  2. When the client is connecting to a server which is not listening, only the error event is emitted, see here, line 451 (this is ambiguous in the spec, because it says when the connection is closed and here the connection wasn't established, but indeed all browsers emit a close here)
  3. And the last one I haven't experienced, but by the looks it's the same case, when the server key is invalid, see here, line 462 (again, I think this should be consistent, e.g. when a user reconnection code waits for a close event, it should get it)

Race condition causes sender to send incorrect frame header.

It has been very difficult to narrow this bug down, but it is 100% reproducible. To reproduce:

  1. The server needs to be sending messages faster than the client can receive them. I need to generate at least 100 messages from server to client, but 200 is more reliable.
  2. The length of the messages needs to be very consistent but gradually increase. This is so you can observe a long sequence of identically repeating frame headers. I accomplished this by embedding a counter integer in the message, so when the counter was less than 9, the integer serialized into one byte; when it was between 10 and 99, it required two bytes, etc. For example, my first 9 messages were each 207 bytes long, then messages 10-99 were each 208 bytes long, then messages 100+ were (or would be) each 209 bytes long ( which would only be correct for a message with counter > 99 ).
  3. What you can observe, either through packet sniffing or by instrumenting the client, is that the frame headers received by the client show a frame length of 207 for 9 message, then 208 for messages 10-99, etc. At least, that's what you should see. What actually happens is that, under the right conditions, the receiver will consistently receive an frame length that corresponds to a later message along with the message body for the current body. In my example, somewhere between message 70-73 (that is, still with a two digit counter in the message body) the sender will use the message length of 209 bytes.
  4. The problem is here: https://github.com/einaros/ws/blob/06121f89f5ab52a242717f68e4d9dc36fe771f2a/lib/Sender.js#L126
    The problem goes completely away if I force this line to always create a new Buffer(totalLength).
  5. If I inspect the contents of the outputBuffer just before the call to Socket.send, (https://github.com/einaros/ws/blob/06121f89f5ab52a242717f68e4d9dc36fe771f2a/lib/Sender.js#L172 )
    I see correct values, but when the bytes actually hit the wire (as measured using wireshark) the incorrect value is sent.
  6. The eventual symptom in my case was a "invalid utf8 sequence" error, because the message length was one byte too high, so it would read the first byte (129 = finalFragment | opcode) of the next frame and try to validate it as utf8.
  7. Of course, there's a one-liner fix that works, but avoids the use of the _sendCache Buffer. How important is this cache? What are the synchronization mechanisms for avoiding this bug?

Note: I cannot reproduce this using a single machine. I have to use a remote server.
Note2: The actual trigger points are sensitive to the message lengths. With shorter messages, I can get it to fail around message 80-85, and with longer messages, I can get it to fail around message 60-65.

node version: 0.6.10
ws version: 0.4.7
arch: x86_64 linux

pong on closed connection error

I keep seeing this error:

/home/deploy/node_modules/ws/lib/WebSocket.js:153
  if (this.readyState != WebSocket.OPEN) throw new Error('not opened');
                                         ^
Error: not opened
    at WebSocket.pong (/home/deploy/node_modules/ws/lib/WebSocket.js:153:48)
    at Receiver.<anonymous> (/home/deploy/node_modules/ws/lib/WebSocket.js:539:10)
    at Receiver.emit (events.js:70:17)
    at Receiver.<anonymous> (/home/deploy/node_modules/ws/lib/Receiver.js:523:12)
    at /home/deploy/node_modules/ws/lib/Receiver.js:518:31
    at Receiver.expectData (/home/deploy/node_modules/ws/lib/Receiver.js:129:5)
    at Receiver.<anonymous> (/home/deploy/node_modules/ws/lib/Receiver.js:517:14)
    at Receiver.<anonymous> (/home/deploy/node_modules/ws/lib/Receiver.js:500:30)
    at Receiver.<anonymous> (/home/deploy/node_modules/ws/lib/Receiver.js:193:19)
    at Receiver.add (/home/deploy/node_modules/ws/lib/Receiver.js:93:24)

Support web-socket-js by implementing Flash Policy response

web-socket-js is the Flash based polyfill/shim for browsers without native support. Flash sockets implement their own form of CORS in the form of a Flash policy response (on port 843 and then on the target port). Answering inline on the same port is supported in Socket.IO and websockify, etc. It would be nice if einaros/ws supported answering Flash policy requests so that it could be used with web-socket-js.

WS Server using Safari: Status Code 400

I am trying to connect to a WebSocketServer. Using Chrome this works fine, but using Safari I am getting an error saying a status code 400 is returned. I believe this might be something to do with the protocol versions, does this library support detecting and using the appropriate protocol for browsers?

Thanks
James

Error in ws during install of codestream

This happened, and it was suggested I put it here. I don't know my way around anything node, so .. here's what happened:

lahwran@home:~$ sudo npm install -g codestream
npm http GET https://registry.npmjs.org/codestream
npm http 304 https://registry.npmjs.org/codestream
npm http GET https://registry.npmjs.org/socket.io-client/0.9.3
npm http GET https://registry.npmjs.org/debug
npm http GET https://registry.npmjs.org/pty.js/0.0.6-1
npm http 304 https://registry.npmjs.org/socket.io-client/0.9.3
npm http 304 https://registry.npmjs.org/pty.js/0.0.6-1
npm http 304 https://registry.npmjs.org/debug

> [email protected] install /usr/lib/node_modules/codestream/node_modules/pty.js
> node-gyp rebuild

info it worked if it ends with ok
spawn python [ '/home/lahwran/.node-gyp/0.6.14/tools/gyp_addon',
 'binding.gyp',
 '-I/usr/lib/node_modules/codestream/node_modules/pty.js/build/config.gypi',
 '-f',
 'make' ]
npm http GET https://registry.npmjs.org/uglify-js/1.2.5
npm http GET https://registry.npmjs.org/ws
npm http GET https://registry.npmjs.org/xmlhttprequest/1.2.2
npm http GET https://registry.npmjs.org/active-x-obfuscator/0.0.1
npm http 304 https://registry.npmjs.org/uglify-js/1.2.5
npm http 304 https://registry.npmjs.org/active-x-obfuscator/0.0.1
npm http 304 https://registry.npmjs.org/xmlhttprequest/1.2.2
spawn make [ 'BUILDTYPE=Release', '-C', 'build' ]
make: Entering directory
`/usr/lib/node_modules/codestream/node_modules/pty.js/build'
 CXX(target) Release/obj.target/pty/src/pty.o
npm http 304 https://registry.npmjs.org/ws
npm http GET https://registry.npmjs.org/zeparser/0.0.5

> [email protected] preinstall /usr/lib/node_modules/codestream/node_modules/socket.io-client/node_modules/ws
> make

node-waf configure build
make: node-waf: Command not found
make: *** [all] Error 127

npm ERR! [email protected] preinstall: `make`
npm ERR! `sh "-c" "make"` failed with 2
npm ERR!
npm ERR! Failed at the [email protected] preinstall script.
npm ERR! This is most likely a problem with the ws package,
npm ERR! not with npm itself.
npm ERR! Tell the author that this fails on your system:
npm ERR!     make
npm ERR! You can get their info via:
npm ERR!     npm owner ls ws
npm ERR! There is likely additional logging output above.
npm ERR!
npm ERR! System Linux 2.6.35-22-generic
npm ERR! command "node" "/usr/bin/npm" "install" "-g" "codestream"
npm ERR! cwd /home/lahwran
npm ERR! node -v v0.6.14
npm ERR! npm -v 1.1.15
npm ERR! code ELIFECYCLE
npm ERR! message [email protected] preinstall: `make`
npm ERR! message `sh "-c" "make"` failed with 2
npm ERR! errno {}
npm ERR!
npm ERR! Additional logging details can be found in:
npm ERR!     /home/lahwran/npm-debug.log
npm not ok
lahwran@home:~$ ../src/pty.cc: In function ‘v8::Handle<v8::Value>
PtyFork(const v8::Arguments&)’:
../src/pty.cc:183: warning: ignoring return value of ‘int chdir(const
char*)’, declared with attribute warn_unused_result
../src/pty.cc: At global scope:
../src/pty.cc:465: fatal error: opening dependency file
./Release/.deps/Release/obj.target/pty/src/pty.o.d.raw: No such file
or directory
compilation terminated.
make: *** [Release/obj.target/pty/src/pty.o] Error 1
make: Leaving directory
`/usr/lib/node_modules/codestream/node_modules/pty.js/build'
ERR! Error: `make` failed with exit code: 2
   at Array.0 (/usr/lib/node_modules/npm/node_modules/node-gyp/lib/build.js:176:25)
   at EventEmitter._tickCallback (node.js:192:40)
ERR! not ok

lahwran@home:~$

I'm on ubuntu 10.10, I installed node with the ubuntu PPA.

for Server._clients, use map (Object) instead of Array for better efficiency

https://github.com/einaros/ws/blob/459b3f6c46e9feea8ca84be12aacfeaa129707d6/lib/WebSocketServer.js#L78

https://gist.github.com/1886673#comments

Not a big deal for less than 10k clients I suppose, but would be nice to have:)

(At 100k objects, a put / delete op takes ~0.001 ms with map (Object), and ~0.1 ms with Array. At 10k objects, this difference is much smaller of course.)

The WebSocket client would need an id to be used as a key in the map, but this could be assigned from a static counter++.

Is it safe to use `wss._clients`?

var WebSocketServer = require('ws').Server;
var util = require('util');

var httpServer = require('http').createServer(function (req, res) {
    console.log("REQUEST", req);
    res.end("END");
});
httpServer.listen(3000);

var wss = new WebSocketServer({server:httpServer});

httpServer.on('upgrade', function (req, socket, head) {
    console.log('UPGRADE', req);
});


wss.on('connection', function (ws) {
    console.log('clients# ', this._clients.length);
});

// Is it safe in the means of BC to use this?
wss._clients.forEach(function (ws) {
  ws.send("foo");
});


Would be great to rename this variable to wss.clients maybe? To indicate that this varaible is safe to rely on?

Kind regards

Missing "close" method in Sender.hixie

The hixie version of the Sender seems to lack the "close" method. Maybe the other methods (like ping, etc.) should be in Sender.hixie as well?

I'm getting this on a server with only hixie connections:

payload must start with 0x00 byte
TypeError: Object # has no method 'close'

Seems like after a broken packet (e.g. connection broken by a proxy) the server wants to fire the connection's "close" method, which does not exist..

High memory usage (or memleak?)

Hi all!

I created a small example for the memory leak my ws (or WebSocket.IO) server has.

This small server only accepts WebSocket connections and sends one message.
Client count and memory usage is displayed every 2 seconds.

The client open 10,000 connections, then every minute 2,000 new connections are openend and 2,000 are closed, so the count stays at about 10,000.

https://gist.github.com/2152933

Memory Graph

The graph is the output of server.js (run on a EC2 "large" instance with node 0.6.13 and ws 0.4.9).

  • Server startup: RSS is about 13 MB (0 clients)
  • When the first 10,000 clients are connected, RSS = 420 MB
  • During the next 10 minutes clients come and go (see client.js), RSS grows to 620 MB
  • heap usage stay stable
  • Client is stopped =(> RSS falls to 220 MB waited 1 minute for GC)
  • After 1 minute, client ist started again => RSS jumps to 440 MB (10,000 clients)
  • During the next minutes, RSS grows again up to 630 MB (after 10 minutes)
  • Client is stopped => RSS falls to 495 MB
  • When I start the client again, RSS usage seems stable (at least compared to the two runs before).

Questions:

  1. 400 MB for 10.000 clients (with no data attached) is much. But I see JS as an interpreted language is not that memory optimized than C. BUT, why does opening and closing 20.000 connections (during the 10 minute period) consume another 200 MB?
  2. The process is at about 30% CPU, so the GC has the chance to kick in (and, ws uses nextTick, so the GC really has a chance)
  3. Why is he GC unable to free the memory after the second run? Can't be the Buffer/SlowBuffer problem (fragmented small Buffers in different 8k SlowBuffers), as there are no Buffers used anymore...
  4. Why does the RSS usage remain pretty stable after the first two runs?

The effect is the same (but slower) with only 1,000 client connections per minute, but things get even worse when I don't stop the client after 10 minutes. Our production server runs with about 30-40% CPU constantly (30k connections), 1-5% at night (1-2k connections), but is never completely idle. The growing of the RSS usage never seems to stop.

On the production server, RSS grows until node crashes (0.4.x crashes at 1 GB) or the process gets killed by the system (0.6 supports more than 1 GB).

I'll try two things tomorrow:

  • The same setup with Node 0.4 (as 0.4 seems much better in regards of memory consumption than 0.6), and
  • with different WebSocket libraries, e.g. "websock", which is not 100% stable but only consumes one third (still leaking though), and a variant of WebSocket.IO with the original Socket.IO (not ws!) hybi parsers, see my "nows" branch.

The setup is a default Amazon EC2 large instance, so this must be an issue for anyone who runs a WebSocket server using ws (or must likely also WebSocket.IO with ws receivers) with some traffic. I refuse to believe Node is not capable of serving this.

Or am I missing something?

Nico

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.