@@ -6,128 +6,153 @@ const WebSocket = require('ws');
66const lookup = maxmind . openSync ( geolite2 . paths . city ) ;
77
88const userMap = { } ;
9+ const websocket = {
910
10- /**
11- * Launches the websocket broadcast server
12- * @param server
13- */
14- module . exports . launch = server => {
15- const wss = new WebSocket . Server ( { server : server } ) ;
16-
17- wss . on ( 'connection' , ( ws , req ) => {
18- let user ;
19-
20- ws . on ( 'message' , async message => {
21-
22- // Answer ping request
23- if ( message === '__ping__' ) {
24- return ws . send ( '__pong__' ) ;
25- }
26-
27- // Try to parse message
28- try {
29- message = JSON . parse ( message ) ;
30- } catch ( ignored ) {
31- return ;
32- }
33-
34- const { type, value} = message ;
35- switch ( type ) {
36- case 'register' : {
37- if ( typeof value === 'string' && value ) {
38- user = await userModel . findOne ( { apikeys : { $elemMatch : { key : value } } } ) ;
39-
40- if ( ! user ) {
41- return ;
42- }
11+ /**
12+ * Launches the websocket broadcast server
13+ * @param server
14+ */
15+ launch ( server ) {
16+ const wss = new WebSocket . Server ( { server : server } ) ;
4317
44- const userid = user . id ;
45- if ( ! ( userid in userMap ) ) {
46- userMap [ userid ] = {
47- websockets : [ ] ,
48- lastBroadcast : 0
49- } ;
50- } else if ( userMap [ userid ] . websockets . includes ( ws ) ) {
51- return ;
52- }
18+ wss . on ( 'connection' , ( ws , req ) => {
19+ let user ;
5320
54- // Lookup ip info
55- const lu = lookup . get ( req . connection . remoteAddress ) ;
56-
57- ws . _sessionInfo = {
58- city : lu . city . names . en ,
59- continent : lu . continent . names . en ,
60- country : lu . country . names . en ,
61- location : lu . location ,
62- registeredCountry : lu . registered_country . names . en ,
63- registerTimestamp : Date . now ( )
64- } ;
65-
66- userMap [ userid ] . websockets . push ( ws ) ;
67-
68- // Approve registration
69- ws . send ( JSON . stringify ( {
70- type : 'registration-approval' ,
71- value : {
72- lastBroadcast : userMap [ userid ] . lastBroadcast
73- }
74- } ) ) ;
75- }
21+ ws . on ( 'message' , async message => {
7622
77- break ;
23+ // Answer ping request
24+ if ( message === '__ping__' ) {
25+ return ws . send ( '__pong__' ) ;
7826 }
79- case 'broadcast' : {
80- if ( user ) {
81- const container = userMap [ user . id ] ;
82- const { websockets} = container ;
83-
84- // Broadcast message
85- for ( let i = 0 , l = websockets . length ; i < l ; i ++ ) {
86- const socket = websockets [ i ] ;
87-
88- if ( socket !== ws ) {
89- socket . send ( JSON . stringify ( {
90- type : 'broadcast' ,
91- value
92- } ) ) ;
27+
28+ // Try to parse message
29+ try {
30+ message = JSON . parse ( message ) ;
31+ } catch ( ignored ) {
32+ return ;
33+ }
34+
35+ const { type, value} = message ;
36+ switch ( type ) {
37+ case 'register' : {
38+ if ( typeof value === 'string' && value ) {
39+ user = await userModel . findOne ( { apikeys : { $elemMatch : { key : value } } } ) ;
40+
41+ if ( ! user ) {
42+ return ;
9343 }
44+
45+ const userid = user . id ;
46+ if ( ! ( userid in userMap ) ) {
47+ userMap [ userid ] = {
48+ websockets : [ ] ,
49+ lastBroadcast : 0
50+ } ;
51+ } else if ( userMap [ userid ] . websockets . includes ( ws ) ) {
52+ return ;
53+ }
54+
55+ // Lookup ip info
56+ const lu = lookup . get ( req . connection . remoteAddress ) ;
57+
58+ ws . _sessionInfo = {
59+ id : Math . floor ( Math . random ( ) * 1e15 ) . toString ( 16 ) + Date . now ( ) . toString ( 16 ) ,
60+ city : lu . city . names . en ,
61+ continent : lu . continent . names . en ,
62+ country : lu . country . names . en ,
63+ location : lu . location ,
64+ registeredCountry : lu . registered_country . names . en ,
65+ registerTimestamp : Date . now ( )
66+ } ;
67+
68+ userMap [ userid ] . websockets . forEach ( s => s . send ( JSON . stringify ( {
69+ type : 'open-session' ,
70+ value : ws . _sessionInfo
71+ } ) ) ) ;
72+
73+ // Append websocket
74+ userMap [ userid ] . websockets . push ( ws ) ;
75+
76+ // Approve registration
77+ ws . send ( JSON . stringify ( {
78+ type : 'registration-approval' ,
79+ value : {
80+ lastBroadcast : userMap [ userid ] . lastBroadcast ,
81+ sessions : websocket . getSessionsBy ( userid )
82+ }
83+ } ) ) ;
9484 }
9585
96- // Update last broadcast timestamp
97- container . lastBroadcast = Date . now ( ) ;
86+ break ;
87+ }
88+ case 'broadcast' : {
89+ if ( user ) {
90+ const container = userMap [ user . id ] ;
91+ const { websockets} = container ;
92+
93+ // Broadcast message
94+ for ( let i = 0 , l = websockets . length ; i < l ; i ++ ) {
95+ const socket = websockets [ i ] ;
96+
97+ if ( socket !== ws ) {
98+ socket . send ( JSON . stringify ( {
99+ type : 'broadcast' ,
100+ value
101+ } ) ) ;
102+ }
103+ }
104+
105+ // Update last broadcast timestamp
106+ container . lastBroadcast = Date . now ( ) ;
107+ }
108+ break ;
98109 }
99- break ;
100110 }
101- }
102- } ) ;
111+ } ) ;
103112
104- ws . on ( 'close' , ( ) => {
113+ ws . on ( 'close' , ( ) => {
105114
106- // Check if socket was registered
107- if ( user ) {
108- const { websockets} = userMap [ user . id ] ;
109- const idx = websockets . indexOf ( ws ) ;
115+ // Check if socket was registered
116+ if ( user ) {
117+ const { websockets} = userMap [ user . id ] ;
118+ const idx = websockets . indexOf ( ws ) ;
110119
111- // Remove socket
112- if ( ~ idx ) {
113- websockets . splice ( idx , 1 ) ;
114- }
120+ // Remove socket
121+ if ( ~ idx ) {
122+ const [ socket ] = websockets . splice ( idx , 1 ) ;
123+
124+ if ( socket ) {
125+ websockets . forEach ( ws => ws . send ( JSON . stringify ( {
126+ type : 'close-session' ,
127+ value : socket . _sessionInfo
128+ } ) ) ) ;
129+ }
130+ }
115131
116- // Clean up if no connection is open anymore
117- if ( ! websockets . length ) {
118- delete userMap [ user . id ] ;
132+ // Clean up if no connection is open anymore
133+ if ( ! websockets . length ) {
134+ delete userMap [ user . id ] ;
135+ }
119136 }
120- }
137+ } ) ;
121138 } ) ;
122- } ) ;
139+ } ,
140+
141+ /**
142+ * Returns the amount of currenty connected user
143+ * @param userid
144+ * @returns {number }
145+ */
146+ getSessionsBy ( userid ) {
147+ const user = userMap [ userid ] ;
148+ return ( ( user && user . websockets ) || [ ] ) . map ( v => v . _sessionInfo ) ;
149+ }
150+
123151} ;
124152
125153/**
126154 * Returns the amount of currenty connected user
127155 * @param userid
128156 * @returns {number }
129157 */
130- module . exports . getSessionsBy = userid => {
131- const user = userMap [ userid ] ;
132- return ( ( user && user . websockets ) || [ ] ) . map ( v => v . _sessionInfo ) ;
133- } ;
158+ module . exports = websocket ;
0 commit comments