Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(21)

Side by Side Diff: talk/app/webrtc/java/jni/androidnetworkmonitor_jni.cc

Issue 1556743002: Bind a socket to a network if the network handle is set. (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Fix a compiling issue for Windows Created 4 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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,
11 * this list of conditions and the following disclaimer in the documentation 11 * this list of conditions and the following disclaimer in the documentation
12 * and/or other materials provided with the distribution. 12 * and/or other materials provided with the distribution.
13 * 3. The name of the author may not be used to endorse or promote products 13 * 3. The name of the author may not be used to endorse or promote products
14 * derived from this software without specific prior written permission. 14 * derived from this software without specific prior written permission.
15 * 15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 18 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
19 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 19 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */ 26 */
27 27
28 #include "talk/app/webrtc/java/jni/androidnetworkmonitor_jni.h" 28 #include "talk/app/webrtc/java/jni/androidnetworkmonitor_jni.h"
29 29
30 #include <dlfcn.h>
31
30 #include "webrtc/base/common.h" 32 #include "webrtc/base/common.h"
33 #include "webrtc/base/ipaddress.h"
31 #include "talk/app/webrtc/java/jni/classreferenceholder.h" 34 #include "talk/app/webrtc/java/jni/classreferenceholder.h"
32 #include "talk/app/webrtc/java/jni/jni_helpers.h" 35 #include "talk/app/webrtc/java/jni/jni_helpers.h"
33 36
34 namespace webrtc_jni { 37 namespace webrtc_jni {
38
35 jobject AndroidNetworkMonitor::application_context_ = nullptr; 39 jobject AndroidNetworkMonitor::application_context_ = nullptr;
36 40
41 static NetworkType GetNetworkTypeFromJava(JNIEnv* jni, jobject j_network_type) {
42 std::string enum_name =
43 GetJavaEnumName(jni, "org/webrtc/NetworkMonitorAutoDetect$ConnectionType",
44 j_network_type);
45 if (enum_name == "CONNECTION_UNKNOWN") {
46 return NetworkType::NETWORK_UNKNOWN;
47 }
48 if (enum_name == "CONNECTION_ETHERNET") {
49 return NetworkType::NETWORK_ETHERNET;
50 }
51 if (enum_name == "CONNECTION_WIFI") {
52 return NetworkType::NETWORK_WIFI;
53 }
54 if (enum_name == "CONNECTION_4G") {
55 return NetworkType::NETWORK_4G;
56 }
57 if (enum_name == "CONNECTION_3G") {
58 return NetworkType::NETWORK_3G;
59 }
60 if (enum_name == "CONNECTION_2G") {
61 return NetworkType::NETWORK_2G;
62 }
63 if (enum_name == "CONNECTION_BLUETOOTH") {
64 return NetworkType::NETWORK_BLUETOOTH;
65 }
66 if (enum_name == "CONNECTION_NONE") {
67 return NetworkType::NETWORK_NONE;
68 }
69 ASSERT(false);
70 return NetworkType::NETWORK_UNKNOWN;
71 }
72
73 static rtc::IPAddress GetIPAddressFromJava(JNIEnv* jni, jobject j_ip_address) {
74 jclass j_ip_address_class = GetObjectClass(jni, j_ip_address);
75 jfieldID j_address_id = GetFieldID(jni, j_ip_address_class, "address", "[B");
76 jbyteArray j_addresses =
77 static_cast<jbyteArray>(GetObjectField(jni, j_ip_address, j_address_id));
78 size_t address_length = jni->GetArrayLength(j_addresses);
79 jbyte* addr_array = jni->GetByteArrayElements(j_addresses, NULL);
80 CHECK_EXCEPTION(jni) << "Error during NetworkMonitor.GetIPAddressFromJava";
81 if (address_length == 4) {
82 // IP4
83 struct in_addr ip4_addr;
84 memcpy(&ip4_addr.s_addr, addr_array, 4);
85 jni->ReleaseByteArrayElements(j_addresses, addr_array, JNI_ABORT);
86 return rtc::IPAddress(ip4_addr);
87 }
88 // IP6
89 RTC_CHECK(address_length == 16);
90 struct in6_addr ip6_addr;
91 memcpy(ip6_addr.s6_addr, addr_array, address_length);
92 jni->ReleaseByteArrayElements(j_addresses, addr_array, JNI_ABORT);
93 return rtc::IPAddress(ip6_addr);
94 }
95
96 static void GetIPAddressesFromJava(JNIEnv* jni,
97 jobjectArray j_ip_addresses,
98 std::vector<rtc::IPAddress>* ip_addresses) {
99 ip_addresses->clear();
100 size_t num_addresses = jni->GetArrayLength(j_ip_addresses);
101 for (size_t i = 0; i < num_addresses; ++i) {
102 jobject j_ip_address = jni->GetObjectArrayElement(j_ip_addresses, i);
103 rtc::IPAddress ip = GetIPAddressFromJava(jni, j_ip_address);
104
105 ip_addresses->push_back(ip);
106 }
107 CHECK_EXCEPTION(jni) << "Error during NetworkMonitor.GetIPAddressesFromJava";
108 }
109
110 static NetworkInformation GetNetworkInformationFromJava(
111 JNIEnv* jni,
112 jobject j_network_info) {
113 jclass j_network_info_class = GetObjectClass(jni, j_network_info);
114 jfieldID j_interface_name_id =
115 GetFieldID(jni, j_network_info_class, "name", "Ljava/lang/String;");
116 jfieldID j_handle_id = GetFieldID(jni, j_network_info_class, "handle", "I");
117 jfieldID j_type_id =
118 GetFieldID(jni, j_network_info_class, "type",
119 "Lorg/webrtc/NetworkMonitorAutoDetect$ConnectionType;");
120 jfieldID j_ip_addresses_id =
121 GetFieldID(jni, j_network_info_class, "ipAddresses",
122 "[Lorg/webrtc/NetworkMonitorAutoDetect$IPAddress;");
123
124 NetworkInformation network_info;
125 network_info.interface_name = JavaToStdString(
126 jni, GetStringField(jni, j_network_info, j_interface_name_id));
127 network_info.handle = static_cast<rtc::NetworkHandle>(
128 GetIntField(jni, j_network_info, j_handle_id));
129 network_info.type = GetNetworkTypeFromJava(
130 jni, GetObjectField(jni, j_network_info, j_type_id));
131 jobjectArray j_ip_addresses = static_cast<jobjectArray>(
132 GetObjectField(jni, j_network_info, j_ip_addresses_id));
133 GetIPAddressesFromJava(jni, j_ip_addresses, &network_info.ip_addresses);
134 CHECK_EXCEPTION(jni) << "Error during NetworkMonitor.GetNetworkInfoFromJava";
135 return network_info;
136 }
137
138 std::string NetworkInformation::ToString() const {
139 std::stringstream ss;
140 ss << "NetInfo[name " << interface_name << "; handle " << handle << "; type "
141 << type << "; address ";
142 for (const rtc::IPAddress address : ip_addresses) {
143 ss << address.ToString() << " ";
144 }
145 ss << "]";
146 return ss.str();
147 }
148
37 // static 149 // static
38 void AndroidNetworkMonitor::SetAndroidContext(JNIEnv* jni, jobject context) { 150 void AndroidNetworkMonitor::SetAndroidContext(JNIEnv* jni, jobject context) {
39 if (application_context_) { 151 if (application_context_) {
40 jni->DeleteGlobalRef(application_context_); 152 jni->DeleteGlobalRef(application_context_);
41 } 153 }
42 application_context_ = NewGlobalRef(jni, context); 154 application_context_ = NewGlobalRef(jni, context);
43 } 155 }
44 156
45 AndroidNetworkMonitor::AndroidNetworkMonitor() 157 AndroidNetworkMonitor::AndroidNetworkMonitor()
46 : j_network_monitor_class_(jni(), 158 : j_network_monitor_class_(jni(),
47 FindClass(jni(), "org/webrtc/NetworkMonitor")), 159 FindClass(jni(), "org/webrtc/NetworkMonitor")),
48 j_network_monitor_( 160 j_network_monitor_(
49 jni(), 161 jni(),
50 jni()->CallStaticObjectMethod( 162 jni()->CallStaticObjectMethod(
51 *j_network_monitor_class_, 163 *j_network_monitor_class_,
52 GetStaticMethodID( 164 GetStaticMethodID(
53 jni(), 165 jni(),
54 *j_network_monitor_class_, 166 *j_network_monitor_class_,
55 "init", 167 "init",
56 "(Landroid/content/Context;)Lorg/webrtc/NetworkMonitor;"), 168 "(Landroid/content/Context;)Lorg/webrtc/NetworkMonitor;"),
57 application_context_)) { 169 application_context_)) {
58 ASSERT(application_context_ != nullptr); 170 ASSERT(application_context_ != nullptr);
59 CHECK_EXCEPTION(jni()) << "Error during NetworkMonitor.init"; 171 CHECK_EXCEPTION(jni()) << "Error during NetworkMonitor.init";
172 thread_checker_.DetachFromThread();
60 } 173 }
61 174
62 void AndroidNetworkMonitor::Start() { 175 void AndroidNetworkMonitor::Start() {
176 NetworkMonitorBase::Start();
177
63 RTC_CHECK(thread_checker_.CalledOnValidThread()); 178 RTC_CHECK(thread_checker_.CalledOnValidThread());
64 jmethodID m = 179 jmethodID m =
65 GetMethodID(jni(), *j_network_monitor_class_, "startMonitoring", "(J)V"); 180 GetMethodID(jni(), *j_network_monitor_class_, "startMonitoring", "(J)V");
66 jni()->CallVoidMethod(*j_network_monitor_, m, jlongFromPointer(this)); 181 jni()->CallVoidMethod(*j_network_monitor_, m, jlongFromPointer(this));
67 CHECK_EXCEPTION(jni()) << "Error during NetworkMonitor.startMonitoring"; 182 CHECK_EXCEPTION(jni()) << "Error during NetworkMonitor.startMonitoring";
68 } 183 }
69 184
70 void AndroidNetworkMonitor::Stop() { 185 void AndroidNetworkMonitor::Stop() {
71 RTC_CHECK(thread_checker_.CalledOnValidThread()); 186 RTC_CHECK(thread_checker_.CalledOnValidThread());
72 jmethodID m = 187 jmethodID m =
73 GetMethodID(jni(), *j_network_monitor_class_, "stopMonitoring", "(J)V"); 188 GetMethodID(jni(), *j_network_monitor_class_, "stopMonitoring", "(J)V");
74 jni()->CallVoidMethod(*j_network_monitor_, m, jlongFromPointer(this)); 189 jni()->CallVoidMethod(*j_network_monitor_, m, jlongFromPointer(this));
75 CHECK_EXCEPTION(jni()) << "Error during NetworkMonitor.stopMonitoring"; 190 CHECK_EXCEPTION(jni()) << "Error during NetworkMonitor.stopMonitoring";
76 } 191 }
77 192
193 int AndroidNetworkMonitor::BindSocketToNetwork(int socket_fd,
194 const rtc::IPAddress& address) {
195 RTC_CHECK(thread_checker_.CalledOnValidThread());
196 if (network_info_map_.find(address) == network_info_map_.end()) {
197 return rtc::ERR_ADDRESS_NOT_FOUND;
pthatcher1 2016/01/14 20:07:24 If you store the result of the .find() you won't h
honghaiz3 2016/01/15 01:00:38 Done.
198 }
199 // Android prior to Lollipop didn't have support for binding sockets to
200 // networks. However, in that case it should not have reached here because
201 // |network_info_map_| should only be populated on Android Lollipop and above.
202 NetworkInformation network = network_info_map_[address];
203
204 // NOTE: This does rely on Android implementation details, but
205 // these details are unlikely to change.
206 typedef int (*SetNetworkForSocket)(unsigned netId, int socketFd);
207 static SetNetworkForSocket setNetworkForSocket;
208 // This is not threadsafe, but we are running this only on the worker thread.
209 if (setNetworkForSocket == nullptr) {
210 // Android's netd client library should always be loaded in our address
211 // space as it shims libc functions like connect().
212 const std::string net_library_path = "libnetd_client.so";
213 void* lib = dlopen(net_library_path.c_str(), RTLD_LAZY);
214 if (lib == nullptr) {
215 LOG(LS_ERROR) << "Library " << net_library_path << " not found!";
216 return rtc::ERR_NOT_IMPLEMENTED;
217 }
218 setNetworkForSocket = reinterpret_cast<SetNetworkForSocket>(
219 dlsym(lib, "setNetworkForSocket"));
220 }
221 if (setNetworkForSocket == nullptr) {
222 LOG(LS_ERROR) << "Symbol setNetworkForSocket not found ";
223 return rtc::ERR_NOT_IMPLEMENTED;
224 }
225 int rv = setNetworkForSocket(network.handle, socket_fd);
226 // If |network| has since disconnected, |rv| will be ENONET. Surface this as
227 // ERR_NETWORK_CHANGED, rather than MapSystemError(ENONET) which gives back
228 // the less descriptive ERR_FAILED.
229 if (rv == ENONET) {
230 rv = rtc::ERR_NETWORK_CHANGED;
231 }
232 return rv;
233 }
234
235 void AndroidNetworkMonitor::OnNetworkAvailable(
236 const NetworkInformation& network_info) {
237 LOG(LS_INFO) << "Network available: " << network_info.ToString();
238 for (rtc::IPAddress address : network_info.ip_addresses) {
239 network_info_map_[address] = network_info;
240 }
241 }
242
243 rtc::NetworkMonitorInterface*
244 AndroidNetworkMonitorFactory::GetOrCreateNetworkMonitor() {
245 rtc::CritScope cs(&crit_);
246 if (!network_monitor_) {
247 network_monitor_.reset(new AndroidNetworkMonitor());
248 }
249 return network_monitor_.get();
250 }
251
78 JOW(void, NetworkMonitor_nativeNotifyConnectionTypeChanged)( 252 JOW(void, NetworkMonitor_nativeNotifyConnectionTypeChanged)(
79 JNIEnv* jni, jobject j_monitor, jlong j_native_monitor) { 253 JNIEnv* jni, jobject j_monitor, jlong j_native_monitor) {
80 rtc::NetworkMonitorInterface* network_monitor = 254 rtc::NetworkMonitorInterface* network_monitor =
81 reinterpret_cast<rtc::NetworkMonitorInterface*>(j_native_monitor); 255 reinterpret_cast<rtc::NetworkMonitorInterface*>(j_native_monitor);
82 network_monitor->OnNetworksChanged(); 256 network_monitor->OnNetworksChanged();
83 } 257 }
84 258
259 JOW(void, NetworkMonitor_nativeNotifyOfNetworkConnect)(
260 JNIEnv* jni, jobject j_monitor, jlong j_native_monitor,
261 jobject j_network_info) {
262 AndroidNetworkMonitor* network_monitor =
263 reinterpret_cast<AndroidNetworkMonitor*>(j_native_monitor);
264 NetworkInformation network_info =
265 GetNetworkInformationFromJava(jni, j_network_info);
266 network_monitor->OnNetworkAvailable(network_info);
267 }
268
85 } // namespace webrtc_jni 269 } // namespace webrtc_jni
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698