Index: webrtc/base/physicalsocketserver.cc |
diff --git a/webrtc/base/physicalsocketserver.cc b/webrtc/base/physicalsocketserver.cc |
index 524617221c894ee8d5530d4167f1a45ac9b3f387..9e54c49322e8ca35528eb4f297f10902cbc4aaa5 100644 |
--- a/webrtc/base/physicalsocketserver.cc |
+++ b/webrtc/base/physicalsocketserver.cc |
@@ -19,6 +19,7 @@ |
#endif |
#if defined(WEBRTC_POSIX) |
+#include <dlfcn.h> |
#include <string.h> |
#include <errno.h> |
#include <fcntl.h> |
@@ -96,6 +97,14 @@ static const int ICMP_HEADER_SIZE = 8u; |
static const int ICMP_PING_TIMEOUT_MILLIS = 10000u; |
#endif |
+static const int ERR_NOT_IMPLEMENTED = -11; |
+ |
+#if defined(ANDROID) && !defined(WEBRTC_CHROMIUM_BUILD) |
+static const int ERR_NETWORK_CHANGED = -21; |
+static const int ERR_FAILED = -1; |
+static const uint32_t INVALID_NETWORK_HANDLE = 0xFFFFFFFF; |
pthatcher1
2016/01/06 21:58:46
Where do these values come from?
honghaiz3
2016/01/12 20:36:42
From the Chromium code. I changed them to an enum
|
+#endif |
+ |
PhysicalSocket::PhysicalSocket(PhysicalSocketServer* ss, SOCKET s) |
: ss_(ss), s_(s), enabled_events_(0), error_(0), |
state_((s == INVALID_SOCKET) ? CS_CLOSED : CS_CONNECTED), |
@@ -177,6 +186,49 @@ int PhysicalSocket::Bind(const SocketAddress& bind_addr) { |
return err; |
} |
+int PhysicalSocket::BindToNetwork(NetworkHandle network) { |
+#if defined(ANDROID) && !defined(WEBRTC_CHROMIUM_BUILD) |
+ LOG(LS_INFO) << "Bind socket " << s_ << " to network handle " << network; |
+ // Android prior to Lollipop didn't have support for binding sockets to |
+ // networks. However, it should not have reached here in that case |
+ // because the default network handle is invalid. |
+ ASSERT(network != INVALID_NETWORK_HANDLE); |
+ |
+ // 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"; |
+ 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) << "Symbol setNetworkForSocket 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; |
pthatcher1
2016/01/06 21:58:46
For readability, can you move this into its own An
honghaiz3
2016/01/12 20:36:42
Done.
|
+#else |
+ ASSERT(false); |
+ return ERR_NOT_IMPLEMENTED; |
+#endif |
+} |
+ |
int PhysicalSocket::Connect(const SocketAddress& addr) { |
// TODO(pthatcher): Implicit creation is required to reconnect... |
// ...but should we make it more explicit? |
@@ -1127,7 +1179,7 @@ bool SocketDispatcher::CheckSignalClose() { |
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 { |
@@ -1621,6 +1673,6 @@ bool PhysicalSocketServer::Wait(int cmsWait, bool process_io) { |
// Done |
return true; |
} |
-#endif // WEBRTC_WIN |
+#endif // WEBRTC_WIN |
} // namespace rtc |