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
```bash
--port <port> # Port to listen on (default: random)
--id <id> # Node ID (default: auto-generated UUID)
--bootstrap <addr> # Bootstrap node address (host:port)
--position <pos> # Initial ring position (default: 0)
--port <port> # Port to listen on (default: random)
--id <id> # Node ID (default: auto-generated UUID)
--bootstrap <addr> # Bootstrap node address (host:port)
--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
```

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 chalk from 'chalk';
import { readFileSync } from 'fs';
const args = process.argv.slice(2);
const options = {};
@@ -21,6 +22,26 @@ for (let i = 0; i < args.length; i++) {
case '--position':
options.ringPosition = parseInt(args[++i]);
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':
console.log(`
${chalk.blue('Ring Network Node')}
@@ -28,16 +49,27 @@ ${chalk.blue('Ring Network Node')}
Usage: node node.js [options]
Options:
--port <port> Port to listen on (default: random)
--id <id> Node ID (default: auto-generated)
--bootstrap <addr> Bootstrap node address (host:port)
--position <pos> Initial ring position (default: 0)
--help Show this help message
--port <port> Port to listen on (default: random)
--id <id> Node ID (default: auto-generated)
--bootstrap <addr> Bootstrap node address (host:port)
--position <pos> Initial ring position (default: 0)
--ice-servers <json> ICE servers configuration (JSON array)
--config <file> Load configuration from JSON file
--help Show this help message
Examples:
node node.js --port 8080
node node.js --port 8081 --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);
break;

Ver fichero

@@ -2,6 +2,7 @@
import { OracleNode } from './src/oracle-node.js';
import chalk from 'chalk';
import { readFileSync } from 'fs';
const args = process.argv.slice(2);
const options = {};
@@ -21,6 +22,26 @@ for (let i = 0; i < args.length; i++) {
case '--position':
options.ringPosition = parseInt(args[++i]);
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':
console.log(`
${chalk.yellow('Ring Network Oracle Node')}
@@ -28,16 +49,27 @@ ${chalk.yellow('Ring Network Oracle Node')}
Usage: node oracle.js [options]
Options:
--port <port> Port to listen on (default: random)
--id <id> Node ID (default: auto-generated)
--bootstrap <addr> Bootstrap node address (host:port)
--position <pos> Initial ring position (default: 0)
--help Show this help message
--port <port> Port to listen on (default: random)
--id <id> Node ID (default: auto-generated)
--bootstrap <addr> Bootstrap node address (host:port)
--position <pos> Initial ring position (default: 0)
--ice-servers <json> ICE servers configuration (JSON array)
--config <file> Load configuration from JSON file
--help Show this help message
Examples:
node oracle.js --port 8080
node oracle.js --port 8081 --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:
- 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.knownNodes = new Map();
this.messageHistory = new Set();

Ver fichero

@@ -4,11 +4,26 @@ import { v4 as uuidv4 } from 'uuid';
import wrtc from '@koush/wrtc';
export class WebRTCManager extends EventEmitter {
constructor(nodeId) {
constructor(nodeId, options = {}) {
super();
this.nodeId = nodeId;
this.connections = 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) {
@@ -23,10 +38,7 @@ export class WebRTCManager extends EventEmitter {
trickle: false,
wrtc: wrtc,
config: {
iceServers: [
{ urls: 'stun:stun.l.google.com:19302' },
{ urls: 'stun:stun1.l.google.com:19302' }
]
iceServers: this.iceServers
}
});
@@ -159,4 +171,32 @@ export class WebRTCManager extends EventEmitter {
}
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;
}
}