ICE servers config

Signed-off-by: ale <ale@manalejandro.com>
Este commit está contenido en:
ale
2025-06-15 13:07:16 +02:00
padre 69205d212f
commit 7c3921cdd3
Se han modificado 8 ficheros con 219 adiciones y 20 borrados

Ver fichero

@@ -74,10 +74,57 @@ npm run start:node -- --port 8083 --bootstrap localhost:8080
### Command Line Options ### Command Line Options
```bash ```bash
--port <port> # Port to listen on (default: random) --port <port> # Port to listen on (default: random)
--id <id> # Node ID (default: auto-generated UUID) --id <id> # Node ID (default: auto-generated UUID)
--bootstrap <addr> # Bootstrap node address (host:port) --bootstrap <addr> # Bootstrap node address (host:port)
--position <pos> # Initial ring position (default: 0) --position <pos> # Initial ring position (default: 0)
--ice-servers <json> # ICE servers configuration (JSON array)
--config <file> # Load configuration from JSON file
--help # Show help message
```
### WebRTC ICE Servers Configuration
The Ring Network uses WebRTC for peer-to-peer connections. You can configure custom ICE servers (STUN/TURN) for better connectivity:
#### Using Command Line
```bash
# With custom STUN servers
node node.js --ice-servers '[{"urls":"stun:your-stun-server.com:19302"}]'
# With TURN server for NAT traversal
node node.js --ice-servers '[{"urls":"stun:stun.l.google.com:19302"},{"urls":"turn:your-turn-server.com:3478","username":"user","credential":"pass"}]'
```
#### Using Configuration Files
```bash
# Load from config file
node node.js --config config/ice-servers-with-turn.json
# For Oracle nodes
node oracle.js --config config/ice-servers-public-turn.json
```
#### Available Configuration Examples
- `config/ice-servers-default.json` - Default Google STUN servers
- `config/ice-servers-with-turn.json` - Template with TURN server
- `config/ice-servers-public-turn.json` - Public TURN servers for testing
#### ICE Server Configuration Format
```json
{
"iceServers": [
{
"urls": "stun:stun.l.google.com:19302"
},
{
"urls": "turn:turnserver.example.com:3478",
"username": "your_username",
"credential": "your_password"
}
]
}
```
--help # Show help message --help # Show help message
``` ```

Ver fichero

@@ -0,0 +1,10 @@
{
"iceServers": [
{
"urls": "stun:stun.l.google.com:19302"
},
{
"urls": "stun:stun1.l.google.com:19302"
}
]
}

Ver fichero

@@ -0,0 +1,21 @@
{
"iceServers": [
{
"urls": [
"stun:stun.l.google.com:19302",
"stun:stun1.l.google.com:19302",
"stun:stun2.l.google.com:19302"
]
},
{
"urls": "turn:openrelay.metered.ca:80",
"username": "openrelayproject",
"credential": "openrelayproject"
},
{
"urls": "turn:openrelay.metered.ca:443",
"username": "openrelayproject",
"credential": "openrelayproject"
}
]
}

Ver fichero

@@ -0,0 +1,15 @@
{
"iceServers": [
{
"urls": "stun:stun.l.google.com:19302"
},
{
"urls": "stun:stun1.l.google.com:19302"
},
{
"urls": "turn:turnserver.example.com:3478",
"username": "your_username",
"credential": "your_password"
}
]
}

42
node.js
Ver fichero

@@ -2,6 +2,7 @@
import { RingNode } from './src/ring-node.js'; import { RingNode } from './src/ring-node.js';
import chalk from 'chalk'; import chalk from 'chalk';
import { readFileSync } from 'fs';
const args = process.argv.slice(2); const args = process.argv.slice(2);
const options = {}; const options = {};
@@ -21,6 +22,26 @@ for (let i = 0; i < args.length; i++) {
case '--position': case '--position':
options.ringPosition = parseInt(args[++i]); options.ringPosition = parseInt(args[++i]);
break; break;
case '--ice-servers':
try {
options.iceServers = JSON.parse(args[++i]);
} catch (error) {
console.error(chalk.red('Error parsing ICE servers JSON:'), error.message);
process.exit(1);
}
break;
case '--config':
try {
const configPath = args[++i];
const configData = JSON.parse(readFileSync(configPath, 'utf8'));
if (configData.iceServers) {
options.iceServers = configData.iceServers;
}
} catch (error) {
console.error(chalk.red('Error loading config file:'), error.message);
process.exit(1);
}
break;
case '--help': case '--help':
console.log(` console.log(`
${chalk.blue('Ring Network Node')} ${chalk.blue('Ring Network Node')}
@@ -28,16 +49,27 @@ ${chalk.blue('Ring Network Node')}
Usage: node node.js [options] Usage: node node.js [options]
Options: Options:
--port <port> Port to listen on (default: random) --port <port> Port to listen on (default: random)
--id <id> Node ID (default: auto-generated) --id <id> Node ID (default: auto-generated)
--bootstrap <addr> Bootstrap node address (host:port) --bootstrap <addr> Bootstrap node address (host:port)
--position <pos> Initial ring position (default: 0) --position <pos> Initial ring position (default: 0)
--help Show this help message --ice-servers <json> ICE servers configuration (JSON array)
--config <file> Load configuration from JSON file
--help Show this help message
Examples: Examples:
node node.js --port 8080 node node.js --port 8080
node node.js --port 8081 --bootstrap localhost:8080 node node.js --port 8081 --bootstrap localhost:8080
node node.js --id mynode --port 8082 --bootstrap localhost:8080 node node.js --id mynode --port 8082 --bootstrap localhost:8080
node node.js --config config/ice-servers-with-turn.json --port 8080
ICE Servers Example:
--ice-servers '[{"urls":"stun:stun.l.google.com:19302"},{"urls":"turn:turn.example.com:3478","username":"user","credential":"pass"}]'
Config File Example:
config/ice-servers-default.json - Default STUN servers
config/ice-servers-with-turn.json - With TURN server
config/ice-servers-public-turn.json - Public TURN servers
`); `);
process.exit(0); process.exit(0);
break; break;

Ver fichero

@@ -2,6 +2,7 @@
import { OracleNode } from './src/oracle-node.js'; import { OracleNode } from './src/oracle-node.js';
import chalk from 'chalk'; import chalk from 'chalk';
import { readFileSync } from 'fs';
const args = process.argv.slice(2); const args = process.argv.slice(2);
const options = {}; const options = {};
@@ -21,6 +22,26 @@ for (let i = 0; i < args.length; i++) {
case '--position': case '--position':
options.ringPosition = parseInt(args[++i]); options.ringPosition = parseInt(args[++i]);
break; break;
case '--ice-servers':
try {
options.iceServers = JSON.parse(args[++i]);
} catch (error) {
console.error(chalk.red('Error parsing ICE servers JSON:'), error.message);
process.exit(1);
}
break;
case '--config':
try {
const configPath = args[++i];
const configData = JSON.parse(readFileSync(configPath, 'utf8'));
if (configData.iceServers) {
options.iceServers = configData.iceServers;
}
} catch (error) {
console.error(chalk.red('Error loading config file:'), error.message);
process.exit(1);
}
break;
case '--help': case '--help':
console.log(` console.log(`
${chalk.yellow('Ring Network Oracle Node')} ${chalk.yellow('Ring Network Oracle Node')}
@@ -28,16 +49,27 @@ ${chalk.yellow('Ring Network Oracle Node')}
Usage: node oracle.js [options] Usage: node oracle.js [options]
Options: Options:
--port <port> Port to listen on (default: random) --port <port> Port to listen on (default: random)
--id <id> Node ID (default: auto-generated) --id <id> Node ID (default: auto-generated)
--bootstrap <addr> Bootstrap node address (host:port) --bootstrap <addr> Bootstrap node address (host:port)
--position <pos> Initial ring position (default: 0) --position <pos> Initial ring position (default: 0)
--help Show this help message --ice-servers <json> ICE servers configuration (JSON array)
--config <file> Load configuration from JSON file
--help Show this help message
Examples: Examples:
node oracle.js --port 8080 node oracle.js --port 8080
node oracle.js --port 8081 --bootstrap localhost:8080 node oracle.js --port 8081 --bootstrap localhost:8080
node oracle.js --id oracle1 --port 8082 --bootstrap localhost:8080 node oracle.js --id oracle1 --port 8082 --bootstrap localhost:8080
node oracle.js --config config/ice-servers-with-turn.json --port 8080
ICE Servers Example:
--ice-servers '[{"urls":"stun:stun.l.google.com:19302"},{"urls":"turn:turn.example.com:3478","username":"user","credential":"pass"}]'
Config File Example:
config/ice-servers-default.json - Default STUN servers
config/ice-servers-with-turn.json - With TURN server
config/ice-servers-public-turn.json - Public TURN servers
Oracle Services: Oracle Services:
- network-analysis: Analyze network topology and health - network-analysis: Analyze network topology and health

Ver fichero

@@ -24,7 +24,9 @@ export class RingNode extends EventEmitter {
} }
}; };
this.webrtc = new WebRTCManager(this.id); this.webrtc = new WebRTCManager(this.id, {
iceServers: options.iceServers
});
this.discoveryServer = null; this.discoveryServer = null;
this.knownNodes = new Map(); this.knownNodes = new Map();
this.messageHistory = new Set(); this.messageHistory = new Set();

Ver fichero

@@ -4,11 +4,26 @@ import { v4 as uuidv4 } from 'uuid';
import wrtc from '@koush/wrtc'; import wrtc from '@koush/wrtc';
export class WebRTCManager extends EventEmitter { export class WebRTCManager extends EventEmitter {
constructor(nodeId) { constructor(nodeId, options = {}) {
super(); super();
this.nodeId = nodeId; this.nodeId = nodeId;
this.connections = new Map(); this.connections = new Map();
this.pendingConnections = new Map(); this.pendingConnections = new Map();
// Configure ICE servers with defaults
this.iceServers = options.iceServers || [
{ urls: 'stun:stun.l.google.com:19302' },
{ urls: 'stun:stun1.l.google.com:19302' }
];
// Validate ICE servers configuration
try {
WebRTCManager.validateIceServers(this.iceServers);
console.log(`🌐 Using ${this.iceServers.length} ICE server(s) for WebRTC connections`);
} catch (error) {
console.error('Invalid ICE servers configuration:', error.message);
throw error;
}
} }
async createConnection(peerId, isInitiator = false) { async createConnection(peerId, isInitiator = false) {
@@ -23,10 +38,7 @@ export class WebRTCManager extends EventEmitter {
trickle: false, trickle: false,
wrtc: wrtc, wrtc: wrtc,
config: { config: {
iceServers: [ iceServers: this.iceServers
{ urls: 'stun:stun.l.google.com:19302' },
{ urls: 'stun:stun1.l.google.com:19302' }
]
} }
}); });
@@ -159,4 +171,32 @@ export class WebRTCManager extends EventEmitter {
} }
this.connections.clear(); this.connections.clear();
} }
static validateIceServers(iceServers) {
if (!Array.isArray(iceServers)) {
throw new Error('ICE servers must be an array');
}
for (const server of iceServers) {
if (!server.urls) {
throw new Error('Each ICE server must have a "urls" property');
}
const urls = Array.isArray(server.urls) ? server.urls : [server.urls];
for (const url of urls) {
if (!url.startsWith('stun:') && !url.startsWith('turn:') && !url.startsWith('turns:')) {
throw new Error(`Invalid ICE server URL: ${url}. Must start with stun:, turn:, or turns:`);
}
}
// If it's a TURN server, it should have credentials
if (urls.some(url => url.startsWith('turn:') || url.startsWith('turns:'))) {
if (!server.username || !server.credential) {
console.warn(`Warning: TURN server ${server.urls} missing username/credential`);
}
}
}
return true;
}
} }