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