Skip to content

Commit e2ebb06

Browse files
authored
Ping feature (#2)
Added ping option
1 parent 357734b commit e2ebb06

File tree

8 files changed

+646
-736
lines changed

8 files changed

+646
-736
lines changed

demo-client.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,4 +49,9 @@ window.addEventListener('load', () => {
4949
client.addEventListener('open', () => {
5050
console.info('Connection open.');
5151
});
52+
53+
// Listen for connection close
54+
client.addEventListener('close', () => {
55+
console.info('Connection closed.');
56+
});
5257
});

package-lock.json

Lines changed: 552 additions & 710 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "netcode",
3-
"version": "1.0.2",
3+
"version": "1.0.3",
44
"description": "NetCode for web video games",
55
"scripts": {
66
"test": "echo \"Error: no test specified\" && exit 1"
@@ -20,16 +20,16 @@
2020
],
2121
"author": "Thomas Jarrand <[email protected]> (https://thomas.jarrand.fr)",
2222
"license": "MIT",
23+
"dependencies": {
24+
"tom32i-event-emitter.js": "^2.0.1",
25+
"websocket-driver": "^0.7.0"
26+
},
2327
"devDependencies": {
2428
"babel-core": "^6.26.3",
2529
"babel-loader": "^7.1.5",
2630
"babel-preset-env": "^1.7.0",
27-
"eslint": "^5.3.0",
28-
"webpack": "^4.16.4",
29-
"webpack-cli": "^3.1.0"
30-
},
31-
"dependencies": {
32-
"tom32i-event-emitter.js": "^2.0.1",
33-
"websocket-driver": "^0.7.0"
31+
"eslint": "^5.8.0",
32+
"webpack": "^4.25.1",
33+
"webpack-cli": "^3.1.2"
3434
}
3535
}

src/client/Client.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ export default class Client extends EventEmitter {
3939
*/
4040
close() {
4141
this.socket.close();
42-
this.onClose();
42+
//this.onClose();
4343
}
4444

4545
/**

src/encoder/BinaryEncoder.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,10 @@ export default class BinaryEncoder {
5555
* @return {Object}
5656
*/
5757
decode(buffer) {
58+
if (!buffer.byteLength) {
59+
throw new Error('Empty buffer');
60+
}
61+
5862
const id = this.idCodec.decode(buffer, 0);
5963
const handler = this.handlersById[id];
6064

src/encoder/codec/index.js

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import Codec from 'netcode/src/encoder/codec/Codec';
2+
import BooleanCodec from 'netcode/src/encoder/codec/BooleanCodec';
3+
import Int8Codec from 'netcode/src/encoder/codec/Int8Codec';
4+
import Int16Codec from 'netcode/src/encoder/codec/Int16Codec';
5+
import Int32Codec from 'netcode/src/encoder/codec/Int32Codec';
6+
import LongIntCodec from 'netcode/src/encoder/codec/LongIntCodec';
7+
import StringCodec from 'netcode/src/encoder/codec/StringCodec';
8+
9+
module.exports = {
10+
Codec,
11+
BooleanCodec,
12+
Int8Codec,
13+
Int16Codec,
14+
Int32Codec,
15+
LongIntCodec,
16+
StringCodec,
17+
};

src/server/Client.js

Lines changed: 45 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,23 +7,30 @@ export default class Client extends EventEmitter {
77
* @param {WebSocket} socket
88
* @param {String} ip
99
* @param {Encoder} encoder
10+
* @param {Number} pingFrequency Ping frequency in milliseconds
1011
*/
11-
constructor(socket, ip, encoder) {
12+
constructor(socket, ip, encoder, pingFrequency = 0) {
1213
super();
1314

14-
this.socket = socket;
15+
this.id = ++INDEX;
1516
this.ip = ip;
17+
this.socket = socket;
1618
this.encoder = encoder;
17-
this.id = ++INDEX;
19+
this.pingInterval = null;
1820

1921
this.onMessage = this.onMessage.bind(this);
2022
this.onError = this.onError.bind(this);
2123
this.onClose = this.onClose.bind(this);
24+
this.ping = this.ping.bind(this);
2225

2326
this.socket.on('message', this.onMessage);
2427
this.socket.on('error', this.onError);
2528
this.socket.on('close', this.onClose);
2629

30+
if (pingFrequency > 0) {
31+
this.socket.on('open', () => this.startPing(pingFrequency));
32+
}
33+
2734
this.socket.send = this.encoder.constructor.binaryType === 'arraybuffer' ? this.socket.binary : this.socket.text;
2835

2936
this.socket.start();
@@ -48,15 +55,46 @@ export default class Client extends EventEmitter {
4855
}
4956
}
5057

58+
/**
59+
* Start ping at given interval
60+
*
61+
* @param {Number} frequency Ping frequency in milliseconds
62+
*/
63+
startPing(frequency) {
64+
if (frequency) {
65+
this.pingInterval = setInterval(this.ping, frequency);
66+
}
67+
}
68+
69+
ping() {
70+
if (this.socket) {
71+
this.socket.ping();
72+
}
73+
}
74+
75+
/**
76+
* Stop ping interval
77+
*/
78+
stopPing() {
79+
if (this.pingInterval) {
80+
clearInterval(this.pingInterval);
81+
this.pingInterval = null;
82+
}
83+
}
84+
5185
/**
5286
* On message
5387
*
5488
* @param {Event} event
5589
*/
5690
onMessage(event) {
57-
const { name, data } = this.encoder.decode(event.data);
91+
try {
92+
const { name, data } = this.encoder.decode(event.data);
5893

59-
this.emit(name, data, this);
94+
this.emit(name, data, this);
95+
} catch (error) {
96+
console.error('[ERROR] Could not parse message:', error, '\n\r\tEvent: ', event);
97+
}
6098
}
6199

62100
/**
@@ -66,12 +104,14 @@ export default class Client extends EventEmitter {
66104
*/
67105
onError(event) {
68106
console.error(`Client ${this.id}: `, event.message);
107+
this.close();
69108
}
70109

71110
/**
72111
* On close
73112
*/
74113
onClose() {
114+
this.stopPing();
75115
this.socket = null;
76116
this.emit('close', this);
77117
}

src/server/Server.js

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,14 @@ import Client from 'netcode/src/server/Client';
66

77
export default class Server extends EventEmitter {
88
/**
9-
* Constructor
10-
*
11-
* @param {Number} port
12-
* @param {String} host
9+
* @param {Number} port Port
10+
* @param {String} host Host
11+
* @param {JsonEncoder|BinaryEncoder} encoder
12+
* @param {Number} ping Ping frequency in seconds (0 for no ping)
13+
* @param {Number} maxLength Paquet max length in bit
14+
* @param {Array} protocols Supported protocols
1315
*/
14-
constructor(port = 8080, host = 'localhost', encoder = new JsonEncoder()) {
16+
constructor(port = 8080, host = 'localhost', encoder = new JsonEncoder(), ping = 0, maxLength = Math.pow(2, 9) - 1, protocols = ['websocket']) {
1517
super();
1618

1719
this.onUpgrade = this.onUpgrade.bind(this);
@@ -22,6 +24,11 @@ export default class Server extends EventEmitter {
2224
this.encoder = encoder;
2325
this.server = http.createServer();
2426
this.clients = new Map();
27+
this.ping = ping;
28+
this.options = {
29+
maxLength,
30+
protocols,
31+
};
2532

2633
this.server.on('error', this.onError);
2734
this.server.on('upgrade', this.onUpgrade);
@@ -69,24 +76,19 @@ export default class Server extends EventEmitter {
6976
* @param {Request} request
7077
* @param {Socket} socket
7178
* @param {Object} body
72-
*
73-
* @return {Boolean}
7479
*/
7580
onUpgrade(request, socket, body) {
7681
if (!WebSocket.isWebSocket(request)) {
7782
return socket.end();
7883
}
7984

8085
const ip = request.headers['x-real-ip'] || request.connection.remoteAddress;
81-
const options = { maxLength: Math.pow(2, 9) - 1, protocols: ['websocket'] };
82-
const driver = WebSocket.http(request, options);
86+
const driver = WebSocket.http(request, this.options);
8387

8488
driver.io.write(body);
8589
socket.pipe(driver.io).pipe(socket);
8690

87-
this.addClient(new Client(driver, ip, this.encoder));
88-
89-
return true;
91+
this.addClient(new Client(driver, ip, this.encoder, this.ping * 1000));
9092
}
9193

9294
/**

0 commit comments

Comments
 (0)