Allowed services support

This commit is contained in:
zakorgy 2016-06-03 15:29:37 +02:00 committed by zakorgyula
parent 530b5a649e
commit 174516ac5b
2 changed files with 41 additions and 3 deletions

View file

@ -16,7 +16,7 @@ use net_traits::bluetooth_thread::{BluetoothDeviceMsg, BluetoothMethodMsg};
use net_traits::bluetooth_thread::{BluetoothResult, BluetoothServiceMsg, BluetoothServicesMsg}; use net_traits::bluetooth_thread::{BluetoothResult, BluetoothServiceMsg, BluetoothServicesMsg};
use rand::{self, Rng}; use rand::{self, Rng};
use std::borrow::ToOwned; use std::borrow::ToOwned;
use std::collections::HashMap; use std::collections::{HashMap, HashSet};
use std::string::String; use std::string::String;
use std::thread; use std::thread;
use std::time::Duration; use std::time::Duration;
@ -32,6 +32,7 @@ const INCLUDED_SERVICE_ERROR: &'static str = "No included service found";
const CHARACTERISTIC_ERROR: &'static str = "No characteristic found"; const CHARACTERISTIC_ERROR: &'static str = "No characteristic found";
const DESCRIPTOR_ERROR: &'static str = "No descriptor found"; const DESCRIPTOR_ERROR: &'static str = "No descriptor found";
const VALUE_ERROR: &'static str = "No characteristic or descriptor found with that id"; const VALUE_ERROR: &'static str = "No characteristic or descriptor found with that id";
const SECURITY_ERROR: &'static str = "The operation is insecure";
// The discovery session needs some time to find any nearby devices // The discovery session needs some time to find any nearby devices
const DISCOVERY_TIMEOUT_MS: u64 = 1500; const DISCOVERY_TIMEOUT_MS: u64 = 1500;
#[cfg(target_os = "linux")] #[cfg(target_os = "linux")]
@ -139,6 +140,7 @@ pub struct BluetoothManager {
cached_services: HashMap<String, BluetoothGATTService>, cached_services: HashMap<String, BluetoothGATTService>,
cached_characteristics: HashMap<String, BluetoothGATTCharacteristic>, cached_characteristics: HashMap<String, BluetoothGATTCharacteristic>,
cached_descriptors: HashMap<String, BluetoothGATTDescriptor>, cached_descriptors: HashMap<String, BluetoothGATTDescriptor>,
allowed_services: HashMap<String, HashSet<String>>,
} }
impl BluetoothManager { impl BluetoothManager {
@ -154,6 +156,7 @@ impl BluetoothManager {
cached_services: HashMap::new(), cached_services: HashMap::new(),
cached_characteristics: HashMap::new(), cached_characteristics: HashMap::new(),
cached_descriptors: HashMap::new(), cached_descriptors: HashMap::new(),
allowed_services: HashMap::new(),
} }
} }
@ -225,7 +228,8 @@ impl BluetoothManager {
if !self.address_to_id.contains_key(&address) { if !self.address_to_id.contains_key(&address) {
let generated_id = self.generate_device_id(); let generated_id = self.generate_device_id();
self.address_to_id.insert(address, generated_id.clone()); self.address_to_id.insert(address, generated_id.clone());
self.cached_devices.insert(generated_id, device.clone()); self.cached_devices.insert(generated_id.clone(), device.clone());
self.allowed_services.insert(generated_id, HashSet::new());
} }
} }
} }
@ -446,6 +450,11 @@ impl BluetoothManager {
Some(id) => id.clone(), Some(id) => id.clone(),
None => return drop(sender.send(Err(String::from(DEVICE_MATCH_ERROR)))), None => return drop(sender.send(Err(String::from(DEVICE_MATCH_ERROR)))),
}; };
let mut services = options.get_services_set();
if let Some(services_set) = self.allowed_services.get(&device_id) {
services = services_set | &services;
}
self.allowed_services.insert(device_id.clone(), services);
if let Some(device) = self.get_device(&mut adapter, &device_id) { if let Some(device) = self.get_device(&mut adapter, &device_id) {
let message = Ok(BluetoothDeviceMsg { let message = Ok(BluetoothDeviceMsg {
id: device_id, id: device_id,
@ -499,6 +508,9 @@ impl BluetoothManager {
uuid: String, uuid: String,
sender: IpcSender<BluetoothResult<BluetoothServiceMsg>>) { sender: IpcSender<BluetoothResult<BluetoothServiceMsg>>) {
let mut adapter = get_adapter_or_return_error!(self, sender); let mut adapter = get_adapter_or_return_error!(self, sender);
if !self.allowed_services.get(&device_id).map_or(false, |s| s.contains(&uuid)) {
return drop(sender.send(Err(String::from(SECURITY_ERROR))));
}
let services = self.get_gatt_services_by_uuid(&mut adapter, &device_id, &uuid); let services = self.get_gatt_services_by_uuid(&mut adapter, &device_id, &uuid);
if services.is_empty() { if services.is_empty() {
return drop(sender.send(Err(String::from(PRIMARY_SERVICE_ERROR)))); return drop(sender.send(Err(String::from(PRIMARY_SERVICE_ERROR))));
@ -523,7 +535,12 @@ impl BluetoothManager {
sender: IpcSender<BluetoothResult<BluetoothServicesMsg>>) { sender: IpcSender<BluetoothResult<BluetoothServicesMsg>>) {
let mut adapter = get_adapter_or_return_error!(self, sender); let mut adapter = get_adapter_or_return_error!(self, sender);
let services = match uuid { let services = match uuid {
Some(id) => self.get_gatt_services_by_uuid(&mut adapter, &device_id, &id), Some(ref id) => {
if !self.allowed_services.get(&device_id).map_or(false, |s| s.contains(id)) {
return drop(sender.send(Err(String::from(SECURITY_ERROR))))
}
self.get_gatt_services_by_uuid(&mut adapter, &device_id, id)
},
None => self.get_and_cache_gatt_services(&mut adapter, &device_id), None => self.get_and_cache_gatt_services(&mut adapter, &device_id),
}; };
if services.is_empty() { if services.is_empty() {

View file

@ -2,6 +2,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use std::collections::HashSet;
use std::slice::Iter; use std::slice::Iter;
// A device name can never be longer than 29 bytes. An adv packet is at most // A device name can never be longer than 29 bytes. An adv packet is at most
@ -16,6 +17,14 @@ impl ServiceUUIDSequence {
pub fn new(vec: Vec<String>) -> ServiceUUIDSequence { pub fn new(vec: Vec<String>) -> ServiceUUIDSequence {
ServiceUUIDSequence(vec) ServiceUUIDSequence(vec)
} }
fn get_services_set(&self) -> HashSet<String> {
let mut set = HashSet::new();
for s in self.0.iter() {
set.insert(s.clone());
}
set
}
} }
#[derive(Deserialize, Serialize)] #[derive(Deserialize, Serialize)]
@ -69,6 +78,14 @@ impl BluetoothScanfilterSequence {
pub fn iter(&self) -> Iter<BluetoothScanfilter> { pub fn iter(&self) -> Iter<BluetoothScanfilter> {
self.0.iter() self.0.iter()
} }
fn get_services_set(&self) -> HashSet<String> {
let mut set = HashSet::new();
for filter in self.iter() {
set = &set | &filter.services.get_services_set();
}
set
}
} }
#[derive(Deserialize, Serialize)] #[derive(Deserialize, Serialize)]
@ -90,4 +107,8 @@ impl RequestDeviceoptions {
pub fn get_filters(&self) -> &BluetoothScanfilterSequence { pub fn get_filters(&self) -> &BluetoothScanfilterSequence {
&self.filters &self.filters
} }
pub fn get_services_set(&self) -> HashSet<String> {
&self.filters.get_services_set() | &self.optional_services.get_services_set()
}
} }