OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2004 The WebRTC Project Authors. All rights reserved. | 2 * Copyright 2004 The WebRTC Project Authors. All rights reserved. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license | 4 * Use of this source code is governed by a BSD-style license |
5 * that can be found in the LICENSE file in the root of the source | 5 * that can be found in the LICENSE file in the root of the source |
6 * tree. An additional intellectual property rights grant can be found | 6 * tree. An additional intellectual property rights grant can be found |
7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
9 */ | 9 */ |
10 | 10 |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
68 | 68 |
69 #include "webrtc/p2p/base/common.h" | 69 #include "webrtc/p2p/base/common.h" |
70 #include "webrtc/rtc_base/checks.h" | 70 #include "webrtc/rtc_base/checks.h" |
71 #include "webrtc/rtc_base/logging.h" | 71 #include "webrtc/rtc_base/logging.h" |
72 | 72 |
73 namespace cricket { | 73 namespace cricket { |
74 | 74 |
75 TCPPort::TCPPort(rtc::Thread* thread, | 75 TCPPort::TCPPort(rtc::Thread* thread, |
76 rtc::PacketSocketFactory* factory, | 76 rtc::PacketSocketFactory* factory, |
77 rtc::Network* network, | 77 rtc::Network* network, |
78 const rtc::IPAddress& ip, | |
79 uint16_t min_port, | 78 uint16_t min_port, |
80 uint16_t max_port, | 79 uint16_t max_port, |
81 const std::string& username, | 80 const std::string& username, |
82 const std::string& password, | 81 const std::string& password, |
83 bool allow_listen) | 82 bool allow_listen) |
84 : Port(thread, | 83 : Port(thread, |
85 LOCAL_PORT_TYPE, | 84 LOCAL_PORT_TYPE, |
86 factory, | 85 factory, |
87 network, | 86 network, |
88 ip, | |
89 min_port, | 87 min_port, |
90 max_port, | 88 max_port, |
91 username, | 89 username, |
92 password), | 90 password), |
93 incoming_only_(false), | 91 incoming_only_(false), |
94 allow_listen_(allow_listen), | 92 allow_listen_(allow_listen), |
95 socket_(NULL), | 93 socket_(NULL), |
96 error_(0) { | 94 error_(0) { |
97 // TODO(mallinath) - Set preference value as per RFC 6544. | 95 // TODO(mallinath) - Set preference value as per RFC 6544. |
98 // http://b/issue?id=7141794 | 96 // http://b/issue?id=7141794 |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
172 socket_->GetState() == rtc::AsyncPacketSocket::STATE_CLOSED) | 170 socket_->GetState() == rtc::AsyncPacketSocket::STATE_CLOSED) |
173 AddAddress(socket_->GetLocalAddress(), socket_->GetLocalAddress(), | 171 AddAddress(socket_->GetLocalAddress(), socket_->GetLocalAddress(), |
174 rtc::SocketAddress(), TCP_PROTOCOL_NAME, "", | 172 rtc::SocketAddress(), TCP_PROTOCOL_NAME, "", |
175 TCPTYPE_PASSIVE_STR, LOCAL_PORT_TYPE, | 173 TCPTYPE_PASSIVE_STR, LOCAL_PORT_TYPE, |
176 ICE_TYPE_PREFERENCE_HOST_TCP, 0, "", true); | 174 ICE_TYPE_PREFERENCE_HOST_TCP, 0, "", true); |
177 } else { | 175 } else { |
178 LOG_J(LS_INFO, this) << "Not listening due to firewall restrictions."; | 176 LOG_J(LS_INFO, this) << "Not listening due to firewall restrictions."; |
179 // Note: We still add the address, since otherwise the remote side won't | 177 // Note: We still add the address, since otherwise the remote side won't |
180 // recognize our incoming TCP connections. According to | 178 // recognize our incoming TCP connections. According to |
181 // https://tools.ietf.org/html/rfc6544#section-4.5, for active candidate, | 179 // https://tools.ietf.org/html/rfc6544#section-4.5, for active candidate, |
182 // the port must be set to the discard port, i.e. 9. | 180 // the port must be set to the discard port, i.e. 9. We can't be 100% sure |
183 AddAddress(rtc::SocketAddress(ip(), DISCARD_PORT), | 181 // which IP address will actually be used, so GetBestIP is as good as we |
184 rtc::SocketAddress(ip(), 0), rtc::SocketAddress(), | 182 // can do. |
185 TCP_PROTOCOL_NAME, "", TCPTYPE_ACTIVE_STR, LOCAL_PORT_TYPE, | 183 // TODO(deadbeef): We could do something like create a dummy socket just to |
186 ICE_TYPE_PREFERENCE_HOST_TCP, 0, "", true); | 184 // see what IP we get. But that may be overkill. |
| 185 AddAddress(rtc::SocketAddress(Network()->GetBestIP(), DISCARD_PORT), |
| 186 rtc::SocketAddress(Network()->GetBestIP(), 0), |
| 187 rtc::SocketAddress(), TCP_PROTOCOL_NAME, "", TCPTYPE_ACTIVE_STR, |
| 188 LOCAL_PORT_TYPE, ICE_TYPE_PREFERENCE_HOST_TCP, 0, "", true); |
187 } | 189 } |
188 } | 190 } |
189 | 191 |
190 int TCPPort::SendTo(const void* data, size_t size, | 192 int TCPPort::SendTo(const void* data, size_t size, |
191 const rtc::SocketAddress& addr, | 193 const rtc::SocketAddress& addr, |
192 const rtc::PacketOptions& options, | 194 const rtc::PacketOptions& options, |
193 bool payload) { | 195 bool payload) { |
194 rtc::AsyncPacketSocket * socket = NULL; | 196 rtc::AsyncPacketSocket * socket = NULL; |
195 TCPConnection* conn = static_cast<TCPConnection*>(GetConnection(addr)); | 197 TCPConnection* conn = static_cast<TCPConnection*>(GetConnection(addr)); |
196 | 198 |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
255 incoming.socket->SignalReadyToSend.connect(this, &TCPPort::OnReadyToSend); | 257 incoming.socket->SignalReadyToSend.connect(this, &TCPPort::OnReadyToSend); |
256 incoming.socket->SignalSentPacket.connect(this, &TCPPort::OnSentPacket); | 258 incoming.socket->SignalSentPacket.connect(this, &TCPPort::OnSentPacket); |
257 | 259 |
258 LOG_J(LS_VERBOSE, this) << "Accepted connection from " | 260 LOG_J(LS_VERBOSE, this) << "Accepted connection from " |
259 << incoming.addr.ToSensitiveString(); | 261 << incoming.addr.ToSensitiveString(); |
260 incoming_.push_back(incoming); | 262 incoming_.push_back(incoming); |
261 } | 263 } |
262 | 264 |
263 void TCPPort::TryCreateServerSocket() { | 265 void TCPPort::TryCreateServerSocket() { |
264 socket_ = socket_factory()->CreateServerTcpSocket( | 266 socket_ = socket_factory()->CreateServerTcpSocket( |
265 rtc::SocketAddress(ip(), 0), min_port(), max_port(), false /* ssl */); | 267 rtc::SocketAddress(Network()->GetBestIP(), 0), min_port(), max_port(), |
| 268 false /* ssl */); |
266 if (!socket_) { | 269 if (!socket_) { |
267 LOG_J(LS_WARNING, this) | 270 LOG_J(LS_WARNING, this) |
268 << "TCP server socket creation failed; continuing anyway."; | 271 << "TCP server socket creation failed; continuing anyway."; |
269 return; | 272 return; |
270 } | 273 } |
271 socket_->SignalNewConnection.connect(this, &TCPPort::OnNewConnection); | 274 socket_->SignalNewConnection.connect(this, &TCPPort::OnNewConnection); |
272 socket_->SignalAddressReady.connect(this, &TCPPort::OnAddressReady); | 275 socket_->SignalAddressReady.connect(this, &TCPPort::OnAddressReady); |
273 } | 276 } |
274 | 277 |
275 rtc::AsyncPacketSocket* TCPPort::GetIncoming( | 278 rtc::AsyncPacketSocket* TCPPort::GetIncoming( |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
316 : Connection(port, 0, candidate), | 319 : Connection(port, 0, candidate), |
317 socket_(socket), | 320 socket_(socket), |
318 error_(0), | 321 error_(0), |
319 outgoing_(socket == NULL), | 322 outgoing_(socket == NULL), |
320 connection_pending_(false), | 323 connection_pending_(false), |
321 pretending_to_be_writable_(false), | 324 pretending_to_be_writable_(false), |
322 reconnection_timeout_(cricket::CONNECTION_WRITE_CONNECT_TIMEOUT) { | 325 reconnection_timeout_(cricket::CONNECTION_WRITE_CONNECT_TIMEOUT) { |
323 if (outgoing_) { | 326 if (outgoing_) { |
324 CreateOutgoingTcpSocket(); | 327 CreateOutgoingTcpSocket(); |
325 } else { | 328 } else { |
326 // Incoming connections should match the network address. | 329 // Incoming connections should match one of the network addresses. Same as |
| 330 // what's being checked in OnConnect, but just DCHECKing here. |
327 LOG_J(LS_VERBOSE, this) | 331 LOG_J(LS_VERBOSE, this) |
328 << "socket ipaddr: " << socket_->GetLocalAddress().ToString() | 332 << "socket ipaddr: " << socket_->GetLocalAddress().ToString() |
329 << ",port() ip:" << port->ip().ToString(); | 333 << ", port() Network:" << port->Network()->ToString(); |
330 RTC_DCHECK(socket_->GetLocalAddress().ipaddr() == port->ip()); | 334 const std::vector<rtc::InterfaceAddress>& desired_addresses = |
| 335 port_->Network()->GetIPs(); |
| 336 RTC_DCHECK(std::find(desired_addresses.begin(), desired_addresses.end(), |
| 337 socket_->GetLocalAddress().ipaddr()) != |
| 338 desired_addresses.end()); |
331 ConnectSocketSignals(socket); | 339 ConnectSocketSignals(socket); |
332 } | 340 } |
333 } | 341 } |
334 | 342 |
335 TCPConnection::~TCPConnection() { | 343 TCPConnection::~TCPConnection() { |
336 } | 344 } |
337 | 345 |
338 int TCPConnection::Send(const void* data, size_t size, | 346 int TCPConnection::Send(const void* data, size_t size, |
339 const rtc::PacketOptions& options) { | 347 const rtc::PacketOptions& options) { |
340 if (!socket_) { | 348 if (!socket_) { |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
383 // would have stopped the outgoing stream. | 391 // would have stopped the outgoing stream. |
384 if (pretending_to_be_writable_) { | 392 if (pretending_to_be_writable_) { |
385 Connection::OnReadyToSend(); | 393 Connection::OnReadyToSend(); |
386 } | 394 } |
387 pretending_to_be_writable_ = false; | 395 pretending_to_be_writable_ = false; |
388 RTC_DCHECK(write_state() == STATE_WRITABLE); | 396 RTC_DCHECK(write_state() == STATE_WRITABLE); |
389 } | 397 } |
390 | 398 |
391 void TCPConnection::OnConnect(rtc::AsyncPacketSocket* socket) { | 399 void TCPConnection::OnConnect(rtc::AsyncPacketSocket* socket) { |
392 RTC_DCHECK(socket == socket_.get()); | 400 RTC_DCHECK(socket == socket_.get()); |
393 // Do not use this connection if the socket bound to a different address than | 401 // Do not use this port if the socket bound to an address not associated with |
394 // the one we asked for. This is seen in Chrome, where TCP sockets cannot be | 402 // the desired network interface. This is seen in Chrome, where TCP sockets |
395 // given a binding address, and the platform is expected to pick the | 403 // cannot be given a binding address, and the platform is expected to pick |
396 // correct local address. | 404 // the correct local address. |
397 const rtc::SocketAddress& socket_addr = socket->GetLocalAddress(); | 405 // |
398 if (socket_addr.ipaddr() == port()->ip()) { | 406 // However, there are two situations in which we allow the bound address to |
| 407 // not be one of the addresses of the requested interface: |
| 408 // 1. The bound address is the loopback address. This happens when a proxy |
| 409 // forces TCP to bind to only the localhost address (see issue 3927). |
| 410 // 2. The bound address is the "any address". This happens when |
| 411 // multiple_routes is disabled (see issue 4780). |
| 412 // |
| 413 // Note that, aside from minor differences in log statements, this logic is |
| 414 // identical to that in TurnPort. |
| 415 const rtc::SocketAddress& socket_address = socket->GetLocalAddress(); |
| 416 const std::vector<rtc::InterfaceAddress>& desired_addresses = |
| 417 port_->Network()->GetIPs(); |
| 418 if (std::find(desired_addresses.begin(), desired_addresses.end(), |
| 419 socket_address.ipaddr()) != desired_addresses.end()) { |
399 LOG_J(LS_VERBOSE, this) << "Connection established to " | 420 LOG_J(LS_VERBOSE, this) << "Connection established to " |
400 << socket->GetRemoteAddress().ToSensitiveString(); | 421 << socket->GetRemoteAddress().ToSensitiveString(); |
401 } else if (IPIsAny(port()->ip())) { | |
402 LOG(LS_WARNING) << "Socket is bound to a different address:" | |
403 << socket_addr.ipaddr().ToString() | |
404 << ", rather then the local port:" | |
405 << port()->ip().ToString() | |
406 << ". Still allowing it since it's any address" | |
407 << ", possibly caused by multi-routes being disabled."; | |
408 } else if (socket_addr.IsLoopbackIP()) { | |
409 LOG(LS_WARNING) << "Socket is bound to a different address:" | |
410 << socket_addr.ipaddr().ToString() | |
411 << ", rather then the local port:" | |
412 << port()->ip().ToString() | |
413 << ". Still allowing it since it's localhost."; | |
414 } else { | 422 } else { |
415 LOG_J(LS_WARNING, this) << "Dropping connection as TCP socket bound to IP " | 423 if (socket->GetLocalAddress().IsLoopbackIP()) { |
416 << socket_addr.ipaddr().ToSensitiveString() | 424 LOG(LS_WARNING) << "Socket is bound to the address:" |
417 << ", different from the local candidate IP " | 425 << socket_address.ipaddr().ToString() |
418 << port()->ip().ToSensitiveString(); | 426 << ", rather then an address associated with network:" |
419 OnClose(socket, 0); | 427 << port_->Network()->ToString() |
420 return; | 428 << ". Still allowing it since it's localhost."; |
| 429 } else if (IPIsAny(port_->Network()->GetBestIP())) { |
| 430 LOG(LS_WARNING) << "Socket is bound to the address:" |
| 431 << socket_address.ipaddr().ToString() |
| 432 << ", rather then an address associated with network:" |
| 433 << port_->Network()->ToString() |
| 434 << ". Still allowing it since it's the 'any' address" |
| 435 << ", possibly caused by multiple_routes being disabled."; |
| 436 } else { |
| 437 LOG(LS_WARNING) << "Dropping connection as TCP socket bound to IP " |
| 438 << socket_address.ipaddr().ToString() |
| 439 << ", rather then an address associated with network:" |
| 440 << port_->Network()->ToString(); |
| 441 OnClose(socket, 0); |
| 442 return; |
| 443 } |
421 } | 444 } |
422 | 445 |
423 // Connection is established successfully. | 446 // Connection is established successfully. |
424 set_connected(true); | 447 set_connected(true); |
425 connection_pending_ = false; | 448 connection_pending_ = false; |
426 } | 449 } |
427 | 450 |
428 void TCPConnection::OnClose(rtc::AsyncPacketSocket* socket, int error) { | 451 void TCPConnection::OnClose(rtc::AsyncPacketSocket* socket, int error) { |
429 RTC_DCHECK(socket == socket_.get()); | 452 RTC_DCHECK(socket == socket_.get()); |
430 LOG_J(LS_INFO, this) << "Connection closed with error " << error; | 453 LOG_J(LS_INFO, this) << "Connection closed with error " << error; |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
494 Connection::OnReadyToSend(); | 517 Connection::OnReadyToSend(); |
495 } | 518 } |
496 | 519 |
497 void TCPConnection::CreateOutgoingTcpSocket() { | 520 void TCPConnection::CreateOutgoingTcpSocket() { |
498 RTC_DCHECK(outgoing_); | 521 RTC_DCHECK(outgoing_); |
499 // TODO(guoweis): Handle failures here (unlikely since TCP). | 522 // TODO(guoweis): Handle failures here (unlikely since TCP). |
500 int opts = (remote_candidate().protocol() == SSLTCP_PROTOCOL_NAME) | 523 int opts = (remote_candidate().protocol() == SSLTCP_PROTOCOL_NAME) |
501 ? rtc::PacketSocketFactory::OPT_TLS_FAKE | 524 ? rtc::PacketSocketFactory::OPT_TLS_FAKE |
502 : 0; | 525 : 0; |
503 socket_.reset(port()->socket_factory()->CreateClientTcpSocket( | 526 socket_.reset(port()->socket_factory()->CreateClientTcpSocket( |
504 rtc::SocketAddress(port()->ip(), 0), remote_candidate().address(), | 527 rtc::SocketAddress(port()->Network()->GetBestIP(), 0), |
505 port()->proxy(), port()->user_agent(), opts)); | 528 remote_candidate().address(), port()->proxy(), port()->user_agent(), |
| 529 opts)); |
506 if (socket_) { | 530 if (socket_) { |
507 LOG_J(LS_VERBOSE, this) | 531 LOG_J(LS_VERBOSE, this) |
508 << "Connecting from " << socket_->GetLocalAddress().ToSensitiveString() | 532 << "Connecting from " << socket_->GetLocalAddress().ToSensitiveString() |
509 << " to " << remote_candidate().address().ToSensitiveString(); | 533 << " to " << remote_candidate().address().ToSensitiveString(); |
510 set_connected(false); | 534 set_connected(false); |
511 connection_pending_ = true; | 535 connection_pending_ = true; |
512 ConnectSocketSignals(socket_.get()); | 536 ConnectSocketSignals(socket_.get()); |
513 } else { | 537 } else { |
514 LOG_J(LS_WARNING, this) << "Failed to create connection to " | 538 LOG_J(LS_WARNING, this) << "Failed to create connection to " |
515 << remote_candidate().address().ToSensitiveString(); | 539 << remote_candidate().address().ToSensitiveString(); |
516 } | 540 } |
517 } | 541 } |
518 | 542 |
519 void TCPConnection::ConnectSocketSignals(rtc::AsyncPacketSocket* socket) { | 543 void TCPConnection::ConnectSocketSignals(rtc::AsyncPacketSocket* socket) { |
520 if (outgoing_) { | 544 if (outgoing_) { |
521 socket->SignalConnect.connect(this, &TCPConnection::OnConnect); | 545 socket->SignalConnect.connect(this, &TCPConnection::OnConnect); |
522 } | 546 } |
523 socket->SignalReadPacket.connect(this, &TCPConnection::OnReadPacket); | 547 socket->SignalReadPacket.connect(this, &TCPConnection::OnReadPacket); |
524 socket->SignalReadyToSend.connect(this, &TCPConnection::OnReadyToSend); | 548 socket->SignalReadyToSend.connect(this, &TCPConnection::OnReadyToSend); |
525 socket->SignalClose.connect(this, &TCPConnection::OnClose); | 549 socket->SignalClose.connect(this, &TCPConnection::OnClose); |
526 } | 550 } |
527 | 551 |
528 } // namespace cricket | 552 } // namespace cricket |
OLD | NEW |