Home | History | Annotate | Download | only in webrtc
      1 /*
      2  * libjingle
      3  * Copyright 2012 Google Inc.
      4  *
      5  * Redistribution and use in source and binary forms, with or without
      6  * modification, are permitted provided that the following conditions are met:
      7  *
      8  *  1. Redistributions of source code must retain the above copyright notice,
      9  *     this list of conditions and the following disclaimer.
     10  *  2. Redistributions in binary form must reproduce the above copyright notice,
     11  *     this list of conditions and the following disclaimer in the documentation
     12  *     and/or other materials provided with the distribution.
     13  *  3. The name of the author may not be used to endorse or promote products
     14  *     derived from this software without specific prior written permission.
     15  *
     16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
     17  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
     18  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
     19  * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     20  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     21  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
     22  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
     23  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
     24  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
     25  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     26  */
     27 
     28 #include "talk/app/webrtc/webrtcsession.h"
     29 
     30 #include <limits.h>
     31 
     32 #include <algorithm>
     33 #include <set>
     34 #include <utility>
     35 #include <vector>
     36 
     37 #include "talk/app/webrtc/jsepicecandidate.h"
     38 #include "talk/app/webrtc/jsepsessiondescription.h"
     39 #include "talk/app/webrtc/mediaconstraintsinterface.h"
     40 #include "talk/app/webrtc/peerconnectioninterface.h"
     41 #include "talk/app/webrtc/sctputils.h"
     42 #include "talk/app/webrtc/webrtcsessiondescriptionfactory.h"
     43 #include "talk/media/base/constants.h"
     44 #include "talk/media/base/videocapturer.h"
     45 #include "talk/session/media/channel.h"
     46 #include "talk/session/media/channelmanager.h"
     47 #include "talk/session/media/mediasession.h"
     48 #include "webrtc/audio/audio_sink.h"
     49 #include "webrtc/base/basictypes.h"
     50 #include "webrtc/base/checks.h"
     51 #include "webrtc/base/helpers.h"
     52 #include "webrtc/base/logging.h"
     53 #include "webrtc/base/stringencode.h"
     54 #include "webrtc/base/stringutils.h"
     55 #include "webrtc/call.h"
     56 #include "webrtc/p2p/base/portallocator.h"
     57 #include "webrtc/p2p/base/transportchannel.h"
     58 
     59 using cricket::ContentInfo;
     60 using cricket::ContentInfos;
     61 using cricket::MediaContentDescription;
     62 using cricket::SessionDescription;
     63 using cricket::TransportInfo;
     64 
     65 using cricket::LOCAL_PORT_TYPE;
     66 using cricket::STUN_PORT_TYPE;
     67 using cricket::RELAY_PORT_TYPE;
     68 using cricket::PRFLX_PORT_TYPE;
     69 
     70 namespace webrtc {
     71 
     72 // Error messages
     73 const char kBundleWithoutRtcpMux[] = "RTCP-MUX must be enabled when BUNDLE "
     74                                      "is enabled.";
     75 const char kCreateChannelFailed[] = "Failed to create channels.";
     76 const char kInvalidCandidates[] = "Description contains invalid candidates.";
     77 const char kInvalidSdp[] = "Invalid session description.";
     78 const char kMlineMismatch[] =
     79     "Offer and answer descriptions m-lines are not matching. Rejecting answer.";
     80 const char kPushDownTDFailed[] =
     81     "Failed to push down transport description:";
     82 const char kSdpWithoutDtlsFingerprint[] =
     83     "Called with SDP without DTLS fingerprint.";
     84 const char kSdpWithoutSdesCrypto[] =
     85     "Called with SDP without SDES crypto.";
     86 const char kSdpWithoutIceUfragPwd[] =
     87     "Called with SDP without ice-ufrag and ice-pwd.";
     88 const char kSessionError[] = "Session error code: ";
     89 const char kSessionErrorDesc[] = "Session error description: ";
     90 const char kDtlsSetupFailureRtp[] =
     91     "Couldn't set up DTLS-SRTP on RTP channel.";
     92 const char kDtlsSetupFailureRtcp[] =
     93     "Couldn't set up DTLS-SRTP on RTCP channel.";
     94 const char kEnableBundleFailed[] = "Failed to enable BUNDLE.";
     95 const int kMaxUnsignalledRecvStreams = 20;
     96 
     97 IceCandidatePairType GetIceCandidatePairCounter(
     98     const cricket::Candidate& local,
     99     const cricket::Candidate& remote) {
    100   const auto& l = local.type();
    101   const auto& r = remote.type();
    102   const auto& host = LOCAL_PORT_TYPE;
    103   const auto& srflx = STUN_PORT_TYPE;
    104   const auto& relay = RELAY_PORT_TYPE;
    105   const auto& prflx = PRFLX_PORT_TYPE;
    106   if (l == host && r == host) {
    107     bool local_private = IPIsPrivate(local.address().ipaddr());
    108     bool remote_private = IPIsPrivate(remote.address().ipaddr());
    109     if (local_private) {
    110       if (remote_private) {
    111         return kIceCandidatePairHostPrivateHostPrivate;
    112       } else {
    113         return kIceCandidatePairHostPrivateHostPublic;
    114       }
    115     } else {
    116       if (remote_private) {
    117         return kIceCandidatePairHostPublicHostPrivate;
    118       } else {
    119         return kIceCandidatePairHostPublicHostPublic;
    120       }
    121     }
    122   }
    123   if (l == host && r == srflx)
    124     return kIceCandidatePairHostSrflx;
    125   if (l == host && r == relay)
    126     return kIceCandidatePairHostRelay;
    127   if (l == host && r == prflx)
    128     return kIceCandidatePairHostPrflx;
    129   if (l == srflx && r == host)
    130     return kIceCandidatePairSrflxHost;
    131   if (l == srflx && r == srflx)
    132     return kIceCandidatePairSrflxSrflx;
    133   if (l == srflx && r == relay)
    134     return kIceCandidatePairSrflxRelay;
    135   if (l == srflx && r == prflx)
    136     return kIceCandidatePairSrflxPrflx;
    137   if (l == relay && r == host)
    138     return kIceCandidatePairRelayHost;
    139   if (l == relay && r == srflx)
    140     return kIceCandidatePairRelaySrflx;
    141   if (l == relay && r == relay)
    142     return kIceCandidatePairRelayRelay;
    143   if (l == relay && r == prflx)
    144     return kIceCandidatePairRelayPrflx;
    145   if (l == prflx && r == host)
    146     return kIceCandidatePairPrflxHost;
    147   if (l == prflx && r == srflx)
    148     return kIceCandidatePairPrflxSrflx;
    149   if (l == prflx && r == relay)
    150     return kIceCandidatePairPrflxRelay;
    151   return kIceCandidatePairMax;
    152 }
    153 
    154 // Compares |answer| against |offer|. Comparision is done
    155 // for number of m-lines in answer against offer. If matches true will be
    156 // returned otherwise false.
    157 static bool VerifyMediaDescriptions(
    158     const SessionDescription* answer, const SessionDescription* offer) {
    159   if (offer->contents().size() != answer->contents().size())
    160     return false;
    161 
    162   for (size_t i = 0; i < offer->contents().size(); ++i) {
    163     if ((offer->contents()[i].name) != answer->contents()[i].name) {
    164       return false;
    165     }
    166     const MediaContentDescription* offer_mdesc =
    167         static_cast<const MediaContentDescription*>(
    168             offer->contents()[i].description);
    169     const MediaContentDescription* answer_mdesc =
    170         static_cast<const MediaContentDescription*>(
    171             answer->contents()[i].description);
    172     if (offer_mdesc->type() != answer_mdesc->type()) {
    173       return false;
    174     }
    175   }
    176   return true;
    177 }
    178 
    179 // Checks that each non-rejected content has SDES crypto keys or a DTLS
    180 // fingerprint. Mismatches, such as replying with a DTLS fingerprint to SDES
    181 // keys, will be caught in Transport negotiation, and backstopped by Channel's
    182 // |secure_required| check.
    183 static bool VerifyCrypto(const SessionDescription* desc,
    184                          bool dtls_enabled,
    185                          std::string* error) {
    186   const ContentInfos& contents = desc->contents();
    187   for (size_t index = 0; index < contents.size(); ++index) {
    188     const ContentInfo* cinfo = &contents[index];
    189     if (cinfo->rejected) {
    190       continue;
    191     }
    192 
    193     // If the content isn't rejected, crypto must be present.
    194     const MediaContentDescription* media =
    195         static_cast<const MediaContentDescription*>(cinfo->description);
    196     const TransportInfo* tinfo = desc->GetTransportInfoByName(cinfo->name);
    197     if (!media || !tinfo) {
    198       // Something is not right.
    199       LOG(LS_ERROR) << kInvalidSdp;
    200       *error = kInvalidSdp;
    201       return false;
    202     }
    203     if (dtls_enabled) {
    204       if (!tinfo->description.identity_fingerprint) {
    205         LOG(LS_WARNING) <<
    206             "Session description must have DTLS fingerprint if DTLS enabled.";
    207         *error = kSdpWithoutDtlsFingerprint;
    208         return false;
    209       }
    210     } else {
    211       if (media->cryptos().empty()) {
    212         LOG(LS_WARNING) <<
    213             "Session description must have SDES when DTLS disabled.";
    214         *error = kSdpWithoutSdesCrypto;
    215         return false;
    216       }
    217     }
    218   }
    219 
    220   return true;
    221 }
    222 
    223 // Checks that each non-rejected content has ice-ufrag and ice-pwd set.
    224 static bool VerifyIceUfragPwdPresent(const SessionDescription* desc) {
    225   const ContentInfos& contents = desc->contents();
    226   for (size_t index = 0; index < contents.size(); ++index) {
    227     const ContentInfo* cinfo = &contents[index];
    228     if (cinfo->rejected) {
    229       continue;
    230     }
    231 
    232     // If the content isn't rejected, ice-ufrag and ice-pwd must be present.
    233     const TransportInfo* tinfo = desc->GetTransportInfoByName(cinfo->name);
    234     if (!tinfo) {
    235       // Something is not right.
    236       LOG(LS_ERROR) << kInvalidSdp;
    237       return false;
    238     }
    239     if (tinfo->description.ice_ufrag.empty() ||
    240         tinfo->description.ice_pwd.empty()) {
    241       LOG(LS_ERROR) << "Session description must have ice ufrag and pwd.";
    242       return false;
    243     }
    244   }
    245   return true;
    246 }
    247 
    248 // Forces |sdesc->crypto_required| to the appropriate state based on the
    249 // current security policy, to ensure a failure occurs if there is an error
    250 // in crypto negotiation.
    251 // Called when processing the local session description.
    252 static void UpdateSessionDescriptionSecurePolicy(cricket::CryptoType type,
    253                                                  SessionDescription* sdesc) {
    254   if (!sdesc) {
    255     return;
    256   }
    257 
    258   // Updating the |crypto_required_| in MediaContentDescription to the
    259   // appropriate state based on the current security policy.
    260   for (cricket::ContentInfos::iterator iter = sdesc->contents().begin();
    261        iter != sdesc->contents().end(); ++iter) {
    262     if (cricket::IsMediaContent(&*iter)) {
    263       MediaContentDescription* mdesc =
    264           static_cast<MediaContentDescription*> (iter->description);
    265       if (mdesc) {
    266         mdesc->set_crypto_required(type);
    267       }
    268     }
    269   }
    270 }
    271 
    272 static bool GetAudioSsrcByTrackId(const SessionDescription* session_description,
    273                                   const std::string& track_id,
    274                                   uint32_t* ssrc) {
    275   const cricket::ContentInfo* audio_info =
    276       cricket::GetFirstAudioContent(session_description);
    277   if (!audio_info) {
    278     LOG(LS_ERROR) << "Audio not used in this call";
    279     return false;
    280   }
    281 
    282   const cricket::MediaContentDescription* audio_content =
    283       static_cast<const cricket::MediaContentDescription*>(
    284           audio_info->description);
    285   const cricket::StreamParams* stream =
    286       cricket::GetStreamByIds(audio_content->streams(), "", track_id);
    287   if (!stream) {
    288     return false;
    289   }
    290 
    291   *ssrc = stream->first_ssrc();
    292   return true;
    293 }
    294 
    295 static bool GetTrackIdBySsrc(const SessionDescription* session_description,
    296                              uint32_t ssrc,
    297                              std::string* track_id) {
    298   ASSERT(track_id != NULL);
    299 
    300   const cricket::ContentInfo* audio_info =
    301       cricket::GetFirstAudioContent(session_description);
    302   if (audio_info) {
    303     const cricket::MediaContentDescription* audio_content =
    304         static_cast<const cricket::MediaContentDescription*>(
    305             audio_info->description);
    306 
    307     const auto* found =
    308         cricket::GetStreamBySsrc(audio_content->streams(), ssrc);
    309     if (found) {
    310       *track_id = found->id;
    311       return true;
    312     }
    313   }
    314 
    315   const cricket::ContentInfo* video_info =
    316       cricket::GetFirstVideoContent(session_description);
    317   if (video_info) {
    318     const cricket::MediaContentDescription* video_content =
    319         static_cast<const cricket::MediaContentDescription*>(
    320             video_info->description);
    321 
    322     const auto* found =
    323         cricket::GetStreamBySsrc(video_content->streams(), ssrc);
    324     if (found) {
    325       *track_id = found->id;
    326       return true;
    327     }
    328   }
    329   return false;
    330 }
    331 
    332 static bool BadSdp(const std::string& source,
    333                    const std::string& type,
    334                    const std::string& reason,
    335                    std::string* err_desc) {
    336   std::ostringstream desc;
    337   desc << "Failed to set " << source;
    338   if (!type.empty()) {
    339     desc << " " << type;
    340   }
    341   desc << " sdp: " << reason;
    342 
    343   if (err_desc) {
    344     *err_desc = desc.str();
    345   }
    346   LOG(LS_ERROR) << desc.str();
    347   return false;
    348 }
    349 
    350 static bool BadSdp(cricket::ContentSource source,
    351                    const std::string& type,
    352                    const std::string& reason,
    353                    std::string* err_desc) {
    354   if (source == cricket::CS_LOCAL) {
    355     return BadSdp("local", type, reason, err_desc);
    356   } else {
    357     return BadSdp("remote", type, reason, err_desc);
    358   }
    359 }
    360 
    361 static bool BadLocalSdp(const std::string& type,
    362                         const std::string& reason,
    363                         std::string* err_desc) {
    364   return BadSdp(cricket::CS_LOCAL, type, reason, err_desc);
    365 }
    366 
    367 static bool BadRemoteSdp(const std::string& type,
    368                          const std::string& reason,
    369                          std::string* err_desc) {
    370   return BadSdp(cricket::CS_REMOTE, type, reason, err_desc);
    371 }
    372 
    373 static bool BadOfferSdp(cricket::ContentSource source,
    374                         const std::string& reason,
    375                         std::string* err_desc) {
    376   return BadSdp(source, SessionDescriptionInterface::kOffer, reason, err_desc);
    377 }
    378 
    379 static bool BadPranswerSdp(cricket::ContentSource source,
    380                            const std::string& reason,
    381                            std::string* err_desc) {
    382   return BadSdp(source, SessionDescriptionInterface::kPrAnswer,
    383                 reason, err_desc);
    384 }
    385 
    386 static bool BadAnswerSdp(cricket::ContentSource source,
    387                          const std::string& reason,
    388                          std::string* err_desc) {
    389   return BadSdp(source, SessionDescriptionInterface::kAnswer, reason, err_desc);
    390 }
    391 
    392 #define GET_STRING_OF_STATE(state)   \
    393   case webrtc::WebRtcSession::state: \
    394     result = #state;                 \
    395     break;
    396 
    397 static std::string GetStateString(webrtc::WebRtcSession::State state) {
    398   std::string result;
    399   switch (state) {
    400     GET_STRING_OF_STATE(STATE_INIT)
    401     GET_STRING_OF_STATE(STATE_SENTOFFER)
    402     GET_STRING_OF_STATE(STATE_RECEIVEDOFFER)
    403     GET_STRING_OF_STATE(STATE_SENTPRANSWER)
    404     GET_STRING_OF_STATE(STATE_RECEIVEDPRANSWER)
    405     GET_STRING_OF_STATE(STATE_INPROGRESS)
    406     GET_STRING_OF_STATE(STATE_CLOSED)
    407     default:
    408       ASSERT(false);
    409       break;
    410   }
    411   return result;
    412 }
    413 
    414 #define GET_STRING_OF_ERROR_CODE(err) \
    415   case webrtc::WebRtcSession::err:    \
    416     result = #err;                    \
    417     break;
    418 
    419 static std::string GetErrorCodeString(webrtc::WebRtcSession::Error err) {
    420   std::string result;
    421   switch (err) {
    422     GET_STRING_OF_ERROR_CODE(ERROR_NONE)
    423     GET_STRING_OF_ERROR_CODE(ERROR_CONTENT)
    424     GET_STRING_OF_ERROR_CODE(ERROR_TRANSPORT)
    425     default:
    426       RTC_DCHECK(false);
    427       break;
    428   }
    429   return result;
    430 }
    431 
    432 static std::string MakeErrorString(const std::string& error,
    433                                    const std::string& desc) {
    434   std::ostringstream ret;
    435   ret << error << " " << desc;
    436   return ret.str();
    437 }
    438 
    439 static std::string MakeTdErrorString(const std::string& desc) {
    440   return MakeErrorString(kPushDownTDFailed, desc);
    441 }
    442 
    443 // Set |option| to the highest-priority value of |key| in the optional
    444 // constraints if the key is found and has a valid value.
    445 template <typename T>
    446 static void SetOptionFromOptionalConstraint(
    447     const MediaConstraintsInterface* constraints,
    448     const std::string& key,
    449     rtc::Optional<T>* option) {
    450   if (!constraints) {
    451     return;
    452   }
    453   std::string string_value;
    454   T value;
    455   if (constraints->GetOptional().FindFirst(key, &string_value)) {
    456     if (rtc::FromString(string_value, &value)) {
    457       *option = rtc::Optional<T>(value);
    458     }
    459   }
    460 }
    461 
    462 uint32_t ConvertIceTransportTypeToCandidateFilter(
    463     PeerConnectionInterface::IceTransportsType type) {
    464   switch (type) {
    465     case PeerConnectionInterface::kNone:
    466         return cricket::CF_NONE;
    467     case PeerConnectionInterface::kRelay:
    468         return cricket::CF_RELAY;
    469     case PeerConnectionInterface::kNoHost:
    470         return (cricket::CF_ALL & ~cricket::CF_HOST);
    471     case PeerConnectionInterface::kAll:
    472         return cricket::CF_ALL;
    473     default: ASSERT(false);
    474   }
    475   return cricket::CF_NONE;
    476 }
    477 
    478 // Help class used to remember if a a remote peer has requested ice restart by
    479 // by sending a description with new ice ufrag and password.
    480 class IceRestartAnswerLatch {
    481  public:
    482   IceRestartAnswerLatch() : ice_restart_(false) { }
    483 
    484   // Returns true if CheckForRemoteIceRestart has been called with a new session
    485   // description where ice password and ufrag has changed since last time
    486   // Reset() was called.
    487   bool Get() const {
    488     return ice_restart_;
    489   }
    490 
    491   void Reset() {
    492     if (ice_restart_) {
    493       ice_restart_ = false;
    494     }
    495   }
    496 
    497   // This method has two purposes: 1. Return whether |new_desc| requests
    498   // an ICE restart (i.e., new ufrag/pwd). 2. If it requests an ICE restart
    499   // and it is an OFFER, remember this in |ice_restart_| so that the next
    500   // Local Answer will be created with new ufrag and pwd.
    501   bool CheckForRemoteIceRestart(const SessionDescriptionInterface* old_desc,
    502                                 const SessionDescriptionInterface* new_desc) {
    503     if (!old_desc) {
    504       return false;
    505     }
    506     const SessionDescription* new_sd = new_desc->description();
    507     const SessionDescription* old_sd = old_desc->description();
    508     const ContentInfos& contents = new_sd->contents();
    509     for (size_t index = 0; index < contents.size(); ++index) {
    510       const ContentInfo* cinfo = &contents[index];
    511       if (cinfo->rejected) {
    512         continue;
    513       }
    514       // If the content isn't rejected, check if ufrag and password has
    515       // changed.
    516       const cricket::TransportDescription* new_transport_desc =
    517           new_sd->GetTransportDescriptionByName(cinfo->name);
    518       const cricket::TransportDescription* old_transport_desc =
    519           old_sd->GetTransportDescriptionByName(cinfo->name);
    520       if (!new_transport_desc || !old_transport_desc) {
    521         // No transport description exist. This is not an ice restart.
    522         continue;
    523       }
    524       if (cricket::IceCredentialsChanged(old_transport_desc->ice_ufrag,
    525                                          old_transport_desc->ice_pwd,
    526                                          new_transport_desc->ice_ufrag,
    527                                          new_transport_desc->ice_pwd)) {
    528         LOG(LS_INFO) << "Remote peer request ice restart.";
    529         if (new_desc->type() == SessionDescriptionInterface::kOffer) {
    530           ice_restart_ = true;
    531         }
    532         return true;
    533       }
    534     }
    535     return false;
    536   }
    537 
    538  private:
    539   bool ice_restart_;
    540 };
    541 
    542 WebRtcSession::WebRtcSession(webrtc::MediaControllerInterface* media_controller,
    543                              rtc::Thread* signaling_thread,
    544                              rtc::Thread* worker_thread,
    545                              cricket::PortAllocator* port_allocator)
    546     : signaling_thread_(signaling_thread),
    547       worker_thread_(worker_thread),
    548       port_allocator_(port_allocator),
    549       // RFC 3264: The numeric value of the session id and version in the
    550       // o line MUST be representable with a "64 bit signed integer".
    551       // Due to this constraint session id |sid_| is max limited to LLONG_MAX.
    552       sid_(rtc::ToString(rtc::CreateRandomId64() & LLONG_MAX)),
    553       transport_controller_(new cricket::TransportController(signaling_thread,
    554                                                              worker_thread,
    555                                                              port_allocator)),
    556       media_controller_(media_controller),
    557       channel_manager_(media_controller_->channel_manager()),
    558       ice_observer_(NULL),
    559       ice_connection_state_(PeerConnectionInterface::kIceConnectionNew),
    560       ice_connection_receiving_(true),
    561       older_version_remote_peer_(false),
    562       dtls_enabled_(false),
    563       data_channel_type_(cricket::DCT_NONE),
    564       ice_restart_latch_(new IceRestartAnswerLatch),
    565       metrics_observer_(NULL) {
    566   transport_controller_->SetIceRole(cricket::ICEROLE_CONTROLLED);
    567   transport_controller_->SignalConnectionState.connect(
    568       this, &WebRtcSession::OnTransportControllerConnectionState);
    569   transport_controller_->SignalReceiving.connect(
    570       this, &WebRtcSession::OnTransportControllerReceiving);
    571   transport_controller_->SignalGatheringState.connect(
    572       this, &WebRtcSession::OnTransportControllerGatheringState);
    573   transport_controller_->SignalCandidatesGathered.connect(
    574       this, &WebRtcSession::OnTransportControllerCandidatesGathered);
    575 }
    576 
    577 WebRtcSession::~WebRtcSession() {
    578   ASSERT(signaling_thread()->IsCurrent());
    579   // Destroy video_channel_ first since it may have a pointer to the
    580   // voice_channel_.
    581   if (video_channel_) {
    582     SignalVideoChannelDestroyed();
    583     channel_manager_->DestroyVideoChannel(video_channel_.release());
    584   }
    585   if (voice_channel_) {
    586     SignalVoiceChannelDestroyed();
    587     channel_manager_->DestroyVoiceChannel(voice_channel_.release());
    588   }
    589   if (data_channel_) {
    590     SignalDataChannelDestroyed();
    591     channel_manager_->DestroyDataChannel(data_channel_.release());
    592   }
    593 
    594   LOG(LS_INFO) << "Session: " << id() << " is destroyed.";
    595 }
    596 
    597 bool WebRtcSession::Initialize(
    598     const PeerConnectionFactoryInterface::Options& options,
    599     const MediaConstraintsInterface* constraints,
    600     rtc::scoped_ptr<DtlsIdentityStoreInterface> dtls_identity_store,
    601     const PeerConnectionInterface::RTCConfiguration& rtc_configuration) {
    602   bundle_policy_ = rtc_configuration.bundle_policy;
    603   rtcp_mux_policy_ = rtc_configuration.rtcp_mux_policy;
    604   video_options_.disable_prerenderer_smoothing =
    605       rtc::Optional<bool>(rtc_configuration.disable_prerenderer_smoothing);
    606   transport_controller_->SetSslMaxProtocolVersion(options.ssl_max_version);
    607 
    608   // Obtain a certificate from RTCConfiguration if any were provided (optional).
    609   rtc::scoped_refptr<rtc::RTCCertificate> certificate;
    610   if (!rtc_configuration.certificates.empty()) {
    611     // TODO(hbos,torbjorng): Decide on certificate-selection strategy instead of
    612     // just picking the first one. The decision should be made based on the DTLS
    613     // handshake. The DTLS negotiations need to know about all certificates.
    614     certificate = rtc_configuration.certificates[0];
    615   }
    616 
    617   SetIceConfig(ParseIceConfig(rtc_configuration));
    618 
    619   // TODO(perkj): Take |constraints| into consideration. Return false if not all
    620   // mandatory constraints can be fulfilled. Note that |constraints|
    621   // can be null.
    622   bool value;
    623 
    624   if (options.disable_encryption) {
    625     dtls_enabled_ = false;
    626   } else {
    627     // Enable DTLS by default if we have an identity store or a certificate.
    628     dtls_enabled_ = (dtls_identity_store || certificate);
    629     // |constraints| can override the default |dtls_enabled_| value.
    630     if (FindConstraint(constraints, MediaConstraintsInterface::kEnableDtlsSrtp,
    631                        &value, nullptr)) {
    632       dtls_enabled_ = value;
    633     }
    634   }
    635 
    636   // Enable creation of RTP data channels if the kEnableRtpDataChannels is set.
    637   // It takes precendence over the disable_sctp_data_channels
    638   // PeerConnectionFactoryInterface::Options.
    639   if (FindConstraint(
    640       constraints, MediaConstraintsInterface::kEnableRtpDataChannels,
    641       &value, NULL) && value) {
    642     LOG(LS_INFO) << "Allowing RTP data engine.";
    643     data_channel_type_ = cricket::DCT_RTP;
    644   } else {
    645     // DTLS has to be enabled to use SCTP.
    646     if (!options.disable_sctp_data_channels && dtls_enabled_) {
    647       LOG(LS_INFO) << "Allowing SCTP data engine.";
    648       data_channel_type_ = cricket::DCT_SCTP;
    649     }
    650   }
    651 
    652   // Find DSCP constraint.
    653   if (FindConstraint(
    654         constraints,
    655         MediaConstraintsInterface::kEnableDscp,
    656         &value, NULL)) {
    657     audio_options_.dscp = rtc::Optional<bool>(value);
    658     video_options_.dscp = rtc::Optional<bool>(value);
    659   }
    660 
    661   // Find Suspend Below Min Bitrate constraint.
    662   if (FindConstraint(
    663           constraints,
    664           MediaConstraintsInterface::kEnableVideoSuspendBelowMinBitrate,
    665           &value,
    666           NULL)) {
    667     video_options_.suspend_below_min_bitrate = rtc::Optional<bool>(value);
    668   }
    669 
    670   SetOptionFromOptionalConstraint(constraints,
    671       MediaConstraintsInterface::kScreencastMinBitrate,
    672       &video_options_.screencast_min_bitrate);
    673 
    674   // Find constraints for cpu overuse detection.
    675   SetOptionFromOptionalConstraint(constraints,
    676       MediaConstraintsInterface::kCpuUnderuseThreshold,
    677       &video_options_.cpu_underuse_threshold);
    678   SetOptionFromOptionalConstraint(constraints,
    679       MediaConstraintsInterface::kCpuOveruseThreshold,
    680       &video_options_.cpu_overuse_threshold);
    681   SetOptionFromOptionalConstraint(constraints,
    682       MediaConstraintsInterface::kCpuOveruseDetection,
    683       &video_options_.cpu_overuse_detection);
    684   SetOptionFromOptionalConstraint(constraints,
    685       MediaConstraintsInterface::kCpuOveruseEncodeUsage,
    686       &video_options_.cpu_overuse_encode_usage);
    687   SetOptionFromOptionalConstraint(constraints,
    688       MediaConstraintsInterface::kCpuUnderuseEncodeRsdThreshold,
    689       &video_options_.cpu_underuse_encode_rsd_threshold);
    690   SetOptionFromOptionalConstraint(constraints,
    691       MediaConstraintsInterface::kCpuOveruseEncodeRsdThreshold,
    692       &video_options_.cpu_overuse_encode_rsd_threshold);
    693 
    694   SetOptionFromOptionalConstraint(constraints,
    695       MediaConstraintsInterface::kNumUnsignalledRecvStreams,
    696       &video_options_.unsignalled_recv_stream_limit);
    697   if (video_options_.unsignalled_recv_stream_limit) {
    698     video_options_.unsignalled_recv_stream_limit = rtc::Optional<int>(
    699         std::max(0, std::min(kMaxUnsignalledRecvStreams,
    700                              *video_options_.unsignalled_recv_stream_limit)));
    701   }
    702 
    703   SetOptionFromOptionalConstraint(constraints,
    704       MediaConstraintsInterface::kHighStartBitrate,
    705       &video_options_.video_start_bitrate);
    706 
    707   SetOptionFromOptionalConstraint(constraints,
    708       MediaConstraintsInterface::kCombinedAudioVideoBwe,
    709       &audio_options_.combined_audio_video_bwe);
    710 
    711   audio_options_.audio_jitter_buffer_max_packets =
    712       rtc::Optional<int>(rtc_configuration.audio_jitter_buffer_max_packets);
    713 
    714   audio_options_.audio_jitter_buffer_fast_accelerate = rtc::Optional<bool>(
    715       rtc_configuration.audio_jitter_buffer_fast_accelerate);
    716 
    717   if (!dtls_enabled_) {
    718     // Construct with DTLS disabled.
    719     webrtc_session_desc_factory_.reset(new WebRtcSessionDescriptionFactory(
    720         signaling_thread(), channel_manager_, this, id()));
    721   } else {
    722     // Construct with DTLS enabled.
    723     if (!certificate) {
    724       // Use the |dtls_identity_store| to generate a certificate.
    725       RTC_DCHECK(dtls_identity_store);
    726       webrtc_session_desc_factory_.reset(new WebRtcSessionDescriptionFactory(
    727           signaling_thread(), channel_manager_, std::move(dtls_identity_store),
    728           this, id()));
    729     } else {
    730       // Use the already generated certificate.
    731       webrtc_session_desc_factory_.reset(new WebRtcSessionDescriptionFactory(
    732           signaling_thread(), channel_manager_, certificate, this, id()));
    733     }
    734   }
    735 
    736   webrtc_session_desc_factory_->SignalCertificateReady.connect(
    737       this, &WebRtcSession::OnCertificateReady);
    738 
    739   if (options.disable_encryption) {
    740     webrtc_session_desc_factory_->SetSdesPolicy(cricket::SEC_DISABLED);
    741   }
    742   port_allocator()->set_candidate_filter(
    743       ConvertIceTransportTypeToCandidateFilter(rtc_configuration.type));
    744 
    745   return true;
    746 }
    747 
    748 void WebRtcSession::Close() {
    749   SetState(STATE_CLOSED);
    750   RemoveUnusedChannels(nullptr);
    751   ASSERT(!voice_channel_);
    752   ASSERT(!video_channel_);
    753   ASSERT(!data_channel_);
    754 }
    755 
    756 void WebRtcSession::SetSdesPolicy(cricket::SecurePolicy secure_policy) {
    757   webrtc_session_desc_factory_->SetSdesPolicy(secure_policy);
    758 }
    759 
    760 cricket::SecurePolicy WebRtcSession::SdesPolicy() const {
    761   return webrtc_session_desc_factory_->SdesPolicy();
    762 }
    763 
    764 bool WebRtcSession::GetSslRole(const std::string& transport_name,
    765                                rtc::SSLRole* role) {
    766   if (!local_desc_ || !remote_desc_) {
    767     LOG(LS_INFO) << "Local and Remote descriptions must be applied to get "
    768                  << "SSL Role of the session.";
    769     return false;
    770   }
    771 
    772   return transport_controller_->GetSslRole(transport_name, role);
    773 }
    774 
    775 bool WebRtcSession::GetSslRole(const cricket::BaseChannel* channel,
    776                                rtc::SSLRole* role) {
    777   return channel && GetSslRole(channel->transport_name(), role);
    778 }
    779 
    780 void WebRtcSession::CreateOffer(
    781     CreateSessionDescriptionObserver* observer,
    782     const PeerConnectionInterface::RTCOfferAnswerOptions& options,
    783     const cricket::MediaSessionOptions& session_options) {
    784   webrtc_session_desc_factory_->CreateOffer(observer, options, session_options);
    785 }
    786 
    787 void WebRtcSession::CreateAnswer(
    788     CreateSessionDescriptionObserver* observer,
    789     const MediaConstraintsInterface* constraints,
    790     const cricket::MediaSessionOptions& session_options) {
    791   webrtc_session_desc_factory_->CreateAnswer(observer, constraints,
    792                                              session_options);
    793 }
    794 
    795 bool WebRtcSession::SetLocalDescription(SessionDescriptionInterface* desc,
    796                                         std::string* err_desc) {
    797   ASSERT(signaling_thread()->IsCurrent());
    798 
    799   // Takes the ownership of |desc| regardless of the result.
    800   rtc::scoped_ptr<SessionDescriptionInterface> desc_temp(desc);
    801 
    802   // Validate SDP.
    803   if (!ValidateSessionDescription(desc, cricket::CS_LOCAL, err_desc)) {
    804     return false;
    805   }
    806 
    807   // Update the initial_offerer flag if this session is the initial_offerer.
    808   Action action = GetAction(desc->type());
    809   if (state() == STATE_INIT && action == kOffer) {
    810     initial_offerer_ = true;
    811     transport_controller_->SetIceRole(cricket::ICEROLE_CONTROLLING);
    812   }
    813 
    814   cricket::SecurePolicy sdes_policy =
    815       webrtc_session_desc_factory_->SdesPolicy();
    816   cricket::CryptoType crypto_required = dtls_enabled_ ?
    817       cricket::CT_DTLS : (sdes_policy == cricket::SEC_REQUIRED ?
    818           cricket::CT_SDES : cricket::CT_NONE);
    819   // Update the MediaContentDescription crypto settings as per the policy set.
    820   UpdateSessionDescriptionSecurePolicy(crypto_required, desc->description());
    821 
    822   local_desc_.reset(desc_temp.release());
    823 
    824   // Transport and Media channels will be created only when offer is set.
    825   if (action == kOffer && !CreateChannels(local_desc_->description())) {
    826     // TODO(mallinath) - Handle CreateChannel failure, as new local description
    827     // is applied. Restore back to old description.
    828     return BadLocalSdp(desc->type(), kCreateChannelFailed, err_desc);
    829   }
    830 
    831   // Remove unused channels if MediaContentDescription is rejected.
    832   RemoveUnusedChannels(local_desc_->description());
    833 
    834   if (!UpdateSessionState(action, cricket::CS_LOCAL, err_desc)) {
    835     return false;
    836   }
    837 
    838   if (remote_desc_) {
    839     // Now that we have a local description, we can push down remote candidates.
    840     UseCandidatesInSessionDescription(remote_desc_.get());
    841   }
    842 
    843   if (error() != ERROR_NONE) {
    844     return BadLocalSdp(desc->type(), GetSessionErrorMsg(), err_desc);
    845   }
    846   return true;
    847 }
    848 
    849 bool WebRtcSession::SetRemoteDescription(SessionDescriptionInterface* desc,
    850                                          std::string* err_desc) {
    851   ASSERT(signaling_thread()->IsCurrent());
    852 
    853   // Takes the ownership of |desc| regardless of the result.
    854   rtc::scoped_ptr<SessionDescriptionInterface> desc_temp(desc);
    855 
    856   // Validate SDP.
    857   if (!ValidateSessionDescription(desc, cricket::CS_REMOTE, err_desc)) {
    858     return false;
    859   }
    860 
    861   rtc::scoped_ptr<SessionDescriptionInterface> old_remote_desc(
    862       remote_desc_.release());
    863   remote_desc_.reset(desc_temp.release());
    864 
    865   // Transport and Media channels will be created only when offer is set.
    866   Action action = GetAction(desc->type());
    867   if (action == kOffer && !CreateChannels(desc->description())) {
    868     // TODO(mallinath) - Handle CreateChannel failure, as new local description
    869     // is applied. Restore back to old description.
    870     return BadRemoteSdp(desc->type(), kCreateChannelFailed, err_desc);
    871   }
    872 
    873   // Remove unused channels if MediaContentDescription is rejected.
    874   RemoveUnusedChannels(desc->description());
    875 
    876   // NOTE: Candidates allocation will be initiated only when SetLocalDescription
    877   // is called.
    878   if (!UpdateSessionState(action, cricket::CS_REMOTE, err_desc)) {
    879     return false;
    880   }
    881 
    882   if (local_desc_ && !UseCandidatesInSessionDescription(desc)) {
    883     return BadRemoteSdp(desc->type(), kInvalidCandidates, err_desc);
    884   }
    885 
    886   // Check if this new SessionDescription contains new ice ufrag and password
    887   // that indicates the remote peer requests ice restart.
    888   bool ice_restart =
    889       ice_restart_latch_->CheckForRemoteIceRestart(old_remote_desc.get(), desc);
    890   // We retain all received candidates only if ICE is not restarted.
    891   // When ICE is restarted, all previous candidates belong to an old generation
    892   // and should not be kept.
    893   // TODO(deadbeef): This goes against the W3C spec which says the remote
    894   // description should only contain candidates from the last set remote
    895   // description plus any candidates added since then. We should remove this
    896   // once we're sure it won't break anything.
    897   if (!ice_restart) {
    898     WebRtcSessionDescriptionFactory::CopyCandidatesFromSessionDescription(
    899         old_remote_desc.get(), desc);
    900   }
    901 
    902   if (error() != ERROR_NONE) {
    903     return BadRemoteSdp(desc->type(), GetSessionErrorMsg(), err_desc);
    904   }
    905 
    906   // Set the the ICE connection state to connecting since the connection may
    907   // become writable with peer reflexive candidates before any remote candidate
    908   // is signaled.
    909   // TODO(pthatcher): This is a short-term solution for crbug/446908. A real fix
    910   // is to have a new signal the indicates a change in checking state from the
    911   // transport and expose a new checking() member from transport that can be
    912   // read to determine the current checking state. The existing SignalConnecting
    913   // actually means "gathering candidates", so cannot be be used here.
    914   if (desc->type() != SessionDescriptionInterface::kOffer &&
    915       ice_connection_state_ == PeerConnectionInterface::kIceConnectionNew) {
    916     SetIceConnectionState(PeerConnectionInterface::kIceConnectionChecking);
    917   }
    918   return true;
    919 }
    920 
    921 void WebRtcSession::LogState(State old_state, State new_state) {
    922   LOG(LS_INFO) << "Session:" << id()
    923                << " Old state:" << GetStateString(old_state)
    924                << " New state:" << GetStateString(new_state);
    925 }
    926 
    927 void WebRtcSession::SetState(State state) {
    928   ASSERT(signaling_thread_->IsCurrent());
    929   if (state != state_) {
    930     LogState(state_, state);
    931     state_ = state;
    932     SignalState(this, state_);
    933   }
    934 }
    935 
    936 void WebRtcSession::SetError(Error error, const std::string& error_desc) {
    937   ASSERT(signaling_thread_->IsCurrent());
    938   if (error != error_) {
    939     error_ = error;
    940     error_desc_ = error_desc;
    941   }
    942 }
    943 
    944 bool WebRtcSession::UpdateSessionState(
    945     Action action, cricket::ContentSource source,
    946     std::string* err_desc) {
    947   ASSERT(signaling_thread()->IsCurrent());
    948 
    949   // If there's already a pending error then no state transition should happen.
    950   // But all call-sites should be verifying this before calling us!
    951   ASSERT(error() == ERROR_NONE);
    952   std::string td_err;
    953   if (action == kOffer) {
    954     if (!PushdownTransportDescription(source, cricket::CA_OFFER, &td_err)) {
    955       return BadOfferSdp(source, MakeTdErrorString(td_err), err_desc);
    956     }
    957     SetState(source == cricket::CS_LOCAL ? STATE_SENTOFFER
    958                                          : STATE_RECEIVEDOFFER);
    959     if (!PushdownMediaDescription(cricket::CA_OFFER, source, err_desc)) {
    960       SetError(ERROR_CONTENT, *err_desc);
    961     }
    962     if (error() != ERROR_NONE) {
    963       return BadOfferSdp(source, GetSessionErrorMsg(), err_desc);
    964     }
    965   } else if (action == kPrAnswer) {
    966     if (!PushdownTransportDescription(source, cricket::CA_PRANSWER, &td_err)) {
    967       return BadPranswerSdp(source, MakeTdErrorString(td_err), err_desc);
    968     }
    969     EnableChannels();
    970     SetState(source == cricket::CS_LOCAL ? STATE_SENTPRANSWER
    971                                          : STATE_RECEIVEDPRANSWER);
    972     if (!PushdownMediaDescription(cricket::CA_PRANSWER, source, err_desc)) {
    973       SetError(ERROR_CONTENT, *err_desc);
    974     }
    975     if (error() != ERROR_NONE) {
    976       return BadPranswerSdp(source, GetSessionErrorMsg(), err_desc);
    977     }
    978   } else if (action == kAnswer) {
    979     const cricket::ContentGroup* local_bundle =
    980         local_desc_->description()->GetGroupByName(cricket::GROUP_TYPE_BUNDLE);
    981     const cricket::ContentGroup* remote_bundle =
    982         remote_desc_->description()->GetGroupByName(cricket::GROUP_TYPE_BUNDLE);
    983     if (local_bundle && remote_bundle) {
    984       // The answerer decides the transport to bundle on.
    985       const cricket::ContentGroup* answer_bundle =
    986           (source == cricket::CS_LOCAL ? local_bundle : remote_bundle);
    987       if (!EnableBundle(*answer_bundle)) {
    988         LOG(LS_WARNING) << "Failed to enable BUNDLE.";
    989         return BadAnswerSdp(source, kEnableBundleFailed, err_desc);
    990       }
    991     }
    992     // Only push down the transport description after enabling BUNDLE; we don't
    993     // want to push down a description on a transport about to be destroyed.
    994     if (!PushdownTransportDescription(source, cricket::CA_ANSWER, &td_err)) {
    995       return BadAnswerSdp(source, MakeTdErrorString(td_err), err_desc);
    996     }
    997     EnableChannels();
    998     SetState(STATE_INPROGRESS);
    999     if (!PushdownMediaDescription(cricket::CA_ANSWER, source, err_desc)) {
   1000       SetError(ERROR_CONTENT, *err_desc);
   1001     }
   1002     if (error() != ERROR_NONE) {
   1003       return BadAnswerSdp(source, GetSessionErrorMsg(), err_desc);
   1004     }
   1005   }
   1006   return true;
   1007 }
   1008 
   1009 WebRtcSession::Action WebRtcSession::GetAction(const std::string& type) {
   1010   if (type == SessionDescriptionInterface::kOffer) {
   1011     return WebRtcSession::kOffer;
   1012   } else if (type == SessionDescriptionInterface::kPrAnswer) {
   1013     return WebRtcSession::kPrAnswer;
   1014   } else if (type == SessionDescriptionInterface::kAnswer) {
   1015     return WebRtcSession::kAnswer;
   1016   }
   1017   ASSERT(false && "unknown action type");
   1018   return WebRtcSession::kOffer;
   1019 }
   1020 
   1021 bool WebRtcSession::PushdownMediaDescription(
   1022     cricket::ContentAction action,
   1023     cricket::ContentSource source,
   1024     std::string* err) {
   1025   auto set_content = [this, action, source, err](cricket::BaseChannel* ch) {
   1026     if (!ch) {
   1027       return true;
   1028     } else if (source == cricket::CS_LOCAL) {
   1029       return ch->PushdownLocalDescription(local_desc_->description(), action,
   1030                                           err);
   1031     } else {
   1032       return ch->PushdownRemoteDescription(remote_desc_->description(), action,
   1033                                            err);
   1034     }
   1035   };
   1036 
   1037   return (set_content(voice_channel()) &&
   1038           set_content(video_channel()) &&
   1039           set_content(data_channel()));
   1040 }
   1041 
   1042 bool WebRtcSession::PushdownTransportDescription(cricket::ContentSource source,
   1043                                                  cricket::ContentAction action,
   1044                                                  std::string* error_desc) {
   1045   RTC_DCHECK(signaling_thread()->IsCurrent());
   1046 
   1047   if (source == cricket::CS_LOCAL) {
   1048     return PushdownLocalTransportDescription(local_desc_->description(), action,
   1049                                              error_desc);
   1050   }
   1051   return PushdownRemoteTransportDescription(remote_desc_->description(), action,
   1052                                             error_desc);
   1053 }
   1054 
   1055 bool WebRtcSession::PushdownLocalTransportDescription(
   1056     const SessionDescription* sdesc,
   1057     cricket::ContentAction action,
   1058     std::string* err) {
   1059   RTC_DCHECK(signaling_thread()->IsCurrent());
   1060 
   1061   if (!sdesc) {
   1062     return false;
   1063   }
   1064 
   1065   for (const TransportInfo& tinfo : sdesc->transport_infos()) {
   1066     if (!transport_controller_->SetLocalTransportDescription(
   1067             tinfo.content_name, tinfo.description, action, err)) {
   1068       return false;
   1069     }
   1070   }
   1071 
   1072   return true;
   1073 }
   1074 
   1075 bool WebRtcSession::PushdownRemoteTransportDescription(
   1076     const SessionDescription* sdesc,
   1077     cricket::ContentAction action,
   1078     std::string* err) {
   1079   RTC_DCHECK(signaling_thread()->IsCurrent());
   1080 
   1081   if (!sdesc) {
   1082     return false;
   1083   }
   1084 
   1085   for (const TransportInfo& tinfo : sdesc->transport_infos()) {
   1086     if (!transport_controller_->SetRemoteTransportDescription(
   1087             tinfo.content_name, tinfo.description, action, err)) {
   1088       return false;
   1089     }
   1090   }
   1091 
   1092   return true;
   1093 }
   1094 
   1095 bool WebRtcSession::GetTransportDescription(
   1096     const SessionDescription* description,
   1097     const std::string& content_name,
   1098     cricket::TransportDescription* tdesc) {
   1099   if (!description || !tdesc) {
   1100     return false;
   1101   }
   1102   const TransportInfo* transport_info =
   1103       description->GetTransportInfoByName(content_name);
   1104   if (!transport_info) {
   1105     return false;
   1106   }
   1107   *tdesc = transport_info->description;
   1108   return true;
   1109 }
   1110 
   1111 bool WebRtcSession::GetTransportStats(SessionStats* stats) {
   1112   ASSERT(signaling_thread()->IsCurrent());
   1113   return (GetChannelTransportStats(voice_channel(), stats) &&
   1114           GetChannelTransportStats(video_channel(), stats) &&
   1115           GetChannelTransportStats(data_channel(), stats));
   1116 }
   1117 
   1118 bool WebRtcSession::GetChannelTransportStats(cricket::BaseChannel* ch,
   1119                                              SessionStats* stats) {
   1120   ASSERT(signaling_thread()->IsCurrent());
   1121   if (!ch) {
   1122     // Not using this channel.
   1123     return true;
   1124   }
   1125 
   1126   const std::string& content_name = ch->content_name();
   1127   const std::string& transport_name = ch->transport_name();
   1128   stats->proxy_to_transport[content_name] = transport_name;
   1129   if (stats->transport_stats.find(transport_name) !=
   1130       stats->transport_stats.end()) {
   1131     // Transport stats already done for this transport.
   1132     return true;
   1133   }
   1134 
   1135   cricket::TransportStats tstats;
   1136   if (!transport_controller_->GetStats(transport_name, &tstats)) {
   1137     return false;
   1138   }
   1139 
   1140   stats->transport_stats[transport_name] = tstats;
   1141   return true;
   1142 }
   1143 
   1144 bool WebRtcSession::GetLocalCertificate(
   1145     const std::string& transport_name,
   1146     rtc::scoped_refptr<rtc::RTCCertificate>* certificate) {
   1147   ASSERT(signaling_thread()->IsCurrent());
   1148   return transport_controller_->GetLocalCertificate(transport_name,
   1149                                                     certificate);
   1150 }
   1151 
   1152 bool WebRtcSession::GetRemoteSSLCertificate(const std::string& transport_name,
   1153                                             rtc::SSLCertificate** cert) {
   1154   ASSERT(signaling_thread()->IsCurrent());
   1155   return transport_controller_->GetRemoteSSLCertificate(transport_name, cert);
   1156 }
   1157 
   1158 cricket::BaseChannel* WebRtcSession::GetChannel(
   1159     const std::string& content_name) {
   1160   if (voice_channel() && voice_channel()->content_name() == content_name) {
   1161     return voice_channel();
   1162   }
   1163   if (video_channel() && video_channel()->content_name() == content_name) {
   1164     return video_channel();
   1165   }
   1166   if (data_channel() && data_channel()->content_name() == content_name) {
   1167     return data_channel();
   1168   }
   1169   return nullptr;
   1170 }
   1171 
   1172 bool WebRtcSession::EnableBundle(const cricket::ContentGroup& bundle) {
   1173   const std::string* first_content_name = bundle.FirstContentName();
   1174   if (!first_content_name) {
   1175     LOG(LS_WARNING) << "Tried to BUNDLE with no contents.";
   1176     return false;
   1177   }
   1178   const std::string& transport_name = *first_content_name;
   1179   cricket::BaseChannel* first_channel = GetChannel(transport_name);
   1180 
   1181   auto maybe_set_transport = [this, bundle, transport_name,
   1182                               first_channel](cricket::BaseChannel* ch) {
   1183     if (!ch || !bundle.HasContentName(ch->content_name())) {
   1184       return true;
   1185     }
   1186 
   1187     if (ch->transport_name() == transport_name) {
   1188       LOG(LS_INFO) << "BUNDLE already enabled for " << ch->content_name()
   1189                    << " on " << transport_name << ".";
   1190       return true;
   1191     }
   1192 
   1193     if (!ch->SetTransport(transport_name)) {
   1194       LOG(LS_WARNING) << "Failed to enable BUNDLE for " << ch->content_name();
   1195       return false;
   1196     }
   1197     LOG(LS_INFO) << "Enabled BUNDLE for " << ch->content_name() << " on "
   1198                  << transport_name << ".";
   1199     return true;
   1200   };
   1201 
   1202   if (!maybe_set_transport(voice_channel()) ||
   1203       !maybe_set_transport(video_channel()) ||
   1204       !maybe_set_transport(data_channel())) {
   1205     return false;
   1206   }
   1207 
   1208   return true;
   1209 }
   1210 
   1211 bool WebRtcSession::ProcessIceMessage(const IceCandidateInterface* candidate) {
   1212   if (!remote_desc_) {
   1213     LOG(LS_ERROR) << "ProcessIceMessage: ICE candidates can't be added "
   1214                   << "without any remote session description.";
   1215      return false;
   1216   }
   1217 
   1218   if (!candidate) {
   1219     LOG(LS_ERROR) << "ProcessIceMessage: Candidate is NULL.";
   1220     return false;
   1221   }
   1222 
   1223   bool valid = false;
   1224   bool ready = ReadyToUseRemoteCandidate(candidate, NULL, &valid);
   1225   if (!valid) {
   1226     return false;
   1227   }
   1228 
   1229   // Add this candidate to the remote session description.
   1230   if (!remote_desc_->AddCandidate(candidate)) {
   1231     LOG(LS_ERROR) << "ProcessIceMessage: Candidate cannot be used.";
   1232     return false;
   1233   }
   1234 
   1235   if (ready) {
   1236     return UseCandidate(candidate);
   1237   } else {
   1238     LOG(LS_INFO) << "ProcessIceMessage: Not ready to use candidate.";
   1239     return true;
   1240   }
   1241 }
   1242 
   1243 bool WebRtcSession::SetIceTransports(
   1244     PeerConnectionInterface::IceTransportsType type) {
   1245   return port_allocator()->set_candidate_filter(
   1246         ConvertIceTransportTypeToCandidateFilter(type));
   1247 }
   1248 
   1249 cricket::IceConfig WebRtcSession::ParseIceConfig(
   1250     const PeerConnectionInterface::RTCConfiguration& config) const {
   1251   cricket::IceConfig ice_config;
   1252   ice_config.receiving_timeout_ms = config.ice_connection_receiving_timeout;
   1253   ice_config.backup_connection_ping_interval =
   1254       config.ice_backup_candidate_pair_ping_interval;
   1255   ice_config.gather_continually = (config.continual_gathering_policy ==
   1256                                    PeerConnectionInterface::GATHER_CONTINUALLY);
   1257   return ice_config;
   1258 }
   1259 
   1260 void WebRtcSession::SetIceConfig(const cricket::IceConfig& config) {
   1261   transport_controller_->SetIceConfig(config);
   1262 }
   1263 
   1264 void WebRtcSession::MaybeStartGathering() {
   1265   transport_controller_->MaybeStartGathering();
   1266 }
   1267 
   1268 bool WebRtcSession::GetLocalTrackIdBySsrc(uint32_t ssrc,
   1269                                           std::string* track_id) {
   1270   if (!local_desc_) {
   1271     return false;
   1272   }
   1273   return webrtc::GetTrackIdBySsrc(local_desc_->description(), ssrc, track_id);
   1274 }
   1275 
   1276 bool WebRtcSession::GetRemoteTrackIdBySsrc(uint32_t ssrc,
   1277                                            std::string* track_id) {
   1278   if (!remote_desc_) {
   1279     return false;
   1280   }
   1281   return webrtc::GetTrackIdBySsrc(remote_desc_->description(), ssrc, track_id);
   1282 }
   1283 
   1284 std::string WebRtcSession::BadStateErrMsg(State state) {
   1285   std::ostringstream desc;
   1286   desc << "Called in wrong state: " << GetStateString(state);
   1287   return desc.str();
   1288 }
   1289 
   1290 void WebRtcSession::SetAudioPlayout(uint32_t ssrc, bool enable) {
   1291   ASSERT(signaling_thread()->IsCurrent());
   1292   if (!voice_channel_) {
   1293     LOG(LS_ERROR) << "SetAudioPlayout: No audio channel exists.";
   1294     return;
   1295   }
   1296   if (!voice_channel_->SetOutputVolume(ssrc, enable ? 1 : 0)) {
   1297     // Allow that SetOutputVolume fail if |enable| is false but assert
   1298     // otherwise. This in the normal case when the underlying media channel has
   1299     // already been deleted.
   1300     ASSERT(enable == false);
   1301   }
   1302 }
   1303 
   1304 void WebRtcSession::SetAudioSend(uint32_t ssrc,
   1305                                  bool enable,
   1306                                  const cricket::AudioOptions& options,
   1307                                  cricket::AudioRenderer* renderer) {
   1308   ASSERT(signaling_thread()->IsCurrent());
   1309   if (!voice_channel_) {
   1310     LOG(LS_ERROR) << "SetAudioSend: No audio channel exists.";
   1311     return;
   1312   }
   1313   if (!voice_channel_->SetAudioSend(ssrc, enable, &options, renderer)) {
   1314     LOG(LS_ERROR) << "SetAudioSend: ssrc is incorrect: " << ssrc;
   1315   }
   1316 }
   1317 
   1318 void WebRtcSession::SetAudioPlayoutVolume(uint32_t ssrc, double volume) {
   1319   ASSERT(signaling_thread()->IsCurrent());
   1320   ASSERT(volume >= 0 && volume <= 10);
   1321   if (!voice_channel_) {
   1322     LOG(LS_ERROR) << "SetAudioPlayoutVolume: No audio channel exists.";
   1323     return;
   1324   }
   1325 
   1326   if (!voice_channel_->SetOutputVolume(ssrc, volume)) {
   1327     ASSERT(false);
   1328   }
   1329 }
   1330 
   1331 void WebRtcSession::SetRawAudioSink(uint32_t ssrc,
   1332                                     rtc::scoped_ptr<AudioSinkInterface> sink) {
   1333   ASSERT(signaling_thread()->IsCurrent());
   1334   if (!voice_channel_)
   1335     return;
   1336 
   1337   voice_channel_->SetRawAudioSink(ssrc, std::move(sink));
   1338 }
   1339 
   1340 bool WebRtcSession::SetCaptureDevice(uint32_t ssrc,
   1341                                      cricket::VideoCapturer* camera) {
   1342   ASSERT(signaling_thread()->IsCurrent());
   1343 
   1344   if (!video_channel_) {
   1345     // |video_channel_| doesnt't exist. Probably because the remote end doesnt't
   1346     // support video.
   1347     LOG(LS_WARNING) << "Video not used in this call.";
   1348     return false;
   1349   }
   1350   if (!video_channel_->SetCapturer(ssrc, camera)) {
   1351     // Allow that SetCapturer fail if |camera| is NULL but assert otherwise.
   1352     // This in the normal case when the underlying media channel has already
   1353     // been deleted.
   1354     ASSERT(camera == NULL);
   1355     return false;
   1356   }
   1357   return true;
   1358 }
   1359 
   1360 void WebRtcSession::SetVideoPlayout(uint32_t ssrc,
   1361                                     bool enable,
   1362                                     cricket::VideoRenderer* renderer) {
   1363   ASSERT(signaling_thread()->IsCurrent());
   1364   if (!video_channel_) {
   1365     LOG(LS_WARNING) << "SetVideoPlayout: No video channel exists.";
   1366     return;
   1367   }
   1368   if (!video_channel_->SetRenderer(ssrc, enable ? renderer : NULL)) {
   1369     // Allow that SetRenderer fail if |renderer| is NULL but assert otherwise.
   1370     // This in the normal case when the underlying media channel has already
   1371     // been deleted.
   1372     ASSERT(renderer == NULL);
   1373   }
   1374 }
   1375 
   1376 void WebRtcSession::SetVideoSend(uint32_t ssrc,
   1377                                  bool enable,
   1378                                  const cricket::VideoOptions* options) {
   1379   ASSERT(signaling_thread()->IsCurrent());
   1380   if (!video_channel_) {
   1381     LOG(LS_WARNING) << "SetVideoSend: No video channel exists.";
   1382     return;
   1383   }
   1384   if (!video_channel_->SetVideoSend(ssrc, enable, options)) {
   1385     // Allow that MuteStream fail if |enable| is false but assert otherwise.
   1386     // This in the normal case when the underlying media channel has already
   1387     // been deleted.
   1388     ASSERT(enable == false);
   1389   }
   1390 }
   1391 
   1392 bool WebRtcSession::CanInsertDtmf(const std::string& track_id) {
   1393   ASSERT(signaling_thread()->IsCurrent());
   1394   if (!voice_channel_) {
   1395     LOG(LS_ERROR) << "CanInsertDtmf: No audio channel exists.";
   1396     return false;
   1397   }
   1398   uint32_t send_ssrc = 0;
   1399   // The Dtmf is negotiated per channel not ssrc, so we only check if the ssrc
   1400   // exists.
   1401   if (!local_desc_ ||
   1402       !GetAudioSsrcByTrackId(local_desc_->description(), track_id,
   1403                              &send_ssrc)) {
   1404     LOG(LS_ERROR) << "CanInsertDtmf: Track does not exist: " << track_id;
   1405     return false;
   1406   }
   1407   return voice_channel_->CanInsertDtmf();
   1408 }
   1409 
   1410 bool WebRtcSession::InsertDtmf(const std::string& track_id,
   1411                                int code, int duration) {
   1412   ASSERT(signaling_thread()->IsCurrent());
   1413   if (!voice_channel_) {
   1414     LOG(LS_ERROR) << "InsertDtmf: No audio channel exists.";
   1415     return false;
   1416   }
   1417   uint32_t send_ssrc = 0;
   1418   if (!VERIFY(local_desc_ && GetAudioSsrcByTrackId(local_desc_->description(),
   1419                                                    track_id, &send_ssrc))) {
   1420     LOG(LS_ERROR) << "InsertDtmf: Track does not exist: " << track_id;
   1421     return false;
   1422   }
   1423   if (!voice_channel_->InsertDtmf(send_ssrc, code, duration)) {
   1424     LOG(LS_ERROR) << "Failed to insert DTMF to channel.";
   1425     return false;
   1426   }
   1427   return true;
   1428 }
   1429 
   1430 sigslot::signal0<>* WebRtcSession::GetOnDestroyedSignal() {
   1431   return &SignalVoiceChannelDestroyed;
   1432 }
   1433 
   1434 bool WebRtcSession::SendData(const cricket::SendDataParams& params,
   1435                              const rtc::Buffer& payload,
   1436                              cricket::SendDataResult* result) {
   1437   if (!data_channel_) {
   1438     LOG(LS_ERROR) << "SendData called when data_channel_ is NULL.";
   1439     return false;
   1440   }
   1441   return data_channel_->SendData(params, payload, result);
   1442 }
   1443 
   1444 bool WebRtcSession::ConnectDataChannel(DataChannel* webrtc_data_channel) {
   1445   if (!data_channel_) {
   1446     LOG(LS_ERROR) << "ConnectDataChannel called when data_channel_ is NULL.";
   1447     return false;
   1448   }
   1449   data_channel_->SignalReadyToSendData.connect(webrtc_data_channel,
   1450                                                &DataChannel::OnChannelReady);
   1451   data_channel_->SignalDataReceived.connect(webrtc_data_channel,
   1452                                             &DataChannel::OnDataReceived);
   1453   data_channel_->SignalStreamClosedRemotely.connect(
   1454       webrtc_data_channel, &DataChannel::OnStreamClosedRemotely);
   1455   return true;
   1456 }
   1457 
   1458 void WebRtcSession::DisconnectDataChannel(DataChannel* webrtc_data_channel) {
   1459   if (!data_channel_) {
   1460     LOG(LS_ERROR) << "DisconnectDataChannel called when data_channel_ is NULL.";
   1461     return;
   1462   }
   1463   data_channel_->SignalReadyToSendData.disconnect(webrtc_data_channel);
   1464   data_channel_->SignalDataReceived.disconnect(webrtc_data_channel);
   1465   data_channel_->SignalStreamClosedRemotely.disconnect(webrtc_data_channel);
   1466 }
   1467 
   1468 void WebRtcSession::AddSctpDataStream(int sid) {
   1469   if (!data_channel_) {
   1470     LOG(LS_ERROR) << "AddDataChannelStreams called when data_channel_ is NULL.";
   1471     return;
   1472   }
   1473   data_channel_->AddRecvStream(cricket::StreamParams::CreateLegacy(sid));
   1474   data_channel_->AddSendStream(cricket::StreamParams::CreateLegacy(sid));
   1475 }
   1476 
   1477 void WebRtcSession::RemoveSctpDataStream(int sid) {
   1478   if (!data_channel_) {
   1479     LOG(LS_ERROR) << "RemoveDataChannelStreams called when data_channel_ is "
   1480                   << "NULL.";
   1481     return;
   1482   }
   1483   data_channel_->RemoveRecvStream(sid);
   1484   data_channel_->RemoveSendStream(sid);
   1485 }
   1486 
   1487 bool WebRtcSession::ReadyToSendData() const {
   1488   return data_channel_ && data_channel_->ready_to_send_data();
   1489 }
   1490 
   1491 cricket::DataChannelType WebRtcSession::data_channel_type() const {
   1492   return data_channel_type_;
   1493 }
   1494 
   1495 bool WebRtcSession::IceRestartPending() const {
   1496   return ice_restart_latch_->Get();
   1497 }
   1498 
   1499 void WebRtcSession::ResetIceRestartLatch() {
   1500   ice_restart_latch_->Reset();
   1501 }
   1502 
   1503 void WebRtcSession::OnCertificateReady(
   1504     const rtc::scoped_refptr<rtc::RTCCertificate>& certificate) {
   1505   transport_controller_->SetLocalCertificate(certificate);
   1506 }
   1507 
   1508 bool WebRtcSession::waiting_for_certificate_for_testing() const {
   1509   return webrtc_session_desc_factory_->waiting_for_certificate_for_testing();
   1510 }
   1511 
   1512 const rtc::scoped_refptr<rtc::RTCCertificate>&
   1513 WebRtcSession::certificate_for_testing() {
   1514   return transport_controller_->certificate_for_testing();
   1515 }
   1516 
   1517 void WebRtcSession::SetIceConnectionState(
   1518       PeerConnectionInterface::IceConnectionState state) {
   1519   if (ice_connection_state_ == state) {
   1520     return;
   1521   }
   1522 
   1523   // ASSERT that the requested transition is allowed.  Note that
   1524   // WebRtcSession does not implement "kIceConnectionClosed" (that is handled
   1525   // within PeerConnection).  This switch statement should compile away when
   1526   // ASSERTs are disabled.
   1527   LOG(LS_INFO) << "Changing IceConnectionState " << ice_connection_state_
   1528                << " => " << state;
   1529   switch (ice_connection_state_) {
   1530     case PeerConnectionInterface::kIceConnectionNew:
   1531       ASSERT(state == PeerConnectionInterface::kIceConnectionChecking);
   1532       break;
   1533     case PeerConnectionInterface::kIceConnectionChecking:
   1534       ASSERT(state == PeerConnectionInterface::kIceConnectionFailed ||
   1535              state == PeerConnectionInterface::kIceConnectionConnected);
   1536       break;
   1537     case PeerConnectionInterface::kIceConnectionConnected:
   1538       ASSERT(state == PeerConnectionInterface::kIceConnectionDisconnected ||
   1539              state == PeerConnectionInterface::kIceConnectionChecking ||
   1540              state == PeerConnectionInterface::kIceConnectionCompleted);
   1541       break;
   1542     case PeerConnectionInterface::kIceConnectionCompleted:
   1543       ASSERT(state == PeerConnectionInterface::kIceConnectionConnected ||
   1544              state == PeerConnectionInterface::kIceConnectionDisconnected);
   1545       break;
   1546     case PeerConnectionInterface::kIceConnectionFailed:
   1547       ASSERT(state == PeerConnectionInterface::kIceConnectionNew);
   1548       break;
   1549     case PeerConnectionInterface::kIceConnectionDisconnected:
   1550       ASSERT(state == PeerConnectionInterface::kIceConnectionChecking ||
   1551              state == PeerConnectionInterface::kIceConnectionConnected ||
   1552              state == PeerConnectionInterface::kIceConnectionCompleted ||
   1553              state == PeerConnectionInterface::kIceConnectionFailed);
   1554       break;
   1555     case PeerConnectionInterface::kIceConnectionClosed:
   1556       ASSERT(false);
   1557       break;
   1558     default:
   1559       ASSERT(false);
   1560       break;
   1561   }
   1562 
   1563   ice_connection_state_ = state;
   1564   if (ice_observer_) {
   1565     ice_observer_->OnIceConnectionChange(ice_connection_state_);
   1566   }
   1567 }
   1568 
   1569 void WebRtcSession::OnTransportControllerConnectionState(
   1570     cricket::IceConnectionState state) {
   1571   switch (state) {
   1572     case cricket::kIceConnectionConnecting:
   1573       // If the current state is Connected or Completed, then there were
   1574       // writable channels but now there are not, so the next state must
   1575       // be Disconnected.
   1576       // kIceConnectionConnecting is currently used as the default,
   1577       // un-connected state by the TransportController, so its only use is
   1578       // detecting disconnections.
   1579       if (ice_connection_state_ ==
   1580               PeerConnectionInterface::kIceConnectionConnected ||
   1581           ice_connection_state_ ==
   1582               PeerConnectionInterface::kIceConnectionCompleted) {
   1583         SetIceConnectionState(
   1584             PeerConnectionInterface::kIceConnectionDisconnected);
   1585       }
   1586       break;
   1587     case cricket::kIceConnectionFailed:
   1588       SetIceConnectionState(PeerConnectionInterface::kIceConnectionFailed);
   1589       break;
   1590     case cricket::kIceConnectionConnected:
   1591       LOG(LS_INFO) << "Changing to ICE connected state because "
   1592                    << "all transports are writable.";
   1593       SetIceConnectionState(PeerConnectionInterface::kIceConnectionConnected);
   1594       break;
   1595     case cricket::kIceConnectionCompleted:
   1596       LOG(LS_INFO) << "Changing to ICE completed state because "
   1597                    << "all transports are complete.";
   1598       if (ice_connection_state_ !=
   1599           PeerConnectionInterface::kIceConnectionConnected) {
   1600         // If jumping directly from "checking" to "connected",
   1601         // signal "connected" first.
   1602         SetIceConnectionState(PeerConnectionInterface::kIceConnectionConnected);
   1603       }
   1604       SetIceConnectionState(PeerConnectionInterface::kIceConnectionCompleted);
   1605       if (metrics_observer_) {
   1606         ReportTransportStats();
   1607       }
   1608       break;
   1609     default:
   1610       ASSERT(false);
   1611   }
   1612 }
   1613 
   1614 void WebRtcSession::OnTransportControllerReceiving(bool receiving) {
   1615   SetIceConnectionReceiving(receiving);
   1616 }
   1617 
   1618 void WebRtcSession::SetIceConnectionReceiving(bool receiving) {
   1619   if (ice_connection_receiving_ == receiving) {
   1620     return;
   1621   }
   1622   ice_connection_receiving_ = receiving;
   1623   if (ice_observer_) {
   1624     ice_observer_->OnIceConnectionReceivingChange(receiving);
   1625   }
   1626 }
   1627 
   1628 void WebRtcSession::OnTransportControllerCandidatesGathered(
   1629     const std::string& transport_name,
   1630     const cricket::Candidates& candidates) {
   1631   ASSERT(signaling_thread()->IsCurrent());
   1632   int sdp_mline_index;
   1633   if (!GetLocalCandidateMediaIndex(transport_name, &sdp_mline_index)) {
   1634     LOG(LS_ERROR) << "OnTransportControllerCandidatesGathered: content name "
   1635                   << transport_name << " not found";
   1636     return;
   1637   }
   1638 
   1639   for (cricket::Candidates::const_iterator citer = candidates.begin();
   1640        citer != candidates.end(); ++citer) {
   1641     // Use transport_name as the candidate media id.
   1642     JsepIceCandidate candidate(transport_name, sdp_mline_index, *citer);
   1643     if (ice_observer_) {
   1644       ice_observer_->OnIceCandidate(&candidate);
   1645     }
   1646     if (local_desc_) {
   1647       local_desc_->AddCandidate(&candidate);
   1648     }
   1649   }
   1650 }
   1651 
   1652 // Enabling voice and video channel.
   1653 void WebRtcSession::EnableChannels() {
   1654   if (voice_channel_ && !voice_channel_->enabled())
   1655     voice_channel_->Enable(true);
   1656 
   1657   if (video_channel_ && !video_channel_->enabled())
   1658     video_channel_->Enable(true);
   1659 
   1660   if (data_channel_ && !data_channel_->enabled())
   1661     data_channel_->Enable(true);
   1662 }
   1663 
   1664 // Returns the media index for a local ice candidate given the content name.
   1665 bool WebRtcSession::GetLocalCandidateMediaIndex(const std::string& content_name,
   1666                                                 int* sdp_mline_index) {
   1667   if (!local_desc_ || !sdp_mline_index) {
   1668     return false;
   1669   }
   1670 
   1671   bool content_found = false;
   1672   const ContentInfos& contents = local_desc_->description()->contents();
   1673   for (size_t index = 0; index < contents.size(); ++index) {
   1674     if (contents[index].name == content_name) {
   1675       *sdp_mline_index = static_cast<int>(index);
   1676       content_found = true;
   1677       break;
   1678     }
   1679   }
   1680   return content_found;
   1681 }
   1682 
   1683 bool WebRtcSession::UseCandidatesInSessionDescription(
   1684     const SessionDescriptionInterface* remote_desc) {
   1685   if (!remote_desc) {
   1686     return true;
   1687   }
   1688   bool ret = true;
   1689 
   1690   for (size_t m = 0; m < remote_desc->number_of_mediasections(); ++m) {
   1691     const IceCandidateCollection* candidates = remote_desc->candidates(m);
   1692     for (size_t n = 0; n < candidates->count(); ++n) {
   1693       const IceCandidateInterface* candidate = candidates->at(n);
   1694       bool valid = false;
   1695       if (!ReadyToUseRemoteCandidate(candidate, remote_desc, &valid)) {
   1696         if (valid) {
   1697           LOG(LS_INFO) << "UseCandidatesInSessionDescription: Not ready to use "
   1698                        << "candidate.";
   1699         }
   1700         continue;
   1701       }
   1702       ret = UseCandidate(candidate);
   1703       if (!ret) {
   1704         break;
   1705       }
   1706     }
   1707   }
   1708   return ret;
   1709 }
   1710 
   1711 bool WebRtcSession::UseCandidate(
   1712     const IceCandidateInterface* candidate) {
   1713 
   1714   size_t mediacontent_index = static_cast<size_t>(candidate->sdp_mline_index());
   1715   size_t remote_content_size = remote_desc_->description()->contents().size();
   1716   if (mediacontent_index >= remote_content_size) {
   1717     LOG(LS_ERROR)
   1718         << "UseRemoteCandidateInSession: Invalid candidate media index.";
   1719     return false;
   1720   }
   1721 
   1722   cricket::ContentInfo content =
   1723       remote_desc_->description()->contents()[mediacontent_index];
   1724   std::vector<cricket::Candidate> candidates;
   1725   candidates.push_back(candidate->candidate());
   1726   // Invoking BaseSession method to handle remote candidates.
   1727   std::string error;
   1728   if (transport_controller_->AddRemoteCandidates(content.name, candidates,
   1729                                                  &error)) {
   1730     // Candidates successfully submitted for checking.
   1731     if (ice_connection_state_ == PeerConnectionInterface::kIceConnectionNew ||
   1732         ice_connection_state_ ==
   1733             PeerConnectionInterface::kIceConnectionDisconnected) {
   1734       // If state is New, then the session has just gotten its first remote ICE
   1735       // candidates, so go to Checking.
   1736       // If state is Disconnected, the session is re-using old candidates or
   1737       // receiving additional ones, so go to Checking.
   1738       // If state is Connected, stay Connected.
   1739       // TODO(bemasc): If state is Connected, and the new candidates are for a
   1740       // newly added transport, then the state actually _should_ move to
   1741       // checking.  Add a way to distinguish that case.
   1742       SetIceConnectionState(PeerConnectionInterface::kIceConnectionChecking);
   1743     }
   1744     // TODO(bemasc): If state is Completed, go back to Connected.
   1745   } else {
   1746     if (!error.empty()) {
   1747       LOG(LS_WARNING) << error;
   1748     }
   1749   }
   1750   return true;
   1751 }
   1752 
   1753 void WebRtcSession::RemoveUnusedChannels(const SessionDescription* desc) {
   1754   // Destroy video_channel_ first since it may have a pointer to the
   1755   // voice_channel_.
   1756   const cricket::ContentInfo* video_info =
   1757       cricket::GetFirstVideoContent(desc);
   1758   if ((!video_info || video_info->rejected) && video_channel_) {
   1759     SignalVideoChannelDestroyed();
   1760     channel_manager_->DestroyVideoChannel(video_channel_.release());
   1761   }
   1762 
   1763   const cricket::ContentInfo* voice_info =
   1764       cricket::GetFirstAudioContent(desc);
   1765   if ((!voice_info || voice_info->rejected) && voice_channel_) {
   1766     SignalVoiceChannelDestroyed();
   1767     channel_manager_->DestroyVoiceChannel(voice_channel_.release());
   1768   }
   1769 
   1770   const cricket::ContentInfo* data_info =
   1771       cricket::GetFirstDataContent(desc);
   1772   if ((!data_info || data_info->rejected) && data_channel_) {
   1773     SignalDataChannelDestroyed();
   1774     channel_manager_->DestroyDataChannel(data_channel_.release());
   1775   }
   1776 }
   1777 
   1778 // TODO(mallinath) - Add a correct error code if the channels are not created
   1779 // due to BUNDLE is enabled but rtcp-mux is disabled.
   1780 bool WebRtcSession::CreateChannels(const SessionDescription* desc) {
   1781   // Creating the media channels and transport proxies.
   1782   const cricket::ContentInfo* voice = cricket::GetFirstAudioContent(desc);
   1783   if (voice && !voice->rejected && !voice_channel_) {
   1784     if (!CreateVoiceChannel(voice)) {
   1785       LOG(LS_ERROR) << "Failed to create voice channel.";
   1786       return false;
   1787     }
   1788   }
   1789 
   1790   const cricket::ContentInfo* video = cricket::GetFirstVideoContent(desc);
   1791   if (video && !video->rejected && !video_channel_) {
   1792     if (!CreateVideoChannel(video)) {
   1793       LOG(LS_ERROR) << "Failed to create video channel.";
   1794       return false;
   1795     }
   1796   }
   1797 
   1798   const cricket::ContentInfo* data = cricket::GetFirstDataContent(desc);
   1799   if (data_channel_type_ != cricket::DCT_NONE &&
   1800       data && !data->rejected && !data_channel_) {
   1801     if (!CreateDataChannel(data)) {
   1802       LOG(LS_ERROR) << "Failed to create data channel.";
   1803       return false;
   1804     }
   1805   }
   1806 
   1807   if (rtcp_mux_policy_ == PeerConnectionInterface::kRtcpMuxPolicyRequire) {
   1808     if (voice_channel()) {
   1809       voice_channel()->ActivateRtcpMux();
   1810     }
   1811     if (video_channel()) {
   1812       video_channel()->ActivateRtcpMux();
   1813     }
   1814     if (data_channel()) {
   1815       data_channel()->ActivateRtcpMux();
   1816     }
   1817   }
   1818 
   1819   // Enable BUNDLE immediately when kBundlePolicyMaxBundle is in effect.
   1820   if (bundle_policy_ == PeerConnectionInterface::kBundlePolicyMaxBundle) {
   1821     const cricket::ContentGroup* bundle_group = desc->GetGroupByName(
   1822         cricket::GROUP_TYPE_BUNDLE);
   1823     if (!bundle_group) {
   1824       LOG(LS_WARNING) << "max-bundle specified without BUNDLE specified";
   1825       return false;
   1826     }
   1827     if (!EnableBundle(*bundle_group)) {
   1828       LOG(LS_WARNING) << "max-bundle failed to enable bundling.";
   1829       return false;
   1830     }
   1831   }
   1832 
   1833   return true;
   1834 }
   1835 
   1836 bool WebRtcSession::CreateVoiceChannel(const cricket::ContentInfo* content) {
   1837   voice_channel_.reset(channel_manager_->CreateVoiceChannel(
   1838       media_controller_, transport_controller_.get(), content->name, true,
   1839       audio_options_));
   1840   if (!voice_channel_) {
   1841     return false;
   1842   }
   1843 
   1844   voice_channel_->SignalDtlsSetupFailure.connect(
   1845       this, &WebRtcSession::OnDtlsSetupFailure);
   1846 
   1847   SignalVoiceChannelCreated();
   1848   voice_channel_->transport_channel()->SignalSentPacket.connect(
   1849       this, &WebRtcSession::OnSentPacket_w);
   1850   return true;
   1851 }
   1852 
   1853 bool WebRtcSession::CreateVideoChannel(const cricket::ContentInfo* content) {
   1854   video_channel_.reset(channel_manager_->CreateVideoChannel(
   1855       media_controller_, transport_controller_.get(), content->name, true,
   1856       video_options_));
   1857   if (!video_channel_) {
   1858     return false;
   1859   }
   1860 
   1861   video_channel_->SignalDtlsSetupFailure.connect(
   1862       this, &WebRtcSession::OnDtlsSetupFailure);
   1863 
   1864   SignalVideoChannelCreated();
   1865   video_channel_->transport_channel()->SignalSentPacket.connect(
   1866       this, &WebRtcSession::OnSentPacket_w);
   1867   return true;
   1868 }
   1869 
   1870 bool WebRtcSession::CreateDataChannel(const cricket::ContentInfo* content) {
   1871   bool sctp = (data_channel_type_ == cricket::DCT_SCTP);
   1872   data_channel_.reset(channel_manager_->CreateDataChannel(
   1873       transport_controller_.get(), content->name, !sctp, data_channel_type_));
   1874   if (!data_channel_) {
   1875     return false;
   1876   }
   1877 
   1878   if (sctp) {
   1879     data_channel_->SignalDataReceived.connect(
   1880         this, &WebRtcSession::OnDataChannelMessageReceived);
   1881   }
   1882 
   1883   data_channel_->SignalDtlsSetupFailure.connect(
   1884       this, &WebRtcSession::OnDtlsSetupFailure);
   1885 
   1886   SignalDataChannelCreated();
   1887   data_channel_->transport_channel()->SignalSentPacket.connect(
   1888       this, &WebRtcSession::OnSentPacket_w);
   1889   return true;
   1890 }
   1891 
   1892 void WebRtcSession::OnDtlsSetupFailure(cricket::BaseChannel*, bool rtcp) {
   1893   SetError(ERROR_TRANSPORT,
   1894            rtcp ? kDtlsSetupFailureRtcp : kDtlsSetupFailureRtp);
   1895 }
   1896 
   1897 void WebRtcSession::OnDataChannelMessageReceived(
   1898     cricket::DataChannel* channel,
   1899     const cricket::ReceiveDataParams& params,
   1900     const rtc::Buffer& payload) {
   1901   RTC_DCHECK(data_channel_type_ == cricket::DCT_SCTP);
   1902   if (params.type == cricket::DMT_CONTROL && IsOpenMessage(payload)) {
   1903     // Received OPEN message; parse and signal that a new data channel should
   1904     // be created.
   1905     std::string label;
   1906     InternalDataChannelInit config;
   1907     config.id = params.ssrc;
   1908     if (!ParseDataChannelOpenMessage(payload, &label, &config)) {
   1909       LOG(LS_WARNING) << "Failed to parse the OPEN message for sid "
   1910                       << params.ssrc;
   1911       return;
   1912     }
   1913     config.open_handshake_role = InternalDataChannelInit::kAcker;
   1914     SignalDataChannelOpenMessage(label, config);
   1915   }
   1916   // Otherwise ignore the message.
   1917 }
   1918 
   1919 // Returns false if bundle is enabled and rtcp_mux is disabled.
   1920 bool WebRtcSession::ValidateBundleSettings(const SessionDescription* desc) {
   1921   bool bundle_enabled = desc->HasGroup(cricket::GROUP_TYPE_BUNDLE);
   1922   if (!bundle_enabled)
   1923     return true;
   1924 
   1925   const cricket::ContentGroup* bundle_group =
   1926       desc->GetGroupByName(cricket::GROUP_TYPE_BUNDLE);
   1927   ASSERT(bundle_group != NULL);
   1928 
   1929   const cricket::ContentInfos& contents = desc->contents();
   1930   for (cricket::ContentInfos::const_iterator citer = contents.begin();
   1931        citer != contents.end(); ++citer) {
   1932     const cricket::ContentInfo* content = (&*citer);
   1933     ASSERT(content != NULL);
   1934     if (bundle_group->HasContentName(content->name) &&
   1935         !content->rejected && content->type == cricket::NS_JINGLE_RTP) {
   1936       if (!HasRtcpMuxEnabled(content))
   1937         return false;
   1938     }
   1939   }
   1940   // RTCP-MUX is enabled in all the contents.
   1941   return true;
   1942 }
   1943 
   1944 bool WebRtcSession::HasRtcpMuxEnabled(
   1945     const cricket::ContentInfo* content) {
   1946   const cricket::MediaContentDescription* description =
   1947       static_cast<cricket::MediaContentDescription*>(content->description);
   1948   return description->rtcp_mux();
   1949 }
   1950 
   1951 bool WebRtcSession::ValidateSessionDescription(
   1952     const SessionDescriptionInterface* sdesc,
   1953     cricket::ContentSource source, std::string* err_desc) {
   1954   std::string type;
   1955   if (error() != ERROR_NONE) {
   1956     return BadSdp(source, type, GetSessionErrorMsg(), err_desc);
   1957   }
   1958 
   1959   if (!sdesc || !sdesc->description()) {
   1960     return BadSdp(source, type, kInvalidSdp, err_desc);
   1961   }
   1962 
   1963   type = sdesc->type();
   1964   Action action = GetAction(sdesc->type());
   1965   if (source == cricket::CS_LOCAL) {
   1966     if (!ExpectSetLocalDescription(action))
   1967       return BadLocalSdp(type, BadStateErrMsg(state()), err_desc);
   1968   } else {
   1969     if (!ExpectSetRemoteDescription(action))
   1970       return BadRemoteSdp(type, BadStateErrMsg(state()), err_desc);
   1971   }
   1972 
   1973   // Verify crypto settings.
   1974   std::string crypto_error;
   1975   if ((webrtc_session_desc_factory_->SdesPolicy() == cricket::SEC_REQUIRED ||
   1976        dtls_enabled_) &&
   1977       !VerifyCrypto(sdesc->description(), dtls_enabled_, &crypto_error)) {
   1978     return BadSdp(source, type, crypto_error, err_desc);
   1979   }
   1980 
   1981   // Verify ice-ufrag and ice-pwd.
   1982   if (!VerifyIceUfragPwdPresent(sdesc->description())) {
   1983     return BadSdp(source, type, kSdpWithoutIceUfragPwd, err_desc);
   1984   }
   1985 
   1986   if (!ValidateBundleSettings(sdesc->description())) {
   1987     return BadSdp(source, type, kBundleWithoutRtcpMux, err_desc);
   1988   }
   1989 
   1990   // Verify m-lines in Answer when compared against Offer.
   1991   if (action == kAnswer) {
   1992     const cricket::SessionDescription* offer_desc =
   1993         (source == cricket::CS_LOCAL) ? remote_desc_->description()
   1994                                       : local_desc_->description();
   1995     if (!VerifyMediaDescriptions(sdesc->description(), offer_desc)) {
   1996       return BadAnswerSdp(source, kMlineMismatch, err_desc);
   1997     }
   1998   }
   1999 
   2000   return true;
   2001 }
   2002 
   2003 bool WebRtcSession::ExpectSetLocalDescription(Action action) {
   2004   return ((action == kOffer && state() == STATE_INIT) ||
   2005           // update local offer
   2006           (action == kOffer && state() == STATE_SENTOFFER) ||
   2007           // update the current ongoing session.
   2008           (action == kOffer && state() == STATE_INPROGRESS) ||
   2009           // accept remote offer
   2010           (action == kAnswer && state() == STATE_RECEIVEDOFFER) ||
   2011           (action == kAnswer && state() == STATE_SENTPRANSWER) ||
   2012           (action == kPrAnswer && state() == STATE_RECEIVEDOFFER) ||
   2013           (action == kPrAnswer && state() == STATE_SENTPRANSWER));
   2014 }
   2015 
   2016 bool WebRtcSession::ExpectSetRemoteDescription(Action action) {
   2017   return ((action == kOffer && state() == STATE_INIT) ||
   2018           // update remote offer
   2019           (action == kOffer && state() == STATE_RECEIVEDOFFER) ||
   2020           // update the current ongoing session
   2021           (action == kOffer && state() == STATE_INPROGRESS) ||
   2022           // accept local offer
   2023           (action == kAnswer && state() == STATE_SENTOFFER) ||
   2024           (action == kAnswer && state() == STATE_RECEIVEDPRANSWER) ||
   2025           (action == kPrAnswer && state() == STATE_SENTOFFER) ||
   2026           (action == kPrAnswer && state() == STATE_RECEIVEDPRANSWER));
   2027 }
   2028 
   2029 std::string WebRtcSession::GetSessionErrorMsg() {
   2030   std::ostringstream desc;
   2031   desc << kSessionError << GetErrorCodeString(error()) << ". ";
   2032   desc << kSessionErrorDesc << error_desc() << ".";
   2033   return desc.str();
   2034 }
   2035 
   2036 // We need to check the local/remote description for the Transport instead of
   2037 // the session, because a new Transport added during renegotiation may have
   2038 // them unset while the session has them set from the previous negotiation.
   2039 // Not doing so may trigger the auto generation of transport description and
   2040 // mess up DTLS identity information, ICE credential, etc.
   2041 bool WebRtcSession::ReadyToUseRemoteCandidate(
   2042     const IceCandidateInterface* candidate,
   2043     const SessionDescriptionInterface* remote_desc,
   2044     bool* valid) {
   2045   *valid = true;;
   2046 
   2047   const SessionDescriptionInterface* current_remote_desc =
   2048       remote_desc ? remote_desc : remote_desc_.get();
   2049 
   2050   if (!current_remote_desc) {
   2051     return false;
   2052   }
   2053 
   2054   size_t mediacontent_index =
   2055       static_cast<size_t>(candidate->sdp_mline_index());
   2056   size_t remote_content_size =
   2057       current_remote_desc->description()->contents().size();
   2058   if (mediacontent_index >= remote_content_size) {
   2059     LOG(LS_ERROR)
   2060         << "ReadyToUseRemoteCandidate: Invalid candidate media index.";
   2061 
   2062     *valid = false;
   2063     return false;
   2064   }
   2065 
   2066   cricket::ContentInfo content =
   2067       current_remote_desc->description()->contents()[mediacontent_index];
   2068   cricket::BaseChannel* channel = GetChannel(content.name);
   2069   if (!channel) {
   2070     return false;
   2071   }
   2072 
   2073   return transport_controller_->ReadyForRemoteCandidates(
   2074       channel->transport_name());
   2075 }
   2076 
   2077 void WebRtcSession::OnTransportControllerGatheringState(
   2078     cricket::IceGatheringState state) {
   2079   ASSERT(signaling_thread()->IsCurrent());
   2080   if (state == cricket::kIceGatheringGathering) {
   2081     if (ice_observer_) {
   2082       ice_observer_->OnIceGatheringChange(
   2083           PeerConnectionInterface::kIceGatheringGathering);
   2084     }
   2085   } else if (state == cricket::kIceGatheringComplete) {
   2086     if (ice_observer_) {
   2087       ice_observer_->OnIceGatheringChange(
   2088           PeerConnectionInterface::kIceGatheringComplete);
   2089       ice_observer_->OnIceComplete();
   2090     }
   2091   }
   2092 }
   2093 
   2094 void WebRtcSession::ReportTransportStats() {
   2095   // Use a set so we don't report the same stats twice if two channels share
   2096   // a transport.
   2097   std::set<std::string> transport_names;
   2098   if (voice_channel()) {
   2099     transport_names.insert(voice_channel()->transport_name());
   2100   }
   2101   if (video_channel()) {
   2102     transport_names.insert(video_channel()->transport_name());
   2103   }
   2104   if (data_channel()) {
   2105     transport_names.insert(data_channel()->transport_name());
   2106   }
   2107   for (const auto& name : transport_names) {
   2108     cricket::TransportStats stats;
   2109     if (transport_controller_->GetStats(name, &stats)) {
   2110       ReportBestConnectionState(stats);
   2111       ReportNegotiatedCiphers(stats);
   2112     }
   2113   }
   2114 }
   2115 // Walk through the ConnectionInfos to gather best connection usage
   2116 // for IPv4 and IPv6.
   2117 void WebRtcSession::ReportBestConnectionState(
   2118     const cricket::TransportStats& stats) {
   2119   RTC_DCHECK(metrics_observer_ != NULL);
   2120   for (cricket::TransportChannelStatsList::const_iterator it =
   2121          stats.channel_stats.begin();
   2122        it != stats.channel_stats.end(); ++it) {
   2123     for (cricket::ConnectionInfos::const_iterator it_info =
   2124            it->connection_infos.begin();
   2125          it_info != it->connection_infos.end(); ++it_info) {
   2126       if (!it_info->best_connection) {
   2127         continue;
   2128       }
   2129 
   2130       PeerConnectionEnumCounterType type = kPeerConnectionEnumCounterMax;
   2131       const cricket::Candidate& local = it_info->local_candidate;
   2132       const cricket::Candidate& remote = it_info->remote_candidate;
   2133 
   2134       // Increment the counter for IceCandidatePairType.
   2135       if (local.protocol() == cricket::TCP_PROTOCOL_NAME ||
   2136           (local.type() == RELAY_PORT_TYPE &&
   2137            local.relay_protocol() == cricket::TCP_PROTOCOL_NAME)) {
   2138         type = kEnumCounterIceCandidatePairTypeTcp;
   2139       } else if (local.protocol() == cricket::UDP_PROTOCOL_NAME) {
   2140         type = kEnumCounterIceCandidatePairTypeUdp;
   2141       } else {
   2142         RTC_CHECK(0);
   2143       }
   2144       metrics_observer_->IncrementEnumCounter(
   2145           type, GetIceCandidatePairCounter(local, remote),
   2146           kIceCandidatePairMax);
   2147 
   2148       // Increment the counter for IP type.
   2149       if (local.address().family() == AF_INET) {
   2150         metrics_observer_->IncrementEnumCounter(
   2151             kEnumCounterAddressFamily, kBestConnections_IPv4,
   2152             kPeerConnectionAddressFamilyCounter_Max);
   2153 
   2154       } else if (local.address().family() == AF_INET6) {
   2155         metrics_observer_->IncrementEnumCounter(
   2156             kEnumCounterAddressFamily, kBestConnections_IPv6,
   2157             kPeerConnectionAddressFamilyCounter_Max);
   2158       } else {
   2159         RTC_CHECK(0);
   2160       }
   2161 
   2162       return;
   2163     }
   2164   }
   2165 }
   2166 
   2167 void WebRtcSession::ReportNegotiatedCiphers(
   2168     const cricket::TransportStats& stats) {
   2169   RTC_DCHECK(metrics_observer_ != NULL);
   2170   if (!dtls_enabled_ || stats.channel_stats.empty()) {
   2171     return;
   2172   }
   2173 
   2174   int srtp_crypto_suite = stats.channel_stats[0].srtp_crypto_suite;
   2175   int ssl_cipher_suite = stats.channel_stats[0].ssl_cipher_suite;
   2176   if (srtp_crypto_suite == rtc::SRTP_INVALID_CRYPTO_SUITE &&
   2177       ssl_cipher_suite == rtc::TLS_NULL_WITH_NULL_NULL) {
   2178     return;
   2179   }
   2180 
   2181   PeerConnectionEnumCounterType srtp_counter_type;
   2182   PeerConnectionEnumCounterType ssl_counter_type;
   2183   if (stats.transport_name == cricket::CN_AUDIO) {
   2184     srtp_counter_type = kEnumCounterAudioSrtpCipher;
   2185     ssl_counter_type = kEnumCounterAudioSslCipher;
   2186   } else if (stats.transport_name == cricket::CN_VIDEO) {
   2187     srtp_counter_type = kEnumCounterVideoSrtpCipher;
   2188     ssl_counter_type = kEnumCounterVideoSslCipher;
   2189   } else if (stats.transport_name == cricket::CN_DATA) {
   2190     srtp_counter_type = kEnumCounterDataSrtpCipher;
   2191     ssl_counter_type = kEnumCounterDataSslCipher;
   2192   } else {
   2193     RTC_NOTREACHED();
   2194     return;
   2195   }
   2196 
   2197   if (srtp_crypto_suite != rtc::SRTP_INVALID_CRYPTO_SUITE) {
   2198     metrics_observer_->IncrementSparseEnumCounter(srtp_counter_type,
   2199                                                   srtp_crypto_suite);
   2200   }
   2201   if (ssl_cipher_suite != rtc::TLS_NULL_WITH_NULL_NULL) {
   2202     metrics_observer_->IncrementSparseEnumCounter(ssl_counter_type,
   2203                                                   ssl_cipher_suite);
   2204   }
   2205 }
   2206 
   2207 void WebRtcSession::OnSentPacket_w(cricket::TransportChannel* channel,
   2208                                    const rtc::SentPacket& sent_packet) {
   2209   RTC_DCHECK(worker_thread()->IsCurrent());
   2210   media_controller_->call_w()->OnSentPacket(sent_packet);
   2211 }
   2212 
   2213 }  // namespace webrtc
   2214