cyfs_util/util/
local_device_manager.rs

1use 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
19// 用以管理本地磁盘上的device文件和密钥
20struct 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    // 切换root
40    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    // 清空缓存
53    pub fn clear_cache(&mut self) {
54        self.list.clear();
55    }
56
57    // 直接添加一个device
58    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    // 获取desc,优先从缓存里面获取
83    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        // 加载密钥
140        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    // 切换root
176    pub fn set_root(&self, dir: &Path) {
177        self.0.lock().unwrap().set_root(dir)
178    }
179
180    // 清空缓存
181    pub fn clear_cache(&self) {
182        self.0.lock().unwrap().clear_cache()
183    }
184
185    // 直接添加一个device
186    pub fn add(&self, name: &str, device: DeviceInfo) -> BuckyResult<()> {
187        self.0.lock().unwrap().add(name, device)
188    }
189
190    // 获取desc,优先从缓存里面获取
191    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}