use crate::server::device::DeviceManager;
use crate::server::connection::ConnectionManagerTrait;
use crate::common::device::{DeviceInfo, DevicePlatform};
use crate::common::error::Result;
use crate::common::protocol::{frame_with_system_command, builder::kicked, Reliability};
use crate::common::MessageParser;
use std::sync::Arc;
use tracing::{debug, error, info, warn};
#[derive(Debug)]
pub struct DeviceConflictResult {
pub conflict_connections: Vec<String>,
}
pub async fn handle_device_conflict(
device_manager: Option<Arc<DeviceManager>>,
user_id: &str,
connection_id: &str,
platform: &DevicePlatform,
device_info: &DeviceInfo,
manager: Arc<dyn ConnectionManagerTrait>,
) -> Result<DeviceConflictResult> {
let mut conflict_connections = Vec::new();
info!(
"[DeviceHandler] 开始处理设备冲突: user_id={}, connection_id={}, platform={:?}",
user_id,
connection_id,
platform
);
let device_manager_clone = device_manager.clone();
if let Some(device_mgr) = &device_manager {
match device_mgr.add_device(user_id, connection_id.to_string(), device_info.clone()).await {
Ok(conflicts) => {
conflict_connections = conflicts;
if !conflict_connections.is_empty() {
info!(
"[DeviceHandler] ✅ 设备冲突检测: 用户 {} 的新平台 {:?} 将踢掉 {} 个旧连接: {:?}",
user_id,
platform,
conflict_connections.len(),
conflict_connections
);
} else {
debug!(
"[DeviceHandler] 无设备冲突: 用户 {} 的新平台 {:?} 可以正常添加",
user_id,
platform
);
}
}
Err(e) => {
error!("[DeviceHandler] 设备管理器错误: {}", e);
}
}
} else {
debug!("[DeviceHandler] 未配置设备管理器,跳过设备冲突检测");
}
if !conflict_connections.is_empty() {
info!(
"[DeviceHandler] 准备踢掉 {} 个冲突连接: {:?}",
conflict_connections.len(),
conflict_connections
);
}
if let Some(device_mgr) = device_manager_clone {
info!(
"[DeviceHandler] 🔍 开始处理 {} 个冲突连接,新连接ID: {}",
conflict_connections.len(),
connection_id
);
for conflict_conn_id in &conflict_connections {
if conflict_conn_id == connection_id {
error!(
"[DeviceHandler] ❌ 严重错误:冲突连接列表包含新连接ID!跳过处理: connection_id={}",
connection_id
);
continue;
}
info!(
"[DeviceHandler] 📤 准备踢掉旧连接: connection_id={} (新连接ID: {})",
conflict_conn_id,
connection_id
);
if let Some((conn, conn_info)) = manager.get_connection(conflict_conn_id).await {
info!(
"[DeviceHandler] 找到冲突连接: connection_id={}, user_id={:?}, format={:?}",
conflict_conn_id,
conn_info.user_id,
conn_info.serialization_format
);
let reason = format!(
"设备冲突:同一用户 ({}) 的同一平台 ({:?}) 已有其他设备在线,当前设备将被踢下线",
user_id,
platform
);
let mut metadata = std::collections::HashMap::new();
metadata.insert("reason".to_string(), "device_conflict".as_bytes().to_vec());
metadata.insert("platform".to_string(), format!("{:?}", platform).as_bytes().to_vec());
metadata.insert("new_device_id".to_string(), device_info.device_id.as_bytes().to_vec());
let kick_cmd = kicked(reason.clone(), Some(metadata));
let kick_frame = frame_with_system_command(kick_cmd, Reliability::AtLeastOnce);
let parser = MessageParser::new(
conn_info.serialization_format,
conn_info.compression,
);
match parser.serialize(&kick_frame) {
Ok(kick_data) => {
if conflict_conn_id == connection_id {
error!(
"[DeviceHandler] ❌ 严重错误:尝试发送KICKED消息给新连接!跳过: connection_id={}",
connection_id
);
continue;
}
let mut c = conn.lock().await;
if let Err(e) = c.send(&kick_data).await {
error!(
"[DeviceHandler] 发送被踢消息失败给旧连接 {}: {}",
conflict_conn_id,
e
);
} else {
info!(
"[DeviceHandler] ✅ 已发送被踢消息给旧连接 {} (新连接: {}): {}",
conflict_conn_id,
connection_id,
reason
);
info!(
"[DeviceHandler] 💡 客户端收到 KICKED 消息后将主动断开连接"
);
}
}
Err(e) => {
error!(
"[DeviceHandler] 序列化被踢消息失败 (旧连接: {}): {}",
conflict_conn_id,
e
);
}
}
if conflict_conn_id == connection_id {
error!(
"[DeviceHandler] ❌ 严重错误:尝试从设备管理器移除新连接的设备!跳过: connection_id={}",
connection_id
);
continue;
}
match device_mgr.remove_device(user_id, conflict_conn_id).await {
Ok(_) => {
info!(
"[DeviceHandler] ✅ 旧连接的设备已从设备管理器移除: {} (新连接: {})",
conflict_conn_id,
connection_id
);
}
Err(e) => {
debug!(
"[DeviceHandler] 旧连接的设备 {} 已不存在于设备管理器: {}",
conflict_conn_id,
e
);
}
}
} else {
warn!(
"[DeviceHandler] 无法获取旧连接信息: {} (连接可能已断开)",
conflict_conn_id
);
}
}
info!(
"[DeviceHandler] ✅ 设备冲突处理完成: 新连接 {} 已保留,已向 {} 个旧连接发送 KICKED 消息",
connection_id,
conflict_connections.len()
);
} else {
warn!(
"[DeviceHandler] ⚠️ 无设备管理器,无法处理设备冲突: {} 个冲突连接",
conflict_connections.len()
);
}
info!(
"[DeviceHandler] 🎯 设备冲突处理完成: 新连接 {} 保留,已通知 {} 个旧连接断开(客户端将主动断开)",
connection_id,
conflict_connections.len()
);
Ok(DeviceConflictResult {
conflict_connections,
})
}