Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(349)

Side by Side Diff: webrtc/p2p/base/port.cc

Issue 1336553003: Revert change which removes GICE (Closed) Base URL: https://chromium.googlesource.com/external/webrtc@master
Patch Set: Created 5 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « webrtc/p2p/base/port.h ('k') | webrtc/p2p/base/port_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
51 uint32 maximum_time, 51 uint32 maximum_time,
52 uint32 now) { 52 uint32 now) {
53 53
54 if (pings_since_last_response.size() == 0) 54 if (pings_since_last_response.size() == 0)
55 return false; 55 return false;
56 56
57 auto first = pings_since_last_response[0]; 57 auto first = pings_since_last_response[0];
58 return now > (first.sent_time + maximum_time); 58 return now > (first.sent_time + maximum_time);
59 } 59 }
60 60
61 // GICE(ICEPROTO_GOOGLE) requires different username for RTP and RTCP.
62 // This function generates a different username by +1 on the last character of
63 // the given username (|rtp_ufrag|).
64 std::string GetRtcpUfragFromRtpUfrag(const std::string& rtp_ufrag) {
65 ASSERT(!rtp_ufrag.empty());
66 if (rtp_ufrag.empty()) {
67 return rtp_ufrag;
68 }
69 // Change the last character to the one next to it in the base64 table.
70 char new_last_char;
71 if (!rtc::Base64::GetNextBase64Char(rtp_ufrag[rtp_ufrag.size() - 1],
72 &new_last_char)) {
73 // Should not be here.
74 ASSERT(false);
75 }
76 std::string rtcp_ufrag = rtp_ufrag;
77 rtcp_ufrag[rtcp_ufrag.size() - 1] = new_last_char;
78 ASSERT(rtcp_ufrag != rtp_ufrag);
79 return rtcp_ufrag;
80 }
81
61 // We will restrict RTT estimates (when used for determining state) to be 82 // We will restrict RTT estimates (when used for determining state) to be
62 // within a reasonable range. 83 // within a reasonable range.
63 const uint32 MINIMUM_RTT = 100; // 0.1 seconds 84 const uint32 MINIMUM_RTT = 100; // 0.1 seconds
64 const uint32 MAXIMUM_RTT = 3000; // 3 seconds 85 const uint32 MAXIMUM_RTT = 3000; // 3 seconds
65 86
66 // When we don't have any RTT data, we have to pick something reasonable. We 87 // When we don't have any RTT data, we have to pick something reasonable. We
67 // use a large value just in case the connection is really slow. 88 // use a large value just in case the connection is really slow.
68 const uint32 DEFAULT_RTT = MAXIMUM_RTT; 89 const uint32 DEFAULT_RTT = MAXIMUM_RTT;
69 90
70 // Computes our estimate of the RTT given the current estimate. 91 // Computes our estimate of the RTT given the current estimate.
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
143 network_(network), 164 network_(network),
144 ip_(ip), 165 ip_(ip),
145 min_port_(0), 166 min_port_(0),
146 max_port_(0), 167 max_port_(0),
147 component_(ICE_CANDIDATE_COMPONENT_DEFAULT), 168 component_(ICE_CANDIDATE_COMPONENT_DEFAULT),
148 generation_(0), 169 generation_(0),
149 ice_username_fragment_(username_fragment), 170 ice_username_fragment_(username_fragment),
150 password_(password), 171 password_(password),
151 timeout_delay_(kPortTimeoutDelay), 172 timeout_delay_(kPortTimeoutDelay),
152 enable_port_packets_(false), 173 enable_port_packets_(false),
174 ice_protocol_(ICEPROTO_HYBRID),
153 ice_role_(ICEROLE_UNKNOWN), 175 ice_role_(ICEROLE_UNKNOWN),
154 tiebreaker_(0), 176 tiebreaker_(0),
155 shared_socket_(true), 177 shared_socket_(true),
156 candidate_filter_(CF_ALL) { 178 candidate_filter_(CF_ALL) {
157 Construct(); 179 Construct();
158 } 180 }
159 181
160 Port::Port(rtc::Thread* thread, 182 Port::Port(rtc::Thread* thread,
161 const std::string& type, 183 const std::string& type,
162 rtc::PacketSocketFactory* factory, 184 rtc::PacketSocketFactory* factory,
(...skipping 10 matching lines...) Expand all
173 network_(network), 195 network_(network),
174 ip_(ip), 196 ip_(ip),
175 min_port_(min_port), 197 min_port_(min_port),
176 max_port_(max_port), 198 max_port_(max_port),
177 component_(ICE_CANDIDATE_COMPONENT_DEFAULT), 199 component_(ICE_CANDIDATE_COMPONENT_DEFAULT),
178 generation_(0), 200 generation_(0),
179 ice_username_fragment_(username_fragment), 201 ice_username_fragment_(username_fragment),
180 password_(password), 202 password_(password),
181 timeout_delay_(kPortTimeoutDelay), 203 timeout_delay_(kPortTimeoutDelay),
182 enable_port_packets_(false), 204 enable_port_packets_(false),
205 ice_protocol_(ICEPROTO_HYBRID),
183 ice_role_(ICEROLE_UNKNOWN), 206 ice_role_(ICEROLE_UNKNOWN),
184 tiebreaker_(0), 207 tiebreaker_(0),
185 shared_socket_(false), 208 shared_socket_(false),
186 candidate_filter_(CF_ALL) { 209 candidate_filter_(CF_ALL) {
187 ASSERT(factory_ != NULL); 210 ASSERT(factory_ != NULL);
188 Construct(); 211 Construct();
189 } 212 }
190 213
191 void Port::Construct() { 214 void Port::Construct() {
192 // TODO(pthatcher): Remove this old behavior once we're sure no one 215 // If the username_fragment and password are empty, we should just create one.
193 // relies on it. If the username_fragment and password are empty,
194 // we should just create one.
195 if (ice_username_fragment_.empty()) { 216 if (ice_username_fragment_.empty()) {
196 ASSERT(password_.empty()); 217 ASSERT(password_.empty());
197 ice_username_fragment_ = rtc::CreateRandomString(ICE_UFRAG_LENGTH); 218 ice_username_fragment_ = rtc::CreateRandomString(ICE_UFRAG_LENGTH);
198 password_ = rtc::CreateRandomString(ICE_PWD_LENGTH); 219 password_ = rtc::CreateRandomString(ICE_PWD_LENGTH);
199 } 220 }
200 LOG_J(LS_INFO, this) << "Port created"; 221 LOG_J(LS_INFO, this) << "Port created";
201 } 222 }
202 223
203 Port::~Port() { 224 Port::~Port() {
204 // Delete all of the remaining connections. We copy the list up front 225 // Delete all of the remaining connections. We copy the list up front
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
286 LOG_J(LS_ERROR, this) << "Received non-STUN packet from unknown address (" 307 LOG_J(LS_ERROR, this) << "Received non-STUN packet from unknown address ("
287 << addr.ToSensitiveString() << ")"; 308 << addr.ToSensitiveString() << ")";
288 } else if (!msg) { 309 } else if (!msg) {
289 // STUN message handled already 310 // STUN message handled already
290 } else if (msg->type() == STUN_BINDING_REQUEST) { 311 } else if (msg->type() == STUN_BINDING_REQUEST) {
291 LOG(LS_INFO) << "Received STUN ping " 312 LOG(LS_INFO) << "Received STUN ping "
292 << " id=" << rtc::hex_encode(msg->transaction_id()) 313 << " id=" << rtc::hex_encode(msg->transaction_id())
293 << " from unknown address " << addr.ToSensitiveString(); 314 << " from unknown address " << addr.ToSensitiveString();
294 315
295 // Check for role conflicts. 316 // Check for role conflicts.
296 if (!MaybeIceRoleConflict(addr, msg.get(), remote_username)) { 317 if (IsStandardIce() &&
318 !MaybeIceRoleConflict(addr, msg.get(), remote_username)) {
297 LOG(LS_INFO) << "Received conflicting role from the peer."; 319 LOG(LS_INFO) << "Received conflicting role from the peer.";
298 return; 320 return;
299 } 321 }
300 322
301 SignalUnknownAddress(this, addr, proto, msg.get(), remote_username, false); 323 SignalUnknownAddress(this, addr, proto, msg.get(), remote_username, false);
302 } else { 324 } else {
303 // NOTE(tschmelcher): STUN_BINDING_RESPONSE is benign. It occurs if we 325 // NOTE(tschmelcher): STUN_BINDING_RESPONSE is benign. It occurs if we
304 // pruned a connection for this port while it had STUN requests in flight, 326 // pruned a connection for this port while it had STUN requests in flight,
305 // because we then get back responses for them, which this code correctly 327 // because we then get back responses for them, which this code correctly
306 // does not handle. 328 // does not handle.
(...skipping 10 matching lines...) Expand all
317 for (; iter != connections_.end(); ++iter) { 339 for (; iter != connections_.end(); ++iter) {
318 iter->second->OnReadyToSend(); 340 iter->second->OnReadyToSend();
319 } 341 }
320 } 342 }
321 343
322 size_t Port::AddPrflxCandidate(const Candidate& local) { 344 size_t Port::AddPrflxCandidate(const Candidate& local) {
323 candidates_.push_back(local); 345 candidates_.push_back(local);
324 return (candidates_.size() - 1); 346 return (candidates_.size() - 1);
325 } 347 }
326 348
349 bool Port::IsStandardIce() const {
350 return (ice_protocol_ == ICEPROTO_RFC5245);
351 }
352
353 bool Port::IsGoogleIce() const {
354 return (ice_protocol_ == ICEPROTO_GOOGLE);
355 }
356
357 bool Port::IsHybridIce() const {
358 return (ice_protocol_ == ICEPROTO_HYBRID);
359 }
360
327 bool Port::GetStunMessage(const char* data, size_t size, 361 bool Port::GetStunMessage(const char* data, size_t size,
328 const rtc::SocketAddress& addr, 362 const rtc::SocketAddress& addr,
329 IceMessage** out_msg, std::string* out_username) { 363 IceMessage** out_msg, std::string* out_username) {
330 // NOTE: This could clearly be optimized to avoid allocating any memory. 364 // NOTE: This could clearly be optimized to avoid allocating any memory.
331 // However, at the data rates we'll be looking at on the client side, 365 // However, at the data rates we'll be looking at on the client side,
332 // this probably isn't worth worrying about. 366 // this probably isn't worth worrying about.
333 ASSERT(out_msg != NULL); 367 ASSERT(out_msg != NULL);
334 ASSERT(out_username != NULL); 368 ASSERT(out_username != NULL);
335 *out_msg = NULL; 369 *out_msg = NULL;
336 out_username->clear(); 370 out_username->clear();
337 371
338 // Don't bother parsing the packet if we can tell it's not STUN. 372 // Don't bother parsing the packet if we can tell it's not STUN.
339 // In ICE mode, all STUN packets will have a valid fingerprint. 373 // In ICE mode, all STUN packets will have a valid fingerprint.
340 if (!StunMessage::ValidateFingerprint(data, size)) { 374 if (IsStandardIce() && !StunMessage::ValidateFingerprint(data, size)) {
341 return false; 375 return false;
342 } 376 }
343 377
344 // Parse the request message. If the packet is not a complete and correct 378 // Parse the request message. If the packet is not a complete and correct
345 // STUN message, then ignore it. 379 // STUN message, then ignore it.
346 rtc::scoped_ptr<IceMessage> stun_msg(new IceMessage()); 380 rtc::scoped_ptr<IceMessage> stun_msg(new IceMessage());
347 rtc::ByteBuffer buf(data, size); 381 rtc::ByteBuffer buf(data, size);
348 if (!stun_msg->Read(&buf) || (buf.Length() > 0)) { 382 if (!stun_msg->Read(&buf) || (buf.Length() > 0)) {
349 return false; 383 return false;
350 } 384 }
351 385
352 if (stun_msg->type() == STUN_BINDING_REQUEST) { 386 if (stun_msg->type() == STUN_BINDING_REQUEST) {
353 // Check for the presence of USERNAME and MESSAGE-INTEGRITY (if ICE) first. 387 // Check for the presence of USERNAME and MESSAGE-INTEGRITY (if ICE) first.
354 // If not present, fail with a 400 Bad Request. 388 // If not present, fail with a 400 Bad Request.
355 if (!stun_msg->GetByteString(STUN_ATTR_USERNAME) || 389 if (!stun_msg->GetByteString(STUN_ATTR_USERNAME) ||
356 !stun_msg->GetByteString(STUN_ATTR_MESSAGE_INTEGRITY)) { 390 (IsStandardIce() &&
391 !stun_msg->GetByteString(STUN_ATTR_MESSAGE_INTEGRITY))) {
357 LOG_J(LS_ERROR, this) << "Received STUN request without username/M-I " 392 LOG_J(LS_ERROR, this) << "Received STUN request without username/M-I "
358 << "from " << addr.ToSensitiveString(); 393 << "from " << addr.ToSensitiveString();
359 SendBindingErrorResponse(stun_msg.get(), addr, STUN_ERROR_BAD_REQUEST, 394 SendBindingErrorResponse(stun_msg.get(), addr, STUN_ERROR_BAD_REQUEST,
360 STUN_ERROR_REASON_BAD_REQUEST); 395 STUN_ERROR_REASON_BAD_REQUEST);
361 return true; 396 return true;
362 } 397 }
363 398
364 // If the username is bad or unknown, fail with a 401 Unauthorized. 399 // If the username is bad or unknown, fail with a 401 Unauthorized.
365 std::string local_ufrag; 400 std::string local_ufrag;
366 std::string remote_ufrag; 401 std::string remote_ufrag;
367 if (!ParseStunUsername(stun_msg.get(), &local_ufrag, &remote_ufrag) || 402 IceProtocolType remote_protocol_type;
403 if (!ParseStunUsername(stun_msg.get(), &local_ufrag, &remote_ufrag,
404 &remote_protocol_type) ||
368 local_ufrag != username_fragment()) { 405 local_ufrag != username_fragment()) {
369 LOG_J(LS_ERROR, this) << "Received STUN request with bad local username " 406 LOG_J(LS_ERROR, this) << "Received STUN request with bad local username "
370 << local_ufrag << " from " 407 << local_ufrag << " from "
371 << addr.ToSensitiveString(); 408 << addr.ToSensitiveString();
372 SendBindingErrorResponse(stun_msg.get(), addr, STUN_ERROR_UNAUTHORIZED, 409 SendBindingErrorResponse(stun_msg.get(), addr, STUN_ERROR_UNAUTHORIZED,
373 STUN_ERROR_REASON_UNAUTHORIZED); 410 STUN_ERROR_REASON_UNAUTHORIZED);
374 return true; 411 return true;
375 } 412 }
376 413
414 // Port is initialized to GOOGLE-ICE protocol type. If pings from remote
415 // are received before the signal message, protocol type may be different.
416 // Based on the STUN username, we can determine what's the remote protocol.
417 // This also enables us to send the response back using the same protocol
418 // as the request.
419 if (IsHybridIce()) {
420 SetIceProtocolType(remote_protocol_type);
421 }
422
377 // If ICE, and the MESSAGE-INTEGRITY is bad, fail with a 401 Unauthorized 423 // If ICE, and the MESSAGE-INTEGRITY is bad, fail with a 401 Unauthorized
378 if (!stun_msg->ValidateMessageIntegrity(data, size, password_)) { 424 if (IsStandardIce() &&
425 !stun_msg->ValidateMessageIntegrity(data, size, password_)) {
379 LOG_J(LS_ERROR, this) << "Received STUN request with bad M-I " 426 LOG_J(LS_ERROR, this) << "Received STUN request with bad M-I "
380 << "from " << addr.ToSensitiveString() 427 << "from " << addr.ToSensitiveString()
381 << ", password_=" << password_; 428 << ", password_=" << password_;
382 SendBindingErrorResponse(stun_msg.get(), addr, STUN_ERROR_UNAUTHORIZED, 429 SendBindingErrorResponse(stun_msg.get(), addr, STUN_ERROR_UNAUTHORIZED,
383 STUN_ERROR_REASON_UNAUTHORIZED); 430 STUN_ERROR_REASON_UNAUTHORIZED);
384 return true; 431 return true;
385 } 432 }
386 out_username->assign(remote_ufrag); 433 out_username->assign(remote_ufrag);
387 } else if ((stun_msg->type() == STUN_BINDING_RESPONSE) || 434 } else if ((stun_msg->type() == STUN_BINDING_RESPONSE) ||
388 (stun_msg->type() == STUN_BINDING_ERROR_RESPONSE)) { 435 (stun_msg->type() == STUN_BINDING_ERROR_RESPONSE)) {
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
429 // Link-local IPv6 ports can only connect to other link-local IPv6 ports. 476 // Link-local IPv6 ports can only connect to other link-local IPv6 ports.
430 if (family == AF_INET6 && 477 if (family == AF_INET6 &&
431 (IPIsLinkLocal(ip()) != IPIsLinkLocal(addr.ipaddr()))) { 478 (IPIsLinkLocal(ip()) != IPIsLinkLocal(addr.ipaddr()))) {
432 return false; 479 return false;
433 } 480 }
434 return true; 481 return true;
435 } 482 }
436 483
437 bool Port::ParseStunUsername(const StunMessage* stun_msg, 484 bool Port::ParseStunUsername(const StunMessage* stun_msg,
438 std::string* local_ufrag, 485 std::string* local_ufrag,
439 std::string* remote_ufrag) const { 486 std::string* remote_ufrag,
487 IceProtocolType* remote_protocol_type) const {
440 // The packet must include a username that either begins or ends with our 488 // The packet must include a username that either begins or ends with our
441 // fragment. It should begin with our fragment if it is a request and it 489 // fragment. It should begin with our fragment if it is a request and it
442 // should end with our fragment if it is a response. 490 // should end with our fragment if it is a response.
443 local_ufrag->clear(); 491 local_ufrag->clear();
444 remote_ufrag->clear(); 492 remote_ufrag->clear();
445 const StunByteStringAttribute* username_attr = 493 const StunByteStringAttribute* username_attr =
446 stun_msg->GetByteString(STUN_ATTR_USERNAME); 494 stun_msg->GetByteString(STUN_ATTR_USERNAME);
447 if (username_attr == NULL) 495 if (username_attr == NULL)
448 return false; 496 return false;
449 497
450 // RFRAG:LFRAG 498 const std::string username_attr_str = username_attr->GetString();
451 const std::string username = username_attr->GetString(); 499 size_t colon_pos = username_attr_str.find(":");
452 size_t colon_pos = username.find(":"); 500 // If we are in hybrid mode set the appropriate ice protocol type based on
453 if (colon_pos == std::string::npos) { 501 // the username argument style.
454 return false; 502 if (IsHybridIce()) {
503 *remote_protocol_type = (colon_pos != std::string::npos) ?
504 ICEPROTO_RFC5245 : ICEPROTO_GOOGLE;
505 } else {
506 *remote_protocol_type = ice_protocol_;
455 } 507 }
508 if (*remote_protocol_type == ICEPROTO_RFC5245) {
509 if (colon_pos != std::string::npos) { // RFRAG:LFRAG
510 *local_ufrag = username_attr_str.substr(0, colon_pos);
511 *remote_ufrag = username_attr_str.substr(
512 colon_pos + 1, username_attr_str.size());
513 } else {
514 return false;
515 }
516 } else if (*remote_protocol_type == ICEPROTO_GOOGLE) {
517 int remote_frag_len = static_cast<int>(username_attr_str.size());
518 remote_frag_len -= static_cast<int>(username_fragment().size());
519 if (remote_frag_len < 0)
520 return false;
456 521
457 *local_ufrag = username.substr(0, colon_pos); 522 *local_ufrag = username_attr_str.substr(0, username_fragment().size());
458 *remote_ufrag = username.substr(colon_pos + 1, username.size()); 523 *remote_ufrag = username_attr_str.substr(
524 username_fragment().size(), username_attr_str.size());
525 }
459 return true; 526 return true;
460 } 527 }
461 528
462 bool Port::MaybeIceRoleConflict( 529 bool Port::MaybeIceRoleConflict(
463 const rtc::SocketAddress& addr, IceMessage* stun_msg, 530 const rtc::SocketAddress& addr, IceMessage* stun_msg,
464 const std::string& remote_ufrag) { 531 const std::string& remote_ufrag) {
465 // Validate ICE_CONTROLLING or ICE_CONTROLLED attributes. 532 // Validate ICE_CONTROLLING or ICE_CONTROLLED attributes.
466 bool ret = true; 533 bool ret = true;
467 IceRole remote_ice_role = ICEROLE_UNKNOWN; 534 IceRole remote_ice_role = ICEROLE_UNKNOWN;
468 uint64 remote_tiebreaker = 0; 535 uint64 remote_tiebreaker = 0;
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
517 default: 584 default:
518 ASSERT(false); 585 ASSERT(false);
519 } 586 }
520 return ret; 587 return ret;
521 } 588 }
522 589
523 void Port::CreateStunUsername(const std::string& remote_username, 590 void Port::CreateStunUsername(const std::string& remote_username,
524 std::string* stun_username_attr_str) const { 591 std::string* stun_username_attr_str) const {
525 stun_username_attr_str->clear(); 592 stun_username_attr_str->clear();
526 *stun_username_attr_str = remote_username; 593 *stun_username_attr_str = remote_username;
527 stun_username_attr_str->append(":"); 594 if (IsStandardIce()) {
595 // Connectivity checks from L->R will have username RFRAG:LFRAG.
596 stun_username_attr_str->append(":");
597 }
528 stun_username_attr_str->append(username_fragment()); 598 stun_username_attr_str->append(username_fragment());
529 } 599 }
530 600
531 void Port::SendBindingResponse(StunMessage* request, 601 void Port::SendBindingResponse(StunMessage* request,
532 const rtc::SocketAddress& addr) { 602 const rtc::SocketAddress& addr) {
533 ASSERT(request->type() == STUN_BINDING_REQUEST); 603 ASSERT(request->type() == STUN_BINDING_REQUEST);
534 604
535 // Retrieve the username from the request. 605 // Retrieve the username from the request.
536 const StunByteStringAttribute* username_attr = 606 const StunByteStringAttribute* username_attr =
537 request->GetByteString(STUN_ATTR_USERNAME); 607 request->GetByteString(STUN_ATTR_USERNAME);
(...skipping 15 matching lines...) Expand all
553 response.AddAttribute(new StunUInt32Attribute( 623 response.AddAttribute(new StunUInt32Attribute(
554 STUN_ATTR_RETRANSMIT_COUNT, retransmit_attr->value())); 624 STUN_ATTR_RETRANSMIT_COUNT, retransmit_attr->value()));
555 625
556 if (retransmit_attr->value() > CONNECTION_WRITE_CONNECT_FAILURES) { 626 if (retransmit_attr->value() > CONNECTION_WRITE_CONNECT_FAILURES) {
557 LOG_J(LS_INFO, this) 627 LOG_J(LS_INFO, this)
558 << "Received a remote ping with high retransmit count: " 628 << "Received a remote ping with high retransmit count: "
559 << retransmit_attr->value(); 629 << retransmit_attr->value();
560 } 630 }
561 } 631 }
562 632
563 response.AddAttribute( 633 // Only GICE messages have USERNAME and MAPPED-ADDRESS in the response.
564 new StunXorAddressAttribute(STUN_ATTR_XOR_MAPPED_ADDRESS, addr)); 634 // ICE messages use XOR-MAPPED-ADDRESS, and add MESSAGE-INTEGRITY.
565 response.AddMessageIntegrity(password_); 635 if (IsStandardIce()) {
566 response.AddFingerprint(); 636 response.AddAttribute(
637 new StunXorAddressAttribute(STUN_ATTR_XOR_MAPPED_ADDRESS, addr));
638 response.AddMessageIntegrity(password_);
639 response.AddFingerprint();
640 } else if (IsGoogleIce()) {
641 response.AddAttribute(
642 new StunAddressAttribute(STUN_ATTR_MAPPED_ADDRESS, addr));
643 response.AddAttribute(new StunByteStringAttribute(
644 STUN_ATTR_USERNAME, username_attr->GetString()));
645 }
567 646
568 // The fact that we received a successful request means that this connection 647 // The fact that we received a successful request means that this connection
569 // (if one exists) should now be readable. 648 // (if one exists) should now be readable.
570 Connection* conn = GetConnection(addr); 649 Connection* conn = GetConnection(addr);
571 650
572 // Send the response message. 651 // Send the response message.
573 rtc::ByteBuffer buf; 652 rtc::ByteBuffer buf;
574 response.Write(&buf); 653 response.Write(&buf);
575 rtc::PacketOptions options(DefaultDscpValue()); 654 rtc::PacketOptions options(DefaultDscpValue());
576 auto err = SendTo(buf.Data(), buf.Length(), addr, options, false); 655 auto err = SendTo(buf.Data(), buf.Length(), addr, options, false);
(...skipping 25 matching lines...) Expand all
602 ASSERT(request->type() == STUN_BINDING_REQUEST); 681 ASSERT(request->type() == STUN_BINDING_REQUEST);
603 682
604 // Fill in the response message. 683 // Fill in the response message.
605 StunMessage response; 684 StunMessage response;
606 response.SetType(STUN_BINDING_ERROR_RESPONSE); 685 response.SetType(STUN_BINDING_ERROR_RESPONSE);
607 response.SetTransactionID(request->transaction_id()); 686 response.SetTransactionID(request->transaction_id());
608 687
609 // When doing GICE, we need to write out the error code incorrectly to 688 // When doing GICE, we need to write out the error code incorrectly to
610 // maintain backwards compatiblility. 689 // maintain backwards compatiblility.
611 StunErrorCodeAttribute* error_attr = StunAttribute::CreateErrorCode(); 690 StunErrorCodeAttribute* error_attr = StunAttribute::CreateErrorCode();
612 error_attr->SetCode(error_code); 691 if (IsStandardIce()) {
692 error_attr->SetCode(error_code);
693 } else if (IsGoogleIce()) {
694 error_attr->SetClass(error_code / 256);
695 error_attr->SetNumber(error_code % 256);
696 }
613 error_attr->SetReason(reason); 697 error_attr->SetReason(reason);
614 response.AddAttribute(error_attr); 698 response.AddAttribute(error_attr);
615 699
616 // Per Section 10.1.2, certain error cases don't get a MESSAGE-INTEGRITY, 700 if (IsStandardIce()) {
617 // because we don't have enough information to determine the shared secret. 701 // Per Section 10.1.2, certain error cases don't get a MESSAGE-INTEGRITY,
618 if (error_code != STUN_ERROR_BAD_REQUEST && 702 // because we don't have enough information to determine the shared secret.
619 error_code != STUN_ERROR_UNAUTHORIZED) 703 if (error_code != STUN_ERROR_BAD_REQUEST &&
620 response.AddMessageIntegrity(password_); 704 error_code != STUN_ERROR_UNAUTHORIZED)
621 response.AddFingerprint(); 705 response.AddMessageIntegrity(password_);
706 response.AddFingerprint();
707 } else if (IsGoogleIce()) {
708 // GICE responses include a username, if one exists.
709 const StunByteStringAttribute* username_attr =
710 request->GetByteString(STUN_ATTR_USERNAME);
711 if (username_attr)
712 response.AddAttribute(new StunByteStringAttribute(
713 STUN_ATTR_USERNAME, username_attr->GetString()));
714 }
622 715
623 // Send the response message. 716 // Send the response message.
624 rtc::ByteBuffer buf; 717 rtc::ByteBuffer buf;
625 response.Write(&buf); 718 response.Write(&buf);
626 rtc::PacketOptions options(DefaultDscpValue()); 719 rtc::PacketOptions options(DefaultDscpValue());
627 SendTo(buf.Data(), buf.Length(), addr, options, false); 720 SendTo(buf.Data(), buf.Length(), addr, options, false);
628 LOG_J(LS_INFO, this) << "Sending STUN binding error: reason=" << reason 721 LOG_J(LS_INFO, this) << "Sending STUN binding error: reason=" << reason
629 << " to " << addr.ToSensitiveString(); 722 << " to " << addr.ToSensitiveString();
630 } 723 }
631 724
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
671 ASSERT(ice_role_ == ICEROLE_CONTROLLED); 764 ASSERT(ice_role_ == ICEROLE_CONTROLLED);
672 // If this port has no connections, then there's no reason to keep it around. 765 // If this port has no connections, then there's no reason to keep it around.
673 // When the connections time out (both read and write), they will delete 766 // When the connections time out (both read and write), they will delete
674 // themselves, so if we have any connections, they are either readable or 767 // themselves, so if we have any connections, they are either readable or
675 // writable (or still connecting). 768 // writable (or still connecting).
676 if (connections_.empty()) 769 if (connections_.empty())
677 Destroy(); 770 Destroy();
678 } 771 }
679 772
680 const std::string Port::username_fragment() const { 773 const std::string Port::username_fragment() const {
681 return ice_username_fragment_; 774 if (!IsStandardIce() &&
775 component_ == ICE_CANDIDATE_COMPONENT_RTCP) {
776 // In GICE mode, we should adjust username fragment for rtcp component.
777 return GetRtcpUfragFromRtpUfrag(ice_username_fragment_);
778 } else {
779 return ice_username_fragment_;
780 }
682 } 781 }
683 782
684 // A ConnectionRequest is a simple STUN ping used to determine writability. 783 // A ConnectionRequest is a simple STUN ping used to determine writability.
685 class ConnectionRequest : public StunRequest { 784 class ConnectionRequest : public StunRequest {
686 public: 785 public:
687 explicit ConnectionRequest(Connection* connection) 786 explicit ConnectionRequest(Connection* connection)
688 : StunRequest(new IceMessage()), 787 : StunRequest(new IceMessage()),
689 connection_(connection) { 788 connection_(connection) {
690 } 789 }
691 790
692 virtual ~ConnectionRequest() { 791 virtual ~ConnectionRequest() {
693 } 792 }
694 793
695 void Prepare(StunMessage* request) override { 794 void Prepare(StunMessage* request) override {
696 request->SetType(STUN_BINDING_REQUEST); 795 request->SetType(STUN_BINDING_REQUEST);
697 std::string username; 796 std::string username;
698 connection_->port()->CreateStunUsername( 797 connection_->port()->CreateStunUsername(
699 connection_->remote_candidate().username(), &username); 798 connection_->remote_candidate().username(), &username);
700 request->AddAttribute( 799 request->AddAttribute(
701 new StunByteStringAttribute(STUN_ATTR_USERNAME, username)); 800 new StunByteStringAttribute(STUN_ATTR_USERNAME, username));
702 801
703 // connection_ already holds this ping, so subtract one from count. 802 // connection_ already holds this ping, so subtract one from count.
704 if (connection_->port()->send_retransmit_count_attribute()) { 803 if (connection_->port()->send_retransmit_count_attribute()) {
705 request->AddAttribute(new StunUInt32Attribute( 804 request->AddAttribute(new StunUInt32Attribute(
706 STUN_ATTR_RETRANSMIT_COUNT, 805 STUN_ATTR_RETRANSMIT_COUNT,
707 static_cast<uint32>( 806 static_cast<uint32>(
708 connection_->pings_since_last_response_.size() - 1))); 807 connection_->pings_since_last_response_.size() - 1)));
709 } 808 }
710 809
711 // Adding ICE_CONTROLLED or ICE_CONTROLLING attribute based on the role. 810 // Adding ICE-specific attributes to the STUN request message.
712 if (connection_->port()->GetIceRole() == ICEROLE_CONTROLLING) { 811 if (connection_->port()->IsStandardIce()) {
713 request->AddAttribute(new StunUInt64Attribute( 812 // Adding ICE_CONTROLLED or ICE_CONTROLLING attribute based on the role.
714 STUN_ATTR_ICE_CONTROLLING, connection_->port()->IceTiebreaker())); 813 if (connection_->port()->GetIceRole() == ICEROLE_CONTROLLING) {
715 // Since we are trying aggressive nomination, sending USE-CANDIDATE 814 request->AddAttribute(new StunUInt64Attribute(
716 // attribute in every ping. 815 STUN_ATTR_ICE_CONTROLLING, connection_->port()->IceTiebreaker()));
717 // If we are dealing with a ice-lite end point, nomination flag 816 // Since we are trying aggressive nomination, sending USE-CANDIDATE
718 // in Connection will be set to false by default. Once the connection 817 // attribute in every ping.
719 // becomes "best connection", nomination flag will be turned on. 818 // If we are dealing with a ice-lite end point, nomination flag
720 if (connection_->use_candidate_attr()) { 819 // in Connection will be set to false by default. Once the connection
721 request->AddAttribute(new StunByteStringAttribute( 820 // becomes "best connection", nomination flag will be turned on.
722 STUN_ATTR_USE_CANDIDATE)); 821 if (connection_->use_candidate_attr()) {
822 request->AddAttribute(new StunByteStringAttribute(
823 STUN_ATTR_USE_CANDIDATE));
824 }
825 } else if (connection_->port()->GetIceRole() == ICEROLE_CONTROLLED) {
826 request->AddAttribute(new StunUInt64Attribute(
827 STUN_ATTR_ICE_CONTROLLED, connection_->port()->IceTiebreaker()));
828 } else {
829 ASSERT(false);
723 } 830 }
724 } else if (connection_->port()->GetIceRole() == ICEROLE_CONTROLLED) { 831
725 request->AddAttribute(new StunUInt64Attribute( 832 // Adding PRIORITY Attribute.
726 STUN_ATTR_ICE_CONTROLLED, connection_->port()->IceTiebreaker())); 833 // Changing the type preference to Peer Reflexive and local preference
727 } else { 834 // and component id information is unchanged from the original priority.
728 ASSERT(false); 835 // priority = (2^24)*(type preference) +
836 // (2^8)*(local preference) +
837 // (2^0)*(256 - component ID)
838 uint32 prflx_priority = ICE_TYPE_PREFERENCE_PRFLX << 24 |
839 (connection_->local_candidate().priority() & 0x00FFFFFF);
840 request->AddAttribute(
841 new StunUInt32Attribute(STUN_ATTR_PRIORITY, prflx_priority));
842
843 // Adding Message Integrity attribute.
844 request->AddMessageIntegrity(connection_->remote_candidate().password());
845 // Adding Fingerprint.
846 request->AddFingerprint();
729 } 847 }
730
731 // Adding PRIORITY Attribute.
732 // Changing the type preference to Peer Reflexive and local preference
733 // and component id information is unchanged from the original priority.
734 // priority = (2^24)*(type preference) +
735 // (2^8)*(local preference) +
736 // (2^0)*(256 - component ID)
737 uint32 prflx_priority = ICE_TYPE_PREFERENCE_PRFLX << 24 |
738 (connection_->local_candidate().priority() & 0x00FFFFFF);
739 request->AddAttribute(
740 new StunUInt32Attribute(STUN_ATTR_PRIORITY, prflx_priority));
741
742 // Adding Message Integrity attribute.
743 request->AddMessageIntegrity(connection_->remote_candidate().password());
744 // Adding Fingerprint.
745 request->AddFingerprint();
746 } 848 }
747 849
748 void OnResponse(StunMessage* response) override { 850 void OnResponse(StunMessage* response) override {
749 connection_->OnConnectionRequestResponse(this, response); 851 connection_->OnConnectionRequestResponse(this, response);
750 } 852 }
751 853
752 void OnErrorResponse(StunMessage* response) override { 854 void OnErrorResponse(StunMessage* response) override {
753 connection_->OnConnectionRequestErrorResponse(this, response); 855 connection_->OnConnectionRequestErrorResponse(this, response);
754 } 856 }
755 857
(...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after
931 // If this is a STUN response, then update the writable bit. 1033 // If this is a STUN response, then update the writable bit.
932 // Log at LS_INFO if we receive a ping on an unwritable connection. 1034 // Log at LS_INFO if we receive a ping on an unwritable connection.
933 rtc::LoggingSeverity sev = (!writable() ? rtc::LS_INFO : rtc::LS_VERBOSE); 1035 rtc::LoggingSeverity sev = (!writable() ? rtc::LS_INFO : rtc::LS_VERBOSE);
934 switch (msg->type()) { 1036 switch (msg->type()) {
935 case STUN_BINDING_REQUEST: 1037 case STUN_BINDING_REQUEST:
936 LOG_JV(sev, this) << "Received STUN ping" 1038 LOG_JV(sev, this) << "Received STUN ping"
937 << ", id=" << rtc::hex_encode(msg->transaction_id()); 1039 << ", id=" << rtc::hex_encode(msg->transaction_id());
938 1040
939 if (remote_ufrag == remote_candidate_.username()) { 1041 if (remote_ufrag == remote_candidate_.username()) {
940 // Check for role conflicts. 1042 // Check for role conflicts.
941 if (!port_->MaybeIceRoleConflict(addr, msg.get(), remote_ufrag)) { 1043 if (port_->IsStandardIce() &&
1044 !port_->MaybeIceRoleConflict(addr, msg.get(), remote_ufrag)) {
942 // Received conflicting role from the peer. 1045 // Received conflicting role from the peer.
943 LOG(LS_INFO) << "Received conflicting role from the peer."; 1046 LOG(LS_INFO) << "Received conflicting role from the peer.";
944 return; 1047 return;
945 } 1048 }
946 1049
947 // Incoming, validated stun request from remote peer. 1050 // Incoming, validated stun request from remote peer.
948 // This call will also set the connection readable. 1051 // This call will also set the connection readable.
949 port_->SendBindingResponse(msg.get(), addr); 1052 port_->SendBindingResponse(msg.get(), addr);
950 1053
951 // If timed out sending writability checks, start up again 1054 // If timed out sending writability checks, start up again
952 if (!pruned_ && (write_state_ == STATE_WRITE_TIMEOUT)) 1055 if (!pruned_ && (write_state_ == STATE_WRITE_TIMEOUT))
953 set_write_state(STATE_WRITE_INIT); 1056 set_write_state(STATE_WRITE_INIT);
954 1057
955 if (port_->GetIceRole() == ICEROLE_CONTROLLED) { 1058 if ((port_->IsStandardIce()) &&
1059 (port_->GetIceRole() == ICEROLE_CONTROLLED)) {
956 const StunByteStringAttribute* use_candidate_attr = 1060 const StunByteStringAttribute* use_candidate_attr =
957 msg->GetByteString(STUN_ATTR_USE_CANDIDATE); 1061 msg->GetByteString(STUN_ATTR_USE_CANDIDATE);
958 if (use_candidate_attr) { 1062 if (use_candidate_attr) {
959 set_nominated(true); 1063 set_nominated(true);
960 SignalNominated(this); 1064 SignalNominated(this);
961 } 1065 }
962 } 1066 }
963 } else { 1067 } else {
964 // The packet had the right local username, but the remote username 1068 // The packet had the right local username, but the remote username
965 // was not the right one for the remote address. 1069 // was not the right one for the remote address.
966 LOG_J(LS_ERROR, this) 1070 LOG_J(LS_ERROR, this)
967 << "Received STUN request with bad remote username " 1071 << "Received STUN request with bad remote username "
968 << remote_ufrag; 1072 << remote_ufrag;
969 port_->SendBindingErrorResponse(msg.get(), addr, 1073 port_->SendBindingErrorResponse(msg.get(), addr,
970 STUN_ERROR_UNAUTHORIZED, 1074 STUN_ERROR_UNAUTHORIZED,
971 STUN_ERROR_REASON_UNAUTHORIZED); 1075 STUN_ERROR_REASON_UNAUTHORIZED);
972 1076
973 } 1077 }
974 break; 1078 break;
975 1079
976 // Response from remote peer. Does it match request sent? 1080 // Response from remote peer. Does it match request sent?
977 // This doesn't just check, it makes callbacks if transaction 1081 // This doesn't just check, it makes callbacks if transaction
978 // id's match. 1082 // id's match.
979 case STUN_BINDING_RESPONSE: 1083 case STUN_BINDING_RESPONSE:
980 case STUN_BINDING_ERROR_RESPONSE: 1084 case STUN_BINDING_ERROR_RESPONSE:
981 if (msg->ValidateMessageIntegrity( 1085 if (port_->IsGoogleIce() ||
1086 msg->ValidateMessageIntegrity(
982 data, size, remote_candidate().password())) { 1087 data, size, remote_candidate().password())) {
983 requests_.CheckResponse(msg.get()); 1088 requests_.CheckResponse(msg.get());
984 } 1089 }
985 // Otherwise silently discard the response message. 1090 // Otherwise silently discard the response message.
986 break; 1091 break;
987 1092
988 // Remote end point sent an STUN indication instead of regular 1093 // Remote end point sent an STUN indication instead of regular
989 // binding request. In this case |last_ping_received_| will be updated. 1094 // binding request. In this case |last_ping_received_| will be updated.
990 // Otherwise we can mark connection to read timeout. No response will be 1095 // Otherwise we can mark connection to read timeout. No response will be
991 // sent in this scenario. 1096 // sent in this scenario.
992 case STUN_BINDING_INDICATION: 1097 case STUN_BINDING_INDICATION:
993 if (read_state_ == STATE_READABLE) { 1098 if (port_->IsStandardIce() && read_state_ == STATE_READABLE) {
994 ReceivedPing(); 1099 ReceivedPing();
995 } else { 1100 } else {
996 LOG_J(LS_WARNING, this) << "Received STUN binding indication " 1101 LOG_J(LS_WARNING, this) << "Received STUN binding indication "
997 << "from an unreadable connection."; 1102 << "from an unreadable connection.";
998 } 1103 }
999 break; 1104 break;
1000 1105
1001 default: 1106 default:
1002 ASSERT(false); 1107 ASSERT(false);
1003 break; 1108 break;
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
1051 PrintPingsSinceLastResponse(&pings, 5); 1156 PrintPingsSinceLastResponse(&pings, 5);
1052 LOG_J(LS_VERBOSE, this) << "UpdateState()" 1157 LOG_J(LS_VERBOSE, this) << "UpdateState()"
1053 << ", ms since last received response=" 1158 << ", ms since last received response="
1054 << now - last_ping_response_received_ 1159 << now - last_ping_response_received_
1055 << ", ms since last received data=" 1160 << ", ms since last received data="
1056 << now - last_data_received_ 1161 << now - last_data_received_
1057 << ", rtt=" << rtt 1162 << ", rtt=" << rtt
1058 << ", pings_since_last_response=" << pings; 1163 << ", pings_since_last_response=" << pings;
1059 } 1164 }
1060 1165
1166 // Check the readable state.
1167 //
1168 // Since we don't know how many pings the other side has attempted, the best
1169 // test we can do is a simple window.
1170 // If other side has not sent ping after connection has become readable, use
1171 // |last_data_received_| as the indication.
1172 // If remote endpoint is doing RFC 5245, it's not required to send ping
1173 // after connection is established. If this connection is serving a data
1174 // channel, it may not be in a position to send media continuously. Do not
1175 // mark connection timeout if it's in RFC5245 mode.
1176 // Below check will be performed with end point if it's doing google-ice.
1177 if (port_->IsGoogleIce() && (read_state_ == STATE_READABLE) &&
1178 (last_ping_received_ + CONNECTION_READ_TIMEOUT <= now) &&
1179 (last_data_received_ + CONNECTION_READ_TIMEOUT <= now)) {
1180 LOG_J(LS_INFO, this) << "Unreadable after " << now - last_ping_received_
1181 << " ms without a ping,"
1182 << " ms since last received response="
1183 << now - last_ping_response_received_
1184 << " ms since last received data="
1185 << now - last_data_received_
1186 << " rtt=" << rtt;
1187 set_read_state(STATE_READ_TIMEOUT);
1188 }
1189
1061 // Check the writable state. (The order of these checks is important.) 1190 // Check the writable state. (The order of these checks is important.)
1062 // 1191 //
1063 // Before becoming unwritable, we allow for a fixed number of pings to fail 1192 // Before becoming unwritable, we allow for a fixed number of pings to fail
1064 // (i.e., receive no response). We also have to give the response time to 1193 // (i.e., receive no response). We also have to give the response time to
1065 // get back, so we include a conservative estimate of this. 1194 // get back, so we include a conservative estimate of this.
1066 // 1195 //
1067 // Before timing out writability, we give a fixed amount of time. This is to 1196 // Before timing out writability, we give a fixed amount of time. This is to
1068 // allow for changes in network conditions. 1197 // allow for changes in network conditions.
1069 1198
1070 if ((write_state_ == STATE_WRITABLE) && 1199 if ((write_state_ == STATE_WRITABLE) &&
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after
1209 LOG_JV(sev, this) << "Received STUN ping response" 1338 LOG_JV(sev, this) << "Received STUN ping response"
1210 << ", id=" << rtc::hex_encode(request->id()) 1339 << ", id=" << rtc::hex_encode(request->id())
1211 << ", code=0" // Makes logging easier to parse. 1340 << ", code=0" // Makes logging easier to parse.
1212 << ", rtt=" << rtt 1341 << ", rtt=" << rtt
1213 << ", use_candidate=" << use_candidate 1342 << ", use_candidate=" << use_candidate
1214 << ", pings_since_last_response=" << pings; 1343 << ", pings_since_last_response=" << pings;
1215 } 1344 }
1216 1345
1217 rtt_ = (RTT_RATIO * rtt_ + rtt) / (RTT_RATIO + 1); 1346 rtt_ = (RTT_RATIO * rtt_ + rtt) / (RTT_RATIO + 1);
1218 1347
1219 MaybeAddPrflxCandidate(request, response); 1348 // Peer reflexive candidate is only for RFC 5245 ICE.
1349 if (port_->IsStandardIce()) {
1350 MaybeAddPrflxCandidate(request, response);
1351 }
1220 } 1352 }
1221 1353
1222 void Connection::OnConnectionRequestErrorResponse(ConnectionRequest* request, 1354 void Connection::OnConnectionRequestErrorResponse(ConnectionRequest* request,
1223 StunMessage* response) { 1355 StunMessage* response) {
1224 const StunErrorCodeAttribute* error_attr = response->GetErrorCode(); 1356 const StunErrorCodeAttribute* error_attr = response->GetErrorCode();
1225 int error_code = STUN_ERROR_GLOBAL_FAILURE; 1357 int error_code = STUN_ERROR_GLOBAL_FAILURE;
1226 if (error_attr) { 1358 if (error_attr) {
1227 error_code = error_attr->code(); 1359 if (port_->IsGoogleIce()) {
1360 // When doing GICE, the error code is written out incorrectly, so we need
1361 // to unmunge it here.
1362 error_code = error_attr->eclass() * 256 + error_attr->number();
1363 } else {
1364 error_code = error_attr->code();
1365 }
1228 } 1366 }
1229 1367
1230 LOG_J(LS_INFO, this) << "Received STUN error response" 1368 LOG_J(LS_INFO, this) << "Received STUN error response"
1231 << " id=" << rtc::hex_encode(request->id()) 1369 << " id=" << rtc::hex_encode(request->id())
1232 << " code=" << error_code 1370 << " code=" << error_code
1233 << " rtt=" << request->Elapsed(); 1371 << " rtt=" << request->Elapsed();
1234 1372
1235 if (error_code == STUN_ERROR_UNKNOWN_ATTRIBUTE || 1373 if (error_code == STUN_ERROR_UNKNOWN_ATTRIBUTE ||
1236 error_code == STUN_ERROR_SERVER_ERROR || 1374 error_code == STUN_ERROR_SERVER_ERROR ||
1237 error_code == STUN_ERROR_UNAUTHORIZED) { 1375 error_code == STUN_ERROR_UNAUTHORIZED) {
(...skipping 185 matching lines...) Expand 10 before | Expand all | Expand 10 after
1423 ASSERT(sent < 0); 1561 ASSERT(sent < 0);
1424 error_ = port_->GetError(); 1562 error_ = port_->GetError();
1425 sent_packets_discarded_++; 1563 sent_packets_discarded_++;
1426 } else { 1564 } else {
1427 send_rate_tracker_.Update(sent); 1565 send_rate_tracker_.Update(sent);
1428 } 1566 }
1429 return sent; 1567 return sent;
1430 } 1568 }
1431 1569
1432 } // namespace cricket 1570 } // namespace cricket
OLDNEW
« no previous file with comments | « webrtc/p2p/base/port.h ('k') | webrtc/p2p/base/port_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698