OLD | NEW |
---|---|
1 /* | 1 /* |
2 * libjingle | 2 * libjingle |
3 * Copyright 2015 Google Inc. | 3 * Copyright 2015 Google Inc. |
4 * | 4 * |
5 * Redistribution and use in source and binary forms, with or without | 5 * Redistribution and use in source and binary forms, with or without |
6 * modification, are permitted provided that the following conditions are met: | 6 * modification, are permitted provided that the following conditions are met: |
7 * | 7 * |
8 * 1. Redistributions of source code must retain the above copyright notice, | 8 * 1. Redistributions of source code must retain the above copyright notice, |
9 * this list of conditions and the following disclaimer. | 9 * this list of conditions and the following disclaimer. |
10 * 2. Redistributions in binary form must reproduce the above copyright notice, | 10 * 2. Redistributions in binary form must reproduce the above copyright notice, |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
64 if (enum_name == "CONNECTION_BLUETOOTH") { | 64 if (enum_name == "CONNECTION_BLUETOOTH") { |
65 return NetworkType::NETWORK_BLUETOOTH; | 65 return NetworkType::NETWORK_BLUETOOTH; |
66 } | 66 } |
67 if (enum_name == "CONNECTION_NONE") { | 67 if (enum_name == "CONNECTION_NONE") { |
68 return NetworkType::NETWORK_NONE; | 68 return NetworkType::NETWORK_NONE; |
69 } | 69 } |
70 ASSERT(false); | 70 ASSERT(false); |
71 return NetworkType::NETWORK_UNKNOWN; | 71 return NetworkType::NETWORK_UNKNOWN; |
72 } | 72 } |
73 | 73 |
74 static rtc::AdapterType AdapterTypeFromNetworkType(NetworkType network_type) { | |
75 switch (network_type) { | |
76 case NETWORK_UNKNOWN: | |
77 RTC_DCHECK(false) << "Unknown network type "; | |
78 return rtc::ADAPTER_TYPE_UNKNOWN; | |
79 case NETWORK_ETHERNET: | |
80 return rtc::ADAPTER_TYPE_ETHERNET; | |
81 case NETWORK_WIFI: | |
82 return rtc::ADAPTER_TYPE_WIFI; | |
83 case NETWORK_4G: | |
84 case NETWORK_3G: | |
85 case NETWORK_2G: | |
86 return rtc::ADAPTER_TYPE_CELLULAR; | |
87 case NETWORK_BLUETOOTH: | |
88 // There is no corresponding mapping for bluetooth networks. | |
89 // Map it to VPN for now. | |
90 return rtc::ADAPTER_TYPE_VPN; | |
91 default: | |
92 RTC_DCHECK(false) << "Invalid network type " << network_type; | |
93 return rtc::ADAPTER_TYPE_UNKNOWN; | |
94 } | |
95 } | |
96 | |
74 static rtc::IPAddress GetIPAddressFromJava(JNIEnv* jni, jobject j_ip_address) { | 97 static rtc::IPAddress GetIPAddressFromJava(JNIEnv* jni, jobject j_ip_address) { |
75 jclass j_ip_address_class = GetObjectClass(jni, j_ip_address); | 98 jclass j_ip_address_class = GetObjectClass(jni, j_ip_address); |
76 jfieldID j_address_id = GetFieldID(jni, j_ip_address_class, "address", "[B"); | 99 jfieldID j_address_id = GetFieldID(jni, j_ip_address_class, "address", "[B"); |
77 jbyteArray j_addresses = | 100 jbyteArray j_addresses = |
78 static_cast<jbyteArray>(GetObjectField(jni, j_ip_address, j_address_id)); | 101 static_cast<jbyteArray>(GetObjectField(jni, j_ip_address, j_address_id)); |
79 size_t address_length = jni->GetArrayLength(j_addresses); | 102 size_t address_length = jni->GetArrayLength(j_addresses); |
80 jbyte* addr_array = jni->GetByteArrayElements(j_addresses, nullptr); | 103 jbyte* addr_array = jni->GetByteArrayElements(j_addresses, nullptr); |
81 CHECK_EXCEPTION(jni) << "Error during GetIPAddressFromJava"; | 104 CHECK_EXCEPTION(jni) << "Error during GetIPAddressFromJava"; |
82 if (address_length == 4) { | 105 if (address_length == 4) { |
83 // IP4 | 106 // IP4 |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
179 started_ = true; | 202 started_ = true; |
180 | 203 |
181 // This is kind of magic behavior, but doing this allows the SocketServer to | 204 // This is kind of magic behavior, but doing this allows the SocketServer to |
182 // use this as a NetworkBinder to bind sockets on a particular network when | 205 // use this as a NetworkBinder to bind sockets on a particular network when |
183 // it creates sockets. | 206 // it creates sockets. |
184 worker_thread()->socketserver()->set_network_binder(this); | 207 worker_thread()->socketserver()->set_network_binder(this); |
185 | 208 |
186 jmethodID m = | 209 jmethodID m = |
187 GetMethodID(jni(), *j_network_monitor_class_, "startMonitoring", "(J)V"); | 210 GetMethodID(jni(), *j_network_monitor_class_, "startMonitoring", "(J)V"); |
188 jni()->CallVoidMethod(*j_network_monitor_, m, jlongFromPointer(this)); | 211 jni()->CallVoidMethod(*j_network_monitor_, m, jlongFromPointer(this)); |
189 CHECK_EXCEPTION(jni()) << "Error during NetworkMonitor.startMonitoring"; | 212 CHECK_EXCEPTION(jni()) << "Error during CallVoidMethod"; |
190 } | 213 } |
191 | 214 |
192 void AndroidNetworkMonitor::Stop() { | 215 void AndroidNetworkMonitor::Stop() { |
193 RTC_CHECK(thread_checker_.CalledOnValidThread()); | 216 RTC_CHECK(thread_checker_.CalledOnValidThread()); |
194 if (!started_) { | 217 if (!started_) { |
195 return; | 218 return; |
196 } | 219 } |
197 started_ = false; | 220 started_ = false; |
198 | 221 |
199 // Once the network monitor stops, it will clear all network information and | 222 // Once the network monitor stops, it will clear all network information and |
200 // it won't find the network handle to bind anyway. | 223 // it won't find the network handle to bind anyway. |
201 if (worker_thread()->socketserver()->network_binder() == this) { | 224 if (worker_thread()->socketserver()->network_binder() == this) { |
202 worker_thread()->socketserver()->set_network_binder(nullptr); | 225 worker_thread()->socketserver()->set_network_binder(nullptr); |
203 } | 226 } |
204 | 227 |
205 jmethodID m = | 228 jmethodID m = |
206 GetMethodID(jni(), *j_network_monitor_class_, "stopMonitoring", "(J)V"); | 229 GetMethodID(jni(), *j_network_monitor_class_, "stopMonitoring", "(J)V"); |
207 jni()->CallVoidMethod(*j_network_monitor_, m, jlongFromPointer(this)); | 230 jni()->CallVoidMethod(*j_network_monitor_, m, jlongFromPointer(this)); |
208 CHECK_EXCEPTION(jni()) << "Error during NetworkMonitor.stopMonitoring"; | 231 CHECK_EXCEPTION(jni()) << "Error during NetworkMonitor.stopMonitoring"; |
209 | 232 |
210 network_info_by_address_.clear(); | 233 network_info_by_handle_.clear(); |
234 } | |
235 | |
236 NetworkInformation* AndroidNetworkMonitor::GetNetworkInfoFromAddress( | |
237 const rtc::IPAddress& address) { | |
238 // Network handles (IDs) are created by the Android OS in the increasing | |
pthatcher1
2016/01/30 02:22:07
in the increasing order => in increasing order
honghaiz3
2016/02/02 04:07:42
This is removed.
| |
239 // order. By searching in the reverse direction, the one that was created most | |
240 // recently is found first in the (unlikely) case that two handles have the | |
241 // same IP address (e.g., caused by accidentally not deleting the old handle). | |
242 auto& networks = network_info_by_handle_; | |
243 auto it = std::find_if( | |
244 networks.rbegin(), networks.rend(), | |
245 [address](const std::pair<NetworkHandle, NetworkInformation>& pos) { | |
pthatcher1
2016/01/30 02:22:07
"pos"? Why not "it" or "kv"?
honghaiz3
2016/02/02 04:07:42
This part is removed.
| |
246 auto& addresses = pos.second.ip_addresses; | |
247 return std::find(addresses.begin(), addresses.end(), address) != | |
248 addresses.end(); | |
249 }); | |
pthatcher1
2016/01/30 02:22:07
Could we not have both a network_info_by_address_
honghaiz3
2016/02/02 04:07:42
Done.
honghaiz3
2016/02/02 17:44:13
Note, I used network_handle_by_address instead of
| |
250 return (it != networks.rend()) ? &(it->second) : nullptr; | |
211 } | 251 } |
212 | 252 |
213 int AndroidNetworkMonitor::BindSocketToNetwork(int socket_fd, | 253 int AndroidNetworkMonitor::BindSocketToNetwork(int socket_fd, |
214 const rtc::IPAddress& address) { | 254 const rtc::IPAddress& address) { |
215 RTC_CHECK(thread_checker_.CalledOnValidThread()); | 255 RTC_CHECK(thread_checker_.CalledOnValidThread()); |
216 auto it = network_info_by_address_.find(address); | 256 // Android prior to Lollipop didn't have support for binding sockets to |
217 if (it == network_info_by_address_.end()) { | 257 // networks. However, in that case it should not have reached here because |
258 // |network_info_by_handle_| should only be populated in Android Lollipop | |
259 // and above. | |
260 // TODO(honghaiz): Add a check for Android version here so that it won't try | |
261 // to look for handle if the Android version is before Lollipop. | |
262 NetworkInformation* network = GetNetworkInfoFromAddress(address); | |
263 if (network == nullptr) { | |
218 return rtc::NETWORK_BIND_ADDRESS_NOT_FOUND; | 264 return rtc::NETWORK_BIND_ADDRESS_NOT_FOUND; |
219 } | 265 } |
220 // Android prior to Lollipop didn't have support for binding sockets to | |
221 // networks. However, in that case it should not have reached here because | |
222 // |network_info_by_address_| should only be populated in Android Lollipop | |
223 // and above. | |
224 NetworkInformation network = it->second; | |
225 | 266 |
226 // NOTE: This does rely on Android implementation details, but | 267 // NOTE: This does rely on Android implementation details, but |
227 // these details are unlikely to change. | 268 // these details are unlikely to change. |
228 typedef int (*SetNetworkForSocket)(unsigned netId, int socketFd); | 269 typedef int (*SetNetworkForSocket)(unsigned netId, int socketFd); |
229 static SetNetworkForSocket setNetworkForSocket; | 270 static SetNetworkForSocket setNetworkForSocket; |
230 // This is not threadsafe, but we are running this only on the worker thread. | 271 // This is not threadsafe, but we are running this only on the worker thread. |
231 if (setNetworkForSocket == nullptr) { | 272 if (setNetworkForSocket == nullptr) { |
232 // Android's netd client library should always be loaded in our address | 273 // Android's netd client library should always be loaded in our address |
233 // space as it shims libc functions like connect(). | 274 // space as it shims libc functions like connect(). |
234 const std::string net_library_path = "libnetd_client.so"; | 275 const std::string net_library_path = "libnetd_client.so"; |
235 void* lib = dlopen(net_library_path.c_str(), RTLD_LAZY); | 276 void* lib = dlopen(net_library_path.c_str(), RTLD_LAZY); |
236 if (lib == nullptr) { | 277 if (lib == nullptr) { |
237 LOG(LS_ERROR) << "Library " << net_library_path << " not found!"; | 278 LOG(LS_ERROR) << "Library " << net_library_path << " not found!"; |
238 return rtc::NETWORK_BIND_NOT_IMPLEMENTED; | 279 return rtc::NETWORK_BIND_NOT_IMPLEMENTED; |
239 } | 280 } |
240 setNetworkForSocket = reinterpret_cast<SetNetworkForSocket>( | 281 setNetworkForSocket = reinterpret_cast<SetNetworkForSocket>( |
241 dlsym(lib, "setNetworkForSocket")); | 282 dlsym(lib, "setNetworkForSocket")); |
242 } | 283 } |
243 if (setNetworkForSocket == nullptr) { | 284 if (setNetworkForSocket == nullptr) { |
244 LOG(LS_ERROR) << "Symbol setNetworkForSocket not found "; | 285 LOG(LS_ERROR) << "Symbol setNetworkForSocket not found "; |
245 return rtc::NETWORK_BIND_NOT_IMPLEMENTED; | 286 return rtc::NETWORK_BIND_NOT_IMPLEMENTED; |
246 } | 287 } |
247 int rv = setNetworkForSocket(network.handle, socket_fd); | 288 int rv = setNetworkForSocket(network->handle, socket_fd); |
248 // If |network| has since disconnected, |rv| will be ENONET. Surface this as | 289 // If |network| has since disconnected, |rv| will be ENONET. Surface this as |
249 // ERR_NETWORK_CHANGED, rather than MapSystemError(ENONET) which gives back | 290 // ERR_NETWORK_CHANGED, rather than MapSystemError(ENONET) which gives back |
250 // the less descriptive ERR_FAILED. | 291 // the less descriptive ERR_FAILED. |
251 if (rv == 0) { | 292 if (rv == 0) { |
252 return rtc::NETWORK_BIND_SUCCESS; | 293 return rtc::NETWORK_BIND_SUCCESS; |
253 } | 294 } |
254 if (rv == ENONET) { | 295 if (rv == ENONET) { |
255 return rtc::NETWORK_BIND_NETWORK_CHANGED; | 296 return rtc::NETWORK_BIND_NETWORK_CHANGED; |
256 } | 297 } |
257 return rtc::NETWORK_BIND_FAILURE; | 298 return rtc::NETWORK_BIND_FAILURE; |
258 } | 299 } |
259 | 300 |
260 void AndroidNetworkMonitor::OnNetworkAvailable( | 301 void AndroidNetworkMonitor::OnNetworkConnected( |
261 const NetworkInformation& network_info) { | 302 const NetworkInformation& network_info) { |
303 LOG(LS_INFO) << "Network connected: " << network_info.ToString(); | |
262 worker_thread()->Invoke<void>(rtc::Bind( | 304 worker_thread()->Invoke<void>(rtc::Bind( |
263 &AndroidNetworkMonitor::OnNetworkAvailable_w, this, network_info)); | 305 &AndroidNetworkMonitor::OnNetworkConnected_w, this, network_info)); |
264 } | 306 } |
265 | 307 |
266 void AndroidNetworkMonitor::OnNetworkAvailable_w( | 308 void AndroidNetworkMonitor::OnNetworkConnected_w( |
267 const NetworkInformation& network_info) { | 309 const NetworkInformation& network_info) { |
268 LOG(LS_INFO) << "Network available: " << network_info.ToString(); | 310 network_info_by_handle_[network_info.handle] = network_info; |
269 for (rtc::IPAddress address : network_info.ip_addresses) { | 311 adapter_type_by_name_[network_info.interface_name] = |
270 network_info_by_address_[address] = network_info; | 312 AdapterTypeFromNetworkType(network_info.type); |
313 } | |
314 | |
315 void AndroidNetworkMonitor::OnNetworkDisconnected(NetworkHandle handle) { | |
316 LOG(LS_INFO) << "Network disconnected for handle " << handle; | |
317 worker_thread()->Invoke<void>( | |
318 rtc::Bind(&AndroidNetworkMonitor::OnNetworkDisconnected_w, this, handle)); | |
319 } | |
320 | |
321 void AndroidNetworkMonitor::OnNetworkDisconnected_w(NetworkHandle handle) { | |
322 network_info_by_handle_.erase(handle); | |
pthatcher1
2016/01/30 02:22:07
You'd just need to do:
iter = network_info_by_han
honghaiz3
2016/02/02 04:07:42
Done.
| |
323 } | |
324 | |
325 void AndroidNetworkMonitor::SetNetworkInfos( | |
326 const std::vector<NetworkInformation>& network_infos) { | |
327 RTC_CHECK(thread_checker_.CalledOnValidThread()); | |
328 network_info_by_handle_.clear(); | |
329 for (NetworkInformation network : network_infos) { | |
330 OnNetworkConnected_w(network); | |
271 } | 331 } |
272 } | 332 } |
273 | 333 |
334 rtc::AdapterType AndroidNetworkMonitor::GetAdapterType( | |
335 const std::string& if_name) { | |
336 // If not found, the default type is 0 (ADAPTER_TYPE_UNKNOWN). | |
337 return adapter_type_by_name_[if_name]; | |
pthatcher1
2016/01/30 02:22:07
I think that's a little too subtle. Doing somethi
honghaiz3
2016/02/02 04:07:42
Done.
| |
338 } | |
339 | |
274 rtc::NetworkMonitorInterface* | 340 rtc::NetworkMonitorInterface* |
275 AndroidNetworkMonitorFactory::CreateNetworkMonitor() { | 341 AndroidNetworkMonitorFactory::CreateNetworkMonitor() { |
276 return new AndroidNetworkMonitor(); | 342 return new AndroidNetworkMonitor(); |
277 } | 343 } |
278 | 344 |
279 JOW(void, NetworkMonitor_nativeNotifyConnectionTypeChanged)( | 345 JOW(void, NetworkMonitor_nativeNotifyConnectionTypeChanged)( |
280 JNIEnv* jni, jobject j_monitor, jlong j_native_monitor) { | 346 JNIEnv* jni, jobject j_monitor, jlong j_native_monitor) { |
281 rtc::NetworkMonitorInterface* network_monitor = | 347 rtc::NetworkMonitorInterface* network_monitor = |
282 reinterpret_cast<rtc::NetworkMonitorInterface*>(j_native_monitor); | 348 reinterpret_cast<rtc::NetworkMonitorInterface*>(j_native_monitor); |
283 network_monitor->OnNetworksChanged(); | 349 network_monitor->OnNetworksChanged(); |
284 } | 350 } |
285 | 351 |
352 JOW(void, NetworkMonitor_nativeNotifyOfActiveNetworkList)( | |
353 JNIEnv* jni, jobject j_monitor, jlong j_native_monitor, | |
354 jobjectArray j_network_infos) { | |
355 AndroidNetworkMonitor* network_monitor = | |
356 reinterpret_cast<AndroidNetworkMonitor*>(j_native_monitor); | |
357 std::vector<NetworkInformation> network_infos; | |
358 size_t num_networks = jni->GetArrayLength(j_network_infos); | |
359 for (size_t i = 0; i < num_networks; ++i) { | |
360 jobject j_network_info = jni->GetObjectArrayElement(j_network_infos, i); | |
361 CHECK_EXCEPTION(jni) << "Error during GetObjectArrayElement"; | |
362 network_infos.push_back(GetNetworkInformationFromJava(jni, j_network_info)); | |
363 } | |
364 network_monitor->SetNetworkInfos(network_infos); | |
365 } | |
366 | |
286 JOW(void, NetworkMonitor_nativeNotifyOfNetworkConnect)( | 367 JOW(void, NetworkMonitor_nativeNotifyOfNetworkConnect)( |
287 JNIEnv* jni, jobject j_monitor, jlong j_native_monitor, | 368 JNIEnv* jni, jobject j_monitor, jlong j_native_monitor, |
288 jobject j_network_info) { | 369 jobject j_network_info) { |
289 AndroidNetworkMonitor* network_monitor = | 370 AndroidNetworkMonitor* network_monitor = |
290 reinterpret_cast<AndroidNetworkMonitor*>(j_native_monitor); | 371 reinterpret_cast<AndroidNetworkMonitor*>(j_native_monitor); |
291 NetworkInformation network_info = | 372 NetworkInformation network_info = |
292 GetNetworkInformationFromJava(jni, j_network_info); | 373 GetNetworkInformationFromJava(jni, j_network_info); |
293 network_monitor->OnNetworkAvailable(network_info); | 374 network_monitor->OnNetworkConnected(network_info); |
375 } | |
376 | |
377 JOW(void, NetworkMonitor_nativeNotifyOfNetworkDisconnect)( | |
378 JNIEnv* jni, jobject j_monitor, jlong j_native_monitor, | |
379 jint network_handle) { | |
380 AndroidNetworkMonitor* network_monitor = | |
381 reinterpret_cast<AndroidNetworkMonitor*>(j_native_monitor); | |
382 network_monitor->OnNetworkDisconnected( | |
383 static_cast<NetworkHandle>(network_handle)); | |
294 } | 384 } |
295 | 385 |
296 } // namespace webrtc_jni | 386 } // namespace webrtc_jni |
OLD | NEW |