media/webrtc/signaling/src/softphonewrapper/CC_SIPCCCall.cpp

Thu, 15 Jan 2015 15:59:08 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 15 Jan 2015 15:59:08 +0100
branch
TOR_BUG_9701
changeset 10
ac0c01689b40
permissions
-rw-r--r--

Implement a real Private Browsing Mode condition by changing the API/ABI;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

     1 /* This Source Code Form is subject to the terms of the Mozilla Public
     2  * License, v. 2.0. If a copy of the MPL was not distributed with this
     3  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     5 #include "CSFLog.h"
     6 #include "timecard.h"
     8 #include "CC_Common.h"
    10 #include "CC_SIPCCCall.h"
    11 #include "CC_SIPCCCallInfo.h"
    12 #include "VcmSIPCCBinding.h"
    13 #include "CSFVideoTermination.h"
    14 #include "CSFAudioTermination.h"
    15 #include "CSFAudioControl.h"
    17 extern "C"
    18 {
    19 #include "ccapi_call.h"
    20 #include "ccapi_call_listener.h"
    21 #include "config_api.h"
    22 }
    24 using namespace std;
    25 using namespace CSF;
    27 static const char* logTag = "CC_SIPCCCall";
    29 CSF_IMPLEMENT_WRAP(CC_SIPCCCall, cc_call_handle_t);
    31 CC_SIPCCCall::CC_SIPCCCall (cc_call_handle_t aCallHandle) :
    32             callHandle(aCallHandle),
    33             pMediaData(new CC_SIPCCCallMediaData(nullptr, false, false, -1)),
    34             m_lock("CC_SIPCCCall")
    35 {
    36     CSFLogInfo( logTag, "Creating  CC_SIPCCCall %u", callHandle );
    38     AudioControl * audioControl = VcmSIPCCBinding::getAudioControl();
    40     if(audioControl)
    41     {
    42          pMediaData->volume = audioControl->getDefaultVolume();
    43     }
    44 }
    47 /*
    48   CCAPI_CALL_EV_CAPABILITY      -- From phone team: "...CCAPI_CALL_EV_CAPABILITY is generated for the capability changes but we decided to
    49                                    suppress it if it's due to state changes. We found it redundant as a state change implicitly implies a
    50                                    capability change. This event will still be generated if the capability changes without a state change.
    51   CCAPI_CALL_EV_CALLINFO        -- From phone team: "...CCAPI_CALL_EV_CALLINFO is generated for any caller id related changes including
    52                                    called/calling/redirecting name/number etc..."
    53   CCAPI_CALL_EV_PLACED_CALLINFO -- From phone team: "CCAPI_CALL_EV_PLACED_CALLINFO was a trigger to update the placed call history and
    54                                    gives the actual number dialed out. I think this event can be deprecated."
    55 */
    57 /*
    58  CallState
    60    REORDER: You get this if you misdial a number.
    61  */
    63 // This function sets the remote window parameters for the call. Note that it currently only tolerates a single
    64 // video stream on the call and would need to be updated to handle multiple remote video streams for conferencing.
    65 void CC_SIPCCCall::setRemoteWindow (VideoWindowHandle window)
    66 {
    67     VideoTermination * pVideo = VcmSIPCCBinding::getVideoTermination();
    68      pMediaData->remoteWindow = window;
    70     if (!pVideo)
    71     {
    72         CSFLogWarn( logTag, "setRemoteWindow: no video provider found");
    73         return;
    74     }
    76     for (StreamMapType::iterator entry =  pMediaData->streamMap.begin(); entry !=  pMediaData->streamMap.end(); entry++)
    77     {
    78         if (entry->second.isVideo)
    79         {
    80             // first video stream found
    81             int streamId = entry->first;
    82             pVideo->setRemoteWindow(streamId,  pMediaData->remoteWindow);
    84             return;
    85         }
    86     }
    87     CSFLogInfo( logTag, "setRemoteWindow:no video stream found in call %u", callHandle );
    88 }
    90 int CC_SIPCCCall::setExternalRenderer(VideoFormat vFormat, ExternalRendererHandle renderer)
    91 {
    92     VideoTermination * pVideo = VcmSIPCCBinding::getVideoTermination();
    93      pMediaData->extRenderer = renderer;
    94      pMediaData->videoFormat = vFormat;
    96     if (!pVideo)
    97     {
    98         CSFLogWarn( logTag, "setExternalRenderer: no video provider found");
    99         return -1;
   100     }
   102     for (StreamMapType::iterator entry =  pMediaData->streamMap.begin(); entry !=  pMediaData->streamMap.end(); entry++)
   103     {
   104         if (entry->second.isVideo)
   105         {
   106             // first video stream found
   107             int streamId = entry->first;
   108             return pVideo->setExternalRenderer(streamId,  pMediaData->videoFormat, pMediaData->extRenderer);
   109         }
   110     }
   111     CSFLogInfo( logTag, "setExternalRenderer:no video stream found in call %u", callHandle );
   112 	return -1;
   113 }
   115 void CC_SIPCCCall::sendIFrame()
   116 {
   117     VideoTermination * pVideo = VcmSIPCCBinding::getVideoTermination();
   119     if (pVideo)
   120     {
   121         pVideo->sendIFrame(callHandle);
   122     }
   123 }
   125 CC_CallInfoPtr CC_SIPCCCall::getCallInfo ()
   126 {
   127     cc_callinfo_ref_t callInfo = CCAPI_Call_getCallInfo(callHandle);
   128     CC_SIPCCCallInfoPtr callInfoPtr = CC_SIPCCCallInfo::wrap(callInfo);
   129     callInfoPtr->setMediaData( pMediaData);
   130     return callInfoPtr.get();
   131 }
   134 //
   135 // Operations - The following function are actions that can be taken the execute an operation on the Call, ie calls
   136 //              down to pSIPCC to originate a call, end a call etc.
   137 //
   139 bool CC_SIPCCCall::originateCall (cc_sdp_direction_t video_pref, const string & digits)
   140 {
   141     return (CCAPI_Call_originateCall(callHandle, video_pref, digits.c_str()) == CC_SUCCESS);
   142 }
   144 bool CC_SIPCCCall::answerCall (cc_sdp_direction_t video_pref)
   145 {
   146     return (CCAPI_Call_answerCall(callHandle, video_pref) == CC_SUCCESS);
   147 }
   149 bool CC_SIPCCCall::hold (cc_hold_reason_t reason)
   150 {
   151     return (CCAPI_Call_hold(callHandle, reason) == CC_SUCCESS);
   152 }
   154 bool CC_SIPCCCall::resume (cc_sdp_direction_t video_pref)
   155 {
   156     return (CCAPI_Call_resume(callHandle, video_pref) == CC_SUCCESS);
   157 }
   159 bool CC_SIPCCCall::endCall()
   160 {
   161     return (CCAPI_Call_endCall(callHandle) == CC_SUCCESS);
   162 }
   164 bool CC_SIPCCCall::sendDigit (cc_digit_t digit)
   165 {
   166 	AudioTermination * pAudio = VcmSIPCCBinding::getAudioTermination();
   167 	mozilla::MutexAutoLock lock(m_lock);
   169     // Convert public digit (as enum or char) to RFC2833 form.
   170 	int digitId = -1;
   171 	switch(digit)
   172 	{
   173 	case '0':
   174 		digitId = 0;
   175 		break;
   176 	case '1':
   177 		digitId = 1;
   178 		break;
   179 	case '2':
   180 		digitId = 2;
   181 		break;
   182 	case '3':
   183 		digitId = 3;
   184 		break;
   185 	case '4':
   186 		digitId = 4;
   187 		break;
   188 	case '5':
   189 		digitId = 5;
   190 		break;
   191 	case '6':
   192 		digitId = 6;
   193 		break;
   194 	case '7':
   195 		digitId = 7;
   196 		break;
   197 	case '8':
   198 		digitId = 8;
   199 		break;
   200 	case '9':
   201 		digitId = 9;
   202 		break;
   203 	case '*':
   204 		digitId = 10;
   205 		break;
   206 	case '#':
   207 		digitId = 11;
   208 		break;
   209 	case 'A':
   210 		digitId = 12;
   211 		break;
   212 	case 'B':
   213 		digitId = 13;
   214 		break;
   215 	case 'C':
   216 		digitId = 14;
   217 		break;
   218 	case 'D':
   219 		digitId = 15;
   220 		break;
   221   case '+':
   222     digitId = 16;
   223     break;
   224 	}
   226     for (StreamMapType::iterator entry =  pMediaData->streamMap.begin(); entry !=  pMediaData->streamMap.end(); entry++)
   227     {
   228 		if (entry->second.isVideo == false)
   229 		{
   230 			// first is the streamId
   231 			if (pAudio->sendDtmf(entry->first, digitId) != 0)
   232 			{
   233 				// We have sent a digit, done.
   234 				break;
   235 			}
   236 			else
   237 			{
   238 				CSFLogWarn( logTag, "sendDigit:sendDtmf returned fail");
   239 			}
   240 		}
   241     }
   242     return (CCAPI_Call_sendDigit(callHandle, digit) == CC_SUCCESS);
   243 }
   245 bool CC_SIPCCCall::backspace()
   246 {
   247     return (CCAPI_Call_backspace(callHandle) == CC_SUCCESS);
   248 }
   250 bool CC_SIPCCCall::redial (cc_sdp_direction_t video_pref)
   251 {
   252     return (CCAPI_Call_redial(callHandle, video_pref) == CC_SUCCESS);
   253 }
   255 bool CC_SIPCCCall::initiateCallForwardAll()
   256 {
   257     return (CCAPI_Call_initiateCallForwardAll(callHandle) == CC_SUCCESS);
   258 }
   260 bool CC_SIPCCCall::endConsultativeCall()
   261 {
   262     return (CCAPI_Call_endConsultativeCall(callHandle) == CC_SUCCESS);
   263 }
   265 bool CC_SIPCCCall::conferenceStart (cc_sdp_direction_t video_pref)
   266 {
   267     return (CCAPI_Call_conferenceStart(callHandle, video_pref) == CC_SUCCESS);
   268 }
   270 bool CC_SIPCCCall::conferenceComplete (CC_CallPtr otherLeg, cc_sdp_direction_t video_pref)
   271 {
   272     return (CCAPI_Call_conferenceComplete(callHandle, ((CC_SIPCCCall*)otherLeg.get())->callHandle, video_pref) == CC_SUCCESS);
   273 }
   275 bool CC_SIPCCCall::transferStart (cc_sdp_direction_t video_pref)
   276 {
   277     return (CCAPI_Call_transferStart(callHandle, video_pref) == CC_SUCCESS);
   278 }
   280 bool CC_SIPCCCall::transferComplete (CC_CallPtr otherLeg,
   281                                      cc_sdp_direction_t video_pref)
   282 {
   283     return (CCAPI_Call_transferComplete(callHandle, ((CC_SIPCCCall*)otherLeg.get())->callHandle, video_pref) == CC_SUCCESS);
   284 }
   286 bool CC_SIPCCCall::cancelTransferOrConferenceFeature()
   287 {
   288     return (CCAPI_Call_cancelTransferOrConferenceFeature(callHandle) == CC_SUCCESS);
   289 }
   291 bool CC_SIPCCCall::directTransfer (CC_CallPtr target)
   292 {
   293     return (CCAPI_Call_directTransfer(callHandle, ((CC_SIPCCCall*)target.get())->callHandle) == CC_SUCCESS);
   294 }
   296 bool CC_SIPCCCall::joinAcrossLine (CC_CallPtr target)
   297 {
   298     return (CCAPI_Call_joinAcrossLine(callHandle, ((CC_SIPCCCall*)target.get())->callHandle) == CC_SUCCESS);
   299 }
   301 bool CC_SIPCCCall::blfCallPickup (cc_sdp_direction_t video_pref, const string & speed)
   302 {
   303     return (CCAPI_Call_blfCallPickup(callHandle, video_pref, speed.c_str()) == CC_SUCCESS);
   304 }
   306 bool CC_SIPCCCall::select()
   307 {
   308     return (CCAPI_Call_select(callHandle) == CC_SUCCESS);
   309 }
   311 bool CC_SIPCCCall::updateVideoMediaCap (cc_sdp_direction_t video_pref)
   312 {
   313     return (CCAPI_Call_updateVideoMediaCap(callHandle, video_pref) == CC_SUCCESS);
   314 }
   316 bool CC_SIPCCCall::sendInfo (const string & infopackage, const string & infotype, const string & infobody)
   317 {
   318     return (CCAPI_Call_sendInfo(callHandle, infopackage.c_str(), infotype.c_str(), infobody.c_str()) == CC_SUCCESS);
   319 }
   321 bool CC_SIPCCCall::muteAudio(void)
   322 {
   323     return setAudioMute(true);
   324 }
   326 bool CC_SIPCCCall::unmuteAudio()
   327 {
   328 	return setAudioMute(false);
   329 }
   331 bool CC_SIPCCCall::muteVideo()
   332 {
   333 	return setVideoMute(true);
   334 }
   336 bool CC_SIPCCCall::unmuteVideo()
   337 {
   338 	return setVideoMute(false);
   339 }
   341 bool CC_SIPCCCall::setAudioMute(bool mute)
   342 {
   343 	bool returnCode = false;
   344 	AudioTermination * pAudio = VcmSIPCCBinding::getAudioTermination();
   345 	pMediaData->audioMuteState = mute;
   346 	// we need to set the mute status of all audio streams in the map
   347 	{
   348 		mozilla::MutexAutoLock lock(m_lock);
   349 		for (StreamMapType::iterator entry =  pMediaData->streamMap.begin(); entry !=  pMediaData->streamMap.end(); entry++)
   350 	    {
   351 			if (entry->second.isVideo == false)
   352 			{
   353 				// first is the streamId
   354 				if (pAudio->mute(entry->first, mute))
   355 				{
   356 					// We have muted at least one stream
   357 					returnCode = true;
   358 				}
   359 				else
   360 				{
   361 					CSFLogWarn( logTag, "setAudioMute:audio mute returned fail");
   362 				}
   363 			}
   364 	    }
   365 	}
   367     if  (CCAPI_Call_setAudioMute(callHandle, mute) != CC_SUCCESS)
   368     {
   369     	returnCode = false;
   370     }
   372 	return returnCode;
   373 }
   375 bool CC_SIPCCCall::setVideoMute(bool mute)
   376 {
   377 	bool returnCode = false;
   378 	VideoTermination * pVideo = VcmSIPCCBinding::getVideoTermination();
   379 	pMediaData->videoMuteState = mute;
   380 	// we need to set the mute status of all audio streams in the map
   381 	{
   382 		mozilla::MutexAutoLock lock(m_lock);
   383 		for (StreamMapType::iterator entry =  pMediaData->streamMap.begin(); entry !=  pMediaData->streamMap.end(); entry++)
   384 	    {
   385 			if (entry->second.isVideo == true)
   386 			{
   387 				// first is the streamId
   388 				if (pVideo->mute(entry->first, mute))
   389 				{
   390 					// We have muted at least one stream
   391 					returnCode = true;
   392 				}
   393 				else
   394 				{
   395 					CSFLogWarn( logTag, "setVideoMute:video mute returned fail");
   396 				}
   397 			}
   398 	    }
   399 	}
   401     if  (CCAPI_Call_setVideoMute(callHandle, mute) != CC_SUCCESS)
   402     {
   403     	returnCode = false;
   404     }
   406 	return returnCode;
   407 }
   409 void CC_SIPCCCall::addStream(int streamId, bool isVideo)
   410 {
   412 	CSFLogInfo( logTag, "addStream: %d video=%s callhandle=%u",
   413         streamId, isVideo ? "TRUE" : "FALSE", callHandle);
   414 	{
   415 		mozilla::MutexAutoLock lock(m_lock);
   416 		pMediaData->streamMap[streamId].isVideo = isVideo;
   417 	}
   418 	// The new stream needs to be given any properties that the call has for it.
   419 	// At the moment the only candidate is the muted state
   420 	if (isVideo)
   421 	{
   422 #ifndef NO_WEBRTC_VIDEO
   423         VideoTermination * pVideo = VcmSIPCCBinding::getVideoTermination();
   425         // if there is a window for this call apply it to the stream
   426         if ( pMediaData->remoteWindow != nullptr)
   427         {
   428             pVideo->setRemoteWindow(streamId,  pMediaData->remoteWindow);
   429         }
   430         else
   431         {
   432             CSFLogInfo( logTag, "addStream: remoteWindow is NULL");
   433         }
   435 		if(pMediaData->extRenderer != nullptr)
   436 		{
   437 			pVideo->setExternalRenderer(streamId, pMediaData->videoFormat, pMediaData->extRenderer);
   438 		}
   439 		else
   440 		{
   441             CSFLogInfo( logTag, "addStream: externalRenderer is NULL");
   443 		}
   446         for (StreamMapType::iterator entry =  pMediaData->streamMap.begin(); entry !=  pMediaData->streamMap.end(); entry++)
   447         {
   448     		if (entry->second.isVideo == false)
   449     		{
   450     			// first is the streamId
   451     			pVideo->setAudioStreamId(entry->first);
   452     		}
   453         }
   454 		if (!pVideo->mute(streamId,  pMediaData->videoMuteState))
   455 		{
   456 			CSFLogError( logTag, "setting video mute state failed for new stream: %d", streamId);
   457 		} else
   458 		{
   459 			CSFLogError( logTag, "setting video mute state SUCCEEDED for new stream: %d", streamId);
   461 		}
   462 #endif
   463 	}
   464 	else
   465 	{
   466 		AudioTermination * pAudio = VcmSIPCCBinding::getAudioTermination();
   467 		if (!pAudio->mute(streamId,  pMediaData->audioMuteState))
   468 		{
   469 			CSFLogError( logTag, "setting audio mute state failed for new stream: %d", streamId);
   470 		}
   471         if (!pAudio->setVolume(streamId,  pMediaData->volume))
   472         {
   473 			CSFLogError( logTag, "setting volume state failed for new stream: %d", streamId);
   474         }
   475 	}
   476 }
   478 void CC_SIPCCCall::removeStream(int streamId)
   479 {
   480 	mozilla::MutexAutoLock lock(m_lock);
   482 	if ( pMediaData->streamMap.erase(streamId) != 1)
   483 	{
   484 		CSFLogError( logTag, "removeStream stream that was never in the streamMap: %d", streamId);
   485 	}
   486 }
   488 bool CC_SIPCCCall::setVolume(int volume)
   489 {
   490 	bool returnCode = false;
   492     AudioTermination * pAudio = VcmSIPCCBinding::getAudioTermination();
   493 	{
   494     	mozilla::MutexAutoLock lock(m_lock);
   495 		for (StreamMapType::iterator entry =  pMediaData->streamMap.begin(); entry !=  pMediaData->streamMap.end(); entry++)
   496 	    {
   497 			if (entry->second.isVideo == false)
   498 			{
   499 			    // first is the streamId
   500                 int streamId = entry->first;
   501 			    if (pAudio->setVolume(streamId, volume))
   502 			    {
   503                     //We have changed the volume on at least one stream,
   504                     //so persist the new volume as the call volume,
   505                     //and report success for the volume change, even if it
   506                     //fails on other streams
   507                      pMediaData->volume = volume;
   508                     returnCode = true;
   509 			    }
   510 			    else
   511 			    {
   512 				    CSFLogWarn( logTag, "setVolume:set volume on stream %d returned fail",
   513                         streamId);
   514                 }
   515             }
   516 	    }
   517 	}
   518     return returnCode;
   519 }
   521 CC_SIPCCCallMediaDataPtr CC_SIPCCCall::getMediaData()
   522 {
   523     return  pMediaData;
   524 }
   526 void CC_SIPCCCall::originateP2PCall (cc_sdp_direction_t video_pref, const std::string & digits, const std::string & ip)
   527 {
   528     CCAPI_Config_set_server_address(ip.c_str());
   529     CCAPI_Call_originateCall(callHandle, video_pref, digits.c_str());
   530 }
   532 /*
   533  * This method works asynchronously, is an onCallEvent with the resulting SDP
   534  */
   535 void CC_SIPCCCall::createOffer (cc_media_constraints_t *constraints,
   536                                 Timecard *tc) {
   537     CCAPI_CreateOffer(callHandle, constraints, tc);
   538 }
   539 /*
   540  * This method works asynchronously, there is onCallEvent with the resulting SDP
   541  */
   542 void CC_SIPCCCall::createAnswer (cc_media_constraints_t *constraints,
   543                                  Timecard *tc) {
   544     CCAPI_CreateAnswer(callHandle, constraints, tc);
   546 }
   548 void CC_SIPCCCall::setLocalDescription(cc_jsep_action_t action,
   549                                        const std::string & sdp,
   550                                        Timecard *tc) {
   551     CCAPI_SetLocalDescription(callHandle, action, sdp.c_str(), tc);
   552 }
   554 void CC_SIPCCCall::setRemoteDescription(cc_jsep_action_t action,
   555                                        const std::string & sdp,
   556                                        Timecard *tc) {
   557     CCAPI_SetRemoteDescription(callHandle, action, sdp.c_str(), tc);
   558 }
   560 void CC_SIPCCCall::setPeerConnection(const std::string& handle)
   561 {
   562   CSFLogDebug(logTag, "setPeerConnection");
   564   peerconnection = handle;  // Cache this here. we need it to make the CC_SIPCCCallInfo
   565   CCAPI_SetPeerConnection(callHandle, handle.c_str());
   566 }
   568 const std::string& CC_SIPCCCall::getPeerConnection() const {
   569   return peerconnection;
   570 }
   572 void CC_SIPCCCall::addStream(cc_media_stream_id_t stream_id,
   573                              cc_media_track_id_t track_id,
   574                              cc_media_type_t media_type,
   575                              cc_media_constraints_t *constraints) {
   576   CCAPI_AddStream(callHandle, stream_id, track_id, media_type, constraints);
   577 }
   579 void CC_SIPCCCall::removeStream(cc_media_stream_id_t stream_id, cc_media_track_id_t track_id, cc_media_type_t media_type) {
   580   CCAPI_RemoveStream(callHandle, stream_id, track_id, media_type);
   581 }
   583 void CC_SIPCCCall::addICECandidate(const std::string & candidate,
   584                                    const std::string & mid,
   585                                    unsigned short level,
   586                                    Timecard *tc) {
   587   CCAPI_AddICECandidate(callHandle, candidate.c_str(), mid.c_str(),
   588                         (cc_level_t) level, tc);
   589 }

mercurial