class WebSocketClient extends WebSocket { constructor(uri) { super(null); this.internalOnOpen = noop; this.internalOnError = noop; native.connect(clientGroup, uri, this); } ping(message, options, dontFailWhenClosed) { if (this.external) { native.client.send(this.external, message, WebSocketClient.OPCODE_PING); } } terminate() { if (this.external) { native.client.terminate(this.external); this.external = null; } } send(message, options, cb) { if (this.external) { if (typeof options === 'function') { cb = options; options = null; } const binary = options && options.binary || typeof message !== 'string'; native.client.send(this.external, message, binary ? WebSocketClient.OPCODE_BINARY : WebSocketClient.OPCODE_TEXT, cb ? (() => { process.nextTick(cb); }) : undefined); } else if (cb) { cb(new Error('not opened')); } } close(code, data) { if (this.external) { native.client.close(this.external, code, data); this.external = null; } } }
n/a
class Server extends EventEmitter { constructor(options, callback) { super(); if (!options) { throw new TypeError('missing options'); } if (options.port === undefined && !options.server && !options.noServer) { throw new TypeError('invalid options'); } var nativeOptions = WebSocketClient.PERMESSAGE_DEFLATE; if (options.perMessageDeflate !== undefined) { if (options.perMessageDeflate === false) { nativeOptions = 0; } } this.serverGroup = native.server.group.create(nativeOptions, options.maxPayload === undefined ? 1048576 : options.maxPayload ); // can these be made private? this._upgradeCallback = noop; this._upgradeListener = null; this._noDelay = options.noDelay === undefined ? true : options.noDelay; this._lastUpgradeListener = true; this._passedHttpServer = options.server; if (!options.noServer) { this.httpServer = options.server ? options.server : http.createServer((request, response) => { // todo: default HTTP response response.end(); }); if (options.path && (!options.path.length || options.path[0] !== '/')) { options.path = '/' + options.path; } this.httpServer.on('upgrade', this._upgradeListener = ((request, socket, head) => { if (!options.path || options.path == request.url.split('?')[0].split('#')[0]) { if (options.verifyClient) { const info = { origin: request.headers.origin, secure: request.connection.authorized !== undefined || request.connection.encrypted !== undefined, req: request }; if (options.verifyClient.length === 2) { options.verifyClient(info, (result, code, name) => { if (result) { this.handleUpgrade(request, socket, head, emitConnection); } else { abortConnection(socket, code, name); } }); } else { if (options.verifyClient(info)) { this.handleUpgrade(request, socket, head, emitConnection); } else { abortConnection(socket, 400, 'Client verification failed'); } } } else { this.handleUpgrade(request, socket, head, emitConnection); } } else { if (this._lastUpgradeListener) { abortConnection(socket, 400, 'URL not supported'); } } })); this.httpServer.on('newListener', (eventName, listener) => { if (eventName === 'upgrade') { this._lastUpgradeListener = false; } }); } native.server.group.onDisconnection(this.serverGroup, (external, code, message, webSocket) => { webSocket.external = null; process.nextTick(() => { webSocket.internalOnClose(code, message); }); native.clearUserData(external); }); native.server.group.onMessage(this.serverGroup, onServerMessage); native.server.group.onPing(this.serverGroup, (message, webSocket) => { webSocket.onping(message); }); native.server.group.onPong(this.serverGroup, (message, webSocket) => { webSocket.onpong(message); }); native.server.group.onConnection(this.serverGroup, (external) => { const webSocket = new WebSocket(external); ...
n/a
http = function () { [native code] }
n/a
http = function () { [native code] }
n/a
function createServer() { [native code] }
...
this._upgradeCallback = noop;
this._upgradeListener = null;
this._noDelay = options.noDelay === undefined ? true : options.noDelay;
this._lastUpgradeListener = true;
this._passedHttpServer = options.server;
if (!options.noServer) {
this.httpServer = options.server ? options.server : http.createServer((request, response
) => {
// todo: default HTTP response
response.end();
});
if (options.path && (!options.path.length || options.path[0] !== '/')) {
options.path = '/' + options.path;
}
...
function getExpressApp() { [native code] }
n/a
function getRequestPrototype() { [native code] }
n/a
function getResponsePrototype() { [native code] }
n/a
function listen() { [native code] }
...
native.setUserData(external, webSocket);
this._upgradeCallback(webSocket);
_upgradeReq = null;
});
if (options.port !== undefined) {
if (options.host) {
this.httpServer.listen(options.port, options.host, () => {
this.emit('listening');
callback && callback();
});
} else {
this.httpServer.listen(options.port, () => {
this.emit('listening');
callback && callback();
...
function on() { [native code] }
...
var WebSocketServer = require('uws').Server;
var wss = new WebSocketServer({ port: 3000 });
function onMessage(message) {
console.log('received: ' + message);
}
wss.on('connection', function(ws) {
ws.on('message', onMessage);
ws.send('something');
});
```
##### Deviations from ws
There are some important incompatibilities with `ws` though, we aim to be ~90% compatible but will never implement behavior that
is deemed too inefficient:
...
function clearUserData() { [native code] }
...
native.client.group.onDisconnection(clientGroup, (external, code, message, webSocket) => {
webSocket.external = null;
process.nextTick(() => {
webSocket.internalOnClose(code, message);
});
native.clearUserData(external);
});
native.client.group.onPing(clientGroup, (message, webSocket) => {
webSocket.onping(message);
});
native.client.group.onPong(clientGroup, (message, webSocket) => {
...
function connect() { [native code] }
...
}
class WebSocketClient extends WebSocket {
constructor(uri) {
super(null);
this.internalOnOpen = noop;
this.internalOnError = noop;
native.connect(clientGroup, uri, this);
}
ping(message, options, dontFailWhenClosed) {
if (this.external) {
native.client.send(this.external, message, WebSocketClient.OPCODE_PING);
}
}
...
function getAddress() { [native code] }
...
}
get readyState() {
return this.external ? WebSocketClient.OPEN : WebSocketClient.CLOSED;
}
get _socket() {
const address = this.external ? native.getAddress(this.external) : new Array(3);
return {
remotePort: address[0],
remoteAddress: address[1],
remoteFamily: address[2]
};
}
...
function getUserData() { [native code] }
...
native.setNoop(noop);
var _upgradeReq = null;
const clientGroup = native.client.group.create();
native.client.group.onConnection(clientGroup, (external) => {
const webSocket = native.getUserData(external);
webSocket.external = external;
webSocket.internalOnOpen();
});
native.client.group.onMessage(clientGroup, (message, webSocket) => {
webSocket.internalOnMessage(message);
});
...
httpServer = function () { [native code] }
n/a
function setNoop() { [native code] }
...
} else {
throw new Error('Compilation of µWebSockets has failed and there is no pre-compiled binary ' +
'available for your system. Please install a supported C++11 compiler and reinstall the module \'uws\'.
x27;);
}
}
})();
native.setNoop(noop);
var _upgradeReq = null;
const clientGroup = native.client.group.create();
native.client.group.onConnection(clientGroup, (external) => {
const webSocket = native.getUserData(external);
...
function setUserData() { [native code] }
...
native.server.group.onPong(this.serverGroup, (message, webSocket) => {
webSocket.onpong(message);
});
native.server.group.onConnection(this.serverGroup, (external) => {
const webSocket = new WebSocket(external);
native.setUserData(external, webSocket);
this._upgradeCallback(webSocket);
_upgradeReq = null;
});
if (options.port !== undefined) {
if (options.host) {
this.httpServer.listen(options.port, options.host, () => {
...
function transfer() { [native code] }
...
}
} else {
const secKey = request.headers['sec-websocket-key'];
const socketHandle = socket.ssl ? socket._parent._handle : socket._handle;
const sslState = socket.ssl ? socket.ssl._external : null;
if (socketHandle && secKey && secKey.length == 24) {
socket.setNoDelay(this._noDelay);
const ticket = native.transfer(socketHandle.fd === -1 ? socketHandle : socketHandle
.fd, sslState);
socket.on('close', (error) => {
if (this.serverGroup) {
_upgradeReq = request;
this._upgradeCallback = callback ? callback : noop;
native.upgrade(this.serverGroup, ticket, secKey, request.headers['sec-websocket-extensions'], request.
headers['sec-websocket-protocol']);
}
});
...
function upgrade() { [native code] }
...
}
handleUpgrade(request, socket, upgradeHead, callback) {
if (socket._isNative) {
if (this.serverGroup) {
_upgradeReq = request;
this._upgradeCallback = callback ? callback : noop;
native.upgrade(this.serverGroup, socket.external, secKey, request.headers
['sec-websocket-extensions'], request.headers['sec-websocket-protocol']);
}
} else {
const secKey = request.headers['sec-websocket-key'];
const socketHandle = socket.ssl ? socket._parent._handle : socket._handle;
const sslState = socket.ssl ? socket.ssl._external : null;
if (socketHandle && secKey && secKey.length == 24) {
socket.setNoDelay(this._noDelay);
...
function close() { [native code] }
...
} else if (cb) {
cb(new Error('not opened'));
}
}
close(code, data) {
if (this.external) {
native.server.close(this.external, code, data);
this.external = null;
}
}
}
class WebSocketClient extends WebSocket {
constructor(uri) {
...
function finalizeMessage() { [native code] }
n/a
function prepareMessage() { [native code] }
n/a
function send() { [native code] }
...
function onMessage(message) {
console.log('received: ' + message);
}
wss.on('connection', function(ws) {
ws.on('message', onMessage);
ws.send('something');
});
```
##### Deviations from ws
There are some important incompatibilities with `ws` though, we aim to be ~90% compatible but will never implement behavior that
is deemed too inefficient:
* Binary data is passed zero-copy as an `ArrayBuffer`. This means you need to copy it to keep it past the callback. It also means
you need to convert it with `Buffer.from(message)` if you expect a `Node.js Buffer`.
...
function sendPrepared() { [native code] }
n/a
function terminate() { [native code] }
...
if (this.external) {
native.server.send(this.external, message, WebSocketClient.OPCODE_PING);
}
}
terminate() {
if (this.external) {
native.server.terminate(this.external);
this.external = null;
}
}
send(message, options, cb) {
if (this.external) {
if (typeof options === 'function') {
...
function close() { [native code] }
...
} else if (cb) {
cb(new Error('not opened'));
}
}
close(code, data) {
if (this.external) {
native.server.close(this.external, code, data);
this.external = null;
}
}
}
class WebSocketClient extends WebSocket {
constructor(uri) {
...
function finalizeMessage() { [native code] }
n/a
function prepareMessage() { [native code] }
n/a
function send() { [native code] }
...
function onMessage(message) {
console.log('received: ' + message);
}
wss.on('connection', function(ws) {
ws.on('message', onMessage);
ws.send('something');
});
```
##### Deviations from ws
There are some important incompatibilities with `ws` though, we aim to be ~90% compatible but will never implement behavior that
is deemed too inefficient:
* Binary data is passed zero-copy as an `ArrayBuffer`. This means you need to copy it to keep it past the callback. It also means
you need to convert it with `Buffer.from(message)` if you expect a `Node.js Buffer`.
...
function sendPrepared() { [native code] }
n/a
function terminate() { [native code] }
...
if (this.external) {
native.server.send(this.external, message, WebSocketClient.OPCODE_PING);
}
}
terminate() {
if (this.external) {
native.server.terminate(this.external);
this.external = null;
}
}
send(message, options, cb) {
if (this.external) {
if (typeof options === 'function') {
...