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/peerconnection.h" 29 30 #include <algorithm> 31 #include <cctype> // for isdigit 32 #include <utility> 33 #include <vector> 34 35 #include "talk/app/webrtc/audiotrack.h" 36 #include "talk/app/webrtc/dtmfsender.h" 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/mediastream.h" 41 #include "talk/app/webrtc/mediastreamobserver.h" 42 #include "talk/app/webrtc/mediastreamproxy.h" 43 #include "talk/app/webrtc/mediastreamtrackproxy.h" 44 #include "talk/app/webrtc/remoteaudiosource.h" 45 #include "talk/app/webrtc/remotevideocapturer.h" 46 #include "talk/app/webrtc/rtpreceiver.h" 47 #include "talk/app/webrtc/rtpsender.h" 48 #include "talk/app/webrtc/streamcollection.h" 49 #include "talk/app/webrtc/videosource.h" 50 #include "talk/app/webrtc/videotrack.h" 51 #include "talk/media/sctp/sctpdataengine.h" 52 #include "talk/session/media/channelmanager.h" 53 #include "webrtc/base/arraysize.h" 54 #include "webrtc/base/logging.h" 55 #include "webrtc/base/stringencode.h" 56 #include "webrtc/base/stringutils.h" 57 #include "webrtc/base/trace_event.h" 58 #include "webrtc/p2p/client/basicportallocator.h" 59 #include "webrtc/system_wrappers/include/field_trial.h" 60 61 namespace { 62 63 using webrtc::DataChannel; 64 using webrtc::MediaConstraintsInterface; 65 using webrtc::MediaStreamInterface; 66 using webrtc::PeerConnectionInterface; 67 using webrtc::RtpSenderInterface; 68 using webrtc::StreamCollection; 69 70 static const char kDefaultStreamLabel[] = "default"; 71 static const char kDefaultAudioTrackLabel[] = "defaulta0"; 72 static const char kDefaultVideoTrackLabel[] = "defaultv0"; 73 74 // The min number of tokens must present in Turn host uri. 75 // e.g. user (at) turn.example.org 76 static const size_t kTurnHostTokensNum = 2; 77 // Number of tokens must be preset when TURN uri has transport param. 78 static const size_t kTurnTransportTokensNum = 2; 79 // The default stun port. 80 static const int kDefaultStunPort = 3478; 81 static const int kDefaultStunTlsPort = 5349; 82 static const char kTransport[] = "transport"; 83 84 // NOTE: Must be in the same order as the ServiceType enum. 85 static const char* kValidIceServiceTypes[] = {"stun", "stuns", "turn", "turns"}; 86 87 // NOTE: A loop below assumes that the first value of this enum is 0 and all 88 // other values are incremental. 89 enum ServiceType { 90 STUN = 0, // Indicates a STUN server. 91 STUNS, // Indicates a STUN server used with a TLS session. 92 TURN, // Indicates a TURN server 93 TURNS, // Indicates a TURN server used with a TLS session. 94 INVALID, // Unknown. 95 }; 96 static_assert(INVALID == arraysize(kValidIceServiceTypes), 97 "kValidIceServiceTypes must have as many strings as ServiceType " 98 "has values."); 99 100 enum { 101 MSG_SET_SESSIONDESCRIPTION_SUCCESS = 0, 102 MSG_SET_SESSIONDESCRIPTION_FAILED, 103 MSG_CREATE_SESSIONDESCRIPTION_FAILED, 104 MSG_GETSTATS, 105 MSG_FREE_DATACHANNELS, 106 }; 107 108 struct SetSessionDescriptionMsg : public rtc::MessageData { 109 explicit SetSessionDescriptionMsg( 110 webrtc::SetSessionDescriptionObserver* observer) 111 : observer(observer) { 112 } 113 114 rtc::scoped_refptr<webrtc::SetSessionDescriptionObserver> observer; 115 std::string error; 116 }; 117 118 struct CreateSessionDescriptionMsg : public rtc::MessageData { 119 explicit CreateSessionDescriptionMsg( 120 webrtc::CreateSessionDescriptionObserver* observer) 121 : observer(observer) {} 122 123 rtc::scoped_refptr<webrtc::CreateSessionDescriptionObserver> observer; 124 std::string error; 125 }; 126 127 struct GetStatsMsg : public rtc::MessageData { 128 GetStatsMsg(webrtc::StatsObserver* observer, 129 webrtc::MediaStreamTrackInterface* track) 130 : observer(observer), track(track) { 131 } 132 rtc::scoped_refptr<webrtc::StatsObserver> observer; 133 rtc::scoped_refptr<webrtc::MediaStreamTrackInterface> track; 134 }; 135 136 // |in_str| should be of format 137 // stunURI = scheme ":" stun-host [ ":" stun-port ] 138 // scheme = "stun" / "stuns" 139 // stun-host = IP-literal / IPv4address / reg-name 140 // stun-port = *DIGIT 141 // 142 // draft-petithuguenin-behave-turn-uris-01 143 // turnURI = scheme ":" turn-host [ ":" turn-port ] 144 // turn-host = username@IP-literal / IPv4address / reg-name 145 bool GetServiceTypeAndHostnameFromUri(const std::string& in_str, 146 ServiceType* service_type, 147 std::string* hostname) { 148 const std::string::size_type colonpos = in_str.find(':'); 149 if (colonpos == std::string::npos) { 150 LOG(LS_WARNING) << "Missing ':' in ICE URI: " << in_str; 151 return false; 152 } 153 if ((colonpos + 1) == in_str.length()) { 154 LOG(LS_WARNING) << "Empty hostname in ICE URI: " << in_str; 155 return false; 156 } 157 *service_type = INVALID; 158 for (size_t i = 0; i < arraysize(kValidIceServiceTypes); ++i) { 159 if (in_str.compare(0, colonpos, kValidIceServiceTypes[i]) == 0) { 160 *service_type = static_cast<ServiceType>(i); 161 break; 162 } 163 } 164 if (*service_type == INVALID) { 165 return false; 166 } 167 *hostname = in_str.substr(colonpos + 1, std::string::npos); 168 return true; 169 } 170 171 bool ParsePort(const std::string& in_str, int* port) { 172 // Make sure port only contains digits. FromString doesn't check this. 173 for (const char& c : in_str) { 174 if (!std::isdigit(c)) { 175 return false; 176 } 177 } 178 return rtc::FromString(in_str, port); 179 } 180 181 // This method parses IPv6 and IPv4 literal strings, along with hostnames in 182 // standard hostname:port format. 183 // Consider following formats as correct. 184 // |hostname:port|, |[IPV6 address]:port|, |IPv4 address|:port, 185 // |hostname|, |[IPv6 address]|, |IPv4 address|. 186 bool ParseHostnameAndPortFromString(const std::string& in_str, 187 std::string* host, 188 int* port) { 189 RTC_DCHECK(host->empty()); 190 if (in_str.at(0) == '[') { 191 std::string::size_type closebracket = in_str.rfind(']'); 192 if (closebracket != std::string::npos) { 193 std::string::size_type colonpos = in_str.find(':', closebracket); 194 if (std::string::npos != colonpos) { 195 if (!ParsePort(in_str.substr(closebracket + 2, std::string::npos), 196 port)) { 197 return false; 198 } 199 } 200 *host = in_str.substr(1, closebracket - 1); 201 } else { 202 return false; 203 } 204 } else { 205 std::string::size_type colonpos = in_str.find(':'); 206 if (std::string::npos != colonpos) { 207 if (!ParsePort(in_str.substr(colonpos + 1, std::string::npos), port)) { 208 return false; 209 } 210 *host = in_str.substr(0, colonpos); 211 } else { 212 *host = in_str; 213 } 214 } 215 return !host->empty(); 216 } 217 218 // Adds a STUN or TURN server to the appropriate list, 219 // by parsing |url| and using the username/password in |server|. 220 bool ParseIceServerUrl(const PeerConnectionInterface::IceServer& server, 221 const std::string& url, 222 cricket::ServerAddresses* stun_servers, 223 std::vector<cricket::RelayServerConfig>* turn_servers) { 224 // draft-nandakumar-rtcweb-stun-uri-01 225 // stunURI = scheme ":" stun-host [ ":" stun-port ] 226 // scheme = "stun" / "stuns" 227 // stun-host = IP-literal / IPv4address / reg-name 228 // stun-port = *DIGIT 229 230 // draft-petithuguenin-behave-turn-uris-01 231 // turnURI = scheme ":" turn-host [ ":" turn-port ] 232 // [ "?transport=" transport ] 233 // scheme = "turn" / "turns" 234 // transport = "udp" / "tcp" / transport-ext 235 // transport-ext = 1*unreserved 236 // turn-host = IP-literal / IPv4address / reg-name 237 // turn-port = *DIGIT 238 RTC_DCHECK(stun_servers != nullptr); 239 RTC_DCHECK(turn_servers != nullptr); 240 std::vector<std::string> tokens; 241 cricket::ProtocolType turn_transport_type = cricket::PROTO_UDP; 242 RTC_DCHECK(!url.empty()); 243 rtc::tokenize(url, '?', &tokens); 244 std::string uri_without_transport = tokens[0]; 245 // Let's look into transport= param, if it exists. 246 if (tokens.size() == kTurnTransportTokensNum) { // ?transport= is present. 247 std::string uri_transport_param = tokens[1]; 248 rtc::tokenize(uri_transport_param, '=', &tokens); 249 if (tokens[0] == kTransport) { 250 // As per above grammar transport param will be consist of lower case 251 // letters. 252 if (!cricket::StringToProto(tokens[1].c_str(), &turn_transport_type) || 253 (turn_transport_type != cricket::PROTO_UDP && 254 turn_transport_type != cricket::PROTO_TCP)) { 255 LOG(LS_WARNING) << "Transport param should always be udp or tcp."; 256 return false; 257 } 258 } 259 } 260 261 std::string hoststring; 262 ServiceType service_type; 263 if (!GetServiceTypeAndHostnameFromUri(uri_without_transport, 264 &service_type, 265 &hoststring)) { 266 LOG(LS_WARNING) << "Invalid transport parameter in ICE URI: " << url; 267 return false; 268 } 269 270 // GetServiceTypeAndHostnameFromUri should never give an empty hoststring 271 RTC_DCHECK(!hoststring.empty()); 272 273 // Let's break hostname. 274 tokens.clear(); 275 rtc::tokenize_with_empty_tokens(hoststring, '@', &tokens); 276 277 std::string username(server.username); 278 if (tokens.size() > kTurnHostTokensNum) { 279 LOG(LS_WARNING) << "Invalid user@hostname format: " << hoststring; 280 return false; 281 } 282 if (tokens.size() == kTurnHostTokensNum) { 283 if (tokens[0].empty() || tokens[1].empty()) { 284 LOG(LS_WARNING) << "Invalid user@hostname format: " << hoststring; 285 return false; 286 } 287 username.assign(rtc::s_url_decode(tokens[0])); 288 hoststring = tokens[1]; 289 } else { 290 hoststring = tokens[0]; 291 } 292 293 int port = kDefaultStunPort; 294 if (service_type == TURNS) { 295 port = kDefaultStunTlsPort; 296 turn_transport_type = cricket::PROTO_TCP; 297 } 298 299 std::string address; 300 if (!ParseHostnameAndPortFromString(hoststring, &address, &port)) { 301 LOG(WARNING) << "Invalid hostname format: " << uri_without_transport; 302 return false; 303 } 304 305 if (port <= 0 || port > 0xffff) { 306 LOG(WARNING) << "Invalid port: " << port; 307 return false; 308 } 309 310 switch (service_type) { 311 case STUN: 312 case STUNS: 313 stun_servers->insert(rtc::SocketAddress(address, port)); 314 break; 315 case TURN: 316 case TURNS: { 317 bool secure = (service_type == TURNS); 318 turn_servers->push_back( 319 cricket::RelayServerConfig(address, port, username, server.password, 320 turn_transport_type, secure)); 321 break; 322 } 323 case INVALID: 324 default: 325 LOG(WARNING) << "Configuration not supported: " << url; 326 return false; 327 } 328 return true; 329 } 330 331 // Check if we can send |new_stream| on a PeerConnection. 332 bool CanAddLocalMediaStream(webrtc::StreamCollectionInterface* current_streams, 333 webrtc::MediaStreamInterface* new_stream) { 334 if (!new_stream || !current_streams) { 335 return false; 336 } 337 if (current_streams->find(new_stream->label()) != nullptr) { 338 LOG(LS_ERROR) << "MediaStream with label " << new_stream->label() 339 << " is already added."; 340 return false; 341 } 342 return true; 343 } 344 345 bool MediaContentDirectionHasSend(cricket::MediaContentDirection dir) { 346 return dir == cricket::MD_SENDONLY || dir == cricket::MD_SENDRECV; 347 } 348 349 // If the direction is "recvonly" or "inactive", treat the description 350 // as containing no streams. 351 // See: https://code.google.com/p/webrtc/issues/detail?id=5054 352 std::vector<cricket::StreamParams> GetActiveStreams( 353 const cricket::MediaContentDescription* desc) { 354 return MediaContentDirectionHasSend(desc->direction()) 355 ? desc->streams() 356 : std::vector<cricket::StreamParams>(); 357 } 358 359 bool IsValidOfferToReceiveMedia(int value) { 360 typedef PeerConnectionInterface::RTCOfferAnswerOptions Options; 361 return (value >= Options::kUndefined) && 362 (value <= Options::kMaxOfferToReceiveMedia); 363 } 364 365 // Add the stream and RTP data channel info to |session_options|. 366 void AddSendStreams( 367 cricket::MediaSessionOptions* session_options, 368 const std::vector<rtc::scoped_refptr<RtpSenderInterface>>& senders, 369 const std::map<std::string, rtc::scoped_refptr<DataChannel>>& 370 rtp_data_channels) { 371 session_options->streams.clear(); 372 for (const auto& sender : senders) { 373 session_options->AddSendStream(sender->media_type(), sender->id(), 374 sender->stream_id()); 375 } 376 377 // Check for data channels. 378 for (const auto& kv : rtp_data_channels) { 379 const DataChannel* channel = kv.second; 380 if (channel->state() == DataChannel::kConnecting || 381 channel->state() == DataChannel::kOpen) { 382 // |streamid| and |sync_label| are both set to the DataChannel label 383 // here so they can be signaled the same way as MediaStreams and Tracks. 384 // For MediaStreams, the sync_label is the MediaStream label and the 385 // track label is the same as |streamid|. 386 const std::string& streamid = channel->label(); 387 const std::string& sync_label = channel->label(); 388 session_options->AddSendStream(cricket::MEDIA_TYPE_DATA, streamid, 389 sync_label); 390 } 391 } 392 } 393 394 } // namespace 395 396 namespace webrtc { 397 398 // Factory class for creating remote MediaStreams and MediaStreamTracks. 399 class RemoteMediaStreamFactory { 400 public: 401 explicit RemoteMediaStreamFactory(rtc::Thread* signaling_thread, 402 cricket::ChannelManager* channel_manager) 403 : signaling_thread_(signaling_thread), 404 channel_manager_(channel_manager) {} 405 406 rtc::scoped_refptr<MediaStreamInterface> CreateMediaStream( 407 const std::string& stream_label) { 408 return MediaStreamProxy::Create(signaling_thread_, 409 MediaStream::Create(stream_label)); 410 } 411 412 AudioTrackInterface* AddAudioTrack(uint32_t ssrc, 413 AudioProviderInterface* provider, 414 webrtc::MediaStreamInterface* stream, 415 const std::string& track_id) { 416 return AddTrack<AudioTrackInterface, AudioTrack, AudioTrackProxy>( 417 stream, track_id, RemoteAudioSource::Create(ssrc, provider)); 418 } 419 420 VideoTrackInterface* AddVideoTrack(webrtc::MediaStreamInterface* stream, 421 const std::string& track_id) { 422 return AddTrack<VideoTrackInterface, VideoTrack, VideoTrackProxy>( 423 stream, track_id, 424 VideoSource::Create(channel_manager_, new RemoteVideoCapturer(), 425 nullptr, true) 426 .get()); 427 } 428 429 private: 430 template <typename TI, typename T, typename TP, typename S> 431 TI* AddTrack(MediaStreamInterface* stream, 432 const std::string& track_id, 433 const S& source) { 434 rtc::scoped_refptr<TI> track( 435 TP::Create(signaling_thread_, T::Create(track_id, source))); 436 track->set_state(webrtc::MediaStreamTrackInterface::kLive); 437 if (stream->AddTrack(track)) { 438 return track; 439 } 440 return nullptr; 441 } 442 443 rtc::Thread* signaling_thread_; 444 cricket::ChannelManager* channel_manager_; 445 }; 446 447 bool ConvertRtcOptionsForOffer( 448 const PeerConnectionInterface::RTCOfferAnswerOptions& rtc_options, 449 cricket::MediaSessionOptions* session_options) { 450 typedef PeerConnectionInterface::RTCOfferAnswerOptions RTCOfferAnswerOptions; 451 if (!IsValidOfferToReceiveMedia(rtc_options.offer_to_receive_audio) || 452 !IsValidOfferToReceiveMedia(rtc_options.offer_to_receive_video)) { 453 return false; 454 } 455 456 if (rtc_options.offer_to_receive_audio != RTCOfferAnswerOptions::kUndefined) { 457 session_options->recv_audio = (rtc_options.offer_to_receive_audio > 0); 458 } 459 if (rtc_options.offer_to_receive_video != RTCOfferAnswerOptions::kUndefined) { 460 session_options->recv_video = (rtc_options.offer_to_receive_video > 0); 461 } 462 463 session_options->vad_enabled = rtc_options.voice_activity_detection; 464 session_options->audio_transport_options.ice_restart = 465 rtc_options.ice_restart; 466 session_options->video_transport_options.ice_restart = 467 rtc_options.ice_restart; 468 session_options->data_transport_options.ice_restart = rtc_options.ice_restart; 469 session_options->bundle_enabled = rtc_options.use_rtp_mux; 470 471 return true; 472 } 473 474 bool ParseConstraintsForAnswer(const MediaConstraintsInterface* constraints, 475 cricket::MediaSessionOptions* session_options) { 476 bool value = false; 477 size_t mandatory_constraints_satisfied = 0; 478 479 // kOfferToReceiveAudio defaults to true according to spec. 480 if (!FindConstraint(constraints, 481 MediaConstraintsInterface::kOfferToReceiveAudio, &value, 482 &mandatory_constraints_satisfied) || 483 value) { 484 session_options->recv_audio = true; 485 } 486 487 // kOfferToReceiveVideo defaults to false according to spec. But 488 // if it is an answer and video is offered, we should still accept video 489 // per default. 490 value = false; 491 if (!FindConstraint(constraints, 492 MediaConstraintsInterface::kOfferToReceiveVideo, &value, 493 &mandatory_constraints_satisfied) || 494 value) { 495 session_options->recv_video = true; 496 } 497 498 if (FindConstraint(constraints, 499 MediaConstraintsInterface::kVoiceActivityDetection, &value, 500 &mandatory_constraints_satisfied)) { 501 session_options->vad_enabled = value; 502 } 503 504 if (FindConstraint(constraints, MediaConstraintsInterface::kUseRtpMux, &value, 505 &mandatory_constraints_satisfied)) { 506 session_options->bundle_enabled = value; 507 } else { 508 // kUseRtpMux defaults to true according to spec. 509 session_options->bundle_enabled = true; 510 } 511 512 if (FindConstraint(constraints, MediaConstraintsInterface::kIceRestart, 513 &value, &mandatory_constraints_satisfied)) { 514 session_options->audio_transport_options.ice_restart = value; 515 session_options->video_transport_options.ice_restart = value; 516 session_options->data_transport_options.ice_restart = value; 517 } else { 518 // kIceRestart defaults to false according to spec. 519 session_options->audio_transport_options.ice_restart = false; 520 session_options->video_transport_options.ice_restart = false; 521 session_options->data_transport_options.ice_restart = false; 522 } 523 524 if (!constraints) { 525 return true; 526 } 527 return mandatory_constraints_satisfied == constraints->GetMandatory().size(); 528 } 529 530 bool ParseIceServers(const PeerConnectionInterface::IceServers& servers, 531 cricket::ServerAddresses* stun_servers, 532 std::vector<cricket::RelayServerConfig>* turn_servers) { 533 for (const webrtc::PeerConnectionInterface::IceServer& server : servers) { 534 if (!server.urls.empty()) { 535 for (const std::string& url : server.urls) { 536 if (url.empty()) { 537 LOG(LS_ERROR) << "Empty uri."; 538 return false; 539 } 540 if (!ParseIceServerUrl(server, url, stun_servers, turn_servers)) { 541 return false; 542 } 543 } 544 } else if (!server.uri.empty()) { 545 // Fallback to old .uri if new .urls isn't present. 546 if (!ParseIceServerUrl(server, server.uri, stun_servers, turn_servers)) { 547 return false; 548 } 549 } else { 550 LOG(LS_ERROR) << "Empty uri."; 551 return false; 552 } 553 } 554 // Candidates must have unique priorities, so that connectivity checks 555 // are performed in a well-defined order. 556 int priority = static_cast<int>(turn_servers->size() - 1); 557 for (cricket::RelayServerConfig& turn_server : *turn_servers) { 558 // First in the list gets highest priority. 559 turn_server.priority = priority--; 560 } 561 return true; 562 } 563 564 PeerConnection::PeerConnection(PeerConnectionFactory* factory) 565 : factory_(factory), 566 observer_(NULL), 567 uma_observer_(NULL), 568 signaling_state_(kStable), 569 ice_state_(kIceNew), 570 ice_connection_state_(kIceConnectionNew), 571 ice_gathering_state_(kIceGatheringNew), 572 local_streams_(StreamCollection::Create()), 573 remote_streams_(StreamCollection::Create()) {} 574 575 PeerConnection::~PeerConnection() { 576 TRACE_EVENT0("webrtc", "PeerConnection::~PeerConnection"); 577 RTC_DCHECK(signaling_thread()->IsCurrent()); 578 // Need to detach RTP senders/receivers from WebRtcSession, 579 // since it's about to be destroyed. 580 for (const auto& sender : senders_) { 581 sender->Stop(); 582 } 583 for (const auto& receiver : receivers_) { 584 receiver->Stop(); 585 } 586 } 587 588 bool PeerConnection::Initialize( 589 const PeerConnectionInterface::RTCConfiguration& configuration, 590 const MediaConstraintsInterface* constraints, 591 rtc::scoped_ptr<cricket::PortAllocator> allocator, 592 rtc::scoped_ptr<DtlsIdentityStoreInterface> dtls_identity_store, 593 PeerConnectionObserver* observer) { 594 TRACE_EVENT0("webrtc", "PeerConnection::Initialize"); 595 RTC_DCHECK(observer != nullptr); 596 if (!observer) { 597 return false; 598 } 599 observer_ = observer; 600 601 port_allocator_ = std::move(allocator); 602 603 cricket::ServerAddresses stun_servers; 604 std::vector<cricket::RelayServerConfig> turn_servers; 605 if (!ParseIceServers(configuration.servers, &stun_servers, &turn_servers)) { 606 return false; 607 } 608 port_allocator_->SetIceServers(stun_servers, turn_servers); 609 610 // To handle both internal and externally created port allocator, we will 611 // enable BUNDLE here. 612 int portallocator_flags = port_allocator_->flags(); 613 portallocator_flags |= cricket::PORTALLOCATOR_ENABLE_SHARED_SOCKET | 614 cricket::PORTALLOCATOR_ENABLE_IPV6; 615 bool value; 616 // If IPv6 flag was specified, we'll not override it by experiment. 617 if (FindConstraint(constraints, MediaConstraintsInterface::kEnableIPv6, 618 &value, nullptr)) { 619 if (!value) { 620 portallocator_flags &= ~(cricket::PORTALLOCATOR_ENABLE_IPV6); 621 } 622 } else if (webrtc::field_trial::FindFullName("WebRTC-IPv6Default") == 623 "Disabled") { 624 portallocator_flags &= ~(cricket::PORTALLOCATOR_ENABLE_IPV6); 625 } 626 627 if (configuration.tcp_candidate_policy == kTcpCandidatePolicyDisabled) { 628 portallocator_flags |= cricket::PORTALLOCATOR_DISABLE_TCP; 629 LOG(LS_INFO) << "TCP candidates are disabled."; 630 } 631 632 port_allocator_->set_flags(portallocator_flags); 633 // No step delay is used while allocating ports. 634 port_allocator_->set_step_delay(cricket::kMinimumStepDelay); 635 636 media_controller_.reset(factory_->CreateMediaController()); 637 638 remote_stream_factory_.reset(new RemoteMediaStreamFactory( 639 factory_->signaling_thread(), media_controller_->channel_manager())); 640 641 session_.reset( 642 new WebRtcSession(media_controller_.get(), factory_->signaling_thread(), 643 factory_->worker_thread(), port_allocator_.get())); 644 stats_.reset(new StatsCollector(this)); 645 646 // Initialize the WebRtcSession. It creates transport channels etc. 647 if (!session_->Initialize(factory_->options(), constraints, 648 std::move(dtls_identity_store), configuration)) { 649 return false; 650 } 651 652 // Register PeerConnection as receiver of local ice candidates. 653 // All the callbacks will be posted to the application from PeerConnection. 654 session_->RegisterIceObserver(this); 655 session_->SignalState.connect(this, &PeerConnection::OnSessionStateChange); 656 session_->SignalVoiceChannelDestroyed.connect( 657 this, &PeerConnection::OnVoiceChannelDestroyed); 658 session_->SignalVideoChannelDestroyed.connect( 659 this, &PeerConnection::OnVideoChannelDestroyed); 660 session_->SignalDataChannelCreated.connect( 661 this, &PeerConnection::OnDataChannelCreated); 662 session_->SignalDataChannelDestroyed.connect( 663 this, &PeerConnection::OnDataChannelDestroyed); 664 session_->SignalDataChannelOpenMessage.connect( 665 this, &PeerConnection::OnDataChannelOpenMessage); 666 return true; 667 } 668 669 rtc::scoped_refptr<StreamCollectionInterface> 670 PeerConnection::local_streams() { 671 return local_streams_; 672 } 673 674 rtc::scoped_refptr<StreamCollectionInterface> 675 PeerConnection::remote_streams() { 676 return remote_streams_; 677 } 678 679 bool PeerConnection::AddStream(MediaStreamInterface* local_stream) { 680 TRACE_EVENT0("webrtc", "PeerConnection::AddStream"); 681 if (IsClosed()) { 682 return false; 683 } 684 if (!CanAddLocalMediaStream(local_streams_, local_stream)) { 685 return false; 686 } 687 688 local_streams_->AddStream(local_stream); 689 MediaStreamObserver* observer = new MediaStreamObserver(local_stream); 690 observer->SignalAudioTrackAdded.connect(this, 691 &PeerConnection::OnAudioTrackAdded); 692 observer->SignalAudioTrackRemoved.connect( 693 this, &PeerConnection::OnAudioTrackRemoved); 694 observer->SignalVideoTrackAdded.connect(this, 695 &PeerConnection::OnVideoTrackAdded); 696 observer->SignalVideoTrackRemoved.connect( 697 this, &PeerConnection::OnVideoTrackRemoved); 698 stream_observers_.push_back(rtc::scoped_ptr<MediaStreamObserver>(observer)); 699 700 for (const auto& track : local_stream->GetAudioTracks()) { 701 OnAudioTrackAdded(track.get(), local_stream); 702 } 703 for (const auto& track : local_stream->GetVideoTracks()) { 704 OnVideoTrackAdded(track.get(), local_stream); 705 } 706 707 stats_->AddStream(local_stream); 708 observer_->OnRenegotiationNeeded(); 709 return true; 710 } 711 712 void PeerConnection::RemoveStream(MediaStreamInterface* local_stream) { 713 TRACE_EVENT0("webrtc", "PeerConnection::RemoveStream"); 714 for (const auto& track : local_stream->GetAudioTracks()) { 715 OnAudioTrackRemoved(track.get(), local_stream); 716 } 717 for (const auto& track : local_stream->GetVideoTracks()) { 718 OnVideoTrackRemoved(track.get(), local_stream); 719 } 720 721 local_streams_->RemoveStream(local_stream); 722 stream_observers_.erase( 723 std::remove_if( 724 stream_observers_.begin(), stream_observers_.end(), 725 [local_stream](const rtc::scoped_ptr<MediaStreamObserver>& observer) { 726 return observer->stream()->label().compare(local_stream->label()) == 727 0; 728 }), 729 stream_observers_.end()); 730 731 if (IsClosed()) { 732 return; 733 } 734 observer_->OnRenegotiationNeeded(); 735 } 736 737 rtc::scoped_refptr<DtmfSenderInterface> PeerConnection::CreateDtmfSender( 738 AudioTrackInterface* track) { 739 TRACE_EVENT0("webrtc", "PeerConnection::CreateDtmfSender"); 740 if (!track) { 741 LOG(LS_ERROR) << "CreateDtmfSender - track is NULL."; 742 return NULL; 743 } 744 if (!local_streams_->FindAudioTrack(track->id())) { 745 LOG(LS_ERROR) << "CreateDtmfSender is called with a non local audio track."; 746 return NULL; 747 } 748 749 rtc::scoped_refptr<DtmfSenderInterface> sender( 750 DtmfSender::Create(track, signaling_thread(), session_.get())); 751 if (!sender.get()) { 752 LOG(LS_ERROR) << "CreateDtmfSender failed on DtmfSender::Create."; 753 return NULL; 754 } 755 return DtmfSenderProxy::Create(signaling_thread(), sender.get()); 756 } 757 758 rtc::scoped_refptr<RtpSenderInterface> PeerConnection::CreateSender( 759 const std::string& kind, 760 const std::string& stream_id) { 761 TRACE_EVENT0("webrtc", "PeerConnection::CreateSender"); 762 RtpSenderInterface* new_sender; 763 if (kind == MediaStreamTrackInterface::kAudioKind) { 764 new_sender = new AudioRtpSender(session_.get(), stats_.get()); 765 } else if (kind == MediaStreamTrackInterface::kVideoKind) { 766 new_sender = new VideoRtpSender(session_.get()); 767 } else { 768 LOG(LS_ERROR) << "CreateSender called with invalid kind: " << kind; 769 return rtc::scoped_refptr<RtpSenderInterface>(); 770 } 771 if (!stream_id.empty()) { 772 new_sender->set_stream_id(stream_id); 773 } 774 senders_.push_back(new_sender); 775 return RtpSenderProxy::Create(signaling_thread(), new_sender); 776 } 777 778 std::vector<rtc::scoped_refptr<RtpSenderInterface>> PeerConnection::GetSenders() 779 const { 780 std::vector<rtc::scoped_refptr<RtpSenderInterface>> senders; 781 for (const auto& sender : senders_) { 782 senders.push_back(RtpSenderProxy::Create(signaling_thread(), sender.get())); 783 } 784 return senders; 785 } 786 787 std::vector<rtc::scoped_refptr<RtpReceiverInterface>> 788 PeerConnection::GetReceivers() const { 789 std::vector<rtc::scoped_refptr<RtpReceiverInterface>> receivers; 790 for (const auto& receiver : receivers_) { 791 receivers.push_back( 792 RtpReceiverProxy::Create(signaling_thread(), receiver.get())); 793 } 794 return receivers; 795 } 796 797 bool PeerConnection::GetStats(StatsObserver* observer, 798 MediaStreamTrackInterface* track, 799 StatsOutputLevel level) { 800 TRACE_EVENT0("webrtc", "PeerConnection::GetStats"); 801 RTC_DCHECK(signaling_thread()->IsCurrent()); 802 if (!VERIFY(observer != NULL)) { 803 LOG(LS_ERROR) << "GetStats - observer is NULL."; 804 return false; 805 } 806 807 stats_->UpdateStats(level); 808 signaling_thread()->Post(this, MSG_GETSTATS, 809 new GetStatsMsg(observer, track)); 810 return true; 811 } 812 813 PeerConnectionInterface::SignalingState PeerConnection::signaling_state() { 814 return signaling_state_; 815 } 816 817 PeerConnectionInterface::IceState PeerConnection::ice_state() { 818 return ice_state_; 819 } 820 821 PeerConnectionInterface::IceConnectionState 822 PeerConnection::ice_connection_state() { 823 return ice_connection_state_; 824 } 825 826 PeerConnectionInterface::IceGatheringState 827 PeerConnection::ice_gathering_state() { 828 return ice_gathering_state_; 829 } 830 831 rtc::scoped_refptr<DataChannelInterface> 832 PeerConnection::CreateDataChannel( 833 const std::string& label, 834 const DataChannelInit* config) { 835 TRACE_EVENT0("webrtc", "PeerConnection::CreateDataChannel"); 836 bool first_datachannel = !HasDataChannels(); 837 838 rtc::scoped_ptr<InternalDataChannelInit> internal_config; 839 if (config) { 840 internal_config.reset(new InternalDataChannelInit(*config)); 841 } 842 rtc::scoped_refptr<DataChannelInterface> channel( 843 InternalCreateDataChannel(label, internal_config.get())); 844 if (!channel.get()) { 845 return nullptr; 846 } 847 848 // Trigger the onRenegotiationNeeded event for every new RTP DataChannel, or 849 // the first SCTP DataChannel. 850 if (session_->data_channel_type() == cricket::DCT_RTP || first_datachannel) { 851 observer_->OnRenegotiationNeeded(); 852 } 853 854 return DataChannelProxy::Create(signaling_thread(), channel.get()); 855 } 856 857 void PeerConnection::CreateOffer(CreateSessionDescriptionObserver* observer, 858 const MediaConstraintsInterface* constraints) { 859 TRACE_EVENT0("webrtc", "PeerConnection::CreateOffer"); 860 if (!VERIFY(observer != nullptr)) { 861 LOG(LS_ERROR) << "CreateOffer - observer is NULL."; 862 return; 863 } 864 RTCOfferAnswerOptions options; 865 866 bool value; 867 size_t mandatory_constraints = 0; 868 869 if (FindConstraint(constraints, 870 MediaConstraintsInterface::kOfferToReceiveAudio, 871 &value, 872 &mandatory_constraints)) { 873 options.offer_to_receive_audio = 874 value ? RTCOfferAnswerOptions::kOfferToReceiveMediaTrue : 0; 875 } 876 877 if (FindConstraint(constraints, 878 MediaConstraintsInterface::kOfferToReceiveVideo, 879 &value, 880 &mandatory_constraints)) { 881 options.offer_to_receive_video = 882 value ? RTCOfferAnswerOptions::kOfferToReceiveMediaTrue : 0; 883 } 884 885 if (FindConstraint(constraints, 886 MediaConstraintsInterface::kVoiceActivityDetection, 887 &value, 888 &mandatory_constraints)) { 889 options.voice_activity_detection = value; 890 } 891 892 if (FindConstraint(constraints, 893 MediaConstraintsInterface::kIceRestart, 894 &value, 895 &mandatory_constraints)) { 896 options.ice_restart = value; 897 } 898 899 if (FindConstraint(constraints, 900 MediaConstraintsInterface::kUseRtpMux, 901 &value, 902 &mandatory_constraints)) { 903 options.use_rtp_mux = value; 904 } 905 906 CreateOffer(observer, options); 907 } 908 909 void PeerConnection::CreateOffer(CreateSessionDescriptionObserver* observer, 910 const RTCOfferAnswerOptions& options) { 911 TRACE_EVENT0("webrtc", "PeerConnection::CreateOffer"); 912 if (!VERIFY(observer != nullptr)) { 913 LOG(LS_ERROR) << "CreateOffer - observer is NULL."; 914 return; 915 } 916 917 cricket::MediaSessionOptions session_options; 918 if (!GetOptionsForOffer(options, &session_options)) { 919 std::string error = "CreateOffer called with invalid options."; 920 LOG(LS_ERROR) << error; 921 PostCreateSessionDescriptionFailure(observer, error); 922 return; 923 } 924 925 session_->CreateOffer(observer, options, session_options); 926 } 927 928 void PeerConnection::CreateAnswer( 929 CreateSessionDescriptionObserver* observer, 930 const MediaConstraintsInterface* constraints) { 931 TRACE_EVENT0("webrtc", "PeerConnection::CreateAnswer"); 932 if (!VERIFY(observer != nullptr)) { 933 LOG(LS_ERROR) << "CreateAnswer - observer is NULL."; 934 return; 935 } 936 937 cricket::MediaSessionOptions session_options; 938 if (!GetOptionsForAnswer(constraints, &session_options)) { 939 std::string error = "CreateAnswer called with invalid constraints."; 940 LOG(LS_ERROR) << error; 941 PostCreateSessionDescriptionFailure(observer, error); 942 return; 943 } 944 945 session_->CreateAnswer(observer, constraints, session_options); 946 } 947 948 void PeerConnection::SetLocalDescription( 949 SetSessionDescriptionObserver* observer, 950 SessionDescriptionInterface* desc) { 951 TRACE_EVENT0("webrtc", "PeerConnection::SetLocalDescription"); 952 if (!VERIFY(observer != nullptr)) { 953 LOG(LS_ERROR) << "SetLocalDescription - observer is NULL."; 954 return; 955 } 956 if (!desc) { 957 PostSetSessionDescriptionFailure(observer, "SessionDescription is NULL."); 958 return; 959 } 960 // Update stats here so that we have the most recent stats for tracks and 961 // streams that might be removed by updating the session description. 962 stats_->UpdateStats(kStatsOutputLevelStandard); 963 std::string error; 964 if (!session_->SetLocalDescription(desc, &error)) { 965 PostSetSessionDescriptionFailure(observer, error); 966 return; 967 } 968 969 // If setting the description decided our SSL role, allocate any necessary 970 // SCTP sids. 971 rtc::SSLRole role; 972 if (session_->data_channel_type() == cricket::DCT_SCTP && 973 session_->GetSslRole(session_->data_channel(), &role)) { 974 AllocateSctpSids(role); 975 } 976 977 // Update state and SSRC of local MediaStreams and DataChannels based on the 978 // local session description. 979 const cricket::ContentInfo* audio_content = 980 GetFirstAudioContent(desc->description()); 981 if (audio_content) { 982 if (audio_content->rejected) { 983 RemoveTracks(cricket::MEDIA_TYPE_AUDIO); 984 } else { 985 const cricket::AudioContentDescription* audio_desc = 986 static_cast<const cricket::AudioContentDescription*>( 987 audio_content->description); 988 UpdateLocalTracks(audio_desc->streams(), audio_desc->type()); 989 } 990 } 991 992 const cricket::ContentInfo* video_content = 993 GetFirstVideoContent(desc->description()); 994 if (video_content) { 995 if (video_content->rejected) { 996 RemoveTracks(cricket::MEDIA_TYPE_VIDEO); 997 } else { 998 const cricket::VideoContentDescription* video_desc = 999 static_cast<const cricket::VideoContentDescription*>( 1000 video_content->description); 1001 UpdateLocalTracks(video_desc->streams(), video_desc->type()); 1002 } 1003 } 1004 1005 const cricket::ContentInfo* data_content = 1006 GetFirstDataContent(desc->description()); 1007 if (data_content) { 1008 const cricket::DataContentDescription* data_desc = 1009 static_cast<const cricket::DataContentDescription*>( 1010 data_content->description); 1011 if (rtc::starts_with(data_desc->protocol().data(), 1012 cricket::kMediaProtocolRtpPrefix)) { 1013 UpdateLocalRtpDataChannels(data_desc->streams()); 1014 } 1015 } 1016 1017 SetSessionDescriptionMsg* msg = new SetSessionDescriptionMsg(observer); 1018 signaling_thread()->Post(this, MSG_SET_SESSIONDESCRIPTION_SUCCESS, msg); 1019 1020 // MaybeStartGathering needs to be called after posting 1021 // MSG_SET_SESSIONDESCRIPTION_SUCCESS, so that we don't signal any candidates 1022 // before signaling that SetLocalDescription completed. 1023 session_->MaybeStartGathering(); 1024 } 1025 1026 void PeerConnection::SetRemoteDescription( 1027 SetSessionDescriptionObserver* observer, 1028 SessionDescriptionInterface* desc) { 1029 TRACE_EVENT0("webrtc", "PeerConnection::SetRemoteDescription"); 1030 if (!VERIFY(observer != nullptr)) { 1031 LOG(LS_ERROR) << "SetRemoteDescription - observer is NULL."; 1032 return; 1033 } 1034 if (!desc) { 1035 PostSetSessionDescriptionFailure(observer, "SessionDescription is NULL."); 1036 return; 1037 } 1038 // Update stats here so that we have the most recent stats for tracks and 1039 // streams that might be removed by updating the session description. 1040 stats_->UpdateStats(kStatsOutputLevelStandard); 1041 std::string error; 1042 if (!session_->SetRemoteDescription(desc, &error)) { 1043 PostSetSessionDescriptionFailure(observer, error); 1044 return; 1045 } 1046 1047 // If setting the description decided our SSL role, allocate any necessary 1048 // SCTP sids. 1049 rtc::SSLRole role; 1050 if (session_->data_channel_type() == cricket::DCT_SCTP && 1051 session_->GetSslRole(session_->data_channel(), &role)) { 1052 AllocateSctpSids(role); 1053 } 1054 1055 const cricket::SessionDescription* remote_desc = desc->description(); 1056 const cricket::ContentInfo* audio_content = GetFirstAudioContent(remote_desc); 1057 const cricket::ContentInfo* video_content = GetFirstVideoContent(remote_desc); 1058 const cricket::AudioContentDescription* audio_desc = 1059 GetFirstAudioContentDescription(remote_desc); 1060 const cricket::VideoContentDescription* video_desc = 1061 GetFirstVideoContentDescription(remote_desc); 1062 const cricket::DataContentDescription* data_desc = 1063 GetFirstDataContentDescription(remote_desc); 1064 1065 // Check if the descriptions include streams, just in case the peer supports 1066 // MSID, but doesn't indicate so with "a=msid-semantic". 1067 if (remote_desc->msid_supported() || 1068 (audio_desc && !audio_desc->streams().empty()) || 1069 (video_desc && !video_desc->streams().empty())) { 1070 remote_peer_supports_msid_ = true; 1071 } 1072 1073 // We wait to signal new streams until we finish processing the description, 1074 // since only at that point will new streams have all their tracks. 1075 rtc::scoped_refptr<StreamCollection> new_streams(StreamCollection::Create()); 1076 1077 // Find all audio rtp streams and create corresponding remote AudioTracks 1078 // and MediaStreams. 1079 if (audio_content) { 1080 if (audio_content->rejected) { 1081 RemoveTracks(cricket::MEDIA_TYPE_AUDIO); 1082 } else { 1083 bool default_audio_track_needed = 1084 !remote_peer_supports_msid_ && 1085 MediaContentDirectionHasSend(audio_desc->direction()); 1086 UpdateRemoteStreamsList(GetActiveStreams(audio_desc), 1087 default_audio_track_needed, audio_desc->type(), 1088 new_streams); 1089 } 1090 } 1091 1092 // Find all video rtp streams and create corresponding remote VideoTracks 1093 // and MediaStreams. 1094 if (video_content) { 1095 if (video_content->rejected) { 1096 RemoveTracks(cricket::MEDIA_TYPE_VIDEO); 1097 } else { 1098 bool default_video_track_needed = 1099 !remote_peer_supports_msid_ && 1100 MediaContentDirectionHasSend(video_desc->direction()); 1101 UpdateRemoteStreamsList(GetActiveStreams(video_desc), 1102 default_video_track_needed, video_desc->type(), 1103 new_streams); 1104 } 1105 } 1106 1107 // Update the DataChannels with the information from the remote peer. 1108 if (data_desc) { 1109 if (rtc::starts_with(data_desc->protocol().data(), 1110 cricket::kMediaProtocolRtpPrefix)) { 1111 UpdateRemoteRtpDataChannels(GetActiveStreams(data_desc)); 1112 } 1113 } 1114 1115 // Iterate new_streams and notify the observer about new MediaStreams. 1116 for (size_t i = 0; i < new_streams->count(); ++i) { 1117 MediaStreamInterface* new_stream = new_streams->at(i); 1118 stats_->AddStream(new_stream); 1119 observer_->OnAddStream(new_stream); 1120 } 1121 1122 UpdateEndedRemoteMediaStreams(); 1123 1124 SetSessionDescriptionMsg* msg = new SetSessionDescriptionMsg(observer); 1125 signaling_thread()->Post(this, MSG_SET_SESSIONDESCRIPTION_SUCCESS, msg); 1126 } 1127 1128 bool PeerConnection::SetConfiguration(const RTCConfiguration& config) { 1129 TRACE_EVENT0("webrtc", "PeerConnection::SetConfiguration"); 1130 if (port_allocator_) { 1131 cricket::ServerAddresses stun_servers; 1132 std::vector<cricket::RelayServerConfig> turn_servers; 1133 if (!ParseIceServers(config.servers, &stun_servers, &turn_servers)) { 1134 return false; 1135 } 1136 port_allocator_->SetIceServers(stun_servers, turn_servers); 1137 } 1138 session_->SetIceConfig(session_->ParseIceConfig(config)); 1139 return session_->SetIceTransports(config.type); 1140 } 1141 1142 bool PeerConnection::AddIceCandidate( 1143 const IceCandidateInterface* ice_candidate) { 1144 TRACE_EVENT0("webrtc", "PeerConnection::AddIceCandidate"); 1145 return session_->ProcessIceMessage(ice_candidate); 1146 } 1147 1148 void PeerConnection::RegisterUMAObserver(UMAObserver* observer) { 1149 TRACE_EVENT0("webrtc", "PeerConnection::RegisterUmaObserver"); 1150 uma_observer_ = observer; 1151 1152 if (session_) { 1153 session_->set_metrics_observer(uma_observer_); 1154 } 1155 1156 // Send information about IPv4/IPv6 status. 1157 if (uma_observer_ && port_allocator_) { 1158 if (port_allocator_->flags() & cricket::PORTALLOCATOR_ENABLE_IPV6) { 1159 uma_observer_->IncrementEnumCounter( 1160 kEnumCounterAddressFamily, kPeerConnection_IPv6, 1161 kPeerConnectionAddressFamilyCounter_Max); 1162 } else { 1163 uma_observer_->IncrementEnumCounter( 1164 kEnumCounterAddressFamily, kPeerConnection_IPv4, 1165 kPeerConnectionAddressFamilyCounter_Max); 1166 } 1167 } 1168 } 1169 1170 const SessionDescriptionInterface* PeerConnection::local_description() const { 1171 return session_->local_description(); 1172 } 1173 1174 const SessionDescriptionInterface* PeerConnection::remote_description() const { 1175 return session_->remote_description(); 1176 } 1177 1178 void PeerConnection::Close() { 1179 TRACE_EVENT0("webrtc", "PeerConnection::Close"); 1180 // Update stats here so that we have the most recent stats for tracks and 1181 // streams before the channels are closed. 1182 stats_->UpdateStats(kStatsOutputLevelStandard); 1183 1184 session_->Close(); 1185 } 1186 1187 void PeerConnection::OnSessionStateChange(WebRtcSession* /*session*/, 1188 WebRtcSession::State state) { 1189 switch (state) { 1190 case WebRtcSession::STATE_INIT: 1191 ChangeSignalingState(PeerConnectionInterface::kStable); 1192 break; 1193 case WebRtcSession::STATE_SENTOFFER: 1194 ChangeSignalingState(PeerConnectionInterface::kHaveLocalOffer); 1195 break; 1196 case WebRtcSession::STATE_SENTPRANSWER: 1197 ChangeSignalingState(PeerConnectionInterface::kHaveLocalPrAnswer); 1198 break; 1199 case WebRtcSession::STATE_RECEIVEDOFFER: 1200 ChangeSignalingState(PeerConnectionInterface::kHaveRemoteOffer); 1201 break; 1202 case WebRtcSession::STATE_RECEIVEDPRANSWER: 1203 ChangeSignalingState(PeerConnectionInterface::kHaveRemotePrAnswer); 1204 break; 1205 case WebRtcSession::STATE_INPROGRESS: 1206 ChangeSignalingState(PeerConnectionInterface::kStable); 1207 break; 1208 case WebRtcSession::STATE_CLOSED: 1209 ChangeSignalingState(PeerConnectionInterface::kClosed); 1210 break; 1211 default: 1212 break; 1213 } 1214 } 1215 1216 void PeerConnection::OnMessage(rtc::Message* msg) { 1217 switch (msg->message_id) { 1218 case MSG_SET_SESSIONDESCRIPTION_SUCCESS: { 1219 SetSessionDescriptionMsg* param = 1220 static_cast<SetSessionDescriptionMsg*>(msg->pdata); 1221 param->observer->OnSuccess(); 1222 delete param; 1223 break; 1224 } 1225 case MSG_SET_SESSIONDESCRIPTION_FAILED: { 1226 SetSessionDescriptionMsg* param = 1227 static_cast<SetSessionDescriptionMsg*>(msg->pdata); 1228 param->observer->OnFailure(param->error); 1229 delete param; 1230 break; 1231 } 1232 case MSG_CREATE_SESSIONDESCRIPTION_FAILED: { 1233 CreateSessionDescriptionMsg* param = 1234 static_cast<CreateSessionDescriptionMsg*>(msg->pdata); 1235 param->observer->OnFailure(param->error); 1236 delete param; 1237 break; 1238 } 1239 case MSG_GETSTATS: { 1240 GetStatsMsg* param = static_cast<GetStatsMsg*>(msg->pdata); 1241 StatsReports reports; 1242 stats_->GetStats(param->track, &reports); 1243 param->observer->OnComplete(reports); 1244 delete param; 1245 break; 1246 } 1247 case MSG_FREE_DATACHANNELS: { 1248 sctp_data_channels_to_free_.clear(); 1249 break; 1250 } 1251 default: 1252 RTC_DCHECK(false && "Not implemented"); 1253 break; 1254 } 1255 } 1256 1257 void PeerConnection::CreateAudioReceiver(MediaStreamInterface* stream, 1258 AudioTrackInterface* audio_track, 1259 uint32_t ssrc) { 1260 receivers_.push_back(new AudioRtpReceiver(audio_track, ssrc, session_.get())); 1261 } 1262 1263 void PeerConnection::CreateVideoReceiver(MediaStreamInterface* stream, 1264 VideoTrackInterface* video_track, 1265 uint32_t ssrc) { 1266 receivers_.push_back(new VideoRtpReceiver(video_track, ssrc, session_.get())); 1267 } 1268 1269 // TODO(deadbeef): Keep RtpReceivers around even if track goes away in remote 1270 // description. 1271 void PeerConnection::DestroyAudioReceiver(MediaStreamInterface* stream, 1272 AudioTrackInterface* audio_track) { 1273 auto it = FindReceiverForTrack(audio_track); 1274 if (it == receivers_.end()) { 1275 LOG(LS_WARNING) << "RtpReceiver for track with id " << audio_track->id() 1276 << " doesn't exist."; 1277 } else { 1278 (*it)->Stop(); 1279 receivers_.erase(it); 1280 } 1281 } 1282 1283 void PeerConnection::DestroyVideoReceiver(MediaStreamInterface* stream, 1284 VideoTrackInterface* video_track) { 1285 auto it = FindReceiverForTrack(video_track); 1286 if (it == receivers_.end()) { 1287 LOG(LS_WARNING) << "RtpReceiver for track with id " << video_track->id() 1288 << " doesn't exist."; 1289 } else { 1290 (*it)->Stop(); 1291 receivers_.erase(it); 1292 } 1293 } 1294 1295 void PeerConnection::OnIceConnectionChange( 1296 PeerConnectionInterface::IceConnectionState new_state) { 1297 RTC_DCHECK(signaling_thread()->IsCurrent()); 1298 // After transitioning to "closed", ignore any additional states from 1299 // WebRtcSession (such as "disconnected"). 1300 if (IsClosed()) { 1301 return; 1302 } 1303 ice_connection_state_ = new_state; 1304 observer_->OnIceConnectionChange(ice_connection_state_); 1305 } 1306 1307 void PeerConnection::OnIceGatheringChange( 1308 PeerConnectionInterface::IceGatheringState new_state) { 1309 RTC_DCHECK(signaling_thread()->IsCurrent()); 1310 if (IsClosed()) { 1311 return; 1312 } 1313 ice_gathering_state_ = new_state; 1314 observer_->OnIceGatheringChange(ice_gathering_state_); 1315 } 1316 1317 void PeerConnection::OnIceCandidate(const IceCandidateInterface* candidate) { 1318 RTC_DCHECK(signaling_thread()->IsCurrent()); 1319 observer_->OnIceCandidate(candidate); 1320 } 1321 1322 void PeerConnection::OnIceComplete() { 1323 RTC_DCHECK(signaling_thread()->IsCurrent()); 1324 observer_->OnIceComplete(); 1325 } 1326 1327 void PeerConnection::OnIceConnectionReceivingChange(bool receiving) { 1328 RTC_DCHECK(signaling_thread()->IsCurrent()); 1329 observer_->OnIceConnectionReceivingChange(receiving); 1330 } 1331 1332 void PeerConnection::ChangeSignalingState( 1333 PeerConnectionInterface::SignalingState signaling_state) { 1334 signaling_state_ = signaling_state; 1335 if (signaling_state == kClosed) { 1336 ice_connection_state_ = kIceConnectionClosed; 1337 observer_->OnIceConnectionChange(ice_connection_state_); 1338 if (ice_gathering_state_ != kIceGatheringComplete) { 1339 ice_gathering_state_ = kIceGatheringComplete; 1340 observer_->OnIceGatheringChange(ice_gathering_state_); 1341 } 1342 } 1343 observer_->OnSignalingChange(signaling_state_); 1344 observer_->OnStateChange(PeerConnectionObserver::kSignalingState); 1345 } 1346 1347 void PeerConnection::OnAudioTrackAdded(AudioTrackInterface* track, 1348 MediaStreamInterface* stream) { 1349 auto sender = FindSenderForTrack(track); 1350 if (sender != senders_.end()) { 1351 // We already have a sender for this track, so just change the stream_id 1352 // so that it's correct in the next call to CreateOffer. 1353 (*sender)->set_stream_id(stream->label()); 1354 return; 1355 } 1356 1357 // Normal case; we've never seen this track before. 1358 AudioRtpSender* new_sender = 1359 new AudioRtpSender(track, stream->label(), session_.get(), stats_.get()); 1360 senders_.push_back(new_sender); 1361 // If the sender has already been configured in SDP, we call SetSsrc, 1362 // which will connect the sender to the underlying transport. This can 1363 // occur if a local session description that contains the ID of the sender 1364 // is set before AddStream is called. It can also occur if the local 1365 // session description is not changed and RemoveStream is called, and 1366 // later AddStream is called again with the same stream. 1367 const TrackInfo* track_info = 1368 FindTrackInfo(local_audio_tracks_, stream->label(), track->id()); 1369 if (track_info) { 1370 new_sender->SetSsrc(track_info->ssrc); 1371 } 1372 } 1373 1374 // TODO(deadbeef): Don't destroy RtpSenders here; they should be kept around 1375 // indefinitely, when we have unified plan SDP. 1376 void PeerConnection::OnAudioTrackRemoved(AudioTrackInterface* track, 1377 MediaStreamInterface* stream) { 1378 auto sender = FindSenderForTrack(track); 1379 if (sender == senders_.end()) { 1380 LOG(LS_WARNING) << "RtpSender for track with id " << track->id() 1381 << " doesn't exist."; 1382 return; 1383 } 1384 (*sender)->Stop(); 1385 senders_.erase(sender); 1386 } 1387 1388 void PeerConnection::OnVideoTrackAdded(VideoTrackInterface* track, 1389 MediaStreamInterface* stream) { 1390 auto sender = FindSenderForTrack(track); 1391 if (sender != senders_.end()) { 1392 // We already have a sender for this track, so just change the stream_id 1393 // so that it's correct in the next call to CreateOffer. 1394 (*sender)->set_stream_id(stream->label()); 1395 return; 1396 } 1397 1398 // Normal case; we've never seen this track before. 1399 VideoRtpSender* new_sender = 1400 new VideoRtpSender(track, stream->label(), session_.get()); 1401 senders_.push_back(new_sender); 1402 const TrackInfo* track_info = 1403 FindTrackInfo(local_video_tracks_, stream->label(), track->id()); 1404 if (track_info) { 1405 new_sender->SetSsrc(track_info->ssrc); 1406 } 1407 } 1408 1409 void PeerConnection::OnVideoTrackRemoved(VideoTrackInterface* track, 1410 MediaStreamInterface* stream) { 1411 auto sender = FindSenderForTrack(track); 1412 if (sender == senders_.end()) { 1413 LOG(LS_WARNING) << "RtpSender for track with id " << track->id() 1414 << " doesn't exist."; 1415 return; 1416 } 1417 (*sender)->Stop(); 1418 senders_.erase(sender); 1419 } 1420 1421 void PeerConnection::PostSetSessionDescriptionFailure( 1422 SetSessionDescriptionObserver* observer, 1423 const std::string& error) { 1424 SetSessionDescriptionMsg* msg = new SetSessionDescriptionMsg(observer); 1425 msg->error = error; 1426 signaling_thread()->Post(this, MSG_SET_SESSIONDESCRIPTION_FAILED, msg); 1427 } 1428 1429 void PeerConnection::PostCreateSessionDescriptionFailure( 1430 CreateSessionDescriptionObserver* observer, 1431 const std::string& error) { 1432 CreateSessionDescriptionMsg* msg = new CreateSessionDescriptionMsg(observer); 1433 msg->error = error; 1434 signaling_thread()->Post(this, MSG_CREATE_SESSIONDESCRIPTION_FAILED, msg); 1435 } 1436 1437 bool PeerConnection::GetOptionsForOffer( 1438 const PeerConnectionInterface::RTCOfferAnswerOptions& rtc_options, 1439 cricket::MediaSessionOptions* session_options) { 1440 if (!ConvertRtcOptionsForOffer(rtc_options, session_options)) { 1441 return false; 1442 } 1443 1444 AddSendStreams(session_options, senders_, rtp_data_channels_); 1445 // Offer to receive audio/video if the constraint is not set and there are 1446 // send streams, or we're currently receiving. 1447 if (rtc_options.offer_to_receive_audio == RTCOfferAnswerOptions::kUndefined) { 1448 session_options->recv_audio = 1449 session_options->HasSendMediaStream(cricket::MEDIA_TYPE_AUDIO) || 1450 !remote_audio_tracks_.empty(); 1451 } 1452 if (rtc_options.offer_to_receive_video == RTCOfferAnswerOptions::kUndefined) { 1453 session_options->recv_video = 1454 session_options->HasSendMediaStream(cricket::MEDIA_TYPE_VIDEO) || 1455 !remote_video_tracks_.empty(); 1456 } 1457 session_options->bundle_enabled = 1458 session_options->bundle_enabled && 1459 (session_options->has_audio() || session_options->has_video() || 1460 session_options->has_data()); 1461 1462 if (session_->data_channel_type() == cricket::DCT_SCTP && HasDataChannels()) { 1463 session_options->data_channel_type = cricket::DCT_SCTP; 1464 } 1465 return true; 1466 } 1467 1468 bool PeerConnection::GetOptionsForAnswer( 1469 const MediaConstraintsInterface* constraints, 1470 cricket::MediaSessionOptions* session_options) { 1471 session_options->recv_audio = false; 1472 session_options->recv_video = false; 1473 if (!ParseConstraintsForAnswer(constraints, session_options)) { 1474 return false; 1475 } 1476 1477 AddSendStreams(session_options, senders_, rtp_data_channels_); 1478 session_options->bundle_enabled = 1479 session_options->bundle_enabled && 1480 (session_options->has_audio() || session_options->has_video() || 1481 session_options->has_data()); 1482 1483 // RTP data channel is handled in MediaSessionOptions::AddStream. SCTP streams 1484 // are not signaled in the SDP so does not go through that path and must be 1485 // handled here. 1486 if (session_->data_channel_type() == cricket::DCT_SCTP) { 1487 session_options->data_channel_type = cricket::DCT_SCTP; 1488 } 1489 return true; 1490 } 1491 1492 void PeerConnection::RemoveTracks(cricket::MediaType media_type) { 1493 UpdateLocalTracks(std::vector<cricket::StreamParams>(), media_type); 1494 UpdateRemoteStreamsList(std::vector<cricket::StreamParams>(), false, 1495 media_type, nullptr); 1496 } 1497 1498 void PeerConnection::UpdateRemoteStreamsList( 1499 const cricket::StreamParamsVec& streams, 1500 bool default_track_needed, 1501 cricket::MediaType media_type, 1502 StreamCollection* new_streams) { 1503 TrackInfos* current_tracks = GetRemoteTracks(media_type); 1504 1505 // Find removed tracks. I.e., tracks where the track id or ssrc don't match 1506 // the new StreamParam. 1507 auto track_it = current_tracks->begin(); 1508 while (track_it != current_tracks->end()) { 1509 const TrackInfo& info = *track_it; 1510 const cricket::StreamParams* params = 1511 cricket::GetStreamBySsrc(streams, info.ssrc); 1512 bool track_exists = params && params->id == info.track_id; 1513 // If this is a default track, and we still need it, don't remove it. 1514 if ((info.stream_label == kDefaultStreamLabel && default_track_needed) || 1515 track_exists) { 1516 ++track_it; 1517 } else { 1518 OnRemoteTrackRemoved(info.stream_label, info.track_id, media_type); 1519 track_it = current_tracks->erase(track_it); 1520 } 1521 } 1522 1523 // Find new and active tracks. 1524 for (const cricket::StreamParams& params : streams) { 1525 // The sync_label is the MediaStream label and the |stream.id| is the 1526 // track id. 1527 const std::string& stream_label = params.sync_label; 1528 const std::string& track_id = params.id; 1529 uint32_t ssrc = params.first_ssrc(); 1530 1531 rtc::scoped_refptr<MediaStreamInterface> stream = 1532 remote_streams_->find(stream_label); 1533 if (!stream) { 1534 // This is a new MediaStream. Create a new remote MediaStream. 1535 stream = remote_stream_factory_->CreateMediaStream(stream_label); 1536 remote_streams_->AddStream(stream); 1537 new_streams->AddStream(stream); 1538 } 1539 1540 const TrackInfo* track_info = 1541 FindTrackInfo(*current_tracks, stream_label, track_id); 1542 if (!track_info) { 1543 current_tracks->push_back(TrackInfo(stream_label, track_id, ssrc)); 1544 OnRemoteTrackSeen(stream_label, track_id, ssrc, media_type); 1545 } 1546 } 1547 1548 // Add default track if necessary. 1549 if (default_track_needed) { 1550 rtc::scoped_refptr<MediaStreamInterface> default_stream = 1551 remote_streams_->find(kDefaultStreamLabel); 1552 if (!default_stream) { 1553 // Create the new default MediaStream. 1554 default_stream = 1555 remote_stream_factory_->CreateMediaStream(kDefaultStreamLabel); 1556 remote_streams_->AddStream(default_stream); 1557 new_streams->AddStream(default_stream); 1558 } 1559 std::string default_track_id = (media_type == cricket::MEDIA_TYPE_AUDIO) 1560 ? kDefaultAudioTrackLabel 1561 : kDefaultVideoTrackLabel; 1562 const TrackInfo* default_track_info = 1563 FindTrackInfo(*current_tracks, kDefaultStreamLabel, default_track_id); 1564 if (!default_track_info) { 1565 current_tracks->push_back( 1566 TrackInfo(kDefaultStreamLabel, default_track_id, 0)); 1567 OnRemoteTrackSeen(kDefaultStreamLabel, default_track_id, 0, media_type); 1568 } 1569 } 1570 } 1571 1572 void PeerConnection::OnRemoteTrackSeen(const std::string& stream_label, 1573 const std::string& track_id, 1574 uint32_t ssrc, 1575 cricket::MediaType media_type) { 1576 MediaStreamInterface* stream = remote_streams_->find(stream_label); 1577 1578 if (media_type == cricket::MEDIA_TYPE_AUDIO) { 1579 AudioTrackInterface* audio_track = remote_stream_factory_->AddAudioTrack( 1580 ssrc, session_.get(), stream, track_id); 1581 CreateAudioReceiver(stream, audio_track, ssrc); 1582 } else if (media_type == cricket::MEDIA_TYPE_VIDEO) { 1583 VideoTrackInterface* video_track = 1584 remote_stream_factory_->AddVideoTrack(stream, track_id); 1585 CreateVideoReceiver(stream, video_track, ssrc); 1586 } else { 1587 RTC_DCHECK(false && "Invalid media type"); 1588 } 1589 } 1590 1591 void PeerConnection::OnRemoteTrackRemoved(const std::string& stream_label, 1592 const std::string& track_id, 1593 cricket::MediaType media_type) { 1594 MediaStreamInterface* stream = remote_streams_->find(stream_label); 1595 1596 if (media_type == cricket::MEDIA_TYPE_AUDIO) { 1597 rtc::scoped_refptr<AudioTrackInterface> audio_track = 1598 stream->FindAudioTrack(track_id); 1599 if (audio_track) { 1600 audio_track->set_state(webrtc::MediaStreamTrackInterface::kEnded); 1601 stream->RemoveTrack(audio_track); 1602 DestroyAudioReceiver(stream, audio_track); 1603 } 1604 } else if (media_type == cricket::MEDIA_TYPE_VIDEO) { 1605 rtc::scoped_refptr<VideoTrackInterface> video_track = 1606 stream->FindVideoTrack(track_id); 1607 if (video_track) { 1608 video_track->set_state(webrtc::MediaStreamTrackInterface::kEnded); 1609 stream->RemoveTrack(video_track); 1610 DestroyVideoReceiver(stream, video_track); 1611 } 1612 } else { 1613 ASSERT(false && "Invalid media type"); 1614 } 1615 } 1616 1617 void PeerConnection::UpdateEndedRemoteMediaStreams() { 1618 std::vector<rtc::scoped_refptr<MediaStreamInterface>> streams_to_remove; 1619 for (size_t i = 0; i < remote_streams_->count(); ++i) { 1620 MediaStreamInterface* stream = remote_streams_->at(i); 1621 if (stream->GetAudioTracks().empty() && stream->GetVideoTracks().empty()) { 1622 streams_to_remove.push_back(stream); 1623 } 1624 } 1625 1626 for (const auto& stream : streams_to_remove) { 1627 remote_streams_->RemoveStream(stream); 1628 observer_->OnRemoveStream(stream); 1629 } 1630 } 1631 1632 void PeerConnection::EndRemoteTracks(cricket::MediaType media_type) { 1633 TrackInfos* current_tracks = GetRemoteTracks(media_type); 1634 for (TrackInfos::iterator track_it = current_tracks->begin(); 1635 track_it != current_tracks->end(); ++track_it) { 1636 const TrackInfo& info = *track_it; 1637 MediaStreamInterface* stream = remote_streams_->find(info.stream_label); 1638 if (media_type == cricket::MEDIA_TYPE_AUDIO) { 1639 AudioTrackInterface* track = stream->FindAudioTrack(info.track_id); 1640 // There's no guarantee the track is still available, e.g. the track may 1641 // have been removed from the stream by javascript. 1642 if (track) { 1643 track->set_state(webrtc::MediaStreamTrackInterface::kEnded); 1644 } 1645 } 1646 if (media_type == cricket::MEDIA_TYPE_VIDEO) { 1647 VideoTrackInterface* track = stream->FindVideoTrack(info.track_id); 1648 // There's no guarantee the track is still available, e.g. the track may 1649 // have been removed from the stream by javascript. 1650 if (track) { 1651 track->set_state(webrtc::MediaStreamTrackInterface::kEnded); 1652 } 1653 } 1654 } 1655 } 1656 1657 void PeerConnection::UpdateLocalTracks( 1658 const std::vector<cricket::StreamParams>& streams, 1659 cricket::MediaType media_type) { 1660 TrackInfos* current_tracks = GetLocalTracks(media_type); 1661 1662 // Find removed tracks. I.e., tracks where the track id, stream label or ssrc 1663 // don't match the new StreamParam. 1664 TrackInfos::iterator track_it = current_tracks->begin(); 1665 while (track_it != current_tracks->end()) { 1666 const TrackInfo& info = *track_it; 1667 const cricket::StreamParams* params = 1668 cricket::GetStreamBySsrc(streams, info.ssrc); 1669 if (!params || params->id != info.track_id || 1670 params->sync_label != info.stream_label) { 1671 OnLocalTrackRemoved(info.stream_label, info.track_id, info.ssrc, 1672 media_type); 1673 track_it = current_tracks->erase(track_it); 1674 } else { 1675 ++track_it; 1676 } 1677 } 1678 1679 // Find new and active tracks. 1680 for (const cricket::StreamParams& params : streams) { 1681 // The sync_label is the MediaStream label and the |stream.id| is the 1682 // track id. 1683 const std::string& stream_label = params.sync_label; 1684 const std::string& track_id = params.id; 1685 uint32_t ssrc = params.first_ssrc(); 1686 const TrackInfo* track_info = 1687 FindTrackInfo(*current_tracks, stream_label, track_id); 1688 if (!track_info) { 1689 current_tracks->push_back(TrackInfo(stream_label, track_id, ssrc)); 1690 OnLocalTrackSeen(stream_label, track_id, params.first_ssrc(), media_type); 1691 } 1692 } 1693 } 1694 1695 void PeerConnection::OnLocalTrackSeen(const std::string& stream_label, 1696 const std::string& track_id, 1697 uint32_t ssrc, 1698 cricket::MediaType media_type) { 1699 RtpSenderInterface* sender = FindSenderById(track_id); 1700 if (!sender) { 1701 LOG(LS_WARNING) << "An unknown RtpSender with id " << track_id 1702 << " has been configured in the local description."; 1703 return; 1704 } 1705 1706 if (sender->media_type() != media_type) { 1707 LOG(LS_WARNING) << "An RtpSender has been configured in the local" 1708 << " description with an unexpected media type."; 1709 return; 1710 } 1711 1712 sender->set_stream_id(stream_label); 1713 sender->SetSsrc(ssrc); 1714 } 1715 1716 void PeerConnection::OnLocalTrackRemoved(const std::string& stream_label, 1717 const std::string& track_id, 1718 uint32_t ssrc, 1719 cricket::MediaType media_type) { 1720 RtpSenderInterface* sender = FindSenderById(track_id); 1721 if (!sender) { 1722 // This is the normal case. I.e., RemoveStream has been called and the 1723 // SessionDescriptions has been renegotiated. 1724 return; 1725 } 1726 1727 // A sender has been removed from the SessionDescription but it's still 1728 // associated with the PeerConnection. This only occurs if the SDP doesn't 1729 // match with the calls to CreateSender, AddStream and RemoveStream. 1730 if (sender->media_type() != media_type) { 1731 LOG(LS_WARNING) << "An RtpSender has been configured in the local" 1732 << " description with an unexpected media type."; 1733 return; 1734 } 1735 1736 sender->SetSsrc(0); 1737 } 1738 1739 void PeerConnection::UpdateLocalRtpDataChannels( 1740 const cricket::StreamParamsVec& streams) { 1741 std::vector<std::string> existing_channels; 1742 1743 // Find new and active data channels. 1744 for (const cricket::StreamParams& params : streams) { 1745 // |it->sync_label| is actually the data channel label. The reason is that 1746 // we use the same naming of data channels as we do for 1747 // MediaStreams and Tracks. 1748 // For MediaStreams, the sync_label is the MediaStream label and the 1749 // track label is the same as |streamid|. 1750 const std::string& channel_label = params.sync_label; 1751 auto data_channel_it = rtp_data_channels_.find(channel_label); 1752 if (!VERIFY(data_channel_it != rtp_data_channels_.end())) { 1753 continue; 1754 } 1755 // Set the SSRC the data channel should use for sending. 1756 data_channel_it->second->SetSendSsrc(params.first_ssrc()); 1757 existing_channels.push_back(data_channel_it->first); 1758 } 1759 1760 UpdateClosingRtpDataChannels(existing_channels, true); 1761 } 1762 1763 void PeerConnection::UpdateRemoteRtpDataChannels( 1764 const cricket::StreamParamsVec& streams) { 1765 std::vector<std::string> existing_channels; 1766 1767 // Find new and active data channels. 1768 for (const cricket::StreamParams& params : streams) { 1769 // The data channel label is either the mslabel or the SSRC if the mslabel 1770 // does not exist. Ex a=ssrc:444330170 mslabel:test1. 1771 std::string label = params.sync_label.empty() 1772 ? rtc::ToString(params.first_ssrc()) 1773 : params.sync_label; 1774 auto data_channel_it = rtp_data_channels_.find(label); 1775 if (data_channel_it == rtp_data_channels_.end()) { 1776 // This is a new data channel. 1777 CreateRemoteRtpDataChannel(label, params.first_ssrc()); 1778 } else { 1779 data_channel_it->second->SetReceiveSsrc(params.first_ssrc()); 1780 } 1781 existing_channels.push_back(label); 1782 } 1783 1784 UpdateClosingRtpDataChannels(existing_channels, false); 1785 } 1786 1787 void PeerConnection::UpdateClosingRtpDataChannels( 1788 const std::vector<std::string>& active_channels, 1789 bool is_local_update) { 1790 auto it = rtp_data_channels_.begin(); 1791 while (it != rtp_data_channels_.end()) { 1792 DataChannel* data_channel = it->second; 1793 if (std::find(active_channels.begin(), active_channels.end(), 1794 data_channel->label()) != active_channels.end()) { 1795 ++it; 1796 continue; 1797 } 1798 1799 if (is_local_update) { 1800 data_channel->SetSendSsrc(0); 1801 } else { 1802 data_channel->RemotePeerRequestClose(); 1803 } 1804 1805 if (data_channel->state() == DataChannel::kClosed) { 1806 rtp_data_channels_.erase(it); 1807 it = rtp_data_channels_.begin(); 1808 } else { 1809 ++it; 1810 } 1811 } 1812 } 1813 1814 void PeerConnection::CreateRemoteRtpDataChannel(const std::string& label, 1815 uint32_t remote_ssrc) { 1816 rtc::scoped_refptr<DataChannel> channel( 1817 InternalCreateDataChannel(label, nullptr)); 1818 if (!channel.get()) { 1819 LOG(LS_WARNING) << "Remote peer requested a DataChannel but" 1820 << "CreateDataChannel failed."; 1821 return; 1822 } 1823 channel->SetReceiveSsrc(remote_ssrc); 1824 observer_->OnDataChannel( 1825 DataChannelProxy::Create(signaling_thread(), channel)); 1826 } 1827 1828 rtc::scoped_refptr<DataChannel> PeerConnection::InternalCreateDataChannel( 1829 const std::string& label, 1830 const InternalDataChannelInit* config) { 1831 if (IsClosed()) { 1832 return nullptr; 1833 } 1834 if (session_->data_channel_type() == cricket::DCT_NONE) { 1835 LOG(LS_ERROR) 1836 << "InternalCreateDataChannel: Data is not supported in this call."; 1837 return nullptr; 1838 } 1839 InternalDataChannelInit new_config = 1840 config ? (*config) : InternalDataChannelInit(); 1841 if (session_->data_channel_type() == cricket::DCT_SCTP) { 1842 if (new_config.id < 0) { 1843 rtc::SSLRole role; 1844 if ((session_->GetSslRole(session_->data_channel(), &role)) && 1845 !sid_allocator_.AllocateSid(role, &new_config.id)) { 1846 LOG(LS_ERROR) << "No id can be allocated for the SCTP data channel."; 1847 return nullptr; 1848 } 1849 } else if (!sid_allocator_.ReserveSid(new_config.id)) { 1850 LOG(LS_ERROR) << "Failed to create a SCTP data channel " 1851 << "because the id is already in use or out of range."; 1852 return nullptr; 1853 } 1854 } 1855 1856 rtc::scoped_refptr<DataChannel> channel(DataChannel::Create( 1857 session_.get(), session_->data_channel_type(), label, new_config)); 1858 if (!channel) { 1859 sid_allocator_.ReleaseSid(new_config.id); 1860 return nullptr; 1861 } 1862 1863 if (channel->data_channel_type() == cricket::DCT_RTP) { 1864 if (rtp_data_channels_.find(channel->label()) != rtp_data_channels_.end()) { 1865 LOG(LS_ERROR) << "DataChannel with label " << channel->label() 1866 << " already exists."; 1867 return nullptr; 1868 } 1869 rtp_data_channels_[channel->label()] = channel; 1870 } else { 1871 RTC_DCHECK(channel->data_channel_type() == cricket::DCT_SCTP); 1872 sctp_data_channels_.push_back(channel); 1873 channel->SignalClosed.connect(this, 1874 &PeerConnection::OnSctpDataChannelClosed); 1875 } 1876 1877 return channel; 1878 } 1879 1880 bool PeerConnection::HasDataChannels() const { 1881 return !rtp_data_channels_.empty() || !sctp_data_channels_.empty(); 1882 } 1883 1884 void PeerConnection::AllocateSctpSids(rtc::SSLRole role) { 1885 for (const auto& channel : sctp_data_channels_) { 1886 if (channel->id() < 0) { 1887 int sid; 1888 if (!sid_allocator_.AllocateSid(role, &sid)) { 1889 LOG(LS_ERROR) << "Failed to allocate SCTP sid."; 1890 continue; 1891 } 1892 channel->SetSctpSid(sid); 1893 } 1894 } 1895 } 1896 1897 void PeerConnection::OnSctpDataChannelClosed(DataChannel* channel) { 1898 RTC_DCHECK(signaling_thread()->IsCurrent()); 1899 for (auto it = sctp_data_channels_.begin(); it != sctp_data_channels_.end(); 1900 ++it) { 1901 if (it->get() == channel) { 1902 if (channel->id() >= 0) { 1903 sid_allocator_.ReleaseSid(channel->id()); 1904 } 1905 // Since this method is triggered by a signal from the DataChannel, 1906 // we can't free it directly here; we need to free it asynchronously. 1907 sctp_data_channels_to_free_.push_back(*it); 1908 sctp_data_channels_.erase(it); 1909 signaling_thread()->Post(this, MSG_FREE_DATACHANNELS, nullptr); 1910 return; 1911 } 1912 } 1913 } 1914 1915 void PeerConnection::OnVoiceChannelDestroyed() { 1916 EndRemoteTracks(cricket::MEDIA_TYPE_AUDIO); 1917 } 1918 1919 void PeerConnection::OnVideoChannelDestroyed() { 1920 EndRemoteTracks(cricket::MEDIA_TYPE_VIDEO); 1921 } 1922 1923 void PeerConnection::OnDataChannelCreated() { 1924 for (const auto& channel : sctp_data_channels_) { 1925 channel->OnTransportChannelCreated(); 1926 } 1927 } 1928 1929 void PeerConnection::OnDataChannelDestroyed() { 1930 // Use a temporary copy of the RTP/SCTP DataChannel list because the 1931 // DataChannel may callback to us and try to modify the list. 1932 std::map<std::string, rtc::scoped_refptr<DataChannel>> temp_rtp_dcs; 1933 temp_rtp_dcs.swap(rtp_data_channels_); 1934 for (const auto& kv : temp_rtp_dcs) { 1935 kv.second->OnTransportChannelDestroyed(); 1936 } 1937 1938 std::vector<rtc::scoped_refptr<DataChannel>> temp_sctp_dcs; 1939 temp_sctp_dcs.swap(sctp_data_channels_); 1940 for (const auto& channel : temp_sctp_dcs) { 1941 channel->OnTransportChannelDestroyed(); 1942 } 1943 } 1944 1945 void PeerConnection::OnDataChannelOpenMessage( 1946 const std::string& label, 1947 const InternalDataChannelInit& config) { 1948 rtc::scoped_refptr<DataChannel> channel( 1949 InternalCreateDataChannel(label, &config)); 1950 if (!channel.get()) { 1951 LOG(LS_ERROR) << "Failed to create DataChannel from the OPEN message."; 1952 return; 1953 } 1954 1955 observer_->OnDataChannel( 1956 DataChannelProxy::Create(signaling_thread(), channel)); 1957 } 1958 1959 RtpSenderInterface* PeerConnection::FindSenderById(const std::string& id) { 1960 auto it = 1961 std::find_if(senders_.begin(), senders_.end(), 1962 [id](const rtc::scoped_refptr<RtpSenderInterface>& sender) { 1963 return sender->id() == id; 1964 }); 1965 return it != senders_.end() ? it->get() : nullptr; 1966 } 1967 1968 std::vector<rtc::scoped_refptr<RtpSenderInterface>>::iterator 1969 PeerConnection::FindSenderForTrack(MediaStreamTrackInterface* track) { 1970 return std::find_if( 1971 senders_.begin(), senders_.end(), 1972 [track](const rtc::scoped_refptr<RtpSenderInterface>& sender) { 1973 return sender->track() == track; 1974 }); 1975 } 1976 1977 std::vector<rtc::scoped_refptr<RtpReceiverInterface>>::iterator 1978 PeerConnection::FindReceiverForTrack(MediaStreamTrackInterface* track) { 1979 return std::find_if( 1980 receivers_.begin(), receivers_.end(), 1981 [track](const rtc::scoped_refptr<RtpReceiverInterface>& receiver) { 1982 return receiver->track() == track; 1983 }); 1984 } 1985 1986 PeerConnection::TrackInfos* PeerConnection::GetRemoteTracks( 1987 cricket::MediaType media_type) { 1988 RTC_DCHECK(media_type == cricket::MEDIA_TYPE_AUDIO || 1989 media_type == cricket::MEDIA_TYPE_VIDEO); 1990 return (media_type == cricket::MEDIA_TYPE_AUDIO) ? &remote_audio_tracks_ 1991 : &remote_video_tracks_; 1992 } 1993 1994 PeerConnection::TrackInfos* PeerConnection::GetLocalTracks( 1995 cricket::MediaType media_type) { 1996 RTC_DCHECK(media_type == cricket::MEDIA_TYPE_AUDIO || 1997 media_type == cricket::MEDIA_TYPE_VIDEO); 1998 return (media_type == cricket::MEDIA_TYPE_AUDIO) ? &local_audio_tracks_ 1999 : &local_video_tracks_; 2000 } 2001 2002 const PeerConnection::TrackInfo* PeerConnection::FindTrackInfo( 2003 const PeerConnection::TrackInfos& infos, 2004 const std::string& stream_label, 2005 const std::string track_id) const { 2006 for (const TrackInfo& track_info : infos) { 2007 if (track_info.stream_label == stream_label && 2008 track_info.track_id == track_id) { 2009 return &track_info; 2010 } 2011 } 2012 return nullptr; 2013 } 2014 2015 DataChannel* PeerConnection::FindDataChannelBySid(int sid) const { 2016 for (const auto& channel : sctp_data_channels_) { 2017 if (channel->id() == sid) { 2018 return channel; 2019 } 2020 } 2021 return nullptr; 2022 } 2023 2024 } // namespace webrtc 2025