15976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org/*
25976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * libjingle
35976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * Copyright 2012, Google Inc.
45976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org *
55976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * Redistribution and use in source and binary forms, with or without
65976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * modification, are permitted provided that the following conditions are met:
75976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org *
85976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org *  1. Redistributions of source code must retain the above copyright notice,
95976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org *     this list of conditions and the following disclaimer.
105976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org *  2. Redistributions in binary form must reproduce the above copyright notice,
115976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org *     this list of conditions and the following disclaimer in the documentation
125976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org *     and/or other materials provided with the distribution.
135976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org *  3. The name of the author may not be used to endorse or promote products
145976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org *     derived from this software without specific prior written permission.
155976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org *
165976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
175976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
185976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
195976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
205976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
215976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
225976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
235976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
245976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
255976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
265976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org */
275976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
285976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#include "talk/app/webrtc/peerconnection.h"
295976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
305976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#include <vector>
315976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
325976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#include "talk/app/webrtc/dtmfsender.h"
335976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#include "talk/app/webrtc/jsepicecandidate.h"
345976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#include "talk/app/webrtc/jsepsessiondescription.h"
355976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#include "talk/app/webrtc/mediastreamhandler.h"
365976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#include "talk/app/webrtc/streamcollection.h"
375976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#include "talk/base/logging.h"
385976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#include "talk/base/stringencode.h"
395976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#include "talk/session/media/channelmanager.h"
405976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
415976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgnamespace {
425976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
435976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgusing webrtc::PeerConnectionInterface;
445976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
455976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org// The min number of tokens in the ice uri.
465976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgstatic const size_t kMinIceUriTokens = 2;
475976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org// The min number of tokens must present in Turn host uri.
485976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org// e.g. user@turn.example.org
495976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgstatic const size_t kTurnHostTokensNum = 2;
505976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org// Number of tokens must be preset when TURN uri has transport param.
515976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgstatic const size_t kTurnTransportTokensNum = 2;
525976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org// The default stun port.
53e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.orgstatic const int kDefaultStunPort = 3478;
54e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.orgstatic const int kDefaultStunTlsPort = 5349;
555976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgstatic const char kTransport[] = "transport";
56e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.orgstatic const char kUdpTransportType[] = "udp";
57e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.orgstatic const char kTcpTransportType[] = "tcp";
585976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
595976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org// NOTE: Must be in the same order as the ServiceType enum.
605976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgstatic const char* kValidIceServiceTypes[] = {
615976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    "stun", "stuns", "turn", "turns", "invalid" };
625976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
635976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgenum ServiceType {
645976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  STUN,     // Indicates a STUN server.
655976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  STUNS,    // Indicates a STUN server used with a TLS session.
665976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  TURN,     // Indicates a TURN server
675976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  TURNS,    // Indicates a TURN server used with a TLS session.
685976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  INVALID,  // Unknown.
695976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org};
705976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
715976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgenum {
72e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org  MSG_SET_SESSIONDESCRIPTION_SUCCESS = 0,
735976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  MSG_SET_SESSIONDESCRIPTION_FAILED,
745976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  MSG_GETSTATS,
755976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  MSG_ICECONNECTIONCHANGE,
765976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  MSG_ICEGATHERINGCHANGE,
775976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  MSG_ICECANDIDATE,
785976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  MSG_ICECOMPLETE,
795976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org};
805976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
815976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgstruct CandidateMsg : public talk_base::MessageData {
825976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  explicit CandidateMsg(const webrtc::JsepIceCandidate* candidate)
835976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      : candidate(candidate) {
845976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
855976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  talk_base::scoped_ptr<const webrtc::JsepIceCandidate> candidate;
865976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org};
875976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
885976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgstruct SetSessionDescriptionMsg : public talk_base::MessageData {
895976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  explicit SetSessionDescriptionMsg(
905976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      webrtc::SetSessionDescriptionObserver* observer)
915976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      : observer(observer) {
925976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
935976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
945976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  talk_base::scoped_refptr<webrtc::SetSessionDescriptionObserver> observer;
955976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  std::string error;
965976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org};
975976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
985976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgstruct GetStatsMsg : public talk_base::MessageData {
995976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  explicit GetStatsMsg(webrtc::StatsObserver* observer)
1005976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      : observer(observer) {
1015976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
1025976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  webrtc::StatsReports reports;
1035976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  talk_base::scoped_refptr<webrtc::StatsObserver> observer;
1045976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org};
1055976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
1065976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgtypedef webrtc::PortAllocatorFactoryInterface::StunConfiguration
1075976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    StunConfiguration;
1085976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgtypedef webrtc::PortAllocatorFactoryInterface::TurnConfiguration
1095976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    TurnConfiguration;
1105976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
1115976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgbool ParseIceServers(const PeerConnectionInterface::IceServers& configuration,
1125976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                     std::vector<StunConfiguration>* stun_config,
1135976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                     std::vector<TurnConfiguration>* turn_config) {
1145976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  // draft-nandakumar-rtcweb-stun-uri-01
1155976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  // stunURI       = scheme ":" stun-host [ ":" stun-port ]
1165976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  // scheme        = "stun" / "stuns"
1175976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  // stun-host     = IP-literal / IPv4address / reg-name
1185976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  // stun-port     = *DIGIT
1195976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
1205976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  // draft-petithuguenin-behave-turn-uris-01
1215976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  // turnURI       = scheme ":" turn-host [ ":" turn-port ]
1225976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  //                 [ "?transport=" transport ]
1235976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  // scheme        = "turn" / "turns"
1245976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  // transport     = "udp" / "tcp" / transport-ext
1255976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  // transport-ext = 1*unreserved
1265976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  // turn-host     = IP-literal / IPv4address / reg-name
1275976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  // turn-port     = *DIGIT
1285976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
1295976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  // TODO(ronghuawu): Handle IPV6 address
1305976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  for (size_t i = 0; i < configuration.size(); ++i) {
1315976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    webrtc::PeerConnectionInterface::IceServer server = configuration[i];
1325976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    if (server.uri.empty()) {
1335976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      LOG(WARNING) << "Empty uri.";
1345976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      continue;
1355976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    }
1365976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    std::vector<std::string> tokens;
137e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org    std::string turn_transport_type = kUdpTransportType;
1385976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    talk_base::tokenize(server.uri, '?', &tokens);
1395976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    std::string uri_without_transport = tokens[0];
1405976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    // Let's look into transport= param, if it exists.
1415976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    if (tokens.size() == kTurnTransportTokensNum) {  // ?transport= is present.
1425976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      std::string uri_transport_param = tokens[1];
1435976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      talk_base::tokenize(uri_transport_param, '=', &tokens);
1445976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      if (tokens[0] == kTransport) {
145e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org        // As per above grammar transport param will be consist of lower case
146e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org        // letters.
147e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org        if (tokens[1] != kUdpTransportType && tokens[1] != kTcpTransportType) {
148e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org          LOG(LS_WARNING) << "Transport param should always be udp or tcp.";
149e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org          continue;
150e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org        }
1515976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org        turn_transport_type = tokens[1];
1525976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      }
1535976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    }
1545976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
1555976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    tokens.clear();
1565976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    talk_base::tokenize(uri_without_transport, ':', &tokens);
1575976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    if (tokens.size() < kMinIceUriTokens) {
1585976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      LOG(WARNING) << "Invalid uri: " << server.uri;
1595976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      continue;
1605976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    }
1615976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    ServiceType service_type = INVALID;
1625976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    const std::string& type = tokens[0];
1635976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    for (size_t i = 0; i < ARRAY_SIZE(kValidIceServiceTypes); ++i) {
1645976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      if (type.compare(kValidIceServiceTypes[i]) == 0) {
1655976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org        service_type = static_cast<ServiceType>(i);
1665976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org        break;
1675976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      }
1685976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    }
1695976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    if (service_type == INVALID) {
1705976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      LOG(WARNING) << "Invalid service type: " << type;
1715976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      continue;
1725976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    }
1735976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    std::string address = tokens[1];
174e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org    int port = kDefaultStunPort;
175e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org    if (service_type == TURNS)
176e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org      port = kDefaultStunTlsPort;
177e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org
1785976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    if (tokens.size() > kMinIceUriTokens) {
1795976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      if (!talk_base::FromString(tokens[2], &port)) {
1805976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org        LOG(LS_WARNING)  << "Failed to parse port string: " << tokens[2];
1815976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org        continue;
1825976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      }
1835976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
1845976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      if (port <= 0 || port > 0xffff) {
1855976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org        LOG(WARNING) << "Invalid port: " << port;
1865976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org        continue;
1875976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      }
1885976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    }
1895976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
1905976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    switch (service_type) {
1915976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      case STUN:
1925976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      case STUNS:
1935976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org        stun_config->push_back(StunConfiguration(address, port));
1945976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org        break;
195e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org      case TURN:
196e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org      case TURNS: {
1975976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org        if (server.username.empty()) {
1985976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org          // Turn url example from the spec |url:"turn:user@turn.example.org"|.
1995976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org          std::vector<std::string> turn_tokens;
2005976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org          talk_base::tokenize(address, '@', &turn_tokens);
2015976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org          if (turn_tokens.size() == kTurnHostTokensNum) {
2025976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org            server.username = talk_base::s_url_decode(turn_tokens[0]);
2035976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org            address = turn_tokens[1];
2045976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org          }
2055976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org        }
206e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org
207e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org        bool secure = (service_type == TURNS);
208e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org
2095976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org        turn_config->push_back(TurnConfiguration(address, port,
2105976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                                                 server.username,
2115976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                                                 server.password,
212e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org                                                 turn_transport_type,
213e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org                                                 secure));
2145976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org        // STUN functionality is part of TURN.
215e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org        // Note: If there is only TURNS is supplied as part of configuration,
216e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org        // we will have problem in fetching server reflexive candidate, as
217e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org        // currently we don't have support of TCP/TLS in stunport.cc.
218e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org        // In that case we should fetch server reflexive addess from
219e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org        // TURN allocate response.
2205976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org        stun_config->push_back(StunConfiguration(address, port));
2215976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org        break;
2225976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      }
2235976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      case INVALID:
2245976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      default:
2255976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org        LOG(WARNING) << "Configuration not supported: " << server.uri;
2265976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org        return false;
2275976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    }
2285976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
2295976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return true;
2305976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
2315976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
2325976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org// Check if we can send |new_stream| on a PeerConnection.
2335976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org// Currently only one audio but multiple video track is supported per
2345976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org// PeerConnection.
2355976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgbool CanAddLocalMediaStream(webrtc::StreamCollectionInterface* current_streams,
2365976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                            webrtc::MediaStreamInterface* new_stream) {
2375976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (!new_stream || !current_streams)
2385976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return false;
2395976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (current_streams->find(new_stream->label()) != NULL) {
2405976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    LOG(LS_ERROR) << "MediaStream with label " << new_stream->label()
2415976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                  << " is already added.";
2425976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return false;
2435976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
2445976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
2455976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return true;
2465976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
2475976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
2485976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}  // namespace
2495976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
2505976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgnamespace webrtc {
2515976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
2525976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgPeerConnection::PeerConnection(PeerConnectionFactory* factory)
2535976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    : factory_(factory),
2545976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      observer_(NULL),
2555976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      signaling_state_(kStable),
2565976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      ice_state_(kIceNew),
2575976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      ice_connection_state_(kIceConnectionNew),
2585976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      ice_gathering_state_(kIceGatheringNew) {
2595976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
2605976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
2615976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgPeerConnection::~PeerConnection() {
2625976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (mediastream_signaling_)
2635976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    mediastream_signaling_->TearDown();
2645976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (stream_handler_container_)
2655976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    stream_handler_container_->TearDown();
2665976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
2675976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
2685976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgbool PeerConnection::Initialize(
2695976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    const PeerConnectionInterface::IceServers& configuration,
2705976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    const MediaConstraintsInterface* constraints,
271e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org    PortAllocatorFactoryInterface* allocator_factory,
272e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org    DTLSIdentityServiceInterface* dtls_identity_service,
2735976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    PeerConnectionObserver* observer) {
2745976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  std::vector<PortAllocatorFactoryInterface::StunConfiguration> stun_config;
2755976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  std::vector<PortAllocatorFactoryInterface::TurnConfiguration> turn_config;
2765976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (!ParseIceServers(configuration, &stun_config, &turn_config)) {
2775976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return false;
2785976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
2795976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
2805976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return DoInitialize(stun_config, turn_config, constraints,
281e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org                      allocator_factory, dtls_identity_service, observer);
2825976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
2835976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
2845976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgbool PeerConnection::DoInitialize(
2855976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    const StunConfigurations& stun_config,
2865976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    const TurnConfigurations& turn_config,
2875976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    const MediaConstraintsInterface* constraints,
2885976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    webrtc::PortAllocatorFactoryInterface* allocator_factory,
289e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org    DTLSIdentityServiceInterface* dtls_identity_service,
2905976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    PeerConnectionObserver* observer) {
2915976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  ASSERT(observer != NULL);
2925976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (!observer)
2935976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return false;
2945976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  observer_ = observer;
2955976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  port_allocator_.reset(
2965976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      allocator_factory->CreatePortAllocator(stun_config, turn_config));
2975976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  // To handle both internal and externally created port allocator, we will
2985976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  // enable BUNDLE here. Also enabling TURN and disable legacy relay service.
2995976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  port_allocator_->set_flags(cricket::PORTALLOCATOR_ENABLE_BUNDLE |
3005976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                             cricket::PORTALLOCATOR_ENABLE_SHARED_UFRAG |
3015976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                             cricket::PORTALLOCATOR_ENABLE_SHARED_SOCKET);
3025976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  // No step delay is used while allocating ports.
3035976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  port_allocator_->set_step_delay(cricket::kMinimumStepDelay);
3045976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
3055976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  mediastream_signaling_.reset(new MediaStreamSignaling(
3065976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      factory_->signaling_thread(), this));
3075976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
3085976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  session_.reset(new WebRtcSession(factory_->channel_manager(),
3095976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                                   factory_->signaling_thread(),
3105976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                                   factory_->worker_thread(),
3115976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                                   port_allocator_.get(),
3125976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                                   mediastream_signaling_.get()));
3135976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  stream_handler_container_.reset(new MediaStreamHandlerContainer(
3145976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      session_.get(), session_.get()));
3155976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  stats_.set_session(session_.get());
3165976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
3175976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  // Initialize the WebRtcSession. It creates transport channels etc.
318e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org  if (!session_->Initialize(constraints, dtls_identity_service))
3195976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return false;
3205976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
3215976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  // Register PeerConnection as receiver of local ice candidates.
3225976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  // All the callbacks will be posted to the application from PeerConnection.
3235976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  session_->RegisterIceObserver(this);
3245976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  session_->SignalState.connect(this, &PeerConnection::OnSessionStateChange);
3255976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return true;
3265976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
3275976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
3285976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgtalk_base::scoped_refptr<StreamCollectionInterface>
3295976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgPeerConnection::local_streams() {
3305976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return mediastream_signaling_->local_streams();
3315976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
3325976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
3335976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgtalk_base::scoped_refptr<StreamCollectionInterface>
3345976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgPeerConnection::remote_streams() {
3355976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return mediastream_signaling_->remote_streams();
3365976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
3375976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
3385976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgbool PeerConnection::AddStream(MediaStreamInterface* local_stream,
3395976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                               const MediaConstraintsInterface* constraints) {
3405976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (IsClosed()) {
3415976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return false;
3425976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
3435976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (!CanAddLocalMediaStream(mediastream_signaling_->local_streams(),
3445976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                              local_stream))
3455976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return false;
3465976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
3475976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  // TODO(perkj): Implement support for MediaConstraints in AddStream.
3485976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (!mediastream_signaling_->AddLocalStream(local_stream)) {
3495976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return false;
3505976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
3515976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  stats_.AddStream(local_stream);
3525976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  observer_->OnRenegotiationNeeded();
3535976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return true;
3545976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
3555976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
3565976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid PeerConnection::RemoveStream(MediaStreamInterface* local_stream) {
3575976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (IsClosed()) {
3585976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return;
3595976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
3605976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  mediastream_signaling_->RemoveLocalStream(local_stream);
3615976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  observer_->OnRenegotiationNeeded();
3625976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
3635976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
3645976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgtalk_base::scoped_refptr<DtmfSenderInterface> PeerConnection::CreateDtmfSender(
3655976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    AudioTrackInterface* track) {
3665976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (!track) {
3675976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    LOG(LS_ERROR) << "CreateDtmfSender - track is NULL.";
3685976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return NULL;
3695976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
3705976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (!mediastream_signaling_->local_streams()->FindAudioTrack(track->id())) {
3715976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    LOG(LS_ERROR) << "CreateDtmfSender is called with a non local audio track.";
3725976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return NULL;
3735976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
3745976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
3755976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  talk_base::scoped_refptr<DtmfSenderInterface> sender(
3765976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      DtmfSender::Create(track, signaling_thread(), session_.get()));
3775976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (!sender.get()) {
3785976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    LOG(LS_ERROR) << "CreateDtmfSender failed on DtmfSender::Create.";
3795976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return NULL;
3805976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
3815976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return DtmfSenderProxy::Create(signaling_thread(), sender.get());
3825976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
3835976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
3845976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgbool PeerConnection::GetStats(StatsObserver* observer,
3855976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                              MediaStreamTrackInterface* track) {
3865976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (!VERIFY(observer != NULL)) {
3875976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    LOG(LS_ERROR) << "GetStats - observer is NULL.";
3885976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return false;
3895976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
3905976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
3915976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  stats_.UpdateStats();
3925976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  talk_base::scoped_ptr<GetStatsMsg> msg(new GetStatsMsg(observer));
3935976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (!stats_.GetStats(track, &(msg->reports))) {
3945976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return false;
3955976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
3965976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  signaling_thread()->Post(this, MSG_GETSTATS, msg.release());
3975976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return true;
3985976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
3995976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
4005976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgPeerConnectionInterface::SignalingState PeerConnection::signaling_state() {
4015976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return signaling_state_;
4025976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
4035976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
4045976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgPeerConnectionInterface::IceState PeerConnection::ice_state() {
4055976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return ice_state_;
4065976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
4075976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
4085976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgPeerConnectionInterface::IceConnectionState
4095976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgPeerConnection::ice_connection_state() {
4105976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return ice_connection_state_;
4115976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
4125976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
4135976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgPeerConnectionInterface::IceGatheringState
4145976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgPeerConnection::ice_gathering_state() {
4155976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return ice_gathering_state_;
4165976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
4175976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
4185976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgtalk_base::scoped_refptr<DataChannelInterface>
4195976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgPeerConnection::CreateDataChannel(
4205976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    const std::string& label,
4215976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    const DataChannelInit* config) {
4225976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  talk_base::scoped_refptr<DataChannelInterface> channel(
4235976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      session_->CreateDataChannel(label, config));
4245976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (!channel.get())
4255976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return NULL;
4265976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
427e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org  // If we've already passed the underlying channel's setup phase, have the
428e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org  // MediaStreamSignaling update data channels manually.
429e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org  if (session_->data_channel() != NULL &&
430e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org      session_->data_channel_type() == cricket::DCT_SCTP) {
431e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org    mediastream_signaling_->UpdateLocalSctpDataChannels();
432e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org    mediastream_signaling_->UpdateRemoteSctpDataChannels();
433e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org  }
434e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org
4355976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  observer_->OnRenegotiationNeeded();
436e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org
4375976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return DataChannelProxy::Create(signaling_thread(), channel.get());
4385976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
4395976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
4405976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid PeerConnection::CreateOffer(CreateSessionDescriptionObserver* observer,
4415976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                                 const MediaConstraintsInterface* constraints) {
4425976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (!VERIFY(observer != NULL)) {
4435976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    LOG(LS_ERROR) << "CreateOffer - observer is NULL.";
4445976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return;
4455976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
446e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org  session_->CreateOffer(observer, constraints);
4475976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
4485976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
4495976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid PeerConnection::CreateAnswer(
4505976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    CreateSessionDescriptionObserver* observer,
4515976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    const MediaConstraintsInterface* constraints) {
4525976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (!VERIFY(observer != NULL)) {
4535976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    LOG(LS_ERROR) << "CreateAnswer - observer is NULL.";
4545976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return;
4555976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
456e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org  session_->CreateAnswer(observer, constraints);
4575976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
4585976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
4595976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid PeerConnection::SetLocalDescription(
4605976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    SetSessionDescriptionObserver* observer,
4615976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    SessionDescriptionInterface* desc) {
4625976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (!VERIFY(observer != NULL)) {
4635976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    LOG(LS_ERROR) << "SetLocalDescription - observer is NULL.";
4645976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return;
4655976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
4665976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (!desc) {
4675976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    PostSetSessionDescriptionFailure(observer, "SessionDescription is NULL.");
4685976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return;
4695976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
4705976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  // Update stats here so that we have the most recent stats for tracks and
4715976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  // streams that might be removed by updating the session description.
4725976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  stats_.UpdateStats();
4735976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  std::string error;
4745976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (!session_->SetLocalDescription(desc, &error)) {
4755976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    PostSetSessionDescriptionFailure(observer, error);
4765976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return;
4775976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
4785976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  SetSessionDescriptionMsg* msg =  new SetSessionDescriptionMsg(observer);
4795976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  signaling_thread()->Post(this, MSG_SET_SESSIONDESCRIPTION_SUCCESS, msg);
4805976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
4815976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
4825976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid PeerConnection::SetRemoteDescription(
4835976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    SetSessionDescriptionObserver* observer,
4845976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    SessionDescriptionInterface* desc) {
4855976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (!VERIFY(observer != NULL)) {
4865976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    LOG(LS_ERROR) << "SetRemoteDescription - observer is NULL.";
4875976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return;
4885976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
4895976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (!desc) {
4905976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    PostSetSessionDescriptionFailure(observer, "SessionDescription is NULL.");
4915976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return;
4925976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
4935976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  // Update stats here so that we have the most recent stats for tracks and
4945976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  // streams that might be removed by updating the session description.
4955976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  stats_.UpdateStats();
4965976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  std::string error;
4975976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (!session_->SetRemoteDescription(desc, &error)) {
4985976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    PostSetSessionDescriptionFailure(observer, error);
4995976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return;
5005976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
5015976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  SetSessionDescriptionMsg* msg  = new SetSessionDescriptionMsg(observer);
5025976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  signaling_thread()->Post(this, MSG_SET_SESSIONDESCRIPTION_SUCCESS, msg);
5035976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
5045976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
5055976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid PeerConnection::PostSetSessionDescriptionFailure(
5065976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    SetSessionDescriptionObserver* observer,
5075976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    const std::string& error) {
5085976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  SetSessionDescriptionMsg* msg  = new SetSessionDescriptionMsg(observer);
5095976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  msg->error = error;
5105976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  signaling_thread()->Post(this, MSG_SET_SESSIONDESCRIPTION_FAILED, msg);
5115976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
5125976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
5135976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgbool PeerConnection::UpdateIce(const IceServers& configuration,
5145976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                               const MediaConstraintsInterface* constraints) {
5155976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  // TODO(ronghuawu): Implement UpdateIce.
5165976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  LOG(LS_ERROR) << "UpdateIce is not implemented.";
5175976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return false;
5185976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
5195976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
5205976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgbool PeerConnection::AddIceCandidate(
5215976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    const IceCandidateInterface* ice_candidate) {
5225976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return session_->ProcessIceMessage(ice_candidate);
5235976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
5245976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
5255976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgconst SessionDescriptionInterface* PeerConnection::local_description() const {
5265976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return session_->local_description();
5275976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
5285976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
5295976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgconst SessionDescriptionInterface* PeerConnection::remote_description() const {
5305976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return session_->remote_description();
5315976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
5325976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
5335976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid PeerConnection::Close() {
5345976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  // Update stats here so that we have the most recent stats for tracks and
5355976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  // streams before the channels are closed.
5365976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  stats_.UpdateStats();
5375976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
5385976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  session_->Terminate();
5395976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
5405976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
5415976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid PeerConnection::OnSessionStateChange(cricket::BaseSession* /*session*/,
5425976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                                          cricket::BaseSession::State state) {
5435976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  switch (state) {
5445976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    case cricket::BaseSession::STATE_INIT:
5455976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      ChangeSignalingState(PeerConnectionInterface::kStable);
5465976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    case cricket::BaseSession::STATE_SENTINITIATE:
5475976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      ChangeSignalingState(PeerConnectionInterface::kHaveLocalOffer);
5485976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      break;
5495976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    case cricket::BaseSession::STATE_SENTPRACCEPT:
5505976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      ChangeSignalingState(PeerConnectionInterface::kHaveLocalPrAnswer);
5515976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      break;
5525976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    case cricket::BaseSession::STATE_RECEIVEDINITIATE:
5535976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      ChangeSignalingState(PeerConnectionInterface::kHaveRemoteOffer);
5545976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      break;
5555976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    case cricket::BaseSession::STATE_RECEIVEDPRACCEPT:
5565976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      ChangeSignalingState(PeerConnectionInterface::kHaveRemotePrAnswer);
5575976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      break;
5585976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    case cricket::BaseSession::STATE_SENTACCEPT:
5595976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    case cricket::BaseSession::STATE_RECEIVEDACCEPT:
5605976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      ChangeSignalingState(PeerConnectionInterface::kStable);
5615976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      break;
5625976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    case cricket::BaseSession::STATE_RECEIVEDTERMINATE:
5635976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      ChangeSignalingState(PeerConnectionInterface::kClosed);
5645976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      break;
5655976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    default:
5665976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      break;
5675976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
5685976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
5695976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
5705976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid PeerConnection::OnMessage(talk_base::Message* msg) {
5715976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  switch (msg->message_id) {
5725976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    case MSG_SET_SESSIONDESCRIPTION_SUCCESS: {
5735976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      SetSessionDescriptionMsg* param =
5745976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org          static_cast<SetSessionDescriptionMsg*>(msg->pdata);
5755976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      param->observer->OnSuccess();
5765976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      delete param;
5775976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      break;
5785976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    }
5795976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    case MSG_SET_SESSIONDESCRIPTION_FAILED: {
5805976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      SetSessionDescriptionMsg* param =
5815976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org          static_cast<SetSessionDescriptionMsg*>(msg->pdata);
5825976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      param->observer->OnFailure(param->error);
5835976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      delete param;
5845976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      break;
5855976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    }
5865976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    case MSG_GETSTATS: {
5875976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      GetStatsMsg* param = static_cast<GetStatsMsg*>(msg->pdata);
5885976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      param->observer->OnComplete(param->reports);
5895976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      delete param;
5905976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      break;
5915976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    }
5925976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    case MSG_ICECONNECTIONCHANGE: {
5935976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      observer_->OnIceConnectionChange(ice_connection_state_);
5945976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      break;
5955976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    }
5965976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    case MSG_ICEGATHERINGCHANGE: {
5975976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      observer_->OnIceGatheringChange(ice_gathering_state_);
5985976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      break;
5995976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    }
6005976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    case MSG_ICECANDIDATE: {
6015976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      CandidateMsg* data = static_cast<CandidateMsg*>(msg->pdata);
6025976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      observer_->OnIceCandidate(data->candidate.get());
6035976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      delete data;
6045976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      break;
6055976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    }
6065976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    case MSG_ICECOMPLETE: {
6075976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      observer_->OnIceComplete();
6085976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      break;
6095976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    }
6105976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    default:
6115976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      ASSERT(false && "Not implemented");
6125976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      break;
6135976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
6145976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
6155976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
6165976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid PeerConnection::OnAddRemoteStream(MediaStreamInterface* stream) {
6175976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  stats_.AddStream(stream);
6185976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  observer_->OnAddStream(stream);
6195976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
6205976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
6215976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid PeerConnection::OnRemoveRemoteStream(MediaStreamInterface* stream) {
6225976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  stream_handler_container_->RemoveRemoteStream(stream);
6235976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  observer_->OnRemoveStream(stream);
6245976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
6255976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
6265976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid PeerConnection::OnAddDataChannel(DataChannelInterface* data_channel) {
6275976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  observer_->OnDataChannel(DataChannelProxy::Create(signaling_thread(),
6285976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                                                    data_channel));
6295976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
6305976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
6315976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid PeerConnection::OnAddRemoteAudioTrack(MediaStreamInterface* stream,
6325976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                                           AudioTrackInterface* audio_track,
6335976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                                           uint32 ssrc) {
6345976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  stream_handler_container_->AddRemoteAudioTrack(stream, audio_track, ssrc);
6355976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
6365976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
6375976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid PeerConnection::OnAddRemoteVideoTrack(MediaStreamInterface* stream,
6385976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                                           VideoTrackInterface* video_track,
6395976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                                           uint32 ssrc) {
6405976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  stream_handler_container_->AddRemoteVideoTrack(stream, video_track, ssrc);
6415976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
6425976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
6435976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid PeerConnection::OnRemoveRemoteAudioTrack(
6445976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    MediaStreamInterface* stream,
6455976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    AudioTrackInterface* audio_track) {
6465976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  stream_handler_container_->RemoveRemoteTrack(stream, audio_track);
6475976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
6485976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
6495976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid PeerConnection::OnRemoveRemoteVideoTrack(
6505976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    MediaStreamInterface* stream,
6515976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    VideoTrackInterface* video_track) {
6525976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  stream_handler_container_->RemoveRemoteTrack(stream, video_track);
6535976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
6545976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid PeerConnection::OnAddLocalAudioTrack(MediaStreamInterface* stream,
6555976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                                          AudioTrackInterface* audio_track,
6565976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                                          uint32 ssrc) {
6575976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  stream_handler_container_->AddLocalAudioTrack(stream, audio_track, ssrc);
6585976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
6595976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid PeerConnection::OnAddLocalVideoTrack(MediaStreamInterface* stream,
6605976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                                          VideoTrackInterface* video_track,
6615976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                                          uint32 ssrc) {
6625976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  stream_handler_container_->AddLocalVideoTrack(stream, video_track, ssrc);
6635976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
6645976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
6655976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid PeerConnection::OnRemoveLocalAudioTrack(MediaStreamInterface* stream,
6665976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                                             AudioTrackInterface* audio_track) {
6675976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  stream_handler_container_->RemoveLocalTrack(stream, audio_track);
6685976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
6695976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
6705976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid PeerConnection::OnRemoveLocalVideoTrack(MediaStreamInterface* stream,
6715976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                                             VideoTrackInterface* video_track) {
6725976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  stream_handler_container_->RemoveLocalTrack(stream, video_track);
6735976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
6745976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
6755976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid PeerConnection::OnRemoveLocalStream(MediaStreamInterface* stream) {
6765976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  stream_handler_container_->RemoveLocalStream(stream);
6775976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
6785976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
6795976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid PeerConnection::OnIceConnectionChange(
6805976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    PeerConnectionInterface::IceConnectionState new_state) {
6815976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  ice_connection_state_ = new_state;
6825976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  signaling_thread()->Post(this, MSG_ICECONNECTIONCHANGE);
6835976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
6845976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
6855976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid PeerConnection::OnIceGatheringChange(
6865976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    PeerConnectionInterface::IceGatheringState new_state) {
6875976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (IsClosed()) {
6885976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return;
6895976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
6905976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  ice_gathering_state_ = new_state;
6915976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  signaling_thread()->Post(this, MSG_ICEGATHERINGCHANGE);
6925976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
6935976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
6945976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid PeerConnection::OnIceCandidate(const IceCandidateInterface* candidate) {
6955976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  JsepIceCandidate* candidate_copy = NULL;
6965976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (candidate) {
6975976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    // TODO(ronghuawu): Make IceCandidateInterface reference counted instead
6985976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    // of making a copy.
6995976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    candidate_copy = new JsepIceCandidate(candidate->sdp_mid(),
7005976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                                          candidate->sdp_mline_index(),
7015976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                                          candidate->candidate());
7025976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
7035976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  // The Post takes the ownership of the |candidate_copy|.
7045976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  signaling_thread()->Post(this, MSG_ICECANDIDATE,
7055976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                           new CandidateMsg(candidate_copy));
7065976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
7075976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
7085976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid PeerConnection::OnIceComplete() {
7095976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  signaling_thread()->Post(this, MSG_ICECOMPLETE);
7105976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
7115976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
7125976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid PeerConnection::ChangeSignalingState(
7135976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    PeerConnectionInterface::SignalingState signaling_state) {
7145976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  signaling_state_ = signaling_state;
7155976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (signaling_state == kClosed) {
7165976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    ice_connection_state_ = kIceConnectionClosed;
7175976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    observer_->OnIceConnectionChange(ice_connection_state_);
7185976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    if (ice_gathering_state_ != kIceGatheringComplete) {
7195976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      ice_gathering_state_ = kIceGatheringComplete;
7205976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      observer_->OnIceGatheringChange(ice_gathering_state_);
7215976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    }
7225976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
7235976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  observer_->OnSignalingChange(signaling_state_);
7245976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  observer_->OnStateChange(PeerConnectionObserver::kSignalingState);
7255976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
7265976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
7275976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}  // namespace webrtc
728