Index: webrtc/base/physicalsocketserver.cc |
diff --git a/webrtc/base/physicalsocketserver.cc b/webrtc/base/physicalsocketserver.cc |
index 07591e8ad332b534516fdb0f27ed21c7fe9f55ec..c044529c8981461acd1ff19c90c1ea502560bfa5 100644 |
--- a/webrtc/base/physicalsocketserver.cc |
+++ b/webrtc/base/physicalsocketserver.cc |
@@ -190,8 +190,42 @@ SocketAddress PhysicalSocket::GetRemoteAddress() const { |
} |
int PhysicalSocket::Bind(const SocketAddress& bind_addr) { |
+ SocketAddress copied_bind_addr = bind_addr; |
+ // If a network binder is available, use it to bind a socket to an interface |
+ // instead of bind(), since this is more reliable on an OS with a weak host |
+ // model. |
+ if (ss_->network_binder()) { |
+ NetworkBindingResult result = |
+ ss_->network_binder()->BindSocketToNetwork(s_, bind_addr.ipaddr()); |
+ if (result == NetworkBindingResult::SUCCESS) { |
+ // Since the network binder handled binding the socket to the desired |
+ // network interface, we don't need to (and shouldn't) include an IP in |
+ // the bind() call; bind() just needs to assign a port. |
+ copied_bind_addr.SetIP(GetAnyIP(copied_bind_addr.ipaddr().family())); |
+ } else if (result == NetworkBindingResult::NOT_IMPLEMENTED) { |
+ LOG(LS_INFO) << "Can't bind socket to network because " |
+ "network binding is not implemented for this OS."; |
+ } else { |
+ if (bind_addr.IsLoopbackIP()) { |
+ // If we couldn't bind to a loopback IP (which should only happen in |
+ // test scenarios), continue on. This may be expected behavior. |
+ LOG(LS_VERBOSE) << "Binding socket to loopback address " |
+ << bind_addr.ipaddr().ToString() |
+ << " failed; result: " << static_cast<int>(result); |
+ } else { |
+ LOG(LS_WARNING) << "Binding socket to network address " |
+ << bind_addr.ipaddr().ToString() |
+ << " failed; result: " << static_cast<int>(result); |
+ // If a network binding was attempted and failed, we should stop here |
+ // and not try to use the socket. Otherwise, we may end up sending |
+ // packets with an invalid source address. |
+ // See: https://bugs.chromium.org/p/webrtc/issues/detail?id=7026 |
+ return -1; |
+ } |
+ } |
+ } |
sockaddr_storage addr_storage; |
- size_t len = bind_addr.ToSockAddrStorage(&addr_storage); |
+ size_t len = copied_bind_addr.ToSockAddrStorage(&addr_storage); |
sockaddr* addr = reinterpret_cast<sockaddr*>(&addr_storage); |
int err = ::bind(s_, addr, static_cast<int>(len)); |
UpdateLastError(); |
@@ -201,14 +235,6 @@ int PhysicalSocket::Bind(const SocketAddress& bind_addr) { |
dbg_addr_.append(GetLocalAddress().ToString()); |
} |
#endif |
- if (ss_->network_binder()) { |
- int result = |
- ss_->network_binder()->BindSocketToNetwork(s_, bind_addr.ipaddr()); |
- if (result < 0) { |
- LOG(LS_INFO) << "Binding socket to network address " |
- << bind_addr.ipaddr().ToString() << " result " << result; |
- } |
- } |
return err; |
} |