Skip to main content

wlan_storage_constants/
constants.rs

1// Copyright 2020 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5use serde::{Deserialize, Serialize};
6
7pub const NODE_SEPARATOR: &'static str = "#/@";
8pub const POLICY_STASH_PREFIX: &str = "config";
9/// The StashNode abstraction requires that writing to a StashNode is done as a named field,
10/// so we will store the network config's data under the POLICY_DATA_KEY.
11pub const POLICY_DATA_KEY: &str = "data";
12pub const POLICY_STORAGE_ID: &str = "saved_networks";
13
14pub type StashedSsid = Vec<u8>;
15
16/// The data that will be stored between reboots of a device. Used to convert the data between JSON
17/// and network config.
18#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
19pub struct PersistentData {
20    pub credential: Credential,
21    pub has_ever_connected: bool,
22}
23
24/// The network identifier is the SSID and security policy of the network, and it is used to
25/// distinguish networks. It mirrors the NetworkIdentifier in fidl_fuchsia_wlan_policy.
26#[derive(Clone, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
27pub struct NetworkIdentifier {
28    pub ssid: StashedSsid,
29    pub security_type: SecurityType,
30}
31
32/// The security type of a network connection. It mirrors the fidl_fuchsia_wlan_policy SecurityType
33#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
34pub enum SecurityType {
35    None,
36    Wep,
37    Wpa,
38    Wpa2,
39    Wpa3,
40}
41
42/// The credential of a network connection. It mirrors the fidl_fuchsia_wlan_policy Credential
43#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
44pub enum Credential {
45    None,
46    Password(Vec<u8>),
47    Psk(Vec<u8>),
48}
49
50/// To deserialize file data into a JSON with a file version and data, a wrapper is needed since
51/// the values of the hashmap must be consistent.
52#[derive(Serialize, Deserialize)]
53#[serde(untagged)]
54pub enum FileContent {
55    Version(u8),
56    Networks(Vec<PersistentStorageData>),
57}
58
59/// The data that will be stored between reboots of a device. Used to convert the data between JSON
60/// and network config.
61#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
62pub struct PersistentStorageData {
63    pub ssid: StashedSsid,
64    pub security_type: SecurityType,
65    pub credential: Credential,
66    #[serde(default = "has_ever_connected_default")]
67    pub has_ever_connected: bool,
68    #[serde(default, skip_serializing_if = "Option::is_none")]
69    pub hidden_probability: Option<f32>,
70}
71
72/// Defines the default value of has_ever_connected in persisted data. This is used so that the
73/// config could be loaded even if this field is missing.
74fn has_ever_connected_default() -> bool {
75    false
76}
77
78impl PersistentStorageData {
79    /// Used when migrating persisted networks from deprecated stash to the new local storage format.
80    pub fn new_from_legacy_data(
81        id: NetworkIdentifier,
82        data: PersistentData,
83    ) -> PersistentStorageData {
84        PersistentStorageData {
85            ssid: id.ssid.clone(),
86            security_type: id.security_type,
87            credential: data.credential,
88            has_ever_connected: data.has_ever_connected,
89            hidden_probability: None,
90        }
91    }
92}
93
94#[cfg(test)]
95mod tests {
96    use super::*;
97    use serde_json;
98
99    #[test]
100    fn test_persistent_storage_data_deserialize_missing_hidden_probability() {
101        let json_str = r#"{
102            "ssid": [102, 111, 111],
103            "security_type": "Wpa2",
104            "credential": { "Password": [112, 97, 115, 115] },
105            "has_ever_connected": true
106        }"#;
107        let data: PersistentStorageData =
108            serde_json::from_str(json_str).expect("deserialize failed");
109        assert_eq!(data.hidden_probability, None);
110    }
111
112    #[test]
113    fn test_persistent_storage_data_serialize_skip_none() {
114        // Check that if the hidden probability is None, it is not included in the serialized data.
115        let data = PersistentStorageData {
116            ssid: b"foo".to_vec(),
117            security_type: SecurityType::Wpa2,
118            credential: Credential::Password(b"pass".to_vec()),
119            has_ever_connected: true,
120            hidden_probability: None,
121        };
122        let json_str = serde_json::to_string(&data).expect("serialize failed");
123        assert!(!json_str.contains("hidden_probability"));
124    }
125
126    #[test]
127    fn test_persistent_storage_data_serialize_and_deserialize() {
128        // Check that serializing and deserializing results in the original data.
129        let data = PersistentStorageData {
130            ssid: b"foo".to_vec(),
131            security_type: SecurityType::Wpa2,
132            credential: Credential::Password(b"pass".to_vec()),
133            has_ever_connected: true,
134            hidden_probability: Some(0.05),
135        };
136        let json_str = serde_json::to_string(&data).expect("serialize failed");
137        assert!(json_str.contains("\"hidden_probability\":0.05"));
138
139        let loaded_data: PersistentStorageData =
140            serde_json::from_str(&json_str).expect("deserialize failed");
141        assert_eq!(loaded_data.hidden_probability, Some(0.05));
142        assert_eq!(loaded_data, data);
143    }
144}