media/webrtc/signaling/src/softphonewrapper/CC_SIPCCService.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 #ifdef _WIN32
     6 #include <windows.h> //plat_api.h seems to need some of the types defined in Windows.h (e.g. boolean)
     7 #endif
     9 #include "CSFLog.h"
    11 #include "CC_CallTypes.h"
    12 #include "CC_SIPCCService.h"
    13 #include "NullDeleter.h"
    14 #include "CC_SIPCCDevice.h"
    15 #include "CC_SIPCCDeviceInfo.h"
    16 #include "CC_SIPCCFeatureInfo.h"
    17 #include "CC_SIPCCCallServerInfo.h"
    18 #include "CC_SIPCCCall.h"
    19 #include "CC_SIPCCCallInfo.h"
    20 #include "CC_SIPCCLine.h"
    21 #include "CC_SIPCCLineInfo.h"
    22 #include "CSFMediaProvider.h"
    23 #include "CSFAudioTermination.h"
    24 #include "CSFVideoTermination.h"
    26 #include "base/platform_thread.h"
    27 #include "base/time.h"
    29 extern "C" {
    30 #include "ccapi_device.h"
    31 }
    32 #include "debug-psipcc-types.h"
    33 #include "VcmSIPCCBinding.h"
    35 #include "csf_common.h"
    37 static const char* logTag = "CC_SIPCCService";
    39 using namespace std;
    41 #define MAX_SUPPORTED_NUM_CALLS        100
    42 #define MAX_SUPPORTED_NUM_LINES        100
    43 #define MAX_SUPPORTED_NUM_FEATURES     100
    44 #define MAX_SUPPORTED_NUM_CALL_SERVERS 100
    46 extern "C"
    47 {
    48 #include "cpr_types.h"
    49 #include "ccapi_device.h"
    50 #include "ccapi_device_info.h"
    51 #include "ccapi_call.h"
    53 #include "cpr_stdio.h"
    54 #include "config_api.h"
    55 #include "ccapi_service.h"
    56 #include "plat_api.h"
    58 /**
    59  * configCtlFetchReq
    60  *
    61  * This function tells the config manager to fetch the CTL file
    62  * and then fetch the config  from the CUCM. It is expected that
    63  * this will result in processing of
    64  * the config file after the config managers response is received.
    65  *
    66  * The response received for this request is asynchronous and
    67  * should be handled via event provided by config manager.
    68  * The CCAPI_Config_reponse api needs to be called for the
    69  * handling of the response to the fetch request
    70  *
    71  */
    72 void configCtlFetchReq(int device_handle)
    73 {
    74     CSFLogDebug(logTag, "In configCtlFetchReq");
    76     CSF::CC_SIPCCService * pPhone = CSF::CC_SIPCCService::_self;
    78     if (pPhone == nullptr)
    79     {
    80         CSFLogError( logTag, "CC_SIPCCService::_self is NULL.");
    81     }
    82     else
    83     {
    84     	CCAPI_Start_response(device_handle, pPhone->deviceName.c_str(), pPhone->sipUser.c_str(),
    85     						 	 pPhone->sipPassword.c_str(), pPhone->sipDomain.c_str());
    86     }
    87 }
    89 /**
    90  * configFetchReq
    91  *
    92  * This function tells the config manager to fetch the latest config
    93  * from the CUCM. It is expected that this will result in processing of
    94  * the config file after the config managers response is received.
    95  *
    96  * The response received for this request is asynchronous and
    97  * should be handled via event provided by config manager.
    98  * The CCAPI_Config_reponse api needs to be called for the
    99  * handling of the response to the fetch request
   100  *
   101  * There are cases where only the config file is needed, for eg: during
   102  * Apply Config, for those situation we use this API
   103  *
   104  */
   105 void configFetchReq(int device_handle)
   106 {
   107     CSFLogDebug( logTag, "In configFetchReq");
   109     configCtlFetchReq(device_handle);
   110 }
   112 /**
   113  * configParserError
   114  *
   115  * Notify the config manager that the config file has an error
   116  * and a new config file needs to be downloaded.
   117  *
   118  * The error could be XML format error or minimum config not being
   119  * present in the config file.  It is expected that
   120  * this will result in processing of
   121  * the config file after the config managers response is received.
   122  *
   123  */
   124 void configParserError(void)
   125 {
   126     CSFLogError( logTag, "In configParserError");
   127 }
   129 /**
   130  * Inform application that pSipcc stack has receive a NOTIFY message of event
   131  * type "service-control" and action=apply-config. The arguments passed to this
   132  * function contains the parameter values received in the message.
   133  *
   134  * @param config_version [in] latest version stamp of phone configuration.
   135  * @param dial_plan_version [in] latest version stamp of the dial plan.
   136  * @param fcp_version [in] latest version stamp of feature policy control.
   137  * @param cucm_result  [in] action taken by the cucm for the changes applied by the
   138  * user to the phone configuration. cucm result could be
   139  *  @li "no_change" - the new phone configuration changes do not impact Unified CM,
   140  *  @li "config_applied" - The Unified CM Administration applied the
   141  *  configuration changes dynamically without requiring phone to re-register,
   142  *  @li "reregister_needed" - The Unified CM Administration applied the
   143  *  configuration changes and required the phone to re-register to make them
   144  *  effective.
   145  * @param load_id [in] - firmware image name that phone should be running with
   146  * @param inactive_load_id [in] - firmware image name that phone should be in inactive partition.
   147  * @param load_server [in] - address of load server to download the  firmware
   148  * image load_id.
   149  * @param log_server [in] - log server address where error report need to be
   150  * sent. Error report, for example, could be related to image download failure
   151  * or phone configuration file download failure.
   152  * @param ppid [in] whether peer to peer upgrade is available
   153  * @return void
   154  */
   155 void configApplyConfigNotify(cc_string_t config_version,
   156 		cc_string_t dial_plan_version,
   157 		cc_string_t fcp_version,
   158 		cc_string_t cucm_result,
   159 		cc_string_t load_id,
   160 		cc_string_t inactive_load_id,
   161 		cc_string_t load_server,
   162 		cc_string_t log_server,
   163 		cc_boolean ppid)
   164 {
   165     CSFLogDebug( logTag, "In configApplyConfigNotify");
   166 }
   168 char * platGetIPAddr ()
   169 {
   170     CSFLogDebug( logTag, "In platGetIPAddr()");
   172     CSF::CC_SIPCCService * pPhone = CSF::CC_SIPCCService::_self;
   174     if (pPhone == nullptr)
   175     {
   176         CSFLogError( logTag, "In platGetIPAddr(). CC_SIPCCService::_self is NULL.");
   177         return (char *) "";
   178     }
   180 	return (char*) pPhone->localAddress.c_str();
   181 }
   183 void ccmedia_flash_once_timer_callback (void)
   184 {
   185 }
   187 /**
   188  * dialPlanFetchReq
   189  *
   190  * This function tells the get file request service to fetch the latest dial
   191  * plan from the CUCM.
   192  *
   193  * @param device_handle [in] handle of the device, the response is for
   194  * @param dialPlanFileName [in] the name of dialplan file to retrieve
   195  *
   196  */
   197 cc_boolean dialPlanFetchReq(int device_handle, char* dialPlanFileName)
   198 {
   199     return 0;
   200 }
   202 /**
   203  * fcpFetchReq
   204  *
   205  * This function tells the get file request service to fetch the latest fcp
   206  * file from the CUCM.
   207  *
   208  * @param device_handle [in] handle of the device, the response is for
   209  * @param dialPlanFileName [in] the name of fcp file to retrieve
   210  *
   211  */
   212 cc_boolean fcpFetchReq(int device_handle, char* fcpFileName)
   213 {
   214     return 0;
   215 }
   217 extern cc_int32_t SipDebugMessage;
   218 extern cc_int32_t SipDebugState;
   219 extern cc_int32_t SipDebugTask;
   220 extern cc_int32_t SipDebugRegState;
   221 extern cc_int32_t GSMDebug;
   222 extern cc_int32_t FIMDebug;
   223 extern cc_int32_t LSMDebug;
   224 extern cc_int32_t FSMDebugSM;
   225 extern int32_t CSMDebugSM;
   226 extern cc_int32_t CCDebug;
   227 extern cc_int32_t CCDebugMsg;
   228 extern cc_int32_t AuthDebug;
   229 extern cc_int32_t ConfigDebug;
   230 extern cc_int32_t DpintDebug;
   231 extern cc_int32_t KpmlDebug;
   232 extern cc_int32_t VCMDebug;
   233 extern cc_int32_t g_CCAppDebug;
   234 extern cc_int32_t g_CCLogDebug;
   235 extern cc_int32_t TNPDebug;
   237 static cc_int32_t * _maskedLoggingEntriesArray[19] = {
   238   &SipDebugMessage, //13
   239   &SipDebugState, //12
   240   &SipDebugTask, //11
   241   &SipDebugRegState, //14
   242   &GSMDebug, //7
   243   &FIMDebug, //4
   244   &LSMDebug, //8
   245   &FSMDebugSM, //5
   246   &CSMDebugSM, //??
   247   &CCDebug, //2
   248   &CCDebugMsg, //3
   249   &AuthDebug, //6
   250   &ConfigDebug, //0
   251   &DpintDebug, //18
   252   &KpmlDebug, //19
   253   &VCMDebug, //??
   254   &g_CCAppDebug, //0
   255   &g_CCLogDebug, //??
   256   &TNPDebug, //1
   257 };
   259 //Following are not covered above. :
   260 //g_cacDebug,9
   261 //g_dcsmDebug, 10
   262 //SipDebugTrx, 14
   263 //TMRDebug, 15
   264 //SipDebugDM, 16
   265 //g_DEFDebug, 17
   266 //g_blfDebug, 21
   267 //g_configappDebug, 23
   268 //CCEVENTDebug, 24
   269 //PLATDebug, 25
   271 //If you add more to this array then you'll need to manually update "HAS_21_BITS" below to be "HAS_22_BITS"
   272 //of whatever the new number of bits defined ends up as. Then modify the code that currently uses HAS_21_BITS
   273 //below to use your new #define.
   274 #define HAS_21_BITS 0x1FFFFF
   276 static int _maxBitValueMaskedLoggingEntries = csf_countof(_maskedLoggingEntriesArray);//Should be 21
   279 } //end extern C
   281 extern "C" void CCAPI_DeviceListener_onDeviceEvent(ccapi_device_event_e type, cc_device_handle_t hDevice, cc_deviceinfo_ref_t dev_info)
   282 {
   283     //CSFLogDebug( logTag, "In CCAPI_DeviceListener_onDeviceEvent");
   284     CSF::CC_SIPCCService::onDeviceEvent(type, hDevice, dev_info);
   285 }
   287 extern "C" void CCAPI_DeviceListener_onFeatureEvent(ccapi_device_event_e type, cc_deviceinfo_ref_t dev_info, cc_featureinfo_ref_t feature_info)
   288 {
   289     //CSFLogDebug( logTag, "In CCAPI_DeviceListener_onFeatureEvent");
   290     CSF::CC_SIPCCService::onFeatureEvent(type, dev_info, feature_info);
   291 }
   293 extern "C" void CCAPI_LineListener_onLineEvent(ccapi_line_event_e type, cc_lineid_t line, cc_lineinfo_ref_t info)
   294 {
   295     //CSFLogDebug( logTag, "In CCAPI_LineListener_onLineEvent");
   296     CSF::CC_SIPCCService::onLineEvent(type, line, info);
   297 }
   299 extern "C" void CCAPI_CallListener_onCallEvent(ccapi_call_event_e type, cc_call_handle_t handle, cc_callinfo_ref_t info)
   300 {
   301     //CSFLogDebug( logTag, "In CCAPI_CallListener_onCallEvent");
   302 	CSF::CC_SIPCCService::onCallEvent(type, handle, info);
   303 }
   307 namespace CSF
   308 {
   310 CC_SIPCCService* CC_SIPCCService::_self = nullptr;
   312 CC_SIPCCService::CC_SIPCCService()
   313 : loggingMask(0),
   314   bCreated(false),
   315   bStarted(false),
   316   m_lock("CC_SIPCCService"),
   317   bUseConfig(false)
   318 {
   319 	// Only one instance allowed!
   320     assert(_self == nullptr);
   321     _self = this;
   322     // <emannion> Commented as part of media provider removal
   323     //vcmMediaBridge.setStreamObserver(this);
   324     //vcmMediaBridge.setMediaProviderObserver(this);
   325 }
   327 CC_SIPCCService::~CC_SIPCCService()
   328 {
   329   destroy();
   331   _self = nullptr;
   332 }
   334 bool CC_SIPCCService::init(const std::string& user, const std::string& password, const std::string& domain, const std::string& device)
   335 {
   336     sipUser = user;
   337     sipPassword = password;
   338     sipDomain = domain;
   339     deviceName = device;
   341     if (!(bCreated = (CCAPI_Service_create() == CC_SUCCESS)))
   342     {
   343         CSFLogError( logTag, "Call to CCAPI_Service_create() failed.");
   344         return false;
   345     }
   346     return true;
   347 }
   349 void CC_SIPCCService::destroy()
   350 {
   351 	stop();
   353     if (bCreated)
   354     {
   355         if (CCAPI_Service_destroy() == CC_FAILURE)
   356         {
   357             CSFLogError( logTag, "Call to CCAPI_Service_destroy() failed.");
   358         }
   360         bCreated = false;
   361     }
   363 	deviceName = "";
   364 	loggingMask = 0;
   366     CC_SIPCCDevice::reset();
   367     CC_SIPCCDeviceInfo::reset();
   368     CC_SIPCCFeatureInfo::reset();
   369     CC_SIPCCCallServerInfo::reset();
   370     CC_SIPCCLine::reset();
   371     CC_SIPCCLineInfo::reset();
   372     CC_SIPCCCall::reset();
   373     CC_SIPCCCallInfo::reset();
   375 	if(audioControlWrapper != nullptr)
   376 	{
   377 		audioControlWrapper->setAudioControl(nullptr);
   378 	}
   379 	if(videoControlWrapper != nullptr)
   380 	{
   381 		videoControlWrapper->setVideoControl(nullptr);
   382 	}
   383 }
   385 void CC_SIPCCService::setDeviceName(const std::string& deviceName)
   386 {
   387 	this->deviceName = deviceName;
   388 }
   390 void CC_SIPCCService::setLoggingMask(int mask)
   391 {
   392 	this->loggingMask = mask;
   393 }
   395 void CC_SIPCCService::setLocalAddressAndGateway(const std::string& localAddress,
   396                                                 const std::string& defaultGW)
   397 {
   398 	this->localAddress = localAddress;
   399     this->defaultGW = defaultGW;
   401     CCAPI_Device_IP_Update(CCAPI_Device_getDeviceID(), localAddress.c_str(), "", 0,
   402                            localAddress.c_str(), "", 0);
   404 	AudioTermination* audio = VcmSIPCCBinding::getAudioTermination();
   405 	if(audio != nullptr)
   406 	{
   407 		audio->setLocalIP(localAddress.c_str());
   408 	}
   409 	VideoTermination* video = VcmSIPCCBinding::getVideoTermination();
   410 	if(video != nullptr)
   411 	{
   412 		video->setLocalIP(localAddress.c_str());
   413 	}
   414 }
   416 /*
   417  * New function to start sip stack without device file download.
   418  */
   419 bool CC_SIPCCService::startService()
   420 {
   421 	AudioTermination * pAudio = VcmSIPCCBinding::getAudioTermination();
   422 	VideoTermination * pVideo = VcmSIPCCBinding::getVideoTermination();
   424 	if(pAudio != nullptr)
   425 	{
   426 		pAudio->setMediaPorts(16384, 32766);
   427 		pAudio->setDSCPValue(184);
   428     	pAudio->setVADEnabled(false);
   429 	}
   431     if (pVideo != nullptr)
   432     {
   433 		pVideo->setDSCPValue(136);
   434     }
   436     bUseConfig = false;
   437     if (!(bStarted = (CCAPI_Service_start() == CC_SUCCESS)))
   438     {
   439         CSFLogError( logTag, "Call to CCAPI_Service_start() failed.");
   440         return false;
   441     }
   443     CC_DevicePtr devicePtr = CC_SIPCCDevice::createDevice ();
   444     if (devicePtr == nullptr)
   445     {
   446     	CSFLogWarn( logTag, "stopping because createDevice failed");
   447     	stop();
   448         return false;
   449     }
   450     CSFLogDebug( logTag, "About to imposeLoggingMask");
   451     applyLoggingMask(loggingMask);
   453     return true;
   454 }
   457 void CC_SIPCCService::stop()
   458 {
   459     if (bStarted)
   460     {
   461     	// But first, tear down all existing calls.
   462     	endAllActiveCalls();
   464         if (CCAPI_Service_stop() == CC_FAILURE)
   465         {
   466             CSFLogError( logTag, "Call to CCAPI_Service_stop() failed.");
   467         }
   469         bStarted = false;
   470     }
   471 }
   473 bool CC_SIPCCService::isStarted()
   474 {
   475 	return bStarted;
   476 }
   478 // !!! Note that accessing *Ptr instances from multiple threads can
   479 // lead to deadlocks, crashes, and spinning threads. Calls to this
   480 // method are not safe except from ccapp_thread.
   481 CC_DevicePtr CC_SIPCCService::getActiveDevice()
   482 {
   483     return CC_SIPCCDevice::wrap(CCAPI_Device_getDeviceID()).get();
   484 }
   486 // !!! Note that accessing *Ptr instances from multiple threads can
   487 // lead to deadlocks, crashes, and spinning threads. Calls to this
   488 // method are not safe except from ccapp_thread.
   489 vector<CC_DevicePtr> CC_SIPCCService::getDevices()
   490 {
   491 	vector<CC_DevicePtr> devices;
   493 	CC_SIPCCDevicePtr pDevice = CC_SIPCCDevice::wrap(CCAPI_Device_getDeviceID());
   494 	if(pDevice != nullptr)
   495 	{
   496         devices.push_back(pDevice.get());
   497     }
   499     return devices;
   500 }
   502 // !!! Note that accessing *Ptr instances from multiple threads can
   503 // lead to deadlocks, crashes, and spinning threads. Calls to this
   504 // method are not safe except from ccapp_thread.
   505 AudioControlPtr CC_SIPCCService::getAudioControl ()
   506 {
   507 	if(audioControlWrapper != nullptr)
   508 	{
   509 		return audioControlWrapper.get();
   510 	}
   511 	else
   512 	{
   513 		audioControlWrapper = AudioControlWrapperPtr(new AudioControlWrapper(VcmSIPCCBinding::getAudioControl()));
   514 		return audioControlWrapper.get();
   515 	}
   516 }
   518 // !!! Note that accessing *Ptr instances from multiple threads can
   519 // lead to deadlocks, crashes, and spinning threads. Calls to this
   520 // method are not safe except from ccapp_thread.
   521 VideoControlPtr CC_SIPCCService::getVideoControl ()
   522 {
   523 	if(videoControlWrapper != nullptr)
   524 	{
   525 		return videoControlWrapper.get();
   526 	}
   527 	else
   528 	{
   529 		videoControlWrapper = VideoControlWrapperPtr(new VideoControlWrapper(VcmSIPCCBinding::getVideoControl()));
   530 		return videoControlWrapper.get();
   531 	}
   532 }
   535 void CC_SIPCCService::applyLoggingMask (int newMask)
   536 {
   537     if (newMask >> _maxBitValueMaskedLoggingEntries > 0)
   538     {
   539     	CSFLogWarn( logTag, "Value of 0x%x specified for mask includes at least one bit value that exceeds the maximum supported bitfield value. "
   540                     "Ignoring unsupported bits.", newMask);
   541     }
   543     CSFLogDebug( logTag, "Applying a sipcc log mask = %d", newMask);
   545     loggingMask = newMask & (HAS_21_BITS);
   547     for (int i=0; i<_maxBitValueMaskedLoggingEntries; i++)
   548     {
   549         *(_maskedLoggingEntriesArray[i]) = (loggingMask >> i) & 0x1;
   550     }
   551 }
   553 // !!! Note that accessing *Ptr instances from multiple threads can
   554 // lead to deadlocks, crashes, and spinning threads. Calls to this
   555 // method are not safe except from ccapp_thread.
   556 void CC_SIPCCService::endAllActiveCalls()
   557 {
   558 	CC_DevicePtr device = getActiveDevice();
   559 	if(device != nullptr)
   560 	{
   561 		CC_DeviceInfoPtr deviceInfo = device->getDeviceInfo();
   562 		vector<CC_CallPtr> calls = deviceInfo->getCalls();
   563 		CSFLogInfo( logTag, "endAllActiveCalls(): %lu calls to be ended.", calls.size());
   564 		for(vector<CC_CallPtr>::iterator it = calls.begin(); it != calls.end(); it++)
   565 		{
   566 			// For each active call, if it can be ended, do so.
   567 			CC_CallPtr call = *it;
   568 			CC_CallInfoPtr callInfo = call->getCallInfo();
   569 			if(callInfo->hasCapability(CC_CallCapabilityEnum::canEndCall))
   570 			{
   571 				CSFLogDebug( logTag, "endAllActiveCalls(): ending call %s -> %s [%s]",
   572 					callInfo->getCallingPartyNumber().c_str(),
   573                     callInfo->getCalledPartyNumber().c_str(),
   574 					call_state_getname(callInfo->getCallState()));
   575 				call->endCall();
   576 			}
   577 			else if(callInfo->hasCapability(CC_CallCapabilityEnum::canResume) && callInfo->getCallState() != REMHOLD)
   578 			{
   579 				CSFLogDebug( logTag, "endAllActiveCalls(): resume then ending call %s -> %s, [%s]",
   580 					callInfo->getCallingPartyNumber().c_str(),
   581                     callInfo->getCalledPartyNumber().c_str(),
   582 					call_state_getname(callInfo->getCallState()));
   583 				call->muteAudio();
   584 				call->resume(callInfo->getVideoDirection());
   585 				call->endCall();
   586 			}
   587 		}
   589 		if(!calls.empty())
   590 		{
   591 #ifdef MOZILLA_INTERNAL_API
   592 			// If we had any calls, allow a short time for the SIP messaging to go out
   593 			PlatformThread::Sleep(500);
   594 #endif
   595 		}
   596     }
   597 }
   600 // C++ Event Handlers
   601 void CC_SIPCCService::onDeviceEvent(ccapi_device_event_e type, cc_device_handle_t handle, cc_deviceinfo_ref_t info)
   602 {
   603     if (_self == nullptr)
   604     {
   605         CSFLogError( logTag, "CC_SIPCCService::_self is NULL. Unable to notify observers of device event.");
   606         return;
   607     }
   609     mozilla::MutexAutoLock lock(_self->m_lock);
   611     CC_SIPCCDevicePtr devicePtr = CC_SIPCCDevice::wrap(handle);
   612     if (devicePtr == nullptr)
   613     {
   614         CSFLogError( logTag, "Unable to notify device observers for device handle (%u), as failed to create CC_DevicePtr", handle);
   615         return;
   616     }
   618     CC_SIPCCDeviceInfoPtr infoPtr = CC_SIPCCDeviceInfo::wrap(info);
   619     if (infoPtr == nullptr)
   620     {
   621         CSFLogError( logTag, "Unable to notify call observers for device handle (%u), as failed to create CC_DeviceInfoPtr", handle);
   622         return;
   623     }
   625     CSFLogInfo( logTag, "onDeviceEvent( %s, %s, [%s] )",
   626       device_event_getname(type),
   627       devicePtr->toString().c_str(),
   628       infoPtr->getDeviceName().c_str());
   629     _self->notifyDeviceEventObservers(type, devicePtr.get(), infoPtr.get());
   630 }
   632 void CC_SIPCCService::onFeatureEvent(ccapi_device_event_e type, cc_deviceinfo_ref_t /* device_info */, cc_featureinfo_ref_t feature_info)
   633 {
   635     if (_self == nullptr)
   636      {
   637          CSFLogError( logTag, "CC_SIPCCService::_self is NULL. Unable to notify observers of device event.");
   638          return;
   639      }
   641      mozilla::MutexAutoLock lock(_self->m_lock);
   643      cc_device_handle_t hDevice = CCAPI_Device_getDeviceID();
   644      CC_DevicePtr devicePtr = CC_SIPCCDevice::wrap(hDevice).get();
   645      if (devicePtr == nullptr)
   646      {
   647          CSFLogError( logTag, "Unable to notify device observers for device handle (%u), as failed to create CC_DevicePtr", hDevice);
   648          return;
   649      }
   651      CC_FeatureInfoPtr infoPtr = CC_SIPCCFeatureInfo::wrap(feature_info).get();
   652      if (infoPtr  == nullptr)
   653      {
   654          CSFLogError( logTag, "Unable to notify call observers for feature info handle (%p), as failed to create CC_FeatureInfoPtr", feature_info);
   655          return;
   656      }
   658      CSFLogInfo( logTag, "onFeatureEvent( %s, %s, [%s] )",
   659          device_event_getname(type),
   660          devicePtr->toString().c_str(),
   661          infoPtr->getDisplayName().c_str());
   662      _self->notifyFeatureEventObservers(type, devicePtr, infoPtr);
   663 }
   665 void CC_SIPCCService::onLineEvent(ccapi_line_event_e eventType, cc_lineid_t line, cc_lineinfo_ref_t info)
   666 {
   667     if (_self == nullptr)
   668     {
   669         CSFLogError( logTag, "CC_SIPCCService::_self is NULL. Unable to notify observers of line event.");
   670         return;
   671     }
   673     mozilla::MutexAutoLock lock(_self->m_lock);
   675     CC_LinePtr linePtr = CC_SIPCCLine::wrap(line).get();
   676     if (linePtr == nullptr)
   677     {
   678         CSFLogError( logTag, "Unable to notify line observers for line lineId (%u), as failed to create CC_LinePtr", line);
   679         return;
   680     }
   682     CC_LineInfoPtr infoPtr = CC_SIPCCLineInfo::wrap(info).get();
   683     if (infoPtr == nullptr)
   684     {
   685         CSFLogError( logTag, "Unable to notify line observers for line lineId (%u), as failed to create CC_LineInfoPtr", line);
   686         return;
   687     }
   689     CSFLogInfo( logTag, "onLineEvent(%s, %s, [%s|%s]",
   690         line_event_getname(eventType), linePtr->toString().c_str(),
   691     	infoPtr->getNumber().c_str(), (infoPtr->getRegState() ? "INS" : "OOS"));
   692     _self->notifyLineEventObservers(eventType, linePtr, infoPtr);
   693 }
   695 void CC_SIPCCService::onCallEvent(ccapi_call_event_e eventType, cc_call_handle_t handle, cc_callinfo_ref_t info)
   696 {
   697     if (_self == nullptr)
   698     {
   699         CSFLogError( logTag, "CC_SIPCCService::_self is NULL. Unable to notify observers of call event.");
   700         return;
   701     }
   703     mozilla::MutexAutoLock lock(_self->m_lock);
   705     CC_SIPCCCallPtr callPtr = CC_SIPCCCall::wrap(handle);
   706     if (callPtr == nullptr)
   707     {
   708         CSFLogError( logTag, "Unable to notify call observers for call handle (%u), as failed to create CC_CallPtr", handle);
   709         return;
   710     }
   712     CC_SIPCCCallInfoPtr infoPtr = CC_SIPCCCallInfo::wrap(info);
   713     if (infoPtr == nullptr)
   714     {
   715         CSFLogError( logTag, "Unable to notify call observers for call handle (%u), as failed to create CC_CallInfoPtr", handle);
   716         return;
   717     }
   719     infoPtr->setMediaData(callPtr->getMediaData());
   721 	set<CSF::CC_CallCapabilityEnum::CC_CallCapability> capSet = infoPtr->getCapabilitySet();
   722     CSFLogInfo( logTag, "onCallEvent(%s, %s, [%s|%s]",
   723         call_event_getname(eventType), callPtr->toString().c_str(),
   724     	call_state_getname(infoPtr->getCallState()), CC_CallCapabilityEnum::toString(capSet).c_str());
   725     _self->notifyCallEventObservers(eventType, callPtr.get(), infoPtr.get());
   727     // To prevent leaking CC_SIPCCCalls, we remove them from the wrapper
   728     // map when the call event information indicates an "on hook" event.
   729     if (infoPtr->getCallState() == ONHOOK) {
   730         CSFLogDebug( logTag, "Removing call info from wrapper map (handle=%u)",
   731                      handle);
   732         CC_SIPCCCall::release(handle);
   733     }
   735     // Once the call info is dispatched to the observers, we never need to
   736     // refer to it again. The next operation will contain its own unique info.
   737     CC_SIPCCCallInfo::release(info);
   738 }
   740 void CC_SIPCCService::addCCObserver ( CC_Observer * observer )
   741 {
   742 	mozilla::MutexAutoLock lock(m_lock);
   743     if (observer == nullptr)
   744     {
   745         CSFLogError( logTag, "NULL value for \"observer\" passed to addCCObserver().");
   746         return;
   747     }
   749     ccObservers.insert(observer);
   750 }
   752 void CC_SIPCCService::removeCCObserver ( CC_Observer * observer )
   753 {
   754 	mozilla::MutexAutoLock lock(m_lock);
   755     ccObservers.erase(observer);
   756 }
   758 //Notify Observers
   759 void CC_SIPCCService::notifyDeviceEventObservers (ccapi_device_event_e eventType, CC_DevicePtr devicePtr, CC_DeviceInfoPtr info)
   760 {
   761   // m_lock must be held by the function that called us
   762 	set<CC_Observer*>::const_iterator it = ccObservers.begin();
   763 	for ( ; it != ccObservers.end(); it++ )
   764     {
   765 	    (*it)->onDeviceEvent(eventType, devicePtr, info);
   766     }
   767 }
   769 void CC_SIPCCService::notifyFeatureEventObservers (ccapi_device_event_e eventType, CC_DevicePtr devicePtr, CC_FeatureInfoPtr info)
   770 {
   771   // m_lock must be held by the function that called us
   772 	set<CC_Observer*>::const_iterator it = ccObservers.begin();
   773 	for ( ; it != ccObservers.end(); it++ )
   774     {
   775 	    (*it)->onFeatureEvent(eventType, devicePtr, info);
   776     }
   777 }
   779 void CC_SIPCCService::notifyLineEventObservers (ccapi_line_event_e eventType, CC_LinePtr linePtr, CC_LineInfoPtr info)
   780 {
   781   // m_lock must be held by the function that called us
   782 	set<CC_Observer*>::const_iterator it = ccObservers.begin();
   783 	for ( ; it != ccObservers.end(); it++ )
   784     {
   785 	    (*it)->onLineEvent(eventType, linePtr, info);
   786     }
   787 }
   789 void CC_SIPCCService::notifyCallEventObservers (ccapi_call_event_e eventType, CC_CallPtr callPtr, CC_CallInfoPtr info)
   790 {
   791   // m_lock must be held by the function that called us
   792 	set<CC_Observer*>::const_iterator it = ccObservers.begin();
   793 	for ( ; it != ccObservers.end(); it++ )
   794     {
   795 	    (*it)->onCallEvent(eventType, callPtr, info);
   796     }
   797 }
   799 // This is called when the SIP stack has caused a new stream to be allocated. This function will
   800 // find the call associated with that stream so that the call can store the streamId.
   802 // !!! Note that accessing *Ptr instances from multiple threads can
   803 // lead to deadlocks, crashes, and spinning threads. Calls to this
   804 // method are not safe except from ccapp_thread.
   805 void CC_SIPCCService::registerStream(cc_call_handle_t call, int streamId, bool isVideo)
   806 {
   807     CSFLogDebug( logTag, "registerStream for call: %d strId=%d video=%s",
   808         call, streamId, isVideo ? "TRUE" : "FALSE");
   809 	// get the object corresponding to the handle
   810     CC_SIPCCCallPtr callPtr = CC_SIPCCCall::wrap(call);
   811     if (callPtr != nullptr)
   812     {
   813     	callPtr->addStream(streamId, isVideo);
   814     }
   815     else
   816     {
   817         CSFLogError( logTag, "registerStream(), No call found for allocated Stream: %d, %s",
   818             streamId, isVideo ? "TRUE" : "FALSE");
   819     }
   820 }
   822 // !!! Note that accessing *Ptr instances from multiple threads can
   823 // lead to deadlocks, crashes, and spinning threads. Calls to this
   824 // method are not safe except from ccapp_thread.
   825 void CC_SIPCCService::deregisterStream(cc_call_handle_t call, int streamId)
   826 {
   827 	// get the object corresponding to the handle
   828     CC_SIPCCCallPtr callPtr = CC_SIPCCCall::wrap(call);
   829     if (callPtr != nullptr)
   830     {
   831     	callPtr->removeStream(streamId);
   832     }
   833     else
   834     {
   835         CSFLogError( logTag, "deregisterStream(), No call found for deallocated Stream: %d", streamId);
   836     }
   837 }
   839 // !!! Note that accessing *Ptr instances from multiple threads can
   840 // lead to deadlocks, crashes, and spinning threads. Calls to this
   841 // method are not safe except from ccapp_thread.
   842 void CC_SIPCCService::dtmfBurst(int digit, int direction, int duration)
   843 {
   844 	// We haven't a clue what stream to use.  Search for a call which has an audio stream.
   845 	vector<CC_SIPCCCallPtr> calls;
   846 	{
   847 		// First build a list of all the calls.
   848 		cc_deviceinfo_ref_t deviceInfoRef = CCAPI_Device_getDeviceInfo(CCAPI_Device_getDeviceID());
   849 		cc_call_handle_t handles[MAX_SUPPORTED_NUM_CALLS] = {};
   850 		cc_uint16_t numHandles = csf_countof(handles);
   852 		CCAPI_DeviceInfo_getCalls(deviceInfoRef, handles, &numHandles);
   854 		for (int i=0; i<numHandles; i++)
   855 		{
   856 			CC_SIPCCCallPtr callPtr = CC_SIPCCCall::wrap(handles[i]);
   857 			calls.push_back(callPtr);
   858 		}
   859 		CCAPI_Device_releaseDeviceInfo(deviceInfoRef);
   860 	}
   862 	// Using the list of all calls, search for those containing an audio stream.
   863 	// Send a DTMF digit on the first one we find.
   865 	AudioTermination * pAudio = VcmSIPCCBinding::getAudioTermination();
   866 	bool bSent = false;
   867 	for(vector<CC_SIPCCCallPtr>::iterator it = calls.begin(); it != calls.end() && !bSent; it++)
   868     {
   869     	CC_SIPCCCallMediaDataPtr pMediaData = (*it)->getMediaData();
   871     	mozilla::MutexAutoLock lock(pMediaData->streamMapMutex);
   872 		for (StreamMapType::iterator entry =  pMediaData->streamMap.begin(); entry !=  pMediaData->streamMap.end(); entry++)
   873 	    {
   874 			if (entry->second.isVideo == false)
   875 			{
   876 				// first is the streamId
   877 				if (pAudio->sendDtmf(entry->first, digit))
   878 				{
   879 					// We have sent a digit, done.
   880 					bSent = true;
   881 					break;
   882 				}
   883 				else
   884 				{
   885 					CSFLogWarn( logTag, "dtmfBurst:sendDtmf returned fail");
   886 				}
   887 			}
   888 	    }
   889     }
   890 }
   892 // !!! Note that accessing *Ptr instances from multiple threads can
   893 // lead to deadlocks, crashes, and spinning threads. Calls to this
   894 // method are not safe except from ccapp_thread.
   895 void CC_SIPCCService::sendIFrame(cc_call_handle_t call_handle)
   896 {
   897 	CC_SIPCCCallPtr callPtr = CC_SIPCCCall::wrap(call_handle);
   898     CC_SIPCCCallMediaDataPtr pMediaData=callPtr->getMediaData();
   899     if (pMediaData != nullptr)
   900     {
   901         for (StreamMapType::iterator entry =  pMediaData->streamMap.begin(); entry !=  pMediaData->streamMap.end(); entry++)
   902         {
   903      		if (entry->second.isVideo == true)
   904             {
   905                 VcmSIPCCBinding::getVideoTermination()->sendIFrame( entry->first );
   906             }
   907         }
   908     }
   909 }
   911 bool CC_SIPCCService::isValidMediaPortRange(int mediaStartPort, int mediaEndPort)
   912 {
   913     if(mediaStartPort < 1024  ||
   914         mediaStartPort > 65535  ||
   915     	mediaEndPort < 1024 ||
   916     	mediaEndPort > 65535 ||
   917     	mediaEndPort - mediaStartPort < 3)
   918     {
   919     		return false;
   920     }
   921     else
   922     {
   923     	return true;
   924     }
   925 }
   927 bool CC_SIPCCService::isValidDSCPValue(int value)
   928 {
   929 	//value is 8-bit value, but the two least significant bits are unused,
   930 	//leaving an effective 6 bits of information.  Valid values are therefore
   931 	//all multiples of 4 that lie between 0 and 252 inclusive.
   932 	if(value >= 0 &&
   933 		value <= 252 &&
   934 		value % 4 == 0)
   935 	{
   936 		return true;
   937 	}
   938 	else
   939 	{
   940 		return false;
   941 	}
   942 }
   944 void CC_SIPCCService::onVideoModeChanged( bool enable )
   945 {
   946 }
   948 // !!! Note that accessing *Ptr instances from multiple threads can
   949 // lead to deadlocks, crashes, and spinning threads. Calls to this
   950 // method are not safe except from ccapp_thread.
   951 void CC_SIPCCService::onKeyFrameRequested( int stream )
   952 // This is called when the Video Provider indicates that it needs to send a request for new key frame to the sender
   953 {
   954     CSFLogDebug(logTag, "onKeyFrameRequested for stream ");
   955 	// We haven't a clue what stream to use.  Search for a call which has an audio stream.
   956 	vector<CC_SIPCCCallPtr> calls;
   957 	{
   958 		// First build a list of all the calls.
   959 		cc_deviceinfo_ref_t deviceInfoRef = CCAPI_Device_getDeviceInfo(CCAPI_Device_getDeviceID());
   960 		cc_call_handle_t handles[MAX_SUPPORTED_NUM_CALLS] = {};
   961 		cc_uint16_t numHandles = csf_countof(handles);
   963 		CCAPI_DeviceInfo_getCalls(deviceInfoRef, handles, &numHandles);
   965 		for (int i=0; i<numHandles; i++)
   966 		{
   967 			CC_SIPCCCallPtr callPtr = CC_SIPCCCall::wrap(handles[i]);
   968 			//CC_SIPCCCallPtr callPtr = wrapCall(handles[i]);
   969 			calls.push_back(callPtr);
   970 		}
   971 		CCAPI_Device_releaseDeviceInfo(deviceInfoRef);
   972 	}
   974 	// Using the list of all calls, search for those containing an video stream.
   975 	// Send the send info SIP message when we find the one with the correct stream id.
   977 	bool bSent = false;
   978 	for(vector<CC_SIPCCCallPtr>::iterator it = calls.begin(); it != calls.end() && !bSent; it++)
   979     {
   980     	CC_SIPCCCallMediaDataPtr pMediaData = (*it)->getMediaData();
   982     	mozilla::MutexAutoLock lock(pMediaData->streamMapMutex);
   983 		for (StreamMapType::iterator entry =  pMediaData->streamMap.begin(); entry !=  pMediaData->streamMap.end(); entry++)
   984 	    {
   985 			if ((entry->first==stream) && (entry->second.isVideo == true))
   986 			{
   987                 CSFLogDebug(logTag, "Send SIP message to originator for stream id %d", stream);
   988 				if ((*it)->sendInfo ( "","application/media_control+xml", "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n"
   989 						"<media_control>\n"
   990 						"\n"
   991 						"  <vc_primitive>\n"
   992 						"    <to_encoder>\n"
   993 						"      <picture_fast_update/>\n"
   994 						"    </to_encoder>\n"
   995 						"  </vc_primitive>\n"
   996 						"\n"
   997 						"</media_control>\n"))
   998 				{
   999 					CSFLogWarn(logTag, "sendinfo returned true");
  1000 					bSent = true;
  1001 					break;
  1003 				else
  1005 					CSFLogWarn(logTag, "sendinfo returned false");
  1012 void CC_SIPCCService::onMediaLost( int callId )
  1016 void CC_SIPCCService::onMediaRestored( int callId )
  1020 bool CC_SIPCCService::setLocalVoipPort(int port) {
  1021 	return CCAPI_Config_set_local_voip_port(port);
  1024 bool CC_SIPCCService::setRemoteVoipPort(int port) {
  1025 	return CCAPI_Config_set_remote_voip_port(port);
  1028 bool CC_SIPCCService::setP2PMode(bool mode)  {
  1029 	return CCAPI_Config_set_p2p_mode(mode);
  1032 bool CC_SIPCCService::setSDPMode(bool mode)  {
  1033 	return CCAPI_Config_set_sdp_mode(mode);
  1036 } // End of namespace CSF

mercurial