• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (C) 2023 Huawei Device Co., Ltd.
2 // Licensed under the Apache License, Version 2.0 (the "License");
3 // you may not use this file except in compliance with the License.
4 // You may obtain a copy of the License at
5 //
6 //     http://www.apache.org/licenses/LICENSE-2.0
7 //
8 // Unless required by applicable law or agreed to in writing, software
9 // distributed under the License is distributed on an "AS IS" BASIS,
10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 // See the License for the specific language governing permissions and
12 // limitations under the License.
13 use std::sync::{Arc, RwLock};
14 
15 use cxx::UniquePtr;
16 use ffi::NetworkRegistry;
17 pub(crate) use ffi::{NetworkInfo, NetworkType};
18 use NetworkState::{Offline, Online};
19 
20 use crate::manage::network_manager::NetworkManager;
21 
22 cfg_oh! {
23     use super::events::TaskManagerEvent;
24     use super::task_manager::TaskManagerTx;
25 }
26 
27 #[derive(Clone)]
28 pub struct Network {
29     pub(crate) inner: NetworkInner,
30     #[cfg(feature = "oh")]
31     pub(crate) _registry: Option<Arc<UniquePtr<NetworkRegistry>>>,
32 }
33 
34 #[derive(Clone, Debug, PartialEq, Eq)]
35 pub(crate) enum NetworkState {
36     Offline,
37     Online(NetworkInfo),
38 }
39 
40 impl Network {
state(&self) -> NetworkState41     pub(crate) fn state(&self) -> NetworkState {
42         self.inner.state.read().unwrap().clone()
43     }
44 }
45 
register_network_change()46 pub(crate) fn register_network_change() {
47     const RETRY_TIME: i32 = if cfg!(test) { 1 } else { 20 };
48     let mut count: i32 = 0;
49     let mut network_manager = NetworkManager::get_instance().lock().unwrap();
50     let tx = network_manager.tx.clone();
51     if network_manager.network.state() != Offline {
52         return;
53     }
54     match tx {
55         Some(tx) => {
56             let mut registry: UniquePtr<NetworkRegistry> = UniquePtr::null();
57             while count < RETRY_TIME {
58                 registry = ffi::RegisterNetworkChange(
59                     Box::new(network_manager.network.inner.clone()),
60                     Box::new(NetworkTaskManagerTx { inner: tx.clone() }),
61                     |task_manager| {
62                         task_manager.inner.send_event(TaskManagerEvent::network());
63                     },
64                     |task_manager| {
65                         task_manager.inner.send_event(TaskManagerEvent::network());
66                     },
67                 );
68                 if registry.is_null() {
69                     std::thread::sleep(std::time::Duration::from_secs(1));
70                     count += 1;
71                     continue;
72                 }
73                 break;
74             }
75             if registry.is_null() {
76                 error!("RegisterNetworkChange failed!");
77                 sys_event!(
78                     ExecFault,
79                     DfxCode::NET_CONN_CLIENT_FAULT_02,
80                     "RegisterNetworkChange failed!"
81                 );
82                 return;
83             }
84             network_manager.network._registry = Some(Arc::new(registry));
85         }
86         None => {
87             error!("register_network_change failed, tx is None!");
88             sys_event!(
89                 ExecFault,
90                 DfxCode::NET_CONN_CLIENT_FAULT_02,
91                 "register_network_change failed, tx is None!"
92             );
93         }
94     }
95 }
96 
97 #[derive(Clone)]
98 pub struct NetworkInner {
99     state: Arc<RwLock<NetworkState>>,
100 }
101 
102 pub struct NetworkTaskManagerTx {
103     #[cfg(feature = "oh")]
104     inner: TaskManagerTx,
105 }
106 
107 impl NetworkInner {
new() -> Self108     pub(crate) fn new() -> Self {
109         Self {
110             state: Arc::new(RwLock::new(NetworkState::Offline)),
111         }
112     }
113 
notify_offline(&self)114     pub(crate) fn notify_offline(&self) {
115         let mut state = self.state.write().unwrap();
116         if *state != Offline {
117             info!("network is offline");
118             *state = Offline;
119         }
120     }
121 
notify_online(&self, info: NetworkInfo) -> bool122     pub(crate) fn notify_online(&self, info: NetworkInfo) -> bool {
123         let mut state = self.state.write().unwrap();
124         if !matches!(&*state, Online(old_info) if old_info == &info  ) {
125             info!("network online {:?}", info);
126             *state = Online(info.clone());
127             true
128         } else {
129             false
130         }
131     }
132 }
133 
134 unsafe impl Send for NetworkRegistry {}
135 unsafe impl Sync for NetworkRegistry {}
136 
137 #[allow(unreachable_pub)]
138 #[cxx::bridge(namespace = "OHOS::Request")]
139 mod ffi {
140 
141     #[derive(Clone, Eq, PartialEq, Debug)]
142     struct NetworkInfo {
143         network_type: NetworkType,
144         is_metered: bool,
145         is_roaming: bool,
146     }
147 
148     #[repr(u8)]
149     #[derive(Copy, Clone, Eq, PartialEq, Debug)]
150     enum NetworkType {
151         Other,
152         Wifi,
153         Cellular,
154     }
155 
156     extern "Rust" {
157         type NetworkInner;
158         type NetworkTaskManagerTx;
notify_online(self: &NetworkInner, info: NetworkInfo) -> bool159         fn notify_online(self: &NetworkInner, info: NetworkInfo) -> bool;
notify_offline(self: &NetworkInner)160         fn notify_offline(self: &NetworkInner);
161     }
162 
163     unsafe extern "C++" {
164         include!("network.h");
165         include!("c_request_database.h");
166         type NetworkRegistry;
RegisterNetworkChange( notifier: Box<NetworkInner>, task_manager: Box<NetworkTaskManagerTx>, notify_online: fn(&NetworkTaskManagerTx), notify_offline: fn(&NetworkTaskManagerTx), ) -> UniquePtr<NetworkRegistry>167         fn RegisterNetworkChange(
168             notifier: Box<NetworkInner>,
169             task_manager: Box<NetworkTaskManagerTx>,
170             notify_online: fn(&NetworkTaskManagerTx),
171             notify_offline: fn(&NetworkTaskManagerTx),
172         ) -> UniquePtr<NetworkRegistry>;
173     }
174 }
175