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

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

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