mirror of
https://github.com/mofeng-git/One-KVM.git
synced 2026-09-12 18:44:25 +08:00
fix: 修复扩展服务开启和自启动状态错误
This commit is contained in:
@@ -14,11 +14,33 @@ use tokio::sync::{Mutex, OwnedMutexGuard};
|
||||
#[derive(Debug, Clone, Copy, Default)]
|
||||
pub struct ConfigApplyOptions {
|
||||
pub force: bool,
|
||||
pub preserve_service_state: bool,
|
||||
pub runtime_only: bool,
|
||||
}
|
||||
|
||||
impl ConfigApplyOptions {
|
||||
pub const fn forced() -> Self {
|
||||
Self { force: true }
|
||||
Self {
|
||||
force: true,
|
||||
preserve_service_state: false,
|
||||
runtime_only: false,
|
||||
}
|
||||
}
|
||||
|
||||
pub const fn preserving_service_state() -> Self {
|
||||
Self {
|
||||
force: false,
|
||||
preserve_service_state: true,
|
||||
runtime_only: false,
|
||||
}
|
||||
}
|
||||
|
||||
pub const fn runtime_only() -> Self {
|
||||
Self {
|
||||
force: false,
|
||||
preserve_service_state: false,
|
||||
runtime_only: true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -449,13 +471,27 @@ pub async fn apply_audio_config(
|
||||
}
|
||||
|
||||
pub async fn enforce_stream_codec_constraints(state: &Arc<AppState>) -> Result<Option<String>> {
|
||||
let config = state.config.get();
|
||||
let config = state.runtime_third_party_config().await;
|
||||
let constraints = StreamCodecConstraints::from_config(&config);
|
||||
state
|
||||
.stream_manager
|
||||
.set_runtime_codec_constraints(constraints.clone())
|
||||
.await;
|
||||
let enforcement =
|
||||
enforce_constraints_with_stream_manager(&state.stream_manager, &constraints).await?;
|
||||
Ok(enforcement.message)
|
||||
}
|
||||
|
||||
async fn validate_runtime_candidate<T>(
|
||||
state: &Arc<AppState>,
|
||||
apply: impl FnOnce(&mut crate::config::AppConfig, T),
|
||||
config: T,
|
||||
) -> Result<()> {
|
||||
let mut candidate = state.runtime_third_party_config().await;
|
||||
apply(&mut candidate, config);
|
||||
validate_third_party_codec_compatibility(&candidate)
|
||||
}
|
||||
|
||||
fn validate_rustdesk_candidate(
|
||||
state: &Arc<AppState>,
|
||||
new_config: &crate::rustdesk::config::RustDeskConfig,
|
||||
@@ -485,12 +521,26 @@ pub async fn apply_rustdesk_config(
|
||||
) -> Result<()> {
|
||||
tracing::info!("Applying RustDesk config changes...");
|
||||
|
||||
validate_rustdesk_candidate(state, new_config)?;
|
||||
if options.runtime_only {
|
||||
validate_runtime_candidate(
|
||||
state,
|
||||
|candidate, config| candidate.rustdesk = config,
|
||||
new_config.clone(),
|
||||
)
|
||||
.await?;
|
||||
} else {
|
||||
validate_rustdesk_candidate(state, new_config)?;
|
||||
}
|
||||
|
||||
let mut rustdesk_guard = state.rustdesk.write().await;
|
||||
let mut credentials_to_save = None;
|
||||
let need_restart = options.force
|
||||
|| old_config.codec != new_config.codec
|
||||
|| old_config.rendezvous_server != new_config.rendezvous_server
|
||||
|| old_config.device_id != new_config.device_id
|
||||
|| old_config.device_password != new_config.device_password;
|
||||
|
||||
if !new_config.enabled {
|
||||
if !options.preserve_service_state && !new_config.enabled {
|
||||
if let Some(ref service) = *rustdesk_guard {
|
||||
service
|
||||
.stop()
|
||||
@@ -501,39 +551,51 @@ pub async fn apply_rustdesk_config(
|
||||
*rustdesk_guard = None;
|
||||
}
|
||||
|
||||
if new_config.enabled {
|
||||
let need_restart = options.force
|
||||
|| old_config.codec != new_config.codec
|
||||
|| old_config.rendezvous_server != new_config.rendezvous_server
|
||||
|| old_config.device_id != new_config.device_id
|
||||
|| old_config.device_password != new_config.device_password;
|
||||
|
||||
if !options.preserve_service_state && new_config.enabled {
|
||||
if rustdesk_guard.is_none() {
|
||||
tracing::info!("Initializing RustDesk service...");
|
||||
let service = crate::rustdesk::RustDeskService::new(
|
||||
let service = std::sync::Arc::new(crate::rustdesk::RustDeskService::new(
|
||||
new_config.clone(),
|
||||
state.stream_manager.clone(),
|
||||
state.hid.clone(),
|
||||
state.audio.clone(),
|
||||
);
|
||||
));
|
||||
*rustdesk_guard = Some(service.clone());
|
||||
service.start().await.map_err(|e| {
|
||||
AppError::Config(format!("Failed to start RustDesk service: {}", e))
|
||||
})?;
|
||||
tracing::info!("RustDesk service started with ID: {}", new_config.device_id);
|
||||
credentials_to_save = service.save_credentials();
|
||||
*rustdesk_guard = Some(std::sync::Arc::new(service));
|
||||
} else if need_restart {
|
||||
} else {
|
||||
if let Some(ref service) = *rustdesk_guard {
|
||||
service.restart(new_config.clone()).await.map_err(|e| {
|
||||
AppError::Config(format!("Failed to restart RustDesk service: {}", e))
|
||||
})?;
|
||||
tracing::info!(
|
||||
"RustDesk service restarted with ID: {}",
|
||||
new_config.device_id
|
||||
);
|
||||
if service.is_listening() {
|
||||
if need_restart {
|
||||
service.restart(new_config.clone()).await.map_err(|e| {
|
||||
AppError::Config(format!("Failed to restart RustDesk service: {}", e))
|
||||
})?;
|
||||
tracing::info!(
|
||||
"RustDesk service restarted with ID: {}",
|
||||
new_config.device_id
|
||||
);
|
||||
}
|
||||
} else {
|
||||
service.update_config(new_config.clone());
|
||||
service.start().await.map_err(|e| {
|
||||
AppError::Config(format!("Failed to start RustDesk service: {}", e))
|
||||
})?;
|
||||
}
|
||||
credentials_to_save = service.save_credentials();
|
||||
}
|
||||
}
|
||||
} else if options.preserve_service_state && need_restart {
|
||||
if let Some(ref service) = *rustdesk_guard {
|
||||
let mut runtime_config = new_config.clone();
|
||||
runtime_config.enabled = true;
|
||||
service.restart(runtime_config).await.map_err(|e| {
|
||||
AppError::Config(format!("Failed to restart RustDesk service: {}", e))
|
||||
})?;
|
||||
credentials_to_save = service.save_credentials();
|
||||
}
|
||||
}
|
||||
|
||||
drop(rustdesk_guard);
|
||||
@@ -567,11 +629,27 @@ pub async fn apply_vnc_config(
|
||||
) -> Result<()> {
|
||||
tracing::info!("Applying VNC config changes...");
|
||||
|
||||
validate_vnc_candidate(state, new_config)?;
|
||||
if options.runtime_only {
|
||||
validate_runtime_candidate(
|
||||
state,
|
||||
|candidate, config| candidate.vnc = config,
|
||||
new_config.clone(),
|
||||
)
|
||||
.await?;
|
||||
} else {
|
||||
validate_vnc_candidate(state, new_config)?;
|
||||
}
|
||||
|
||||
if new_config.enabled {
|
||||
let mut candidate = state.config.get().as_ref().clone();
|
||||
let runtime_config = state.runtime_third_party_config().await;
|
||||
let will_run = if options.preserve_service_state {
|
||||
runtime_config.vnc.enabled
|
||||
} else {
|
||||
new_config.enabled
|
||||
};
|
||||
if will_run {
|
||||
let mut candidate = runtime_config;
|
||||
candidate.vnc = new_config.clone();
|
||||
candidate.vnc.enabled = true;
|
||||
let constraints = StreamCodecConstraints::from_config(&candidate);
|
||||
match enforce_constraints_with_stream_manager(&state.stream_manager, &constraints).await {
|
||||
Ok(result) if result.changed => {
|
||||
@@ -588,37 +666,52 @@ pub async fn apply_vnc_config(
|
||||
}
|
||||
|
||||
let mut vnc_guard = state.vnc.write().await;
|
||||
let need_restart = options.force
|
||||
|| old_config.bind != new_config.bind
|
||||
|| old_config.port != new_config.port
|
||||
|| old_config.encoding != new_config.encoding
|
||||
|| old_config.password != new_config.password
|
||||
|| old_config.allow_one_client != new_config.allow_one_client;
|
||||
|
||||
if !new_config.enabled {
|
||||
if !options.preserve_service_state && !new_config.enabled {
|
||||
if let Some(ref service) = *vnc_guard {
|
||||
service.stop().await?;
|
||||
}
|
||||
*vnc_guard = None;
|
||||
}
|
||||
|
||||
if new_config.enabled {
|
||||
let need_restart = options.force
|
||||
|| old_config.bind != new_config.bind
|
||||
|| old_config.port != new_config.port
|
||||
|| old_config.encoding != new_config.encoding
|
||||
|| old_config.password != new_config.password
|
||||
|| old_config.allow_one_client != new_config.allow_one_client;
|
||||
|
||||
if !options.preserve_service_state && new_config.enabled {
|
||||
if vnc_guard.is_none() {
|
||||
let service = crate::vnc::VncService::new(
|
||||
let service = Arc::new(crate::vnc::VncService::new(
|
||||
new_config.clone(),
|
||||
state.stream_manager.clone(),
|
||||
state.hid.clone(),
|
||||
);
|
||||
));
|
||||
*vnc_guard = Some(service.clone());
|
||||
service.start().await?;
|
||||
*vnc_guard = Some(Arc::new(service));
|
||||
tracing::info!("VNC service started");
|
||||
} else if need_restart {
|
||||
} else {
|
||||
if let Some(ref service) = *vnc_guard {
|
||||
service.restart(new_config.clone()).await?;
|
||||
tracing::info!("VNC service restarted");
|
||||
if matches!(
|
||||
service.status().await,
|
||||
crate::vnc::VncServiceStatus::Running
|
||||
) {
|
||||
if need_restart {
|
||||
service.restart(new_config.clone()).await?;
|
||||
tracing::info!("VNC service restarted");
|
||||
}
|
||||
} else {
|
||||
service.update_config(new_config.clone()).await;
|
||||
service.start().await?;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if options.preserve_service_state && need_restart {
|
||||
if let Some(ref service) = *vnc_guard {
|
||||
let mut runtime_config = new_config.clone();
|
||||
runtime_config.enabled = true;
|
||||
service.restart(runtime_config).await?;
|
||||
}
|
||||
}
|
||||
|
||||
drop(vnc_guard);
|
||||
@@ -637,11 +730,28 @@ pub async fn apply_rtsp_config(
|
||||
) -> Result<()> {
|
||||
tracing::info!("Applying RTSP config changes...");
|
||||
|
||||
validate_rtsp_candidate(state, new_config)?;
|
||||
if options.runtime_only {
|
||||
validate_runtime_candidate(
|
||||
state,
|
||||
|candidate, config| candidate.rtsp = config,
|
||||
new_config.clone(),
|
||||
)
|
||||
.await?;
|
||||
} else {
|
||||
validate_rtsp_candidate(state, new_config)?;
|
||||
}
|
||||
|
||||
let mut rtsp_guard = state.rtsp.write().await;
|
||||
let need_restart = options.force
|
||||
|| old_config.bind != new_config.bind
|
||||
|| old_config.port != new_config.port
|
||||
|| old_config.path != new_config.path
|
||||
|| old_config.codec != new_config.codec
|
||||
|| old_config.username != new_config.username
|
||||
|| old_config.password != new_config.password
|
||||
|| old_config.allow_one_client != new_config.allow_one_client;
|
||||
|
||||
if !new_config.enabled {
|
||||
if !options.preserve_service_state && !new_config.enabled {
|
||||
if let Some(ref service) = *rtsp_guard {
|
||||
service
|
||||
.stop()
|
||||
@@ -651,27 +761,37 @@ pub async fn apply_rtsp_config(
|
||||
*rtsp_guard = None;
|
||||
}
|
||||
|
||||
if new_config.enabled {
|
||||
let need_restart = options.force
|
||||
|| old_config.bind != new_config.bind
|
||||
|| old_config.port != new_config.port
|
||||
|| old_config.path != new_config.path
|
||||
|| old_config.codec != new_config.codec
|
||||
|| old_config.username != new_config.username
|
||||
|| old_config.password != new_config.password
|
||||
|| old_config.allow_one_client != new_config.allow_one_client;
|
||||
|
||||
if !options.preserve_service_state && new_config.enabled {
|
||||
if rtsp_guard.is_none() {
|
||||
let service = RtspService::new(new_config.clone(), state.stream_manager.clone());
|
||||
let service = Arc::new(RtspService::new(
|
||||
new_config.clone(),
|
||||
state.stream_manager.clone(),
|
||||
));
|
||||
*rtsp_guard = Some(service.clone());
|
||||
service.start().await?;
|
||||
tracing::info!("RTSP service started");
|
||||
*rtsp_guard = Some(Arc::new(service));
|
||||
} else if need_restart {
|
||||
} else {
|
||||
if let Some(ref service) = *rtsp_guard {
|
||||
service.restart(new_config.clone()).await?;
|
||||
tracing::info!("RTSP service restarted");
|
||||
if matches!(
|
||||
service.status().await,
|
||||
crate::rtsp::RtspServiceStatus::Running
|
||||
) {
|
||||
if need_restart {
|
||||
service.restart(new_config.clone()).await?;
|
||||
tracing::info!("RTSP service restarted");
|
||||
}
|
||||
} else {
|
||||
service.update_config(new_config.clone()).await;
|
||||
service.start().await?;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if options.preserve_service_state && need_restart {
|
||||
if let Some(ref service) = *rtsp_guard {
|
||||
let mut runtime_config = new_config.clone();
|
||||
runtime_config.enabled = true;
|
||||
service.restart(runtime_config).await?;
|
||||
}
|
||||
}
|
||||
|
||||
drop(rtsp_guard);
|
||||
|
||||
Reference in New Issue
Block a user