cloudpub_client/plugins/onec/
mod.rs1use crate::config::{ClientConfig, ClientOpts, EnvConfig, ENV_CONFIG};
2use crate::plugins::httpd::{setup_httpd, start_httpd};
3use crate::plugins::Plugin;
4use crate::shell::{find, get_cache_dir, SubProcess};
5use anyhow::{bail, Context, Result};
6use async_trait::async_trait;
7use cloudpub_common::protocol::message::Message;
8use cloudpub_common::protocol::ServerEndpoint;
9use parking_lot::RwLock;
10use std::path::PathBuf;
11use std::sync::Arc;
12use tokio::sync::mpsc;
13use xml::escape::escape_str_attribute;
14
15#[cfg(target_os = "windows")]
16const WSAP_MODULE: &str = "wsap24.dll";
17
18#[cfg(all(unix, debug_assertions))]
19const WSAP_MODULE: &str = "wsap24t.so";
20
21#[cfg(all(unix, not(debug_assertions)))]
22const WSAP_MODULE: &str = "wsap24.so";
23
24pub const ONEC_SUBDIR: &str = "1c";
25const ONEC_CONFIG: &str = include_str!("httpd.conf");
26const DEFAULT_VRD: &str = include_str!("default.vrd");
27
28fn detect_platform() -> Option<EnvConfig> {
29 for patform in ENV_CONFIG.iter() {
30 if std::path::Path::new(&patform.1.home_1c).exists() {
31 return Some((*patform.1).clone());
32 }
33 }
34 None
35}
36
37fn check_enviroment(config: Arc<RwLock<ClientConfig>>) -> Result<EnvConfig> {
38 let env = if let Some(platform) = config.read().one_c_platform.as_ref() {
39 ENV_CONFIG.get(platform).cloned()
40 } else {
41 detect_platform()
42 };
43
44 let mut env = if let Some(env) = env {
45 env
46 } else {
47 bail!("Платформа 1C не найдена, укажите ее битность (x32/x64) и путь в настройках");
48 };
49
50 if let Some(one_c_home) = &config.read().one_c_home {
51 env.home_1c = PathBuf::from(one_c_home);
52 }
53
54 if !std::path::Path::new(&env.home_1c).exists() {
55 bail!(
56 "Путь до платформы 1C ({}) не найден, укажите его в настройках",
57 env.home_1c.to_str().unwrap()
58 );
59 }
60 Ok(env)
61}
62
63pub struct OneCPlugin;
64
65#[async_trait]
66impl Plugin for OneCPlugin {
67 fn name(&self) -> &'static str {
68 "onec"
69 }
70
71 async fn setup(
72 &self,
73 config: &Arc<RwLock<ClientConfig>>,
74 _opts: &ClientOpts,
75 command_rx: &mut mpsc::Receiver<Message>,
76 result_tx: &mpsc::Sender<Message>,
77 ) -> Result<()> {
78 let env = check_enviroment(config.clone())?;
79 setup_httpd(config, command_rx, result_tx, env).await
80 }
81
82 async fn publish(
83 &self,
84 endpoint: &ServerEndpoint,
85 config: &Arc<RwLock<ClientConfig>>,
86 _opts: &ClientOpts,
87 result_tx: &mpsc::Sender<Message>,
88 ) -> Result<SubProcess> {
89 let env = check_enviroment(config.clone())?;
90
91 let one_c_publish_dir = config
92 .read()
93 .one_c_publish_dir
94 .as_ref()
95 .map(PathBuf::from)
96 .unwrap_or_else(|| get_cache_dir(ONEC_SUBDIR).unwrap());
97
98 let publish_dir = one_c_publish_dir.join(&endpoint.guid);
99
100 std::fs::create_dir_all(publish_dir.clone()).context("Can't create publish dir")?;
101
102 let mut default_vrd = publish_dir.clone();
103 default_vrd.push("default.vrd");
104
105 let wsap_error = format!(
106 "Модуль {} на найден в {}. Проверьте настройки и убедитесь что у вас установлены модули расширения веб-сервера для 1С", WSAP_MODULE, &env.home_1c.to_str().unwrap());
107
108 let wsap = if let Some(wsap) =
109 find(&env.home_1c, &PathBuf::from(WSAP_MODULE)).context(wsap_error.clone())?
110 {
111 wsap
112 } else {
113 bail!(wsap_error);
114 };
115
116 let local_addr = endpoint.client.as_ref().unwrap().local_addr.clone();
117 let ib = if std::path::Path::new(&local_addr).exists() {
119 format!("File=\"{}\"", local_addr)
120 } else {
121 local_addr.clone()
122 };
123
124 let vrd_config = DEFAULT_VRD.replace("[[IB]]", &escape_str_attribute(&ib));
125
126 if !default_vrd.exists() {
127 std::fs::write(&default_vrd, vrd_config).context("Ошибка записи default.vrd")?;
128 }
129
130 let httpd_config = ONEC_CONFIG.replace("[[WSAP_MODULE]]", wsap.to_str().unwrap());
131
132 start_httpd(
133 endpoint,
134 &httpd_config,
135 ONEC_SUBDIR,
136 publish_dir.to_str().unwrap(),
137 env,
138 result_tx.clone(),
139 )
140 .await
141 }
142}