blob: 5210e17f60956640402b3a831a3df2e3d4a8cca2 [file] [log] [blame]
// Copyright 2018 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
use app::client::App;
use failure::{Error, ResultExt};
use futures::future::ok as fok;
use futures::{Future, FutureExt, StreamExt};
use std::fs::File;
use std::fs::OpenOptions;
use std::io::{Read, Write};
use std::path::PathBuf;
use std::sync::{Arc, Mutex};
use std::{thread, time};
use toml;
use app::client::Launcher;
use fidl_bluetooth_bonder::{BonderEvent, BonderEventStream, BonderMarker, BondingData};
use fidl_bluetooth_control::ControlMarker;
use fidl_bluetooth_gatt::Server_Marker;
use fidl_bluetooth_low_energy::{CentralMarker, PeripheralMarker};
use bond_defs::BondMap;
static BT_MGR_DIR: &'static str = "data/bt-mgr";
pub struct BondStore {
bonds: BondMap,
bond_store: File,
}
impl BondStore {
pub fn load_store() -> Result<Self, Error> {
let store_path: PathBuf = [BT_MGR_DIR, "/bonds.toml"].iter().collect();
let mut bond_store = OpenOptions::new()
.read(true)
.write(true)
.create(true)
.open(store_path)?;
let mut contents = String::new();
bond_store
.read_to_string(&mut contents)
.expect("The bond storage file is corrupted");
let bonds: BondMap = toml::from_str(contents.as_str()).unwrap();
Ok(BondStore { bonds, bond_store })
}
pub fn add(&mut self, local_id: String, bond_data: BondingData) {
self.bonds.inner_mut().entry(local_id)
// TODO look up syntax, push if not there
// .or_insert(VecBondingData{inner: vec![]})
.and_modify(move |entry| {
entry.inner.push(bond_data);
});
let _ = self.save_state();
}
pub fn bonds(&self) -> &BondMap {
&self.bonds
}
pub fn save_state(&mut self) -> Result<(), Error> {
let toml = toml::to_string_pretty(&self.bonds)?;
self.bond_store.write_all(toml.as_bytes())?;
self.bond_store.sync_data()?;
Ok(())
}
}
pub fn bond(bond_store: Arc<Mutex<BondStore>>, bt_gap: App) -> Result<(), Error> {
let bond_svc = bt_gap.connect_to_service(BonderMarker)?;
let bond_store = bond_store.lock().unwrap();
for (bond_key, bond_data) in bond_store.bonds.inner().iter() {
// TODO make the iter work
// bond_svc.add_bonded_devices(bond_key, bond_data.into_iter());
}
Ok(())
}
pub fn watch_bonds(
bond_store: Arc<Mutex<BondStore>>,
) -> impl Future<Item = BonderEventStream, Error = Error> {
let launcher = Launcher::new()
.context("Failed to open launcher service")
.unwrap();
let app = launcher
.launch(String::from("bt-gap"), None)
.context("Failed to launch bt-gap (bluetooth) service")
.unwrap();
thread::sleep(time::Duration::from_millis(2000));
let app = app.connect_to_service(BonderMarker);
let stream = app.unwrap().take_event_stream();
stream
.for_each(move |evt| {
match evt {
BonderEvent::OnNewBondingData { local_id, data } => {
let mut bond_store = bond_store.lock().unwrap();
bond_store.add(local_id, data)
}
}
fok(())
})
.err_into()
}