Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/cli/src/tunnels/service.rs
3314 views
1
/*---------------------------------------------------------------------------------------------
2
* Copyright (c) Microsoft Corporation. All rights reserved.
3
* Licensed under the MIT License. See License.txt in the project root for license information.
4
*--------------------------------------------------------------------------------------------*/
5
6
use std::path::{Path, PathBuf};
7
8
use async_trait::async_trait;
9
10
use crate::log;
11
use crate::state::LauncherPaths;
12
use crate::util::errors::{wrap, AnyError};
13
use crate::util::io::{tailf, TailEvent};
14
15
pub const SERVICE_LOG_FILE_NAME: &str = "tunnel-service.log";
16
17
#[async_trait]
18
pub trait ServiceContainer: Send {
19
async fn run_service(
20
&mut self,
21
log: log::Logger,
22
launcher_paths: LauncherPaths,
23
) -> Result<(), AnyError>;
24
}
25
26
#[async_trait]
27
pub trait ServiceManager {
28
/// Registers the current executable as a service to run with the given set
29
/// of arguments.
30
async fn register(&self, exe: PathBuf, args: &[&str]) -> Result<(), AnyError>;
31
32
/// Runs the service using the given handle. The executable *must not* take
33
/// any action which may fail prior to calling this to ensure service
34
/// states may update.
35
async fn run(
36
self,
37
launcher_paths: LauncherPaths,
38
handle: impl 'static + ServiceContainer,
39
) -> Result<(), AnyError>;
40
41
/// Show logs from the running service to standard out.
42
async fn show_logs(&self) -> Result<(), AnyError>;
43
44
/// Gets whether the tunnel service is installed.
45
async fn is_installed(&self) -> Result<bool, AnyError>;
46
47
/// Unregisters the current executable as a service.
48
async fn unregister(&self) -> Result<(), AnyError>;
49
}
50
51
#[cfg(target_os = "windows")]
52
pub type ServiceManagerImpl = super::service_windows::WindowsService;
53
54
#[cfg(target_os = "linux")]
55
pub type ServiceManagerImpl = super::service_linux::SystemdService;
56
57
#[cfg(target_os = "macos")]
58
pub type ServiceManagerImpl = super::service_macos::LaunchdService;
59
60
#[allow(unreachable_code)]
61
#[allow(unused_variables)]
62
pub fn create_service_manager(log: log::Logger, paths: &LauncherPaths) -> ServiceManagerImpl {
63
#[cfg(target_os = "macos")]
64
{
65
super::service_macos::LaunchdService::new(log, paths)
66
}
67
#[cfg(target_os = "windows")]
68
{
69
super::service_windows::WindowsService::new(log, paths)
70
}
71
#[cfg(target_os = "linux")]
72
{
73
super::service_linux::SystemdService::new(log, paths.clone())
74
}
75
}
76
77
#[allow(dead_code)] // unused on Linux
78
pub(crate) async fn tail_log_file(log_file: &Path) -> Result<(), AnyError> {
79
if !log_file.exists() {
80
println!("The tunnel service has not started yet.");
81
return Ok(());
82
}
83
84
let file = std::fs::File::open(log_file).map_err(|e| wrap(e, "error opening log file"))?;
85
let mut rx = tailf(file, 20);
86
while let Some(line) = rx.recv().await {
87
match line {
88
TailEvent::Line(l) => print!("{l}"),
89
TailEvent::Reset => println!("== Tunnel service restarted =="),
90
TailEvent::Err(e) => return Err(wrap(e, "error reading log file").into()),
91
}
92
}
93
94
Ok(())
95
}
96
97