1/* 2 * Copyright 2004 The WebRTC Project Authors. All rights reserved. 3 * 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 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 11#include "webrtc/p2p/base/port.h" 12 13#include <algorithm> 14#include <vector> 15 16#include "webrtc/p2p/base/common.h" 17#include "webrtc/p2p/base/portallocator.h" 18#include "webrtc/base/base64.h" 19#include "webrtc/base/crc32.h" 20#include "webrtc/base/helpers.h" 21#include "webrtc/base/logging.h" 22#include "webrtc/base/messagedigest.h" 23#include "webrtc/base/scoped_ptr.h" 24#include "webrtc/base/stringencode.h" 25#include "webrtc/base/stringutils.h" 26 27namespace { 28 29// Determines whether we have seen at least the given maximum number of 30// pings fail to have a response. 31inline bool TooManyFailures( 32 const std::vector<cricket::Connection::SentPing>& pings_since_last_response, 33 uint32_t maximum_failures, 34 uint32_t rtt_estimate, 35 uint32_t now) { 36 // If we haven't sent that many pings, then we can't have failed that many. 37 if (pings_since_last_response.size() < maximum_failures) 38 return false; 39 40 // Check if the window in which we would expect a response to the ping has 41 // already elapsed. 42 uint32_t expected_response_time = 43 pings_since_last_response[maximum_failures - 1].sent_time + rtt_estimate; 44 return now > expected_response_time; 45} 46 47// Determines whether we have gone too long without seeing any response. 48inline bool TooLongWithoutResponse( 49 const std::vector<cricket::Connection::SentPing>& pings_since_last_response, 50 uint32_t maximum_time, 51 uint32_t now) { 52 if (pings_since_last_response.size() == 0) 53 return false; 54 55 auto first = pings_since_last_response[0]; 56 return now > (first.sent_time + maximum_time); 57} 58 59// We will restrict RTT estimates (when used for determining state) to be 60// within a reasonable range. 61const uint32_t MINIMUM_RTT = 100; // 0.1 seconds 62const uint32_t MAXIMUM_RTT = 3000; // 3 seconds 63 64// When we don't have any RTT data, we have to pick something reasonable. We 65// use a large value just in case the connection is really slow. 66const uint32_t DEFAULT_RTT = MAXIMUM_RTT; 67 68// Computes our estimate of the RTT given the current estimate. 69inline uint32_t ConservativeRTTEstimate(uint32_t rtt) { 70 return std::max(MINIMUM_RTT, std::min(MAXIMUM_RTT, 2 * rtt)); 71} 72 73// Weighting of the old rtt value to new data. 74const int RTT_RATIO = 3; // 3 : 1 75 76// The delay before we begin checking if this port is useless. 77const int kPortTimeoutDelay = 30 * 1000; // 30 seconds 78} 79 80namespace cricket { 81 82// TODO(ronghuawu): Use "host", "srflx", "prflx" and "relay". But this requires 83// the signaling part be updated correspondingly as well. 84const char LOCAL_PORT_TYPE[] = "local"; 85const char STUN_PORT_TYPE[] = "stun"; 86const char PRFLX_PORT_TYPE[] = "prflx"; 87const char RELAY_PORT_TYPE[] = "relay"; 88 89const char UDP_PROTOCOL_NAME[] = "udp"; 90const char TCP_PROTOCOL_NAME[] = "tcp"; 91const char SSLTCP_PROTOCOL_NAME[] = "ssltcp"; 92 93static const char* const PROTO_NAMES[] = { UDP_PROTOCOL_NAME, 94 TCP_PROTOCOL_NAME, 95 SSLTCP_PROTOCOL_NAME }; 96 97const char* ProtoToString(ProtocolType proto) { 98 return PROTO_NAMES[proto]; 99} 100 101bool StringToProto(const char* value, ProtocolType* proto) { 102 for (size_t i = 0; i <= PROTO_LAST; ++i) { 103 if (_stricmp(PROTO_NAMES[i], value) == 0) { 104 *proto = static_cast<ProtocolType>(i); 105 return true; 106 } 107 } 108 return false; 109} 110 111// RFC 6544, TCP candidate encoding rules. 112const int DISCARD_PORT = 9; 113const char TCPTYPE_ACTIVE_STR[] = "active"; 114const char TCPTYPE_PASSIVE_STR[] = "passive"; 115const char TCPTYPE_SIMOPEN_STR[] = "so"; 116 117// Foundation: An arbitrary string that is the same for two candidates 118// that have the same type, base IP address, protocol (UDP, TCP, 119// etc.), and STUN or TURN server. If any of these are different, 120// then the foundation will be different. Two candidate pairs with 121// the same foundation pairs are likely to have similar network 122// characteristics. Foundations are used in the frozen algorithm. 123static std::string ComputeFoundation( 124 const std::string& type, 125 const std::string& protocol, 126 const rtc::SocketAddress& base_address) { 127 std::ostringstream ost; 128 ost << type << base_address.ipaddr().ToString() << protocol; 129 return rtc::ToString<uint32_t>(rtc::ComputeCrc32(ost.str())); 130} 131 132Port::Port(rtc::Thread* thread, 133 rtc::PacketSocketFactory* factory, 134 rtc::Network* network, 135 const rtc::IPAddress& ip, 136 const std::string& username_fragment, 137 const std::string& password) 138 : thread_(thread), 139 factory_(factory), 140 send_retransmit_count_attribute_(false), 141 network_(network), 142 ip_(ip), 143 min_port_(0), 144 max_port_(0), 145 component_(ICE_CANDIDATE_COMPONENT_DEFAULT), 146 generation_(0), 147 ice_username_fragment_(username_fragment), 148 password_(password), 149 timeout_delay_(kPortTimeoutDelay), 150 enable_port_packets_(false), 151 ice_role_(ICEROLE_UNKNOWN), 152 tiebreaker_(0), 153 shared_socket_(true), 154 candidate_filter_(CF_ALL) { 155 Construct(); 156} 157 158Port::Port(rtc::Thread* thread, 159 const std::string& type, 160 rtc::PacketSocketFactory* factory, 161 rtc::Network* network, 162 const rtc::IPAddress& ip, 163 uint16_t min_port, 164 uint16_t max_port, 165 const std::string& username_fragment, 166 const std::string& password) 167 : thread_(thread), 168 factory_(factory), 169 type_(type), 170 send_retransmit_count_attribute_(false), 171 network_(network), 172 ip_(ip), 173 min_port_(min_port), 174 max_port_(max_port), 175 component_(ICE_CANDIDATE_COMPONENT_DEFAULT), 176 generation_(0), 177 ice_username_fragment_(username_fragment), 178 password_(password), 179 timeout_delay_(kPortTimeoutDelay), 180 enable_port_packets_(false), 181 ice_role_(ICEROLE_UNKNOWN), 182 tiebreaker_(0), 183 shared_socket_(false), 184 candidate_filter_(CF_ALL) { 185 ASSERT(factory_ != NULL); 186 Construct(); 187} 188 189void Port::Construct() { 190 // TODO(pthatcher): Remove this old behavior once we're sure no one 191 // relies on it. If the username_fragment and password are empty, 192 // we should just create one. 193 if (ice_username_fragment_.empty()) { 194 ASSERT(password_.empty()); 195 ice_username_fragment_ = rtc::CreateRandomString(ICE_UFRAG_LENGTH); 196 password_ = rtc::CreateRandomString(ICE_PWD_LENGTH); 197 } 198 LOG_J(LS_INFO, this) << "Port created"; 199} 200 201Port::~Port() { 202 // Delete all of the remaining connections. We copy the list up front 203 // because each deletion will cause it to be modified. 204 205 std::vector<Connection*> list; 206 207 AddressMap::iterator iter = connections_.begin(); 208 while (iter != connections_.end()) { 209 list.push_back(iter->second); 210 ++iter; 211 } 212 213 for (uint32_t i = 0; i < list.size(); i++) 214 delete list[i]; 215} 216 217Connection* Port::GetConnection(const rtc::SocketAddress& remote_addr) { 218 AddressMap::const_iterator iter = connections_.find(remote_addr); 219 if (iter != connections_.end()) 220 return iter->second; 221 else 222 return NULL; 223} 224 225void Port::AddAddress(const rtc::SocketAddress& address, 226 const rtc::SocketAddress& base_address, 227 const rtc::SocketAddress& related_address, 228 const std::string& protocol, 229 const std::string& relay_protocol, 230 const std::string& tcptype, 231 const std::string& type, 232 uint32_t type_preference, 233 uint32_t relay_preference, 234 bool final) { 235 if (protocol == TCP_PROTOCOL_NAME && type == LOCAL_PORT_TYPE) { 236 ASSERT(!tcptype.empty()); 237 } 238 239 Candidate c; 240 c.set_id(rtc::CreateRandomString(8)); 241 c.set_component(component_); 242 c.set_type(type); 243 c.set_protocol(protocol); 244 c.set_relay_protocol(relay_protocol); 245 c.set_tcptype(tcptype); 246 c.set_address(address); 247 c.set_priority(c.GetPriority(type_preference, network_->preference(), 248 relay_preference)); 249 c.set_username(username_fragment()); 250 c.set_password(password_); 251 c.set_network_name(network_->name()); 252 c.set_network_type(network_->type()); 253 c.set_generation(generation_); 254 c.set_related_address(related_address); 255 c.set_foundation(ComputeFoundation(type, protocol, base_address)); 256 candidates_.push_back(c); 257 SignalCandidateReady(this, c); 258 259 if (final) { 260 SignalPortComplete(this); 261 } 262} 263 264void Port::AddConnection(Connection* conn) { 265 connections_[conn->remote_candidate().address()] = conn; 266 conn->SignalDestroyed.connect(this, &Port::OnConnectionDestroyed); 267 SignalConnectionCreated(this, conn); 268} 269 270void Port::OnReadPacket( 271 const char* data, size_t size, const rtc::SocketAddress& addr, 272 ProtocolType proto) { 273 // If the user has enabled port packets, just hand this over. 274 if (enable_port_packets_) { 275 SignalReadPacket(this, data, size, addr); 276 return; 277 } 278 279 // If this is an authenticated STUN request, then signal unknown address and 280 // send back a proper binding response. 281 rtc::scoped_ptr<IceMessage> msg; 282 std::string remote_username; 283 if (!GetStunMessage(data, size, addr, msg.accept(), &remote_username)) { 284 LOG_J(LS_ERROR, this) << "Received non-STUN packet from unknown address (" 285 << addr.ToSensitiveString() << ")"; 286 } else if (!msg) { 287 // STUN message handled already 288 } else if (msg->type() == STUN_BINDING_REQUEST) { 289 LOG(LS_INFO) << "Received STUN ping " 290 << " id=" << rtc::hex_encode(msg->transaction_id()) 291 << " from unknown address " << addr.ToSensitiveString(); 292 293 // Check for role conflicts. 294 if (!MaybeIceRoleConflict(addr, msg.get(), remote_username)) { 295 LOG(LS_INFO) << "Received conflicting role from the peer."; 296 return; 297 } 298 299 SignalUnknownAddress(this, addr, proto, msg.get(), remote_username, false); 300 } else { 301 // NOTE(tschmelcher): STUN_BINDING_RESPONSE is benign. It occurs if we 302 // pruned a connection for this port while it had STUN requests in flight, 303 // because we then get back responses for them, which this code correctly 304 // does not handle. 305 if (msg->type() != STUN_BINDING_RESPONSE) { 306 LOG_J(LS_ERROR, this) << "Received unexpected STUN message type (" 307 << msg->type() << ") from unknown address (" 308 << addr.ToSensitiveString() << ")"; 309 } 310 } 311} 312 313void Port::OnReadyToSend() { 314 AddressMap::iterator iter = connections_.begin(); 315 for (; iter != connections_.end(); ++iter) { 316 iter->second->OnReadyToSend(); 317 } 318} 319 320size_t Port::AddPrflxCandidate(const Candidate& local) { 321 candidates_.push_back(local); 322 return (candidates_.size() - 1); 323} 324 325bool Port::GetStunMessage(const char* data, size_t size, 326 const rtc::SocketAddress& addr, 327 IceMessage** out_msg, std::string* out_username) { 328 // NOTE: This could clearly be optimized to avoid allocating any memory. 329 // However, at the data rates we'll be looking at on the client side, 330 // this probably isn't worth worrying about. 331 ASSERT(out_msg != NULL); 332 ASSERT(out_username != NULL); 333 *out_msg = NULL; 334 out_username->clear(); 335 336 // Don't bother parsing the packet if we can tell it's not STUN. 337 // In ICE mode, all STUN packets will have a valid fingerprint. 338 if (!StunMessage::ValidateFingerprint(data, size)) { 339 return false; 340 } 341 342 // Parse the request message. If the packet is not a complete and correct 343 // STUN message, then ignore it. 344 rtc::scoped_ptr<IceMessage> stun_msg(new IceMessage()); 345 rtc::ByteBuffer buf(data, size); 346 if (!stun_msg->Read(&buf) || (buf.Length() > 0)) { 347 return false; 348 } 349 350 if (stun_msg->type() == STUN_BINDING_REQUEST) { 351 // Check for the presence of USERNAME and MESSAGE-INTEGRITY (if ICE) first. 352 // If not present, fail with a 400 Bad Request. 353 if (!stun_msg->GetByteString(STUN_ATTR_USERNAME) || 354 !stun_msg->GetByteString(STUN_ATTR_MESSAGE_INTEGRITY)) { 355 LOG_J(LS_ERROR, this) << "Received STUN request without username/M-I " 356 << "from " << addr.ToSensitiveString(); 357 SendBindingErrorResponse(stun_msg.get(), addr, STUN_ERROR_BAD_REQUEST, 358 STUN_ERROR_REASON_BAD_REQUEST); 359 return true; 360 } 361 362 // If the username is bad or unknown, fail with a 401 Unauthorized. 363 std::string local_ufrag; 364 std::string remote_ufrag; 365 if (!ParseStunUsername(stun_msg.get(), &local_ufrag, &remote_ufrag) || 366 local_ufrag != username_fragment()) { 367 LOG_J(LS_ERROR, this) << "Received STUN request with bad local username " 368 << local_ufrag << " from " 369 << addr.ToSensitiveString(); 370 SendBindingErrorResponse(stun_msg.get(), addr, STUN_ERROR_UNAUTHORIZED, 371 STUN_ERROR_REASON_UNAUTHORIZED); 372 return true; 373 } 374 375 // If ICE, and the MESSAGE-INTEGRITY is bad, fail with a 401 Unauthorized 376 if (!stun_msg->ValidateMessageIntegrity(data, size, password_)) { 377 LOG_J(LS_ERROR, this) << "Received STUN request with bad M-I " 378 << "from " << addr.ToSensitiveString() 379 << ", password_=" << password_; 380 SendBindingErrorResponse(stun_msg.get(), addr, STUN_ERROR_UNAUTHORIZED, 381 STUN_ERROR_REASON_UNAUTHORIZED); 382 return true; 383 } 384 out_username->assign(remote_ufrag); 385 } else if ((stun_msg->type() == STUN_BINDING_RESPONSE) || 386 (stun_msg->type() == STUN_BINDING_ERROR_RESPONSE)) { 387 if (stun_msg->type() == STUN_BINDING_ERROR_RESPONSE) { 388 if (const StunErrorCodeAttribute* error_code = stun_msg->GetErrorCode()) { 389 LOG_J(LS_ERROR, this) << "Received STUN binding error:" 390 << " class=" << error_code->eclass() 391 << " number=" << error_code->number() 392 << " reason='" << error_code->reason() << "'" 393 << " from " << addr.ToSensitiveString(); 394 // Return message to allow error-specific processing 395 } else { 396 LOG_J(LS_ERROR, this) << "Received STUN binding error without a error " 397 << "code from " << addr.ToSensitiveString(); 398 return true; 399 } 400 } 401 // NOTE: Username should not be used in verifying response messages. 402 out_username->clear(); 403 } else if (stun_msg->type() == STUN_BINDING_INDICATION) { 404 LOG_J(LS_VERBOSE, this) << "Received STUN binding indication:" 405 << " from " << addr.ToSensitiveString(); 406 out_username->clear(); 407 // No stun attributes will be verified, if it's stun indication message. 408 // Returning from end of the this method. 409 } else { 410 LOG_J(LS_ERROR, this) << "Received STUN packet with invalid type (" 411 << stun_msg->type() << ") from " 412 << addr.ToSensitiveString(); 413 return true; 414 } 415 416 // Return the STUN message found. 417 *out_msg = stun_msg.release(); 418 return true; 419} 420 421bool Port::IsCompatibleAddress(const rtc::SocketAddress& addr) { 422 int family = ip().family(); 423 // We use single-stack sockets, so families must match. 424 if (addr.family() != family) { 425 return false; 426 } 427 // Link-local IPv6 ports can only connect to other link-local IPv6 ports. 428 if (family == AF_INET6 && 429 (IPIsLinkLocal(ip()) != IPIsLinkLocal(addr.ipaddr()))) { 430 return false; 431 } 432 return true; 433} 434 435bool Port::ParseStunUsername(const StunMessage* stun_msg, 436 std::string* local_ufrag, 437 std::string* remote_ufrag) const { 438 // The packet must include a username that either begins or ends with our 439 // fragment. It should begin with our fragment if it is a request and it 440 // should end with our fragment if it is a response. 441 local_ufrag->clear(); 442 remote_ufrag->clear(); 443 const StunByteStringAttribute* username_attr = 444 stun_msg->GetByteString(STUN_ATTR_USERNAME); 445 if (username_attr == NULL) 446 return false; 447 448 // RFRAG:LFRAG 449 const std::string username = username_attr->GetString(); 450 size_t colon_pos = username.find(":"); 451 if (colon_pos == std::string::npos) { 452 return false; 453 } 454 455 *local_ufrag = username.substr(0, colon_pos); 456 *remote_ufrag = username.substr(colon_pos + 1, username.size()); 457 return true; 458} 459 460bool Port::MaybeIceRoleConflict( 461 const rtc::SocketAddress& addr, IceMessage* stun_msg, 462 const std::string& remote_ufrag) { 463 // Validate ICE_CONTROLLING or ICE_CONTROLLED attributes. 464 bool ret = true; 465 IceRole remote_ice_role = ICEROLE_UNKNOWN; 466 uint64_t remote_tiebreaker = 0; 467 const StunUInt64Attribute* stun_attr = 468 stun_msg->GetUInt64(STUN_ATTR_ICE_CONTROLLING); 469 if (stun_attr) { 470 remote_ice_role = ICEROLE_CONTROLLING; 471 remote_tiebreaker = stun_attr->value(); 472 } 473 474 // If |remote_ufrag| is same as port local username fragment and 475 // tie breaker value received in the ping message matches port 476 // tiebreaker value this must be a loopback call. 477 // We will treat this as valid scenario. 478 if (remote_ice_role == ICEROLE_CONTROLLING && 479 username_fragment() == remote_ufrag && 480 remote_tiebreaker == IceTiebreaker()) { 481 return true; 482 } 483 484 stun_attr = stun_msg->GetUInt64(STUN_ATTR_ICE_CONTROLLED); 485 if (stun_attr) { 486 remote_ice_role = ICEROLE_CONTROLLED; 487 remote_tiebreaker = stun_attr->value(); 488 } 489 490 switch (ice_role_) { 491 case ICEROLE_CONTROLLING: 492 if (ICEROLE_CONTROLLING == remote_ice_role) { 493 if (remote_tiebreaker >= tiebreaker_) { 494 SignalRoleConflict(this); 495 } else { 496 // Send Role Conflict (487) error response. 497 SendBindingErrorResponse(stun_msg, addr, 498 STUN_ERROR_ROLE_CONFLICT, STUN_ERROR_REASON_ROLE_CONFLICT); 499 ret = false; 500 } 501 } 502 break; 503 case ICEROLE_CONTROLLED: 504 if (ICEROLE_CONTROLLED == remote_ice_role) { 505 if (remote_tiebreaker < tiebreaker_) { 506 SignalRoleConflict(this); 507 } else { 508 // Send Role Conflict (487) error response. 509 SendBindingErrorResponse(stun_msg, addr, 510 STUN_ERROR_ROLE_CONFLICT, STUN_ERROR_REASON_ROLE_CONFLICT); 511 ret = false; 512 } 513 } 514 break; 515 default: 516 ASSERT(false); 517 } 518 return ret; 519} 520 521void Port::CreateStunUsername(const std::string& remote_username, 522 std::string* stun_username_attr_str) const { 523 stun_username_attr_str->clear(); 524 *stun_username_attr_str = remote_username; 525 stun_username_attr_str->append(":"); 526 stun_username_attr_str->append(username_fragment()); 527} 528 529void Port::SendBindingResponse(StunMessage* request, 530 const rtc::SocketAddress& addr) { 531 ASSERT(request->type() == STUN_BINDING_REQUEST); 532 533 // Retrieve the username from the request. 534 const StunByteStringAttribute* username_attr = 535 request->GetByteString(STUN_ATTR_USERNAME); 536 ASSERT(username_attr != NULL); 537 if (username_attr == NULL) { 538 // No valid username, skip the response. 539 return; 540 } 541 542 // Fill in the response message. 543 StunMessage response; 544 response.SetType(STUN_BINDING_RESPONSE); 545 response.SetTransactionID(request->transaction_id()); 546 const StunUInt32Attribute* retransmit_attr = 547 request->GetUInt32(STUN_ATTR_RETRANSMIT_COUNT); 548 if (retransmit_attr) { 549 // Inherit the incoming retransmit value in the response so the other side 550 // can see our view of lost pings. 551 response.AddAttribute(new StunUInt32Attribute( 552 STUN_ATTR_RETRANSMIT_COUNT, retransmit_attr->value())); 553 554 if (retransmit_attr->value() > CONNECTION_WRITE_CONNECT_FAILURES) { 555 LOG_J(LS_INFO, this) 556 << "Received a remote ping with high retransmit count: " 557 << retransmit_attr->value(); 558 } 559 } 560 561 response.AddAttribute( 562 new StunXorAddressAttribute(STUN_ATTR_XOR_MAPPED_ADDRESS, addr)); 563 response.AddMessageIntegrity(password_); 564 response.AddFingerprint(); 565 566 // Send the response message. 567 rtc::ByteBuffer buf; 568 response.Write(&buf); 569 rtc::PacketOptions options(DefaultDscpValue()); 570 auto err = SendTo(buf.Data(), buf.Length(), addr, options, false); 571 if (err < 0) { 572 LOG_J(LS_ERROR, this) 573 << "Failed to send STUN ping response" 574 << ", to=" << addr.ToSensitiveString() 575 << ", err=" << err 576 << ", id=" << rtc::hex_encode(response.transaction_id()); 577 } else { 578 // Log at LS_INFO if we send a stun ping response on an unwritable 579 // connection. 580 Connection* conn = GetConnection(addr); 581 rtc::LoggingSeverity sev = (conn && !conn->writable()) ? 582 rtc::LS_INFO : rtc::LS_VERBOSE; 583 LOG_JV(sev, this) 584 << "Sent STUN ping response" 585 << ", to=" << addr.ToSensitiveString() 586 << ", id=" << rtc::hex_encode(response.transaction_id()); 587 } 588} 589 590void Port::SendBindingErrorResponse(StunMessage* request, 591 const rtc::SocketAddress& addr, 592 int error_code, const std::string& reason) { 593 ASSERT(request->type() == STUN_BINDING_REQUEST); 594 595 // Fill in the response message. 596 StunMessage response; 597 response.SetType(STUN_BINDING_ERROR_RESPONSE); 598 response.SetTransactionID(request->transaction_id()); 599 600 // When doing GICE, we need to write out the error code incorrectly to 601 // maintain backwards compatiblility. 602 StunErrorCodeAttribute* error_attr = StunAttribute::CreateErrorCode(); 603 error_attr->SetCode(error_code); 604 error_attr->SetReason(reason); 605 response.AddAttribute(error_attr); 606 607 // Per Section 10.1.2, certain error cases don't get a MESSAGE-INTEGRITY, 608 // because we don't have enough information to determine the shared secret. 609 if (error_code != STUN_ERROR_BAD_REQUEST && 610 error_code != STUN_ERROR_UNAUTHORIZED) 611 response.AddMessageIntegrity(password_); 612 response.AddFingerprint(); 613 614 // Send the response message. 615 rtc::ByteBuffer buf; 616 response.Write(&buf); 617 rtc::PacketOptions options(DefaultDscpValue()); 618 SendTo(buf.Data(), buf.Length(), addr, options, false); 619 LOG_J(LS_INFO, this) << "Sending STUN binding error: reason=" << reason 620 << " to " << addr.ToSensitiveString(); 621} 622 623void Port::OnMessage(rtc::Message *pmsg) { 624 ASSERT(pmsg->message_id == MSG_DEAD); 625 if (dead()) { 626 Destroy(); 627 } 628} 629 630std::string Port::ToString() const { 631 std::stringstream ss; 632 ss << "Port[" << content_name_ << ":" << component_ 633 << ":" << generation_ << ":" << type_ 634 << ":" << network_->ToString() << "]"; 635 return ss.str(); 636} 637 638void Port::EnablePortPackets() { 639 enable_port_packets_ = true; 640} 641 642void Port::OnConnectionDestroyed(Connection* conn) { 643 AddressMap::iterator iter = 644 connections_.find(conn->remote_candidate().address()); 645 ASSERT(iter != connections_.end()); 646 connections_.erase(iter); 647 648 // On the controlled side, ports time out after all connections fail. 649 // Note: If a new connection is added after this message is posted, but it 650 // fails and is removed before kPortTimeoutDelay, then this message will 651 // still cause the Port to be destroyed. 652 if (dead()) { 653 thread_->PostDelayed(timeout_delay_, this, MSG_DEAD); 654 } 655} 656 657void Port::Destroy() { 658 ASSERT(connections_.empty()); 659 LOG_J(LS_INFO, this) << "Port deleted"; 660 SignalDestroyed(this); 661 delete this; 662} 663 664const std::string Port::username_fragment() const { 665 return ice_username_fragment_; 666} 667 668// A ConnectionRequest is a simple STUN ping used to determine writability. 669class ConnectionRequest : public StunRequest { 670 public: 671 explicit ConnectionRequest(Connection* connection) 672 : StunRequest(new IceMessage()), 673 connection_(connection) { 674 } 675 676 virtual ~ConnectionRequest() { 677 } 678 679 void Prepare(StunMessage* request) override { 680 request->SetType(STUN_BINDING_REQUEST); 681 std::string username; 682 connection_->port()->CreateStunUsername( 683 connection_->remote_candidate().username(), &username); 684 request->AddAttribute( 685 new StunByteStringAttribute(STUN_ATTR_USERNAME, username)); 686 687 // connection_ already holds this ping, so subtract one from count. 688 if (connection_->port()->send_retransmit_count_attribute()) { 689 request->AddAttribute(new StunUInt32Attribute( 690 STUN_ATTR_RETRANSMIT_COUNT, 691 static_cast<uint32_t>(connection_->pings_since_last_response_.size() - 692 1))); 693 } 694 695 // Adding ICE_CONTROLLED or ICE_CONTROLLING attribute based on the role. 696 if (connection_->port()->GetIceRole() == ICEROLE_CONTROLLING) { 697 request->AddAttribute(new StunUInt64Attribute( 698 STUN_ATTR_ICE_CONTROLLING, connection_->port()->IceTiebreaker())); 699 // Since we are trying aggressive nomination, sending USE-CANDIDATE 700 // attribute in every ping. 701 // If we are dealing with a ice-lite end point, nomination flag 702 // in Connection will be set to false by default. Once the connection 703 // becomes "best connection", nomination flag will be turned on. 704 if (connection_->use_candidate_attr()) { 705 request->AddAttribute(new StunByteStringAttribute( 706 STUN_ATTR_USE_CANDIDATE)); 707 } 708 } else if (connection_->port()->GetIceRole() == ICEROLE_CONTROLLED) { 709 request->AddAttribute(new StunUInt64Attribute( 710 STUN_ATTR_ICE_CONTROLLED, connection_->port()->IceTiebreaker())); 711 } else { 712 ASSERT(false); 713 } 714 715 // Adding PRIORITY Attribute. 716 // Changing the type preference to Peer Reflexive and local preference 717 // and component id information is unchanged from the original priority. 718 // priority = (2^24)*(type preference) + 719 // (2^8)*(local preference) + 720 // (2^0)*(256 - component ID) 721 uint32_t prflx_priority = 722 ICE_TYPE_PREFERENCE_PRFLX << 24 | 723 (connection_->local_candidate().priority() & 0x00FFFFFF); 724 request->AddAttribute( 725 new StunUInt32Attribute(STUN_ATTR_PRIORITY, prflx_priority)); 726 727 // Adding Message Integrity attribute. 728 request->AddMessageIntegrity(connection_->remote_candidate().password()); 729 // Adding Fingerprint. 730 request->AddFingerprint(); 731 } 732 733 void OnResponse(StunMessage* response) override { 734 connection_->OnConnectionRequestResponse(this, response); 735 } 736 737 void OnErrorResponse(StunMessage* response) override { 738 connection_->OnConnectionRequestErrorResponse(this, response); 739 } 740 741 void OnTimeout() override { 742 connection_->OnConnectionRequestTimeout(this); 743 } 744 745 void OnSent() override { 746 connection_->OnConnectionRequestSent(this); 747 // Each request is sent only once. After a single delay , the request will 748 // time out. 749 timeout_ = true; 750 } 751 752 int resend_delay() override { 753 return CONNECTION_RESPONSE_TIMEOUT; 754 } 755 756 private: 757 Connection* connection_; 758}; 759 760// 761// Connection 762// 763 764Connection::Connection(Port* port, 765 size_t index, 766 const Candidate& remote_candidate) 767 : port_(port), 768 local_candidate_index_(index), 769 remote_candidate_(remote_candidate), 770 write_state_(STATE_WRITE_INIT), 771 receiving_(false), 772 connected_(true), 773 pruned_(false), 774 use_candidate_attr_(false), 775 nominated_(false), 776 remote_ice_mode_(ICEMODE_FULL), 777 requests_(port->thread()), 778 rtt_(DEFAULT_RTT), 779 last_ping_sent_(0), 780 last_ping_received_(0), 781 last_data_received_(0), 782 last_ping_response_received_(0), 783 recv_rate_tracker_(100u, 10u), 784 send_rate_tracker_(100u, 10u), 785 sent_packets_discarded_(0), 786 sent_packets_total_(0), 787 reported_(false), 788 state_(STATE_WAITING), 789 receiving_timeout_(WEAK_CONNECTION_RECEIVE_TIMEOUT), 790 time_created_ms_(rtc::Time()) { 791 // All of our connections start in WAITING state. 792 // TODO(mallinath) - Start connections from STATE_FROZEN. 793 // Wire up to send stun packets 794 requests_.SignalSendPacket.connect(this, &Connection::OnSendStunPacket); 795 LOG_J(LS_INFO, this) << "Connection created"; 796} 797 798Connection::~Connection() { 799} 800 801const Candidate& Connection::local_candidate() const { 802 ASSERT(local_candidate_index_ < port_->Candidates().size()); 803 return port_->Candidates()[local_candidate_index_]; 804} 805 806uint64_t Connection::priority() const { 807 uint64_t priority = 0; 808 // RFC 5245 - 5.7.2. Computing Pair Priority and Ordering Pairs 809 // Let G be the priority for the candidate provided by the controlling 810 // agent. Let D be the priority for the candidate provided by the 811 // controlled agent. 812 // pair priority = 2^32*MIN(G,D) + 2*MAX(G,D) + (G>D?1:0) 813 IceRole role = port_->GetIceRole(); 814 if (role != ICEROLE_UNKNOWN) { 815 uint32_t g = 0; 816 uint32_t d = 0; 817 if (role == ICEROLE_CONTROLLING) { 818 g = local_candidate().priority(); 819 d = remote_candidate_.priority(); 820 } else { 821 g = remote_candidate_.priority(); 822 d = local_candidate().priority(); 823 } 824 priority = std::min(g, d); 825 priority = priority << 32; 826 priority += 2 * std::max(g, d) + (g > d ? 1 : 0); 827 } 828 return priority; 829} 830 831void Connection::set_write_state(WriteState value) { 832 WriteState old_value = write_state_; 833 write_state_ = value; 834 if (value != old_value) { 835 LOG_J(LS_VERBOSE, this) << "set_write_state from: " << old_value << " to " 836 << value; 837 SignalStateChange(this); 838 } 839} 840 841void Connection::set_receiving(bool value) { 842 if (value != receiving_) { 843 LOG_J(LS_VERBOSE, this) << "set_receiving to " << value; 844 receiving_ = value; 845 SignalStateChange(this); 846 } 847} 848 849void Connection::set_state(State state) { 850 State old_state = state_; 851 state_ = state; 852 if (state != old_state) { 853 LOG_J(LS_VERBOSE, this) << "set_state"; 854 } 855} 856 857void Connection::set_connected(bool value) { 858 bool old_value = connected_; 859 connected_ = value; 860 if (value != old_value) { 861 LOG_J(LS_VERBOSE, this) << "set_connected from: " << old_value << " to " 862 << value; 863 } 864} 865 866void Connection::set_use_candidate_attr(bool enable) { 867 use_candidate_attr_ = enable; 868} 869 870void Connection::OnSendStunPacket(const void* data, size_t size, 871 StunRequest* req) { 872 rtc::PacketOptions options(port_->DefaultDscpValue()); 873 auto err = port_->SendTo( 874 data, size, remote_candidate_.address(), options, false); 875 if (err < 0) { 876 LOG_J(LS_WARNING, this) << "Failed to send STUN ping " 877 << " err=" << err 878 << " id=" << rtc::hex_encode(req->id()); 879 } 880} 881 882void Connection::OnReadPacket( 883 const char* data, size_t size, const rtc::PacketTime& packet_time) { 884 rtc::scoped_ptr<IceMessage> msg; 885 std::string remote_ufrag; 886 const rtc::SocketAddress& addr(remote_candidate_.address()); 887 if (!port_->GetStunMessage(data, size, addr, msg.accept(), &remote_ufrag)) { 888 // The packet did not parse as a valid STUN message 889 // This is a data packet, pass it along. 890 set_receiving(true); 891 last_data_received_ = rtc::Time(); 892 recv_rate_tracker_.AddSamples(size); 893 SignalReadPacket(this, data, size, packet_time); 894 895 // If timed out sending writability checks, start up again 896 if (!pruned_ && (write_state_ == STATE_WRITE_TIMEOUT)) { 897 LOG(LS_WARNING) << "Received a data packet on a timed-out Connection. " 898 << "Resetting state to STATE_WRITE_INIT."; 899 set_write_state(STATE_WRITE_INIT); 900 } 901 } else if (!msg) { 902 // The packet was STUN, but failed a check and was handled internally. 903 } else { 904 // The packet is STUN and passed the Port checks. 905 // Perform our own checks to ensure this packet is valid. 906 // If this is a STUN request, then update the receiving bit and respond. 907 // If this is a STUN response, then update the writable bit. 908 // Log at LS_INFO if we receive a ping on an unwritable connection. 909 rtc::LoggingSeverity sev = (!writable() ? rtc::LS_INFO : rtc::LS_VERBOSE); 910 switch (msg->type()) { 911 case STUN_BINDING_REQUEST: 912 LOG_JV(sev, this) << "Received STUN ping" 913 << ", id=" << rtc::hex_encode(msg->transaction_id()); 914 915 if (remote_ufrag == remote_candidate_.username()) { 916 HandleBindingRequest(msg.get()); 917 } else { 918 // The packet had the right local username, but the remote username 919 // was not the right one for the remote address. 920 LOG_J(LS_ERROR, this) 921 << "Received STUN request with bad remote username " 922 << remote_ufrag; 923 port_->SendBindingErrorResponse(msg.get(), addr, 924 STUN_ERROR_UNAUTHORIZED, 925 STUN_ERROR_REASON_UNAUTHORIZED); 926 927 } 928 break; 929 930 // Response from remote peer. Does it match request sent? 931 // This doesn't just check, it makes callbacks if transaction 932 // id's match. 933 case STUN_BINDING_RESPONSE: 934 case STUN_BINDING_ERROR_RESPONSE: 935 if (msg->ValidateMessageIntegrity( 936 data, size, remote_candidate().password())) { 937 requests_.CheckResponse(msg.get()); 938 } 939 // Otherwise silently discard the response message. 940 break; 941 942 // Remote end point sent an STUN indication instead of regular binding 943 // request. In this case |last_ping_received_| will be updated but no 944 // response will be sent. 945 case STUN_BINDING_INDICATION: 946 ReceivedPing(); 947 break; 948 949 default: 950 ASSERT(false); 951 break; 952 } 953 } 954} 955 956void Connection::HandleBindingRequest(IceMessage* msg) { 957 // This connection should now be receiving. 958 ReceivedPing(); 959 960 const rtc::SocketAddress& remote_addr = remote_candidate_.address(); 961 const std::string& remote_ufrag = remote_candidate_.username(); 962 // Check for role conflicts. 963 if (!port_->MaybeIceRoleConflict(remote_addr, msg, remote_ufrag)) { 964 // Received conflicting role from the peer. 965 LOG(LS_INFO) << "Received conflicting role from the peer."; 966 return; 967 } 968 969 // This is a validated stun request from remote peer. 970 port_->SendBindingResponse(msg, remote_addr); 971 972 // If it timed out on writing check, start up again 973 if (!pruned_ && write_state_ == STATE_WRITE_TIMEOUT) { 974 set_write_state(STATE_WRITE_INIT); 975 } 976 977 if (port_->GetIceRole() == ICEROLE_CONTROLLED) { 978 const StunByteStringAttribute* use_candidate_attr = 979 msg->GetByteString(STUN_ATTR_USE_CANDIDATE); 980 if (use_candidate_attr) { 981 set_nominated(true); 982 SignalNominated(this); 983 } 984 } 985} 986 987void Connection::OnReadyToSend() { 988 if (write_state_ == STATE_WRITABLE) { 989 SignalReadyToSend(this); 990 } 991} 992 993void Connection::Prune() { 994 if (!pruned_ || active()) { 995 LOG_J(LS_VERBOSE, this) << "Connection pruned"; 996 pruned_ = true; 997 requests_.Clear(); 998 set_write_state(STATE_WRITE_TIMEOUT); 999 } 1000} 1001 1002void Connection::Destroy() { 1003 LOG_J(LS_VERBOSE, this) << "Connection destroyed"; 1004 port_->thread()->Post(this, MSG_DELETE); 1005} 1006 1007void Connection::FailAndDestroy() { 1008 set_state(Connection::STATE_FAILED); 1009 Destroy(); 1010} 1011 1012void Connection::PrintPingsSinceLastResponse(std::string* s, size_t max) { 1013 std::ostringstream oss; 1014 oss << std::boolalpha; 1015 if (pings_since_last_response_.size() > max) { 1016 for (size_t i = 0; i < max; i++) { 1017 const SentPing& ping = pings_since_last_response_[i]; 1018 oss << rtc::hex_encode(ping.id) << " "; 1019 } 1020 oss << "... " << (pings_since_last_response_.size() - max) << " more"; 1021 } else { 1022 for (const SentPing& ping : pings_since_last_response_) { 1023 oss << rtc::hex_encode(ping.id) << " "; 1024 } 1025 } 1026 *s = oss.str(); 1027} 1028 1029void Connection::UpdateState(uint32_t now) { 1030 uint32_t rtt = ConservativeRTTEstimate(rtt_); 1031 1032 if (LOG_CHECK_LEVEL(LS_VERBOSE)) { 1033 std::string pings; 1034 PrintPingsSinceLastResponse(&pings, 5); 1035 LOG_J(LS_VERBOSE, this) << "UpdateState()" 1036 << ", ms since last received response=" 1037 << now - last_ping_response_received_ 1038 << ", ms since last received data=" 1039 << now - last_data_received_ 1040 << ", rtt=" << rtt 1041 << ", pings_since_last_response=" << pings; 1042 } 1043 1044 // Check the writable state. (The order of these checks is important.) 1045 // 1046 // Before becoming unwritable, we allow for a fixed number of pings to fail 1047 // (i.e., receive no response). We also have to give the response time to 1048 // get back, so we include a conservative estimate of this. 1049 // 1050 // Before timing out writability, we give a fixed amount of time. This is to 1051 // allow for changes in network conditions. 1052 1053 if ((write_state_ == STATE_WRITABLE) && 1054 TooManyFailures(pings_since_last_response_, 1055 CONNECTION_WRITE_CONNECT_FAILURES, 1056 rtt, 1057 now) && 1058 TooLongWithoutResponse(pings_since_last_response_, 1059 CONNECTION_WRITE_CONNECT_TIMEOUT, 1060 now)) { 1061 uint32_t max_pings = CONNECTION_WRITE_CONNECT_FAILURES; 1062 LOG_J(LS_INFO, this) << "Unwritable after " << max_pings 1063 << " ping failures and " 1064 << now - pings_since_last_response_[0].sent_time 1065 << " ms without a response," 1066 << " ms since last received ping=" 1067 << now - last_ping_received_ 1068 << " ms since last received data=" 1069 << now - last_data_received_ 1070 << " rtt=" << rtt; 1071 set_write_state(STATE_WRITE_UNRELIABLE); 1072 } 1073 if ((write_state_ == STATE_WRITE_UNRELIABLE || 1074 write_state_ == STATE_WRITE_INIT) && 1075 TooLongWithoutResponse(pings_since_last_response_, 1076 CONNECTION_WRITE_TIMEOUT, 1077 now)) { 1078 LOG_J(LS_INFO, this) << "Timed out after " 1079 << now - pings_since_last_response_[0].sent_time 1080 << " ms without a response" 1081 << ", rtt=" << rtt; 1082 set_write_state(STATE_WRITE_TIMEOUT); 1083 } 1084 1085 // Check the receiving state. 1086 uint32_t last_recv_time = last_received(); 1087 bool receiving = now <= last_recv_time + receiving_timeout_; 1088 set_receiving(receiving); 1089 if (dead(now)) { 1090 Destroy(); 1091 } 1092} 1093 1094void Connection::Ping(uint32_t now) { 1095 last_ping_sent_ = now; 1096 ConnectionRequest *req = new ConnectionRequest(this); 1097 pings_since_last_response_.push_back(SentPing(req->id(), now)); 1098 LOG_J(LS_VERBOSE, this) << "Sending STUN ping " 1099 << ", id=" << rtc::hex_encode(req->id()); 1100 requests_.Send(req); 1101 state_ = STATE_INPROGRESS; 1102} 1103 1104void Connection::ReceivedPing() { 1105 set_receiving(true); 1106 last_ping_received_ = rtc::Time(); 1107} 1108 1109void Connection::ReceivedPingResponse() { 1110 // We've already validated that this is a STUN binding response with 1111 // the correct local and remote username for this connection. 1112 // So if we're not already, become writable. We may be bringing a pruned 1113 // connection back to life, but if we don't really want it, we can always 1114 // prune it again. 1115 set_receiving(true); 1116 set_write_state(STATE_WRITABLE); 1117 set_state(STATE_SUCCEEDED); 1118 pings_since_last_response_.clear(); 1119 last_ping_response_received_ = rtc::Time(); 1120} 1121 1122bool Connection::dead(uint32_t now) const { 1123 if (last_received() > 0) { 1124 // If it has ever received anything, we keep it alive until it hasn't 1125 // received anything for DEAD_CONNECTION_RECEIVE_TIMEOUT. This covers the 1126 // normal case of a successfully used connection that stops working. This 1127 // also allows a remote peer to continue pinging over a locally inactive 1128 // (pruned) connection. 1129 return (now > (last_received() + DEAD_CONNECTION_RECEIVE_TIMEOUT)); 1130 } 1131 1132 if (active()) { 1133 // If it has never received anything, keep it alive as long as it is 1134 // actively pinging and not pruned. Otherwise, the connection might be 1135 // deleted before it has a chance to ping. This is the normal case for a 1136 // new connection that is pinging but hasn't received anything yet. 1137 return false; 1138 } 1139 1140 // If it has never received anything and is not actively pinging (pruned), we 1141 // keep it around for at least MIN_CONNECTION_LIFETIME to prevent connections 1142 // from being pruned too quickly during a network change event when two 1143 // networks would be up simultaneously but only for a brief period. 1144 return now > (time_created_ms_ + MIN_CONNECTION_LIFETIME); 1145} 1146 1147std::string Connection::ToDebugId() const { 1148 std::stringstream ss; 1149 ss << std::hex << this; 1150 return ss.str(); 1151} 1152 1153std::string Connection::ToString() const { 1154 const char CONNECT_STATE_ABBREV[2] = { 1155 '-', // not connected (false) 1156 'C', // connected (true) 1157 }; 1158 const char RECEIVE_STATE_ABBREV[2] = { 1159 '-', // not receiving (false) 1160 'R', // receiving (true) 1161 }; 1162 const char WRITE_STATE_ABBREV[4] = { 1163 'W', // STATE_WRITABLE 1164 'w', // STATE_WRITE_UNRELIABLE 1165 '-', // STATE_WRITE_INIT 1166 'x', // STATE_WRITE_TIMEOUT 1167 }; 1168 const std::string ICESTATE[4] = { 1169 "W", // STATE_WAITING 1170 "I", // STATE_INPROGRESS 1171 "S", // STATE_SUCCEEDED 1172 "F" // STATE_FAILED 1173 }; 1174 const Candidate& local = local_candidate(); 1175 const Candidate& remote = remote_candidate(); 1176 std::stringstream ss; 1177 ss << "Conn[" << ToDebugId() 1178 << ":" << port_->content_name() 1179 << ":" << local.id() << ":" << local.component() 1180 << ":" << local.generation() 1181 << ":" << local.type() << ":" << local.protocol() 1182 << ":" << local.address().ToSensitiveString() 1183 << "->" << remote.id() << ":" << remote.component() 1184 << ":" << remote.priority() 1185 << ":" << remote.type() << ":" 1186 << remote.protocol() << ":" << remote.address().ToSensitiveString() << "|" 1187 << CONNECT_STATE_ABBREV[connected()] 1188 << RECEIVE_STATE_ABBREV[receiving()] 1189 << WRITE_STATE_ABBREV[write_state()] 1190 << ICESTATE[state()] << "|" 1191 << priority() << "|"; 1192 if (rtt_ < DEFAULT_RTT) { 1193 ss << rtt_ << "]"; 1194 } else { 1195 ss << "-]"; 1196 } 1197 return ss.str(); 1198} 1199 1200std::string Connection::ToSensitiveString() const { 1201 return ToString(); 1202} 1203 1204void Connection::OnConnectionRequestResponse(ConnectionRequest* request, 1205 StunMessage* response) { 1206 // Log at LS_INFO if we receive a ping response on an unwritable 1207 // connection. 1208 rtc::LoggingSeverity sev = !writable() ? rtc::LS_INFO : rtc::LS_VERBOSE; 1209 1210 uint32_t rtt = request->Elapsed(); 1211 1212 ReceivedPingResponse(); 1213 1214 if (LOG_CHECK_LEVEL_V(sev)) { 1215 bool use_candidate = ( 1216 response->GetByteString(STUN_ATTR_USE_CANDIDATE) != nullptr); 1217 std::string pings; 1218 PrintPingsSinceLastResponse(&pings, 5); 1219 LOG_JV(sev, this) << "Received STUN ping response" 1220 << ", id=" << rtc::hex_encode(request->id()) 1221 << ", code=0" // Makes logging easier to parse. 1222 << ", rtt=" << rtt 1223 << ", use_candidate=" << use_candidate 1224 << ", pings_since_last_response=" << pings; 1225 } 1226 1227 rtt_ = (RTT_RATIO * rtt_ + rtt) / (RTT_RATIO + 1); 1228 1229 MaybeAddPrflxCandidate(request, response); 1230} 1231 1232void Connection::OnConnectionRequestErrorResponse(ConnectionRequest* request, 1233 StunMessage* response) { 1234 const StunErrorCodeAttribute* error_attr = response->GetErrorCode(); 1235 int error_code = STUN_ERROR_GLOBAL_FAILURE; 1236 if (error_attr) { 1237 error_code = error_attr->code(); 1238 } 1239 1240 LOG_J(LS_INFO, this) << "Received STUN error response" 1241 << " id=" << rtc::hex_encode(request->id()) 1242 << " code=" << error_code 1243 << " rtt=" << request->Elapsed(); 1244 1245 if (error_code == STUN_ERROR_UNKNOWN_ATTRIBUTE || 1246 error_code == STUN_ERROR_SERVER_ERROR || 1247 error_code == STUN_ERROR_UNAUTHORIZED) { 1248 // Recoverable error, retry 1249 } else if (error_code == STUN_ERROR_STALE_CREDENTIALS) { 1250 // Race failure, retry 1251 } else if (error_code == STUN_ERROR_ROLE_CONFLICT) { 1252 HandleRoleConflictFromPeer(); 1253 } else { 1254 // This is not a valid connection. 1255 LOG_J(LS_ERROR, this) << "Received STUN error response, code=" 1256 << error_code << "; killing connection"; 1257 FailAndDestroy(); 1258 } 1259} 1260 1261void Connection::OnConnectionRequestTimeout(ConnectionRequest* request) { 1262 // Log at LS_INFO if we miss a ping on a writable connection. 1263 rtc::LoggingSeverity sev = writable() ? rtc::LS_INFO : rtc::LS_VERBOSE; 1264 LOG_JV(sev, this) << "Timing-out STUN ping " 1265 << rtc::hex_encode(request->id()) 1266 << " after " << request->Elapsed() << " ms"; 1267} 1268 1269void Connection::OnConnectionRequestSent(ConnectionRequest* request) { 1270 // Log at LS_INFO if we send a ping on an unwritable connection. 1271 rtc::LoggingSeverity sev = !writable() ? rtc::LS_INFO : rtc::LS_VERBOSE; 1272 bool use_candidate = use_candidate_attr(); 1273 LOG_JV(sev, this) << "Sent STUN ping" 1274 << ", id=" << rtc::hex_encode(request->id()) 1275 << ", use_candidate=" << use_candidate; 1276} 1277 1278void Connection::HandleRoleConflictFromPeer() { 1279 port_->SignalRoleConflict(port_); 1280} 1281 1282void Connection::MaybeSetRemoteIceCredentials(const std::string& ice_ufrag, 1283 const std::string& ice_pwd) { 1284 if (remote_candidate_.username() == ice_ufrag && 1285 remote_candidate_.password().empty()) { 1286 remote_candidate_.set_password(ice_pwd); 1287 } 1288} 1289 1290void Connection::MaybeUpdatePeerReflexiveCandidate( 1291 const Candidate& new_candidate) { 1292 if (remote_candidate_.type() == PRFLX_PORT_TYPE && 1293 new_candidate.type() != PRFLX_PORT_TYPE && 1294 remote_candidate_.protocol() == new_candidate.protocol() && 1295 remote_candidate_.address() == new_candidate.address() && 1296 remote_candidate_.username() == new_candidate.username() && 1297 remote_candidate_.password() == new_candidate.password() && 1298 remote_candidate_.generation() == new_candidate.generation()) { 1299 remote_candidate_ = new_candidate; 1300 } 1301} 1302 1303void Connection::OnMessage(rtc::Message *pmsg) { 1304 ASSERT(pmsg->message_id == MSG_DELETE); 1305 LOG_J(LS_INFO, this) << "Connection deleted"; 1306 SignalDestroyed(this); 1307 delete this; 1308} 1309 1310uint32_t Connection::last_received() const { 1311 return std::max(last_data_received_, 1312 std::max(last_ping_received_, last_ping_response_received_)); 1313} 1314 1315size_t Connection::recv_bytes_second() { 1316 return round(recv_rate_tracker_.ComputeRate()); 1317} 1318 1319size_t Connection::recv_total_bytes() { 1320 return recv_rate_tracker_.TotalSampleCount(); 1321} 1322 1323size_t Connection::sent_bytes_second() { 1324 return round(send_rate_tracker_.ComputeRate()); 1325} 1326 1327size_t Connection::sent_total_bytes() { 1328 return send_rate_tracker_.TotalSampleCount(); 1329} 1330 1331size_t Connection::sent_discarded_packets() { 1332 return sent_packets_discarded_; 1333} 1334 1335size_t Connection::sent_total_packets() { 1336 return sent_packets_total_; 1337} 1338 1339void Connection::MaybeAddPrflxCandidate(ConnectionRequest* request, 1340 StunMessage* response) { 1341 // RFC 5245 1342 // The agent checks the mapped address from the STUN response. If the 1343 // transport address does not match any of the local candidates that the 1344 // agent knows about, the mapped address represents a new candidate -- a 1345 // peer reflexive candidate. 1346 const StunAddressAttribute* addr = 1347 response->GetAddress(STUN_ATTR_XOR_MAPPED_ADDRESS); 1348 if (!addr) { 1349 LOG(LS_WARNING) << "Connection::OnConnectionRequestResponse - " 1350 << "No MAPPED-ADDRESS or XOR-MAPPED-ADDRESS found in the " 1351 << "stun response message"; 1352 return; 1353 } 1354 1355 bool known_addr = false; 1356 for (size_t i = 0; i < port_->Candidates().size(); ++i) { 1357 if (port_->Candidates()[i].address() == addr->GetAddress()) { 1358 known_addr = true; 1359 break; 1360 } 1361 } 1362 if (known_addr) { 1363 return; 1364 } 1365 1366 // RFC 5245 1367 // Its priority is set equal to the value of the PRIORITY attribute 1368 // in the Binding request. 1369 const StunUInt32Attribute* priority_attr = 1370 request->msg()->GetUInt32(STUN_ATTR_PRIORITY); 1371 if (!priority_attr) { 1372 LOG(LS_WARNING) << "Connection::OnConnectionRequestResponse - " 1373 << "No STUN_ATTR_PRIORITY found in the " 1374 << "stun response message"; 1375 return; 1376 } 1377 const uint32_t priority = priority_attr->value(); 1378 std::string id = rtc::CreateRandomString(8); 1379 1380 Candidate new_local_candidate; 1381 new_local_candidate.set_id(id); 1382 new_local_candidate.set_component(local_candidate().component()); 1383 new_local_candidate.set_type(PRFLX_PORT_TYPE); 1384 new_local_candidate.set_protocol(local_candidate().protocol()); 1385 new_local_candidate.set_address(addr->GetAddress()); 1386 new_local_candidate.set_priority(priority); 1387 new_local_candidate.set_username(local_candidate().username()); 1388 new_local_candidate.set_password(local_candidate().password()); 1389 new_local_candidate.set_network_name(local_candidate().network_name()); 1390 new_local_candidate.set_network_type(local_candidate().network_type()); 1391 new_local_candidate.set_related_address(local_candidate().address()); 1392 new_local_candidate.set_foundation( 1393 ComputeFoundation(PRFLX_PORT_TYPE, local_candidate().protocol(), 1394 local_candidate().address())); 1395 1396 // Change the local candidate of this Connection to the new prflx candidate. 1397 local_candidate_index_ = port_->AddPrflxCandidate(new_local_candidate); 1398 1399 // SignalStateChange to force a re-sort in P2PTransportChannel as this 1400 // Connection's local candidate has changed. 1401 SignalStateChange(this); 1402} 1403 1404ProxyConnection::ProxyConnection(Port* port, 1405 size_t index, 1406 const Candidate& remote_candidate) 1407 : Connection(port, index, remote_candidate) {} 1408 1409int ProxyConnection::Send(const void* data, size_t size, 1410 const rtc::PacketOptions& options) { 1411 if (write_state_ == STATE_WRITE_INIT || write_state_ == STATE_WRITE_TIMEOUT) { 1412 error_ = EWOULDBLOCK; 1413 return SOCKET_ERROR; 1414 } 1415 sent_packets_total_++; 1416 int sent = port_->SendTo(data, size, remote_candidate_.address(), 1417 options, true); 1418 if (sent <= 0) { 1419 ASSERT(sent < 0); 1420 error_ = port_->GetError(); 1421 sent_packets_discarded_++; 1422 } else { 1423 send_rate_tracker_.AddSamples(sent); 1424 } 1425 return sent; 1426} 1427 1428} // namespace cricket 1429