Index: webrtc/base/physicalsocketserver.cc |
diff --git a/webrtc/base/physicalsocketserver.cc b/webrtc/base/physicalsocketserver.cc |
index 4a4c0a36ba923323bcd21c57b24e9f3341ba591f..513110890844e697bd46d5e0a4834693ea375052 100644 |
--- a/webrtc/base/physicalsocketserver.cc |
+++ b/webrtc/base/physicalsocketserver.cc |
@@ -14,6 +14,8 @@ |
#include <assert.h> |
+#include <dlfcn.h> |
+ |
#ifdef MEMORY_SANITIZER |
#include <sanitizer/msan_interface.h> |
#endif |
@@ -97,6 +99,11 @@ static const int ICMP_HEADER_SIZE = 8u; |
static const int ICMP_PING_TIMEOUT_MILLIS = 10000u; |
#endif |
+static const int ERR_NOT_IMPLEMENTED = -11; |
+static const int ERR_NETWORK_CHANGED = -21; |
+static const int ERR_FAILED = -1; |
+static const uint32_t INVALID_NETWORK_HANDLE = 0xFFFFFFFF; |
+ |
class PhysicalSocket : public AsyncSocket, public sigslot::has_slots<> { |
public: |
PhysicalSocket(PhysicalSocketServer* ss, SOCKET s = INVALID_SOCKET) |
@@ -181,6 +188,54 @@ class PhysicalSocket : public AsyncSocket, public sigslot::has_slots<> { |
return err; |
} |
+ int BindToNetwork(NetworkHandle network) override { |
+ LOG(LS_INFO) << "Bind socket " << s_ << " to network " << network; |
+ if (network == INVALID_NETWORK_HANDLE) |
+ return -1; |
+#if defined(ANDROID) && !defined(WEBRTC_CHROMIUM_BUILD) |
+ // Android prior to Lollipop didn't have support for binding sockets to |
+ // networks. |
+ // if (base::android::BuildInfo::GetInstance()->sdk_int() < |
+ // base::android::SDK_VERSION_LOLLIPOP) { |
+ // return ERR_NOT_IMPLEMENTED; |
+ //} |
+ |
+ // NOTE: This does rely on Android implementation details, but |
+ // these details are unlikely to change. |
+ typedef int (*SetNetworkForSocket)(unsigned netId, int socketFd); |
+ static SetNetworkForSocket setNetworkForSocket; |
+ // This is racy, but all racers should come out with the same answer so it |
+ // shouldn't matter. |
+ if (setNetworkForSocket == nullptr) { |
+ // Android's netd client library should always be loaded in our address |
+ // space as it shims libc functions like connect(). |
+ const std::string net_library_path = "libnetd_client.so"; |
+ LOG(LS_ERROR) << "Load Library " << net_library_path; |
+ void* lib = dlopen(net_library_path.c_str(), RTLD_LAZY); |
+ if (lib == nullptr) { |
+ LOG(LS_ERROR) << "Library " << net_library_path << " not found!"; |
+ return ERR_NOT_IMPLEMENTED; |
+ } |
+ setNetworkForSocket = reinterpret_cast<SetNetworkForSocket>( |
+ dlsym(lib, "setNetworkForSocket")); |
+ } |
+ if (setNetworkForSocket == nullptr) { |
+ LOG(LS_ERROR) << "symbole not found "; |
+ return ERR_NOT_IMPLEMENTED; |
+ } |
+ int rv = setNetworkForSocket(network, s_); |
+ // If |network| has since disconnected, |rv| will be ENONET. Surface this |
+ // as |
+ // ERR_NETWORK_CHANGED, rather than MapSystemError(ENONET) which gives back |
+ // the less descriptive ERR_FAILED. |
+ if (rv == ENONET) |
+ return ERR_NETWORK_CHANGED; |
+ return ERR_FAILED; |
+#else |
+ return ERR_NOT_IMPLEMENTED; |
+#endif |
+ } |
+ |
int Connect(const SocketAddress& addr) override { |
// TODO: Implicit creation is required to reconnect... |
// ...but should we make it more explicit? |
@@ -1138,7 +1193,7 @@ class SocketDispatcher : public Dispatcher, public PhysicalSocket { |
int SocketDispatcher::next_id_ = 0; |
-#endif // WEBRTC_WIN |
+#endif // WEBRTC_WIN |
// Sets the value of a boolean value to false when signaled. |
class Signaler : public EventDispatcher { |
@@ -1632,6 +1687,6 @@ bool PhysicalSocketServer::Wait(int cmsWait, bool process_io) { |
// Done |
return true; |
} |
-#endif // WEBRTC_WIN |
+#endif // WEBRTC_WIN |
} // namespace rtc |