1use super::*;
2
3pub struct Host {
4 members: Arc<Members>,
5 pairing: Mutex<Option<Live>>,
6}
7
8#[allow(clippy::type_complexity)]
9struct Members {
10 me: Hello,
11 notebook: String,
12 reach: Option<Reach>,
13 relay: Option<String>,
14 sharing: Mutex<Sharing>,
15 changes: Mutex<()>,
16 pending: Mutex<BTreeMap<[u8; 16], (Arc<Hello>, Line)>>,
17 access: Mutex<HashMap<[u8; 16], Live>>,
18 room: Mutex<Option<Live>>,
19 served: Arc<Served>,
20 events: Arc<dyn Fn() + Send + Sync>,
21 keep: Box<dyn Fn(&Sharing) -> io::Result<()> + Send + Sync>,
22}
23
24impl Host {
25 /// Shares a notebook, keeping every credential change before granting or revoking access.
26 #[allow(clippy::too_many_arguments)]
27 pub fn start(
28 storage: Box<dyn Storage>,
29 me: Hello,
30 sharing: Sharing,
31 notebook: &str,
32 reach: Option<Reach>,
33 relay: Option<&str>,
34 events: impl Fn() + Send + Sync + 'static,
35 keep: impl Fn(&Sharing) -> io::Result<()> + Send + Sync + 'static,
36 ) -> io::Result<Self> {
37 keep(&sharing)?;
38 let members = Arc::new(Members {
39 me,
40 notebook: notebook.to_owned(),
41 reach,
42 relay: relay.map(str::to_owned),
43 sharing: Mutex::new(sharing),
44 changes: Mutex::default(),
45 pending: Mutex::default(),
46 access: Mutex::default(),
47 room: Mutex::default(),
48 served: Arc::new(Served {
49 storage,
50 images: Mutex::default(),
51 snapshots: Mutex::default(),
52 puts: Mutex::default(),
53 guests: Mutex::default(),
54 writers: Mutex::default(),
55 host: Mutex::default(),
56 room: Mutex::default(),
57 }),
58 events: Arc::new(events),
59 keep: Box::new(keep),
60 });
61 let sharing = members.sharing.lock().unwrap().clone();
62 members.presence(sharing.secret)?;
63 for device in &sharing.members {
64 members.open(device.secret)?;
65 }
66 let pairing = Mutex::new(Some(members.pair(&sharing)?));
67 Ok(Self { members, pairing })
68 }
69
70 pub fn code(&self) -> Option<String> {
71 let mut pairing = self.pairing.lock().unwrap();
72 let pairing = pairing.as_mut()?;
73 let mut sharing = self.members.sharing.lock().unwrap();
74 if pairing.burned() {
75 let mut next = sharing.clone();
76 next.code = super::super::code::secret().ok()?;
77 (self.members.keep)(&next).ok()?;
78 *pairing = self.members.pair(&next).ok()?;
79 *sharing = next;
80 }
81 let code = pairing.code();
82 if let Some(code) = &code
83 && *code != sharing.code
84 {
85 let mut next = sharing.clone();
86 next.code = code.clone();
87 (self.members.keep)(&next).ok()?;
88 *sharing = next;
89 }
90 code
91 }
92
93 pub fn sharing(&self) -> Sharing {
94 self.code();
95 self.members.sharing.lock().unwrap().clone()
96 }
97
98 pub fn relayed(&self) -> Relayed {
99 self.pairing
100 .lock()
101 .unwrap()
102 .as_ref()
103 .map_or(Relayed::Unknown, Live::relayed)
104 }
105
106 pub fn guests(&self) -> Vec<Peer> {
107 self.members
108 .room
109 .lock()
110 .unwrap()
111 .as_ref()
112 .map(Live::peers)
113 .unwrap_or_default()
114 }
115
116 pub fn devices(&self) -> Vec<(Device, bool)> {
117 let sharing = self.members.sharing.lock().unwrap();
118 let access = self.members.access.lock().unwrap();
119 sharing
120 .members
121 .iter()
122 .map(|device| {
123 let connected = access
124 .get(&device.secret)
125 .is_some_and(|live| !live.peers().is_empty());
126 (device.clone(), connected)
127 })
128 .collect()
129 }
130
131 pub fn requests(&self) -> Vec<Arc<Hello>> {
132 self.members
133 .pending
134 .lock()
135 .unwrap()
136 .values()
137 .map(|(hello, _)| Arc::clone(hello))
138 .collect()
139 }
140
141 pub fn approve(&self, approve: bool) -> io::Result<()> {
142 let mut sharing = self.members.sharing.lock().unwrap();
143 let mut next = sharing.clone();
144 next.approve = approve;
145 (self.members.keep)(&next)?;
146 *sharing = next;
147 drop(sharing);
148 if !approve {
149 for hello in self.requests() {
150 self.allow(&hello.peer)?;
151 }
152 }
153 (self.members.events)();
154 Ok(())
155 }
156
157 pub fn allow(&self, peer: &[u8; 16]) -> io::Result<()> {
158 let pending = self.members.pending.lock().unwrap().remove(peer);
159 if let Some((hello, line)) = pending {
160 if let Err(error) = self.members.grant(&hello, &line) {
161 self.members
162 .pending
163 .lock()
164 .unwrap()
165 .insert(*peer, (hello, line));
166 return Err(error);
167 }
168 (self.members.events)();
169 }
170 Ok(())
171 }
172
173 pub fn decline(&self, peer: &[u8; 16]) {
174 if let Some((_, line)) = self.members.pending.lock().unwrap().remove(peer) {
175 let _ = line.send(kind::APPROVAL, &wire::Approval::Declined);
176 (self.members.events)();
177 }
178 }
179
180 pub fn remove(&self, secret: &[u8; 16]) -> io::Result<()> {
181 let _change = self.members.changes.lock().unwrap();
182 let mut sharing = self.members.sharing.lock().unwrap();
183 if !sharing
184 .members
185 .iter()
186 .any(|device| device.secret == *secret)
187 {
188 return Ok(());
189 }
190 let mut next = sharing.clone();
191 next.members.retain(|device| device.secret != *secret);
192 getrandom::fill(&mut next.secret)
193 .map_err(|_| io::Error::other("System random source failed"))?;
194 next.code = super::super::code::secret()?;
195 (self.members.keep)(&next)?;
196 *sharing = next.clone();
197 drop(sharing);
198 let removed = self.members.access.lock().unwrap().remove(secret);
199 if let Some(removed) = removed {
200 for peer in removed.peers() {
201 self.members.served.forget(&peer.hello.peer);
202 }
203 removed.leave("removed");
204 }
205 self.members.presence(next.secret)?;
206 *self.pairing.lock().unwrap() = Some(self.members.pair(&next)?);
207 let access = self.members.access.lock().unwrap();
208 for device in &next.members {
209 if let Some(live) = access.get(&device.secret) {
210 live.sender().send(
211 kind::WELCOME,
212 &self.members.welcome(&next, device.secret),
213 None,
214 );
215 }
216 }
217 (self.members.events)();
218 Ok(())
219 }
220
221 pub fn set_presence(&self, presence: Presence) {
222 if let Some(room) = &*self.members.room.lock().unwrap() {
223 room.set_presence(presence);
224 }
225 }
226
227 pub fn on_changed(&self, listener: crate::session::Listener) {
228 *self.members.served.host.lock().unwrap() = Some(listener);
229 }
230
231 pub fn touched(&self, paths: &[String]) {
232 for path in paths {
233 self.members.served.changed_here(path);
234 }
235 self.members.served.tell(paths);
236 }
237
238 pub fn stop(&self) {
239 let _change = self.members.changes.lock().unwrap();
240 drop(self.pairing.lock().unwrap().take());
241 self.members.pending.lock().unwrap().clear();
242 let access = std::mem::take(&mut *self.members.access.lock().unwrap());
243 for (_, live) in access {
244 live.leave(STOPPED);
245 }
246 drop(self.members.room.lock().unwrap().take());
247 }
248}
249
250impl Members {
251 fn welcome(&self, sharing: &Sharing, secret: [u8; 16]) -> Welcome {
252 Welcome {
253 share: sharing.share,
254 secret,
255 room: sharing.secret,
256 notebook: self.notebook.clone(),
257 host: self.me.name.clone(),
258 }
259 }
260
261 fn presence(self: &Arc<Self>, secret: [u8; 16]) -> io::Result<()> {
262 let told = Arc::clone(&self.events);
263 let live = Live::start(
264 self.me.clone(),
265 &Room::Notebook(secret),
266 self.reach,
267 self.relay.as_deref(),
268 move |_| told(),
269 )?;
270 *self.served.room.lock().unwrap() = Some(live.sender());
271 *self.room.lock().unwrap() = Some(live);
272 Ok(())
273 }
274
275 fn open(self: &Arc<Self>, secret: [u8; 16]) -> io::Result<()> {
276 let members = Arc::downgrade(self);
277 let live = Live::start(
278 Hello {
279 serves: Some(self.sharing.lock().unwrap().share),
280 ..self.me.clone()
281 },
282 &Room::Notebook(secret),
283 self.reach,
284 self.relay.as_deref(),
285 move |event| {
286 let Some(members) = members.upgrade() else {
287 return;
288 };
289 match event {
290 Event::Met(hello, line) => {
291 let sharing = members.sharing.lock().unwrap();
292 if !sharing.members.iter().any(|device| device.secret == secret) {
293 line.hang_up("removed");
294 return;
295 }
296 members.served.admit(hello.peer, line);
297 let _ = line.send(kind::WELCOME, &members.welcome(&sharing, secret));
298 }
299 Event::Left(hello) => members.served.forget(&hello.peer),
300 Event::Frame { from, kind, body }
301 if wire::KNOWN.contains(&kind) && kind > 256 && kind != kind::REPLY =>
302 {
303 members.served.queue(&from.peer, kind, body)
304 }
305 Event::Changed => (members.events)(),
306 _ => {}
307 }
308 },
309 )?;
310 self.access.lock().unwrap().insert(secret, live);
311 Ok(())
312 }
313
314 fn grant(self: &Arc<Self>, hello: &Hello, line: &Line) -> io::Result<()> {
315 let _change = self.changes.lock().unwrap();
316 if self.room.lock().unwrap().is_none() {
317 return Err(io::ErrorKind::NotConnected.into());
318 }
319 let mut secret = [0; 16];
320 getrandom::fill(&mut secret)
321 .map_err(|_| io::Error::other("System random source failed"))?;
322 if self.sharing.lock().unwrap().members.len() >= 64 {
323 return Err(io::ErrorKind::ResourceBusy.into());
324 }
325 self.open(secret)?;
326 let kept = (|| -> io::Result<Welcome> {
327 let mut sharing = self.sharing.lock().unwrap();
328 let mut next = sharing.clone();
329 next.members.push(Device {
330 secret,
331 name: hello.name.clone(),
332 device: hello.device.clone(),
333 });
334 (self.keep)(&next)?;
335 *sharing = next;
336 Ok(self.welcome(&sharing, secret))
337 })();
338 let welcome = match kept {
339 Ok(welcome) => welcome,
340 Err(error) => {
341 drop(self.access.lock().unwrap().remove(&secret));
342 return Err(error);
343 }
344 };
345 line.send(kind::WELCOME, &welcome)?;
346 (self.events)();
347 Ok(())
348 }
349
350 fn pair(self: &Arc<Self>, sharing: &Sharing) -> io::Result<Live> {
351 let members = Arc::downgrade(self);
352 Live::start(
353 Hello {
354 serves: None,
355 ..self.me.clone()
356 },
357 &Room::share(&sharing.code, &sharing.password),
358 self.reach,
359 self.relay.as_deref(),
360 move |event| {
361 let Some(members) = members.upgrade() else {
362 return;
363 };
364 match event {
365 Event::Met(hello, line) => {
366 if members.sharing.lock().unwrap().approve {
367 let mut pending = members.pending.lock().unwrap();
368 if pending.len() < 32 {
369 pending.insert(hello.peer, (Arc::clone(hello), line.clone()));
370 let _ = line.send(kind::APPROVAL, &wire::Approval::Pending);
371 } else {
372 let _ = line.send(kind::APPROVAL, &wire::Approval::Failed);
373 }
374 drop(pending);
375 (members.events)();
376 } else if let Err(error) = members.grant(hello, line) {
377 eprintln!("Live Share: could not admit a device: {error}");
378 let _ = line.send(kind::APPROVAL, &wire::Approval::Failed);
379 }
380 }
381 Event::Left(hello) => {
382 members.pending.lock().unwrap().remove(&hello.peer);
383 (members.events)();
384 }
385 Event::Changed => (members.events)(),
386 _ => {}
387 }
388 },
389 )
390 }
391}