| Index: webrtc/p2p/base/tcpport.cc
|
| diff --git a/webrtc/p2p/base/tcpport.cc b/webrtc/p2p/base/tcpport.cc
|
| index 86670cd3668bb56ec5e6b01efb44313080d4ec35..cbb25b91927f9fd5268521db5207dc2bd4c2ab3f 100644
|
| --- a/webrtc/p2p/base/tcpport.cc
|
| +++ b/webrtc/p2p/base/tcpport.cc
|
| @@ -75,7 +75,6 @@ namespace cricket {
|
| TCPPort::TCPPort(rtc::Thread* thread,
|
| rtc::PacketSocketFactory* factory,
|
| rtc::Network* network,
|
| - const rtc::IPAddress& ip,
|
| uint16_t min_port,
|
| uint16_t max_port,
|
| const std::string& username,
|
| @@ -85,7 +84,6 @@ TCPPort::TCPPort(rtc::Thread* thread,
|
| LOCAL_PORT_TYPE,
|
| factory,
|
| network,
|
| - ip,
|
| min_port,
|
| max_port,
|
| username,
|
| @@ -179,11 +177,15 @@ void TCPPort::PrepareAddress() {
|
| // Note: We still add the address, since otherwise the remote side won't
|
| // recognize our incoming TCP connections. According to
|
| // https://tools.ietf.org/html/rfc6544#section-4.5, for active candidate,
|
| - // the port must be set to the discard port, i.e. 9.
|
| - AddAddress(rtc::SocketAddress(ip(), DISCARD_PORT),
|
| - rtc::SocketAddress(ip(), 0), rtc::SocketAddress(),
|
| - TCP_PROTOCOL_NAME, "", TCPTYPE_ACTIVE_STR, LOCAL_PORT_TYPE,
|
| - ICE_TYPE_PREFERENCE_HOST_TCP, 0, "", true);
|
| + // the port must be set to the discard port, i.e. 9. We can't be 100% sure
|
| + // which IP address will actually be used, so GetBestIP is as good as we
|
| + // can do.
|
| + // TODO(deadbeef): We could do something like create a dummy socket just to
|
| + // see what IP we get. But that may be overkill.
|
| + AddAddress(rtc::SocketAddress(Network()->GetBestIP(), DISCARD_PORT),
|
| + rtc::SocketAddress(Network()->GetBestIP(), 0),
|
| + rtc::SocketAddress(), TCP_PROTOCOL_NAME, "", TCPTYPE_ACTIVE_STR,
|
| + LOCAL_PORT_TYPE, ICE_TYPE_PREFERENCE_HOST_TCP, 0, "", true);
|
| }
|
| }
|
|
|
| @@ -262,7 +264,8 @@ void TCPPort::OnNewConnection(rtc::AsyncPacketSocket* socket,
|
|
|
| void TCPPort::TryCreateServerSocket() {
|
| socket_ = socket_factory()->CreateServerTcpSocket(
|
| - rtc::SocketAddress(ip(), 0), min_port(), max_port(), false /* ssl */);
|
| + rtc::SocketAddress(Network()->GetBestIP(), 0), min_port(), max_port(),
|
| + false /* ssl */);
|
| if (!socket_) {
|
| LOG_J(LS_WARNING, this)
|
| << "TCP server socket creation failed; continuing anyway.";
|
| @@ -323,11 +326,16 @@ TCPConnection::TCPConnection(TCPPort* port,
|
| if (outgoing_) {
|
| CreateOutgoingTcpSocket();
|
| } else {
|
| - // Incoming connections should match the network address.
|
| + // Incoming connections should match one of the network addresses. Same as
|
| + // what's being checked in OnConnect, but just DCHECKing here.
|
| LOG_J(LS_VERBOSE, this)
|
| << "socket ipaddr: " << socket_->GetLocalAddress().ToString()
|
| - << ",port() ip:" << port->ip().ToString();
|
| - RTC_DCHECK(socket_->GetLocalAddress().ipaddr() == port->ip());
|
| + << ", port() Network:" << port->Network()->ToString();
|
| + const std::vector<rtc::InterfaceAddress>& desired_addresses =
|
| + port_->Network()->GetIPs();
|
| + RTC_DCHECK(std::find(desired_addresses.begin(), desired_addresses.end(),
|
| + socket_->GetLocalAddress().ipaddr()) !=
|
| + desired_addresses.end());
|
| ConnectSocketSignals(socket);
|
| }
|
| }
|
| @@ -390,34 +398,49 @@ void TCPConnection::OnConnectionRequestResponse(ConnectionRequest* req,
|
|
|
| void TCPConnection::OnConnect(rtc::AsyncPacketSocket* socket) {
|
| RTC_DCHECK(socket == socket_.get());
|
| - // Do not use this connection if the socket bound to a different address than
|
| - // the one we asked for. This is seen in Chrome, where TCP sockets cannot be
|
| - // given a binding address, and the platform is expected to pick the
|
| - // correct local address.
|
| - const rtc::SocketAddress& socket_addr = socket->GetLocalAddress();
|
| - if (socket_addr.ipaddr() == port()->ip()) {
|
| + // Do not use this port if the socket bound to an address not associated with
|
| + // the desired network interface. This is seen in Chrome, where TCP sockets
|
| + // cannot be given a binding address, and the platform is expected to pick
|
| + // the correct local address.
|
| + //
|
| + // However, there are two situations in which we allow the bound address to
|
| + // not be one of the addresses of the requested interface:
|
| + // 1. The bound address is the loopback address. This happens when a proxy
|
| + // forces TCP to bind to only the localhost address (see issue 3927).
|
| + // 2. The bound address is the "any address". This happens when
|
| + // multiple_routes is disabled (see issue 4780).
|
| + //
|
| + // Note that, aside from minor differences in log statements, this logic is
|
| + // identical to that in TurnPort.
|
| + const rtc::SocketAddress& socket_address = socket->GetLocalAddress();
|
| + const std::vector<rtc::InterfaceAddress>& desired_addresses =
|
| + port_->Network()->GetIPs();
|
| + if (std::find(desired_addresses.begin(), desired_addresses.end(),
|
| + socket_address.ipaddr()) != desired_addresses.end()) {
|
| LOG_J(LS_VERBOSE, this) << "Connection established to "
|
| << socket->GetRemoteAddress().ToSensitiveString();
|
| - } else if (IPIsAny(port()->ip())) {
|
| - LOG(LS_WARNING) << "Socket is bound to a different address:"
|
| - << socket_addr.ipaddr().ToString()
|
| - << ", rather then the local port:"
|
| - << port()->ip().ToString()
|
| - << ". Still allowing it since it's any address"
|
| - << ", possibly caused by multi-routes being disabled.";
|
| - } else if (socket_addr.IsLoopbackIP()) {
|
| - LOG(LS_WARNING) << "Socket is bound to a different address:"
|
| - << socket_addr.ipaddr().ToString()
|
| - << ", rather then the local port:"
|
| - << port()->ip().ToString()
|
| - << ". Still allowing it since it's localhost.";
|
| } else {
|
| - LOG_J(LS_WARNING, this) << "Dropping connection as TCP socket bound to IP "
|
| - << socket_addr.ipaddr().ToSensitiveString()
|
| - << ", different from the local candidate IP "
|
| - << port()->ip().ToSensitiveString();
|
| - OnClose(socket, 0);
|
| - return;
|
| + if (socket->GetLocalAddress().IsLoopbackIP()) {
|
| + LOG(LS_WARNING) << "Socket is bound to the address:"
|
| + << socket_address.ipaddr().ToString()
|
| + << ", rather then an address associated with network:"
|
| + << port_->Network()->ToString()
|
| + << ". Still allowing it since it's localhost.";
|
| + } else if (IPIsAny(port_->Network()->GetBestIP())) {
|
| + LOG(LS_WARNING) << "Socket is bound to the address:"
|
| + << socket_address.ipaddr().ToString()
|
| + << ", rather then an address associated with network:"
|
| + << port_->Network()->ToString()
|
| + << ". Still allowing it since it's the 'any' address"
|
| + << ", possibly caused by multiple_routes being disabled.";
|
| + } else {
|
| + LOG(LS_WARNING) << "Dropping connection as TCP socket bound to IP "
|
| + << socket_address.ipaddr().ToString()
|
| + << ", rather then an address associated with network:"
|
| + << port_->Network()->ToString();
|
| + OnClose(socket, 0);
|
| + return;
|
| + }
|
| }
|
|
|
| // Connection is established successfully.
|
| @@ -501,8 +524,9 @@ void TCPConnection::CreateOutgoingTcpSocket() {
|
| ? rtc::PacketSocketFactory::OPT_TLS_FAKE
|
| : 0;
|
| socket_.reset(port()->socket_factory()->CreateClientTcpSocket(
|
| - rtc::SocketAddress(port()->ip(), 0), remote_candidate().address(),
|
| - port()->proxy(), port()->user_agent(), opts));
|
| + rtc::SocketAddress(port()->Network()->GetBestIP(), 0),
|
| + remote_candidate().address(), port()->proxy(), port()->user_agent(),
|
| + opts));
|
| if (socket_) {
|
| LOG_J(LS_VERBOSE, this)
|
| << "Connecting from " << socket_->GetLocalAddress().ToSensitiveString()
|
|
|