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/webrtcsession.h"
295976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
305976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#include <algorithm>
315976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#include <climits>
325976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#include <vector>
335976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
345976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#include "talk/app/webrtc/jsepicecandidate.h"
355976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#include "talk/app/webrtc/jsepsessiondescription.h"
365976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#include "talk/app/webrtc/mediaconstraintsinterface.h"
375976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#include "talk/app/webrtc/mediastreamsignaling.h"
385976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#include "talk/app/webrtc/peerconnectioninterface.h"
39e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org#include "talk/app/webrtc/webrtcsessiondescriptionfactory.h"
405976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#include "talk/base/helpers.h"
415976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#include "talk/base/logging.h"
425976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#include "talk/base/stringencode.h"
435976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#include "talk/media/base/constants.h"
445976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#include "talk/media/base/videocapturer.h"
455976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#include "talk/session/media/channel.h"
465976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#include "talk/session/media/channelmanager.h"
475976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#include "talk/session/media/mediasession.h"
485976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
495976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgusing cricket::ContentInfo;
505976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgusing cricket::ContentInfos;
515976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgusing cricket::MediaContentDescription;
525976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgusing cricket::SessionDescription;
535976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgusing cricket::TransportInfo;
545976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
555976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgnamespace webrtc {
565976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
575976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgconst char kInternalConstraintPrefix[] = "internal";
585976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
595976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org// Supported MediaConstraints.
605976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org// DTLS-SRTP pseudo-constraints.
615976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgconst char MediaConstraintsInterface::kEnableDtlsSrtp[] =
625976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    "DtlsSrtpKeyAgreement";
635976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org// DataChannel pseudo constraints.
645976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgconst char MediaConstraintsInterface::kEnableRtpDataChannels[] =
655976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    "RtpDataChannels";
665976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org// This constraint is for internal use only, representing the Chrome command
675976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org// line flag. So it is prefixed with kInternalConstraintPrefix so JS values
685976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org// will be removed.
695976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgconst char MediaConstraintsInterface::kEnableSctpDataChannels[] =
705976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    "internalSctpDataChannels";
715976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
725976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org// Error messages
735976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgconst char kSetLocalSdpFailed[] = "SetLocalDescription failed: ";
745976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgconst char kSetRemoteSdpFailed[] = "SetRemoteDescription failed: ";
755976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgconst char kCreateChannelFailed[] = "Failed to create channels.";
76c1c67e5a722135af4ca83ee4c7d2dbe3f26bae70henrike@webrtc.orgconst char kBundleWithoutRtcpMux[] = "RTCP-MUX must be enabled when BUNDLE "
77c1c67e5a722135af4ca83ee4c7d2dbe3f26bae70henrike@webrtc.org                                     "is enabled.";
785976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgconst char kInvalidCandidates[] = "Description contains invalid candidates.";
795976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgconst char kInvalidSdp[] = "Invalid session description.";
805976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgconst char kMlineMismatch[] =
815976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    "Offer and answer descriptions m-lines are not matching. "
825976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    "Rejecting answer.";
835976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgconst char kSdpWithoutCrypto[] = "Called with a SDP without crypto enabled.";
845976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgconst char kSessionError[] = "Session error code: ";
855976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgconst char kUpdateStateFailed[] = "Failed to update session state: ";
865976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgconst char kPushDownOfferTDFailed[] =
875976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    "Failed to push down offer transport description.";
885976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgconst char kPushDownPranswerTDFailed[] =
895976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    "Failed to push down pranswer transport description.";
905976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgconst char kPushDownAnswerTDFailed[] =
915976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    "Failed to push down answer transport description.";
925976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
935976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org// Compares |answer| against |offer|. Comparision is done
945976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org// for number of m-lines in answer against offer. If matches true will be
955976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org// returned otherwise false.
965976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgstatic bool VerifyMediaDescriptions(
975976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    const SessionDescription* answer, const SessionDescription* offer) {
985976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (offer->contents().size() != answer->contents().size())
995976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return false;
1005976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
1015976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  for (size_t i = 0; i < offer->contents().size(); ++i) {
1025976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    if ((offer->contents()[i].name) != answer->contents()[i].name) {
1035976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      return false;
1045976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    }
1055976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
1065976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return true;
1075976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
1085976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
1095976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org// Checks that each non-rejected content has SDES crypto keys or a DTLS
1105976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org// fingerprint. Mismatches, such as replying with a DTLS fingerprint to SDES
1115976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org// keys, will be caught in Transport negotiation, and backstopped by Channel's
1125976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org// |secure_required| check.
1135976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgstatic bool VerifyCrypto(const SessionDescription* desc) {
1145976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (!desc) {
1155976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return false;
1165976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
1175976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  const ContentInfos& contents = desc->contents();
1185976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  for (size_t index = 0; index < contents.size(); ++index) {
1195976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    const ContentInfo* cinfo = &contents[index];
1205976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    if (cinfo->rejected) {
1215976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      continue;
1225976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    }
1235976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
1245976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    // If the content isn't rejected, crypto must be present.
1255976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    const MediaContentDescription* media =
1265976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org        static_cast<const MediaContentDescription*>(cinfo->description);
1275976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    const TransportInfo* tinfo = desc->GetTransportInfoByName(cinfo->name);
1285976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    if (!media || !tinfo) {
1295976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      // Something is not right.
1305976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      LOG(LS_ERROR) << kInvalidSdp;
1315976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      return false;
1325976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    }
1335976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    if (media->cryptos().empty() &&
1345976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org        !tinfo->description.identity_fingerprint) {
1355976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      // Crypto must be supplied.
1365976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      LOG(LS_WARNING) << "Session description must have SDES or DTLS-SRTP.";
1375976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      return false;
1385976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    }
1395976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
1405976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
1415976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return true;
1425976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
1435976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
144e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org// Forces |sdesc->crypto_required| to the appropriate state based on the
145e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org// current security policy, to ensure a failure occurs if there is an error
146e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org// in crypto negotiation.
147e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org// Called when processing the local session description.
148e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.orgstatic void UpdateSessionDescriptionSecurePolicy(
149e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org    cricket::SecureMediaPolicy secure_policy,
150e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org    SessionDescription* sdesc) {
151e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org  if (!sdesc) {
152e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org    return;
153e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org  }
1545976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
155e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org  // Updating the |crypto_required_| in MediaContentDescription to the
156e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org  // appropriate state based on the current security policy.
157e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org  for (cricket::ContentInfos::iterator iter = sdesc->contents().begin();
158e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org       iter != sdesc->contents().end(); ++iter) {
159e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org    if (cricket::IsMediaContent(&*iter)) {
160e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org      MediaContentDescription* mdesc =
161e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org          static_cast<MediaContentDescription*> (iter->description);
162e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org      if (mdesc) {
163e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org        mdesc->set_crypto_required(secure_policy == cricket::SEC_REQUIRED);
164e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org      }
165e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org    }
166e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org  }
1675976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
1685976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
1695976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgstatic bool GetAudioSsrcByTrackId(
1705976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    const SessionDescription* session_description,
1715976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    const std::string& track_id, uint32 *ssrc) {
1725976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  const cricket::ContentInfo* audio_info =
1735976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      cricket::GetFirstAudioContent(session_description);
1745976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (!audio_info) {
1755976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    LOG(LS_ERROR) << "Audio not used in this call";
1765976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return false;
1775976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
1785976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
1795976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  const cricket::MediaContentDescription* audio_content =
1805976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      static_cast<const cricket::MediaContentDescription*>(
1815976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org          audio_info->description);
1825976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  cricket::StreamParams stream;
1835976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (!cricket::GetStreamByIds(audio_content->streams(), "", track_id,
1845976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                               &stream)) {
1855976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return false;
1865976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
1875976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  *ssrc = stream.first_ssrc();
1885976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return true;
1895976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
1905976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
1915976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgstatic bool GetTrackIdBySsrc(const SessionDescription* session_description,
1925976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                             uint32 ssrc, std::string* track_id) {
1935976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  ASSERT(track_id != NULL);
1945976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
1955976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  cricket::StreamParams stream_out;
1965976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  const cricket::ContentInfo* audio_info =
1975976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      cricket::GetFirstAudioContent(session_description);
1985976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (!audio_info) {
1995976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return false;
2005976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
2015976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  const cricket::MediaContentDescription* audio_content =
2025976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      static_cast<const cricket::MediaContentDescription*>(
2035976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org          audio_info->description);
2045976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
2055976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (cricket::GetStreamBySsrc(audio_content->streams(), ssrc, &stream_out)) {
2065976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    *track_id = stream_out.id;
2075976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return true;
2085976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
2095976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
2105976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  const cricket::ContentInfo* video_info =
2115976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      cricket::GetFirstVideoContent(session_description);
2125976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (!video_info) {
2135976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return false;
2145976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
2155976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  const cricket::MediaContentDescription* video_content =
2165976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      static_cast<const cricket::MediaContentDescription*>(
2175976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org          video_info->description);
2185976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
2195976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (cricket::GetStreamBySsrc(video_content->streams(), ssrc, &stream_out)) {
2205976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    *track_id = stream_out.id;
2215976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return true;
2225976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
2235976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return false;
2245976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
2255976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
2265976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgstatic bool BadSdp(const std::string& desc, std::string* err_desc) {
2275976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (err_desc) {
2285976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    *err_desc = desc;
2295976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
2305976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  LOG(LS_ERROR) << desc;
2315976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return false;
2325976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
2335976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
2345976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgstatic bool BadLocalSdp(const std::string& desc, std::string* err_desc) {
2355976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  std::string set_local_sdp_failed = kSetLocalSdpFailed;
2365976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  set_local_sdp_failed.append(desc);
2375976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return BadSdp(set_local_sdp_failed, err_desc);
2385976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
2395976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
2405976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgstatic bool BadRemoteSdp(const std::string& desc, std::string* err_desc) {
2415976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  std::string set_remote_sdp_failed = kSetRemoteSdpFailed;
2425976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  set_remote_sdp_failed.append(desc);
2435976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return BadSdp(set_remote_sdp_failed, err_desc);
2445976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
2455976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
2465976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgstatic bool BadSdp(cricket::ContentSource source,
2475976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                   const std::string& desc, std::string* err_desc) {
2485976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (source == cricket::CS_LOCAL) {
2495976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return BadLocalSdp(desc, err_desc);
2505976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  } else {
2515976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return BadRemoteSdp(desc, err_desc);
2525976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
2535976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
2545976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
2555976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgstatic std::string SessionErrorMsg(cricket::BaseSession::Error error) {
2565976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  std::ostringstream desc;
2575976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  desc << kSessionError << error;
2585976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return desc.str();
2595976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
2605976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
2615976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#define GET_STRING_OF_STATE(state)  \
2625976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  case cricket::BaseSession::state:  \
2635976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    result = #state;  \
2645976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    break;
2655976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
2665976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgstatic std::string GetStateString(cricket::BaseSession::State state) {
2675976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  std::string result;
2685976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  switch (state) {
2695976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    GET_STRING_OF_STATE(STATE_INIT)
2705976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    GET_STRING_OF_STATE(STATE_SENTINITIATE)
2715976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    GET_STRING_OF_STATE(STATE_RECEIVEDINITIATE)
2725976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    GET_STRING_OF_STATE(STATE_SENTPRACCEPT)
2735976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    GET_STRING_OF_STATE(STATE_SENTACCEPT)
2745976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    GET_STRING_OF_STATE(STATE_RECEIVEDPRACCEPT)
2755976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    GET_STRING_OF_STATE(STATE_RECEIVEDACCEPT)
2765976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    GET_STRING_OF_STATE(STATE_SENTMODIFY)
2775976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    GET_STRING_OF_STATE(STATE_RECEIVEDMODIFY)
2785976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    GET_STRING_OF_STATE(STATE_SENTREJECT)
2795976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    GET_STRING_OF_STATE(STATE_RECEIVEDREJECT)
2805976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    GET_STRING_OF_STATE(STATE_SENTREDIRECT)
2815976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    GET_STRING_OF_STATE(STATE_SENTTERMINATE)
2825976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    GET_STRING_OF_STATE(STATE_RECEIVEDTERMINATE)
2835976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    GET_STRING_OF_STATE(STATE_INPROGRESS)
2845976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    GET_STRING_OF_STATE(STATE_DEINIT)
2855976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    default:
2865976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      ASSERT(false);
2875976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      break;
2885976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
2895976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return result;
2905976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
2915976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
2925976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#define GET_STRING_OF_ERROR(err)  \
2935976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  case cricket::BaseSession::err:  \
2945976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    result = #err;  \
2955976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    break;
2965976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
2975976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgstatic std::string GetErrorString(cricket::BaseSession::Error err) {
2985976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  std::string result;
2995976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  switch (err) {
3005976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    GET_STRING_OF_ERROR(ERROR_NONE)
3015976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    GET_STRING_OF_ERROR(ERROR_TIME)
3025976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    GET_STRING_OF_ERROR(ERROR_RESPONSE)
3035976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    GET_STRING_OF_ERROR(ERROR_NETWORK)
3045976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    GET_STRING_OF_ERROR(ERROR_CONTENT)
3055976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    GET_STRING_OF_ERROR(ERROR_TRANSPORT)
3065976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    default:
3075976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      ASSERT(false);
3085976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      break;
3095976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
3105976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return result;
3115976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
3125976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
3135976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgstatic bool SetSessionStateFailed(cricket::ContentSource source,
3145976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                                  cricket::BaseSession::Error err,
3155976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                                  std::string* err_desc) {
3165976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  std::string set_state_err = kUpdateStateFailed;
3175976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  set_state_err.append(GetErrorString(err));
3185976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return BadSdp(source, set_state_err, err_desc);
3195976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
3205976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
3215976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org// Help class used to remember if a a remote peer has requested ice restart by
3225976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org// by sending a description with new ice ufrag and password.
3235976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgclass IceRestartAnswerLatch {
3245976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org public:
3255976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  IceRestartAnswerLatch() : ice_restart_(false) { }
3265976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
327e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org  // Returns true if CheckForRemoteIceRestart has been called with a new session
328e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org  // description where ice password and ufrag has changed since last time
329e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org  // Reset() was called.
330e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org  bool Get() const {
331e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org    return ice_restart_;
332e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org  }
333e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org
334e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org  void Reset() {
3355976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    if (ice_restart_) {
3365976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      ice_restart_ = false;
3375976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    }
3385976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
3395976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
3405976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  void CheckForRemoteIceRestart(
3415976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      const SessionDescriptionInterface* old_desc,
3425976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      const SessionDescriptionInterface* new_desc) {
3435976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    if (!old_desc || new_desc->type() != SessionDescriptionInterface::kOffer) {
3445976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      return;
3455976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    }
3465976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    const SessionDescription* new_sd = new_desc->description();
3475976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    const SessionDescription* old_sd = old_desc->description();
3485976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    const ContentInfos& contents = new_sd->contents();
3495976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    for (size_t index = 0; index < contents.size(); ++index) {
3505976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      const ContentInfo* cinfo = &contents[index];
3515976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      if (cinfo->rejected) {
3525976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org        continue;
3535976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      }
3545976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      // If the content isn't rejected, check if ufrag and password has
3555976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      // changed.
3565976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      const cricket::TransportDescription* new_transport_desc =
3575976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org          new_sd->GetTransportDescriptionByName(cinfo->name);
3585976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      const cricket::TransportDescription* old_transport_desc =
3595976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org          old_sd->GetTransportDescriptionByName(cinfo->name);
3605976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      if (!new_transport_desc || !old_transport_desc) {
3615976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org        // No transport description exist. This is not an ice restart.
3625976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org        continue;
3635976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      }
3645976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      if (new_transport_desc->ice_pwd != old_transport_desc->ice_pwd &&
3655976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org          new_transport_desc->ice_ufrag != old_transport_desc->ice_ufrag) {
3665976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org        LOG(LS_INFO) << "Remote peer request ice restart.";
3675976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org        ice_restart_ = true;
3685976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org        break;
3695976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      }
3705976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    }
3715976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
3725976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
3735976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org private:
3745976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  bool ice_restart_;
3755976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org};
3765976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
377e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.orgWebRtcSession::WebRtcSession(
378e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org    cricket::ChannelManager* channel_manager,
379e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org    talk_base::Thread* signaling_thread,
380e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org    talk_base::Thread* worker_thread,
381e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org    cricket::PortAllocator* port_allocator,
382e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org    MediaStreamSignaling* mediastream_signaling)
3835976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    : cricket::BaseSession(signaling_thread, worker_thread, port_allocator,
3845976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                           talk_base::ToString(talk_base::CreateRandomId64() &
3855976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                                               LLONG_MAX),
3865976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                           cricket::NS_JINGLE_RTP, false),
3875976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      // RFC 3264: The numeric value of the session id and version in the
3885976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      // o line MUST be representable with a "64 bit signed integer".
3895976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      // Due to this constraint session id |sid_| is max limited to LLONG_MAX.
3905976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      channel_manager_(channel_manager),
3915976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      mediastream_signaling_(mediastream_signaling),
3925976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      ice_observer_(NULL),
3935976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      ice_connection_state_(PeerConnectionInterface::kIceConnectionNew),
3945976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      older_version_remote_peer_(false),
3955976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      data_channel_type_(cricket::DCT_NONE),
3965976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      ice_restart_latch_(new IceRestartAnswerLatch) {
3975976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
3985976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
3995976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgWebRtcSession::~WebRtcSession() {
4005976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (voice_channel_.get()) {
4015976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    SignalVoiceChannelDestroyed();
4025976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    channel_manager_->DestroyVoiceChannel(voice_channel_.release());
4035976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
4045976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (video_channel_.get()) {
4055976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    SignalVideoChannelDestroyed();
4065976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    channel_manager_->DestroyVideoChannel(video_channel_.release());
4075976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
4085976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (data_channel_.get()) {
4095976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    SignalDataChannelDestroyed();
4105976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    channel_manager_->DestroyDataChannel(data_channel_.release());
4115976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
4125976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  for (size_t i = 0; i < saved_candidates_.size(); ++i) {
4135976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    delete saved_candidates_[i];
4145976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
4155976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  delete identity();
4165976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
4175976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
418e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.orgbool WebRtcSession::Initialize(
419e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org    const MediaConstraintsInterface* constraints,
420e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org    DTLSIdentityServiceInterface* dtls_identity_service) {
4215976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  // TODO(perkj): Take |constraints| into consideration. Return false if not all
4225976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  // mandatory constraints can be fulfilled. Note that |constraints|
4235976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  // can be null.
4245976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  bool value;
4255976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  // Enable creation of RTP data channels if the kEnableRtpDataChannels is set.
4265976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  // It takes precendence over the kEnableSctpDataChannels constraint.
4275976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (FindConstraint(
4285976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      constraints, MediaConstraintsInterface::kEnableRtpDataChannels,
4295976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      &value, NULL) && value) {
4305976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    LOG(LS_INFO) << "Allowing RTP data engine.";
4315976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    data_channel_type_ = cricket::DCT_RTP;
432e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org  } else {
433e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org    bool sctp_enabled = FindConstraint(
434e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org        constraints,
435e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org        MediaConstraintsInterface::kEnableSctpDataChannels,
436e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org        &value, NULL) && value;
437e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org    bool dtls_enabled = FindConstraint(
438e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org        constraints,
439e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org        MediaConstraintsInterface::kEnableDtlsSrtp,
440e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org        &value, NULL) && value;
441e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org
442e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org    // DTLS has to be enabled to use SCTP.
443e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org    if (sctp_enabled && dtls_enabled) {
444e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org      LOG(LS_INFO) << "Allowing SCTP data engine.";
445e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org      data_channel_type_ = cricket::DCT_SCTP;
446e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org    }
4475976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
4485976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (data_channel_type_ != cricket::DCT_NONE) {
4495976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    mediastream_signaling_->SetDataChannelFactory(this);
4505976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
4515976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
4525976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  const cricket::VideoCodec default_codec(
4535976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      JsepSessionDescription::kDefaultVideoCodecId,
4545976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      JsepSessionDescription::kDefaultVideoCodecName,
4555976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      JsepSessionDescription::kMaxVideoCodecWidth,
4565976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      JsepSessionDescription::kMaxVideoCodecHeight,
4575976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      JsepSessionDescription::kDefaultVideoCodecFramerate,
4585976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      JsepSessionDescription::kDefaultVideoCodecPreference);
4595976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  channel_manager_->SetDefaultVideoEncoderConfig(
4605976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      cricket::VideoEncoderConfig(default_codec));
461e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org
462e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org  webrtc_session_desc_factory_.reset(new WebRtcSessionDescriptionFactory(
463e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org      signaling_thread(),
464e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org      channel_manager_,
465e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org      mediastream_signaling_,
466e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org      dtls_identity_service,
467e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org      this,
468e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org      id(),
469e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org      data_channel_type_,
470e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org      constraints));
471e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org
472e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org  webrtc_session_desc_factory_->SignalIdentityReady.connect(
473e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org      this, &WebRtcSession::OnIdentityReady);
4745976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return true;
4755976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
4765976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
4775976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid WebRtcSession::Terminate() {
4785976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  SetState(STATE_RECEIVEDTERMINATE);
4795976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  RemoveUnusedChannelsAndTransports(NULL);
4805976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  ASSERT(voice_channel_.get() == NULL);
4815976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  ASSERT(video_channel_.get() == NULL);
4825976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  ASSERT(data_channel_.get() == NULL);
4835976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
4845976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
4855976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgbool WebRtcSession::StartCandidatesAllocation() {
4865976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  // SpeculativelyConnectTransportChannels, will call ConnectChannels method
4875976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  // from TransportProxy to start gathering ice candidates.
4885976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  SpeculativelyConnectAllTransportChannels();
4895976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (!saved_candidates_.empty()) {
4905976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    // If there are saved candidates which arrived before local description is
4915976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    // set, copy those to remote description.
4925976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    CopySavedCandidates(remote_desc_.get());
4935976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
4945976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  // Push remote candidates present in remote description to transport channels.
4955976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  UseCandidatesInSessionDescription(remote_desc_.get());
4965976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return true;
4975976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
4985976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
4995976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid WebRtcSession::set_secure_policy(
5005976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    cricket::SecureMediaPolicy secure_policy) {
501e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org  webrtc_session_desc_factory_->set_secure(secure_policy);
5025976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
5035976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
504e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.orgcricket::SecureMediaPolicy WebRtcSession::secure_policy() const {
505e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org  return webrtc_session_desc_factory_->secure();
5065976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
5075976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
508e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.orgvoid WebRtcSession::CreateOffer(CreateSessionDescriptionObserver* observer,
509e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org                                const MediaConstraintsInterface* constraints) {
510e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org  webrtc_session_desc_factory_->CreateOffer(observer, constraints);
511e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org}
5125976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
513e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.orgvoid WebRtcSession::CreateAnswer(CreateSessionDescriptionObserver* observer,
514e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org                                 const MediaConstraintsInterface* constraints) {
515e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org  webrtc_session_desc_factory_->CreateAnswer(observer, constraints);
5165976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
5175976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
5185976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgbool WebRtcSession::SetLocalDescription(SessionDescriptionInterface* desc,
5195976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                                        std::string* err_desc) {
520e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org  cricket::SecureMediaPolicy secure_policy =
521e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org      webrtc_session_desc_factory_->secure();
522b30f5947ff2af0e3b77751bacec5dc7350c4dcd6sergeyu@chromium.org  // Takes the ownership of |desc| regardless of the result.
523b30f5947ff2af0e3b77751bacec5dc7350c4dcd6sergeyu@chromium.org  talk_base::scoped_ptr<SessionDescriptionInterface> desc_temp(desc);
524b30f5947ff2af0e3b77751bacec5dc7350c4dcd6sergeyu@chromium.org
5255976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (error() != cricket::BaseSession::ERROR_NONE) {
5265976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return BadLocalSdp(SessionErrorMsg(error()), err_desc);
5275976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
5285976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
5295976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (!desc || !desc->description()) {
5305976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return BadLocalSdp(kInvalidSdp, err_desc);
5315976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
532c1c67e5a722135af4ca83ee4c7d2dbe3f26bae70henrike@webrtc.org
533c1c67e5a722135af4ca83ee4c7d2dbe3f26bae70henrike@webrtc.org  if (!VerifyBundleSettings(desc->description())) {
534c1c67e5a722135af4ca83ee4c7d2dbe3f26bae70henrike@webrtc.org    return BadLocalSdp(kBundleWithoutRtcpMux, err_desc);
535c1c67e5a722135af4ca83ee4c7d2dbe3f26bae70henrike@webrtc.org  }
536c1c67e5a722135af4ca83ee4c7d2dbe3f26bae70henrike@webrtc.org
5375976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  Action action = GetAction(desc->type());
5385976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (!ExpectSetLocalDescription(action)) {
5395976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    std::string type = desc->type();
5405976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return BadLocalSdp(BadStateErrMsg(type, state()), err_desc);
5415976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
542e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org  if (secure_policy == cricket::SEC_REQUIRED &&
5435976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      !VerifyCrypto(desc->description())) {
5445976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return BadLocalSdp(kSdpWithoutCrypto, err_desc);
5455976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
5465976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (action == kAnswer && !VerifyMediaDescriptions(
5475976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org          desc->description(), remote_description()->description())) {
5485976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return BadLocalSdp(kMlineMismatch, err_desc);
5495976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
5505976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
5515976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  // Update the initiator flag if this session is the initiator.
5525976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (state() == STATE_INIT && action == kOffer) {
5535976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    set_initiator(true);
5545976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
5555976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
5565976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  // Update the MediaContentDescription crypto settings as per the policy set.
557e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org  UpdateSessionDescriptionSecurePolicy(secure_policy, desc->description());
5585976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
5595976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  set_local_description(desc->description()->Copy());
560b30f5947ff2af0e3b77751bacec5dc7350c4dcd6sergeyu@chromium.org  local_desc_.reset(desc_temp.release());
5615976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
5625976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  // Transport and Media channels will be created only when offer is set.
563b30f5947ff2af0e3b77751bacec5dc7350c4dcd6sergeyu@chromium.org  if (action == kOffer && !CreateChannels(local_desc_->description())) {
5645976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    // TODO(mallinath) - Handle CreateChannel failure, as new local description
5655976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    // is applied. Restore back to old description.
5665976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return BadLocalSdp(kCreateChannelFailed, err_desc);
5675976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
5685976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
5695976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  // Remove channel and transport proxies, if MediaContentDescription is
5705976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  // rejected.
571b30f5947ff2af0e3b77751bacec5dc7350c4dcd6sergeyu@chromium.org  RemoveUnusedChannelsAndTransports(local_desc_->description());
5725976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
5735976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (!UpdateSessionState(action, cricket::CS_LOCAL,
574b30f5947ff2af0e3b77751bacec5dc7350c4dcd6sergeyu@chromium.org                          local_desc_->description(), err_desc)) {
5755976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return false;
5765976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
5775976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  // Kick starting the ice candidates allocation.
5785976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  StartCandidatesAllocation();
5795976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
5805976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  // Update state and SSRC of local MediaStreams and DataChannels based on the
5815976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  // local session description.
5825976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  mediastream_signaling_->OnLocalDescriptionChanged(local_desc_.get());
5835976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
5845976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (error() != cricket::BaseSession::ERROR_NONE) {
5855976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return BadLocalSdp(SessionErrorMsg(error()), err_desc);
5865976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
5875976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return true;
5885976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
5895976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
5905976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgbool WebRtcSession::SetRemoteDescription(SessionDescriptionInterface* desc,
5915976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                                         std::string* err_desc) {
592e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org  cricket::SecureMediaPolicy secure_policy =
593e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org      webrtc_session_desc_factory_->secure();
594b30f5947ff2af0e3b77751bacec5dc7350c4dcd6sergeyu@chromium.org  // Takes the ownership of |desc| regardless of the result.
595b30f5947ff2af0e3b77751bacec5dc7350c4dcd6sergeyu@chromium.org  talk_base::scoped_ptr<SessionDescriptionInterface> desc_temp(desc);
596b30f5947ff2af0e3b77751bacec5dc7350c4dcd6sergeyu@chromium.org
5975976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (error() != cricket::BaseSession::ERROR_NONE) {
5985976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return BadRemoteSdp(SessionErrorMsg(error()), err_desc);
5995976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
6005976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
6015976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (!desc || !desc->description()) {
6025976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return BadRemoteSdp(kInvalidSdp, err_desc);
6035976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
604c1c67e5a722135af4ca83ee4c7d2dbe3f26bae70henrike@webrtc.org
605c1c67e5a722135af4ca83ee4c7d2dbe3f26bae70henrike@webrtc.org  if (!VerifyBundleSettings(desc->description())) {
606c1c67e5a722135af4ca83ee4c7d2dbe3f26bae70henrike@webrtc.org    return BadRemoteSdp(kBundleWithoutRtcpMux, err_desc);
607c1c67e5a722135af4ca83ee4c7d2dbe3f26bae70henrike@webrtc.org  }
608c1c67e5a722135af4ca83ee4c7d2dbe3f26bae70henrike@webrtc.org
6095976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  Action action = GetAction(desc->type());
6105976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (!ExpectSetRemoteDescription(action)) {
6115976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    std::string type = desc->type();
6125976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return BadRemoteSdp(BadStateErrMsg(type, state()), err_desc);
6135976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
6145976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
6155976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (action == kAnswer && !VerifyMediaDescriptions(
6165976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org          desc->description(), local_description()->description())) {
6175976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return BadRemoteSdp(kMlineMismatch, err_desc);
6185976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
6195976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
620e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org  if (secure_policy == cricket::SEC_REQUIRED &&
6215976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      !VerifyCrypto(desc->description())) {
6225976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return BadRemoteSdp(kSdpWithoutCrypto, err_desc);
6235976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
6245976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
6255976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  // Transport and Media channels will be created only when offer is set.
6265976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (action == kOffer && !CreateChannels(desc->description())) {
6275976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    // TODO(mallinath) - Handle CreateChannel failure, as new local description
6285976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    // is applied. Restore back to old description.
6295976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return BadRemoteSdp(kCreateChannelFailed, err_desc);
6305976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
6315976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
6325976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  // Remove channel and transport proxies, if MediaContentDescription is
6335976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  // rejected.
6345976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  RemoveUnusedChannelsAndTransports(desc->description());
6355976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
6365976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  // NOTE: Candidates allocation will be initiated only when SetLocalDescription
6375976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  // is called.
6385976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  set_remote_description(desc->description()->Copy());
6395976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (!UpdateSessionState(action, cricket::CS_REMOTE,
6405976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                          desc->description(), err_desc)) {
6415976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return false;
6425976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
6435976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
6445976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  // Update remote MediaStreams.
6455976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  mediastream_signaling_->OnRemoteDescriptionChanged(desc);
6465976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (local_description() && !UseCandidatesInSessionDescription(desc)) {
6475976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return BadRemoteSdp(kInvalidCandidates, err_desc);
6485976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
6495976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
6505976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  // Copy all saved candidates.
6515976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  CopySavedCandidates(desc);
6525976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  // We retain all received candidates.
653e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org  WebRtcSessionDescriptionFactory::CopyCandidatesFromSessionDescription(
654e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org      remote_desc_.get(), desc);
6555976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  // Check if this new SessionDescription contains new ice ufrag and password
6565976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  // that indicates the remote peer requests ice restart.
6575976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  ice_restart_latch_->CheckForRemoteIceRestart(remote_desc_.get(),
6585976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                                               desc);
659b30f5947ff2af0e3b77751bacec5dc7350c4dcd6sergeyu@chromium.org  remote_desc_.reset(desc_temp.release());
6605976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (error() != cricket::BaseSession::ERROR_NONE) {
6615976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return BadRemoteSdp(SessionErrorMsg(error()), err_desc);
6625976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
6635976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return true;
6645976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
6655976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
6665976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgbool WebRtcSession::UpdateSessionState(
6675976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    Action action, cricket::ContentSource source,
6685976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    const cricket::SessionDescription* desc,
6695976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    std::string* err_desc) {
6705976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  // If there's already a pending error then no state transition should happen.
6715976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  // But all call-sites should be verifying this before calling us!
6725976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  ASSERT(error() == cricket::BaseSession::ERROR_NONE);
6735976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (action == kOffer) {
6745976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    if (!PushdownTransportDescription(source, cricket::CA_OFFER)) {
6755976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      return BadSdp(source, kPushDownOfferTDFailed, err_desc);
6765976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    }
6775976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    SetState(source == cricket::CS_LOCAL ?
6785976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org        STATE_SENTINITIATE : STATE_RECEIVEDINITIATE);
6795976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    if (error() != cricket::BaseSession::ERROR_NONE) {
6805976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      return SetSessionStateFailed(source, error(), err_desc);
6815976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    }
6825976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  } else if (action == kPrAnswer) {
6835976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    if (!PushdownTransportDescription(source, cricket::CA_PRANSWER)) {
6845976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      return BadSdp(source, kPushDownPranswerTDFailed, err_desc);
6855976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    }
6865976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    EnableChannels();
6875976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    SetState(source == cricket::CS_LOCAL ?
6885976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org        STATE_SENTPRACCEPT : STATE_RECEIVEDPRACCEPT);
6895976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    if (error() != cricket::BaseSession::ERROR_NONE) {
6905976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      return SetSessionStateFailed(source, error(), err_desc);
6915976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    }
6925976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  } else if (action == kAnswer) {
6935976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    if (!PushdownTransportDescription(source, cricket::CA_ANSWER)) {
6945976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      return BadSdp(source, kPushDownAnswerTDFailed, err_desc);
6955976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    }
6965976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    MaybeEnableMuxingSupport();
6975976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    EnableChannels();
6985976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    SetState(source == cricket::CS_LOCAL ?
6995976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org        STATE_SENTACCEPT : STATE_RECEIVEDACCEPT);
7005976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    if (error() != cricket::BaseSession::ERROR_NONE) {
7015976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      return SetSessionStateFailed(source, error(), err_desc);
7025976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    }
7035976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
7045976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return true;
7055976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
7065976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
7075976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgWebRtcSession::Action WebRtcSession::GetAction(const std::string& type) {
7085976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (type == SessionDescriptionInterface::kOffer) {
7095976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return WebRtcSession::kOffer;
7105976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  } else if (type == SessionDescriptionInterface::kPrAnswer) {
7115976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return WebRtcSession::kPrAnswer;
7125976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  } else if (type == SessionDescriptionInterface::kAnswer) {
7135976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return WebRtcSession::kAnswer;
7145976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
7155976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  ASSERT(false && "unknown action type");
7165976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return WebRtcSession::kOffer;
7175976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
7185976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
7195976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgbool WebRtcSession::ProcessIceMessage(const IceCandidateInterface* candidate) {
7205976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (state() == STATE_INIT) {
7215976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org     LOG(LS_ERROR) << "ProcessIceMessage: ICE candidates can't be added "
7225976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                   << "without any offer (local or remote) "
7235976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                   << "session description.";
7245976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org     return false;
7255976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
7265976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
7275976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (!candidate) {
7285976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    LOG(LS_ERROR) << "ProcessIceMessage: Candidate is NULL";
7295976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return false;
7305976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
7315976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
7325976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (!local_description() || !remote_description()) {
7335976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    LOG(LS_INFO) << "ProcessIceMessage: Remote description not set, "
7345976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                 << "save the candidate for later use.";
7355976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    saved_candidates_.push_back(
7365976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org        new JsepIceCandidate(candidate->sdp_mid(), candidate->sdp_mline_index(),
7375976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                             candidate->candidate()));
7385976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return true;
7395976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
7405976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
7415976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  // Add this candidate to the remote session description.
7425976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (!remote_desc_->AddCandidate(candidate)) {
7435976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    LOG(LS_ERROR) << "ProcessIceMessage: Candidate cannot be used";
7445976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return false;
7455976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
7465976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
7475976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return UseCandidatesInSessionDescription(remote_desc_.get());
7485976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
7495976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
7505976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgbool WebRtcSession::GetTrackIdBySsrc(uint32 ssrc, std::string* id) {
7515976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (GetLocalTrackId(ssrc, id)) {
7525976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    if (GetRemoteTrackId(ssrc, id)) {
7535976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      LOG(LS_WARNING) << "SSRC " << ssrc
7545976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                      << " exists in both local and remote descriptions";
7555976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      return true;  // We return the remote track id.
7565976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    }
7575976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return true;
7585976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  } else {
7595976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return GetRemoteTrackId(ssrc, id);
7605976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
7615976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
7625976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
7635976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgbool WebRtcSession::GetLocalTrackId(uint32 ssrc, std::string* track_id) {
7645976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (!BaseSession::local_description())
7655976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return false;
7665976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return webrtc::GetTrackIdBySsrc(
7675976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    BaseSession::local_description(), ssrc, track_id);
7685976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
7695976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
7705976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgbool WebRtcSession::GetRemoteTrackId(uint32 ssrc, std::string* track_id) {
7715976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (!BaseSession::remote_description())
7725976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      return false;
7735976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return webrtc::GetTrackIdBySsrc(
7745976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    BaseSession::remote_description(), ssrc, track_id);
7755976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
7765976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
7775976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgstd::string WebRtcSession::BadStateErrMsg(
7785976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    const std::string& type, State state) {
7795976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  std::ostringstream desc;
7805976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  desc << "Called with type in wrong state, "
7815976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org       << "type: " << type << " state: " << GetStateString(state);
7825976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return desc.str();
7835976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
7845976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
785c1c67e5a722135af4ca83ee4c7d2dbe3f26bae70henrike@webrtc.orgvoid WebRtcSession::SetAudioPlayout(uint32 ssrc, bool enable,
786c1c67e5a722135af4ca83ee4c7d2dbe3f26bae70henrike@webrtc.org                                    cricket::AudioRenderer* renderer) {
7875976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  ASSERT(signaling_thread()->IsCurrent());
7885976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (!voice_channel_) {
7895976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    LOG(LS_ERROR) << "SetAudioPlayout: No audio channel exists.";
7905976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return;
7915976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
792c1c67e5a722135af4ca83ee4c7d2dbe3f26bae70henrike@webrtc.org  if (!voice_channel_->SetRemoteRenderer(ssrc, renderer)) {
793c1c67e5a722135af4ca83ee4c7d2dbe3f26bae70henrike@webrtc.org    // SetRenderer() can fail if the ssrc does not match any playout channel.
794c1c67e5a722135af4ca83ee4c7d2dbe3f26bae70henrike@webrtc.org    LOG(LS_ERROR) << "SetAudioPlayout: ssrc is incorrect: " << ssrc;
795c1c67e5a722135af4ca83ee4c7d2dbe3f26bae70henrike@webrtc.org    return;
796c1c67e5a722135af4ca83ee4c7d2dbe3f26bae70henrike@webrtc.org  }
7975976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (!voice_channel_->SetOutputScaling(ssrc, enable ? 1 : 0, enable ? 1 : 0)) {
7985976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    // Allow that SetOutputScaling fail if |enable| is false but assert
7995976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    // otherwise. This in the normal case when the underlying media channel has
8005976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    // already been deleted.
8015976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    ASSERT(enable == false);
8025976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
8035976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
8045976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
8055976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid WebRtcSession::SetAudioSend(uint32 ssrc, bool enable,
806c1c67e5a722135af4ca83ee4c7d2dbe3f26bae70henrike@webrtc.org                                 const cricket::AudioOptions& options,
807c1c67e5a722135af4ca83ee4c7d2dbe3f26bae70henrike@webrtc.org                                 cricket::AudioRenderer* renderer) {
8085976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  ASSERT(signaling_thread()->IsCurrent());
8095976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (!voice_channel_) {
8105976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    LOG(LS_ERROR) << "SetAudioSend: No audio channel exists.";
8115976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return;
8125976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
813c1c67e5a722135af4ca83ee4c7d2dbe3f26bae70henrike@webrtc.org  if (!voice_channel_->SetLocalRenderer(ssrc, renderer)) {
814c1c67e5a722135af4ca83ee4c7d2dbe3f26bae70henrike@webrtc.org    // SetRenderer() can fail if the ssrc does not match any send channel.
815c1c67e5a722135af4ca83ee4c7d2dbe3f26bae70henrike@webrtc.org    LOG(LS_ERROR) << "SetAudioSend: ssrc is incorrect: " << ssrc;
816c1c67e5a722135af4ca83ee4c7d2dbe3f26bae70henrike@webrtc.org    return;
817c1c67e5a722135af4ca83ee4c7d2dbe3f26bae70henrike@webrtc.org  }
8185976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (!voice_channel_->MuteStream(ssrc, !enable)) {
8195976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    // Allow that MuteStream fail if |enable| is false but assert otherwise.
8205976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    // This in the normal case when the underlying media channel has already
8215976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    // been deleted.
8225976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    ASSERT(enable == false);
8235976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return;
8245976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
8255976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (enable)
8265976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    voice_channel_->SetChannelOptions(options);
8275976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
8285976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
8295976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgbool WebRtcSession::SetCaptureDevice(uint32 ssrc,
8305976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                                     cricket::VideoCapturer* camera) {
8315976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  ASSERT(signaling_thread()->IsCurrent());
8325976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
8335976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (!video_channel_.get()) {
8345976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    // |video_channel_| doesnt't exist. Probably because the remote end doesnt't
8355976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    // support video.
8365976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    LOG(LS_WARNING) << "Video not used in this call.";
8375976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return false;
8385976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
8395976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (!video_channel_->SetCapturer(ssrc, camera)) {
8405976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    // Allow that SetCapturer fail if |camera| is NULL but assert otherwise.
8415976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    // This in the normal case when the underlying media channel has already
8425976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    // been deleted.
8435976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    ASSERT(camera == NULL);
8445976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return false;
8455976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
8465976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return true;
8475976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
8485976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
8495976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid WebRtcSession::SetVideoPlayout(uint32 ssrc,
8505976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                                    bool enable,
8515976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                                    cricket::VideoRenderer* renderer) {
8525976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  ASSERT(signaling_thread()->IsCurrent());
8535976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (!video_channel_) {
8545976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    LOG(LS_WARNING) << "SetVideoPlayout: No video channel exists.";
8555976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return;
8565976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
8575976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (!video_channel_->SetRenderer(ssrc, enable ? renderer : NULL)) {
8585976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    // Allow that SetRenderer fail if |renderer| is NULL but assert otherwise.
8595976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    // This in the normal case when the underlying media channel has already
8605976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    // been deleted.
8615976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    ASSERT(renderer == NULL);
8625976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
8635976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
8645976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
8655976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid WebRtcSession::SetVideoSend(uint32 ssrc, bool enable,
8665976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                                 const cricket::VideoOptions* options) {
8675976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  ASSERT(signaling_thread()->IsCurrent());
8685976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (!video_channel_) {
8695976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    LOG(LS_WARNING) << "SetVideoSend: No video channel exists.";
8705976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return;
8715976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
8725976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (!video_channel_->MuteStream(ssrc, !enable)) {
8735976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    // Allow that MuteStream fail if |enable| is false but assert otherwise.
8745976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    // This in the normal case when the underlying media channel has already
8755976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    // been deleted.
8765976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    ASSERT(enable == false);
8775976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return;
8785976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
8795976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (enable && options)
8805976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    video_channel_->SetChannelOptions(*options);
8815976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
8825976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
8835976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgbool WebRtcSession::CanInsertDtmf(const std::string& track_id) {
8845976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  ASSERT(signaling_thread()->IsCurrent());
8855976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (!voice_channel_) {
8865976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    LOG(LS_ERROR) << "CanInsertDtmf: No audio channel exists.";
8875976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return false;
8885976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
8895976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  uint32 send_ssrc = 0;
8905976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  // The Dtmf is negotiated per channel not ssrc, so we only check if the ssrc
8915976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  // exists.
8925976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (!GetAudioSsrcByTrackId(BaseSession::local_description(), track_id,
8935976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                             &send_ssrc)) {
8945976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    LOG(LS_ERROR) << "CanInsertDtmf: Track does not exist: " << track_id;
8955976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return false;
8965976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
8975976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return voice_channel_->CanInsertDtmf();
8985976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
8995976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
9005976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgbool WebRtcSession::InsertDtmf(const std::string& track_id,
9015976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                               int code, int duration) {
9025976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  ASSERT(signaling_thread()->IsCurrent());
9035976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (!voice_channel_) {
9045976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    LOG(LS_ERROR) << "InsertDtmf: No audio channel exists.";
9055976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return false;
9065976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
9075976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  uint32 send_ssrc = 0;
9085976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (!VERIFY(GetAudioSsrcByTrackId(BaseSession::local_description(),
9095976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                                    track_id, &send_ssrc))) {
9105976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    LOG(LS_ERROR) << "InsertDtmf: Track does not exist: " << track_id;
9115976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return false;
9125976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
9135976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (!voice_channel_->InsertDtmf(send_ssrc, code, duration,
9145976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                                  cricket::DF_SEND)) {
9155976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    LOG(LS_ERROR) << "Failed to insert DTMF to channel.";
9165976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return false;
9175976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
9185976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return true;
9195976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
9205976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
9215976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgsigslot::signal0<>* WebRtcSession::GetOnDestroyedSignal() {
9225976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return &SignalVoiceChannelDestroyed;
9235976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
9245976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
9255976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgtalk_base::scoped_refptr<DataChannel> WebRtcSession::CreateDataChannel(
9265976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      const std::string& label,
9275976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      const DataChannelInit* config) {
9285976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (state() == STATE_RECEIVEDTERMINATE) {
9295976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return NULL;
9305976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
9315976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (data_channel_type_ == cricket::DCT_NONE) {
9325976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    LOG(LS_ERROR) << "CreateDataChannel: Data is not supported in this call.";
9335976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return NULL;
9345976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
9355976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  DataChannelInit new_config = config ? (*config) : DataChannelInit();
9365976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
9375976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (data_channel_type_ == cricket::DCT_SCTP) {
9385976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    if (new_config.id < 0) {
9395976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      if (!mediastream_signaling_->AllocateSctpId(&new_config.id)) {
9405976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org        LOG(LS_ERROR) << "No id can be allocated for the SCTP data channel.";
9415976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org        return NULL;
9425976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      }
9435976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    } else if (!mediastream_signaling_->IsSctpIdAvailable(new_config.id)) {
9445976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      LOG(LS_ERROR) << "Failed to create a SCTP data channel "
9455976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                    << "because the id is already in use or out of range.";
9465976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      return NULL;
9475976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    }
9485976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
949e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org
9505976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  talk_base::scoped_refptr<DataChannel> channel(
9515976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      DataChannel::Create(this, label, &new_config));
9525976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (channel == NULL)
9535976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return NULL;
9545976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (!mediastream_signaling_->AddDataChannel(channel))
9555976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return NULL;
956e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org  if (data_channel_type_ == cricket::DCT_SCTP) {
957e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org    if (config == NULL) {
958e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org      LOG(LS_WARNING) << "Could not send data channel OPEN message"
959e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org                      << " because of NULL config.";
960e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org      return NULL;
961e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org    }
962e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org    if (data_channel_.get()) {
963e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org      channel->SetReceiveSsrc(new_config.id);
964e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org      channel->SetSendSsrc(new_config.id);
965e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org      channel->ConnectToDataSession();
966e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org    }
967e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org    if (!config->negotiated) {
968e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org      talk_base::Buffer *payload = new talk_base::Buffer;
969e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org      if (!mediastream_signaling_->WriteDataChannelOpenMessage(
970e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org              label, *config, payload)) {
971e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org        LOG(LS_WARNING) << "Could not write data channel OPEN message";
972e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org      }
973e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org      // SendControl may queue the message until the data channel's set up,
974e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org      // or congestion clears.
975e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org      channel->SendControl(payload);
976e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org    }
977e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org  }
9785976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return channel;
9795976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
9805976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
9815976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgcricket::DataChannelType WebRtcSession::data_channel_type() const {
9825976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return data_channel_type_;
9835976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
9845976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
985e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.orgbool WebRtcSession::IceRestartPending() const {
986e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org  return ice_restart_latch_->Get();
987e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org}
988e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org
989e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.orgvoid WebRtcSession::ResetIceRestartLatch() {
990e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org  ice_restart_latch_->Reset();
991e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org}
992e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org
993e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.orgvoid WebRtcSession::OnIdentityReady(talk_base::SSLIdentity* identity) {
994e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org  SetIdentity(identity);
995e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org}
996e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org
997e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.orgbool WebRtcSession::waiting_for_identity() const {
998e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org  return webrtc_session_desc_factory_->waiting_for_identity();
999e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org}
1000e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org
10015976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid WebRtcSession::SetIceConnectionState(
10025976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      PeerConnectionInterface::IceConnectionState state) {
10035976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (ice_connection_state_ == state) {
10045976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return;
10055976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
10065976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
10075976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  // ASSERT that the requested transition is allowed.  Note that
10085976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  // WebRtcSession does not implement "kIceConnectionClosed" (that is handled
10095976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  // within PeerConnection).  This switch statement should compile away when
10105976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  // ASSERTs are disabled.
10115976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  switch (ice_connection_state_) {
10125976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    case PeerConnectionInterface::kIceConnectionNew:
10135976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      ASSERT(state == PeerConnectionInterface::kIceConnectionChecking);
10145976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      break;
10155976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    case PeerConnectionInterface::kIceConnectionChecking:
10165976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      ASSERT(state == PeerConnectionInterface::kIceConnectionFailed ||
10175976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org             state == PeerConnectionInterface::kIceConnectionConnected);
10185976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      break;
10195976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    case PeerConnectionInterface::kIceConnectionConnected:
10205976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      ASSERT(state == PeerConnectionInterface::kIceConnectionDisconnected ||
10215976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org             state == PeerConnectionInterface::kIceConnectionChecking ||
10225976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org             state == PeerConnectionInterface::kIceConnectionCompleted);
10235976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      break;
10245976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    case PeerConnectionInterface::kIceConnectionCompleted:
10255976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      ASSERT(state == PeerConnectionInterface::kIceConnectionConnected ||
10265976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org             state == PeerConnectionInterface::kIceConnectionDisconnected);
10275976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      break;
10285976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    case PeerConnectionInterface::kIceConnectionFailed:
10295976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      ASSERT(state == PeerConnectionInterface::kIceConnectionNew);
10305976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      break;
10315976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    case PeerConnectionInterface::kIceConnectionDisconnected:
10325976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      ASSERT(state == PeerConnectionInterface::kIceConnectionChecking ||
10335976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org             state == PeerConnectionInterface::kIceConnectionConnected ||
10345976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org             state == PeerConnectionInterface::kIceConnectionCompleted ||
10355976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org             state == PeerConnectionInterface::kIceConnectionFailed);
10365976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      break;
10375976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    case PeerConnectionInterface::kIceConnectionClosed:
10385976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      ASSERT(false);
10395976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      break;
10405976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    default:
10415976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      ASSERT(false);
10425976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      break;
10435976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
10445976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
10455976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  ice_connection_state_ = state;
10465976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (ice_observer_) {
10475976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    ice_observer_->OnIceConnectionChange(ice_connection_state_);
10485976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
10495976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
10505976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
10515976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid WebRtcSession::OnTransportRequestSignaling(
10525976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    cricket::Transport* transport) {
10535976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  ASSERT(signaling_thread()->IsCurrent());
10545976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  transport->OnSignalingReady();
10555976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (ice_observer_) {
10565976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    ice_observer_->OnIceGatheringChange(
10575976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      PeerConnectionInterface::kIceGatheringGathering);
10585976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
10595976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
10605976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
10615976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid WebRtcSession::OnTransportConnecting(cricket::Transport* transport) {
10625976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  ASSERT(signaling_thread()->IsCurrent());
10635976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  // start monitoring for the write state of the transport.
10645976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  OnTransportWritable(transport);
10655976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
10665976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
10675976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid WebRtcSession::OnTransportWritable(cricket::Transport* transport) {
10685976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  ASSERT(signaling_thread()->IsCurrent());
10695976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  // TODO(bemasc): Expose more API from Transport to detect when
10705976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  // candidate selection starts or stops, due to success or failure.
10715976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (transport->all_channels_writable()) {
10725976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    if (ice_connection_state_ ==
10735976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org            PeerConnectionInterface::kIceConnectionChecking ||
10745976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org        ice_connection_state_ ==
10755976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org            PeerConnectionInterface::kIceConnectionDisconnected) {
10765976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      SetIceConnectionState(PeerConnectionInterface::kIceConnectionConnected);
10775976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    }
10785976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  } else if (transport->HasChannels()) {
10795976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    // If the current state is Connected or Completed, then there were writable
10805976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    // channels but now there are not, so the next state must be Disconnected.
10815976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    if (ice_connection_state_ ==
10825976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org            PeerConnectionInterface::kIceConnectionConnected ||
10835976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org        ice_connection_state_ ==
10845976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org            PeerConnectionInterface::kIceConnectionCompleted) {
10855976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      SetIceConnectionState(
10865976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org          PeerConnectionInterface::kIceConnectionDisconnected);
10875976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    }
10885976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
10895976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
10905976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
10915976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid WebRtcSession::OnTransportProxyCandidatesReady(
10925976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    cricket::TransportProxy* proxy, const cricket::Candidates& candidates) {
10935976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  ASSERT(signaling_thread()->IsCurrent());
10945976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  ProcessNewLocalCandidate(proxy->content_name(), candidates);
10955976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
10965976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
10975976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgbool WebRtcSession::ExpectSetLocalDescription(Action action) {
10985976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return ((action == kOffer && state() == STATE_INIT) ||
10995976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org          // update local offer
11005976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org          (action == kOffer && state() == STATE_SENTINITIATE) ||
11015976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org          // update the current ongoing session.
11025976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org          (action == kOffer && state() == STATE_RECEIVEDACCEPT) ||
11035976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org          (action == kOffer && state() == STATE_SENTACCEPT) ||
11045976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org          (action == kOffer && state() == STATE_INPROGRESS) ||
11055976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org          // accept remote offer
11065976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org          (action == kAnswer && state() == STATE_RECEIVEDINITIATE) ||
11075976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org          (action == kAnswer && state() == STATE_SENTPRACCEPT) ||
11085976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org          (action == kPrAnswer && state() == STATE_RECEIVEDINITIATE) ||
11095976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org          (action == kPrAnswer && state() == STATE_SENTPRACCEPT));
11105976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
11115976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
11125976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgbool WebRtcSession::ExpectSetRemoteDescription(Action action) {
11135976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return ((action == kOffer && state() == STATE_INIT) ||
11145976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org          // update remote offer
11155976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org          (action == kOffer && state() == STATE_RECEIVEDINITIATE) ||
11165976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org          // update the current ongoing session
11175976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org          (action == kOffer && state() == STATE_RECEIVEDACCEPT) ||
11185976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org          (action == kOffer && state() == STATE_SENTACCEPT) ||
11195976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org          (action == kOffer && state() == STATE_INPROGRESS) ||
11205976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org          // accept local offer
11215976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org          (action == kAnswer && state() == STATE_SENTINITIATE) ||
11225976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org          (action == kAnswer && state() == STATE_RECEIVEDPRACCEPT) ||
11235976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org          (action == kPrAnswer && state() == STATE_SENTINITIATE) ||
11245976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org          (action == kPrAnswer && state() == STATE_RECEIVEDPRACCEPT));
11255976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
11265976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
11275976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid WebRtcSession::OnCandidatesAllocationDone() {
11285976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  ASSERT(signaling_thread()->IsCurrent());
11295976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (ice_observer_) {
11305976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    ice_observer_->OnIceGatheringChange(
11315976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      PeerConnectionInterface::kIceGatheringComplete);
11325976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    ice_observer_->OnIceComplete();
11335976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
11345976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
11355976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
11365976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org// Enabling voice and video channel.
11375976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid WebRtcSession::EnableChannels() {
11385976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (voice_channel_ && !voice_channel_->enabled())
11395976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    voice_channel_->Enable(true);
11405976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
11415976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (video_channel_ && !video_channel_->enabled())
11425976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    video_channel_->Enable(true);
11435976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
11445976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (data_channel_.get() && !data_channel_->enabled())
11455976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    data_channel_->Enable(true);
11465976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
11475976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
11485976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid WebRtcSession::ProcessNewLocalCandidate(
11495976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    const std::string& content_name,
11505976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    const cricket::Candidates& candidates) {
11515976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  int sdp_mline_index;
11525976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (!GetLocalCandidateMediaIndex(content_name, &sdp_mline_index)) {
11535976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    LOG(LS_ERROR) << "ProcessNewLocalCandidate: content name "
11545976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                  << content_name << " not found";
11555976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return;
11565976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
11575976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
11585976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  for (cricket::Candidates::const_iterator citer = candidates.begin();
11595976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      citer != candidates.end(); ++citer) {
11605976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    // Use content_name as the candidate media id.
11615976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    JsepIceCandidate candidate(content_name, sdp_mline_index, *citer);
11625976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    if (ice_observer_) {
11635976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      ice_observer_->OnIceCandidate(&candidate);
11645976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    }
11655976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    if (local_desc_) {
11665976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      local_desc_->AddCandidate(&candidate);
11675976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    }
11685976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
11695976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
11705976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
11715976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org// Returns the media index for a local ice candidate given the content name.
11725976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgbool WebRtcSession::GetLocalCandidateMediaIndex(const std::string& content_name,
11735976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                                                int* sdp_mline_index) {
11745976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (!BaseSession::local_description() || !sdp_mline_index)
11755976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return false;
11765976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
11775976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  bool content_found = false;
11785976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  const ContentInfos& contents = BaseSession::local_description()->contents();
11795976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  for (size_t index = 0; index < contents.size(); ++index) {
11805976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    if (contents[index].name == content_name) {
1181b30f5947ff2af0e3b77751bacec5dc7350c4dcd6sergeyu@chromium.org      *sdp_mline_index = static_cast<int>(index);
11825976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      content_found = true;
11835976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      break;
11845976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    }
11855976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
11865976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return content_found;
11875976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
11885976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
11895976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgbool WebRtcSession::UseCandidatesInSessionDescription(
11905976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    const SessionDescriptionInterface* remote_desc) {
11915976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (!remote_desc)
11925976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return true;
11935976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  bool ret = true;
11945976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  for (size_t m = 0; m < remote_desc->number_of_mediasections(); ++m) {
11955976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    const IceCandidateCollection* candidates = remote_desc->candidates(m);
11965976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    for  (size_t n = 0; n < candidates->count(); ++n) {
11975976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      ret = UseCandidate(candidates->at(n));
11985976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      if (!ret)
11995976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org        break;
12005976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    }
12015976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
12025976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return ret;
12035976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
12045976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
12055976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgbool WebRtcSession::UseCandidate(
12065976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    const IceCandidateInterface* candidate) {
12075976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
12085976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  size_t mediacontent_index = static_cast<size_t>(candidate->sdp_mline_index());
12095976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  size_t remote_content_size =
12105976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      BaseSession::remote_description()->contents().size();
12115976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (mediacontent_index >= remote_content_size) {
12125976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    LOG(LS_ERROR)
12135976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org        << "UseRemoteCandidateInSession: Invalid candidate media index.";
12145976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return false;
12155976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
12165976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
12175976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  cricket::ContentInfo content =
12185976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      BaseSession::remote_description()->contents()[mediacontent_index];
12195976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  std::vector<cricket::Candidate> candidates;
12205976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  candidates.push_back(candidate->candidate());
12215976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  // Invoking BaseSession method to handle remote candidates.
12225976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  std::string error;
12235976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (OnRemoteCandidates(content.name, candidates, &error)) {
12245976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    // Candidates successfully submitted for checking.
12255976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    if (ice_connection_state_ == PeerConnectionInterface::kIceConnectionNew ||
12265976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org        ice_connection_state_ ==
12275976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org            PeerConnectionInterface::kIceConnectionDisconnected) {
12285976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      // If state is New, then the session has just gotten its first remote ICE
12295976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      // candidates, so go to Checking.
12305976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      // If state is Disconnected, the session is re-using old candidates or
12315976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      // receiving additional ones, so go to Checking.
12325976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      // If state is Connected, stay Connected.
12335976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      // TODO(bemasc): If state is Connected, and the new candidates are for a
12345976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      // newly added transport, then the state actually _should_ move to
12355976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      // checking.  Add a way to distinguish that case.
12365976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      SetIceConnectionState(PeerConnectionInterface::kIceConnectionChecking);
12375976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    }
12385976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    // TODO(bemasc): If state is Completed, go back to Connected.
12395976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  } else {
12405976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    LOG(LS_WARNING) << error;
12415976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
12425976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return true;
12435976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
12445976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
12455976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid WebRtcSession::RemoveUnusedChannelsAndTransports(
12465976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    const SessionDescription* desc) {
12475976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  const cricket::ContentInfo* voice_info =
12485976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      cricket::GetFirstAudioContent(desc);
12495976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if ((!voice_info || voice_info->rejected) && voice_channel_) {
12505976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    mediastream_signaling_->OnAudioChannelClose();
12515976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    SignalVoiceChannelDestroyed();
12525976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    const std::string content_name = voice_channel_->content_name();
12535976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    channel_manager_->DestroyVoiceChannel(voice_channel_.release());
12545976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    DestroyTransportProxy(content_name);
12555976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
12565976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
12575976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  const cricket::ContentInfo* video_info =
12585976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      cricket::GetFirstVideoContent(desc);
12595976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if ((!video_info || video_info->rejected) && video_channel_) {
12605976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    mediastream_signaling_->OnVideoChannelClose();
12615976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    SignalVideoChannelDestroyed();
12625976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    const std::string content_name = video_channel_->content_name();
12635976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    channel_manager_->DestroyVideoChannel(video_channel_.release());
12645976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    DestroyTransportProxy(content_name);
12655976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
12665976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
12675976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  const cricket::ContentInfo* data_info =
12685976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      cricket::GetFirstDataContent(desc);
12695976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if ((!data_info || data_info->rejected) && data_channel_) {
12705976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    mediastream_signaling_->OnDataChannelClose();
12715976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    SignalDataChannelDestroyed();
12725976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    const std::string content_name = data_channel_->content_name();
12735976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    channel_manager_->DestroyDataChannel(data_channel_.release());
12745976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    DestroyTransportProxy(content_name);
12755976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
12765976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
12775976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
1278c1c67e5a722135af4ca83ee4c7d2dbe3f26bae70henrike@webrtc.org// TODO(mallinath) - Add a correct error code if the channels are not creatued
1279c1c67e5a722135af4ca83ee4c7d2dbe3f26bae70henrike@webrtc.org// due to BUNDLE is enabled but rtcp-mux is disabled.
12805976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgbool WebRtcSession::CreateChannels(const SessionDescription* desc) {
12815976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  // Disabling the BUNDLE flag in PortAllocator if offer disabled it.
1282c1c67e5a722135af4ca83ee4c7d2dbe3f26bae70henrike@webrtc.org  bool bundle_enabled = desc->HasGroup(cricket::GROUP_TYPE_BUNDLE);
1283c1c67e5a722135af4ca83ee4c7d2dbe3f26bae70henrike@webrtc.org  if (state() == STATE_INIT && !bundle_enabled) {
12845976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    port_allocator()->set_flags(port_allocator()->flags() &
12855976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                                ~cricket::PORTALLOCATOR_ENABLE_BUNDLE);
12865976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
12875976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
12885976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  // Creating the media channels and transport proxies.
12895976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  const cricket::ContentInfo* voice = cricket::GetFirstAudioContent(desc);
12905976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (voice && !voice->rejected && !voice_channel_) {
1291c1c67e5a722135af4ca83ee4c7d2dbe3f26bae70henrike@webrtc.org    if (!CreateVoiceChannel(voice)) {
12925976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      LOG(LS_ERROR) << "Failed to create voice channel.";
12935976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      return false;
12945976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    }
12955976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
12965976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
12975976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  const cricket::ContentInfo* video = cricket::GetFirstVideoContent(desc);
12985976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (video && !video->rejected && !video_channel_) {
1299c1c67e5a722135af4ca83ee4c7d2dbe3f26bae70henrike@webrtc.org    if (!CreateVideoChannel(video)) {
13005976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      LOG(LS_ERROR) << "Failed to create video channel.";
13015976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      return false;
13025976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    }
13035976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
13045976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
13055976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  const cricket::ContentInfo* data = cricket::GetFirstDataContent(desc);
13065976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (data_channel_type_ != cricket::DCT_NONE &&
13075976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      data && !data->rejected && !data_channel_.get()) {
1308c1c67e5a722135af4ca83ee4c7d2dbe3f26bae70henrike@webrtc.org    if (!CreateDataChannel(data)) {
13095976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      LOG(LS_ERROR) << "Failed to create data channel.";
13105976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      return false;
13115976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    }
13125976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
13135976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
13145976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return true;
13155976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
13165976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
1317c1c67e5a722135af4ca83ee4c7d2dbe3f26bae70henrike@webrtc.orgbool WebRtcSession::CreateVoiceChannel(const cricket::ContentInfo* content) {
13185976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  voice_channel_.reset(channel_manager_->CreateVoiceChannel(
1319c1c67e5a722135af4ca83ee4c7d2dbe3f26bae70henrike@webrtc.org      this, content->name, true));
1320c1c67e5a722135af4ca83ee4c7d2dbe3f26bae70henrike@webrtc.org  return (voice_channel_ != NULL);
13215976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
13225976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
1323c1c67e5a722135af4ca83ee4c7d2dbe3f26bae70henrike@webrtc.orgbool WebRtcSession::CreateVideoChannel(const cricket::ContentInfo* content) {
13245976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  video_channel_.reset(channel_manager_->CreateVideoChannel(
1325c1c67e5a722135af4ca83ee4c7d2dbe3f26bae70henrike@webrtc.org      this, content->name, true, voice_channel_.get()));
1326c1c67e5a722135af4ca83ee4c7d2dbe3f26bae70henrike@webrtc.org  return (video_channel_ != NULL);
13275976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
13285976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
1329c1c67e5a722135af4ca83ee4c7d2dbe3f26bae70henrike@webrtc.orgbool WebRtcSession::CreateDataChannel(const cricket::ContentInfo* content) {
13305976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  bool rtcp = (data_channel_type_ == cricket::DCT_RTP);
13315976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  data_channel_.reset(channel_manager_->CreateDataChannel(
1332e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org      this, content->name, rtcp, data_channel_type_));
1333e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org  if (!data_channel_.get()) {
1334e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org    return false;
1335e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org  }
1336e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org  data_channel_->SignalDataReceived.connect(
1337e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org      this, &WebRtcSession::OnDataReceived);
1338e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org  return true;
13395976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
13405976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
13415976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid WebRtcSession::CopySavedCandidates(
13425976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    SessionDescriptionInterface* dest_desc) {
13435976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (!dest_desc) {
13445976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    ASSERT(false);
13455976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return;
13465976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
13475976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  for (size_t i = 0; i < saved_candidates_.size(); ++i) {
13485976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    dest_desc->AddCandidate(saved_candidates_[i]);
13495976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    delete saved_candidates_[i];
13505976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
13515976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  saved_candidates_.clear();
13525976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
13535976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
1354e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org// Look for OPEN messages and set up data channels in response.
1355e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.orgvoid WebRtcSession::OnDataReceived(
1356e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org    cricket::DataChannel* channel,
1357e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org    const cricket::ReceiveDataParams& params,
1358e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org    const talk_base::Buffer& payload) {
1359e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org  if (params.type != cricket::DMT_CONTROL) {
13605976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return;
13615976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
13625976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
1363e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org  std::string label;
1364e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org  DataChannelInit config;
1365e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org  if (!mediastream_signaling_->ParseDataChannelOpenMessage(
1366e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org          payload, &label, &config)) {
1367e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org    LOG(LS_WARNING) << "Failed to parse data channel OPEN message.";
1368e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org    return;
1369e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org  }
1370e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org
1371e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org  config.negotiated = true;  // This is the negotiation.
1372e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org
1373e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org  if (!mediastream_signaling_->AddDataChannelFromOpenMessage(
1374e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org          label, config)) {
1375e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org    LOG(LS_WARNING) << "Failed to create data channel from OPEN message.";
1376e6781b6279d20210a5050a3e55e9c7effd3b144ewu@webrtc.org    return;
13775976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
13785976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
13795976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
1380c1c67e5a722135af4ca83ee4c7d2dbe3f26bae70henrike@webrtc.org// Returns false if bundle is enabled and rtcp_mux is disabled.
1381c1c67e5a722135af4ca83ee4c7d2dbe3f26bae70henrike@webrtc.orgbool WebRtcSession::VerifyBundleSettings(const SessionDescription* desc) {
1382c1c67e5a722135af4ca83ee4c7d2dbe3f26bae70henrike@webrtc.org  bool bundle_enabled = desc->HasGroup(cricket::GROUP_TYPE_BUNDLE);
1383c1c67e5a722135af4ca83ee4c7d2dbe3f26bae70henrike@webrtc.org  if (!bundle_enabled)
1384c1c67e5a722135af4ca83ee4c7d2dbe3f26bae70henrike@webrtc.org    return true;
1385c1c67e5a722135af4ca83ee4c7d2dbe3f26bae70henrike@webrtc.org
1386c1c67e5a722135af4ca83ee4c7d2dbe3f26bae70henrike@webrtc.org  const cricket::ContentGroup* bundle_group =
1387c1c67e5a722135af4ca83ee4c7d2dbe3f26bae70henrike@webrtc.org      desc->GetGroupByName(cricket::GROUP_TYPE_BUNDLE);
1388c1c67e5a722135af4ca83ee4c7d2dbe3f26bae70henrike@webrtc.org  ASSERT(bundle_group != NULL);
1389c1c67e5a722135af4ca83ee4c7d2dbe3f26bae70henrike@webrtc.org
1390c1c67e5a722135af4ca83ee4c7d2dbe3f26bae70henrike@webrtc.org  const cricket::ContentInfos& contents = desc->contents();
1391c1c67e5a722135af4ca83ee4c7d2dbe3f26bae70henrike@webrtc.org  for (cricket::ContentInfos::const_iterator citer = contents.begin();
1392c1c67e5a722135af4ca83ee4c7d2dbe3f26bae70henrike@webrtc.org       citer != contents.end(); ++citer) {
1393c1c67e5a722135af4ca83ee4c7d2dbe3f26bae70henrike@webrtc.org    const cricket::ContentInfo* content = (&*citer);
1394c1c67e5a722135af4ca83ee4c7d2dbe3f26bae70henrike@webrtc.org    ASSERT(content != NULL);
1395c1c67e5a722135af4ca83ee4c7d2dbe3f26bae70henrike@webrtc.org    if (bundle_group->HasContentName(content->name) &&
1396c1c67e5a722135af4ca83ee4c7d2dbe3f26bae70henrike@webrtc.org        !content->rejected && content->type == cricket::NS_JINGLE_RTP) {
1397c1c67e5a722135af4ca83ee4c7d2dbe3f26bae70henrike@webrtc.org      if (!HasRtcpMuxEnabled(content))
1398c1c67e5a722135af4ca83ee4c7d2dbe3f26bae70henrike@webrtc.org        return false;
1399c1c67e5a722135af4ca83ee4c7d2dbe3f26bae70henrike@webrtc.org    }
1400c1c67e5a722135af4ca83ee4c7d2dbe3f26bae70henrike@webrtc.org  }
1401c1c67e5a722135af4ca83ee4c7d2dbe3f26bae70henrike@webrtc.org  // RTCP-MUX is enabled in all the contents.
1402c1c67e5a722135af4ca83ee4c7d2dbe3f26bae70henrike@webrtc.org  return true;
1403c1c67e5a722135af4ca83ee4c7d2dbe3f26bae70henrike@webrtc.org}
1404c1c67e5a722135af4ca83ee4c7d2dbe3f26bae70henrike@webrtc.org
1405c1c67e5a722135af4ca83ee4c7d2dbe3f26bae70henrike@webrtc.orgbool WebRtcSession::HasRtcpMuxEnabled(
1406c1c67e5a722135af4ca83ee4c7d2dbe3f26bae70henrike@webrtc.org    const cricket::ContentInfo* content) {
1407c1c67e5a722135af4ca83ee4c7d2dbe3f26bae70henrike@webrtc.org  const cricket::MediaContentDescription* description =
1408c1c67e5a722135af4ca83ee4c7d2dbe3f26bae70henrike@webrtc.org      static_cast<cricket::MediaContentDescription*>(content->description);
1409c1c67e5a722135af4ca83ee4c7d2dbe3f26bae70henrike@webrtc.org  return description->rtcp_mux();
1410c1c67e5a722135af4ca83ee4c7d2dbe3f26bae70henrike@webrtc.org}
1411c1c67e5a722135af4ca83ee4c7d2dbe3f26bae70henrike@webrtc.org
14125976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}  // namespace webrtc
1413