wormhole/lib/ConnectingSocket.js
2021-03-25 20:24:43 +02:00

80 lines
No EOL
2.6 KiB
JavaScript

const constants = require('./constants');
const handshake = require('./handshake');
class ConnectingSocket {
constructor({ socket, res, req, websocketKey, upgradeHeader, websocketVersion }) {
this.websocketKey = websocketKey;
this.upgradeHeader = upgradeHeader;
this.websocketVersion = websocketVersion;
this.socket = socket;
this.res = res;
this.req = req;
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 accepted 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 this.socket;
};
ConnectingSocket.prototype.rejectConnection = function(status=403) {
try {
this.socket._setAccepted(false);
} catch(e) {
throw new Error('Tried to set socket fate (wether it is accepted 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;