-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathfake-net.js
88 lines (77 loc) · 2.67 KB
/
fake-net.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
"use strict";
/**
* Simulates a network by using events to enable simpler testing.
*/
module.exports = class FakeNet {
/**
* Specifies a chance of a message failing to be sent and
* the maximum delay of a message (in milliseconds) if it
* is sent.
*
* This version is designed to simulate more realistic network
* conditions for testing.
*
* The messageDelay parameter is the maximum -- a message may
* be delayed any amount of time between 0 ms and the delay specified.
*
* @param {number} [chanceMessageFails] - Should be in the range of 0 to 1.
* @param {number} [messageDelay] - Time that a message may be delayed.
*/
constructor(chanceMessageFails=0, messageDelay=0) {
this.clients = new Map();
this.chanceMessageFails = chanceMessageFails;
this.messageDelayMax = messageDelay;
}
/**
* Registers clients to the network.
* Clients and Miners are registered by public key.
*
* @param {...Object} clientList - clients to be registered to this network (may be Client or Miner)
*/
register(...clientList) {
for (const client of clientList) {
this.clients.set(client.address, client);
}
}
/**
* Broadcasts to all clients within this.clients the message msg and payload o.
*
* @param {String} msg - the name of the event being broadcasted (e.g. "PROOF_FOUND")
* @param {Object} o - payload of the message
*/
broadcast(msg, o) {
for (const address of this.clients.keys()) {
this.sendMessage(address, msg, o);
}
}
/**
* Sends message msg and payload o directly to Client name.
*
* The message may be lost or delayed, with the probability
* defined for this instance.
*
* @param {String} address - the public key address of the client or miner to which to send the message
* @param {String} msg - the name of the event being broadcasted (e.g. "PROOF_FOUND")
* @param {Object} o - payload of the message
*/
sendMessage(address, msg, o) {
if (typeof o !== 'object') throw new Error(`Expecting an object, but got a ${typeof o}`);
// Serializing/deserializing the object to prevent cheating in single threaded mode.
let o2 = JSON.parse(JSON.stringify(o));
const client = this.clients.get(address);
let delay = Math.floor(Math.random() * this.messageDelayMax);
if (Math.random() > this.chanceMessageFails) {
setTimeout(() => client.emit(msg, o2), delay);
}
}
/**
* Tests whether a client is registered with the network.
*
* @param {Client} client - the client to test for.
*
* @returns {boolean} True if the client is already registered.
*/
recognizes(client) {
return this.clients.has(client.address);
}
};