cyfs_util/util/
local_device_manager.rs1use cyfs_base::{
2 BuckyError, BuckyErrorCode, BuckyResult, Device, FileDecoder, NamedObject, PrivateKey,
3 StandardObject,
4};
5
6use std::collections::{hash_map::Entry, HashMap};
7use std::path::{Path, PathBuf};
8use std::sync::{Arc, Mutex};
9
10use lazy_static::lazy_static;
11
12#[derive(Clone, Debug)]
13pub struct DeviceInfo {
14 pub device: Device,
15
16 pub private_key: Option<PrivateKey>,
17}
18
19struct LocalDeviceManagerImpl {
21 root: PathBuf,
22 list: HashMap<String, DeviceInfo>,
23}
24
25impl LocalDeviceManagerImpl {
26 fn new() -> Self {
27 let root = crate::get_cyfs_root_path().join("etc").join("desc");
28
29 Self {
30 root,
31 list: HashMap::new(),
32 }
33 }
34
35 pub fn get_root(&self) -> PathBuf {
36 self.root.clone()
37 }
38
39 pub fn set_root(&mut self, dir: &Path) {
41 if self.root != dir {
42 info!(
43 "change ood desc dir: {} -> {}",
44 self.root.display(),
45 dir.display()
46 );
47 self.root = dir.to_owned();
48 self.list.clear();
49 }
50 }
51
52 pub fn clear_cache(&mut self) {
54 self.list.clear();
55 }
56
57 pub fn add(&mut self, name: &str, device: DeviceInfo) -> BuckyResult<()> {
59 match self.list.entry(name.to_owned()) {
60 Entry::Occupied(_o) => {
61 error!(
62 "direct add new device but already exists! id={}, device={}",
63 name,
64 device.device.desc().device_id()
65 );
66
67 Err(BuckyError::from(BuckyErrorCode::AlreadyExists))
68 }
69 Entry::Vacant(v) => {
70 info!(
71 "direct add new device info: id={}, device={}",
72 name,
73 device.device.desc().device_id()
74 );
75 v.insert(device);
76
77 Ok(())
78 }
79 }
80 }
81
82 pub fn load(&mut self, name: &str) -> BuckyResult<DeviceInfo> {
84 if let Some(desc) = self.list.get(name) {
85 return Ok(desc.clone());
86 }
87
88 let desc = self.load_direct(name)?;
89 let ret = desc.clone();
90 self.list.insert(name.to_owned(), desc);
91
92 Ok(ret)
93 }
94
95 pub fn load_direct(&self, name: &str) -> BuckyResult<DeviceInfo> {
96 let desc_file_name = format!("{}.desc", name);
97 let desc_file = self.root.join(desc_file_name);
98
99 if !desc_file.is_file() {
100 let msg = format!("desc file not exists! file={}", desc_file.display());
101 error!("{}", msg);
102
103 return Err(BuckyError::new(BuckyErrorCode::NotFound, msg));
104 }
105
106 let mut buf: Vec<u8> = Vec::new();
107 let ret = StandardObject::decode_from_file(desc_file.as_path(), &mut buf);
108 if let Err(e) = ret {
109 let msg = format!("load desc file error! file={}, {}", desc_file.display(), e,);
110 error!("{}", msg);
111 return Err(BuckyError::new(BuckyErrorCode::InvalidFormat, msg));
112 }
113
114 info!("load desc success! file={}", desc_file.display());
115 let (desc, _) = ret.unwrap();
116
117 let device;
118 match desc {
119 StandardObject::Device(p) => {
120 device = p;
121 }
122 other @ _ => {
123 let msg = format!(
124 "unsupport desc type! file={}, desc={:?}",
125 desc_file.display(),
126 other
127 );
128 error!("{}", msg);
129
130 return Err(BuckyError::new(BuckyErrorCode::UnSupport, msg));
131 }
132 };
133
134 let mut device_info = DeviceInfo {
135 device,
136 private_key: None,
137 };
138
139 let sec_file_name = format!("{}.sec", name);
141 let sec_file = self.root.join(sec_file_name);
142 if sec_file.is_file() {
143 let mut buf: Vec<u8> = Vec::new();
144 let ret = PrivateKey::decode_from_file(sec_file.as_path(), &mut buf);
145 if let Err(e) = ret {
146 let msg = format!("load sec file error! file={}, {}", sec_file.display(), e,);
147 error!("{}", msg);
148 return Err(BuckyError::new(BuckyErrorCode::InvalidFormat, msg));
149 }
150
151 info!("load sec success! file={}", sec_file.display());
152
153 let (private_key, _) = ret.unwrap();
154 device_info.private_key = Some(private_key);
155 } else {
156 warn!("sec file not exists! file={}", sec_file.display());
157 }
158
159 Ok(device_info)
160 }
161}
162
163#[derive(Clone)]
164pub struct LocalDeviceManager(Arc<Mutex<LocalDeviceManagerImpl>>);
165
166impl LocalDeviceManager {
167 pub fn new() -> Self {
168 Self(Arc::new(Mutex::new(LocalDeviceManagerImpl::new())))
169 }
170
171 pub fn get_root(&self) -> PathBuf {
172 self.0.lock().unwrap().get_root()
173 }
174
175 pub fn set_root(&self, dir: &Path) {
177 self.0.lock().unwrap().set_root(dir)
178 }
179
180 pub fn clear_cache(&self) {
182 self.0.lock().unwrap().clear_cache()
183 }
184
185 pub fn add(&self, name: &str, device: DeviceInfo) -> BuckyResult<()> {
187 self.0.lock().unwrap().add(name, device)
188 }
189
190 pub fn load(&self, name: &str) -> BuckyResult<DeviceInfo> {
192 self.0.lock().unwrap().load(name)
193 }
194
195 pub fn load_direct(&self, name: &str) -> BuckyResult<DeviceInfo> {
196 self.0.lock().unwrap().load_direct(name)
197 }
198}
199
200lazy_static! {
201 pub static ref LOCAL_DEVICE_MANAGER: LocalDeviceManager = LocalDeviceManager::new();
202}