media/webrtc/signaling/src/callcontrol/CallControlManagerImpl.cpp

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rwxr-xr-x

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     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 <errno.h>
     6 #include <string>
     7 #include <prcvar.h>
     8 #include <prlock.h>
    10 #include "CSFLog.h"
    12 #include "CC_SIPCCDevice.h"
    13 #include "CC_SIPCCDeviceInfo.h"
    14 #include "CC_SIPCCFeatureInfo.h"
    15 #include "CC_SIPCCLine.h"
    16 #include "CC_SIPCCLineInfo.h"
    17 #include "CC_SIPCCCallInfo.h"
    18 #include "CallControlManagerImpl.h"
    19 #include "csf_common.h"
    21 extern "C"
    22 {
    23 #include "config_api.h"
    24 }
    27 static const char logTag[] = "CallControlManager";
    29 using namespace std;
    30 using namespace CSFUnified;
    32 namespace CSF
    33 {
    36 CallControlManagerImpl::CallControlManagerImpl()
    37 : m_lock("CallControlManagerImpl"),
    38   multiClusterMode(false),
    39   sipccLoggingMask(0xFFFFFFFF),
    40   authenticationStatus(AuthenticationStatusEnum::eNotAuthenticated),
    41   connectionState(ConnectionStatusEnum::eIdle)
    42 {
    43     CSFLogInfo(logTag, "CallControlManagerImpl()");
    44 }
    46 CallControlManagerImpl::~CallControlManagerImpl()
    47 {
    48     CSFLogInfo(logTag, "~CallControlManagerImpl()");
    49     destroy();
    50 }
    52 bool CallControlManagerImpl::destroy()
    53 {
    54     CSFLogInfo(logTag, "destroy()");
    55     bool retval = disconnect();
    56     if(retval == false)
    57 	{
    58 		return retval;
    59 	}
    60 	return retval;
    61 }
    63 // Observers
    64 void CallControlManagerImpl::addCCObserver ( CC_Observer * observer )
    65 {
    66 	mozilla::MutexAutoLock lock(m_lock);
    67     if (observer == nullptr)
    68     {
    69         CSFLogError(logTag, "NULL value for \"observer\" passed to addCCObserver().");
    70         return;
    71     }
    73     ccObservers.insert(observer);
    74 }
    76 void CallControlManagerImpl::removeCCObserver ( CC_Observer * observer )
    77 {
    78 	mozilla::MutexAutoLock lock(m_lock);
    79     ccObservers.erase(observer);
    80 }
    82 void CallControlManagerImpl::addECCObserver ( ECC_Observer * observer )
    83 {
    84 	mozilla::MutexAutoLock lock(m_lock);
    85     if (observer == nullptr)
    86     {
    87         CSFLogError(logTag, "NULL value for \"observer\" passed to addECCObserver().");
    88         return;
    89     }
    91     eccObservers.insert(observer);
    92 }
    94 void CallControlManagerImpl::removeECCObserver ( ECC_Observer * observer )
    95 {
    96 	mozilla::MutexAutoLock lock(m_lock);
    97     eccObservers.erase(observer);
    98 }
   100 void CallControlManagerImpl::setMultiClusterMode(bool allowMultipleClusters)
   101 {
   102     CSFLogInfo(logTag, "setMultiClusterMode(%s)",
   103       allowMultipleClusters ? "TRUE" : "FALSE");
   104     multiClusterMode = allowMultipleClusters;
   105 }
   107 void CallControlManagerImpl::setSIPCCLoggingMask(const cc_int32_t mask)
   108 {
   109     CSFLogInfo(logTag, "setSIPCCLoggingMask(%u)", mask);
   110     sipccLoggingMask = mask;
   111 }
   113 void CallControlManagerImpl::setAuthenticationString(const std::string &authString)
   114 {
   115     CSFLogInfo(logTag, "setAuthenticationString()");
   116     this->authString = authString;
   117 }
   119 void CallControlManagerImpl::setSecureCachePath(const std::string &secureCachePath)
   120 {
   121     CSFLogInfo(logTag, "setSecureCachePath(%s)", secureCachePath.c_str());
   122     this->secureCachePath = secureCachePath;
   123 }
   125 // Add local codecs
   126 void CallControlManagerImpl::setAudioCodecs(int codecMask)
   127 {
   128   CSFLogDebug(logTag, "setAudioCodecs %X", codecMask);
   130   VcmSIPCCBinding::setAudioCodecs(codecMask);
   131 }
   133 void CallControlManagerImpl::setVideoCodecs(int codecMask)
   134 {
   135   CSFLogDebug(logTag, "setVideoCodecs %X", codecMask);
   137   VcmSIPCCBinding::setVideoCodecs(codecMask);
   138 }
   140 AuthenticationStatusEnum::AuthenticationStatus CallControlManagerImpl::getAuthenticationStatus()
   141 {
   142     return authenticationStatus;
   143 }
   145 bool CallControlManagerImpl::registerUser( const std::string& deviceName, const std::string& user, const std::string& password, const std::string& domain )
   146 {
   147 	setConnectionState(ConnectionStatusEnum::eRegistering);
   149     CSFLogInfo(logTag, "registerUser(%s, %s )", user.c_str(), domain.c_str());
   150     if(phone != nullptr)
   151     {
   152     	setConnectionState(ConnectionStatusEnum::eReady);
   154         CSFLogError(logTag, "registerUser() failed - already connected!");
   155         return false;
   156     }
   158     softPhone = CC_SIPCCServicePtr(new CC_SIPCCService());
   159     phone = softPhone;
   160     phone->init(user, password, domain, deviceName);
   161     softPhone->setLoggingMask(sipccLoggingMask);
   162     phone->addCCObserver(this);
   164     phone->setP2PMode(false);
   166     bool bStarted = phone->startService();
   167     if (!bStarted) {
   168         setConnectionState(ConnectionStatusEnum::eFailed);
   169     } else {
   170         setConnectionState(ConnectionStatusEnum::eReady);
   171     }
   173     return bStarted;
   174 }
   176 bool CallControlManagerImpl::startP2PMode(const std::string& user)
   177 {
   178 	setConnectionState(ConnectionStatusEnum::eRegistering);
   180     CSFLogInfo(logTag, "startP2PMode(%s)", user.c_str());
   181     if(phone != nullptr)
   182     {
   183     	setConnectionState(ConnectionStatusEnum::eReady);
   185         CSFLogError(logTag, "startP2PMode() failed - already started in p2p mode!");
   186         return false;
   187     }
   189     softPhone = CC_SIPCCServicePtr(new CC_SIPCCService());
   190     phone = softPhone;
   191     phone->init(user, "", "127.0.0.1", "sipdevice");
   192     softPhone->setLoggingMask(sipccLoggingMask);
   193     phone->addCCObserver(this);
   195     phone->setP2PMode(true);
   197     bool bStarted = phone->startService();
   198     if (!bStarted) {
   199         setConnectionState(ConnectionStatusEnum::eFailed);
   200     } else {
   201         setConnectionState(ConnectionStatusEnum::eReady);
   202     }
   204     return bStarted;
   205 }
   207 bool CallControlManagerImpl::startSDPMode()
   208 {
   209     CSFLogInfo(logTag, "startSDPMode");
   210     if(phone != nullptr)
   211     {
   212         CSFLogError(logTag, "%s failed - already started in SDP mode!",__FUNCTION__);
   213         return false;
   214     }
   215     softPhone = CC_SIPCCServicePtr(new CC_SIPCCService());
   216     phone = softPhone;
   217     phone->init("JSEP", "", "127.0.0.1", "sipdevice");
   218     softPhone->setLoggingMask(sipccLoggingMask);
   219     phone->addCCObserver(this);
   220     phone->setSDPMode(true);
   222     return phone->startService();
   223 }
   225 bool CallControlManagerImpl::disconnect()
   226 {
   227     CSFLogInfo(logTag, "disconnect()");
   228     if(phone == nullptr)
   229         return true;
   231     connectionState = ConnectionStatusEnum::eIdle;
   232     phone->removeCCObserver(this);
   233     phone->stop();
   234     phone->destroy();
   235     phone = nullptr;
   236     softPhone = nullptr;
   238     return true;
   239 }
   241 std::string CallControlManagerImpl::getPreferredDeviceName()
   242 {
   243     return preferredDevice;
   244 }
   246 std::string CallControlManagerImpl::getPreferredLineDN()
   247 {
   248     return preferredLineDN;
   249 }
   251 ConnectionStatusEnum::ConnectionStatus CallControlManagerImpl::getConnectionStatus()
   252 {
   253     return connectionState;
   254 }
   256 std::string CallControlManagerImpl::getCurrentServer()
   257 {
   258     return "";
   259 }
   261 // Currently controlled device
   262 CC_DevicePtr CallControlManagerImpl::getActiveDevice()
   263 {
   264     if(phone != nullptr)
   265         return phone->getActiveDevice();
   267     return CC_DevicePtr();
   268 }
   270 // All known devices
   271 PhoneDetailsVtrPtr CallControlManagerImpl::getAvailablePhoneDetails()
   272 {
   273   PhoneDetailsVtrPtr result = PhoneDetailsVtrPtr(new PhoneDetailsVtr());
   274   for(PhoneDetailsMap::iterator it = phoneDetailsMap.begin(); it != phoneDetailsMap.end(); it++)
   275   {
   276     PhoneDetailsPtr details = it->second.get();
   277     result->push_back(details);
   278   }
   279   return result;
   280 }
   282 PhoneDetailsPtr CallControlManagerImpl::getAvailablePhoneDetails(const std::string& deviceName)
   283 {
   284     PhoneDetailsMap::iterator it = phoneDetailsMap.find(deviceName);
   285     if(it != phoneDetailsMap.end())
   286     {
   287         return it->second.get();
   288     }
   289     return PhoneDetailsPtr();
   290 }
   291 // Media setup
   292 VideoControlPtr CallControlManagerImpl::getVideoControl()
   293 {
   294     if(phone != nullptr)
   295         return phone->getVideoControl();
   297     return VideoControlPtr();
   298 }
   300 AudioControlPtr CallControlManagerImpl::getAudioControl()
   301 {
   302     if(phone != nullptr)
   303         return phone->getAudioControl();
   305     return AudioControlPtr();
   306 }
   308 bool CallControlManagerImpl::setProperty(ConfigPropertyKeysEnum::ConfigPropertyKeys key, std::string& value)
   309 {
   310   unsigned long strtoul_result;
   311   char *strtoul_end;
   313   CSFLogInfo(logTag, "setProperty( %s )", value.c_str());
   315   if (key == ConfigPropertyKeysEnum::eLocalVoipPort) {
   316     errno = 0;
   317     strtoul_result = strtoul(value.c_str(), &strtoul_end, 10);
   319     if (errno || value.c_str() == strtoul_end || strtoul_result > USHRT_MAX) {
   320       return false;
   321     }
   323     CCAPI_Config_set_local_voip_port((int) strtoul_result);
   324   } else if (key == ConfigPropertyKeysEnum::eRemoteVoipPort) {
   325     errno = 0;
   326     strtoul_result = strtoul(value.c_str(), &strtoul_end, 10);
   328     if (errno || value.c_str() == strtoul_end || strtoul_result > USHRT_MAX) {
   329       return false;
   330     }
   332     CCAPI_Config_set_remote_voip_port((int) strtoul_result);
   333   } else if (key == ConfigPropertyKeysEnum::eTransport) {
   334     if (value == "tcp")
   335       CCAPI_Config_set_transport_udp(false);
   336     else
   337       CCAPI_Config_set_transport_udp(true);
   338   }
   340   return true;
   341 }
   343 std::string CallControlManagerImpl::getProperty(ConfigPropertyKeysEnum::ConfigPropertyKeys key)
   344 {
   345   std::string retValue = "NONESET";
   346   char tmpString[11];
   348   CSFLogInfo(logTag, "getProperty()");
   350   if (key == ConfigPropertyKeysEnum::eLocalVoipPort) {
   351     csf_sprintf(tmpString, sizeof(tmpString), "%u", CCAPI_Config_get_local_voip_port());
   352     retValue = tmpString;
   353   } else if (key == ConfigPropertyKeysEnum::eRemoteVoipPort) {
   354     csf_sprintf(tmpString, sizeof(tmpString), "%u", CCAPI_Config_get_remote_voip_port());
   355     retValue = tmpString;
   356   } else if (key == ConfigPropertyKeysEnum::eVersion) {
   357     const char* version = CCAPI_Config_get_version();
   358     retValue = version;
   359   }
   361   return retValue;
   362 }
   363 /*
   364   There are a number of factors that determine PhoneAvailabilityType::PhoneAvailability. The supported states for this enum are:
   365   { eUnknown, eAvailable, eUnAvailable, eNotAllowed }. eUnknown is the default value, which is set when there is no information
   366   available that would otherwise determine the availability value. The factors that can influence PhoneAvailability are:
   367   phone mode, and for a given device (described by DeviceInfo) the model, and the name of the device. For phone control mode, the
   368   device registration and whether CUCM says the device is CTI controllable (or not) is a factor.
   370   For Phone Control mode the state machine is:
   372      is blacklisted model name? -> Yes -> NOT_ALLOWED
   373         (see Note1 below)
   374               ||
   375               \/
   376               No
   377               ||
   378               \/
   379        is CTI Controllable?
   380      (determined from CUCM) -> No -> NOT_ALLOWED
   381               ||
   382               \/
   383               Yes
   384               ||
   385               \/
   386   Can we tell if it's registered? -> No -> ?????? TODO: Seems to depends on other factors (look at suggestedAvailability parameter
   387               ||                                        in DeviceSubProviderImpl.addOrUpdateDevice() in CSF1G Java code.
   388               \/
   389               Yes
   390               ||
   391               \/
   392          is Registered?
   393      (determined from CUCM) -> No -> NOT_AVAILABLE
   394               ||
   395               \/
   396               Yes
   397               ||
   398               \/
   399            AVAILABLE
   401   ========
   403   For Softphone mode the state machine is:
   405         is device excluded?
   406    (based on "ExcludedDevices"   -> Yes -> NOT_ALLOWED
   407          config settings
   408         (see Note2 below))
   409               ||
   410               \/
   411               No
   412               ||
   413               \/
   414           isSoftphone?
   418      Note1: model name has to match completely, ie it's not a sub-string match, but we are ignoring case. So, if the blacklist
   419             contains a string "Cisco Unified Personal Communicator" then the model has to match this completely (but can be a
   420             different case) to be a match. In CSF1G the blacklist is hard-wired to:
   421                 { "Cisco Unified Personal Communicator",
   422                   "Cisco Unified Client Services Framework",
   423                   "Client Services Framework",
   424                   "Client Services Core" }
   426      Note2: The "ExcludedDevices" is a comma-separated list of device name prefixes (not model name). Unlike the above, this is
   427             a sub-string match, but only a "starts with" sub-string match, not anywhere in the string. If the device name
   428             is a complete match then this is also excluded, ie doesn't have to be a sub-string. For example, if the
   429             ExcludeDevices list contains { "ECP", "UPC" } then assuming we're in softphone mode, then any device whose
   430             name starts with the strings ECP or UPC, or whose complete name is either of these will be deemed to be excluded
   431             and will be marked as NOT_ALLOWED straightaway. In Phone Control mode the "ExcludedDevices" list i not taken into
   432             account at all in the determination of availability.
   434      Note3: isSoftphone() function
   436   The config service provides a list of "blacklisted" device name prefixes, that is, if the name of the device starts with a
   437   sub-string that matches an entry in the blacklist, then it is straightaway removed from the list? marked as NOT_ALLOWED.
   438  */
   440 // CC_Observers
   441 void CallControlManagerImpl::onDeviceEvent(ccapi_device_event_e deviceEvent, CC_DevicePtr devicePtr, CC_DeviceInfoPtr info)
   442 {
   443     notifyDeviceEventObservers(deviceEvent, devicePtr, info);
   444 }
   445 void CallControlManagerImpl::onFeatureEvent(ccapi_device_event_e deviceEvent, CC_DevicePtr devicePtr, CC_FeatureInfoPtr info)
   446 {
   447     notifyFeatureEventObservers(deviceEvent, devicePtr, info);
   448 }
   449 void CallControlManagerImpl::onLineEvent(ccapi_line_event_e lineEvent,     CC_LinePtr linePtr, CC_LineInfoPtr info)
   450 {
   451     notifyLineEventObservers(lineEvent, linePtr, info);
   452 }
   453 void CallControlManagerImpl::onCallEvent(ccapi_call_event_e callEvent,     CC_CallPtr callPtr, CC_CallInfoPtr info)
   454 {
   455     notifyCallEventObservers(callEvent, callPtr, info);
   456 }
   459 void CallControlManagerImpl::notifyDeviceEventObservers (ccapi_device_event_e deviceEvent, CC_DevicePtr devicePtr, CC_DeviceInfoPtr info)
   460 {
   461 	mozilla::MutexAutoLock lock(m_lock);
   462     set<CC_Observer*>::const_iterator it = ccObservers.begin();
   463     for ( ; it != ccObservers.end(); it++ )
   464     {
   465         (*it)->onDeviceEvent(deviceEvent, devicePtr, info);
   466     }
   467 }
   469 void CallControlManagerImpl::notifyFeatureEventObservers (ccapi_device_event_e deviceEvent, CC_DevicePtr devicePtr, CC_FeatureInfoPtr info)
   470 {
   471 	mozilla::MutexAutoLock lock(m_lock);
   472     set<CC_Observer*>::const_iterator it = ccObservers.begin();
   473     for ( ; it != ccObservers.end(); it++ )
   474     {
   475         (*it)->onFeatureEvent(deviceEvent, devicePtr, info);
   476     }
   477 }
   479 void CallControlManagerImpl::notifyLineEventObservers (ccapi_line_event_e lineEvent, CC_LinePtr linePtr, CC_LineInfoPtr info)
   480 {
   481 	mozilla::MutexAutoLock lock(m_lock);
   482     set<CC_Observer*>::const_iterator it = ccObservers.begin();
   483     for ( ; it != ccObservers.end(); it++ )
   484     {
   485         (*it)->onLineEvent(lineEvent, linePtr, info);
   486     }
   487 }
   489 void CallControlManagerImpl::notifyCallEventObservers (ccapi_call_event_e callEvent, CC_CallPtr callPtr, CC_CallInfoPtr info)
   490 {
   491 	mozilla::MutexAutoLock lock(m_lock);
   492     set<CC_Observer*>::const_iterator it = ccObservers.begin();
   493     for ( ; it != ccObservers.end(); it++ )
   494     {
   495         (*it)->onCallEvent(callEvent, callPtr, info);
   496     }
   497 }
   499 void CallControlManagerImpl::notifyAvailablePhoneEvent (AvailablePhoneEventType::AvailablePhoneEvent event,
   500         const PhoneDetailsPtr availablePhoneDetails)
   501 {
   502 	mozilla::MutexAutoLock lock(m_lock);
   503     set<ECC_Observer*>::const_iterator it = eccObservers.begin();
   504     for ( ; it != eccObservers.end(); it++ )
   505     {
   506         (*it)->onAvailablePhoneEvent(event, availablePhoneDetails);
   507     }
   508 }
   510 void CallControlManagerImpl::notifyAuthenticationStatusChange (AuthenticationStatusEnum::AuthenticationStatus status)
   511 {
   512 	mozilla::MutexAutoLock lock(m_lock);
   513     set<ECC_Observer*>::const_iterator it = eccObservers.begin();
   514     for ( ; it != eccObservers.end(); it++ )
   515     {
   516         (*it)->onAuthenticationStatusChange(status);
   517     }
   518 }
   520 void CallControlManagerImpl::notifyConnectionStatusChange(ConnectionStatusEnum::ConnectionStatus status)
   521 {
   522 	mozilla::MutexAutoLock lock(m_lock);
   523     set<ECC_Observer*>::const_iterator it = eccObservers.begin();
   524     for ( ; it != eccObservers.end(); it++ )
   525     {
   526         (*it)->onConnectionStatusChange(status);
   527     }
   528 }
   530 void CallControlManagerImpl::setConnectionState(ConnectionStatusEnum::ConnectionStatus status)
   531 {
   532 	connectionState = status;
   533 	notifyConnectionStatusChange(status);
   534 }
   535 }

mercurial