1 /* 2 * libjingle 3 * Copyright 2004 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 <string> 29 #include "talk/base/helpers.h" 30 #include "talk/base/logging.h" 31 #include "talk/base/thread.h" 32 #include "talk/base/window.h" 33 #include "talk/media/base/constants.h" 34 #include "talk/media/base/screencastid.h" 35 #include "talk/p2p/base/parsing.h" 36 #include "talk/session/media/call.h" 37 #include "talk/session/media/mediasessionclient.h" 38 39 namespace cricket { 40 41 const uint32 MSG_CHECKAUTODESTROY = 1; 42 const uint32 MSG_TERMINATECALL = 2; 43 const uint32 MSG_PLAYDTMF = 3; 44 45 namespace { 46 const int kDTMFDelay = 300; // msec 47 const size_t kMaxDTMFDigits = 30; 48 const int kSendToVoicemailTimeout = 1000*20; 49 const int kNoVoicemailTimeout = 1000*180; 50 const int kMediaMonitorInterval = 1000*15; 51 // In order to be the same as the server-side switching, this must be 100. 52 const int kAudioMonitorPollPeriodMillis = 100; 53 54 // V is a pointer type. 55 template<class K, class V> 56 V FindOrNull(const std::map<K, V>& map, 57 const K& key) { 58 typename std::map<K, V>::const_iterator it = map.find(key); 59 return (it != map.end()) ? it->second : NULL; 60 } 61 62 63 bool ContentContainsCrypto(const cricket::ContentInfo* content) { 64 if (content != NULL) { 65 const cricket::MediaContentDescription* desc = 66 static_cast<const cricket::MediaContentDescription*>( 67 content->description); 68 if (!desc || desc->cryptos().empty()) { 69 return false; 70 } 71 } 72 return true; 73 } 74 75 } 76 77 Call::Call(MediaSessionClient* session_client) 78 : id_(talk_base::CreateRandomId()), 79 session_client_(session_client), 80 local_renderer_(NULL), 81 has_video_(false), 82 has_data_(false), 83 muted_(false), 84 video_muted_(false), 85 send_to_voicemail_(true), 86 playing_dtmf_(false) { 87 } 88 89 Call::~Call() { 90 while (media_session_map_.begin() != media_session_map_.end()) { 91 Session* session = media_session_map_.begin()->second.session; 92 RemoveSession(session); 93 session_client_->session_manager()->DestroySession(session); 94 } 95 talk_base::Thread::Current()->Clear(this); 96 } 97 98 Session* Call::InitiateSession(const buzz::Jid& to, 99 const buzz::Jid& initiator, 100 const CallOptions& options) { 101 std::string id; 102 std::string initiator_name = initiator.Str(); 103 return InternalInitiateSession(id, to, initiator_name, options); 104 } 105 106 Session *Call::InitiateSession(const std::string& id, 107 const buzz::Jid& to, 108 const CallOptions& options) { 109 std::string initiator_name; 110 return InternalInitiateSession(id, to, initiator_name, options); 111 } 112 113 void Call::IncomingSession(Session* session, const SessionDescription* offer) { 114 AddSession(session, offer); 115 116 // Make sure the session knows about the incoming ssrcs. This needs to be done 117 // prior to the SignalSessionState call, because that may trigger handling of 118 // these new SSRCs, so they need to be registered before then. 119 UpdateRemoteMediaStreams(session, offer->contents(), false); 120 121 // Missed the first state, the initiate, which is needed by 122 // call_client. 123 SignalSessionState(this, session, Session::STATE_RECEIVEDINITIATE); 124 } 125 126 void Call::AcceptSession(Session* session, 127 const cricket::CallOptions& options) { 128 MediaSessionMap::iterator it = media_session_map_.find(session->id()); 129 if (it != media_session_map_.end()) { 130 const SessionDescription* answer = session_client_->CreateAnswer( 131 session->remote_description(), options); 132 it->second.session->Accept(answer); 133 } 134 } 135 136 void Call::RejectSession(Session* session) { 137 // Assume polite decline. 138 MediaSessionMap::iterator it = media_session_map_.find(session->id()); 139 if (it != media_session_map_.end()) 140 it->second.session->Reject(STR_TERMINATE_DECLINE); 141 } 142 143 void Call::TerminateSession(Session* session) { 144 MediaSessionMap::iterator it = media_session_map_.find(session->id()); 145 if (it != media_session_map_.end()) { 146 // Assume polite terminations. 147 it->second.session->Terminate(); 148 } 149 } 150 151 void Call::Terminate() { 152 // Copy the list so that we can iterate over it in a stable way 153 std::vector<Session*> sessions = this->sessions(); 154 155 // There may be more than one session to terminate 156 std::vector<Session*>::iterator it; 157 for (it = sessions.begin(); it != sessions.end(); ++it) { 158 TerminateSession(*it); 159 } 160 } 161 162 bool Call::SendViewRequest(Session* session, 163 const ViewRequest& view_request) { 164 StaticVideoViews::const_iterator it; 165 for (it = view_request.static_video_views.begin(); 166 it != view_request.static_video_views.end(); ++it) { 167 StreamParams found_stream; 168 bool found = false; 169 MediaStreams* recv_streams = GetMediaStreams(session); 170 if (recv_streams) 171 found = recv_streams->GetVideoStream(it->selector, &found_stream); 172 if (!found) { 173 LOG(LS_WARNING) << "Trying to send view request for (" 174 << it->selector.ssrc << ", '" 175 << it->selector.groupid << "', '" 176 << it->selector.streamid << "'" 177 << ") is not in the local streams."; 178 return false; 179 } 180 } 181 182 XmlElements elems; 183 WriteError error; 184 if (!WriteJingleViewRequest(CN_VIDEO, view_request, &elems, &error)) { 185 LOG(LS_ERROR) << "Couldn't write out view request: " << error.text; 186 return false; 187 } 188 189 return session->SendInfoMessage(elems); 190 } 191 192 void Call::SetLocalRenderer(VideoRenderer* renderer) { 193 local_renderer_ = renderer; 194 if (session_client_->GetFocus() == this) { 195 session_client_->channel_manager()->SetLocalRenderer(renderer); 196 } 197 } 198 199 void Call::SetVideoRenderer(Session* session, uint32 ssrc, 200 VideoRenderer* renderer) { 201 VideoChannel* video_channel = GetVideoChannel(session); 202 if (video_channel) { 203 video_channel->SetRenderer(ssrc, renderer); 204 LOG(LS_INFO) << "Set renderer of ssrc " << ssrc 205 << " to " << renderer << "."; 206 } else { 207 LOG(LS_INFO) << "Failed to set renderer of ssrc " << ssrc << "."; 208 } 209 } 210 211 void Call::OnMessage(talk_base::Message* message) { 212 switch (message->message_id) { 213 case MSG_CHECKAUTODESTROY: 214 // If no more sessions for this call, delete it 215 if (media_session_map_.empty()) 216 session_client_->DestroyCall(this); 217 break; 218 case MSG_TERMINATECALL: 219 // Signal to the user that a timeout has happened and the call should 220 // be sent to voicemail. 221 if (send_to_voicemail_) { 222 SignalSetupToCallVoicemail(); 223 } 224 225 // Callee didn't answer - terminate call 226 Terminate(); 227 break; 228 case MSG_PLAYDTMF: 229 ContinuePlayDTMF(); 230 } 231 } 232 233 std::vector<Session*> Call::sessions() { 234 std::vector<Session*> sessions; 235 MediaSessionMap::iterator it; 236 for (it = media_session_map_.begin(); it != media_session_map_.end(); ++it) 237 sessions.push_back(it->second.session); 238 239 return sessions; 240 } 241 242 bool Call::AddSession(Session* session, const SessionDescription* offer) { 243 bool succeeded = true; 244 MediaSession media_session; 245 media_session.session = session; 246 media_session.voice_channel = NULL; 247 media_session.video_channel = NULL; 248 media_session.data_channel = NULL; 249 media_session.recv_streams = NULL; 250 251 const ContentInfo* audio_offer = GetFirstAudioContent(offer); 252 const ContentInfo* video_offer = GetFirstVideoContent(offer); 253 const ContentInfo* data_offer = GetFirstDataContent(offer); 254 has_video_ = (video_offer != NULL); 255 has_data_ = (data_offer != NULL); 256 257 ASSERT(audio_offer != NULL); 258 // Create voice channel and start a media monitor. 259 media_session.voice_channel = 260 session_client_->channel_manager()->CreateVoiceChannel( 261 session, audio_offer->name, has_video_); 262 // voice_channel can be NULL in case of NullVoiceEngine. 263 if (media_session.voice_channel) { 264 media_session.voice_channel->SignalMediaMonitor.connect( 265 this, &Call::OnMediaMonitor); 266 media_session.voice_channel->StartMediaMonitor(kMediaMonitorInterval); 267 } else { 268 succeeded = false; 269 } 270 271 // If desired, create video channel and start a media monitor. 272 if (has_video_ && succeeded) { 273 media_session.video_channel = 274 session_client_->channel_manager()->CreateVideoChannel( 275 session, video_offer->name, true, media_session.voice_channel); 276 // video_channel can be NULL in case of NullVideoEngine. 277 if (media_session.video_channel) { 278 media_session.video_channel->SignalMediaMonitor.connect( 279 this, &Call::OnMediaMonitor); 280 media_session.video_channel->StartMediaMonitor(kMediaMonitorInterval); 281 } else { 282 succeeded = false; 283 } 284 } 285 286 // If desired, create data channel. 287 if (has_data_ && succeeded) { 288 const DataContentDescription* data = GetFirstDataContentDescription(offer); 289 if (data == NULL) { 290 succeeded = false; 291 } else { 292 DataChannelType data_channel_type = DCT_RTP; 293 if ((data->protocol() == kMediaProtocolSctp) || 294 (data->protocol() == kMediaProtocolDtlsSctp)) { 295 data_channel_type = DCT_SCTP; 296 } 297 298 bool rtcp = false; 299 media_session.data_channel = 300 session_client_->channel_manager()->CreateDataChannel( 301 session, data_offer->name, rtcp, data_channel_type); 302 if (media_session.data_channel) { 303 media_session.data_channel->SignalDataReceived.connect( 304 this, &Call::OnDataReceived); 305 } else { 306 succeeded = false; 307 } 308 } 309 } 310 311 if (succeeded) { 312 // Add session to list, create channels for this session. 313 media_session.recv_streams = new MediaStreams; 314 media_session_map_[session->id()] = media_session; 315 session->SignalState.connect(this, &Call::OnSessionState); 316 session->SignalError.connect(this, &Call::OnSessionError); 317 session->SignalInfoMessage.connect( 318 this, &Call::OnSessionInfoMessage); 319 session->SignalRemoteDescriptionUpdate.connect( 320 this, &Call::OnRemoteDescriptionUpdate); 321 session->SignalReceivedTerminateReason 322 .connect(this, &Call::OnReceivedTerminateReason); 323 324 // If this call has the focus, enable this session's channels. 325 if (session_client_->GetFocus() == this) { 326 EnableSessionChannels(session, true); 327 } 328 329 // Signal client. 330 SignalAddSession(this, session); 331 } 332 333 return succeeded; 334 } 335 336 void Call::RemoveSession(Session* session) { 337 MediaSessionMap::iterator it = media_session_map_.find(session->id()); 338 if (it == media_session_map_.end()) 339 return; 340 341 // Remove all the screencasts, if they haven't been already. 342 while (!it->second.started_screencasts.empty()) { 343 uint32 ssrc = it->second.started_screencasts.begin()->first; 344 if (!StopScreencastWithoutSendingUpdate(it->second.session, ssrc)) { 345 LOG(LS_ERROR) << "Unable to stop screencast with ssrc " << ssrc; 346 ASSERT(false); 347 } 348 } 349 350 // Destroy video channel 351 VideoChannel* video_channel = it->second.video_channel; 352 if (video_channel != NULL) 353 session_client_->channel_manager()->DestroyVideoChannel(video_channel); 354 355 // Destroy voice channel 356 VoiceChannel* voice_channel = it->second.voice_channel; 357 if (voice_channel != NULL) 358 session_client_->channel_manager()->DestroyVoiceChannel(voice_channel); 359 360 // Destroy data channel 361 DataChannel* data_channel = it->second.data_channel; 362 if (data_channel != NULL) 363 session_client_->channel_manager()->DestroyDataChannel(data_channel); 364 365 delete it->second.recv_streams; 366 media_session_map_.erase(it); 367 368 // Destroy speaker monitor 369 StopSpeakerMonitor(session); 370 371 // Signal client 372 SignalRemoveSession(this, session); 373 374 // The call auto destroys when the last session is removed 375 talk_base::Thread::Current()->Post(this, MSG_CHECKAUTODESTROY); 376 } 377 378 VoiceChannel* Call::GetVoiceChannel(Session* session) const { 379 MediaSessionMap::const_iterator it = media_session_map_.find(session->id()); 380 return (it != media_session_map_.end()) ? it->second.voice_channel : NULL; 381 } 382 383 VideoChannel* Call::GetVideoChannel(Session* session) const { 384 MediaSessionMap::const_iterator it = media_session_map_.find(session->id()); 385 return (it != media_session_map_.end()) ? it->second.video_channel : NULL; 386 } 387 388 DataChannel* Call::GetDataChannel(Session* session) const { 389 MediaSessionMap::const_iterator it = media_session_map_.find(session->id()); 390 return (it != media_session_map_.end()) ? it->second.data_channel : NULL; 391 } 392 393 MediaStreams* Call::GetMediaStreams(Session* session) const { 394 MediaSessionMap::const_iterator it = media_session_map_.find(session->id()); 395 return (it != media_session_map_.end()) ? it->second.recv_streams : NULL; 396 } 397 398 void Call::EnableChannels(bool enable) { 399 MediaSessionMap::iterator it; 400 for (it = media_session_map_.begin(); it != media_session_map_.end(); ++it) { 401 EnableSessionChannels(it->second.session, enable); 402 } 403 session_client_->channel_manager()->SetLocalRenderer( 404 (enable) ? local_renderer_ : NULL); 405 } 406 407 void Call::EnableSessionChannels(Session* session, bool enable) { 408 MediaSessionMap::iterator it = media_session_map_.find(session->id()); 409 if (it == media_session_map_.end()) 410 return; 411 412 VoiceChannel* voice_channel = it->second.voice_channel; 413 VideoChannel* video_channel = it->second.video_channel; 414 DataChannel* data_channel = it->second.data_channel; 415 if (voice_channel != NULL) 416 voice_channel->Enable(enable); 417 if (video_channel != NULL) 418 video_channel->Enable(enable); 419 if (data_channel != NULL) 420 data_channel->Enable(enable); 421 } 422 423 void Call::Mute(bool mute) { 424 muted_ = mute; 425 MediaSessionMap::iterator it; 426 for (it = media_session_map_.begin(); it != media_session_map_.end(); ++it) { 427 if (it->second.voice_channel != NULL) 428 it->second.voice_channel->MuteStream(0, mute); 429 } 430 } 431 432 void Call::MuteVideo(bool mute) { 433 video_muted_ = mute; 434 MediaSessionMap::iterator it; 435 for (it = media_session_map_.begin(); it != media_session_map_.end(); ++it) { 436 if (it->second.video_channel != NULL) 437 it->second.video_channel->MuteStream(0, mute); 438 } 439 } 440 441 bool Call::SendData(Session* session, 442 const SendDataParams& params, 443 const talk_base::Buffer& payload, 444 SendDataResult* result) { 445 DataChannel* data_channel = GetDataChannel(session); 446 if (!data_channel) { 447 LOG(LS_WARNING) << "Could not send data: no data channel."; 448 return false; 449 } 450 451 return data_channel->SendData(params, payload, result); 452 } 453 454 void Call::PressDTMF(int event) { 455 // Queue up this digit 456 if (queued_dtmf_.size() < kMaxDTMFDigits) { 457 LOG(LS_INFO) << "Call::PressDTMF(" << event << ")"; 458 459 queued_dtmf_.push_back(event); 460 461 if (!playing_dtmf_) { 462 ContinuePlayDTMF(); 463 } 464 } 465 } 466 467 cricket::VideoFormat ScreencastFormatFromFps(int fps) { 468 // The capturer pretty much ignore this, but just in case we give it 469 // a resolution big enough to cover any expected desktop. In any 470 // case, it can't be 0x0, or the CaptureManager will fail to use it. 471 return cricket::VideoFormat( 472 1, 1, 473 cricket::VideoFormat::FpsToInterval(fps), cricket::FOURCC_ANY); 474 } 475 476 bool Call::StartScreencast(Session* session, 477 const std::string& streamid, uint32 ssrc, 478 const ScreencastId& screencastid, int fps) { 479 MediaSessionMap::iterator it = media_session_map_.find(session->id()); 480 if (it == media_session_map_.end()) { 481 return false; 482 } 483 484 VideoChannel *video_channel = GetVideoChannel(session); 485 if (!video_channel) { 486 LOG(LS_WARNING) << "Cannot add screencast" 487 << " because there is no video channel."; 488 return false; 489 } 490 491 VideoCapturer *capturer = video_channel->AddScreencast(ssrc, screencastid); 492 if (capturer == NULL) { 493 LOG(LS_WARNING) << "Could not create screencast capturer."; 494 return false; 495 } 496 497 VideoFormat format = ScreencastFormatFromFps(fps); 498 if (!session_client_->channel_manager()->StartVideoCapture( 499 capturer, format)) { 500 LOG(LS_WARNING) << "Could not start video capture."; 501 video_channel->RemoveScreencast(ssrc); 502 return false; 503 } 504 505 if (!video_channel->SetCapturer(ssrc, capturer)) { 506 LOG(LS_WARNING) << "Could not start sending screencast."; 507 session_client_->channel_manager()->StopVideoCapture( 508 capturer, ScreencastFormatFromFps(fps)); 509 video_channel->RemoveScreencast(ssrc); 510 } 511 512 // TODO(pthatcher): Once the CaptureManager has a nicer interface 513 // for removing captures (such as having StartCapture return a 514 // handle), remove this StartedCapture stuff. 515 it->second.started_screencasts.insert( 516 std::make_pair(ssrc, StartedCapture(capturer, format))); 517 518 // TODO(pthatcher): Verify we aren't re-using an existing id or 519 // ssrc. 520 StreamParams stream; 521 stream.id = streamid; 522 stream.ssrcs.push_back(ssrc); 523 VideoContentDescription* video = CreateVideoStreamUpdate(stream); 524 525 // TODO(pthatcher): Wait until view request before sending video. 526 video_channel->SetLocalContent(video, CA_UPDATE); 527 SendVideoStreamUpdate(session, video); 528 return true; 529 } 530 531 bool Call::StopScreencast(Session* session, 532 const std::string& streamid, uint32 ssrc) { 533 if (!StopScreencastWithoutSendingUpdate(session, ssrc)) { 534 return false; 535 } 536 537 VideoChannel *video_channel = GetVideoChannel(session); 538 if (!video_channel) { 539 LOG(LS_WARNING) << "Cannot add screencast" 540 << " because there is no video channel."; 541 return false; 542 } 543 544 StreamParams stream; 545 stream.id = streamid; 546 // No ssrcs 547 VideoContentDescription* video = CreateVideoStreamUpdate(stream); 548 549 video_channel->SetLocalContent(video, CA_UPDATE); 550 SendVideoStreamUpdate(session, video); 551 return true; 552 } 553 554 bool Call::StopScreencastWithoutSendingUpdate( 555 Session* session, uint32 ssrc) { 556 MediaSessionMap::iterator it = media_session_map_.find(session->id()); 557 if (it == media_session_map_.end()) { 558 return false; 559 } 560 561 VideoChannel *video_channel = GetVideoChannel(session); 562 if (!video_channel) { 563 LOG(LS_WARNING) << "Cannot remove screencast" 564 << " because there is no video channel."; 565 return false; 566 } 567 568 StartedScreencastMap::const_iterator screencast_iter = 569 it->second.started_screencasts.find(ssrc); 570 if (screencast_iter == it->second.started_screencasts.end()) { 571 LOG(LS_WARNING) << "Could not stop screencast " << ssrc 572 << " because there is no capturer."; 573 return false; 574 } 575 576 VideoCapturer* capturer = screencast_iter->second.capturer; 577 VideoFormat format = screencast_iter->second.format; 578 video_channel->SetCapturer(ssrc, NULL); 579 if (!session_client_->channel_manager()->StopVideoCapture( 580 capturer, format)) { 581 LOG(LS_WARNING) << "Could not stop screencast " << ssrc 582 << " because could not stop capture."; 583 return false; 584 } 585 video_channel->RemoveScreencast(ssrc); 586 it->second.started_screencasts.erase(ssrc); 587 return true; 588 } 589 590 VideoContentDescription* Call::CreateVideoStreamUpdate( 591 const StreamParams& stream) { 592 VideoContentDescription* video = new VideoContentDescription(); 593 video->set_multistream(true); 594 video->set_partial(true); 595 video->AddStream(stream); 596 return video; 597 } 598 599 void Call::SendVideoStreamUpdate( 600 Session* session, VideoContentDescription* video) { 601 // Takes the ownership of |video|. 602 talk_base::scoped_ptr<VideoContentDescription> description(video); 603 const ContentInfo* video_info = 604 GetFirstVideoContent(session->local_description()); 605 if (video_info == NULL) { 606 LOG(LS_WARNING) << "Cannot send stream update for video."; 607 return; 608 } 609 610 std::vector<ContentInfo> contents; 611 contents.push_back( 612 ContentInfo(video_info->name, video_info->type, description.get())); 613 614 session->SendDescriptionInfoMessage(contents); 615 } 616 617 void Call::ContinuePlayDTMF() { 618 playing_dtmf_ = false; 619 620 // Check to see if we have a queued tone 621 if (queued_dtmf_.size() > 0) { 622 playing_dtmf_ = true; 623 624 int tone = queued_dtmf_.front(); 625 queued_dtmf_.pop_front(); 626 627 LOG(LS_INFO) << "Call::ContinuePlayDTMF(" << tone << ")"; 628 for (MediaSessionMap::iterator it = media_session_map_.begin(); 629 it != media_session_map_.end(); ++it) { 630 if (it->second.voice_channel != NULL) { 631 it->second.voice_channel->PressDTMF(tone, true); 632 } 633 } 634 635 // Post a message to play the next tone or at least clear the playing_dtmf_ 636 // bit. 637 talk_base::Thread::Current()->PostDelayed(kDTMFDelay, this, MSG_PLAYDTMF); 638 } 639 } 640 641 void Call::Join(Call* call, bool enable) { 642 for (MediaSessionMap::iterator it = call->media_session_map_.begin(); 643 it != call->media_session_map_.end(); ++it) { 644 // Shouldn't already exist. 645 ASSERT(media_session_map_.find(it->first) == media_session_map_.end()); 646 media_session_map_[it->first] = it->second; 647 648 it->second.session->SignalState.connect(this, &Call::OnSessionState); 649 it->second.session->SignalError.connect(this, &Call::OnSessionError); 650 it->second.session->SignalReceivedTerminateReason 651 .connect(this, &Call::OnReceivedTerminateReason); 652 653 EnableSessionChannels(it->second.session, enable); 654 } 655 656 // Moved all the sessions over, so the other call should no longer have any. 657 call->media_session_map_.clear(); 658 } 659 660 void Call::StartConnectionMonitor(Session* session, int cms) { 661 VoiceChannel* voice_channel = GetVoiceChannel(session); 662 if (voice_channel) { 663 voice_channel->SignalConnectionMonitor.connect(this, 664 &Call::OnConnectionMonitor); 665 voice_channel->StartConnectionMonitor(cms); 666 } 667 668 VideoChannel* video_channel = GetVideoChannel(session); 669 if (video_channel) { 670 video_channel->SignalConnectionMonitor.connect(this, 671 &Call::OnConnectionMonitor); 672 video_channel->StartConnectionMonitor(cms); 673 } 674 } 675 676 void Call::StopConnectionMonitor(Session* session) { 677 VoiceChannel* voice_channel = GetVoiceChannel(session); 678 if (voice_channel) { 679 voice_channel->StopConnectionMonitor(); 680 voice_channel->SignalConnectionMonitor.disconnect(this); 681 } 682 683 VideoChannel* video_channel = GetVideoChannel(session); 684 if (video_channel) { 685 video_channel->StopConnectionMonitor(); 686 video_channel->SignalConnectionMonitor.disconnect(this); 687 } 688 } 689 690 void Call::StartAudioMonitor(Session* session, int cms) { 691 VoiceChannel* voice_channel = GetVoiceChannel(session); 692 if (voice_channel) { 693 voice_channel->SignalAudioMonitor.connect(this, &Call::OnAudioMonitor); 694 voice_channel->StartAudioMonitor(cms); 695 } 696 } 697 698 void Call::StopAudioMonitor(Session* session) { 699 VoiceChannel* voice_channel = GetVoiceChannel(session); 700 if (voice_channel) { 701 voice_channel->StopAudioMonitor(); 702 voice_channel->SignalAudioMonitor.disconnect(this); 703 } 704 } 705 706 bool Call::IsAudioMonitorRunning(Session* session) { 707 VoiceChannel* voice_channel = GetVoiceChannel(session); 708 if (voice_channel) { 709 return voice_channel->IsAudioMonitorRunning(); 710 } else { 711 return false; 712 } 713 } 714 715 void Call::StartSpeakerMonitor(Session* session) { 716 if (speaker_monitor_map_.find(session->id()) == speaker_monitor_map_.end()) { 717 if (!IsAudioMonitorRunning(session)) { 718 StartAudioMonitor(session, kAudioMonitorPollPeriodMillis); 719 } 720 CurrentSpeakerMonitor* speaker_monitor = 721 new cricket::CurrentSpeakerMonitor(this, session); 722 speaker_monitor->SignalUpdate.connect(this, &Call::OnSpeakerMonitor); 723 speaker_monitor->Start(); 724 speaker_monitor_map_[session->id()] = speaker_monitor; 725 } else { 726 LOG(LS_WARNING) << "Already started speaker monitor for session " 727 << session->id() << "."; 728 } 729 } 730 731 void Call::StopSpeakerMonitor(Session* session) { 732 if (speaker_monitor_map_.find(session->id()) == speaker_monitor_map_.end()) { 733 LOG(LS_WARNING) << "Speaker monitor for session " 734 << session->id() << " already stopped."; 735 } else { 736 CurrentSpeakerMonitor* monitor = speaker_monitor_map_[session->id()]; 737 monitor->Stop(); 738 speaker_monitor_map_.erase(session->id()); 739 delete monitor; 740 } 741 } 742 743 void Call::OnConnectionMonitor(VoiceChannel* channel, 744 const std::vector<ConnectionInfo> &infos) { 745 SignalConnectionMonitor(this, infos); 746 } 747 748 void Call::OnMediaMonitor(VoiceChannel* channel, const VoiceMediaInfo& info) { 749 last_voice_media_info_ = info; 750 SignalMediaMonitor(this, info); 751 } 752 753 void Call::OnAudioMonitor(VoiceChannel* channel, const AudioInfo& info) { 754 SignalAudioMonitor(this, info); 755 } 756 757 void Call::OnSpeakerMonitor(CurrentSpeakerMonitor* monitor, uint32 ssrc) { 758 Session* session = static_cast<Session*>(monitor->session()); 759 MediaStreams* recv_streams = GetMediaStreams(session); 760 if (recv_streams) { 761 StreamParams stream; 762 recv_streams->GetAudioStream(StreamSelector(ssrc), &stream); 763 SignalSpeakerMonitor(this, session, stream); 764 } 765 } 766 767 void Call::OnConnectionMonitor(VideoChannel* channel, 768 const std::vector<ConnectionInfo> &infos) { 769 SignalVideoConnectionMonitor(this, infos); 770 } 771 772 void Call::OnMediaMonitor(VideoChannel* channel, const VideoMediaInfo& info) { 773 SignalVideoMediaMonitor(this, info); 774 } 775 776 void Call::OnDataReceived(DataChannel* channel, 777 const ReceiveDataParams& params, 778 const talk_base::Buffer& payload) { 779 SignalDataReceived(this, params, payload); 780 } 781 782 uint32 Call::id() { 783 return id_; 784 } 785 786 void Call::OnSessionState(BaseSession* base_session, BaseSession::State state) { 787 Session* session = static_cast<Session*>(base_session); 788 switch (state) { 789 case Session::STATE_RECEIVEDACCEPT: 790 UpdateRemoteMediaStreams(session, 791 session->remote_description()->contents(), false); 792 session_client_->session_manager()->signaling_thread()->Clear(this, 793 MSG_TERMINATECALL); 794 break; 795 case Session::STATE_RECEIVEDREJECT: 796 case Session::STATE_RECEIVEDTERMINATE: 797 session_client_->session_manager()->signaling_thread()->Clear(this, 798 MSG_TERMINATECALL); 799 break; 800 default: 801 break; 802 } 803 SignalSessionState(this, session, state); 804 } 805 806 void Call::OnSessionError(BaseSession* base_session, Session::Error error) { 807 session_client_->session_manager()->signaling_thread()->Clear(this, 808 MSG_TERMINATECALL); 809 SignalSessionError(this, static_cast<Session*>(base_session), error); 810 } 811 812 void Call::OnSessionInfoMessage(Session* session, 813 const buzz::XmlElement* action_elem) { 814 if (!IsJingleViewRequest(action_elem)) { 815 return; 816 } 817 818 ViewRequest view_request; 819 ParseError error; 820 if (!ParseJingleViewRequest(action_elem, &view_request, &error)) { 821 LOG(LS_WARNING) << "Failed to parse view request: " << error.text; 822 return; 823 } 824 825 VideoChannel* video_channel = GetVideoChannel(session); 826 if (video_channel == NULL) { 827 LOG(LS_WARNING) << "Ignore view request since we have no video channel."; 828 return; 829 } 830 831 if (!video_channel->ApplyViewRequest(view_request)) { 832 LOG(LS_WARNING) << "Failed to ApplyViewRequest."; 833 } 834 } 835 836 void Call::OnRemoteDescriptionUpdate(BaseSession* base_session, 837 const ContentInfos& updated_contents) { 838 Session* session = static_cast<Session*>(base_session); 839 840 const ContentInfo* audio_content = GetFirstAudioContent(updated_contents); 841 if (audio_content) { 842 const AudioContentDescription* audio_update = 843 static_cast<const AudioContentDescription*>(audio_content->description); 844 if (!audio_update->codecs().empty()) { 845 UpdateVoiceChannelRemoteContent(session, audio_update); 846 } 847 } 848 849 const ContentInfo* video_content = GetFirstVideoContent(updated_contents); 850 if (video_content) { 851 const VideoContentDescription* video_update = 852 static_cast<const VideoContentDescription*>(video_content->description); 853 if (!video_update->codecs().empty()) { 854 UpdateVideoChannelRemoteContent(session, video_update); 855 } 856 } 857 858 const ContentInfo* data_content = GetFirstDataContent(updated_contents); 859 if (data_content) { 860 const DataContentDescription* data_update = 861 static_cast<const DataContentDescription*>(data_content->description); 862 if (!data_update->codecs().empty()) { 863 UpdateDataChannelRemoteContent(session, data_update); 864 } 865 } 866 867 UpdateRemoteMediaStreams(session, updated_contents, true); 868 } 869 870 bool Call::UpdateVoiceChannelRemoteContent( 871 Session* session, const AudioContentDescription* audio) { 872 VoiceChannel* voice_channel = GetVoiceChannel(session); 873 if (!voice_channel->SetRemoteContent(audio, CA_UPDATE)) { 874 LOG(LS_ERROR) << "Failure in audio SetRemoteContent with CA_UPDATE"; 875 session->SetError(BaseSession::ERROR_CONTENT); 876 return false; 877 } 878 return true; 879 } 880 881 bool Call::UpdateVideoChannelRemoteContent( 882 Session* session, const VideoContentDescription* video) { 883 VideoChannel* video_channel = GetVideoChannel(session); 884 if (!video_channel->SetRemoteContent(video, CA_UPDATE)) { 885 LOG(LS_ERROR) << "Failure in video SetRemoteContent with CA_UPDATE"; 886 session->SetError(BaseSession::ERROR_CONTENT); 887 return false; 888 } 889 return true; 890 } 891 892 bool Call::UpdateDataChannelRemoteContent( 893 Session* session, const DataContentDescription* data) { 894 DataChannel* data_channel = GetDataChannel(session); 895 if (!data_channel->SetRemoteContent(data, CA_UPDATE)) { 896 LOG(LS_ERROR) << "Failure in data SetRemoteContent with CA_UPDATE"; 897 session->SetError(BaseSession::ERROR_CONTENT); 898 return false; 899 } 900 return true; 901 } 902 903 void Call::UpdateRemoteMediaStreams(Session* session, 904 const ContentInfos& updated_contents, 905 bool update_channels) { 906 MediaStreams* recv_streams = GetMediaStreams(session); 907 if (!recv_streams) 908 return; 909 910 cricket::MediaStreams added_streams; 911 cricket::MediaStreams removed_streams; 912 913 const ContentInfo* audio_content = GetFirstAudioContent(updated_contents); 914 if (audio_content) { 915 const AudioContentDescription* audio_update = 916 static_cast<const AudioContentDescription*>(audio_content->description); 917 UpdateRecvStreams(audio_update->streams(), 918 update_channels ? GetVoiceChannel(session) : NULL, 919 recv_streams->mutable_audio(), 920 added_streams.mutable_audio(), 921 removed_streams.mutable_audio()); 922 } 923 924 const ContentInfo* video_content = GetFirstVideoContent(updated_contents); 925 if (video_content) { 926 const VideoContentDescription* video_update = 927 static_cast<const VideoContentDescription*>(video_content->description); 928 UpdateRecvStreams(video_update->streams(), 929 update_channels ? GetVideoChannel(session) : NULL, 930 recv_streams->mutable_video(), 931 added_streams.mutable_video(), 932 removed_streams.mutable_video()); 933 } 934 935 const ContentInfo* data_content = GetFirstDataContent(updated_contents); 936 if (data_content) { 937 const DataContentDescription* data_update = 938 static_cast<const DataContentDescription*>(data_content->description); 939 UpdateRecvStreams(data_update->streams(), 940 update_channels ? GetDataChannel(session) : NULL, 941 recv_streams->mutable_data(), 942 added_streams.mutable_data(), 943 removed_streams.mutable_data()); 944 } 945 946 if (!added_streams.empty() || !removed_streams.empty()) { 947 SignalMediaStreamsUpdate(this, session, added_streams, removed_streams); 948 } 949 } 950 951 void FindStreamChanges(const std::vector<StreamParams>& streams, 952 const std::vector<StreamParams>& updates, 953 std::vector<StreamParams>* added_streams, 954 std::vector<StreamParams>* removed_streams) { 955 for (std::vector<StreamParams>::const_iterator update = updates.begin(); 956 update != updates.end(); ++update) { 957 StreamParams stream; 958 if (GetStreamByIds(streams, update->groupid, update->id, &stream)) { 959 if (!update->has_ssrcs()) { 960 removed_streams->push_back(stream); 961 } 962 } else { 963 // There's a bug on reflector that will send <stream>s even 964 // though there is not ssrc (which means there isn't really a 965 // stream). To work around it, we simply ignore new <stream>s 966 // that don't have any ssrcs. 967 if (update->has_ssrcs()) { 968 added_streams->push_back(*update); 969 } 970 } 971 } 972 } 973 974 void Call::UpdateRecvStreams(const std::vector<StreamParams>& update_streams, 975 BaseChannel* channel, 976 std::vector<StreamParams>* recv_streams, 977 std::vector<StreamParams>* added_streams, 978 std::vector<StreamParams>* removed_streams) { 979 FindStreamChanges(*recv_streams, 980 update_streams, added_streams, removed_streams); 981 AddRecvStreams(*added_streams, 982 channel, recv_streams); 983 RemoveRecvStreams(*removed_streams, 984 channel, recv_streams); 985 } 986 987 void Call::AddRecvStreams(const std::vector<StreamParams>& added_streams, 988 BaseChannel* channel, 989 std::vector<StreamParams>* recv_streams) { 990 std::vector<StreamParams>::const_iterator stream; 991 for (stream = added_streams.begin(); 992 stream != added_streams.end(); 993 ++stream) { 994 AddRecvStream(*stream, channel, recv_streams); 995 } 996 } 997 998 void Call::AddRecvStream(const StreamParams& stream, 999 BaseChannel* channel, 1000 std::vector<StreamParams>* recv_streams) { 1001 if (channel && stream.has_ssrcs()) { 1002 channel->AddRecvStream(stream); 1003 } 1004 recv_streams->push_back(stream); 1005 } 1006 1007 void Call::RemoveRecvStreams(const std::vector<StreamParams>& removed_streams, 1008 BaseChannel* channel, 1009 std::vector<StreamParams>* recv_streams) { 1010 std::vector<StreamParams>::const_iterator stream; 1011 for (stream = removed_streams.begin(); 1012 stream != removed_streams.end(); 1013 ++stream) { 1014 RemoveRecvStream(*stream, channel, recv_streams); 1015 } 1016 } 1017 1018 void Call::RemoveRecvStream(const StreamParams& stream, 1019 BaseChannel* channel, 1020 std::vector<StreamParams>* recv_streams) { 1021 if (channel && stream.has_ssrcs()) { 1022 // TODO(pthatcher): Change RemoveRecvStream to take a stream argument. 1023 channel->RemoveRecvStream(stream.first_ssrc()); 1024 } 1025 RemoveStreamByIds(recv_streams, stream.groupid, stream.id); 1026 } 1027 1028 void Call::OnReceivedTerminateReason(Session* session, 1029 const std::string& reason) { 1030 session_client_->session_manager()->signaling_thread()->Clear(this, 1031 MSG_TERMINATECALL); 1032 SignalReceivedTerminateReason(this, session, reason); 1033 } 1034 1035 // TODO(mdodd): Get ride of this method since all Hangouts are using a secure 1036 // connection. 1037 bool Call::secure() const { 1038 if (session_client_->secure() == SEC_DISABLED) { 1039 return false; 1040 } 1041 1042 bool ret = true; 1043 int i = 0; 1044 1045 MediaSessionMap::const_iterator it; 1046 for (it = media_session_map_.begin(); it != media_session_map_.end(); ++it) { 1047 LOG_F(LS_VERBOSE) << "session[" << i 1048 << "], check local and remote descriptions"; 1049 i++; 1050 1051 if (!SessionDescriptionContainsCrypto( 1052 it->second.session->local_description()) || 1053 !SessionDescriptionContainsCrypto( 1054 it->second.session->remote_description())) { 1055 ret = false; 1056 break; 1057 } 1058 } 1059 1060 LOG_F(LS_VERBOSE) << "secure=" << ret; 1061 return ret; 1062 } 1063 1064 bool Call::SessionDescriptionContainsCrypto( 1065 const SessionDescription* sdesc) const { 1066 if (sdesc == NULL) { 1067 LOG_F(LS_VERBOSE) << "sessionDescription is NULL"; 1068 return false; 1069 } 1070 1071 return ContentContainsCrypto(sdesc->GetContentByName(CN_AUDIO)) && 1072 ContentContainsCrypto(sdesc->GetContentByName(CN_VIDEO)); 1073 } 1074 1075 Session* Call::InternalInitiateSession(const std::string& id, 1076 const buzz::Jid& to, 1077 const std::string& initiator_name, 1078 const CallOptions& options) { 1079 const SessionDescription* offer = session_client_->CreateOffer(options); 1080 1081 Session* session = session_client_->CreateSession(id, this); 1082 session->set_initiator_name(initiator_name); 1083 1084 AddSession(session, offer); 1085 session->Initiate(to.Str(), offer); 1086 1087 // After this timeout, terminate the call because the callee isn't 1088 // answering 1089 session_client_->session_manager()->signaling_thread()->Clear(this, 1090 MSG_TERMINATECALL); 1091 session_client_->session_manager()->signaling_thread()->PostDelayed( 1092 send_to_voicemail_ ? kSendToVoicemailTimeout : kNoVoicemailTimeout, 1093 this, MSG_TERMINATECALL); 1094 return session; 1095 } 1096 1097 } // namespace cricket 1098