Skip to content
Snippets Groups Projects
Commit 569e6edf authored by Nicolas Pope's avatar Nicolas Pope
Browse files

More tests and connection setup for js net library

parent d289cd06
No related branches found
No related tags found
No related merge requests found
Pipeline #9638 passed
......@@ -15,6 +15,7 @@
"ws": "^6.2.1"
},
"devDependencies": {
"chai": "^4.2.0",
"mocha": "^6.0.2"
}
}
......@@ -13,7 +13,10 @@ function Socket(uri) {
'close': []
};
this.handshake_ = false;
this.lasterr_ = null;
this.connected_ = false;
this.valid_ = false;
this.buffer_ = new Buffer(0);
if (t == "string") {
......@@ -23,24 +26,49 @@ function Socket(uri) {
}
}
Socket.ERROR_BADPROTOCOL = 0x01;
Socket.ERROR_BADHOST = 0x02;
Socket.ERROR_BADHANDSHAKE = 0x03;
Socket.ERROR_MALFORMEDURI = 0x04;
Socket.prototype.isValid = function() {
return this.valid_;
}
/**
* Construct the correct kind of socket connection from a URI.
*/
Socket.prototype._fromURI = function(uri) {
let uriobj = urijs.parse(uri);
this.uri_ = uri;
this.scheme_ = uriobj.scheme;
// Could not parse uri so report error
if (uriobj.scheme === undefined || uriobj.host === undefined) {
this.lasterr_ = Socket.ERROR_MALFORMEDURI;
this.dispatch('error', [this.lasterr_]);
return;
}
// Websocket protocol
if (this.scheme_ == "ws") {
// Detect if in browser or not, choose correct websocket object
if (typeof WebSocket == "undefined") {
// Nodejs
this.socket_ = new ws(uri);
} else {
// Browser
this.socket_ = new WebSocket(uri);
}
this._initWebsocket();
// TCP
} else if (this.scheme_ == "tcp") {
this.socket_ = net.connect(uriobj.port, uriobj.host);
this._initTCPSocket();
// Unrecognised protocol
} else {
console.error("Invalid URI scheme for socket: ", this.scheme_);
this.lasterr_ = Socket.ERROR_BADPROTOCOL;
this.dispatch('error', [this.lasterr_]);
}
}
......@@ -60,7 +88,12 @@ Socket.prototype._fromObject = function(sock) {
else if (this.scheme_ == "tcp") this._initTCPSocket();
}
/**
* Setup correct handlers for a websocket connection.
*/
Socket.prototype._initWebsocket = function() {
this.valid_ = true;
let dataHandler = (data) => {
let size = binary.readUInt32LE(data, 0);
let service = binary.readUInt32LE(data, 4);
......@@ -80,9 +113,27 @@ Socket.prototype._initWebsocket = function() {
} else {
this.socket_.on('message', dataHandler);
}
this.socket_.on('open', () => {
this.connected_ = true;
this.dispatch('open', []);
});
this.socket_.on('error', (err) => {
this.connected_ = false;
this.valid_ = false;
switch (err.errno) {
case 'ENOTFOUND' : this.lasterr_ = Socket.ERROR_BADHOST; break;
default : this.lasterr_ = err.errno;
}
this.dispatch('error', [this.lasterr_]);
});
this.socket_.on('close', () => {
this.dispatch('close', []);
});
}
Socket.prototype._initTCPSocket = function() {
this.valid_ = true;
let dataHandler = (data) => {
console.log('Received: ' + data);
this.buffer_ = Buffer.concat([this.buffer_, data]);
......@@ -111,12 +162,28 @@ Socket.prototype._initTCPSocket = function() {
this.connected_ = true;
this.dispatch('open', []);
});
this.socket_.on('error', (err) => {
this.connected_ = false;
this.valid_ = false;
console.log("Sock error: ", err);
switch (err.errno) {
case 'ENOTFOUND' : this.lasterr_ = Socket.ERROR_BADHOST; break;
default : this.lasterr_ = err.errno;
}
this.dispatch('error', [this.lasterr_]);
});
this.socket_.on('close', () => {
this.dispatch('close', []);
});
}
Socket.prototype.isConnected = function() {
return this.connected_;
}
/**
* Register event handlers.
*/
Socket.prototype.on = function(name, f) {
if (typeof name == "string") {
if (this.handlers_.hasOwnProperty(name)) {
......@@ -124,6 +191,10 @@ Socket.prototype.on = function(name, f) {
} else {
console.error("Unrecognised handler: ", name);
}
if (name == "error" && this.lasterr_ != null) {
f(this.lasterr_);
}
} else if (typeof name == "number") {
if (this.handlers_[name] === undefined) this.handlers_[name] = [];
this.handlers_[name].push(f);
......@@ -145,7 +216,11 @@ Socket.prototype.dispatch = function(h, args) {
}
Socket.prototype.close = function() {
if (this.scheme_ == "ws") {
this.socket_.close();
} else {
this.socket_.destroy();
}
this.socket_ = null;
}
......
const Socket = require('../src/socket.js');
const assert = require('assert');
const assert = require('chai').assert;
const net = require('net');
const binary = require('bops');
const WebSocket = require('ws');
describe("Constructing a socket", function() {
describe("Socket()", function() {
let server;
let wss;
let dobadhandshake = false;
beforeEach(() => {
dobadhandshake = false;
server = net.createServer(socket => {
console.log("Client connected");
socket.on('error', ()=> {});
if (dobadhandshake) {
socket.write(Buffer.from([44,55,33,22,23,44,87]));
} else {
socket.write(Buffer.from([0x12,0x09,0x64,0x53,0x00,0x34,0x99,0x10,3,0,0,0,3,0,0,0,67,67,67,67,67,67]));
}
});
server.listen(9000, 'localhost');
wss = new WebSocket.Server({ port: 9001 });
wss.on('connection', (ws) => {
ws.on('error', ()=> {});
if (dobadhandshake) {
ws.send(Buffer.from([44,55,33,22,23,44,87]));
} else {
ws.send(Buffer.from([0x12,0x09,0x64,0x53,0x00,0x34,0x99,0x10,3,0,0,0,3,0,0,0,67,67,67,67,67,67]));
}
});
});
it("Connects to a valid tcp uri", function(done) {
context("with a valid connection uri and handshake", () => {
it("make a tcp connection", function(done) {
let sock = new Socket("tcp://localhost:9000");
sock.on('open', () => {
console.log("OPEN");
assert.equal(sock.isConnected(),true);
assert.isOk(sock.isConnected());
sock.close();
done();
});
});
it("make a websocket connection", function(done) {
let sock = new Socket("ws://localhost:9001");
sock.on('open', () => {
assert.isOk(sock.isConnected());
sock.close();
done();
});
});
});
context("with a valid uri but bad handshake", () => {
it("should reject the connection", () => {
let diderror = false;
dobadhandshake = true;
let sock = new Socket("tcp://localhost:9000");
sock.on('error', (errno) => {
diderror = true;
assert.equal(errno, Socket.ERROR_BADHANDSHAKE);
assert.isOk(sock.isValid());
assert.isNotOk(sock.isConnected());
});
assert.isOk(diderror);
});
});
context("with an invalid connection uri", () => {
it("should give protocol error", () => {
let diderror = false;
let sock = new Socket("xyz://localhost:9000");
sock.on('error', (errno) => {
diderror = true;
assert.equal(errno, Socket.ERROR_BADPROTOCOL);
assert.isNotOk(sock.isValid());
});
assert.isOk(diderror);
});
it("should give host error", (done) => {
let sock = new Socket("tcp://blah.blah:9000");
sock.on('error', (errno) => {
assert.equal(errno, Socket.ERROR_BADHOST);
assert.isNotOk(sock.isValid());
done();
});
});
it("should give a malformed uri error", () => {
let diderror = false;
let sock = new Socket("helloworld");
sock.on('error', (errno) => {
diderror = true;
assert.equal(errno, Socket.ERROR_MALFORMEDURI);
assert.isNotOk(sock.isValid());
});
assert.isOk(diderror);
});
});
afterEach(() => {
server.close(() => { console.log("Closed"); });
server.unref();
wss.close();
});
});
......@@ -34,7 +113,6 @@ describe("Receiving messages on a tcp socket", function() {
beforeEach(() => {
server = net.createServer(socket => {
console.log("Client connected");
socket.write(Buffer.from([8,0,0,0,44,0,0,0,23,0,0,0]));
});
server.listen(9001, 'localhost');
......@@ -57,3 +135,4 @@ describe("Receiving messages on a tcp socket", function() {
});
});
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment