Home | History | Annotate | Download | only in client
      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/client/basicportallocator.h"
     29 
     30 #include <string>
     31 #include <vector>
     32 
     33 #include "talk/p2p/base/basicpacketsocketfactory.h"
     34 #include "talk/p2p/base/common.h"
     35 #include "talk/p2p/base/port.h"
     36 #include "talk/p2p/base/relayport.h"
     37 #include "talk/p2p/base/stunport.h"
     38 #include "talk/p2p/base/tcpport.h"
     39 #include "talk/p2p/base/turnport.h"
     40 #include "talk/p2p/base/udpport.h"
     41 #include "webrtc/base/common.h"
     42 #include "webrtc/base/helpers.h"
     43 #include "webrtc/base/logging.h"
     44 
     45 using rtc::CreateRandomId;
     46 using rtc::CreateRandomString;
     47 
     48 namespace {
     49 
     50 enum {
     51   MSG_CONFIG_START,
     52   MSG_CONFIG_READY,
     53   MSG_ALLOCATE,
     54   MSG_ALLOCATION_PHASE,
     55   MSG_SHAKE,
     56   MSG_SEQUENCEOBJECTS_CREATED,
     57   MSG_CONFIG_STOP,
     58 };
     59 
     60 const int PHASE_UDP = 0;
     61 const int PHASE_RELAY = 1;
     62 const int PHASE_TCP = 2;
     63 const int PHASE_SSLTCP = 3;
     64 
     65 const int kNumPhases = 4;
     66 
     67 const int SHAKE_MIN_DELAY = 45 * 1000;  // 45 seconds
     68 const int SHAKE_MAX_DELAY = 90 * 1000;  // 90 seconds
     69 
     70 int ShakeDelay() {
     71   int range = SHAKE_MAX_DELAY - SHAKE_MIN_DELAY + 1;
     72   return SHAKE_MIN_DELAY + CreateRandomId() % range;
     73 }
     74 
     75 }  // namespace
     76 
     77 namespace cricket {
     78 
     79 const uint32 DISABLE_ALL_PHASES =
     80   PORTALLOCATOR_DISABLE_UDP
     81   | PORTALLOCATOR_DISABLE_TCP
     82   | PORTALLOCATOR_DISABLE_STUN
     83   | PORTALLOCATOR_DISABLE_RELAY;
     84 
     85 // Performs the allocation of ports, in a sequenced (timed) manner, for a given
     86 // network and IP address.
     87 class AllocationSequence : public rtc::MessageHandler,
     88                            public sigslot::has_slots<> {
     89  public:
     90   enum State {
     91     kInit,       // Initial state.
     92     kRunning,    // Started allocating ports.
     93     kStopped,    // Stopped from running.
     94     kCompleted,  // All ports are allocated.
     95 
     96     // kInit --> kRunning --> {kCompleted|kStopped}
     97   };
     98 
     99   AllocationSequence(BasicPortAllocatorSession* session,
    100                      rtc::Network* network,
    101                      PortConfiguration* config,
    102                      uint32 flags);
    103   ~AllocationSequence();
    104   bool Init();
    105   void Clear();
    106 
    107   State state() const { return state_; }
    108 
    109   // Disables the phases for a new sequence that this one already covers for an
    110   // equivalent network setup.
    111   void DisableEquivalentPhases(rtc::Network* network,
    112       PortConfiguration* config, uint32* flags);
    113 
    114   // Starts and stops the sequence.  When started, it will continue allocating
    115   // new ports on its own timed schedule.
    116   void Start();
    117   void Stop();
    118 
    119   // MessageHandler
    120   void OnMessage(rtc::Message* msg);
    121 
    122   void EnableProtocol(ProtocolType proto);
    123   bool ProtocolEnabled(ProtocolType proto) const;
    124 
    125   // Signal from AllocationSequence, when it's done with allocating ports.
    126   // This signal is useful, when port allocation fails which doesn't result
    127   // in any candidates. Using this signal BasicPortAllocatorSession can send
    128   // its candidate discovery conclusion signal. Without this signal,
    129   // BasicPortAllocatorSession doesn't have any event to trigger signal. This
    130   // can also be achieved by starting timer in BPAS.
    131   sigslot::signal1<AllocationSequence*> SignalPortAllocationComplete;
    132 
    133  private:
    134   typedef std::vector<ProtocolType> ProtocolList;
    135 
    136   bool IsFlagSet(uint32 flag) {
    137     return ((flags_ & flag) != 0);
    138   }
    139   void CreateUDPPorts();
    140   void CreateTCPPorts();
    141   void CreateStunPorts();
    142   void CreateRelayPorts();
    143   void CreateGturnPort(const RelayServerConfig& config);
    144   void CreateTurnPort(const RelayServerConfig& config);
    145 
    146   void OnReadPacket(rtc::AsyncPacketSocket* socket,
    147                     const char* data, size_t size,
    148                     const rtc::SocketAddress& remote_addr,
    149                     const rtc::PacketTime& packet_time);
    150 
    151   void OnPortDestroyed(PortInterface* port);
    152 
    153   BasicPortAllocatorSession* session_;
    154   rtc::Network* network_;
    155   rtc::IPAddress ip_;
    156   PortConfiguration* config_;
    157   State state_;
    158   uint32 flags_;
    159   ProtocolList protocols_;
    160   rtc::scoped_ptr<rtc::AsyncPacketSocket> udp_socket_;
    161   // There will be only one udp port per AllocationSequence.
    162   UDPPort* udp_port_;
    163   std::vector<TurnPort*> turn_ports_;
    164   int phase_;
    165 };
    166 
    167 // BasicPortAllocator
    168 BasicPortAllocator::BasicPortAllocator(
    169     rtc::NetworkManager* network_manager,
    170     rtc::PacketSocketFactory* socket_factory)
    171     : network_manager_(network_manager),
    172       socket_factory_(socket_factory) {
    173   ASSERT(socket_factory_ != NULL);
    174   Construct();
    175 }
    176 
    177 BasicPortAllocator::BasicPortAllocator(
    178     rtc::NetworkManager* network_manager)
    179     : network_manager_(network_manager),
    180       socket_factory_(NULL) {
    181   Construct();
    182 }
    183 
    184 BasicPortAllocator::BasicPortAllocator(
    185     rtc::NetworkManager* network_manager,
    186     rtc::PacketSocketFactory* socket_factory,
    187     const ServerAddresses& stun_servers)
    188     : network_manager_(network_manager),
    189       socket_factory_(socket_factory),
    190       stun_servers_(stun_servers) {
    191   ASSERT(socket_factory_ != NULL);
    192   Construct();
    193 }
    194 
    195 BasicPortAllocator::BasicPortAllocator(
    196     rtc::NetworkManager* network_manager,
    197     const ServerAddresses& stun_servers,
    198     const rtc::SocketAddress& relay_address_udp,
    199     const rtc::SocketAddress& relay_address_tcp,
    200     const rtc::SocketAddress& relay_address_ssl)
    201     : network_manager_(network_manager),
    202       socket_factory_(NULL),
    203       stun_servers_(stun_servers) {
    204 
    205   RelayServerConfig config(RELAY_GTURN);
    206   if (!relay_address_udp.IsNil())
    207     config.ports.push_back(ProtocolAddress(relay_address_udp, PROTO_UDP));
    208   if (!relay_address_tcp.IsNil())
    209     config.ports.push_back(ProtocolAddress(relay_address_tcp, PROTO_TCP));
    210   if (!relay_address_ssl.IsNil())
    211     config.ports.push_back(ProtocolAddress(relay_address_ssl, PROTO_SSLTCP));
    212 
    213   if (!config.ports.empty())
    214     AddRelay(config);
    215 
    216   Construct();
    217 }
    218 
    219 void BasicPortAllocator::Construct() {
    220   allow_tcp_listen_ = true;
    221 }
    222 
    223 BasicPortAllocator::~BasicPortAllocator() {
    224 }
    225 
    226 PortAllocatorSession *BasicPortAllocator::CreateSessionInternal(
    227     const std::string& content_name, int component,
    228     const std::string& ice_ufrag, const std::string& ice_pwd) {
    229   return new BasicPortAllocatorSession(
    230       this, content_name, component, ice_ufrag, ice_pwd);
    231 }
    232 
    233 
    234 // BasicPortAllocatorSession
    235 BasicPortAllocatorSession::BasicPortAllocatorSession(
    236     BasicPortAllocator *allocator,
    237     const std::string& content_name,
    238     int component,
    239     const std::string& ice_ufrag,
    240     const std::string& ice_pwd)
    241     : PortAllocatorSession(content_name, component,
    242                            ice_ufrag, ice_pwd, allocator->flags()),
    243       allocator_(allocator), network_thread_(NULL),
    244       socket_factory_(allocator->socket_factory()),
    245       allocation_started_(false),
    246       network_manager_started_(false),
    247       running_(false),
    248       allocation_sequences_created_(false) {
    249   allocator_->network_manager()->SignalNetworksChanged.connect(
    250       this, &BasicPortAllocatorSession::OnNetworksChanged);
    251   allocator_->network_manager()->StartUpdating();
    252 }
    253 
    254 BasicPortAllocatorSession::~BasicPortAllocatorSession() {
    255   allocator_->network_manager()->StopUpdating();
    256   if (network_thread_ != NULL)
    257     network_thread_->Clear(this);
    258 
    259   for (uint32 i = 0; i < sequences_.size(); ++i) {
    260     // AllocationSequence should clear it's map entry for turn ports before
    261     // ports are destroyed.
    262     sequences_[i]->Clear();
    263   }
    264 
    265   std::vector<PortData>::iterator it;
    266   for (it = ports_.begin(); it != ports_.end(); it++)
    267     delete it->port();
    268 
    269   for (uint32 i = 0; i < configs_.size(); ++i)
    270     delete configs_[i];
    271 
    272   for (uint32 i = 0; i < sequences_.size(); ++i)
    273     delete sequences_[i];
    274 }
    275 
    276 void BasicPortAllocatorSession::StartGettingPorts() {
    277   network_thread_ = rtc::Thread::Current();
    278   if (!socket_factory_) {
    279     owned_socket_factory_.reset(
    280         new rtc::BasicPacketSocketFactory(network_thread_));
    281     socket_factory_ = owned_socket_factory_.get();
    282   }
    283 
    284   running_ = true;
    285   network_thread_->Post(this, MSG_CONFIG_START);
    286 
    287   if (flags() & PORTALLOCATOR_ENABLE_SHAKER)
    288     network_thread_->PostDelayed(ShakeDelay(), this, MSG_SHAKE);
    289 }
    290 
    291 void BasicPortAllocatorSession::StopGettingPorts() {
    292   ASSERT(rtc::Thread::Current() == network_thread_);
    293   running_ = false;
    294   network_thread_->Clear(this, MSG_ALLOCATE);
    295   for (uint32 i = 0; i < sequences_.size(); ++i)
    296     sequences_[i]->Stop();
    297   network_thread_->Post(this, MSG_CONFIG_STOP);
    298 }
    299 
    300 void BasicPortAllocatorSession::OnMessage(rtc::Message *message) {
    301   switch (message->message_id) {
    302   case MSG_CONFIG_START:
    303     ASSERT(rtc::Thread::Current() == network_thread_);
    304     GetPortConfigurations();
    305     break;
    306 
    307   case MSG_CONFIG_READY:
    308     ASSERT(rtc::Thread::Current() == network_thread_);
    309     OnConfigReady(static_cast<PortConfiguration*>(message->pdata));
    310     break;
    311 
    312   case MSG_ALLOCATE:
    313     ASSERT(rtc::Thread::Current() == network_thread_);
    314     OnAllocate();
    315     break;
    316 
    317   case MSG_SHAKE:
    318     ASSERT(rtc::Thread::Current() == network_thread_);
    319     OnShake();
    320     break;
    321   case MSG_SEQUENCEOBJECTS_CREATED:
    322     ASSERT(rtc::Thread::Current() == network_thread_);
    323     OnAllocationSequenceObjectsCreated();
    324     break;
    325   case MSG_CONFIG_STOP:
    326     ASSERT(rtc::Thread::Current() == network_thread_);
    327     OnConfigStop();
    328     break;
    329   default:
    330     ASSERT(false);
    331   }
    332 }
    333 
    334 void BasicPortAllocatorSession::GetPortConfigurations() {
    335   PortConfiguration* config = new PortConfiguration(allocator_->stun_servers(),
    336                                                     username(),
    337                                                     password());
    338 
    339   for (size_t i = 0; i < allocator_->relays().size(); ++i) {
    340     config->AddRelay(allocator_->relays()[i]);
    341   }
    342   ConfigReady(config);
    343 }
    344 
    345 void BasicPortAllocatorSession::ConfigReady(PortConfiguration* config) {
    346   network_thread_->Post(this, MSG_CONFIG_READY, config);
    347 }
    348 
    349 // Adds a configuration to the list.
    350 void BasicPortAllocatorSession::OnConfigReady(PortConfiguration* config) {
    351   if (config)
    352     configs_.push_back(config);
    353 
    354   AllocatePorts();
    355 }
    356 
    357 void BasicPortAllocatorSession::OnConfigStop() {
    358   ASSERT(rtc::Thread::Current() == network_thread_);
    359 
    360   // If any of the allocated ports have not completed the candidates allocation,
    361   // mark those as error. Since session doesn't need any new candidates
    362   // at this stage of the allocation, it's safe to discard any new candidates.
    363   bool send_signal = false;
    364   for (std::vector<PortData>::iterator it = ports_.begin();
    365        it != ports_.end(); ++it) {
    366     if (!it->complete()) {
    367       // Updating port state to error, which didn't finish allocating candidates
    368       // yet.
    369       it->set_error();
    370       send_signal = true;
    371     }
    372   }
    373 
    374   // Did we stop any running sequences?
    375   for (std::vector<AllocationSequence*>::iterator it = sequences_.begin();
    376        it != sequences_.end() && !send_signal; ++it) {
    377     if ((*it)->state() == AllocationSequence::kStopped) {
    378       send_signal = true;
    379     }
    380   }
    381 
    382   // If we stopped anything that was running, send a done signal now.
    383   if (send_signal) {
    384     MaybeSignalCandidatesAllocationDone();
    385   }
    386 }
    387 
    388 void BasicPortAllocatorSession::AllocatePorts() {
    389   ASSERT(rtc::Thread::Current() == network_thread_);
    390   network_thread_->Post(this, MSG_ALLOCATE);
    391 }
    392 
    393 void BasicPortAllocatorSession::OnAllocate() {
    394   if (network_manager_started_)
    395     DoAllocate();
    396 
    397   allocation_started_ = true;
    398 }
    399 
    400 // For each network, see if we have a sequence that covers it already.  If not,
    401 // create a new sequence to create the appropriate ports.
    402 void BasicPortAllocatorSession::DoAllocate() {
    403   bool done_signal_needed = false;
    404   std::vector<rtc::Network*> networks;
    405   allocator_->network_manager()->GetNetworks(&networks);
    406   if (networks.empty()) {
    407     LOG(LS_WARNING) << "Machine has no networks; no ports will be allocated";
    408     done_signal_needed = true;
    409   } else {
    410     for (uint32 i = 0; i < networks.size(); ++i) {
    411       PortConfiguration* config = NULL;
    412       if (configs_.size() > 0)
    413         config = configs_.back();
    414 
    415       uint32 sequence_flags = flags();
    416       if ((sequence_flags & DISABLE_ALL_PHASES) == DISABLE_ALL_PHASES) {
    417         // If all the ports are disabled we should just fire the allocation
    418         // done event and return.
    419         done_signal_needed = true;
    420         break;
    421       }
    422 
    423       // Disables phases that are not specified in this config.
    424       if (!config || config->StunServers().empty()) {
    425         // No STUN ports specified in this config.
    426         sequence_flags |= PORTALLOCATOR_DISABLE_STUN;
    427       }
    428       if (!config || config->relays.empty()) {
    429         // No relay ports specified in this config.
    430         sequence_flags |= PORTALLOCATOR_DISABLE_RELAY;
    431       }
    432 
    433       if (!(sequence_flags & PORTALLOCATOR_ENABLE_IPV6) &&
    434 #ifdef USE_WEBRTC_DEV_BRANCH
    435           networks[i]->GetBestIP().family() == AF_INET6) {
    436 #else  // USE_WEBRTC_DEV_BRANCH
    437           networks[i]->ip().family() == AF_INET6) {
    438 #endif  // USE_WEBRTC_DEV_BRANCH
    439         // Skip IPv6 networks unless the flag's been set.
    440         continue;
    441       }
    442 
    443       // Disable phases that would only create ports equivalent to
    444       // ones that we have already made.
    445       DisableEquivalentPhases(networks[i], config, &sequence_flags);
    446 
    447       if ((sequence_flags & DISABLE_ALL_PHASES) == DISABLE_ALL_PHASES) {
    448         // New AllocationSequence would have nothing to do, so don't make it.
    449         continue;
    450       }
    451 
    452       AllocationSequence* sequence =
    453           new AllocationSequence(this, networks[i], config, sequence_flags);
    454       if (!sequence->Init()) {
    455         delete sequence;
    456         continue;
    457       }
    458       done_signal_needed = true;
    459       sequence->SignalPortAllocationComplete.connect(
    460           this, &BasicPortAllocatorSession::OnPortAllocationComplete);
    461       if (running_)
    462         sequence->Start();
    463       sequences_.push_back(sequence);
    464     }
    465   }
    466   if (done_signal_needed) {
    467     network_thread_->Post(this, MSG_SEQUENCEOBJECTS_CREATED);
    468   }
    469 }
    470 
    471 void BasicPortAllocatorSession::OnNetworksChanged() {
    472   network_manager_started_ = true;
    473   if (allocation_started_)
    474     DoAllocate();
    475 }
    476 
    477 void BasicPortAllocatorSession::DisableEquivalentPhases(
    478     rtc::Network* network, PortConfiguration* config, uint32* flags) {
    479   for (uint32 i = 0; i < sequences_.size() &&
    480       (*flags & DISABLE_ALL_PHASES) != DISABLE_ALL_PHASES; ++i) {
    481     sequences_[i]->DisableEquivalentPhases(network, config, flags);
    482   }
    483 }
    484 
    485 void BasicPortAllocatorSession::AddAllocatedPort(Port* port,
    486                                                  AllocationSequence * seq,
    487                                                  bool prepare_address) {
    488   if (!port)
    489     return;
    490 
    491   LOG(LS_INFO) << "Adding allocated port for " << content_name();
    492   port->set_content_name(content_name());
    493   port->set_component(component_);
    494   port->set_generation(generation());
    495   if (allocator_->proxy().type != rtc::PROXY_NONE)
    496     port->set_proxy(allocator_->user_agent(), allocator_->proxy());
    497   port->set_send_retransmit_count_attribute((allocator_->flags() &
    498       PORTALLOCATOR_ENABLE_STUN_RETRANSMIT_ATTRIBUTE) != 0);
    499 
    500   PortData data(port, seq);
    501   ports_.push_back(data);
    502 
    503   port->SignalCandidateReady.connect(
    504       this, &BasicPortAllocatorSession::OnCandidateReady);
    505   port->SignalPortComplete.connect(this,
    506       &BasicPortAllocatorSession::OnPortComplete);
    507   port->SignalDestroyed.connect(this,
    508       &BasicPortAllocatorSession::OnPortDestroyed);
    509   port->SignalPortError.connect(
    510       this, &BasicPortAllocatorSession::OnPortError);
    511   LOG_J(LS_INFO, port) << "Added port to allocator";
    512 
    513   if (prepare_address)
    514     port->PrepareAddress();
    515 }
    516 
    517 void BasicPortAllocatorSession::OnAllocationSequenceObjectsCreated() {
    518   allocation_sequences_created_ = true;
    519   // Send candidate allocation complete signal if we have no sequences.
    520   MaybeSignalCandidatesAllocationDone();
    521 }
    522 
    523 void BasicPortAllocatorSession::OnCandidateReady(
    524     Port* port, const Candidate& c) {
    525   ASSERT(rtc::Thread::Current() == network_thread_);
    526   PortData* data = FindPort(port);
    527   ASSERT(data != NULL);
    528   // Discarding any candidate signal if port allocation status is
    529   // already in completed state.
    530   if (data->complete())
    531     return;
    532 
    533   // Send candidates whose protocol is enabled.
    534   std::vector<Candidate> candidates;
    535   ProtocolType pvalue;
    536   bool candidate_allowed_to_send = CheckCandidateFilter(c);
    537   if (StringToProto(c.protocol().c_str(), &pvalue) &&
    538       data->sequence()->ProtocolEnabled(pvalue) &&
    539       candidate_allowed_to_send) {
    540     candidates.push_back(c);
    541   }
    542 
    543   if (!candidates.empty()) {
    544     SignalCandidatesReady(this, candidates);
    545   }
    546 
    547   // Moving to READY state as we have atleast one candidate from the port.
    548   // Since this port has atleast one candidate we should forward this port
    549   // to listners, to allow connections from this port.
    550   // Also we should make sure that candidate gathered from this port is allowed
    551   // to send outside.
    552   if (!data->ready() && candidate_allowed_to_send) {
    553     data->set_ready();
    554     SignalPortReady(this, port);
    555   }
    556 }
    557 
    558 void BasicPortAllocatorSession::OnPortComplete(Port* port) {
    559   ASSERT(rtc::Thread::Current() == network_thread_);
    560   PortData* data = FindPort(port);
    561   ASSERT(data != NULL);
    562 
    563   // Ignore any late signals.
    564   if (data->complete())
    565     return;
    566 
    567   // Moving to COMPLETE state.
    568   data->set_complete();
    569   // Send candidate allocation complete signal if this was the last port.
    570   MaybeSignalCandidatesAllocationDone();
    571 }
    572 
    573 void BasicPortAllocatorSession::OnPortError(Port* port) {
    574   ASSERT(rtc::Thread::Current() == network_thread_);
    575   PortData* data = FindPort(port);
    576   ASSERT(data != NULL);
    577   // We might have already given up on this port and stopped it.
    578   if (data->complete())
    579     return;
    580 
    581   // SignalAddressError is currently sent from StunPort/TurnPort.
    582   // But this signal itself is generic.
    583   data->set_error();
    584   // Send candidate allocation complete signal if this was the last port.
    585   MaybeSignalCandidatesAllocationDone();
    586 }
    587 
    588 void BasicPortAllocatorSession::OnProtocolEnabled(AllocationSequence* seq,
    589                                                   ProtocolType proto) {
    590   std::vector<Candidate> candidates;
    591   for (std::vector<PortData>::iterator it = ports_.begin();
    592        it != ports_.end(); ++it) {
    593     if (it->sequence() != seq)
    594       continue;
    595 
    596     const std::vector<Candidate>& potentials = it->port()->Candidates();
    597     for (size_t i = 0; i < potentials.size(); ++i) {
    598       if (!CheckCandidateFilter(potentials[i]))
    599         continue;
    600       ProtocolType pvalue;
    601       if (!StringToProto(potentials[i].protocol().c_str(), &pvalue))
    602         continue;
    603       if (pvalue == proto) {
    604         candidates.push_back(potentials[i]);
    605       }
    606     }
    607   }
    608 
    609   if (!candidates.empty()) {
    610     SignalCandidatesReady(this, candidates);
    611   }
    612 }
    613 
    614 bool BasicPortAllocatorSession::CheckCandidateFilter(const Candidate& c) {
    615   uint32 filter = allocator_->candidate_filter();
    616   bool allowed = false;
    617   if (filter & CF_RELAY) {
    618     allowed |= (c.type() == RELAY_PORT_TYPE);
    619   }
    620 
    621   if (filter & CF_REFLEXIVE) {
    622     // We allow host candidates if the filter allows server-reflexive candidates
    623     // and the candidate is a public IP. Because we don't generate
    624     // server-reflexive candidates if they have the same IP as the host
    625     // candidate (i.e. when the host candidate is a public IP), filtering to
    626     // only server-reflexive candidates won't work right when the host
    627     // candidates have public IPs.
    628     allowed |= (c.type() == STUN_PORT_TYPE) ||
    629                (c.type() == LOCAL_PORT_TYPE && !c.address().IsPrivateIP());
    630   }
    631 
    632   if (filter & CF_HOST) {
    633     allowed |= (c.type() == LOCAL_PORT_TYPE);
    634   }
    635 
    636   return allowed;
    637 }
    638 
    639 void BasicPortAllocatorSession::OnPortAllocationComplete(
    640     AllocationSequence* seq) {
    641   // Send candidate allocation complete signal if all ports are done.
    642   MaybeSignalCandidatesAllocationDone();
    643 }
    644 
    645 void BasicPortAllocatorSession::MaybeSignalCandidatesAllocationDone() {
    646   // Send signal only if all required AllocationSequence objects
    647   // are created.
    648   if (!allocation_sequences_created_)
    649     return;
    650 
    651   // Check that all port allocation sequences are complete.
    652   for (std::vector<AllocationSequence*>::iterator it = sequences_.begin();
    653        it != sequences_.end(); ++it) {
    654     if ((*it)->state() == AllocationSequence::kRunning)
    655       return;
    656   }
    657 
    658   // If all allocated ports are in complete state, session must have got all
    659   // expected candidates. Session will trigger candidates allocation complete
    660   // signal.
    661   for (std::vector<PortData>::iterator it = ports_.begin();
    662        it != ports_.end(); ++it) {
    663     if (!it->complete())
    664       return;
    665   }
    666   LOG(LS_INFO) << "All candidates gathered for " << content_name_ << ":"
    667                << component_ << ":" << generation();
    668   SignalCandidatesAllocationDone(this);
    669 }
    670 
    671 void BasicPortAllocatorSession::OnPortDestroyed(
    672     PortInterface* port) {
    673   ASSERT(rtc::Thread::Current() == network_thread_);
    674   for (std::vector<PortData>::iterator iter = ports_.begin();
    675        iter != ports_.end(); ++iter) {
    676     if (port == iter->port()) {
    677       ports_.erase(iter);
    678       LOG_J(LS_INFO, port) << "Removed port from allocator ("
    679                            << static_cast<int>(ports_.size()) << " remaining)";
    680       return;
    681     }
    682   }
    683   ASSERT(false);
    684 }
    685 
    686 void BasicPortAllocatorSession::OnShake() {
    687   LOG(INFO) << ">>>>> SHAKE <<<<< >>>>> SHAKE <<<<< >>>>> SHAKE <<<<<";
    688 
    689   std::vector<Port*> ports;
    690   std::vector<Connection*> connections;
    691 
    692   for (size_t i = 0; i < ports_.size(); ++i) {
    693     if (ports_[i].ready())
    694       ports.push_back(ports_[i].port());
    695   }
    696 
    697   for (size_t i = 0; i < ports.size(); ++i) {
    698     Port::AddressMap::const_iterator iter;
    699     for (iter = ports[i]->connections().begin();
    700          iter != ports[i]->connections().end();
    701          ++iter) {
    702       connections.push_back(iter->second);
    703     }
    704   }
    705 
    706   LOG(INFO) << ">>>>> Destroying " << ports.size() << " ports and "
    707             << connections.size() << " connections";
    708 
    709   for (size_t i = 0; i < connections.size(); ++i)
    710     connections[i]->Destroy();
    711 
    712   if (running_ || (ports.size() > 0) || (connections.size() > 0))
    713     network_thread_->PostDelayed(ShakeDelay(), this, MSG_SHAKE);
    714 }
    715 
    716 BasicPortAllocatorSession::PortData* BasicPortAllocatorSession::FindPort(
    717     Port* port) {
    718   for (std::vector<PortData>::iterator it = ports_.begin();
    719        it != ports_.end(); ++it) {
    720     if (it->port() == port) {
    721       return &*it;
    722     }
    723   }
    724   return NULL;
    725 }
    726 
    727 // AllocationSequence
    728 
    729 AllocationSequence::AllocationSequence(BasicPortAllocatorSession* session,
    730                                        rtc::Network* network,
    731                                        PortConfiguration* config,
    732                                        uint32 flags)
    733     : session_(session),
    734       network_(network),
    735 
    736 #ifdef USE_WEBRTC_DEV_BRANCH
    737       ip_(network->GetBestIP()),
    738 #else  // USE_WEBRTC_DEV_BRANCH
    739       ip_(network->ip()),
    740 #endif  // USE_WEBRTC_DEV_BRANCH
    741       config_(config),
    742       state_(kInit),
    743       flags_(flags),
    744       udp_socket_(),
    745       udp_port_(NULL),
    746       phase_(0) {
    747 }
    748 
    749 bool AllocationSequence::Init() {
    750   if (IsFlagSet(PORTALLOCATOR_ENABLE_SHARED_SOCKET) &&
    751       !IsFlagSet(PORTALLOCATOR_ENABLE_SHARED_UFRAG)) {
    752     LOG(LS_ERROR) << "Shared socket option can't be set without "
    753                   << "shared ufrag.";
    754     ASSERT(false);
    755     return false;
    756   }
    757 
    758   if (IsFlagSet(PORTALLOCATOR_ENABLE_SHARED_SOCKET)) {
    759     udp_socket_.reset(session_->socket_factory()->CreateUdpSocket(
    760         rtc::SocketAddress(ip_, 0), session_->allocator()->min_port(),
    761         session_->allocator()->max_port()));
    762     if (udp_socket_) {
    763       udp_socket_->SignalReadPacket.connect(
    764           this, &AllocationSequence::OnReadPacket);
    765     }
    766     // Continuing if |udp_socket_| is NULL, as local TCP and RelayPort using TCP
    767     // are next available options to setup a communication channel.
    768   }
    769   return true;
    770 }
    771 
    772 void AllocationSequence::Clear() {
    773   udp_port_ = NULL;
    774   turn_ports_.clear();
    775 }
    776 
    777 AllocationSequence::~AllocationSequence() {
    778   session_->network_thread()->Clear(this);
    779 }
    780 
    781 void AllocationSequence::DisableEquivalentPhases(rtc::Network* network,
    782     PortConfiguration* config, uint32* flags) {
    783 #ifdef USE_WEBRTC_DEV_BRANCH
    784   if (!((network == network_) && (ip_ == network->GetBestIP()))) {
    785 #else  // USE_WEBRTC_DEV_BRANCH
    786   if (!((network == network_) && (ip_ == network->ip()))) {
    787 #endif  // USE_WEBRTC_DEV_BRANCH
    788     // Different network setup; nothing is equivalent.
    789     return;
    790   }
    791 
    792   // Else turn off the stuff that we've already got covered.
    793 
    794   // Every config implicitly specifies local, so turn that off right away.
    795   *flags |= PORTALLOCATOR_DISABLE_UDP;
    796   *flags |= PORTALLOCATOR_DISABLE_TCP;
    797 
    798   if (config_ && config) {
    799     if (config_->StunServers() == config->StunServers()) {
    800       // Already got this STUN servers covered.
    801       *flags |= PORTALLOCATOR_DISABLE_STUN;
    802     }
    803     if (!config_->relays.empty()) {
    804       // Already got relays covered.
    805       // NOTE: This will even skip a _different_ set of relay servers if we
    806       // were to be given one, but that never happens in our codebase. Should
    807       // probably get rid of the list in PortConfiguration and just keep a
    808       // single relay server in each one.
    809       *flags |= PORTALLOCATOR_DISABLE_RELAY;
    810     }
    811   }
    812 }
    813 
    814 void AllocationSequence::Start() {
    815   state_ = kRunning;
    816   session_->network_thread()->Post(this, MSG_ALLOCATION_PHASE);
    817 }
    818 
    819 void AllocationSequence::Stop() {
    820   // If the port is completed, don't set it to stopped.
    821   if (state_ == kRunning) {
    822     state_ = kStopped;
    823     session_->network_thread()->Clear(this, MSG_ALLOCATION_PHASE);
    824   }
    825 }
    826 
    827 void AllocationSequence::OnMessage(rtc::Message* msg) {
    828   ASSERT(rtc::Thread::Current() == session_->network_thread());
    829   ASSERT(msg->message_id == MSG_ALLOCATION_PHASE);
    830 
    831   const char* const PHASE_NAMES[kNumPhases] = {
    832     "Udp", "Relay", "Tcp", "SslTcp"
    833   };
    834 
    835   // Perform all of the phases in the current step.
    836   LOG_J(LS_INFO, network_) << "Allocation Phase="
    837                            << PHASE_NAMES[phase_];
    838 
    839   switch (phase_) {
    840     case PHASE_UDP:
    841       CreateUDPPorts();
    842       CreateStunPorts();
    843       EnableProtocol(PROTO_UDP);
    844       break;
    845 
    846     case PHASE_RELAY:
    847       CreateRelayPorts();
    848       break;
    849 
    850     case PHASE_TCP:
    851       CreateTCPPorts();
    852       EnableProtocol(PROTO_TCP);
    853       break;
    854 
    855     case PHASE_SSLTCP:
    856       state_ = kCompleted;
    857       EnableProtocol(PROTO_SSLTCP);
    858       break;
    859 
    860     default:
    861       ASSERT(false);
    862   }
    863 
    864   if (state() == kRunning) {
    865     ++phase_;
    866     session_->network_thread()->PostDelayed(
    867         session_->allocator()->step_delay(),
    868         this, MSG_ALLOCATION_PHASE);
    869   } else {
    870     // If all phases in AllocationSequence are completed, no allocation
    871     // steps needed further. Canceling  pending signal.
    872     session_->network_thread()->Clear(this, MSG_ALLOCATION_PHASE);
    873     SignalPortAllocationComplete(this);
    874   }
    875 }
    876 
    877 void AllocationSequence::EnableProtocol(ProtocolType proto) {
    878   if (!ProtocolEnabled(proto)) {
    879     protocols_.push_back(proto);
    880     session_->OnProtocolEnabled(this, proto);
    881   }
    882 }
    883 
    884 bool AllocationSequence::ProtocolEnabled(ProtocolType proto) const {
    885   for (ProtocolList::const_iterator it = protocols_.begin();
    886        it != protocols_.end(); ++it) {
    887     if (*it == proto)
    888       return true;
    889   }
    890   return false;
    891 }
    892 
    893 void AllocationSequence::CreateUDPPorts() {
    894   if (IsFlagSet(PORTALLOCATOR_DISABLE_UDP)) {
    895     LOG(LS_VERBOSE) << "AllocationSequence: UDP ports disabled, skipping.";
    896     return;
    897   }
    898 
    899   // TODO(mallinath) - Remove UDPPort creating socket after shared socket
    900   // is enabled completely.
    901   UDPPort* port = NULL;
    902   if (IsFlagSet(PORTALLOCATOR_ENABLE_SHARED_SOCKET) && udp_socket_) {
    903     port = UDPPort::Create(session_->network_thread(),
    904                            session_->socket_factory(), network_,
    905                            udp_socket_.get(),
    906                            session_->username(), session_->password());
    907   } else {
    908     port = UDPPort::Create(session_->network_thread(),
    909                            session_->socket_factory(),
    910                            network_, ip_,
    911                            session_->allocator()->min_port(),
    912                            session_->allocator()->max_port(),
    913                            session_->username(), session_->password());
    914   }
    915 
    916   if (port) {
    917     // If shared socket is enabled, STUN candidate will be allocated by the
    918     // UDPPort.
    919     if (IsFlagSet(PORTALLOCATOR_ENABLE_SHARED_SOCKET)) {
    920       udp_port_ = port;
    921 
    922       // If STUN is not disabled, setting stun server address to port.
    923       if (!IsFlagSet(PORTALLOCATOR_DISABLE_STUN)) {
    924         // If config has stun_servers, use it to get server reflexive candidate
    925         // otherwise use first TURN server which supports UDP.
    926         if (config_ && !config_->StunServers().empty()) {
    927           LOG(LS_INFO) << "AllocationSequence: UDPPort will be handling the "
    928                        <<  "STUN candidate generation.";
    929           port->set_server_addresses(config_->StunServers());
    930         } else if (config_ &&
    931                    config_->SupportsProtocol(RELAY_TURN, PROTO_UDP)) {
    932           port->set_server_addresses(config_->GetRelayServerAddresses(
    933               RELAY_TURN, PROTO_UDP));
    934           LOG(LS_INFO) << "AllocationSequence: TURN Server address will be "
    935                        << " used for generating STUN candidate.";
    936         }
    937       }
    938     }
    939 
    940     session_->AddAllocatedPort(port, this, true);
    941     port->SignalDestroyed.connect(this, &AllocationSequence::OnPortDestroyed);
    942   }
    943 }
    944 
    945 void AllocationSequence::CreateTCPPorts() {
    946   if (IsFlagSet(PORTALLOCATOR_DISABLE_TCP)) {
    947     LOG(LS_VERBOSE) << "AllocationSequence: TCP ports disabled, skipping.";
    948     return;
    949   }
    950 
    951   Port* port = TCPPort::Create(session_->network_thread(),
    952                                session_->socket_factory(),
    953                                network_, ip_,
    954                                session_->allocator()->min_port(),
    955                                session_->allocator()->max_port(),
    956                                session_->username(), session_->password(),
    957                                session_->allocator()->allow_tcp_listen());
    958   if (port) {
    959     session_->AddAllocatedPort(port, this, true);
    960     // Since TCPPort is not created using shared socket, |port| will not be
    961     // added to the dequeue.
    962   }
    963 }
    964 
    965 void AllocationSequence::CreateStunPorts() {
    966   if (IsFlagSet(PORTALLOCATOR_DISABLE_STUN)) {
    967     LOG(LS_VERBOSE) << "AllocationSequence: STUN ports disabled, skipping.";
    968     return;
    969   }
    970 
    971   if (IsFlagSet(PORTALLOCATOR_ENABLE_SHARED_SOCKET)) {
    972     return;
    973   }
    974 
    975   // If BasicPortAllocatorSession::OnAllocate left STUN ports enabled then we
    976   // ought to have an address for them here.
    977   ASSERT(config_ && !config_->StunServers().empty());
    978   if (!(config_ && !config_->StunServers().empty())) {
    979     LOG(LS_WARNING)
    980         << "AllocationSequence: No STUN server configured, skipping.";
    981     return;
    982   }
    983 
    984   StunPort* port = StunPort::Create(session_->network_thread(),
    985                                 session_->socket_factory(),
    986                                 network_, ip_,
    987                                 session_->allocator()->min_port(),
    988                                 session_->allocator()->max_port(),
    989                                 session_->username(), session_->password(),
    990                                 config_->StunServers());
    991   if (port) {
    992     session_->AddAllocatedPort(port, this, true);
    993     // Since StunPort is not created using shared socket, |port| will not be
    994     // added to the dequeue.
    995   }
    996 }
    997 
    998 void AllocationSequence::CreateRelayPorts() {
    999   if (IsFlagSet(PORTALLOCATOR_DISABLE_RELAY)) {
   1000      LOG(LS_VERBOSE) << "AllocationSequence: Relay ports disabled, skipping.";
   1001      return;
   1002   }
   1003 
   1004   // If BasicPortAllocatorSession::OnAllocate left relay ports enabled then we
   1005   // ought to have a relay list for them here.
   1006   ASSERT(config_ && !config_->relays.empty());
   1007   if (!(config_ && !config_->relays.empty())) {
   1008     LOG(LS_WARNING)
   1009         << "AllocationSequence: No relay server configured, skipping.";
   1010     return;
   1011   }
   1012 
   1013   PortConfiguration::RelayList::const_iterator relay;
   1014   for (relay = config_->relays.begin();
   1015        relay != config_->relays.end(); ++relay) {
   1016     if (relay->type == RELAY_GTURN) {
   1017       CreateGturnPort(*relay);
   1018     } else if (relay->type == RELAY_TURN) {
   1019       CreateTurnPort(*relay);
   1020     } else {
   1021       ASSERT(false);
   1022     }
   1023   }
   1024 }
   1025 
   1026 void AllocationSequence::CreateGturnPort(const RelayServerConfig& config) {
   1027   // TODO(mallinath) - Rename RelayPort to GTurnPort.
   1028   RelayPort* port = RelayPort::Create(session_->network_thread(),
   1029                                       session_->socket_factory(),
   1030                                       network_, ip_,
   1031                                       session_->allocator()->min_port(),
   1032                                       session_->allocator()->max_port(),
   1033                                       config_->username, config_->password);
   1034   if (port) {
   1035     // Since RelayPort is not created using shared socket, |port| will not be
   1036     // added to the dequeue.
   1037     // Note: We must add the allocated port before we add addresses because
   1038     //       the latter will create candidates that need name and preference
   1039     //       settings.  However, we also can't prepare the address (normally
   1040     //       done by AddAllocatedPort) until we have these addresses.  So we
   1041     //       wait to do that until below.
   1042     session_->AddAllocatedPort(port, this, false);
   1043 
   1044     // Add the addresses of this protocol.
   1045     PortList::const_iterator relay_port;
   1046     for (relay_port = config.ports.begin();
   1047          relay_port != config.ports.end();
   1048          ++relay_port) {
   1049       port->AddServerAddress(*relay_port);
   1050       port->AddExternalAddress(*relay_port);
   1051     }
   1052     // Start fetching an address for this port.
   1053     port->PrepareAddress();
   1054   }
   1055 }
   1056 
   1057 void AllocationSequence::CreateTurnPort(const RelayServerConfig& config) {
   1058   PortList::const_iterator relay_port;
   1059   for (relay_port = config.ports.begin();
   1060        relay_port != config.ports.end(); ++relay_port) {
   1061     TurnPort* port = NULL;
   1062     // Shared socket mode must be enabled only for UDP based ports. Hence
   1063     // don't pass shared socket for ports which will create TCP sockets.
   1064     // TODO(mallinath) - Enable shared socket mode for TURN ports. Disabled
   1065     // due to webrtc bug https://code.google.com/p/webrtc/issues/detail?id=3537
   1066     if (IsFlagSet(PORTALLOCATOR_ENABLE_SHARED_SOCKET) &&
   1067         relay_port->proto == PROTO_UDP) {
   1068       port = TurnPort::Create(session_->network_thread(),
   1069                               session_->socket_factory(),
   1070                               network_, udp_socket_.get(),
   1071                               session_->username(), session_->password(),
   1072                               *relay_port, config.credentials, config.priority);
   1073 
   1074       turn_ports_.push_back(port);
   1075       // Listen to the port destroyed signal, to allow AllocationSequence to
   1076       // remove entrt from it's map.
   1077       port->SignalDestroyed.connect(this, &AllocationSequence::OnPortDestroyed);
   1078     } else {
   1079       port = TurnPort::Create(session_->network_thread(),
   1080                               session_->socket_factory(),
   1081                               network_, ip_,
   1082                               session_->allocator()->min_port(),
   1083                               session_->allocator()->max_port(),
   1084                               session_->username(),
   1085                               session_->password(),
   1086                               *relay_port, config.credentials, config.priority);
   1087     }
   1088     ASSERT(port != NULL);
   1089     session_->AddAllocatedPort(port, this, true);
   1090   }
   1091 }
   1092 
   1093 void AllocationSequence::OnReadPacket(
   1094     rtc::AsyncPacketSocket* socket, const char* data, size_t size,
   1095     const rtc::SocketAddress& remote_addr,
   1096     const rtc::PacketTime& packet_time) {
   1097   ASSERT(socket == udp_socket_.get());
   1098 
   1099   bool turn_port_found = false;
   1100 
   1101   // Try to find the TurnPort that matches the remote address. Note that the
   1102   // message could be a STUN binding response if the TURN server is also used as
   1103   // a STUN server. We don't want to parse every message here to check if it is
   1104   // a STUN binding response, so we pass the message to TurnPort regardless of
   1105   // the message type. The TurnPort will just ignore the message since it will
   1106   // not find any request by transaction ID.
   1107   for (std::vector<TurnPort*>::const_iterator it = turn_ports_.begin();
   1108        it != turn_ports_.end(); ++it) {
   1109     TurnPort* port = *it;
   1110     if (port->server_address().address == remote_addr) {
   1111       port->HandleIncomingPacket(socket, data, size, remote_addr, packet_time);
   1112       turn_port_found = true;
   1113       break;
   1114     }
   1115   }
   1116 
   1117   if (udp_port_) {
   1118     const ServerAddresses& stun_servers = udp_port_->server_addresses();
   1119 
   1120     // Pass the packet to the UdpPort if there is no matching TurnPort, or if
   1121     // the TURN server is also a STUN server.
   1122     if (!turn_port_found ||
   1123         stun_servers.find(remote_addr) != stun_servers.end()) {
   1124       udp_port_->HandleIncomingPacket(
   1125           socket, data, size, remote_addr, packet_time);
   1126     }
   1127   }
   1128 }
   1129 
   1130 void AllocationSequence::OnPortDestroyed(PortInterface* port) {
   1131   if (udp_port_ == port) {
   1132     udp_port_ = NULL;
   1133     return;
   1134   }
   1135 
   1136   turn_ports_.erase(std::find(turn_ports_.begin(), turn_ports_.end(), port));
   1137 }
   1138 
   1139 // PortConfiguration
   1140 PortConfiguration::PortConfiguration(
   1141     const rtc::SocketAddress& stun_address,
   1142     const std::string& username,
   1143     const std::string& password)
   1144     : stun_address(stun_address), username(username), password(password) {
   1145   if (!stun_address.IsNil())
   1146     stun_servers.insert(stun_address);
   1147 }
   1148 
   1149 PortConfiguration::PortConfiguration(const ServerAddresses& stun_servers,
   1150                                      const std::string& username,
   1151                                      const std::string& password)
   1152     : stun_servers(stun_servers),
   1153       username(username),
   1154       password(password) {
   1155   if (!stun_servers.empty())
   1156     stun_address = *(stun_servers.begin());
   1157 }
   1158 
   1159 ServerAddresses PortConfiguration::StunServers() {
   1160   if (!stun_address.IsNil() &&
   1161       stun_servers.find(stun_address) == stun_servers.end()) {
   1162     stun_servers.insert(stun_address);
   1163   }
   1164   return stun_servers;
   1165 }
   1166 
   1167 void PortConfiguration::AddRelay(const RelayServerConfig& config) {
   1168   relays.push_back(config);
   1169 }
   1170 
   1171 bool PortConfiguration::SupportsProtocol(
   1172     const RelayServerConfig& relay, ProtocolType type) const {
   1173   PortList::const_iterator relay_port;
   1174   for (relay_port = relay.ports.begin();
   1175         relay_port != relay.ports.end();
   1176         ++relay_port) {
   1177     if (relay_port->proto == type)
   1178       return true;
   1179   }
   1180   return false;
   1181 }
   1182 
   1183 bool PortConfiguration::SupportsProtocol(RelayType turn_type,
   1184                                          ProtocolType type) const {
   1185   for (size_t i = 0; i < relays.size(); ++i) {
   1186     if (relays[i].type == turn_type &&
   1187         SupportsProtocol(relays[i], type))
   1188       return true;
   1189   }
   1190   return false;
   1191 }
   1192 
   1193 ServerAddresses PortConfiguration::GetRelayServerAddresses(
   1194     RelayType turn_type, ProtocolType type) const {
   1195   ServerAddresses servers;
   1196   for (size_t i = 0; i < relays.size(); ++i) {
   1197     if (relays[i].type == turn_type && SupportsProtocol(relays[i], type)) {
   1198       servers.insert(relays[i].ports.front().address);
   1199     }
   1200   }
   1201   return servers;
   1202 }
   1203 
   1204 }  // namespace cricket
   1205