diodejs 0.0.5 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -87,13 +87,22 @@ async function main() {
87
87
  const connection = new DiodeConnection(host, port, certPath);
88
88
  await connection.connect();
89
89
 
90
- const publishedPorts = [8080]; // Ports you want to publish
91
- const publishPort = new PublishPort(connection, publishedPorts, certPath);
92
-
90
+ // Option 1: Simple array of ports (all public)
91
+ const publishedPorts = [8080, 3000];
92
+
93
+ // Option 2: Object with port configurations for public/private access control
94
+ const publishedPortsWithConfig = {
95
+ 8080: { mode: 'public' }, // Public port, accessible by any device
96
+ 3000: {
97
+ mode: 'private',
98
+ whitelist: ['0x1234abcd5678...', '0x9876fedc5432...'] // Only these devices can connect
99
+ }
100
+ };
101
+
102
+ const publishPort = new PublishPort(connection, publishedPortsWithConfig, certPath);
93
103
  }
94
104
 
95
105
  main();
96
-
97
106
  ```
98
107
 
99
108
  ## Reference
@@ -149,7 +158,9 @@ main();
149
158
 
150
159
  - **Constructor**: `new PublishPort(connection, publishedPorts, certPath)`
151
160
  - `connection` (DiodeConnection): An instance of `DiodeConnection`.
152
- - `publishedPorts` (array): An array of ports to publish.
161
+ - `publishedPorts` (array|object): Either:
162
+ - An array of ports to publish (all public mode)
163
+ - An object mapping ports to their configuration: `{ port: { mode: 'public'|'private', whitelist: ['0x123...'] } }`
153
164
  - `certPath` (string): The path to the device certificate.
154
165
 
155
166
  - **Methods**:
package/bindPort.js CHANGED
@@ -13,8 +13,7 @@ class BindPort {
13
13
 
14
14
  bind () {
15
15
  const deviceId = Buffer.from(this.deviceIdHex, 'hex');
16
- const clientSockets = new Map();
17
-
16
+ // Remove local clientSockets map and use the one from connection
18
17
  const rpc = new DiodeRPC(this.connection);
19
18
 
20
19
  // Listen for data events from the device
@@ -31,12 +30,17 @@ class BindPort {
31
30
  const dataRef = Buffer.from(refRaw);
32
31
  const data = Buffer.from(dataRaw);
33
32
 
34
- // Find the associated client socket
35
- const clientSocket = clientSockets.get(dataRef.toString('hex'));
33
+ // Find the associated client socket from connection
34
+ const clientSocket = this.connection.getClientSocket(dataRef);
36
35
  if (clientSocket) {
37
36
  clientSocket.write(data);
38
37
  } else {
39
- logger.warn(`No client socket found for ref: ${dataRef.toString('hex')}`);
38
+ const connectionInfo = this.connection.getConnection(dataRef);
39
+ if (connectionInfo) {
40
+ logger.debug(`No client socket found for ref: ${dataRef.toString('hex')}, but connection exists for ${connectionInfo.host}:${connectionInfo.port}`);
41
+ } else {
42
+ logger.warn(`No client socket found for ref: ${dataRef.toString('hex')}`);
43
+ }
40
44
  }
41
45
  } else if (messageType === 'portclose') {
42
46
  const refRaw = messageContent[1];
@@ -44,14 +48,16 @@ class BindPort {
44
48
  const dataRef = Buffer.from(refRaw);
45
49
 
46
50
  // Close the associated client socket
47
- const clientSocket = clientSockets.get(dataRef.toString('hex'));
51
+ const clientSocket = this.connection.getClientSocket(dataRef);
48
52
  if (clientSocket) {
49
53
  clientSocket.end();
50
- clientSockets.delete(dataRef.toString('hex'));
54
+ this.connection.deleteClientSocket(dataRef);
51
55
  logger.info(`Port closed for ref: ${dataRef.toString('hex')}`);
52
56
  }
53
57
  } else {
54
- logger.warn(`Unknown unsolicited message type: ${messageType}`);
58
+ if (messageType != 'portopen') {
59
+ logger.warn(`Unknown unsolicited message type: ${messageType}`);
60
+ }
55
61
  }
56
62
  });
57
63
 
@@ -76,8 +82,8 @@ class BindPort {
76
82
  return;
77
83
  }
78
84
 
79
- // Store the client socket with the ref (using hex string as key)
80
- clientSockets.set(ref.toString('hex'), clientSocket);
85
+ // Store the client socket with the ref using connection's method
86
+ this.connection.addClientSocket(ref, clientSocket);
81
87
 
82
88
  // When data is received from the client, send it to the device
83
89
  clientSocket.on('data', async (data) => {
@@ -92,11 +98,11 @@ class BindPort {
92
98
  // Handle client socket closure
93
99
  clientSocket.on('end', async () => {
94
100
  logger.info('Client disconnected');
95
- if (ref && clientSockets.has(ref.toString('hex'))) {
101
+ if (ref && this.connection.hasClientSocket(ref)) {
96
102
  try {
97
103
  await rpc.portClose(ref);
98
104
  logger.info(`Port closed on device for ref: ${ref.toString('hex')}`);
99
- clientSockets.delete(ref.toString('hex'));
105
+ this.connection.deleteClientSocket(ref);
100
106
  } catch (error) {
101
107
  logger.error(`Error closing port on device: ${error}`);
102
108
  }
package/connection.js CHANGED
@@ -28,6 +28,10 @@ class DiodeConnection extends EventEmitter {
28
28
  this.RPC = new DiodeRPC(this);
29
29
  this.isReconnecting = false;
30
30
  this.connectPromise = null;
31
+
32
+ // Add maps for storing client sockets and connections
33
+ this.clientSockets = new Map(); // For BindPort
34
+ this.connections = new Map(); // For PublishPort
31
35
 
32
36
  // Check if certPath exists, if not generate the certificate
33
37
  if (!fs.existsSync(this.certPath)) {
@@ -562,6 +566,40 @@ class DiodeConnection extends EventEmitter {
562
566
  close() {
563
567
  this.socket.end();
564
568
  }
569
+
570
+ // Client sockets management methods (for BindPort)
571
+ addClientSocket(ref, socket) {
572
+ this.clientSockets.set(ref.toString('hex'), socket);
573
+ }
574
+
575
+ getClientSocket(ref) {
576
+ return this.clientSockets.get(ref.toString('hex'));
577
+ }
578
+
579
+ deleteClientSocket(ref) {
580
+ return this.clientSockets.delete(ref.toString('hex'));
581
+ }
582
+
583
+ hasClientSocket(ref) {
584
+ return this.clientSockets.has(ref.toString('hex'));
585
+ }
586
+
587
+ // Connections management methods (for PublishPort)
588
+ addConnection(ref, connectionInfo) {
589
+ this.connections.set(ref.toString('hex'), connectionInfo);
590
+ }
591
+
592
+ getConnection(ref) {
593
+ return this.connections.get(ref.toString('hex'));
594
+ }
595
+
596
+ deleteConnection(ref) {
597
+ return this.connections.delete(ref.toString('hex'));
598
+ }
599
+
600
+ hasConnection(ref) {
601
+ return this.connections.has(ref.toString('hex'));
602
+ }
565
603
  }
566
604
 
567
605
 
@@ -0,0 +1,23 @@
1
+ const DiodeConnection = require('../connection')
2
+ const PublishPort = require('../publishPort')
3
+ const BindPort = require('../bindPort')
4
+
5
+ const host = 'us2.prenet.diode.io';
6
+ const port = 41046;
7
+ const certPath = 'device_certificate.pem';
8
+
9
+ const connection = new DiodeConnection(host, port, certPath);
10
+
11
+ async function main() {
12
+ await connection.connect();
13
+ const publishedPorts = [8080]; // Ports you want to publish
14
+ const publishPort = new PublishPort(connection, publishedPorts, certPath);
15
+
16
+ const portForward = new BindPort(connection, 3002, 8080, "5365baf29cb7ab58de588dfc448913cb609283e2");
17
+ portForward.bind();
18
+
19
+ }
20
+
21
+ main();
22
+
23
+
@@ -11,7 +11,7 @@ async function startPublishing() {
11
11
  const connection = new DiodeConnection(host, port, certPath);
12
12
  await connection.connect();
13
13
 
14
- const publishedPorts = [8080]; // Ports you want to publish
14
+ const publishedPorts = {8080: {mode: 'private', whitelist: ['0xca1e71d8105a598810578fb6042fa8cbc1e7f039']}}
15
15
  const publishPort = new PublishPort(connection, publishedPorts, certPath);
16
16
 
17
17
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "diodejs",
3
- "version": "0.0.5",
3
+ "version": "0.1.1",
4
4
  "description": "A JavaScript client for interacting with the Diode network. It provides functionalities to bind and publish ports, send RPC commands, and handle responses.",
5
5
  "main": "index.js",
6
6
  "scripts": {
package/publishPort.js CHANGED
@@ -39,9 +39,34 @@ class PublishPort extends EventEmitter {
39
39
  constructor(connection, publishedPorts, certPath) {
40
40
  super();
41
41
  this.connection = connection;
42
- this.publishedPorts = new Set(publishedPorts); // Convert array to a Set
43
- this.connections = new Map(); // Map to store active connections
42
+
43
+ // Convert publishedPorts to a Map with configurations
44
+ this.publishedPorts = new Map();
45
+
46
+ // Handle both array format and object format
47
+ if (Array.isArray(publishedPorts)) {
48
+ // Legacy array format - treat all ports as public
49
+ publishedPorts.forEach(port => {
50
+ this.publishedPorts.set(port, { mode: 'public', whitelist: [] });
51
+ });
52
+ } else if (typeof publishedPorts === 'object' && publishedPorts !== null) {
53
+ // New object format with configurations
54
+ Object.entries(publishedPorts).forEach(([port, config]) => {
55
+ const portNum = parseInt(port, 10);
56
+ // Ensure config is properly structured
57
+ const portConfig = typeof config === 'object' && config !== null
58
+ ? {
59
+ mode: config.mode || 'public',
60
+ whitelist: Array.isArray(config.whitelist) ? config.whitelist : []
61
+ }
62
+ : { mode: 'public', whitelist: [] };
63
+
64
+ this.publishedPorts.set(portNum, portConfig);
65
+ });
66
+ }
67
+
44
68
  this.startListening();
69
+ logger.info(`Publishing ports: ${Array.from(this.publishedPorts.keys())}`);
45
70
  this.rpc = new DiodeRPC(connection);
46
71
  this.certPath = certPath;
47
72
  }
@@ -60,7 +85,9 @@ class PublishPort extends EventEmitter {
60
85
  } else if (messageType === 'portclose') {
61
86
  this.handlePortClose(sessionIdRaw, messageContent);
62
87
  } else {
63
- logger.warn(`Unknown unsolicited message type: ${messageType}`);
88
+ if (messageType != 'data') {
89
+ logger.warn(`Unknown unsolicited message type: ${messageType}`);
90
+ }
64
91
  }
65
92
  });
66
93
  }
@@ -74,7 +101,7 @@ class PublishPort extends EventEmitter {
74
101
  const sessionId = Buffer.from(sessionIdRaw);
75
102
  const portString = makeReadable(portStringRaw);
76
103
  const ref = Buffer.from(refRaw);
77
- const deviceId = Buffer.from(deviceIdRaw).toString('hex');
104
+ const deviceId = `0x${Buffer.from(deviceIdRaw).toString('hex')}`;
78
105
 
79
106
  logger.info(`Received portopen request for portString ${portString} with ref ${ref.toString('hex')} from device ${deviceId}`);
80
107
 
@@ -94,13 +121,24 @@ class PublishPort extends EventEmitter {
94
121
  }
95
122
 
96
123
  // Check if the port is published
97
- if (!this.publishedPorts.has(port)) { // Use .has() instead of .includes()
124
+ if (!this.publishedPorts.has(port)) {
98
125
  logger.warn(`Port ${port} is not published. Rejecting request.`);
99
126
  // Send error response
100
127
  this.rpc.sendError(sessionId, ref, 'Port is not published');
101
128
  return;
102
129
  }
103
130
 
131
+ // Get port configuration and check whitelist if in private mode
132
+ const portConfig = this.publishedPorts.get(port);
133
+ if (portConfig.mode === 'private' && Array.isArray(portConfig.whitelist)) {
134
+ if (!portConfig.whitelist.includes(deviceId)) {
135
+ logger.warn(`Device ${deviceId} is not whitelisted for port ${port}. Rejecting request.`);
136
+ this.rpc.sendError(sessionId, ref, 'Device not whitelisted');
137
+ return;
138
+ }
139
+ logger.info(`Device ${deviceId} is whitelisted for port ${port}. Accepting request.`);
140
+ }
141
+
104
142
  // Handle based on protocol
105
143
  if (protocol === 'tcp') {
106
144
  this.handleTCPConnection(sessionId, ref, port);
@@ -127,14 +165,14 @@ class PublishPort extends EventEmitter {
127
165
  logger.info(`Local service disconnected`);
128
166
  // Send portclose message to Diode
129
167
  this.rpc.portClose(ref);
130
- this.connections.delete(ref.toString('hex'));
168
+ this.connection.deleteConnection(ref);
131
169
  });
132
170
 
133
171
  localSocket.on('error', (err) => {
134
172
  logger.error(`Error with local service: ${err}`);
135
173
  // Send portclose message to Diode
136
174
  this.rpc.portClose(ref);
137
- this.connections.delete(ref.toString('hex'));
175
+ this.connection.deleteConnection(ref);
138
176
  });
139
177
  }
140
178
  }
@@ -150,8 +188,8 @@ class PublishPort extends EventEmitter {
150
188
  // Handle data, end, and error events
151
189
  this.setupLocalSocketHandlers(localSocket, ref, 'tcp');
152
190
 
153
- // Store the local socket with the ref
154
- this.connections.set(ref.toString('hex'), { socket: localSocket, protocol: 'tcp' });
191
+ // Store the local socket with the ref using connection's method
192
+ this.connection.addConnection(ref, { socket: localSocket, protocol: 'tcp' });
155
193
  }
156
194
 
157
195
  handleTLSConnection(sessionId, ref, port) {
@@ -189,16 +227,16 @@ class PublishPort extends EventEmitter {
189
227
  tlsSocket.on('error', (err) => {
190
228
  logger.error(`TLS Socket error: ${err}`);
191
229
  this.rpc.portClose(ref);
192
- this.connections.delete(ref.toString('hex'));
230
+ this.connection.deleteConnection(ref);
193
231
  });
194
232
 
195
233
  tlsSocket.on('close', () => {
196
234
  console.log('TLS Socket closed');
197
- this.connections.delete(ref.toString('hex'));
235
+ this.connection.deleteConnection(ref);
198
236
  });
199
237
 
200
- // Store the connection info
201
- this.connections.set(ref.toString('hex'), {
238
+ // Store the connection info using connection's method
239
+ this.connection.addConnection(ref, {
202
240
  diodeSocket,
203
241
  tlsSocket,
204
242
  localSocket,
@@ -216,8 +254,8 @@ class PublishPort extends EventEmitter {
216
254
  // Send success response
217
255
  this.rpc.sendResponse(sessionId, ref, 'ok');
218
256
 
219
- // Store the connection info
220
- this.connections.set(ref.toString('hex'), {
257
+ // Store the connection info using connection's method
258
+ this.connection.addConnection(ref, {
221
259
  socket: localSocket,
222
260
  protocol: 'udp',
223
261
  remoteInfo,
@@ -238,7 +276,7 @@ class PublishPort extends EventEmitter {
238
276
  localSocket.on('error', (err) => {
239
277
  logger.error(`UDP Socket error: ${err}`);
240
278
  this.rpc.portClose(ref);
241
- this.connections.delete(ref.toString('hex'));
279
+ this.connection.deleteConnection(ref);
242
280
  });
243
281
  }
244
282
 
@@ -250,7 +288,7 @@ class PublishPort extends EventEmitter {
250
288
  const ref = Buffer.from(refRaw);
251
289
  const data = Buffer.from(dataRaw)//.slice(4);
252
290
 
253
- const connectionInfo = this.connections.get(ref.toString('hex'));
291
+ const connectionInfo = this.connection.getConnection(ref);
254
292
  if (connectionInfo) {
255
293
  const { socket: localSocket, protocol, remoteInfo } = connectionInfo;
256
294
 
@@ -277,8 +315,13 @@ class PublishPort extends EventEmitter {
277
315
  diodeSocket.pushData(data);
278
316
  }
279
317
  } else {
280
- logger.warn(`No local connection found for ref ${ref.toString('hex')}. Sending portclose.`);
281
- this.rpc.sendError(sessionId, ref, 'No local connection found');
318
+ const clientSocket = this.connection.getClientSocket(ref);
319
+ if (clientSocket) {
320
+ logger.debug(`No local connection found for ref: ${ref.toString('hex')}, but client socket exists`);
321
+ } else {
322
+ logger.warn(`No local connection found for ref ${ref.toString('hex')}. Sending portclose.`);
323
+ this.rpc.sendError(sessionId, ref, 'No local connection found');
324
+ }
282
325
  }
283
326
  }
284
327
 
@@ -289,7 +332,7 @@ class PublishPort extends EventEmitter {
289
332
 
290
333
  logger.info(`Received portclose for ref ${ref.toString('hex')}`);
291
334
 
292
- const connectionInfo = this.connections.get(ref.toString('hex'));
335
+ const connectionInfo = this.connection.getConnection(ref);
293
336
  if (connectionInfo) {
294
337
  const { diodeSocket, tlsSocket, socket: localSocket } = connectionInfo;
295
338
  // End all sockets
@@ -302,7 +345,7 @@ class PublishPort extends EventEmitter {
302
345
  localSocket.end();
303
346
  }
304
347
  }
305
- this.connections.delete(ref.toString('hex'));
348
+ this.connection.deleteConnection(ref);
306
349
  }
307
350
  }
308
351
  }