10e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org/*
20e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * libjingle
30e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * Copyright 2004--2005, Google Inc.
40e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *
50e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * Redistribution and use in source and binary forms, with or without
60e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * modification, are permitted provided that the following conditions are met:
70e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *
80e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *  1. Redistributions of source code must retain the above copyright notice,
90e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *     this list of conditions and the following disclaimer.
100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *  2. Redistributions in binary form must reproduce the above copyright notice,
110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *     this list of conditions and the following disclaimer in the documentation
120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *     and/or other materials provided with the distribution.
130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *  3. The name of the author may not be used to endorse or promote products
140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *     derived from this software without specific prior written permission.
150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *
160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org */
270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include "talk/p2p/client/basicportallocator.h"
290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include <string>
310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include <vector>
320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include "talk/base/common.h"
340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include "talk/base/helpers.h"
350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include "talk/base/logging.h"
360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include "talk/p2p/base/basicpacketsocketfactory.h"
370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include "talk/p2p/base/common.h"
380e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include "talk/p2p/base/port.h"
390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include "talk/p2p/base/relayport.h"
400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include "talk/p2p/base/stunport.h"
410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include "talk/p2p/base/tcpport.h"
420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include "talk/p2p/base/turnport.h"
430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include "talk/p2p/base/udpport.h"
440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgusing talk_base::CreateRandomId;
460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgusing talk_base::CreateRandomString;
470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgnamespace {
490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgconst uint32 MSG_CONFIG_START = 1;
510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgconst uint32 MSG_CONFIG_READY = 2;
520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgconst uint32 MSG_ALLOCATE = 3;
530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgconst uint32 MSG_ALLOCATION_PHASE = 4;
540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgconst uint32 MSG_SHAKE = 5;
550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgconst uint32 MSG_SEQUENCEOBJECTS_CREATED = 6;
560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgconst uint32 MSG_CONFIG_STOP = 7;
570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgconst uint32 ALLOCATE_DELAY = 250;
590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgconst int PHASE_UDP = 0;
610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgconst int PHASE_RELAY = 1;
620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgconst int PHASE_TCP = 2;
630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgconst int PHASE_SSLTCP = 3;
640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
650e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgconst int kNumPhases = 4;
660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
670e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgconst int SHAKE_MIN_DELAY = 45 * 1000;  // 45 seconds
680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgconst int SHAKE_MAX_DELAY = 90 * 1000;  // 90 seconds
690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgint ShakeDelay() {
710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  int range = SHAKE_MAX_DELAY - SHAKE_MIN_DELAY + 1;
720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return SHAKE_MIN_DELAY + CreateRandomId() % range;
730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}  // namespace
760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgnamespace cricket {
780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
790e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgconst uint32 DISABLE_ALL_PHASES =
800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  PORTALLOCATOR_DISABLE_UDP
810e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  | PORTALLOCATOR_DISABLE_TCP
820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  | PORTALLOCATOR_DISABLE_STUN
830e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  | PORTALLOCATOR_DISABLE_RELAY;
840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
850e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// Performs the allocation of ports, in a sequenced (timed) manner, for a given
860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// network and IP address.
870e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgclass AllocationSequence : public talk_base::MessageHandler,
880e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                           public sigslot::has_slots<> {
890e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org public:
900e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  enum State {
910e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    kInit,       // Initial state.
920e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    kRunning,    // Started allocating ports.
930e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    kStopped,    // Stopped from running.
940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    kCompleted,  // All ports are allocated.
950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
960e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    // kInit --> kRunning --> {kCompleted|kStopped}
970e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  };
980e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
990e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  AllocationSequence(BasicPortAllocatorSession* session,
1000e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                     talk_base::Network* network,
1010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                     PortConfiguration* config,
1020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                     uint32 flags);
1030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ~AllocationSequence();
1040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  bool Init();
10509bb4f1719581ba8529ebc34407832b200288ad9mallinath@webrtc.org  void Clear();
1060e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1070e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  State state() const { return state_; }
1080e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1090e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // Disables the phases for a new sequence that this one already covers for an
1100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // equivalent network setup.
1110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  void DisableEquivalentPhases(talk_base::Network* network,
1120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      PortConfiguration* config, uint32* flags);
1130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // Starts and stops the sequence.  When started, it will continue allocating
1150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // new ports on its own timed schedule.
1160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  void Start();
1170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  void Stop();
1180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // MessageHandler
1200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  void OnMessage(talk_base::Message* msg);
1210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  void EnableProtocol(ProtocolType proto);
1230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  bool ProtocolEnabled(ProtocolType proto) const;
1240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // Signal from AllocationSequence, when it's done with allocating ports.
1260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // This signal is useful, when port allocation fails which doesn't result
1270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // in any candidates. Using this signal BasicPortAllocatorSession can send
1280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // its candidate discovery conclusion signal. Without this signal,
1290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // BasicPortAllocatorSession doesn't have any event to trigger signal. This
1300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // can also be achieved by starting timer in BPAS.
1310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  sigslot::signal1<AllocationSequence*> SignalPortAllocationComplete;
1320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org private:
1340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  typedef std::vector<ProtocolType> ProtocolList;
1350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  bool IsFlagSet(uint32 flag) {
1370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return ((flags_ & flag) != 0);
1380e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
1390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  void CreateUDPPorts();
1400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  void CreateTCPPorts();
1410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  void CreateStunPorts();
1420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  void CreateRelayPorts();
1430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  void CreateGturnPort(const RelayServerConfig& config);
1440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  void CreateTurnPort(const RelayServerConfig& config);
1450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  void OnReadPacket(talk_base::AsyncPacketSocket* socket,
1470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                    const char* data, size_t size,
148f89a403cd8db88001322bbb0765c4636fd123700wu@webrtc.org                    const talk_base::SocketAddress& remote_addr,
149f89a403cd8db88001322bbb0765c4636fd123700wu@webrtc.org                    const talk_base::PacketTime& packet_time);
150f89a403cd8db88001322bbb0765c4636fd123700wu@webrtc.org
1510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  void OnPortDestroyed(PortInterface* port);
152afaf4d10603cf012a13d43a62fbc43c0757ec3b9buildbot@webrtc.org  void OnResolvedTurnServerAddress(
153afaf4d10603cf012a13d43a62fbc43c0757ec3b9buildbot@webrtc.org    TurnPort* port, const talk_base::SocketAddress& server_address,
154afaf4d10603cf012a13d43a62fbc43c0757ec3b9buildbot@webrtc.org    const talk_base::SocketAddress& resolved_server_address);
1550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  BasicPortAllocatorSession* session_;
1570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  talk_base::Network* network_;
1580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  talk_base::IPAddress ip_;
1590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  PortConfiguration* config_;
1600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  State state_;
1610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  uint32 flags_;
1620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ProtocolList protocols_;
1630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  talk_base::scoped_ptr<talk_base::AsyncPacketSocket> udp_socket_;
164afaf4d10603cf012a13d43a62fbc43c0757ec3b9buildbot@webrtc.org  // There will be only one udp port per AllocationSequence.
165ba4b69f4755d1bfb1a956f390cb3ce2713189cf2buildbot@webrtc.org  UDPPort* udp_port_;
166afaf4d10603cf012a13d43a62fbc43c0757ec3b9buildbot@webrtc.org  // Keeping a map for turn ports keyed with server addresses.
167afaf4d10603cf012a13d43a62fbc43c0757ec3b9buildbot@webrtc.org  std::map<talk_base::SocketAddress, Port*> turn_ports_;
1680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  int phase_;
1690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org};
1700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// BasicPortAllocator
1720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgBasicPortAllocator::BasicPortAllocator(
1730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    talk_base::NetworkManager* network_manager,
1740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    talk_base::PacketSocketFactory* socket_factory)
1750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    : network_manager_(network_manager),
1760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      socket_factory_(socket_factory) {
1770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ASSERT(socket_factory_ != NULL);
1780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  Construct();
1790e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
1800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1810e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgBasicPortAllocator::BasicPortAllocator(
1820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    talk_base::NetworkManager* network_manager)
1830e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    : network_manager_(network_manager),
1840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      socket_factory_(NULL) {
1850e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  Construct();
1860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
1870e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1880e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgBasicPortAllocator::BasicPortAllocator(
1890e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    talk_base::NetworkManager* network_manager,
1900e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    talk_base::PacketSocketFactory* socket_factory,
1910e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    const talk_base::SocketAddress& stun_address)
1920e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    : network_manager_(network_manager),
1930e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      socket_factory_(socket_factory),
1940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      stun_address_(stun_address) {
1950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ASSERT(socket_factory_ != NULL);
1960e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  Construct();
1970e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
1980e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1990e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgBasicPortAllocator::BasicPortAllocator(
2000e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    talk_base::NetworkManager* network_manager,
2010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    const talk_base::SocketAddress& stun_address,
2020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    const talk_base::SocketAddress& relay_address_udp,
2030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    const talk_base::SocketAddress& relay_address_tcp,
2040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    const talk_base::SocketAddress& relay_address_ssl)
2050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    : network_manager_(network_manager),
2060e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      socket_factory_(NULL),
2070e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      stun_address_(stun_address) {
2080e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
2090e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  RelayServerConfig config(RELAY_GTURN);
210ba4b69f4755d1bfb1a956f390cb3ce2713189cf2buildbot@webrtc.org  if (!relay_address_udp.IsNil())
2110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    config.ports.push_back(ProtocolAddress(relay_address_udp, PROTO_UDP));
212ba4b69f4755d1bfb1a956f390cb3ce2713189cf2buildbot@webrtc.org  if (!relay_address_tcp.IsNil())
2130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    config.ports.push_back(ProtocolAddress(relay_address_tcp, PROTO_TCP));
214ba4b69f4755d1bfb1a956f390cb3ce2713189cf2buildbot@webrtc.org  if (!relay_address_ssl.IsNil())
2150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    config.ports.push_back(ProtocolAddress(relay_address_ssl, PROTO_SSLTCP));
216ba4b69f4755d1bfb1a956f390cb3ce2713189cf2buildbot@webrtc.org
217ba4b69f4755d1bfb1a956f390cb3ce2713189cf2buildbot@webrtc.org  if (!config.ports.empty())
218ba4b69f4755d1bfb1a956f390cb3ce2713189cf2buildbot@webrtc.org    AddRelay(config);
2190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
2200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  Construct();
2210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
2220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
2230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid BasicPortAllocator::Construct() {
2240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  allow_tcp_listen_ = true;
2250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
2260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
2270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgBasicPortAllocator::~BasicPortAllocator() {
2280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
2290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
2300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgPortAllocatorSession *BasicPortAllocator::CreateSessionInternal(
2310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    const std::string& content_name, int component,
2320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    const std::string& ice_ufrag, const std::string& ice_pwd) {
2330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return new BasicPortAllocatorSession(this, content_name, component,
2340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                                       ice_ufrag, ice_pwd);
2350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
2360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
2370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// BasicPortAllocatorSession
2380e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgBasicPortAllocatorSession::BasicPortAllocatorSession(
2390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    BasicPortAllocator *allocator,
2400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    const std::string& content_name,
2410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    int component,
2420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    const std::string& ice_ufrag,
2430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    const std::string& ice_pwd)
2440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    : PortAllocatorSession(content_name, component,
2450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                           ice_ufrag, ice_pwd, allocator->flags()),
2460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      allocator_(allocator), network_thread_(NULL),
2470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      socket_factory_(allocator->socket_factory()),
2480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      allocation_started_(false),
2490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      network_manager_started_(false),
2500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      running_(false),
2510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      allocation_sequences_created_(false) {
2520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  allocator_->network_manager()->SignalNetworksChanged.connect(
2530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      this, &BasicPortAllocatorSession::OnNetworksChanged);
2540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  allocator_->network_manager()->StartUpdating();
2550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
2560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
2570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgBasicPortAllocatorSession::~BasicPortAllocatorSession() {
2580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  allocator_->network_manager()->StopUpdating();
2590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (network_thread_ != NULL)
2600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    network_thread_->Clear(this);
2610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
26209bb4f1719581ba8529ebc34407832b200288ad9mallinath@webrtc.org  for (uint32 i = 0; i < sequences_.size(); ++i) {
26309bb4f1719581ba8529ebc34407832b200288ad9mallinath@webrtc.org    // AllocationSequence should clear it's map entry for turn ports before
26409bb4f1719581ba8529ebc34407832b200288ad9mallinath@webrtc.org    // ports are destroyed.
26509bb4f1719581ba8529ebc34407832b200288ad9mallinath@webrtc.org    sequences_[i]->Clear();
26609bb4f1719581ba8529ebc34407832b200288ad9mallinath@webrtc.org  }
26709bb4f1719581ba8529ebc34407832b200288ad9mallinath@webrtc.org
2680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  std::vector<PortData>::iterator it;
2690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  for (it = ports_.begin(); it != ports_.end(); it++)
2700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    delete it->port();
2710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
2720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  for (uint32 i = 0; i < configs_.size(); ++i)
2730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    delete configs_[i];
2740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
2750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  for (uint32 i = 0; i < sequences_.size(); ++i)
2760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    delete sequences_[i];
2770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
2780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
2790e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid BasicPortAllocatorSession::StartGettingPorts() {
2800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  network_thread_ = talk_base::Thread::Current();
2810e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (!socket_factory_) {
2820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    owned_socket_factory_.reset(
2830e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        new talk_base::BasicPacketSocketFactory(network_thread_));
2840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    socket_factory_ = owned_socket_factory_.get();
2850e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
2860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
2870e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  running_ = true;
2880e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  network_thread_->Post(this, MSG_CONFIG_START);
2890e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
2900e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (flags() & PORTALLOCATOR_ENABLE_SHAKER)
2910e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    network_thread_->PostDelayed(ShakeDelay(), this, MSG_SHAKE);
2920e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
2930e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
2940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid BasicPortAllocatorSession::StopGettingPorts() {
2950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ASSERT(talk_base::Thread::Current() == network_thread_);
2960e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  running_ = false;
2970e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  network_thread_->Clear(this, MSG_ALLOCATE);
2980e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  for (uint32 i = 0; i < sequences_.size(); ++i)
2990e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    sequences_[i]->Stop();
3000e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  network_thread_->Post(this, MSG_CONFIG_STOP);
3010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
3020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
3030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid BasicPortAllocatorSession::OnMessage(talk_base::Message *message) {
3040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  switch (message->message_id) {
3050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  case MSG_CONFIG_START:
3060e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    ASSERT(talk_base::Thread::Current() == network_thread_);
3070e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    GetPortConfigurations();
3080e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    break;
3090e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
3100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  case MSG_CONFIG_READY:
3110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    ASSERT(talk_base::Thread::Current() == network_thread_);
3120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    OnConfigReady(static_cast<PortConfiguration*>(message->pdata));
3130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    break;
3140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
3150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  case MSG_ALLOCATE:
3160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    ASSERT(talk_base::Thread::Current() == network_thread_);
3170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    OnAllocate();
3180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    break;
3190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
3200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  case MSG_SHAKE:
3210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    ASSERT(talk_base::Thread::Current() == network_thread_);
3220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    OnShake();
3230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    break;
3240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  case MSG_SEQUENCEOBJECTS_CREATED:
3250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    ASSERT(talk_base::Thread::Current() == network_thread_);
3260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    OnAllocationSequenceObjectsCreated();
3270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    break;
3280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  case MSG_CONFIG_STOP:
3290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    ASSERT(talk_base::Thread::Current() == network_thread_);
3300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    OnConfigStop();
3310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    break;
3320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  default:
3330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    ASSERT(false);
3340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
3350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
3360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
3370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid BasicPortAllocatorSession::GetPortConfigurations() {
3380e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  PortConfiguration* config = new PortConfiguration(allocator_->stun_address(),
3390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                                                    username(),
3400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                                                    password());
3410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
3420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  for (size_t i = 0; i < allocator_->relays().size(); ++i) {
3430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    config->AddRelay(allocator_->relays()[i]);
3440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
3450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ConfigReady(config);
3460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
3470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
3480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid BasicPortAllocatorSession::ConfigReady(PortConfiguration* config) {
3490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  network_thread_->Post(this, MSG_CONFIG_READY, config);
3500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
3510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
3520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// Adds a configuration to the list.
3530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid BasicPortAllocatorSession::OnConfigReady(PortConfiguration* config) {
3540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (config)
3550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    configs_.push_back(config);
3560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
3570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  AllocatePorts();
3580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
3590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
3600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid BasicPortAllocatorSession::OnConfigStop() {
3610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ASSERT(talk_base::Thread::Current() == network_thread_);
3620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
3630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // If any of the allocated ports have not completed the candidates allocation,
3640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // mark those as error. Since session doesn't need any new candidates
3650e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // at this stage of the allocation, it's safe to discard any new candidates.
3660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  bool send_signal = false;
3670e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  for (std::vector<PortData>::iterator it = ports_.begin();
3680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org       it != ports_.end(); ++it) {
3690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (!it->complete()) {
3700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      // Updating port state to error, which didn't finish allocating candidates
3710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      // yet.
3720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      it->set_error();
3730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      send_signal = true;
3740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
3750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
3760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
3770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // Did we stop any running sequences?
3780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  for (std::vector<AllocationSequence*>::iterator it = sequences_.begin();
3790e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org       it != sequences_.end() && !send_signal; ++it) {
3800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if ((*it)->state() == AllocationSequence::kStopped) {
3810e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      send_signal = true;
3820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
3830e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
3840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
3850e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // If we stopped anything that was running, send a done signal now.
3860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (send_signal) {
3870e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    MaybeSignalCandidatesAllocationDone();
3880e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
3890e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
3900e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
3910e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid BasicPortAllocatorSession::AllocatePorts() {
3920e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ASSERT(talk_base::Thread::Current() == network_thread_);
3930e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  network_thread_->Post(this, MSG_ALLOCATE);
3940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
3950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
3960e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid BasicPortAllocatorSession::OnAllocate() {
3970e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (network_manager_started_)
3980e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    DoAllocate();
3990e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
4000e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  allocation_started_ = true;
4010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (running_)
4020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    network_thread_->PostDelayed(ALLOCATE_DELAY, this, MSG_ALLOCATE);
4030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
4040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
4050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// For each network, see if we have a sequence that covers it already.  If not,
4060e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// create a new sequence to create the appropriate ports.
4070e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid BasicPortAllocatorSession::DoAllocate() {
4080e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  bool done_signal_needed = false;
4090e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  std::vector<talk_base::Network*> networks;
4100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  allocator_->network_manager()->GetNetworks(&networks);
4110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (networks.empty()) {
4120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    LOG(LS_WARNING) << "Machine has no networks; no ports will be allocated";
4130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    done_signal_needed = true;
4140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  } else {
4150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    for (uint32 i = 0; i < networks.size(); ++i) {
4160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      PortConfiguration* config = NULL;
4170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      if (configs_.size() > 0)
4180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        config = configs_.back();
4190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
4200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      uint32 sequence_flags = flags();
4210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      if ((sequence_flags & DISABLE_ALL_PHASES) == DISABLE_ALL_PHASES) {
4220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        // If all the ports are disabled we should just fire the allocation
4230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        // done event and return.
4240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        done_signal_needed = true;
4250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        break;
4260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      }
4270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
4280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      // Disables phases that are not specified in this config.
4290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      if (!config || config->stun_address.IsNil()) {
4300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        // No STUN ports specified in this config.
4310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        sequence_flags |= PORTALLOCATOR_DISABLE_STUN;
4320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      }
4330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      if (!config || config->relays.empty()) {
4340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        // No relay ports specified in this config.
4350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        sequence_flags |= PORTALLOCATOR_DISABLE_RELAY;
4360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      }
4370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
4380e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      if (!(sequence_flags & PORTALLOCATOR_ENABLE_IPV6) &&
4390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org          networks[i]->ip().family() == AF_INET6) {
4400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        // Skip IPv6 networks unless the flag's been set.
4410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        continue;
4420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      }
4430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
4440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      // Disable phases that would only create ports equivalent to
4450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      // ones that we have already made.
4460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      DisableEquivalentPhases(networks[i], config, &sequence_flags);
4470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
4480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      if ((sequence_flags & DISABLE_ALL_PHASES) == DISABLE_ALL_PHASES) {
4490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        // New AllocationSequence would have nothing to do, so don't make it.
4500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        continue;
4510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      }
4520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
4530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      AllocationSequence* sequence =
4540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org          new AllocationSequence(this, networks[i], config, sequence_flags);
4550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      if (!sequence->Init()) {
4560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        delete sequence;
4570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        continue;
4580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      }
4590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      done_signal_needed = true;
4600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      sequence->SignalPortAllocationComplete.connect(
4610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org          this, &BasicPortAllocatorSession::OnPortAllocationComplete);
4620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      if (running_)
4630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        sequence->Start();
4640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      sequences_.push_back(sequence);
4650e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
4660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
4670e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (done_signal_needed) {
4680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    network_thread_->Post(this, MSG_SEQUENCEOBJECTS_CREATED);
4690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
4700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
4710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
4720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid BasicPortAllocatorSession::OnNetworksChanged() {
4730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  network_manager_started_ = true;
4740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (allocation_started_)
4750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    DoAllocate();
4760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
4770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
4780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid BasicPortAllocatorSession::DisableEquivalentPhases(
4790e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    talk_base::Network* network, PortConfiguration* config, uint32* flags) {
4800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  for (uint32 i = 0; i < sequences_.size() &&
4810e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      (*flags & DISABLE_ALL_PHASES) != DISABLE_ALL_PHASES; ++i) {
4820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    sequences_[i]->DisableEquivalentPhases(network, config, flags);
4830e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
4840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
4850e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
4860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid BasicPortAllocatorSession::AddAllocatedPort(Port* port,
4870e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                                                 AllocationSequence * seq,
4880e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                                                 bool prepare_address) {
4890e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (!port)
4900e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return;
4910e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
4920e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  LOG(LS_INFO) << "Adding allocated port for " << content_name();
4930e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  port->set_content_name(content_name());
4940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  port->set_component(component_);
4950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  port->set_generation(generation());
4960e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (allocator_->proxy().type != talk_base::PROXY_NONE)
4970e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    port->set_proxy(allocator_->user_agent(), allocator_->proxy());
4980e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  port->set_send_retransmit_count_attribute((allocator_->flags() &
4990e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      PORTALLOCATOR_ENABLE_STUN_RETRANSMIT_ATTRIBUTE) != 0);
5000e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
5010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  PortData data(port, seq);
5020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ports_.push_back(data);
5030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
5040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  port->SignalCandidateReady.connect(
5050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      this, &BasicPortAllocatorSession::OnCandidateReady);
5060e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  port->SignalPortComplete.connect(this,
5070e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      &BasicPortAllocatorSession::OnPortComplete);
5080e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  port->SignalDestroyed.connect(this,
5090e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      &BasicPortAllocatorSession::OnPortDestroyed);
5100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  port->SignalPortError.connect(
5110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      this, &BasicPortAllocatorSession::OnPortError);
5120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  LOG_J(LS_INFO, port) << "Added port to allocator";
5130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
5140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (prepare_address)
5150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    port->PrepareAddress();
5160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
5170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
5180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid BasicPortAllocatorSession::OnAllocationSequenceObjectsCreated() {
5190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  allocation_sequences_created_ = true;
5200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // Send candidate allocation complete signal if we have no sequences.
5210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  MaybeSignalCandidatesAllocationDone();
5220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
5230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
5240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid BasicPortAllocatorSession::OnCandidateReady(
5250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    Port* port, const Candidate& c) {
5260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ASSERT(talk_base::Thread::Current() == network_thread_);
5270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  PortData* data = FindPort(port);
5280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ASSERT(data != NULL);
5290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // Discarding any candidate signal if port allocation status is
5300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // already in completed state.
5310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (data->complete())
5320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return;
5330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
5340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // Send candidates whose protocol is enabled.
5350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  std::vector<Candidate> candidates;
5360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ProtocolType pvalue;
5370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (StringToProto(c.protocol().c_str(), &pvalue) &&
5380e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      data->sequence()->ProtocolEnabled(pvalue)) {
5390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    candidates.push_back(c);
5400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
5410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
5420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (!candidates.empty()) {
5430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    SignalCandidatesReady(this, candidates);
5440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
5450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
5460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // Moving to READY state as we have atleast one candidate from the port.
5470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // Since this port has atleast one candidate we should forward this port
5480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // to listners, to allow connections from this port.
5490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (!data->ready()) {
5500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    data->set_ready();
5510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    SignalPortReady(this, port);
5520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
5530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
5540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
5550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid BasicPortAllocatorSession::OnPortComplete(Port* port) {
5560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ASSERT(talk_base::Thread::Current() == network_thread_);
5570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  PortData* data = FindPort(port);
5580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ASSERT(data != NULL);
5590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
5600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // Ignore any late signals.
5610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (data->complete())
5620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return;
5630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
5640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // Moving to COMPLETE state.
5650e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  data->set_complete();
5660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // Send candidate allocation complete signal if this was the last port.
5670e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  MaybeSignalCandidatesAllocationDone();
5680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
5690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
5700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid BasicPortAllocatorSession::OnPortError(Port* port) {
5710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ASSERT(talk_base::Thread::Current() == network_thread_);
5720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  PortData* data = FindPort(port);
5730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ASSERT(data != NULL);
5740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // We might have already given up on this port and stopped it.
5750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (data->complete())
5760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return;
5770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
5780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // SignalAddressError is currently sent from StunPort/TurnPort.
5790e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // But this signal itself is generic.
5800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  data->set_error();
5810e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // Send candidate allocation complete signal if this was the last port.
5820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  MaybeSignalCandidatesAllocationDone();
5830e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
5840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
5850e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid BasicPortAllocatorSession::OnProtocolEnabled(AllocationSequence* seq,
5860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                                                  ProtocolType proto) {
5870e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  std::vector<Candidate> candidates;
5880e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  for (std::vector<PortData>::iterator it = ports_.begin();
5890e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org       it != ports_.end(); ++it) {
5900e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (it->sequence() != seq)
5910e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      continue;
5920e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
5930e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    const std::vector<Candidate>& potentials = it->port()->Candidates();
5940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    for (size_t i = 0; i < potentials.size(); ++i) {
5950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      ProtocolType pvalue;
5960e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      if (!StringToProto(potentials[i].protocol().c_str(), &pvalue))
5970e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        continue;
5980e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      if (pvalue == proto) {
5990e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        candidates.push_back(potentials[i]);
6000e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      }
6010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
6020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
6030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
6040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (!candidates.empty()) {
6050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    SignalCandidatesReady(this, candidates);
6060e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
6070e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
6080e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
6090e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid BasicPortAllocatorSession::OnPortAllocationComplete(
6100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    AllocationSequence* seq) {
6110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // Send candidate allocation complete signal if all ports are done.
6120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  MaybeSignalCandidatesAllocationDone();
6130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
6140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
6150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid BasicPortAllocatorSession::MaybeSignalCandidatesAllocationDone() {
6160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // Send signal only if all required AllocationSequence objects
6170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // are created.
6180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (!allocation_sequences_created_)
6190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return;
6200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
6210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // Check that all port allocation sequences are complete.
6220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  for (std::vector<AllocationSequence*>::iterator it = sequences_.begin();
6230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org       it != sequences_.end(); ++it) {
6240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if ((*it)->state() == AllocationSequence::kRunning)
6250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      return;
6260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
6270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
6280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // If all allocated ports are in complete state, session must have got all
6290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // expected candidates. Session will trigger candidates allocation complete
6300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // signal.
6310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  for (std::vector<PortData>::iterator it = ports_.begin();
6320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org       it != ports_.end(); ++it) {
6330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (!it->complete())
6340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      return;
6350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
6360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  LOG(LS_INFO) << "All candidates gathered for " << content_name_ << ":"
6370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org               << component_ << ":" << generation();
6380e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  SignalCandidatesAllocationDone(this);
6390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
6400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
6410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid BasicPortAllocatorSession::OnPortDestroyed(
6420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    PortInterface* port) {
6430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ASSERT(talk_base::Thread::Current() == network_thread_);
6440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  for (std::vector<PortData>::iterator iter = ports_.begin();
6450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org       iter != ports_.end(); ++iter) {
6460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (port == iter->port()) {
6470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      ports_.erase(iter);
6480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      LOG_J(LS_INFO, port) << "Removed port from allocator ("
6490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                           << static_cast<int>(ports_.size()) << " remaining)";
6500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      return;
6510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
6520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
6530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ASSERT(false);
6540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
6550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
6560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid BasicPortAllocatorSession::OnShake() {
6570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  LOG(INFO) << ">>>>> SHAKE <<<<< >>>>> SHAKE <<<<< >>>>> SHAKE <<<<<";
6580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
6590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  std::vector<Port*> ports;
6600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  std::vector<Connection*> connections;
6610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
6620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  for (size_t i = 0; i < ports_.size(); ++i) {
6630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (ports_[i].ready())
6640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      ports.push_back(ports_[i].port());
6650e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
6660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
6670e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  for (size_t i = 0; i < ports.size(); ++i) {
6680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    Port::AddressMap::const_iterator iter;
6690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    for (iter = ports[i]->connections().begin();
6700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org         iter != ports[i]->connections().end();
6710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org         ++iter) {
6720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      connections.push_back(iter->second);
6730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
6740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
6750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
6760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  LOG(INFO) << ">>>>> Destroying " << ports.size() << " ports and "
6770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org            << connections.size() << " connections";
6780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
6790e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  for (size_t i = 0; i < connections.size(); ++i)
6800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    connections[i]->Destroy();
6810e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
6820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (running_ || (ports.size() > 0) || (connections.size() > 0))
6830e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    network_thread_->PostDelayed(ShakeDelay(), this, MSG_SHAKE);
6840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
6850e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
6860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgBasicPortAllocatorSession::PortData* BasicPortAllocatorSession::FindPort(
6870e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    Port* port) {
6880e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  for (std::vector<PortData>::iterator it = ports_.begin();
6890e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org       it != ports_.end(); ++it) {
6900e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (it->port() == port) {
6910e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      return &*it;
6920e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
6930e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
6940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return NULL;
6950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
6960e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
6970e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// AllocationSequence
6980e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
6990e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgAllocationSequence::AllocationSequence(BasicPortAllocatorSession* session,
7000e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                                       talk_base::Network* network,
7010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                                       PortConfiguration* config,
7020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                                       uint32 flags)
7030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    : session_(session),
7040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      network_(network),
7050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      ip_(network->ip()),
7060e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      config_(config),
7070e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      state_(kInit),
7080e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      flags_(flags),
7095c9dd59107e049112f2e9a62d08a02ef4448a957wu@webrtc.org      udp_socket_(),
710afaf4d10603cf012a13d43a62fbc43c0757ec3b9buildbot@webrtc.org      udp_port_(NULL),
7110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      phase_(0) {
7120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
7130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
7140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool AllocationSequence::Init() {
7150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (IsFlagSet(PORTALLOCATOR_ENABLE_SHARED_SOCKET) &&
7160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      !IsFlagSet(PORTALLOCATOR_ENABLE_SHARED_UFRAG)) {
7170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    LOG(LS_ERROR) << "Shared socket option can't be set without "
7180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                  << "shared ufrag.";
7190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    ASSERT(false);
7200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return false;
7210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
7220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
7230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (IsFlagSet(PORTALLOCATOR_ENABLE_SHARED_SOCKET)) {
7240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    udp_socket_.reset(session_->socket_factory()->CreateUdpSocket(
7250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        talk_base::SocketAddress(ip_, 0), session_->allocator()->min_port(),
7260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        session_->allocator()->max_port()));
7270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (udp_socket_) {
7280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      udp_socket_->SignalReadPacket.connect(
7290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org          this, &AllocationSequence::OnReadPacket);
7300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
7310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    // Continuing if |udp_socket_| is NULL, as local TCP and RelayPort using TCP
7320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    // are next available options to setup a communication channel.
7330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
7340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return true;
7350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
7360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
73709bb4f1719581ba8529ebc34407832b200288ad9mallinath@webrtc.orgvoid AllocationSequence::Clear() {
73809bb4f1719581ba8529ebc34407832b200288ad9mallinath@webrtc.org  udp_port_ = NULL;
73909bb4f1719581ba8529ebc34407832b200288ad9mallinath@webrtc.org  turn_ports_.clear();
74009bb4f1719581ba8529ebc34407832b200288ad9mallinath@webrtc.org}
74109bb4f1719581ba8529ebc34407832b200288ad9mallinath@webrtc.org
7420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgAllocationSequence::~AllocationSequence() {
7430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  session_->network_thread()->Clear(this);
7440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
7450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
7460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid AllocationSequence::DisableEquivalentPhases(talk_base::Network* network,
7470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    PortConfiguration* config, uint32* flags) {
7480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (!((network == network_) && (ip_ == network->ip()))) {
7490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    // Different network setup; nothing is equivalent.
7500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return;
7510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
7520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
7530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // Else turn off the stuff that we've already got covered.
7540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
7550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // Every config implicitly specifies local, so turn that off right away.
7560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  *flags |= PORTALLOCATOR_DISABLE_UDP;
7570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  *flags |= PORTALLOCATOR_DISABLE_TCP;
7580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
7590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (config_ && config) {
7600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (config_->stun_address == config->stun_address) {
7610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      // Already got this STUN server covered.
7620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      *flags |= PORTALLOCATOR_DISABLE_STUN;
7630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
7640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (!config_->relays.empty()) {
7650e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      // Already got relays covered.
7660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      // NOTE: This will even skip a _different_ set of relay servers if we
7670e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      // were to be given one, but that never happens in our codebase. Should
7680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      // probably get rid of the list in PortConfiguration and just keep a
7690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      // single relay server in each one.
7700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      *flags |= PORTALLOCATOR_DISABLE_RELAY;
7710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
7720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
7730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
7740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
7750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid AllocationSequence::Start() {
7760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  state_ = kRunning;
7770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  session_->network_thread()->Post(this, MSG_ALLOCATION_PHASE);
7780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
7790e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
7800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid AllocationSequence::Stop() {
7810e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // If the port is completed, don't set it to stopped.
7820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (state_ == kRunning) {
7830e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    state_ = kStopped;
7840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    session_->network_thread()->Clear(this, MSG_ALLOCATION_PHASE);
7850e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
7860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
7870e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
7880e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid AllocationSequence::OnMessage(talk_base::Message* msg) {
7890e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ASSERT(talk_base::Thread::Current() == session_->network_thread());
7900e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ASSERT(msg->message_id == MSG_ALLOCATION_PHASE);
7910e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
7920e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  const char* const PHASE_NAMES[kNumPhases] = {
7930e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    "Udp", "Relay", "Tcp", "SslTcp"
7940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  };
7950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
7960e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // Perform all of the phases in the current step.
7970e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  LOG_J(LS_INFO, network_) << "Allocation Phase="
7980e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                           << PHASE_NAMES[phase_];
7990e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
8000e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  switch (phase_) {
8010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    case PHASE_UDP:
8020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      CreateUDPPorts();
8030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      CreateStunPorts();
8040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      EnableProtocol(PROTO_UDP);
8050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      break;
8060e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
8070e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    case PHASE_RELAY:
8080e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      CreateRelayPorts();
8090e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      break;
8100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
8110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    case PHASE_TCP:
8120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      CreateTCPPorts();
8130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      EnableProtocol(PROTO_TCP);
8140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      break;
8150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
8160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    case PHASE_SSLTCP:
8170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      state_ = kCompleted;
8180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      EnableProtocol(PROTO_SSLTCP);
8190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      break;
8200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
8210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    default:
8220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      ASSERT(false);
8230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
8240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
8250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (state() == kRunning) {
8260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    ++phase_;
8270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    session_->network_thread()->PostDelayed(
8280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        session_->allocator()->step_delay(),
8290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        this, MSG_ALLOCATION_PHASE);
8300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  } else {
8310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    // If all phases in AllocationSequence are completed, no allocation
8320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    // steps needed further. Canceling  pending signal.
8330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    session_->network_thread()->Clear(this, MSG_ALLOCATION_PHASE);
8340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    SignalPortAllocationComplete(this);
8350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
8360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
8370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
8380e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid AllocationSequence::EnableProtocol(ProtocolType proto) {
8390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (!ProtocolEnabled(proto)) {
8400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    protocols_.push_back(proto);
8410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    session_->OnProtocolEnabled(this, proto);
8420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
8430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
8440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
8450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool AllocationSequence::ProtocolEnabled(ProtocolType proto) const {
8460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  for (ProtocolList::const_iterator it = protocols_.begin();
8470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org       it != protocols_.end(); ++it) {
8480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (*it == proto)
8490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      return true;
8500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
8510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return false;
8520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
8530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
8540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid AllocationSequence::CreateUDPPorts() {
8550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (IsFlagSet(PORTALLOCATOR_DISABLE_UDP)) {
8560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    LOG(LS_VERBOSE) << "AllocationSequence: UDP ports disabled, skipping.";
8570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return;
8580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
8590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
8600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // TODO(mallinath) - Remove UDPPort creating socket after shared socket
8610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // is enabled completely.
8620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  UDPPort* port = NULL;
8630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (IsFlagSet(PORTALLOCATOR_ENABLE_SHARED_SOCKET) && udp_socket_) {
86419da4659bfe1cd99b6b1476cae9bc74e99e0b09dsergeyu@chromium.org    port = UDPPort::Create(session_->network_thread(),
86519da4659bfe1cd99b6b1476cae9bc74e99e0b09dsergeyu@chromium.org                           session_->socket_factory(), network_,
8660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                           udp_socket_.get(),
8670e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                           session_->username(), session_->password());
8680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  } else {
8690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    port = UDPPort::Create(session_->network_thread(),
8700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                           session_->socket_factory(),
8710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                           network_, ip_,
8720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                           session_->allocator()->min_port(),
8730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                           session_->allocator()->max_port(),
8740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                           session_->username(), session_->password());
8750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
8760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
8770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (port) {
8780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    // If shared socket is enabled, STUN candidate will be allocated by the
8790e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    // UDPPort.
880bf9b1e0e3c606f615851d9f33f4d5222acfc921emallinath@webrtc.org    if (IsFlagSet(PORTALLOCATOR_ENABLE_SHARED_SOCKET)) {
881afaf4d10603cf012a13d43a62fbc43c0757ec3b9buildbot@webrtc.org      udp_port_ = port;
882bf9b1e0e3c606f615851d9f33f4d5222acfc921emallinath@webrtc.org
883bf9b1e0e3c606f615851d9f33f4d5222acfc921emallinath@webrtc.org      // If STUN is not disabled, setting stun server address to port.
884bf9b1e0e3c606f615851d9f33f4d5222acfc921emallinath@webrtc.org      if (!IsFlagSet(PORTALLOCATOR_DISABLE_STUN)) {
885ba4b69f4755d1bfb1a956f390cb3ce2713189cf2buildbot@webrtc.org        // If config has stun_address, use it to get server reflexive candidate
886ba4b69f4755d1bfb1a956f390cb3ce2713189cf2buildbot@webrtc.org        // otherwise use first TURN server which supports UDP.
887ba4b69f4755d1bfb1a956f390cb3ce2713189cf2buildbot@webrtc.org        if (config_ && !config_->stun_address.IsNil()) {
888ba4b69f4755d1bfb1a956f390cb3ce2713189cf2buildbot@webrtc.org          LOG(LS_INFO) << "AllocationSequence: UDPPort will be handling the "
889ba4b69f4755d1bfb1a956f390cb3ce2713189cf2buildbot@webrtc.org                       <<  "STUN candidate generation.";
890bf9b1e0e3c606f615851d9f33f4d5222acfc921emallinath@webrtc.org          port->set_server_addr(config_->stun_address);
891ba4b69f4755d1bfb1a956f390cb3ce2713189cf2buildbot@webrtc.org        } else if (config_ &&
892ba4b69f4755d1bfb1a956f390cb3ce2713189cf2buildbot@webrtc.org                   config_->SupportsProtocol(RELAY_TURN, PROTO_UDP)) {
893ba4b69f4755d1bfb1a956f390cb3ce2713189cf2buildbot@webrtc.org          port->set_server_addr(config_->GetFirstRelayServerAddress(
894ba4b69f4755d1bfb1a956f390cb3ce2713189cf2buildbot@webrtc.org              RELAY_TURN, PROTO_UDP));
895ba4b69f4755d1bfb1a956f390cb3ce2713189cf2buildbot@webrtc.org          LOG(LS_INFO) << "AllocationSequence: TURN Server address will be "
896ba4b69f4755d1bfb1a956f390cb3ce2713189cf2buildbot@webrtc.org                       << " used for generating STUN candidate.";
897bf9b1e0e3c606f615851d9f33f4d5222acfc921emallinath@webrtc.org        }
898afaf4d10603cf012a13d43a62fbc43c0757ec3b9buildbot@webrtc.org      }
8990e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
9000e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
9010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    session_->AddAllocatedPort(port, this, true);
9020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    port->SignalDestroyed.connect(this, &AllocationSequence::OnPortDestroyed);
9030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
9040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
9050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
9060e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid AllocationSequence::CreateTCPPorts() {
9070e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (IsFlagSet(PORTALLOCATOR_DISABLE_TCP)) {
9080e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    LOG(LS_VERBOSE) << "AllocationSequence: TCP ports disabled, skipping.";
9090e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return;
9100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
9110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
9120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  Port* port = TCPPort::Create(session_->network_thread(),
9130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                               session_->socket_factory(),
9140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                               network_, ip_,
9150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                               session_->allocator()->min_port(),
9160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                               session_->allocator()->max_port(),
9170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                               session_->username(), session_->password(),
9180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                               session_->allocator()->allow_tcp_listen());
9190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (port) {
9200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    session_->AddAllocatedPort(port, this, true);
9210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    // Since TCPPort is not created using shared socket, |port| will not be
9220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    // added to the dequeue.
9230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
9240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
9250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
9260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid AllocationSequence::CreateStunPorts() {
9270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (IsFlagSet(PORTALLOCATOR_DISABLE_STUN)) {
9280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    LOG(LS_VERBOSE) << "AllocationSequence: STUN ports disabled, skipping.";
9290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return;
9300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
9310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
9320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (IsFlagSet(PORTALLOCATOR_ENABLE_SHARED_SOCKET)) {
9330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return;
9340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
9350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
9360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // If BasicPortAllocatorSession::OnAllocate left STUN ports enabled then we
9370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // ought to have an address for them here.
9380e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ASSERT(config_ && !config_->stun_address.IsNil());
9390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (!(config_ && !config_->stun_address.IsNil())) {
9400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    LOG(LS_WARNING)
9410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        << "AllocationSequence: No STUN server configured, skipping.";
9420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return;
9430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
9440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
9450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  StunPort* port = StunPort::Create(session_->network_thread(),
9460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                                session_->socket_factory(),
9470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                                network_, ip_,
9480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                                session_->allocator()->min_port(),
9490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                                session_->allocator()->max_port(),
9500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                                session_->username(), session_->password(),
9510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                                config_->stun_address);
9520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (port) {
9530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    session_->AddAllocatedPort(port, this, true);
9540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    // Since StunPort is not created using shared socket, |port| will not be
9550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    // added to the dequeue.
9560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
9570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
9580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
9590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid AllocationSequence::CreateRelayPorts() {
9600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (IsFlagSet(PORTALLOCATOR_DISABLE_RELAY)) {
9610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org     LOG(LS_VERBOSE) << "AllocationSequence: Relay ports disabled, skipping.";
9620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org     return;
9630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
9640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
9650e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // If BasicPortAllocatorSession::OnAllocate left relay ports enabled then we
9660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // ought to have a relay list for them here.
9670e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ASSERT(config_ && !config_->relays.empty());
9680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (!(config_ && !config_->relays.empty())) {
9690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    LOG(LS_WARNING)
9700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        << "AllocationSequence: No relay server configured, skipping.";
9710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return;
9720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
9730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
9740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  PortConfiguration::RelayList::const_iterator relay;
9750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  for (relay = config_->relays.begin();
9760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org       relay != config_->relays.end(); ++relay) {
9770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (relay->type == RELAY_GTURN) {
9780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      CreateGturnPort(*relay);
9790e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    } else if (relay->type == RELAY_TURN) {
9800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      CreateTurnPort(*relay);
9810e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    } else {
9820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      ASSERT(false);
9830e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
9840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
9850e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
9860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
9870e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid AllocationSequence::CreateGturnPort(const RelayServerConfig& config) {
9880e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // TODO(mallinath) - Rename RelayPort to GTurnPort.
9890e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  RelayPort* port = RelayPort::Create(session_->network_thread(),
9900e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                                      session_->socket_factory(),
9910e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                                      network_, ip_,
9920e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                                      session_->allocator()->min_port(),
9930e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                                      session_->allocator()->max_port(),
9940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                                      config_->username, config_->password);
9950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (port) {
9960e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    // Since RelayPort is not created using shared socket, |port| will not be
9970e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    // added to the dequeue.
9980e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    // Note: We must add the allocated port before we add addresses because
9990e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    //       the latter will create candidates that need name and preference
10000e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    //       settings.  However, we also can't prepare the address (normally
10010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    //       done by AddAllocatedPort) until we have these addresses.  So we
10020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    //       wait to do that until below.
10030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    session_->AddAllocatedPort(port, this, false);
10040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
10050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    // Add the addresses of this protocol.
10060e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    PortList::const_iterator relay_port;
10070e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    for (relay_port = config.ports.begin();
10080e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org         relay_port != config.ports.end();
10090e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org         ++relay_port) {
10100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      port->AddServerAddress(*relay_port);
10110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      port->AddExternalAddress(*relay_port);
10120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
10130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    // Start fetching an address for this port.
10140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    port->PrepareAddress();
10150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
10160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
10170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
10180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid AllocationSequence::CreateTurnPort(const RelayServerConfig& config) {
10190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  PortList::const_iterator relay_port;
10200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  for (relay_port = config.ports.begin();
10210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org       relay_port != config.ports.end(); ++relay_port) {
1022afaf4d10603cf012a13d43a62fbc43c0757ec3b9buildbot@webrtc.org    TurnPort* port = NULL;
1023005164e2d795e55bbadcce1be828bd39f04c07fdbuildbot@webrtc.org    // Shared socket mode must be enabled only for UDP based ports. Hence
1024005164e2d795e55bbadcce1be828bd39f04c07fdbuildbot@webrtc.org    // don't pass shared socket for ports which will create TCP sockets.
1025005164e2d795e55bbadcce1be828bd39f04c07fdbuildbot@webrtc.org    if (IsFlagSet(PORTALLOCATOR_ENABLE_SHARED_SOCKET) &&
1026005164e2d795e55bbadcce1be828bd39f04c07fdbuildbot@webrtc.org        relay_port->proto == PROTO_UDP) {
1027afaf4d10603cf012a13d43a62fbc43c0757ec3b9buildbot@webrtc.org      port = TurnPort::Create(session_->network_thread(),
1028afaf4d10603cf012a13d43a62fbc43c0757ec3b9buildbot@webrtc.org                              session_->socket_factory(),
1029afaf4d10603cf012a13d43a62fbc43c0757ec3b9buildbot@webrtc.org                              network_, udp_socket_.get(),
1030afaf4d10603cf012a13d43a62fbc43c0757ec3b9buildbot@webrtc.org                              session_->username(), session_->password(),
1031afaf4d10603cf012a13d43a62fbc43c0757ec3b9buildbot@webrtc.org                              *relay_port, config.credentials);
1032afaf4d10603cf012a13d43a62fbc43c0757ec3b9buildbot@webrtc.org      // If we are using shared socket for TURN and udp ports, we need to
1033afaf4d10603cf012a13d43a62fbc43c0757ec3b9buildbot@webrtc.org      // find a way to demux the packets to the correct port when received.
1034afaf4d10603cf012a13d43a62fbc43c0757ec3b9buildbot@webrtc.org      // Mapping against server_address is one way of doing this. When packet
1035afaf4d10603cf012a13d43a62fbc43c0757ec3b9buildbot@webrtc.org      // is received the remote_address will be checked against the map.
1036afaf4d10603cf012a13d43a62fbc43c0757ec3b9buildbot@webrtc.org      // If server address is not resolved, a signal will be sent from the port
1037afaf4d10603cf012a13d43a62fbc43c0757ec3b9buildbot@webrtc.org      // after the address is resolved. The map entry will updated with the
1038afaf4d10603cf012a13d43a62fbc43c0757ec3b9buildbot@webrtc.org      // resolved address when the signal is received from the port.
1039005164e2d795e55bbadcce1be828bd39f04c07fdbuildbot@webrtc.org      if ((*relay_port).address.IsUnresolved()) {
1040afaf4d10603cf012a13d43a62fbc43c0757ec3b9buildbot@webrtc.org        // If server address is not resolved then listen for signal from port.
1041005164e2d795e55bbadcce1be828bd39f04c07fdbuildbot@webrtc.org        port->SignalResolvedServerAddress.connect(
1042005164e2d795e55bbadcce1be828bd39f04c07fdbuildbot@webrtc.org            this, &AllocationSequence::OnResolvedTurnServerAddress);
1043afaf4d10603cf012a13d43a62fbc43c0757ec3b9buildbot@webrtc.org      }
1044005164e2d795e55bbadcce1be828bd39f04c07fdbuildbot@webrtc.org      turn_ports_[(*relay_port).address] = port;
104509bb4f1719581ba8529ebc34407832b200288ad9mallinath@webrtc.org      // Listen to the port destroyed signal, to allow AllocationSequence to
104609bb4f1719581ba8529ebc34407832b200288ad9mallinath@webrtc.org      // remove entrt from it's map.
104709bb4f1719581ba8529ebc34407832b200288ad9mallinath@webrtc.org      port->SignalDestroyed.connect(this, &AllocationSequence::OnPortDestroyed);
1048005164e2d795e55bbadcce1be828bd39f04c07fdbuildbot@webrtc.org    } else {
1049005164e2d795e55bbadcce1be828bd39f04c07fdbuildbot@webrtc.org      port = TurnPort::Create(session_->network_thread(),
1050005164e2d795e55bbadcce1be828bd39f04c07fdbuildbot@webrtc.org                              session_->socket_factory(),
1051005164e2d795e55bbadcce1be828bd39f04c07fdbuildbot@webrtc.org                              network_, ip_,
1052005164e2d795e55bbadcce1be828bd39f04c07fdbuildbot@webrtc.org                              session_->allocator()->min_port(),
1053005164e2d795e55bbadcce1be828bd39f04c07fdbuildbot@webrtc.org                              session_->allocator()->max_port(),
1054005164e2d795e55bbadcce1be828bd39f04c07fdbuildbot@webrtc.org                              session_->username(),
1055005164e2d795e55bbadcce1be828bd39f04c07fdbuildbot@webrtc.org                              session_->password(),
1056005164e2d795e55bbadcce1be828bd39f04c07fdbuildbot@webrtc.org                              *relay_port, config.credentials);
10570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
1058005164e2d795e55bbadcce1be828bd39f04c07fdbuildbot@webrtc.org    ASSERT(port != NULL);
1059005164e2d795e55bbadcce1be828bd39f04c07fdbuildbot@webrtc.org    session_->AddAllocatedPort(port, this, true);
10600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
10610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
10620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
10630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid AllocationSequence::OnReadPacket(
10640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    talk_base::AsyncPacketSocket* socket, const char* data, size_t size,
1065f89a403cd8db88001322bbb0765c4636fd123700wu@webrtc.org    const talk_base::SocketAddress& remote_addr,
1066f89a403cd8db88001322bbb0765c4636fd123700wu@webrtc.org    const talk_base::PacketTime& packet_time) {
10670e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ASSERT(socket == udp_socket_.get());
1068afaf4d10603cf012a13d43a62fbc43c0757ec3b9buildbot@webrtc.org  // If the packet is received from one of the TURN server in the config, then
1069afaf4d10603cf012a13d43a62fbc43c0757ec3b9buildbot@webrtc.org  // pass down the packet to that port, otherwise it will be handed down to
1070afaf4d10603cf012a13d43a62fbc43c0757ec3b9buildbot@webrtc.org  // the local udp port.
1071afaf4d10603cf012a13d43a62fbc43c0757ec3b9buildbot@webrtc.org  Port* port = NULL;
1072afaf4d10603cf012a13d43a62fbc43c0757ec3b9buildbot@webrtc.org  std::map<talk_base::SocketAddress, Port*>::iterator iter =
1073afaf4d10603cf012a13d43a62fbc43c0757ec3b9buildbot@webrtc.org      turn_ports_.find(remote_addr);
1074afaf4d10603cf012a13d43a62fbc43c0757ec3b9buildbot@webrtc.org  if (iter != turn_ports_.end()) {
1075afaf4d10603cf012a13d43a62fbc43c0757ec3b9buildbot@webrtc.org    port = iter->second;
1076afaf4d10603cf012a13d43a62fbc43c0757ec3b9buildbot@webrtc.org  } else if (udp_port_) {
1077afaf4d10603cf012a13d43a62fbc43c0757ec3b9buildbot@webrtc.org    port = udp_port_;
10780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
1079afaf4d10603cf012a13d43a62fbc43c0757ec3b9buildbot@webrtc.org  ASSERT(port != NULL);
1080bf9b1e0e3c606f615851d9f33f4d5222acfc921emallinath@webrtc.org  if (port) {
1081bf9b1e0e3c606f615851d9f33f4d5222acfc921emallinath@webrtc.org    port->HandleIncomingPacket(socket, data, size, remote_addr, packet_time);
1082bf9b1e0e3c606f615851d9f33f4d5222acfc921emallinath@webrtc.org  }
10830e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
10840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
10850e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid AllocationSequence::OnPortDestroyed(PortInterface* port) {
1086afaf4d10603cf012a13d43a62fbc43c0757ec3b9buildbot@webrtc.org  if (udp_port_ == port) {
1087afaf4d10603cf012a13d43a62fbc43c0757ec3b9buildbot@webrtc.org    udp_port_ = NULL;
1088afaf4d10603cf012a13d43a62fbc43c0757ec3b9buildbot@webrtc.org  } else {
1089afaf4d10603cf012a13d43a62fbc43c0757ec3b9buildbot@webrtc.org    std::map<talk_base::SocketAddress, Port*>::iterator iter;
1090afaf4d10603cf012a13d43a62fbc43c0757ec3b9buildbot@webrtc.org    for (iter = turn_ports_.begin(); iter != turn_ports_.end(); ++iter) {
1091afaf4d10603cf012a13d43a62fbc43c0757ec3b9buildbot@webrtc.org      if (iter->second == port) {
1092afaf4d10603cf012a13d43a62fbc43c0757ec3b9buildbot@webrtc.org        turn_ports_.erase(iter);
1093afaf4d10603cf012a13d43a62fbc43c0757ec3b9buildbot@webrtc.org        break;
1094afaf4d10603cf012a13d43a62fbc43c0757ec3b9buildbot@webrtc.org      }
1095afaf4d10603cf012a13d43a62fbc43c0757ec3b9buildbot@webrtc.org    }
1096afaf4d10603cf012a13d43a62fbc43c0757ec3b9buildbot@webrtc.org  }
1097afaf4d10603cf012a13d43a62fbc43c0757ec3b9buildbot@webrtc.org}
1098afaf4d10603cf012a13d43a62fbc43c0757ec3b9buildbot@webrtc.org
1099afaf4d10603cf012a13d43a62fbc43c0757ec3b9buildbot@webrtc.orgvoid AllocationSequence::OnResolvedTurnServerAddress(
1100afaf4d10603cf012a13d43a62fbc43c0757ec3b9buildbot@webrtc.org    TurnPort* port, const talk_base::SocketAddress& server_address,
1101afaf4d10603cf012a13d43a62fbc43c0757ec3b9buildbot@webrtc.org    const talk_base::SocketAddress& resolved_server_address) {
1102afaf4d10603cf012a13d43a62fbc43c0757ec3b9buildbot@webrtc.org  std::map<talk_base::SocketAddress, Port*>::iterator iter;
1103afaf4d10603cf012a13d43a62fbc43c0757ec3b9buildbot@webrtc.org  iter = turn_ports_.find(server_address);
1104258851dd5adc9951102ce955177266a4d219a87dbuildbot@webrtc.org  if (iter == turn_ports_.end()) {
1105258851dd5adc9951102ce955177266a4d219a87dbuildbot@webrtc.org    LOG(LS_INFO) << "TurnPort entry is not found in the map.";
1106258851dd5adc9951102ce955177266a4d219a87dbuildbot@webrtc.org    return;
1107258851dd5adc9951102ce955177266a4d219a87dbuildbot@webrtc.org  }
1108afaf4d10603cf012a13d43a62fbc43c0757ec3b9buildbot@webrtc.org
110996e0526e1b4d0774b89a41f3ae61d302c781d4d7buildbot@webrtc.org  ASSERT(iter->second == port);
1110afaf4d10603cf012a13d43a62fbc43c0757ec3b9buildbot@webrtc.org  // Remove old entry and then insert using the resolved address as key.
1111afaf4d10603cf012a13d43a62fbc43c0757ec3b9buildbot@webrtc.org  turn_ports_.erase(iter);
1112afaf4d10603cf012a13d43a62fbc43c0757ec3b9buildbot@webrtc.org  turn_ports_[resolved_server_address] = port;
11130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
11140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
11150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// PortConfiguration
11160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgPortConfiguration::PortConfiguration(
11170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    const talk_base::SocketAddress& stun_address,
11180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    const std::string& username,
11190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    const std::string& password)
11200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    : stun_address(stun_address),
11210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      username(username),
11220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      password(password) {
11230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
11240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
11250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid PortConfiguration::AddRelay(const RelayServerConfig& config) {
11260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  relays.push_back(config);
11270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
11280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
11290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool PortConfiguration::SupportsProtocol(
1130afaf4d10603cf012a13d43a62fbc43c0757ec3b9buildbot@webrtc.org    const RelayServerConfig& relay, ProtocolType type) const {
11310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  PortList::const_iterator relay_port;
11320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  for (relay_port = relay.ports.begin();
11330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        relay_port != relay.ports.end();
11340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        ++relay_port) {
11350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (relay_port->proto == type)
11360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      return true;
11370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
11380e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return false;
11390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
11400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1141ba4b69f4755d1bfb1a956f390cb3ce2713189cf2buildbot@webrtc.orgbool PortConfiguration::SupportsProtocol(RelayType turn_type,
1142afaf4d10603cf012a13d43a62fbc43c0757ec3b9buildbot@webrtc.org                                         ProtocolType type) const {
1143afaf4d10603cf012a13d43a62fbc43c0757ec3b9buildbot@webrtc.org  for (size_t i = 0; i < relays.size(); ++i) {
1144afaf4d10603cf012a13d43a62fbc43c0757ec3b9buildbot@webrtc.org    if (relays[i].type == turn_type &&
1145afaf4d10603cf012a13d43a62fbc43c0757ec3b9buildbot@webrtc.org        SupportsProtocol(relays[i], type))
1146afaf4d10603cf012a13d43a62fbc43c0757ec3b9buildbot@webrtc.org      return true;
1147afaf4d10603cf012a13d43a62fbc43c0757ec3b9buildbot@webrtc.org  }
1148afaf4d10603cf012a13d43a62fbc43c0757ec3b9buildbot@webrtc.org  return false;
1149afaf4d10603cf012a13d43a62fbc43c0757ec3b9buildbot@webrtc.org}
1150afaf4d10603cf012a13d43a62fbc43c0757ec3b9buildbot@webrtc.org
1151ba4b69f4755d1bfb1a956f390cb3ce2713189cf2buildbot@webrtc.orgtalk_base::SocketAddress PortConfiguration::GetFirstRelayServerAddress(
1152ba4b69f4755d1bfb1a956f390cb3ce2713189cf2buildbot@webrtc.org    RelayType turn_type, ProtocolType type) const {
1153ba4b69f4755d1bfb1a956f390cb3ce2713189cf2buildbot@webrtc.org  for (size_t i = 0; i < relays.size(); ++i) {
1154ba4b69f4755d1bfb1a956f390cb3ce2713189cf2buildbot@webrtc.org    if (relays[i].type == turn_type && SupportsProtocol(relays[i], type)) {
1155ba4b69f4755d1bfb1a956f390cb3ce2713189cf2buildbot@webrtc.org      return relays[i].ports.front().address;
1156ba4b69f4755d1bfb1a956f390cb3ce2713189cf2buildbot@webrtc.org    }
1157ba4b69f4755d1bfb1a956f390cb3ce2713189cf2buildbot@webrtc.org  }
1158ba4b69f4755d1bfb1a956f390cb3ce2713189cf2buildbot@webrtc.org  return talk_base::SocketAddress();
1159ba4b69f4755d1bfb1a956f390cb3ce2713189cf2buildbot@webrtc.org}
1160ba4b69f4755d1bfb1a956f390cb3ce2713189cf2buildbot@webrtc.org
11610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}  // namespace cricket
1162