18
18
*/
19
19
const { AdvancedBase } = require ( "@heyputer/puter-js-common" ) ;
20
20
const BaseService = require ( "../../services/BaseService" ) ;
21
-
22
- class KeyPairHelper extends AdvancedBase {
23
- static MODULES = {
24
- tweetnacl : require ( 'tweetnacl' ) ,
25
- } ;
26
-
27
- constructor ( {
28
- kpublic,
29
- ksecret,
30
- } ) {
31
- super ( ) ;
32
- this . kpublic = kpublic ;
33
- this . ksecret = ksecret ;
34
- this . nonce_ = 0 ;
35
- }
36
-
37
- to_nacl_key_ ( key ) {
38
- console . log ( 'WUT' , key ) ;
39
- const full_buffer = Buffer . from ( key , 'base64' ) ;
40
-
41
- // Remove version byte (assumed to be 0x31 and ignored for now)
42
- const buffer = full_buffer . slice ( 1 ) ;
43
-
44
- return new Uint8Array ( buffer ) ;
45
- }
46
-
47
- get naclSecret ( ) {
48
- return this . naclSecret_ ?? (
49
- this . naclSecret_ = this . to_nacl_key_ ( this . ksecret ) ) ;
50
- }
51
- get naclPublic ( ) {
52
- return this . naclPublic_ ?? (
53
- this . naclPublic_ = this . to_nacl_key_ ( this . kpublic ) ) ;
54
- }
55
-
56
- write ( text ) {
57
- const require = this . require ;
58
- const nacl = require ( 'tweetnacl' ) ;
59
-
60
- const nonce = nacl . randomBytes ( nacl . box . nonceLength ) ;
61
- const message = { } ;
62
-
63
- const textUint8 = new Uint8Array ( Buffer . from ( text , 'utf-8' ) ) ;
64
- const encryptedText = nacl . box (
65
- textUint8 , nonce ,
66
- this . naclPublic , this . naclSecret
67
- ) ;
68
- message . text = Buffer . from ( encryptedText ) ;
69
- message . nonce = Buffer . from ( nonce ) ;
70
-
71
- return message ;
72
- }
73
-
74
- read ( message ) {
75
- const require = this . require ;
76
- const nacl = require ( 'tweetnacl' ) ;
77
-
78
- const arr = nacl . box . open (
79
- new Uint8Array ( message . text ) ,
80
- new Uint8Array ( message . nonce ) ,
81
- this . naclPublic ,
82
- this . naclSecret ,
83
- ) ;
84
-
85
- return Buffer . from ( arr ) . toString ( 'utf-8' ) ;
86
- }
87
- }
88
-
89
- class Peer extends AdvancedBase {
90
- static AUTHENTICATING = Symbol ( 'AUTHENTICATING' ) ;
91
- static ONLINE = Symbol ( 'ONLINE' ) ;
92
- static OFFLINE = Symbol ( 'OFFLINE' ) ;
93
-
94
- static MODULES = {
95
- sioclient : require ( 'socket.io-client' ) ,
96
- crypto : require ( 'crypto' ) ,
97
- } ;
98
-
99
- constructor ( svc_broadcast , config ) {
100
- super ( ) ;
101
- this . svc_broadcast = svc_broadcast ;
102
- this . log = this . svc_broadcast . log ;
103
- this . config = config ;
104
- }
105
-
106
- send ( data ) {
107
- if ( ! this . socket ) return ;
108
- const require = this . require ;
109
- const crypto = require ( 'crypto' ) ;
110
- const iv = crypto . randomBytes ( 16 ) ;
111
- const cipher = crypto . createCipheriv (
112
- 'aes-256-cbc' ,
113
- this . aesKey ,
114
- iv ,
115
- ) ;
116
- const jsonified = JSON . stringify ( data ) ;
117
- let buffers = [ ] ;
118
- buffers . push ( cipher . update ( Buffer . from ( jsonified , 'utf-8' ) ) ) ;
119
- buffers . push ( cipher . final ( ) ) ;
120
- const buffer = Buffer . concat ( buffers ) ;
121
- this . socket . send ( {
122
- iv,
123
- message : buffer ,
124
- } ) ;
125
- }
126
-
127
- get state ( ) {
128
- try {
129
- if ( this . socket ?. connected ) return this . constructor . ONLINE ;
130
- } catch ( e ) {
131
- console . error ( 'could not get peer state' , e ) ;
132
- }
133
- return this . constructor . OFFLINE ;
134
- }
135
-
136
- connect ( ) {
137
- const address = this . config . address ;
138
- const socket = this . modules . sioclient ( address , {
139
- transports : [ 'websocket' ] ,
140
- path : '/wssinternal' ,
141
- reconnection : true ,
142
- extraHeaders : {
143
- ...( this . config . host ? {
144
- Host : this . config . host ,
145
- } : { } )
146
- }
147
- } ) ;
148
- socket . on ( 'connect' , ( ) => {
149
- this . log . info ( `connected` , {
150
- address : this . config . address
151
- } ) ;
152
-
153
- const require = this . require ;
154
- const crypto = require ( 'crypto' ) ;
155
- this . aesKey = crypto . randomBytes ( 32 ) ;
156
-
157
- const kp_helper = new KeyPairHelper ( {
158
- kpublic : this . config . key ,
159
- ksecret : this . svc_broadcast . config . keys . secret ,
160
- } ) ;
161
- socket . send ( {
162
- $ : 'take-my-key' ,
163
- key : this . svc_broadcast . config . keys . public ,
164
- message : kp_helper . write (
165
- this . aesKey . toString ( 'base64' )
166
- ) ,
167
- } ) ;
168
- } ) ;
169
- socket . on ( 'disconnect' , ( ) => {
170
- this . log . info ( `disconnected` , {
171
- address : this . config . address
172
- } ) ;
173
- } ) ;
174
- socket . on ( 'connect_error' , e => {
175
- this . log . info ( `connection error` , {
176
- address : this . config . address ,
177
- message : e . message ,
178
- } ) ;
179
- } ) ;
180
- socket . on ( 'error' , e => {
181
- this . log . info ( 'error' , {
182
- message : e . message ,
183
- } ) ;
184
- } ) ;
185
-
186
- this . socket = socket ;
187
- }
188
- }
189
-
190
- class Connection extends AdvancedBase {
191
- static MODULES = {
192
- crypto : require ( 'crypto' ) ,
193
- }
194
-
195
- static AUTHENTICATING = {
196
- on_message ( data ) {
197
- if ( data . $ !== 'take-my-key' ) {
198
- this . disconnect ( ) ;
199
- return ;
200
- }
201
-
202
- const hasKey = this . svc_broadcast . trustedPublicKeys_ [ data . key ] ;
203
- if ( ! hasKey ) {
204
- this . disconnect ( ) ;
205
- return ;
206
- }
207
-
208
- const is_trusted =
209
- this . svc_broadcast . trustedPublicKeys_
210
- . hasOwnProperty ( data . key )
211
- if ( ! is_trusted ) {
212
- this . disconnect ( ) ;
213
- return ;
214
- }
215
-
216
- const kp_helper = new KeyPairHelper ( {
217
- kpublic : data . key ,
218
- ksecret : this . svc_broadcast . config . keys . secret ,
219
- } ) ;
220
-
221
- const message = kp_helper . read ( data . message ) ;
222
- this . aesKey = Buffer . from ( message , 'base64' ) ;
223
-
224
- this . state = this . constructor . ONLINE ;
225
- }
226
- }
227
- static ONLINE = {
228
- on_message ( data ) {
229
- if ( ! this . on_message ) return ;
230
-
231
- const require = this . require ;
232
- const crypto = require ( 'crypto' ) ;
233
- const decipher = crypto . createDecipheriv (
234
- 'aes-256-cbc' ,
235
- this . aesKey ,
236
- data . iv ,
237
- )
238
- const buffers = [ ] ;
239
- buffers . push ( decipher . update ( data . message ) ) ;
240
- buffers . push ( decipher . final ( ) ) ;
241
-
242
- const rawjson = Buffer . concat ( buffers ) . toString ( 'utf-8' ) ;
243
-
244
- const output = JSON . parse ( rawjson ) ;
245
-
246
- this . on_message ( output ) ;
247
- }
248
- }
249
- static OFFLINE = {
250
- on_message ( ) {
251
- throw new Error ( 'unexpected message' ) ;
252
- }
253
- }
254
-
255
- constructor ( svc_broadcast , socket ) {
256
- super ( ) ;
257
- this . state = this . constructor . AUTHENTICATING ;
258
- this . svc_broadcast = svc_broadcast ;
259
- this . log = this . svc_broadcast . log ;
260
- this . socket = socket ;
261
-
262
- socket . on ( 'message' , data => {
263
- this . state . on_message . call ( this , data ) ;
264
- } ) ;
265
- }
266
-
267
- disconnect ( ) {
268
- this . socket . disconnect ( true ) ;
269
- this . state = this . constructor . OFFLINE ;
270
- }
271
- }
21
+ const { CLink } = require ( "./connection/CLink" ) ;
22
+ const { SLink } = require ( "./connection/SLink" ) ;
272
23
273
24
class BroadcastService extends BaseService {
274
25
static MODULES = {
@@ -286,7 +37,11 @@ class BroadcastService extends BaseService {
286
37
const peers = this . config . peers ?? [ ] ;
287
38
for ( const peer_config of peers ) {
288
39
this . trustedPublicKeys_ [ peer_config . key ] = true ;
289
- const peer = new Peer ( this , peer_config ) ;
40
+ const peer = new CLink ( {
41
+ keys : this . config . keys ,
42
+ config : peer_config ,
43
+ log : this . log ,
44
+ } ) ;
290
45
this . peers_ . push ( peer ) ;
291
46
peer . connect ( ) ;
292
47
}
@@ -301,7 +56,6 @@ class BroadcastService extends BaseService {
301
56
if ( meta . from_outside ) return ;
302
57
303
58
for ( const peer of this . peers_ ) {
304
- if ( peer . state !== Peer . ONLINE ) continue ;
305
59
peer . send ( { key, data, meta } ) ;
306
60
}
307
61
}
@@ -318,10 +72,14 @@ class BroadcastService extends BaseService {
318
72
} ) ;
319
73
320
74
io . on ( 'connection' , async socket => {
321
- const conn = new Connection ( this , socket ) ;
75
+ const conn = new SLink ( {
76
+ keys : this . config . keys ,
77
+ trustedKeys : this . trustedPublicKeys_ ,
78
+ socket,
79
+ } ) ;
322
80
this . connections_ . push ( conn ) ;
323
81
324
- conn . on_message = ( { key, data, meta } ) => {
82
+ conn . channels . message . on ( ( { key, data, meta } ) => {
325
83
if ( meta . from_outside ) {
326
84
this . log . noticeme ( 'possible over-sending' ) ;
327
85
return ;
@@ -335,7 +93,7 @@ class BroadcastService extends BaseService {
335
93
336
94
meta . from_outside = true ;
337
95
svc_event . emit ( key , data , meta ) ;
338
- } ;
96
+ } ) ;
339
97
} ) ;
340
98
341
99
0 commit comments