Thu, 15 Jan 2015 15:59:08 +0100
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;
1002 }
1003 else
1004 {
1005 CSFLogWarn(logTag, "sendinfo returned false");
1006 }
1007 }
1008 }
1009 }
1010 }
1012 void CC_SIPCCService::onMediaLost( int callId )
1013 {
1014 }
1016 void CC_SIPCCService::onMediaRestored( int callId )
1017 {
1018 }
1020 bool CC_SIPCCService::setLocalVoipPort(int port) {
1021 return CCAPI_Config_set_local_voip_port(port);
1022 }
1024 bool CC_SIPCCService::setRemoteVoipPort(int port) {
1025 return CCAPI_Config_set_remote_voip_port(port);
1026 }
1028 bool CC_SIPCCService::setP2PMode(bool mode) {
1029 return CCAPI_Config_set_p2p_mode(mode);
1030 }
1032 bool CC_SIPCCService::setSDPMode(bool mode) {
1033 return CCAPI_Config_set_sdp_mode(mode);
1034 }
1036 } // End of namespace CSF