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