refactor: 升级依赖版本并优化构建系统

- 升级核心依赖 (axum 0.8, tower-http 0.6, alsa 0.11 等)
- 简化交叉编译配置,切换至 Debian 11 提高兼容性
- 新增 Debian 包打包支持 (debuerreotype 模板)
- 移除独立的 mjpeg 解码器,简化视频模块
- 静态链接 libx264/libx265/libopus 到二进制
This commit is contained in:
mofeng-git
2026-01-10 10:59:00 +08:00
parent 3fa91772f0
commit e670f1ffd1
46 changed files with 893 additions and 1156 deletions

View File

@@ -57,7 +57,7 @@ async fn handle_audio_socket(socket: WebSocket, state: Arc<AppState>) {
// Send error message before closing
let _ = sender
.send(Message::Text(
r#"{"error": "Audio not streaming"}"#.to_string(),
r#"{"error": "Audio not streaming"}"#.to_string().into(),
))
.await;
return;
@@ -83,7 +83,7 @@ async fn handle_audio_socket(socket: WebSocket, state: Arc<AppState>) {
match opus_result {
Ok(frame) => {
let binary = encode_audio_packet(&frame, stream_start);
if sender.send(Message::Binary(binary)).await.is_err() {
if sender.send(Message::Binary(binary.into())).await.is_err() {
debug!("Failed to send audio frame, client disconnected");
break;
}
@@ -133,7 +133,7 @@ async fn handle_audio_socket(socket: WebSocket, state: Arc<AppState>) {
// Periodic ping to keep connection alive (using interval)
_ = ping_interval.tick() => {
if sender.send(Message::Ping(vec![])).await.is_err() {
if sender.send(Message::Ping(vec![].into())).await.is_err() {
warn!("Failed to send ping, disconnecting");
break;
}

View File

@@ -82,7 +82,7 @@ async fn handle_terminal_websocket(client_ws: WebSocket, query_string: String) {
let client_to_ttyd = tokio::spawn(async move {
while let Some(msg) = client_rx.next().await {
let ttyd_msg = match msg {
Ok(AxumMessage::Text(text)) => TungsteniteMessage::Text(text),
Ok(AxumMessage::Text(text)) => TungsteniteMessage::Text(text.to_string().into()),
Ok(AxumMessage::Binary(data)) => TungsteniteMessage::Binary(data),
Ok(AxumMessage::Ping(data)) => TungsteniteMessage::Ping(data),
Ok(AxumMessage::Pong(data)) => TungsteniteMessage::Pong(data),
@@ -103,7 +103,7 @@ async fn handle_terminal_websocket(client_ws: WebSocket, query_string: String) {
let ttyd_to_client = tokio::spawn(async move {
while let Some(msg) = ttyd_rx.next().await {
let client_msg = match msg {
Ok(TungsteniteMessage::Text(text)) => AxumMessage::Text(text),
Ok(TungsteniteMessage::Text(text)) => AxumMessage::Text(text.to_string().into()),
Ok(TungsteniteMessage::Binary(data)) => AxumMessage::Binary(data),
Ok(TungsteniteMessage::Ping(data)) => AxumMessage::Ping(data),
Ok(TungsteniteMessage::Pong(data)) => AxumMessage::Pong(data),

View File

@@ -70,7 +70,7 @@ pub fn create_router(state: Arc<AppState>) -> Router {
// Audio WebSocket endpoint
.route("/ws/audio", any(audio_ws_handler))
// User can change their own password (handler will check ownership)
.route("/users/:id/password", post(handlers::change_user_password));
.route("/users/{id}/password", post(handlers::change_user_password));
// Admin-only routes (require admin privileges)
let admin_routes = Router::new()
@@ -106,8 +106,8 @@ pub fn create_router(state: Arc<AppState>) -> Router {
.route("/msd/images", get(handlers::msd_images_list))
.route("/msd/images/download", post(handlers::msd_image_download))
.route("/msd/images/download/cancel", post(handlers::msd_image_download_cancel))
.route("/msd/images/:id", get(handlers::msd_image_get))
.route("/msd/images/:id", delete(handlers::msd_image_delete))
.route("/msd/images/{id}", get(handlers::msd_image_get))
.route("/msd/images/{id}", delete(handlers::msd_image_delete))
.route("/msd/connect", post(handlers::msd_connect))
.route("/msd/disconnect", post(handlers::msd_disconnect))
// MSD Virtual Drive endpoints
@@ -115,9 +115,9 @@ pub fn create_router(state: Arc<AppState>) -> Router {
.route("/msd/drive", delete(handlers::msd_drive_delete))
.route("/msd/drive/init", post(handlers::msd_drive_init))
.route("/msd/drive/files", get(handlers::msd_drive_files))
.route("/msd/drive/files/*path", get(handlers::msd_drive_download))
.route("/msd/drive/files/*path", delete(handlers::msd_drive_file_delete))
.route("/msd/drive/mkdir/*path", post(handlers::msd_drive_mkdir))
.route("/msd/drive/files/{*path}", get(handlers::msd_drive_download))
.route("/msd/drive/files/{*path}", delete(handlers::msd_drive_file_delete))
.route("/msd/drive/mkdir/{*path}", post(handlers::msd_drive_mkdir))
// ATX (Power Control) endpoints
.route("/atx/status", get(handlers::atx_status))
.route("/atx/power", post(handlers::atx_power))
@@ -127,14 +127,14 @@ pub fn create_router(state: Arc<AppState>) -> Router {
// User management endpoints
.route("/users", get(handlers::list_users))
.route("/users", post(handlers::create_user))
.route("/users/:id", put(handlers::update_user))
.route("/users/:id", delete(handlers::delete_user))
.route("/users/{id}", put(handlers::update_user))
.route("/users/{id}", delete(handlers::delete_user))
// Extension management endpoints
.route("/extensions", get(handlers::extensions::list_extensions))
.route("/extensions/:id", get(handlers::extensions::get_extension))
.route("/extensions/:id/start", post(handlers::extensions::start_extension))
.route("/extensions/:id/stop", post(handlers::extensions::stop_extension))
.route("/extensions/:id/logs", get(handlers::extensions::get_extension_logs))
.route("/extensions/{id}", get(handlers::extensions::get_extension))
.route("/extensions/{id}/start", post(handlers::extensions::start_extension))
.route("/extensions/{id}/stop", post(handlers::extensions::stop_extension))
.route("/extensions/{id}/logs", get(handlers::extensions::get_extension_logs))
.route("/extensions/ttyd/config", patch(handlers::extensions::update_ttyd_config))
.route("/extensions/ttyd/status", get(handlers::extensions::get_ttyd_status))
.route("/extensions/gostc/config", patch(handlers::extensions::update_gostc_config))
@@ -143,7 +143,7 @@ pub fn create_router(state: Arc<AppState>) -> Router {
.route("/terminal", get(handlers::terminal::terminal_index))
.route("/terminal/", get(handlers::terminal::terminal_index))
.route("/terminal/ws", get(handlers::terminal::terminal_ws))
.route("/terminal/*path", get(handlers::terminal::terminal_proxy))
.route("/terminal/{*path}", get(handlers::terminal::terminal_proxy))
// Apply admin middleware to all admin routes
.layer(middleware::from_fn_with_state(state.clone(), require_admin));

View File

@@ -45,7 +45,7 @@ where
{
Router::new()
.route("/", get(index_handler))
.route("/*path", get(static_handler))
.route("/{*path}", get(static_handler))
}
/// Serve index.html for root path

View File

@@ -79,7 +79,7 @@ async fn handle_socket(socket: WebSocket, state: Arc<AppState>) {
if !device_info_sent && !subscribed_topics.is_empty() {
let device_info = state.get_device_info().await;
if let Ok(json) = serialize_event(&device_info) {
if sender.send(Message::Text(json)).await.is_err() {
if sender.send(Message::Text(json.into())).await.is_err() {
warn!("Failed to send device info to client");
break;
}
@@ -113,7 +113,7 @@ async fn handle_socket(socket: WebSocket, state: Arc<AppState>) {
// Filter event based on subscribed topics
if should_send_event(&event, &subscribed_topics) {
if let Ok(json) = serialize_event(&event) {
if sender.send(Message::Text(json)).await.is_err() {
if sender.send(Message::Text(json.into())).await.is_err() {
warn!("Failed to send event to client, disconnecting");
break;
}
@@ -127,7 +127,7 @@ async fn handle_socket(socket: WebSocket, state: Arc<AppState>) {
message: format!("Lagged by {} events", n),
};
if let Ok(json) = serialize_event(&error_event) {
let _ = sender.send(Message::Text(json)).await;
let _ = sender.send(Message::Text(json.into())).await;
}
}
Err(_) => {
@@ -139,7 +139,7 @@ async fn handle_socket(socket: WebSocket, state: Arc<AppState>) {
// Heartbeat
_ = heartbeat_interval.tick() => {
if sender.send(Message::Ping(vec![])).await.is_err() {
if sender.send(Message::Ping(vec![].into())).await.is_err() {
warn!("Failed to send ping, disconnecting");
break;
}