ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/salaryman/trunk/src/server/main.rs
Revision: 13
Committed: Wed Jul 9 20:24:36 2025 UTC (3 months ago) by yuzu
Original Path: trunk/src/smd/main.rs
File size: 3182 byte(s)
Log Message:
working network communication

File Contents

# User Rev Content
1 yuzu 13 mod context;
2 yuzu 11 mod endpoints;
3    
4 yuzu 9 use clap::Parser;
5 yuzu 13 use dropshot::{ApiDescription, ConfigLogging, ConfigLoggingLevel, ServerBuilder};
6 yuzu 12 use salaryman::service::{Service, ServiceConf};
7 yuzu 13 use schemars::JsonSchema;
8 yuzu 9 use serde::{Deserialize, Serialize};
9 yuzu 13 use tokio::{fs::read_to_string, sync::Mutex};
10 yuzu 9
11 yuzu 13 use std::{net::IpAddr, path::PathBuf, sync::Arc};
12 yuzu 9
13 yuzu 13 use crate::context::SalarymanDContext;
14     use crate::endpoints::{endpoint_get_config, endpoint_post_stdin};
15    
16 yuzu 9 #[derive(Parser, Debug)]
17     #[command(version, about, long_about = None)]
18     struct Args {
19     #[arg(
20     short,
21     long,
22     value_name = "FILE",
23     help = "config file override",
24     default_value = "salaryman.toml"
25     )]
26     config: PathBuf,
27     #[arg(
28     short,
29     long,
30     value_name = "ADDR",
31     help = "IP address to bind API to",
32     default_value = "127.0.0.1"
33     )]
34     address: IpAddr,
35     #[arg(
36     short,
37     long,
38     value_name = "PORT",
39     help = "TCP Port to bind API to",
40     default_value = "3080"
41     )]
42     port: u16,
43     }
44    
45 yuzu 13 #[derive(Serialize, Deserialize, JsonSchema, Clone, Debug)]
46     pub struct User {
47     pub username: String,
48     pub token: String,
49 yuzu 9 }
50    
51 yuzu 13 #[derive(Serialize, Deserialize, JsonSchema, Clone, Debug)]
52     pub struct Config {
53     pub address: Option<IpAddr>,
54     pub port: Option<u16>,
55     pub user: Vec<User>,
56     pub service: Vec<ServiceConf>,
57     }
58     impl Config {
59     pub fn new() -> Self {
60     Self {
61     address: None,
62     port: None,
63     user: Vec::new(),
64     service: Vec::new(),
65     }
66     }
67     }
68    
69 yuzu 11 async fn load_config(file: &PathBuf) -> Result<Config, Box<dyn std::error::Error>> {
70 yuzu 9 let s: String = match read_to_string(file).await {
71     Ok(s) => s,
72 yuzu 12 Err(_) => {
73     return Err(Box::new(std::io::Error::new(
74     std::io::ErrorKind::NotFound,
75     "cannot find config file",
76     )));
77     }
78 yuzu 9 };
79     match toml::from_str(s.as_str()) {
80 yuzu 11 Ok(c) => Ok(c),
81 yuzu 12 Err(_) => Err(Box::new(std::io::Error::new(
82     std::io::ErrorKind::Other,
83     "unable to parse config file",
84     ))),
85 yuzu 9 }
86     }
87    
88     #[tokio::main]
89     async fn main() -> Result<(), Box<dyn std::error::Error>> {
90     let args = Args::parse();
91 yuzu 11 let conf: Config = load_config(&args.config).await?;
92 yuzu 13 let mut services: Vec<Arc<Mutex<Service>>> = Vec::new();
93 yuzu 9 for i in 0..conf.service.len() {
94 yuzu 13 services.push(Arc::new(Mutex::new(Service::from_conf(&conf.service[i]))));
95 yuzu 9 if conf.service[i].autostart {
96 yuzu 13 let mut lock = services[i].lock().await;
97     lock.start().await?;
98     lock.scan_stdout().await?;
99     lock.scan_stderr().await?;
100     drop(lock);
101 yuzu 9 }
102     }
103 yuzu 13 let log_conf = ConfigLogging::StderrTerminal {
104     level: ConfigLoggingLevel::Info,
105     };
106     let log = log_conf.to_logger("smd")?;
107     let ctx = Arc::new(SalarymanDContext::from_parts(conf, services));
108     let mut api = ApiDescription::new();
109     api.register(endpoint_get_config).unwrap();
110     api.register(endpoint_post_stdin).unwrap();
111     let server = ServerBuilder::new(api, ctx.clone(), log).start()?;
112     server.await?;
113 yuzu 9 Ok(())
114     }