wormhole/lib/ConnectingSocket.js

78 lines
2.5 KiB
JavaScript
Raw Normal View History

const constants = require('./constants');
const handshake = require('./handshake');
class ConnectingSocket {
constructor({ socket, res, websocketKey, upgradeHeader, websocketVersion }) {
this.websocketKey = websocketKey;
this.upgradeHeader = upgradeHeader;
this.websocketVersion = websocketVersion;
this.socket = socket;
this.res = res;
this.connectionSuccess = undefined;
}
}
ConnectingSocket.prototype._handshakeEndWithStatus = function(status=400) {
this.res.writeHead(status);
this.res.end();
};
ConnectingSocket.prototype._handshakeAccept = function(websocketAccept) {
this.res.writeHead(101, {
'Upgrade': 'websocket',
'Connection': 'Upgrade',
'Sec-WebSocket-Accept': websocketAccept
});
this.res.end();
};
ConnectingSocket.prototype._failConnection = function(status=400) {
this.socket._setConnectionState(constants.states.CLOSING);
this._handshakeEndWithStatus(status);
this.socket._setConnectionState(constants.states.CLOSED);
this.connectionSuccess = false;
return true;
};
ConnectingSocket.prototype.acceptConnection = function() {
try {
this.socket._setAccepted(true);
} catch(e) {
throw new Error('Tried to set socket fate (wether it is accept or not) more than once. Check if there are multiple listeners for the "connect" event or if you are somehow calling accept or reject multiple times.');
}
const websocketAccept = handshake.generateWebsocketAcceptValue(this.websocketKey);
if (!websocketAccept) return this._failConnection(400);
this._handshakeAccept(websocketAccept);
this.socket._setConnectionState(constants.states.OPEN);
this.connectionSuccess = true;
return true;
};
ConnectingSocket.prototype.rejectConnection = function(status=403) {
try {
this.socket._setAccepted(false);
} catch(e) {
throw new Error('Tried to set socket fate (wether it is accept or not) more than once. Check if there are multiple listeners for the "connect" event or if you are somehow calling accept or reject multiple times.');
}
this._failConnection(status);
return true;
};
ConnectingSocket.prototype.connectionFunctions = function() {
const headersValid = handshake.validateHeaders({ upgradeHeader: this.upgradeHeader, websocketVersion: this.websocketVersion });
if (!headersValid) return;
return {
accept: this.acceptConnection.bind(this),
reject: this.rejectConnection.bind(this)
}
};
module.exports = ConnectingSocket;