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