-
Notifications
You must be signed in to change notification settings - Fork 121
/
Copy pathnetwork-bridge.js
145 lines (123 loc) · 4.32 KB
/
network-bridge.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
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
import { reject } from './helpers/array-helpers';
function trimQueryPartFromURL(url) {
const queryIndex = url.indexOf('?');
return queryIndex >= 0 ? url.slice(0, queryIndex) : url;
}
/*
* The network bridge is a way for the mock websocket object to 'communicate' with
* all available servers. This is a singleton object so it is important that you
* clean up urlMap whenever you are finished.
*/
class NetworkBridge {
constructor() {
this.urlMap = {};
}
/*
* Attaches a websocket object to the urlMap hash so that it can find the server
* it is connected to and the server in turn can find it.
*
* @param {object} websocket - websocket object to add to the urlMap hash
* @param {string} url
*/
attachWebSocket(websocket, url) {
const serverURL = trimQueryPartFromURL(url);
const connectionLookup = this.urlMap[serverURL];
if (connectionLookup && connectionLookup.server && connectionLookup.websockets.indexOf(websocket) === -1) {
connectionLookup.websockets.push(websocket);
return connectionLookup.server;
}
}
/*
* Attaches a websocket to a room
*/
addMembershipToRoom(websocket, room) {
const connectionLookup = this.urlMap[trimQueryPartFromURL(websocket.url)];
if (connectionLookup && connectionLookup.server && connectionLookup.websockets.indexOf(websocket) !== -1) {
if (!connectionLookup.roomMemberships[room]) {
connectionLookup.roomMemberships[room] = [];
}
connectionLookup.roomMemberships[room].push(websocket);
}
}
/*
* Attaches a server object to the urlMap hash so that it can find a websockets
* which are connected to it and so that websockets can in turn can find it.
*
* @param {object} server - server object to add to the urlMap hash
* @param {string} url
*/
attachServer(server, url) {
const serverUrl = trimQueryPartFromURL(url);
const connectionLookup = this.urlMap[serverUrl];
if (!connectionLookup) {
this.urlMap[serverUrl] = {
server,
websockets: [],
roomMemberships: {}
};
return server;
}
}
/*
* Finds the server which is 'running' on the given url.
*
* @param {string} url - the url to use to find which server is running on it
*/
serverLookup(url) {
const serverURL = trimQueryPartFromURL(url);
const connectionLookup = this.urlMap[serverURL];
if (connectionLookup) {
return connectionLookup.server;
}
}
/*
* Finds all websockets which is 'listening' on the given url.
*
* @param {string} url - the url to use to find all websockets which are associated with it
* @param {string} room - if a room is provided, will only return sockets in this room
* @param {class} broadcaster - socket that is broadcasting and is to be excluded from the lookup
*/
websocketsLookup(url, room, broadcaster) {
const serverURL = trimQueryPartFromURL(url);
let websockets;
const connectionLookup = this.urlMap[serverURL];
websockets = connectionLookup ? connectionLookup.websockets : [];
if (room) {
const members = connectionLookup.roomMemberships[room];
websockets = members || [];
}
return broadcaster ? websockets.filter(websocket => websocket !== broadcaster) : websockets;
}
/*
* Removes the entry associated with the url.
*
* @param {string} url
*/
removeServer(url) {
delete this.urlMap[trimQueryPartFromURL(url)];
}
/*
* Removes the individual websocket from the map of associated websockets.
*
* @param {object} websocket - websocket object to remove from the url map
* @param {string} url
*/
removeWebSocket(websocket, url) {
const serverURL = trimQueryPartFromURL(url);
const connectionLookup = this.urlMap[serverURL];
if (connectionLookup) {
connectionLookup.websockets = reject(connectionLookup.websockets, socket => socket === websocket);
}
}
/*
* Removes a websocket from a room
*/
removeMembershipFromRoom(websocket, room) {
const connectionLookup = this.urlMap[trimQueryPartFromURL(websocket.url)];
const memberships = connectionLookup.roomMemberships[room];
if (connectionLookup && memberships !== null) {
connectionLookup.roomMemberships[room] = reject(memberships, socket => socket === websocket);
}
}
}
export default new NetworkBridge(); // Note: this is a singleton