ant_service_management/
daemon.rs

1// Copyright (C) 2024 MaidSafe.net limited.
2//
3// This SAFE Network Software is licensed to you under The General Public License (GPL), version 3.
4// Unless required by applicable law or agreed to in writing, the SAFE Network Software distributed
5// under the GPL Licence is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
6// KIND, either express or implied. Please review the Licences for the specific language governing
7// permissions and limitations relating to use of the SAFE Network Software.
8
9use crate::{
10    ServiceStateActions, ServiceStatus, UpgradeOptions,
11    control::ServiceControl,
12    error::{Error, Result},
13};
14use async_trait::async_trait;
15use serde::{Deserialize, Serialize};
16use service_manager::ServiceInstallCtx;
17use std::{ffi::OsString, net::SocketAddr, path::PathBuf, sync::Arc};
18use tokio::sync::RwLock;
19
20#[derive(Clone, Debug, Serialize, Deserialize)]
21pub struct DaemonServiceData {
22    pub daemon_path: PathBuf,
23    pub endpoint: Option<SocketAddr>,
24    pub pid: Option<u32>,
25    pub service_name: String,
26    pub status: ServiceStatus,
27    pub version: String,
28}
29
30pub struct DaemonService {
31    pub service_data: Arc<RwLock<DaemonServiceData>>,
32    pub service_control: Box<dyn ServiceControl + Send>,
33}
34
35impl DaemonService {
36    pub fn new(
37        service_data: Arc<RwLock<DaemonServiceData>>,
38        service_control: Box<dyn ServiceControl + Send>,
39    ) -> DaemonService {
40        DaemonService {
41            service_data,
42            service_control,
43        }
44    }
45}
46
47#[async_trait]
48impl ServiceStateActions for DaemonService {
49    async fn bin_path(&self) -> PathBuf {
50        self.service_data.read().await.daemon_path.clone()
51    }
52
53    async fn build_upgrade_install_context(
54        &self,
55        _options: UpgradeOptions,
56    ) -> Result<ServiceInstallCtx> {
57        let (address, port) = self
58            .service_data
59            .read()
60            .await
61            .endpoint
62            .ok_or_else(|| {
63                error!("Daemon endpoint not set in the service_data");
64                Error::DaemonEndpointNotSet
65            })
66            .map(|e| (e.ip().to_string(), e.port().to_string()))?;
67
68        let install_ctx = ServiceInstallCtx {
69            args: vec![
70                OsString::from("--port"),
71                OsString::from(port),
72                OsString::from("--address"),
73                OsString::from(address),
74            ],
75            autostart: true,
76            contents: None,
77            environment: None,
78            label: self.service_data.read().await.service_name.parse()?,
79            program: self.service_data.read().await.daemon_path.clone(),
80            username: None,
81            working_directory: None,
82            disable_restart_on_failure: false,
83        };
84        Ok(install_ctx)
85    }
86
87    async fn data_dir_path(&self) -> PathBuf {
88        PathBuf::new()
89    }
90
91    async fn is_user_mode(&self) -> bool {
92        // The daemon service should never run in user mode.
93        false
94    }
95
96    async fn log_dir_path(&self) -> PathBuf {
97        PathBuf::new()
98    }
99
100    async fn name(&self) -> String {
101        self.service_data.read().await.service_name.clone()
102    }
103
104    async fn pid(&self) -> Option<u32> {
105        self.service_data.read().await.pid
106    }
107
108    async fn on_remove(&self) {
109        self.service_data.write().await.status = ServiceStatus::Removed;
110    }
111
112    async fn on_start(&self, pid: Option<u32>, _full_refresh: bool) -> Result<()> {
113        self.service_data.write().await.pid = pid;
114        self.service_data.write().await.status = ServiceStatus::Running;
115        Ok(())
116    }
117
118    async fn on_stop(&self) -> Result<()> {
119        self.service_data.write().await.pid = None;
120        self.service_data.write().await.status = ServiceStatus::Stopped;
121        Ok(())
122    }
123
124    async fn set_version(&self, version: &str) {
125        self.service_data.write().await.version = version.to_string();
126    }
127
128    async fn status(&self) -> ServiceStatus {
129        self.service_data.read().await.status.clone()
130    }
131
132    async fn version(&self) -> String {
133        self.service_data.read().await.version.clone()
134    }
135}