Files
makemd/server/src/core/network/P2PConnectionService.ts

127 lines
4.4 KiB
TypeScript
Raw Normal View History

import { logger } from '../../utils/logger';
import { FederatedNode, FederatedNodeService } from './FederatedNodeService';
import { RedisService } from '../../utils/RedisService';
export interface P2PMessage {
from: string;
to: string;
type: string;
payload: any;
signature: string;
timestamp: number;
}
/**
* [SOV_NET_06] Libp2p/WebRTC (P2P Connectivity)
* @description Hub
* P2P
* Autocomplete-First (V31.5)
*/
export class P2PConnectionService {
private static readonly CONNECTION_CACHE_PREFIX = 'sov_net:p2p:conn:';
private static readonly PEER_STORE_KEY = 'sov_net:p2p:peers';
/**
* P2P (DHT Discovery & PeerStore)
*/
static async init() {
logger.info(`[SovNet] Initializing P2P connection listener (Libp2p/DHT mode)...`);
// 1. 启动 DHT 发现循环 (模拟)
setInterval(async () => {
await this.discoverPeersViaDHT();
}, 60000); // 每分钟发现一次
}
/**
* DHT PeerStore (DHT Discovery)
* @private
*/
private static async discoverPeersViaDHT() {
logger.info(`[SovNet] Scanning DHT for new Hub nodes...`);
// 模拟从分布式哈希表发现新节点
const activeNodes = await FederatedNodeService.getActiveNodes();
const peerIds = activeNodes.map(n => n.nodeId);
await RedisService.set(this.PEER_STORE_KEY, JSON.stringify(peerIds));
logger.info(`[SovNet] PeerStore synchronized. ${peerIds.length} peers discovered.`);
}
/**
* P2P (Noise/TLS 1.3 Handshake)
* @param targetNodeId ID
*/
static async connectToNode(targetNodeId: string): Promise<boolean> {
logger.info(`[SovNet] Attempting P2P connection to node: ${targetNodeId}`);
const nodes = await FederatedNodeService.getActiveNodes();
const targetNode = nodes.find(n => n.nodeId === targetNodeId);
if (!targetNode) {
logger.error(`[SovNet] Target node ${targetNodeId} not found or offline.`);
return false;
}
try {
// 1. 模拟 Noise Protocol / TLS 1.3 双向加密握手 (Noise-IK)
const handshakeSuccess = await this.performP2PHandshake(targetNode);
if (!handshakeSuccess) {
logger.warn(`[SovNet] Handshake failed with node ${targetNodeId}. Connection rejected.`);
return false;
}
// 2. 建立多路复用流 (Stream Multiplexing)
await this.establishMplexStream(targetNodeId);
// 3. 缓存连接状态
await RedisService.set(`${this.CONNECTION_CACHE_PREFIX}${targetNodeId}`, 'ESTABLISHED', 300);
logger.info(`[SovNet] P2P (Noise/TLS 1.3) connection established with node ${targetNodeId}`);
return true;
} catch (err: any) {
logger.error(`[SovNet] P2P connection failed: ${err.message}`);
return false;
}
}
/**
* (Stream Multiplexing)
* @private
*/
private static async establishMplexStream(nodeId: string) {
// 模拟 mplex / yamux 流复用建立
logger.info(`[SovNet] Mplex stream multiplexing initialized for ${nodeId}`);
}
/**
* P2P (Life-cycle Management)
* @param message
*/
static async sendMessage(message: P2PMessage): Promise<boolean> {
logger.info(`[SovNet] Sending P2P message to ${message.to} (Type: ${message.type})`);
const connectionStatus = await RedisService.get(`${this.CONNECTION_CACHE_PREFIX}${message.to}`);
if (connectionStatus !== 'ESTABLISHED') {
const reconnected = await this.connectToNode(message.to);
if (!reconnected) return false;
}
// 实际生产中通过 libp2p.pubsub 或 stream 发送
// 模拟发送成功并更新最后活动时间
await RedisService.set(`${this.CONNECTION_CACHE_PREFIX}${message.to}`, 'ESTABLISHED', 300);
return true;
}
/**
* Noise/TLS 1.3 (Noise-IK)
* @private
*/
private static async performP2PHandshake(node: FederatedNode): Promise<boolean> {
logger.info(`[SovNet] Performing Noise-IK handshake with DID: ${node.did}`);
// 模拟验证远程节点 DID 签名与证书链
// 生产环境中会使用 node.publicKey 进行加密挑战响应
return node.trustScore > 0.4; // 降低一点门槛以兼容更多节点
}
}