Lifecycle

Module lifecycle

Siprix module lifecycle shown on image below.

ModuleLifecycle diagram

Create

Lifecycle starts from invoking method Module_Create(), which allocates internal singletone structures. In this state library can only return its version and all other methods will return error ENotInitialized. Application can’t create one more instance, method always returns the same existing one. Application can’t destroy created instance, it automatically deallocated when application ends.

Initialize

Method Module_Initialize() initializes module. It creates log file, starts worker and background threads, does other required actions. In this state module is ready to process all available actions: add/remove accounts, making calls, etc.

When this method finished application can restore previous state (list of accounts, selected devices) by deserialize saved data and invoking Account_Add().

One more important operation after initialize it’s set event handler, which will receive events (callbacks) raised by library. Library provides two ways to do that:

UnInitialize

Method Module_UnInitialize() un-initializes module. It unregisters accounts, ends calls, stops threads, does other required actions.

Example of module lifecycle implementation in C++ application.
class SiprixCliApp : public Siprix::ISiprixEventHandler
{
...
   bool initializeSiprixModule()
   {
      sprxModule_ = Siprix::Module_Create();

      Siprix::IniData* ini = Siprix::Ini_GetDefault();
      Ini_SetLicense(ini, "...license-credentials...");
      Ini_SetLogLevelFile(ini, Siprix::LogLevel::Debug);
      Ini_SetLogLevelIde(ini, Siprix::LogLevel::NoLog);
      Ini_SetTlsVerifyServer(ini, true);

      const Siprix::ErrorCode err = Siprix::Module_Initialize(sprxModule_, ini);
      if (err != Siprix::ErrorCode::EOK)
      {
         std::cout << "Can't initialize siprix module.\n"
                   << " Err: " << err << " " << Siprix::GetErrorText(err) << std::endl;
         return false;
      }
      else
      {
         std::cout << "Siprix module successfully initialized.\n"
                   << "Version: "<<Siprix::Module_Version(sprxModule_) << std::endl;

         Callback_SetEventHandler(sprxModule_, this);
         return true;
      }
   }

   void SiprixCliApp::handleCmds()
   {
      while (true)
      {
         std::cout << "\n>>> Enter command: ";
         ...
         bool menuExit = false;
         menuExit = handleCmdMain(curMenu, cmd); break;
         ...
         break;
      }

      Module_UnInitialize(sprxModule_);
   }
   ...
protected:
   Siprix::ISiprixModule* sprxModule_ = nullptr;
};

Account lifecycle

Add account

Siprix account lifecycle starts from invoking method Account_Add(), which adds account to list of accounts, opens new port (if required), sends registration request (if required). Each account has its own settings and doesn’t depend on other accounts. Application can add as many accounts as required.

For each added account library assigns its own unique id starting from 1. Returned account id is using as argument of other methods. This id is valid only during current session. When application will add account after new library initialization it may got different id.

If application tries to add account with same AOR (user@domain) as alredy exist lib will return error ErrorCode::EDuplicateAccount and existing account id.

List of all available account attributes see in Account attributes functions.

Example of adding account in C++ application.
Siprix::AccData* acc = Siprix::Acc_GetDefault();
Siprix::Acc_SetSipServer(acc, "sip.someserver.com");
Siprix::Acc_SetSipExtension(acc, "113355");
Siprix::Acc_SetSipPassword(acc, "abcdefg");
Siprix::Acc_SetExpireTime(acc, 300);
Siprix::Acc_SetTranspProtocol(acc, Siprix::SipTransport::TCP);
...

Siprix::AccountId accId=0;
const Siprix::ErrorCode err = Siprix::Account_Add(sprxModule_, acc, &accId);
if (err != Siprix::ErrorCode::EOK)
{
   std::cout << "Can't add account.\n"
             << " Err: " << err << " " << Siprix::GetErrorText(err) << std::endl;
}
else
{
   std::cout << "Accound added. Assigned id: "<< accId << std::endl;
}

Edit (update) account

App can edit account’s attributes and apply changes by invoking Account_Update().

Library has the following limitations related editing:

  • It’s not allowed to modify sipExtension, sipServer, transport attributes. App can only add new account with required attributes and remove existing if it’s not required;

  • It’s not allowed to edit account when there are call(s) on it. In this case lib will return error ErrorCode::EAccountHasCalls.

Account’s registration state

Possible states of accounts registration shown on image below.

Account registration states diagram

When application set non zero expire time via method Acc_SetExpireTime() library will send REGISTER request just after adding account.

When application set zero expire time account will not able to receive incoming calls (its registration state set as RegState::REMOVED), but it’s valid and can be used for starting outgoing calls.

When received response from remote side or expired timeout library raises ISiprixEventHandler::OnAccountRegState() which application should use for updating actual account state and UI.

Call lifecycle

Siprix call lifecycle shown on image below.

Call states diagram

It has three entry points:

For each new call library assigns its own unique id starting from 200, when account’s ids started from 1. It allows easily distinct CallId and AccountId values during debugging.

Example of initiating outgoing call in C++ application.
Siprix::DestData* dest = Siprix::Dest_GetDefault();
Dest_SetExtension(dest, destExtension);
Dest_SetAccountId(dest, accId);
Dest_SetVideoCall(dest, withVideo);
...

Siprix::CallId callId = 0;
const Siprix::ErrorCode err = Siprix::Call_Invite(sprxModule_, dest, &callId);
if (err != Siprix::ErrorCode::EOK)
{
   std::cout << "Can't initiate call.\n"
             << " Err: " << err << " " << Siprix::GetErrorText(err) << std::endl;
}
else
{
   std::cout << "Call initiated. Assigned id: "<< callId << std::endl;
}

Subscriptions lifecycle

Siprix provides ability to create subscriptions via sending SUBSCRIBE request and receive updates with NOTIFY response. App can use it for tracking presence, BLF and other states of remote extensions. Subscription lifecycle shown on image below.

Subscrition states diagram

Lifecycle starts from invoking method Subscription_Create(), which adds new subscription and sends SUBSCRIBE request using credentials and transport of the specified account. Remote side may accept this subscription and notify its current state or reject it (depends on the SIP server settings and client implementation). See more ISiprixEventHandler::OnSubscriptionState().

App maintains list of subscriptions by creating them, displaying updated status when received NOTIFY (signalled by library’s callback) and removing if not required.