mirror of
https://github.com/mofeng-git/One-KVM.git
synced 2026-01-29 00:51:53 +08:00
feat(rustdesk): 完整实现RustDesk协议和P2P连接
重大变更: - 从prost切换到protobuf 3.4实现完整的RustDesk协议栈 - 新增P2P打洞模块(punch.rs)支持直连和中继回退 - 重构加密系统:临时Curve25519密钥对+Ed25519签名 - 完善HID适配器:支持CapsLock状态同步和修饰键映射 - 添加音频流支持:Opus编码+音频帧适配器 - 优化视频流:改进帧适配器和编码器协商 - 移除pacer.rs简化视频管道 扩展系统: - 在设置向导中添加扩展步骤(ttyd/rustdesk切换) - 扩展可用性检测和自动启动 - 新增WebConfig handler用于Web服务器配置 前端改进: - SetupView增加第4步扩展配置 - 音频设备列表和配置界面 - 新增多语言支持(en-US/zh-CN) - TypeScript类型生成更新 文档: - 更新系统架构文档 - 完善config/hid/rustdesk/video/webrtc模块文档
This commit is contained in:
128
src/rustdesk/punch.rs
Normal file
128
src/rustdesk/punch.rs
Normal file
@@ -0,0 +1,128 @@
|
||||
//! P2P Punch Hole Implementation
|
||||
//!
|
||||
//! This module implements TCP direct connection attempts with relay fallback.
|
||||
//! When a PunchHole request is received, we try to connect directly to the peer.
|
||||
//! If the direct connection fails (timeout), we fall back to relay.
|
||||
|
||||
use std::net::SocketAddr;
|
||||
use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
|
||||
use tokio::net::TcpStream;
|
||||
use tracing::{debug, info, warn};
|
||||
|
||||
use super::connection::ConnectionManager;
|
||||
|
||||
/// Timeout for direct TCP connection attempt
|
||||
const DIRECT_CONNECT_TIMEOUT_MS: u64 = 3000;
|
||||
|
||||
/// Result of a punch hole attempt
|
||||
#[derive(Debug)]
|
||||
pub enum PunchResult {
|
||||
/// Direct connection succeeded
|
||||
DirectConnection(TcpStream),
|
||||
/// Direct connection failed, should use relay
|
||||
NeedRelay,
|
||||
}
|
||||
|
||||
/// Attempt direct TCP connection to peer
|
||||
///
|
||||
/// This is a simplified P2P approach:
|
||||
/// 1. Try to connect directly to the peer's address
|
||||
/// 2. If successful within timeout, use direct connection
|
||||
/// 3. If failed or timeout, fall back to relay
|
||||
pub async fn try_direct_connection(peer_addr: SocketAddr) -> PunchResult {
|
||||
info!("Attempting direct TCP connection to {}", peer_addr);
|
||||
|
||||
match tokio::time::timeout(
|
||||
Duration::from_millis(DIRECT_CONNECT_TIMEOUT_MS),
|
||||
TcpStream::connect(peer_addr),
|
||||
)
|
||||
.await
|
||||
{
|
||||
Ok(Ok(stream)) => {
|
||||
info!("Direct TCP connection to {} succeeded", peer_addr);
|
||||
PunchResult::DirectConnection(stream)
|
||||
}
|
||||
Ok(Err(e)) => {
|
||||
debug!("Direct TCP connection to {} failed: {}", peer_addr, e);
|
||||
PunchResult::NeedRelay
|
||||
}
|
||||
Err(_) => {
|
||||
debug!("Direct TCP connection to {} timed out", peer_addr);
|
||||
PunchResult::NeedRelay
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Punch hole handler that tries direct connection first, then falls back to relay
|
||||
pub struct PunchHoleHandler {
|
||||
connection_manager: Arc<ConnectionManager>,
|
||||
}
|
||||
|
||||
impl PunchHoleHandler {
|
||||
pub fn new(connection_manager: Arc<ConnectionManager>) -> Self {
|
||||
Self { connection_manager }
|
||||
}
|
||||
|
||||
/// Handle punch hole request
|
||||
///
|
||||
/// Tries direct connection first, falls back to relay if needed.
|
||||
/// Returns true if direct connection succeeded, false if relay is needed.
|
||||
pub async fn handle_punch_hole(
|
||||
&self,
|
||||
peer_addr: Option<SocketAddr>,
|
||||
) -> bool {
|
||||
let peer_addr = match peer_addr {
|
||||
Some(addr) => addr,
|
||||
None => {
|
||||
warn!("No peer address available for punch hole");
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
match try_direct_connection(peer_addr).await {
|
||||
PunchResult::DirectConnection(stream) => {
|
||||
// Direct connection succeeded, accept it
|
||||
match self.connection_manager.accept_connection(stream, peer_addr).await {
|
||||
Ok(_) => {
|
||||
info!("P2P direct connection established with {}", peer_addr);
|
||||
true
|
||||
}
|
||||
Err(e) => {
|
||||
warn!("Failed to accept direct connection: {}", e);
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
PunchResult::NeedRelay => {
|
||||
debug!("Direct connection failed, need relay for {}", peer_addr);
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Spawn a punch hole attempt with relay fallback
|
||||
///
|
||||
/// This function spawns an async task that:
|
||||
/// 1. Tries direct TCP connection to peer
|
||||
/// 2. If successful, accepts the connection
|
||||
/// 3. If failed, calls the relay callback
|
||||
pub fn spawn_punch_with_fallback<F>(
|
||||
connection_manager: Arc<ConnectionManager>,
|
||||
peer_addr: Option<SocketAddr>,
|
||||
relay_callback: F,
|
||||
) where
|
||||
F: FnOnce() + Send + 'static,
|
||||
{
|
||||
tokio::spawn(async move {
|
||||
let handler = PunchHoleHandler::new(connection_manager);
|
||||
|
||||
if !handler.handle_punch_hole(peer_addr).await {
|
||||
// Direct connection failed, use relay
|
||||
info!("Falling back to relay connection");
|
||||
relay_callback();
|
||||
}
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user