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/base/rawtransportchannel.h"
290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include <string>
310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include <vector>
320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include "talk/base/common.h"
330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include "talk/p2p/base/constants.h"
340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include "talk/p2p/base/portallocator.h"
350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include "talk/p2p/base/portinterface.h"
360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include "talk/p2p/base/rawtransport.h"
370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include "talk/p2p/base/relayport.h"
380e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include "talk/p2p/base/sessionmanager.h"
390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include "talk/p2p/base/stunport.h"
400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include "talk/xmllite/qname.h"
410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include "talk/xmllite/xmlelement.h"
420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include "talk/xmpp/constants.h"
430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#if defined(FEATURE_ENABLE_PSTN)
450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgnamespace {
470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgconst uint32 MSG_DESTROY_UNUSED_PORTS = 1;
490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}  // namespace
510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgnamespace cricket {
530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgRawTransportChannel::RawTransportChannel(const std::string& content_name,
550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                                         int component,
560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                                         RawTransport* transport,
570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                                         talk_base::Thread *worker_thread,
580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                                         PortAllocator *allocator)
590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  : TransportChannelImpl(content_name, component),
600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    raw_transport_(transport),
610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    allocator_(allocator),
620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    allocator_session_(NULL),
630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    stun_port_(NULL),
640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    relay_port_(NULL),
650e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    port_(NULL),
660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    use_relay_(false) {
670e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (worker_thread == NULL)
680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    worker_thread_ = raw_transport_->worker_thread();
690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  else
700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    worker_thread_ = worker_thread;
710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgRawTransportChannel::~RawTransportChannel() {
740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  delete allocator_session_;
750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
77391247d05a663265807c400947ab6eb01ae3d690mallinath@webrtc.orgint RawTransportChannel::SendPacket(const char *data, size_t size,
78f5e5b3a9ce372d0e3cc594bf0036dda64a57d81dmallinath@webrtc.org                                    const talk_base::PacketOptions& options,
79391247d05a663265807c400947ab6eb01ae3d690mallinath@webrtc.org                                    int flags) {
800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (port_ == NULL)
810e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return -1;
820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (remote_address_.IsNil())
830e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return -1;
840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (flags != 0)
850e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return -1;
86f5e5b3a9ce372d0e3cc594bf0036dda64a57d81dmallinath@webrtc.org  return port_->SendTo(data, size, remote_address_, options, true);
870e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
880e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
890e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgint RawTransportChannel::SetOption(talk_base::Socket::Option opt, int value) {
900e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // TODO: allow these to be set before we have a port
910e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (port_ == NULL)
920e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return -1;
930e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return port_->SetOption(opt, value);
940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
960e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgint RawTransportChannel::GetError() {
970e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return (port_ != NULL) ? port_->GetError() : 0;
980e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
990e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1000e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid RawTransportChannel::Connect() {
1010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // Create an allocator that only returns stun and relay ports.
1020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // Use empty string for ufrag and pwd here. There won't be any STUN or relay
1030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // interactions when using RawTC.
1040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // TODO: Change raw to only use local udp ports.
1050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  allocator_session_ = allocator_->CreateSession(
1060e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      SessionId(), content_name(), component(), "", "");
1070e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1080e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  uint32 flags = PORTALLOCATOR_DISABLE_UDP | PORTALLOCATOR_DISABLE_TCP;
1090e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#if !defined(FEATURE_ENABLE_STUN_CLASSIFICATION)
1110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  flags |= PORTALLOCATOR_DISABLE_RELAY;
1120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#endif
1130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  allocator_session_->set_flags(flags);
1140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  allocator_session_->SignalPortReady.connect(
1150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      this, &RawTransportChannel::OnPortReady);
1160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  allocator_session_->SignalCandidatesReady.connect(
1170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      this, &RawTransportChannel::OnCandidatesReady);
1180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // The initial ports will include stun.
1200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  allocator_session_->StartGettingPorts();
1210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
1220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid RawTransportChannel::Reset() {
1240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  set_readable(false);
1250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  set_writable(false);
1260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  delete allocator_session_;
1280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  allocator_session_ = NULL;
1300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  stun_port_ = NULL;
1310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  relay_port_ = NULL;
1320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  port_ = NULL;
1330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  remote_address_ = talk_base::SocketAddress();
1340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
1350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid RawTransportChannel::OnCandidate(const Candidate& candidate) {
1370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  remote_address_ = candidate.address();
1380e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ASSERT(!remote_address_.IsNil());
1390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  set_readable(true);
1400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // We can write once we have a port and a remote address.
1420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (port_ != NULL)
1430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    SetWritable();
1440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
1450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid RawTransportChannel::OnRemoteAddress(
1470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    const talk_base::SocketAddress& remote_address) {
1480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  remote_address_ = remote_address;
1490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  set_readable(true);
1500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (port_ != NULL)
1520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    SetWritable();
1530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
1540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// Note about stun classification
1560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// Code to classify our NAT type and use the relay port if we are behind an
1570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// asymmetric NAT is under a FEATURE_ENABLE_STUN_CLASSIFICATION #define.
1580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// To turn this one we will have to enable a second stun address and make sure
1590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// that the relay server works for raw UDP.
1600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org//
1610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// Another option is to classify the NAT type early and not offer the raw
1620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// transport type at all if we can't support it.
1630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid RawTransportChannel::OnPortReady(
1650e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    PortAllocatorSession* session, PortInterface* port) {
1660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ASSERT(session == allocator_session_);
1670e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (port->Type() == STUN_PORT_TYPE) {
1690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    stun_port_ = static_cast<StunPort*>(port);
1700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  } else if (port->Type() == RELAY_PORT_TYPE) {
1710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    relay_port_ = static_cast<RelayPort*>(port);
1720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  } else {
1730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    ASSERT(false);
1740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
1750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
1760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid RawTransportChannel::OnCandidatesReady(
1780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    PortAllocatorSession *session, const std::vector<Candidate>& candidates) {
1790e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ASSERT(session == allocator_session_);
1800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ASSERT(candidates.size() >= 1);
1810e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // The most recent candidate is the one we haven't seen yet.
1830e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  Candidate c = candidates[candidates.size() - 1];
1840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1850e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (c.type() == STUN_PORT_TYPE) {
1860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    ASSERT(stun_port_ != NULL);
1870e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1880e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#if defined(FEATURE_ENABLE_STUN_CLASSIFICATION)
1890e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    // We need to wait until we have two addresses.
1900e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (stun_port_->candidates().size() < 2)
1910e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      return;
1920e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1930e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    // This is the second address.  If these addresses are the same, then we
1940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    // are not behind a symmetric NAT.  Hence, a stun port should be sufficient.
1950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (stun_port_->candidates()[0].address() ==
1960e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        stun_port_->candidates()[1].address()) {
1970e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      SetPort(stun_port_);
1980e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      return;
1990e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
2000e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
2010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    // We will need to use relay.
2020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    use_relay_ = true;
2030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
2040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    // If we already have a relay address, we're good.  Otherwise, we will need
2050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    // to wait until one arrives.
2060e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (relay_port_->candidates().size() > 0)
2070e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      SetPort(relay_port_);
2080e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#else  // defined(FEATURE_ENABLE_STUN_CLASSIFICATION)
2090e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    // Always use the stun port.  We don't classify right now so just assume it
2100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    // will work fine.
2110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    SetPort(stun_port_);
2120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#endif
2130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  } else if (c.type() == RELAY_PORT_TYPE) {
2140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (use_relay_)
2150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      SetPort(relay_port_);
2160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  } else {
2170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    ASSERT(false);
2180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
2190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
2200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
2210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid RawTransportChannel::SetPort(PortInterface* port) {
2220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ASSERT(port_ == NULL);
2230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  port_ = port;
2240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
2250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // We don't need any ports other than the one we picked.
2260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  allocator_session_->StopGettingPorts();
2270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  worker_thread_->Post(
2280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      this, MSG_DESTROY_UNUSED_PORTS, NULL);
2290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
2300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // Send a message to the other client containing our address.
2310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
2320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ASSERT(port_->Candidates().size() >= 1);
2330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ASSERT(port_->Candidates()[0].protocol() == "udp");
2340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  SignalCandidateReady(this, port_->Candidates()[0]);
2350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
2360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // Read all packets from this port.
2370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  port_->EnablePortPackets();
2380e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  port_->SignalReadPacket.connect(this, &RawTransportChannel::OnReadPacket);
2390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
2400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // We can write once we have a port and a remote address.
2410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (!remote_address_.IsAny())
2420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    SetWritable();
2430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
2440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
2450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid RawTransportChannel::SetWritable() {
2460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ASSERT(port_ != NULL);
2470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ASSERT(!remote_address_.IsAny());
2480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
2490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  set_writable(true);
2500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
2510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  Candidate remote_candidate;
2520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  remote_candidate.set_address(remote_address_);
2530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  SignalRouteChange(this, remote_candidate);
2540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
2550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
2560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid RawTransportChannel::OnReadPacket(
2570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    PortInterface* port, const char* data, size_t size,
2580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    const talk_base::SocketAddress& addr) {
2590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ASSERT(port_ == port);
260f89a403cd8db88001322bbb0765c4636fd123700wu@webrtc.org  SignalReadPacket(this, data, size, talk_base::CreatePacketTime(0), 0);
2610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
2620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
2630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid RawTransportChannel::OnMessage(talk_base::Message* msg) {
2640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ASSERT(msg->message_id == MSG_DESTROY_UNUSED_PORTS);
2650e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ASSERT(port_ != NULL);
2660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (port_ != stun_port_) {
2670e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    stun_port_->Destroy();
2680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    stun_port_ = NULL;
2690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
2700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (port_ != relay_port_ && relay_port_ != NULL) {
2710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    relay_port_->Destroy();
2720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    relay_port_ = NULL;
2730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
2740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
2750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
2760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}  // namespace cricket
2770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#endif  // defined(FEATURE_ENABLE_PSTN)
278