1/*
2 * libjingle
3 * Copyright 2004, Google Inc.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 *  1. Redistributions of source code must retain the above copyright notice,
9 *     this list of conditions and the following disclaimer.
10 *  2. Redistributions in binary form must reproduce the above copyright notice,
11 *     this list of conditions and the following disclaimer in the documentation
12 *     and/or other materials provided with the distribution.
13 *  3. The name of the author may not be used to endorse or promote products
14 *     derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
19 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28#include "talk/p2p/base/transport.h"
29
30#include "talk/p2p/base/candidate.h"
31#include "talk/p2p/base/constants.h"
32#include "talk/p2p/base/parsing.h"
33#include "talk/p2p/base/port.h"
34#include "talk/p2p/base/sessionmanager.h"
35#include "talk/p2p/base/transportchannelimpl.h"
36#include "webrtc/libjingle/xmllite/xmlelement.h"
37#include "talk/xmpp/constants.h"
38#include "webrtc/base/bind.h"
39#include "webrtc/base/common.h"
40#include "webrtc/base/logging.h"
41
42namespace cricket {
43
44using rtc::Bind;
45
46enum {
47  MSG_ONSIGNALINGREADY = 1,
48  MSG_ONREMOTECANDIDATE,
49  MSG_READSTATE,
50  MSG_WRITESTATE,
51  MSG_REQUESTSIGNALING,
52  MSG_CANDIDATEREADY,
53  MSG_ROUTECHANGE,
54  MSG_CONNECTING,
55  MSG_CANDIDATEALLOCATIONCOMPLETE,
56  MSG_ROLECONFLICT,
57  MSG_COMPLETED,
58  MSG_FAILED,
59};
60
61struct ChannelParams : public rtc::MessageData {
62  ChannelParams() : channel(NULL), candidate(NULL) {}
63  explicit ChannelParams(int component)
64      : component(component), channel(NULL), candidate(NULL) {}
65  explicit ChannelParams(Candidate* candidate)
66      : channel(NULL), candidate(candidate) {
67  }
68
69  ~ChannelParams() {
70    delete candidate;
71  }
72
73  std::string name;
74  int component;
75  TransportChannelImpl* channel;
76  Candidate* candidate;
77};
78
79static std::string IceProtoToString(TransportProtocol proto) {
80  std::string proto_str;
81  switch (proto) {
82    case ICEPROTO_GOOGLE:
83      proto_str = "gice";
84      break;
85    case ICEPROTO_HYBRID:
86      proto_str = "hybrid";
87      break;
88    case ICEPROTO_RFC5245:
89      proto_str = "ice";
90      break;
91    default:
92      ASSERT(false);
93      break;
94  }
95  return proto_str;
96}
97
98static bool VerifyIceParams(const TransportDescription& desc) {
99  // For legacy protocols.
100  if (desc.ice_ufrag.empty() && desc.ice_pwd.empty())
101    return true;
102
103  if (desc.ice_ufrag.length() < ICE_UFRAG_MIN_LENGTH ||
104      desc.ice_ufrag.length() > ICE_UFRAG_MAX_LENGTH) {
105    return false;
106  }
107  if (desc.ice_pwd.length() < ICE_PWD_MIN_LENGTH ||
108      desc.ice_pwd.length() > ICE_PWD_MAX_LENGTH) {
109    return false;
110  }
111  return true;
112}
113
114bool BadTransportDescription(const std::string& desc, std::string* err_desc) {
115  if (err_desc) {
116    *err_desc = desc;
117  }
118  LOG(LS_ERROR) << desc;
119  return false;
120}
121
122bool IceCredentialsChanged(const std::string& old_ufrag,
123                           const std::string& old_pwd,
124                           const std::string& new_ufrag,
125                           const std::string& new_pwd) {
126  // TODO(jiayl): The standard (RFC 5245 Section 9.1.1.1) says that ICE should
127  // restart when both the ufrag and password are changed, but we do restart
128  // when either ufrag or passwrod is changed to keep compatible with GICE. We
129  // should clean this up when GICE is no longer used.
130  return (old_ufrag != new_ufrag) || (old_pwd != new_pwd);
131}
132
133static bool IceCredentialsChanged(const TransportDescription& old_desc,
134                                  const TransportDescription& new_desc) {
135  return IceCredentialsChanged(old_desc.ice_ufrag, old_desc.ice_pwd,
136                               new_desc.ice_ufrag, new_desc.ice_pwd);
137}
138
139Transport::Transport(rtc::Thread* signaling_thread,
140                     rtc::Thread* worker_thread,
141                     const std::string& content_name,
142                     const std::string& type,
143                     PortAllocator* allocator)
144  : signaling_thread_(signaling_thread),
145    worker_thread_(worker_thread),
146    content_name_(content_name),
147    type_(type),
148    allocator_(allocator),
149    destroyed_(false),
150    readable_(TRANSPORT_STATE_NONE),
151    writable_(TRANSPORT_STATE_NONE),
152    was_writable_(false),
153    connect_requested_(false),
154    ice_role_(ICEROLE_UNKNOWN),
155    tiebreaker_(0),
156    protocol_(ICEPROTO_HYBRID),
157    remote_ice_mode_(ICEMODE_FULL) {
158}
159
160Transport::~Transport() {
161  ASSERT(signaling_thread_->IsCurrent());
162  ASSERT(destroyed_);
163}
164
165void Transport::SetIceRole(IceRole role) {
166  worker_thread_->Invoke<void>(Bind(&Transport::SetIceRole_w, this, role));
167}
168
169void Transport::SetIdentity(rtc::SSLIdentity* identity) {
170  worker_thread_->Invoke<void>(Bind(&Transport::SetIdentity_w, this, identity));
171}
172
173bool Transport::GetIdentity(rtc::SSLIdentity** identity) {
174  // The identity is set on the worker thread, so for safety it must also be
175  // acquired on the worker thread.
176  return worker_thread_->Invoke<bool>(
177      Bind(&Transport::GetIdentity_w, this, identity));
178}
179
180bool Transport::GetRemoteCertificate(rtc::SSLCertificate** cert) {
181  // Channels can be deleted on the worker thread, so for safety the remote
182  // certificate is acquired on the worker thread.
183  return worker_thread_->Invoke<bool>(
184      Bind(&Transport::GetRemoteCertificate_w, this, cert));
185}
186
187bool Transport::GetRemoteCertificate_w(rtc::SSLCertificate** cert) {
188  ASSERT(worker_thread()->IsCurrent());
189  if (channels_.empty())
190    return false;
191
192  ChannelMap::iterator iter = channels_.begin();
193  return iter->second->GetRemoteCertificate(cert);
194}
195
196bool Transport::SetLocalTransportDescription(
197    const TransportDescription& description,
198    ContentAction action,
199    std::string* error_desc) {
200  return worker_thread_->Invoke<bool>(Bind(
201      &Transport::SetLocalTransportDescription_w, this,
202      description, action, error_desc));
203}
204
205bool Transport::SetRemoteTransportDescription(
206    const TransportDescription& description,
207    ContentAction action,
208    std::string* error_desc) {
209  return worker_thread_->Invoke<bool>(Bind(
210      &Transport::SetRemoteTransportDescription_w, this,
211      description, action, error_desc));
212}
213
214TransportChannelImpl* Transport::CreateChannel(int component) {
215  return worker_thread_->Invoke<TransportChannelImpl*>(Bind(
216      &Transport::CreateChannel_w, this, component));
217}
218
219TransportChannelImpl* Transport::CreateChannel_w(int component) {
220  ASSERT(worker_thread()->IsCurrent());
221  TransportChannelImpl *impl;
222  rtc::CritScope cs(&crit_);
223
224  // Create the entry if it does not exist.
225  bool impl_exists = false;
226  if (channels_.find(component) == channels_.end()) {
227    impl = CreateTransportChannel(component);
228    channels_[component] = ChannelMapEntry(impl);
229  } else {
230    impl = channels_[component].get();
231    impl_exists = true;
232  }
233
234  // Increase the ref count.
235  channels_[component].AddRef();
236  destroyed_ = false;
237
238  if (impl_exists) {
239    // If this is an existing channel, we should just return it without
240    // connecting to all the signal again.
241    return impl;
242  }
243
244  // Push down our transport state to the new channel.
245  impl->SetIceRole(ice_role_);
246  impl->SetIceTiebreaker(tiebreaker_);
247  // TODO(ronghuawu): Change CreateChannel_w to be able to return error since
248  // below Apply**Description_w calls can fail.
249  if (local_description_)
250    ApplyLocalTransportDescription_w(impl, NULL);
251  if (remote_description_)
252    ApplyRemoteTransportDescription_w(impl, NULL);
253  if (local_description_ && remote_description_)
254    ApplyNegotiatedTransportDescription_w(impl, NULL);
255
256  impl->SignalReadableState.connect(this, &Transport::OnChannelReadableState);
257  impl->SignalWritableState.connect(this, &Transport::OnChannelWritableState);
258  impl->SignalRequestSignaling.connect(
259      this, &Transport::OnChannelRequestSignaling);
260  impl->SignalCandidateReady.connect(this, &Transport::OnChannelCandidateReady);
261  impl->SignalRouteChange.connect(this, &Transport::OnChannelRouteChange);
262  impl->SignalCandidatesAllocationDone.connect(
263      this, &Transport::OnChannelCandidatesAllocationDone);
264  impl->SignalRoleConflict.connect(this, &Transport::OnRoleConflict);
265  impl->SignalConnectionRemoved.connect(
266      this, &Transport::OnChannelConnectionRemoved);
267
268  if (connect_requested_) {
269    impl->Connect();
270    if (channels_.size() == 1) {
271      // If this is the first channel, then indicate that we have started
272      // connecting.
273      signaling_thread()->Post(this, MSG_CONNECTING, NULL);
274    }
275  }
276  return impl;
277}
278
279TransportChannelImpl* Transport::GetChannel(int component) {
280  rtc::CritScope cs(&crit_);
281  ChannelMap::iterator iter = channels_.find(component);
282  return (iter != channels_.end()) ? iter->second.get() : NULL;
283}
284
285bool Transport::HasChannels() {
286  rtc::CritScope cs(&crit_);
287  return !channels_.empty();
288}
289
290void Transport::DestroyChannel(int component) {
291  worker_thread_->Invoke<void>(Bind(
292      &Transport::DestroyChannel_w, this, component));
293}
294
295void Transport::DestroyChannel_w(int component) {
296  ASSERT(worker_thread()->IsCurrent());
297
298  TransportChannelImpl* impl = NULL;
299  {
300    rtc::CritScope cs(&crit_);
301    ChannelMap::iterator iter = channels_.find(component);
302    if (iter == channels_.end())
303      return;
304
305    iter->second.DecRef();
306    if (!iter->second.ref()) {
307      impl = iter->second.get();
308      channels_.erase(iter);
309    }
310  }
311
312  if (connect_requested_ && channels_.empty()) {
313    // We're no longer attempting to connect.
314    signaling_thread()->Post(this, MSG_CONNECTING, NULL);
315  }
316
317  if (impl) {
318    // Check in case the deleted channel was the only non-writable channel.
319    OnChannelWritableState(impl);
320    DestroyTransportChannel(impl);
321  }
322}
323
324void Transport::ConnectChannels() {
325  ASSERT(signaling_thread()->IsCurrent());
326  worker_thread_->Invoke<void>(Bind(&Transport::ConnectChannels_w, this));
327}
328
329void Transport::ConnectChannels_w() {
330  ASSERT(worker_thread()->IsCurrent());
331  if (connect_requested_ || channels_.empty())
332    return;
333  connect_requested_ = true;
334  signaling_thread()->Post(
335      this, MSG_CANDIDATEREADY, NULL);
336
337  if (!local_description_) {
338    // TOOD(mallinath) : TransportDescription(TD) shouldn't be generated here.
339    // As Transport must know TD is offer or answer and cricket::Transport
340    // doesn't have the capability to decide it. This should be set by the
341    // Session.
342    // Session must generate local TD before remote candidates pushed when
343    // initiate request initiated by the remote.
344    LOG(LS_INFO) << "Transport::ConnectChannels_w: No local description has "
345                 << "been set. Will generate one.";
346    TransportDescription desc(NS_GINGLE_P2P, std::vector<std::string>(),
347                              rtc::CreateRandomString(ICE_UFRAG_LENGTH),
348                              rtc::CreateRandomString(ICE_PWD_LENGTH),
349                              ICEMODE_FULL, CONNECTIONROLE_NONE, NULL,
350                              Candidates());
351    SetLocalTransportDescription_w(desc, CA_OFFER, NULL);
352  }
353
354  CallChannels_w(&TransportChannelImpl::Connect);
355  if (!channels_.empty()) {
356    signaling_thread()->Post(this, MSG_CONNECTING, NULL);
357  }
358}
359
360void Transport::OnConnecting_s() {
361  ASSERT(signaling_thread()->IsCurrent());
362  SignalConnecting(this);
363}
364
365void Transport::DestroyAllChannels() {
366  ASSERT(signaling_thread()->IsCurrent());
367  worker_thread_->Invoke<void>(
368      Bind(&Transport::DestroyAllChannels_w, this));
369  worker_thread()->Clear(this);
370  signaling_thread()->Clear(this);
371  destroyed_ = true;
372}
373
374void Transport::DestroyAllChannels_w() {
375  ASSERT(worker_thread()->IsCurrent());
376  std::vector<TransportChannelImpl*> impls;
377  {
378    rtc::CritScope cs(&crit_);
379    for (ChannelMap::iterator iter = channels_.begin();
380         iter != channels_.end();
381         ++iter) {
382      iter->second.DecRef();
383      if (!iter->second.ref())
384        impls.push_back(iter->second.get());
385      }
386    }
387  channels_.clear();
388
389
390  for (size_t i = 0; i < impls.size(); ++i)
391    DestroyTransportChannel(impls[i]);
392}
393
394void Transport::ResetChannels() {
395  ASSERT(signaling_thread()->IsCurrent());
396  worker_thread_->Invoke<void>(Bind(&Transport::ResetChannels_w, this));
397}
398
399void Transport::ResetChannels_w() {
400  ASSERT(worker_thread()->IsCurrent());
401
402  // We are no longer attempting to connect
403  connect_requested_ = false;
404
405  // Clear out the old messages, they aren't relevant
406  rtc::CritScope cs(&crit_);
407  ready_candidates_.clear();
408
409  // Reset all of the channels
410  CallChannels_w(&TransportChannelImpl::Reset);
411}
412
413void Transport::OnSignalingReady() {
414  ASSERT(signaling_thread()->IsCurrent());
415  if (destroyed_) return;
416
417  worker_thread()->Post(this, MSG_ONSIGNALINGREADY, NULL);
418
419  // Notify the subclass.
420  OnTransportSignalingReady();
421}
422
423void Transport::CallChannels_w(TransportChannelFunc func) {
424  ASSERT(worker_thread()->IsCurrent());
425  rtc::CritScope cs(&crit_);
426  for (ChannelMap::iterator iter = channels_.begin();
427       iter != channels_.end();
428       ++iter) {
429    ((iter->second.get())->*func)();
430  }
431}
432
433bool Transport::VerifyCandidate(const Candidate& cand, std::string* error) {
434  // No address zero.
435  if (cand.address().IsNil() || cand.address().IsAny()) {
436    *error = "candidate has address of zero";
437    return false;
438  }
439
440  // Disallow all ports below 1024, except for 80 and 443 on public addresses.
441  int port = cand.address().port();
442  if (cand.protocol() == TCP_PROTOCOL_NAME &&
443      (cand.tcptype() == TCPTYPE_ACTIVE_STR || port == 0)) {
444    // Expected for active-only candidates per
445    // http://tools.ietf.org/html/rfc6544#section-4.5 so no error.
446    // Libjingle clients emit port 0, in "active" mode.
447    return true;
448  }
449  if (port < 1024) {
450    if ((port != 80) && (port != 443)) {
451      *error = "candidate has port below 1024, but not 80 or 443";
452      return false;
453    }
454
455    if (cand.address().IsPrivateIP()) {
456      *error = "candidate has port of 80 or 443 with private IP address";
457      return false;
458    }
459  }
460
461  return true;
462}
463
464
465bool Transport::GetStats(TransportStats* stats) {
466  ASSERT(signaling_thread()->IsCurrent());
467  return worker_thread_->Invoke<bool>(Bind(
468      &Transport::GetStats_w, this, stats));
469}
470
471bool Transport::GetStats_w(TransportStats* stats) {
472  ASSERT(worker_thread()->IsCurrent());
473  stats->content_name = content_name();
474  stats->channel_stats.clear();
475  for (ChannelMap::iterator iter = channels_.begin();
476       iter != channels_.end();
477       ++iter) {
478    TransportChannelStats substats;
479    substats.component = iter->second->component();
480    if (!iter->second->GetStats(&substats.connection_infos)) {
481      return false;
482    }
483    stats->channel_stats.push_back(substats);
484  }
485  return true;
486}
487
488bool Transport::GetSslRole(rtc::SSLRole* ssl_role) const {
489  return worker_thread_->Invoke<bool>(Bind(
490      &Transport::GetSslRole_w, this, ssl_role));
491}
492
493void Transport::OnRemoteCandidates(const std::vector<Candidate>& candidates) {
494  for (std::vector<Candidate>::const_iterator iter = candidates.begin();
495       iter != candidates.end();
496       ++iter) {
497    OnRemoteCandidate(*iter);
498  }
499}
500
501void Transport::OnRemoteCandidate(const Candidate& candidate) {
502  ASSERT(signaling_thread()->IsCurrent());
503  if (destroyed_) return;
504
505  if (!HasChannel(candidate.component())) {
506    LOG(LS_WARNING) << "Ignoring candidate for unknown component "
507                    << candidate.component();
508    return;
509  }
510
511  ChannelParams* params = new ChannelParams(new Candidate(candidate));
512  worker_thread()->Post(this, MSG_ONREMOTECANDIDATE, params);
513}
514
515void Transport::OnRemoteCandidate_w(const Candidate& candidate) {
516  ASSERT(worker_thread()->IsCurrent());
517  ChannelMap::iterator iter = channels_.find(candidate.component());
518  // It's ok for a channel to go away while this message is in transit.
519  if (iter != channels_.end()) {
520    iter->second->OnCandidate(candidate);
521  }
522}
523
524void Transport::OnChannelReadableState(TransportChannel* channel) {
525  ASSERT(worker_thread()->IsCurrent());
526  signaling_thread()->Post(this, MSG_READSTATE, NULL);
527}
528
529void Transport::OnChannelReadableState_s() {
530  ASSERT(signaling_thread()->IsCurrent());
531  TransportState readable = GetTransportState_s(true);
532  if (readable_ != readable) {
533    readable_ = readable;
534    SignalReadableState(this);
535  }
536}
537
538void Transport::OnChannelWritableState(TransportChannel* channel) {
539  ASSERT(worker_thread()->IsCurrent());
540  signaling_thread()->Post(this, MSG_WRITESTATE, NULL);
541
542  MaybeCompleted_w();
543}
544
545void Transport::OnChannelWritableState_s() {
546  ASSERT(signaling_thread()->IsCurrent());
547  TransportState writable = GetTransportState_s(false);
548  if (writable_ != writable) {
549    was_writable_ = (writable_ == TRANSPORT_STATE_ALL);
550    writable_ = writable;
551    SignalWritableState(this);
552  }
553}
554
555TransportState Transport::GetTransportState_s(bool read) {
556  ASSERT(signaling_thread()->IsCurrent());
557  rtc::CritScope cs(&crit_);
558  bool any = false;
559  bool all = !channels_.empty();
560  for (ChannelMap::iterator iter = channels_.begin();
561       iter != channels_.end();
562       ++iter) {
563    bool b = (read ? iter->second->readable() :
564      iter->second->writable());
565    any = any || b;
566    all = all && b;
567  }
568  if (all) {
569    return TRANSPORT_STATE_ALL;
570  } else if (any) {
571    return TRANSPORT_STATE_SOME;
572  } else {
573    return TRANSPORT_STATE_NONE;
574  }
575}
576
577void Transport::OnChannelRequestSignaling(TransportChannelImpl* channel) {
578  ASSERT(worker_thread()->IsCurrent());
579  ChannelParams* params = new ChannelParams(channel->component());
580  signaling_thread()->Post(this, MSG_REQUESTSIGNALING, params);
581}
582
583void Transport::OnChannelRequestSignaling_s(int component) {
584  ASSERT(signaling_thread()->IsCurrent());
585  LOG(LS_INFO) << "Transport: " << content_name_ << ", allocating candidates";
586  // Resetting ICE state for the channel.
587  {
588    rtc::CritScope cs(&crit_);
589    ChannelMap::iterator iter = channels_.find(component);
590    if (iter != channels_.end())
591      iter->second.set_candidates_allocated(false);
592  }
593  SignalRequestSignaling(this);
594}
595
596void Transport::OnChannelCandidateReady(TransportChannelImpl* channel,
597                                        const Candidate& candidate) {
598  ASSERT(worker_thread()->IsCurrent());
599  rtc::CritScope cs(&crit_);
600  ready_candidates_.push_back(candidate);
601
602  // We hold any messages until the client lets us connect.
603  if (connect_requested_) {
604    signaling_thread()->Post(
605        this, MSG_CANDIDATEREADY, NULL);
606  }
607}
608
609void Transport::OnChannelCandidateReady_s() {
610  ASSERT(signaling_thread()->IsCurrent());
611  ASSERT(connect_requested_);
612
613  std::vector<Candidate> candidates;
614  {
615    rtc::CritScope cs(&crit_);
616    candidates.swap(ready_candidates_);
617  }
618
619  // we do the deleting of Candidate* here to keep the new above and
620  // delete below close to each other
621  if (!candidates.empty()) {
622    SignalCandidatesReady(this, candidates);
623  }
624}
625
626void Transport::OnChannelRouteChange(TransportChannel* channel,
627                                     const Candidate& remote_candidate) {
628  ASSERT(worker_thread()->IsCurrent());
629  ChannelParams* params = new ChannelParams(new Candidate(remote_candidate));
630  params->channel = static_cast<cricket::TransportChannelImpl*>(channel);
631  signaling_thread()->Post(this, MSG_ROUTECHANGE, params);
632}
633
634void Transport::OnChannelRouteChange_s(const TransportChannel* channel,
635                                       const Candidate& remote_candidate) {
636  ASSERT(signaling_thread()->IsCurrent());
637  SignalRouteChange(this, remote_candidate.component(), remote_candidate);
638}
639
640void Transport::OnChannelCandidatesAllocationDone(
641    TransportChannelImpl* channel) {
642  ASSERT(worker_thread()->IsCurrent());
643  rtc::CritScope cs(&crit_);
644  ChannelMap::iterator iter = channels_.find(channel->component());
645  ASSERT(iter != channels_.end());
646  LOG(LS_INFO) << "Transport: " << content_name_ << ", component "
647               << channel->component() << " allocation complete";
648  iter->second.set_candidates_allocated(true);
649
650  // If all channels belonging to this Transport got signal, then
651  // forward this signal to upper layer.
652  // Can this signal arrive before all transport channels are created?
653  for (iter = channels_.begin(); iter != channels_.end(); ++iter) {
654    if (!iter->second.candidates_allocated())
655      return;
656  }
657  signaling_thread_->Post(this, MSG_CANDIDATEALLOCATIONCOMPLETE);
658
659  MaybeCompleted_w();
660}
661
662void Transport::OnChannelCandidatesAllocationDone_s() {
663  ASSERT(signaling_thread()->IsCurrent());
664  LOG(LS_INFO) << "Transport: " << content_name_ << " allocation complete";
665  SignalCandidatesAllocationDone(this);
666}
667
668void Transport::OnRoleConflict(TransportChannelImpl* channel) {
669  signaling_thread_->Post(this, MSG_ROLECONFLICT);
670}
671
672void Transport::OnChannelConnectionRemoved(TransportChannelImpl* channel) {
673  ASSERT(worker_thread()->IsCurrent());
674  MaybeCompleted_w();
675
676  // Check if the state is now Failed.
677  // Failed is only available in the Controlling ICE role.
678  if (channel->GetIceRole() != ICEROLE_CONTROLLING) {
679    return;
680  }
681
682  ChannelMap::iterator iter = channels_.find(channel->component());
683  ASSERT(iter != channels_.end());
684  // Failed can only occur after candidate allocation has stopped.
685  if (!iter->second.candidates_allocated()) {
686    return;
687  }
688
689  size_t connections = channel->GetConnectionCount();
690  if (connections == 0) {
691    // A Transport has failed if any of its channels have no remaining
692    // connections.
693    signaling_thread_->Post(this, MSG_FAILED);
694  }
695}
696
697void Transport::MaybeCompleted_w() {
698  ASSERT(worker_thread()->IsCurrent());
699
700  // A Transport's ICE process is completed if all of its channels are writable,
701  // have finished allocating candidates, and have pruned all but one of their
702  // connections.
703  ChannelMap::const_iterator iter;
704  for (iter = channels_.begin(); iter != channels_.end(); ++iter) {
705    const TransportChannelImpl* channel = iter->second.get();
706    if (!(channel->writable() &&
707          channel->GetConnectionCount() == 1 &&
708          channel->GetIceRole() == ICEROLE_CONTROLLING &&
709          iter->second.candidates_allocated())) {
710      return;
711    }
712  }
713
714  signaling_thread_->Post(this, MSG_COMPLETED);
715}
716
717void Transport::SetIceRole_w(IceRole role) {
718  rtc::CritScope cs(&crit_);
719  ice_role_ = role;
720  for (ChannelMap::iterator iter = channels_.begin();
721       iter != channels_.end(); ++iter) {
722    iter->second->SetIceRole(ice_role_);
723  }
724}
725
726void Transport::SetRemoteIceMode_w(IceMode mode) {
727  rtc::CritScope cs(&crit_);
728  remote_ice_mode_ = mode;
729  // Shouldn't channels be created after this method executed?
730  for (ChannelMap::iterator iter = channels_.begin();
731       iter != channels_.end(); ++iter) {
732    iter->second->SetRemoteIceMode(remote_ice_mode_);
733  }
734}
735
736bool Transport::SetLocalTransportDescription_w(
737    const TransportDescription& desc,
738    ContentAction action,
739    std::string* error_desc) {
740  bool ret = true;
741  rtc::CritScope cs(&crit_);
742
743  if (!VerifyIceParams(desc)) {
744    return BadTransportDescription("Invalid ice-ufrag or ice-pwd length",
745                                   error_desc);
746  }
747
748  if (local_description_ && IceCredentialsChanged(*local_description_, desc)) {
749    IceRole new_ice_role = (action == CA_OFFER) ? ICEROLE_CONTROLLING
750                                                : ICEROLE_CONTROLLED;
751
752    // It must be called before ApplyLocalTransportDescription_w, which may
753    // trigger an ICE restart and depends on the new ICE role.
754    SetIceRole_w(new_ice_role);
755  }
756
757  local_description_.reset(new TransportDescription(desc));
758
759  for (ChannelMap::iterator iter = channels_.begin();
760       iter != channels_.end(); ++iter) {
761    ret &= ApplyLocalTransportDescription_w(iter->second.get(), error_desc);
762  }
763  if (!ret)
764    return false;
765
766  // If PRANSWER/ANSWER is set, we should decide transport protocol type.
767  if (action == CA_PRANSWER || action == CA_ANSWER) {
768    ret &= NegotiateTransportDescription_w(action, error_desc);
769  }
770  return ret;
771}
772
773bool Transport::SetRemoteTransportDescription_w(
774    const TransportDescription& desc,
775    ContentAction action,
776    std::string* error_desc) {
777  bool ret = true;
778  rtc::CritScope cs(&crit_);
779
780  if (!VerifyIceParams(desc)) {
781    return BadTransportDescription("Invalid ice-ufrag or ice-pwd length",
782                                   error_desc);
783  }
784
785  remote_description_.reset(new TransportDescription(desc));
786  for (ChannelMap::iterator iter = channels_.begin();
787       iter != channels_.end(); ++iter) {
788    ret &= ApplyRemoteTransportDescription_w(iter->second.get(), error_desc);
789  }
790
791  // If PRANSWER/ANSWER is set, we should decide transport protocol type.
792  if (action == CA_PRANSWER || action == CA_ANSWER) {
793    ret = NegotiateTransportDescription_w(CA_OFFER, error_desc);
794  }
795  return ret;
796}
797
798bool Transport::ApplyLocalTransportDescription_w(TransportChannelImpl* ch,
799                                                 std::string* error_desc) {
800  // If existing protocol_type is HYBRID, we may have not chosen the final
801  // protocol type, so update the channel protocol type from the
802  // local description. Otherwise, skip updating the protocol type.
803  // We check for HYBRID to avoid accidental changes; in the case of a
804  // session renegotiation, the new offer will have the google-ice ICE option,
805  // so we need to make sure we don't switch back from ICE mode to HYBRID
806  // when this happens.
807  // There are some other ways we could have solved this, but this is the
808  // simplest. The ultimate solution will be to get rid of GICE altogether.
809  IceProtocolType protocol_type;
810  if (ch->GetIceProtocolType(&protocol_type) &&
811      protocol_type == ICEPROTO_HYBRID) {
812    ch->SetIceProtocolType(
813        TransportProtocolFromDescription(local_description()));
814  }
815  ch->SetIceCredentials(local_description_->ice_ufrag,
816                        local_description_->ice_pwd);
817  return true;
818}
819
820bool Transport::ApplyRemoteTransportDescription_w(TransportChannelImpl* ch,
821                                                  std::string* error_desc) {
822  ch->SetRemoteIceCredentials(remote_description_->ice_ufrag,
823                              remote_description_->ice_pwd);
824  return true;
825}
826
827bool Transport::ApplyNegotiatedTransportDescription_w(
828    TransportChannelImpl* channel, std::string* error_desc) {
829  channel->SetIceProtocolType(protocol_);
830  channel->SetRemoteIceMode(remote_ice_mode_);
831  return true;
832}
833
834bool Transport::NegotiateTransportDescription_w(ContentAction local_role,
835                                                std::string* error_desc) {
836  // TODO(ekr@rtfm.com): This is ICE-specific stuff. Refactor into
837  // P2PTransport.
838  const TransportDescription* offer;
839  const TransportDescription* answer;
840
841  if (local_role == CA_OFFER) {
842    offer = local_description_.get();
843    answer = remote_description_.get();
844  } else {
845    offer = remote_description_.get();
846    answer = local_description_.get();
847  }
848
849  TransportProtocol offer_proto = TransportProtocolFromDescription(offer);
850  TransportProtocol answer_proto = TransportProtocolFromDescription(answer);
851
852  // If offered protocol is gice/ice, then we expect to receive matching
853  // protocol in answer, anything else is treated as an error.
854  // HYBRID is not an option when offered specific protocol.
855  // If offered protocol is HYBRID and answered protocol is HYBRID then
856  // gice is preferred protocol.
857  // TODO(mallinath) - Answer from local or remote should't have both ice
858  // and gice support. It should always pick which protocol it wants to use.
859  // Once WebRTC stops supporting gice (for backward compatibility), HYBRID in
860  // answer must be treated as error.
861  if ((offer_proto == ICEPROTO_GOOGLE || offer_proto == ICEPROTO_RFC5245) &&
862      (offer_proto != answer_proto)) {
863    std::ostringstream desc;
864    desc << "Offer and answer protocol mismatch: "
865         << IceProtoToString(offer_proto)
866         << " vs "
867         << IceProtoToString(answer_proto);
868    return BadTransportDescription(desc.str(), error_desc);
869  }
870  protocol_ = answer_proto == ICEPROTO_HYBRID ? ICEPROTO_GOOGLE : answer_proto;
871
872  // If transport is in ICEROLE_CONTROLLED and remote end point supports only
873  // ice_lite, this local end point should take CONTROLLING role.
874  if (ice_role_ == ICEROLE_CONTROLLED &&
875      remote_description_->ice_mode == ICEMODE_LITE) {
876    SetIceRole_w(ICEROLE_CONTROLLING);
877  }
878
879  // Update remote ice_mode to all existing channels.
880  remote_ice_mode_ = remote_description_->ice_mode;
881
882  // Now that we have negotiated everything, push it downward.
883  // Note that we cache the result so that if we have race conditions
884  // between future SetRemote/SetLocal invocations and new channel
885  // creation, we have the negotiation state saved until a new
886  // negotiation happens.
887  for (ChannelMap::iterator iter = channels_.begin();
888       iter != channels_.end();
889       ++iter) {
890    if (!ApplyNegotiatedTransportDescription_w(iter->second.get(), error_desc))
891      return false;
892  }
893  return true;
894}
895
896void Transport::OnMessage(rtc::Message* msg) {
897  switch (msg->message_id) {
898    case MSG_ONSIGNALINGREADY:
899      CallChannels_w(&TransportChannelImpl::OnSignalingReady);
900      break;
901    case MSG_ONREMOTECANDIDATE: {
902        ChannelParams* params = static_cast<ChannelParams*>(msg->pdata);
903        OnRemoteCandidate_w(*params->candidate);
904        delete params;
905      }
906      break;
907    case MSG_CONNECTING:
908      OnConnecting_s();
909      break;
910    case MSG_READSTATE:
911      OnChannelReadableState_s();
912      break;
913    case MSG_WRITESTATE:
914      OnChannelWritableState_s();
915      break;
916    case MSG_REQUESTSIGNALING: {
917        ChannelParams* params = static_cast<ChannelParams*>(msg->pdata);
918        OnChannelRequestSignaling_s(params->component);
919        delete params;
920      }
921      break;
922    case MSG_CANDIDATEREADY:
923      OnChannelCandidateReady_s();
924      break;
925    case MSG_ROUTECHANGE: {
926        ChannelParams* params = static_cast<ChannelParams*>(msg->pdata);
927        OnChannelRouteChange_s(params->channel, *params->candidate);
928        delete params;
929      }
930      break;
931    case MSG_CANDIDATEALLOCATIONCOMPLETE:
932      OnChannelCandidatesAllocationDone_s();
933      break;
934    case MSG_ROLECONFLICT:
935      SignalRoleConflict();
936      break;
937    case MSG_COMPLETED:
938      SignalCompleted(this);
939      break;
940    case MSG_FAILED:
941      SignalFailed(this);
942      break;
943  }
944}
945
946bool TransportParser::ParseAddress(const buzz::XmlElement* elem,
947                                   const buzz::QName& address_name,
948                                   const buzz::QName& port_name,
949                                   rtc::SocketAddress* address,
950                                   ParseError* error) {
951  if (!elem->HasAttr(address_name))
952    return BadParse("address does not have " + address_name.LocalPart(), error);
953  if (!elem->HasAttr(port_name))
954    return BadParse("address does not have " + port_name.LocalPart(), error);
955
956  address->SetIP(elem->Attr(address_name));
957  std::istringstream ist(elem->Attr(port_name));
958  int port = 0;
959  ist >> port;
960  address->SetPort(port);
961
962  return true;
963}
964
965// We're GICE if the namespace is NS_GOOGLE_P2P, or if NS_JINGLE_ICE_UDP is
966// used and the GICE ice-option is set.
967TransportProtocol TransportProtocolFromDescription(
968    const TransportDescription* desc) {
969  ASSERT(desc != NULL);
970  if (desc->transport_type == NS_JINGLE_ICE_UDP) {
971    return (desc->HasOption(ICE_OPTION_GICE)) ?
972        ICEPROTO_HYBRID : ICEPROTO_RFC5245;
973  }
974  return ICEPROTO_GOOGLE;
975}
976
977}  // namespace cricket
978