13 min read

This article by Flavio E Goncalves and Bogdan-Andrei Iancu, the authors of the book Building Telephony Systems with OpenSIPS – Second Edition, will help you to understand who can use OpenSIPS. This is followed by a description of the OpenSIPS design. It is essential to fully understand OpenSIPS—from the outside and inside perspectives—before using it.

In this article, you will see the following:

  • The different usage scenarios for OpenSIPS or when to use it
  • The OpenSIPS internal design and structure

(For more resources related to this topic, see here.)

Who’s using OpenSIPS?

A wide range of Session Initiation Protocol (SIP) oriented service providers choose OpenSIPS to power their platform, mainly because of its throughput and capabilities and also because of its reliability as a stable and mature open source software project.

Voice over Internet Protocol (VoIP) service providers take advantage of the rich feature set of OpenSIPS to build attractive and competitive services for residential or enterprise customers. The flexibility of OpenSIPS (in terms of service creation) and the fast releasing cycle give them an advantage in creating cutting-edge services in the competitive VoIP markets.

The ability to pipe large amounts of traffic through OpenSIPS in a reliable and precise fashion allows providers for trunking services, Direct Inward Dialing (DID), or termination services to scale and become more efficient. The dynamic nature of these services and the interoperability concerns are key aspects that make OpenSIPS the perfect candidate for the job.

Currently, OpenSIPS has exceeded its original Class 4 status and is now able to offer Class 5 signaling features. So, hosted/virtual Private Branch Exchange (PBX) providers use OpenSIPS as a core component to emulate PBX-like services. OpenSIPS is flexible enough to integrate all the complex Class 5 features and even more in order to interface with external SIP engines (such as media servers).

The ability of OpenSIPS to frontend existing platforms for the load balancing and clustering (even geo distribution) core components opens the markets populated by existing players who offer PBX services or termination services. Such players can now take advantage of OpenSIPS too.

Besides calls, OpenSIPS provides you with present and instant messaging capabilities, which are essential to buildservices such as Rich Communication Services (RCS).

In the area of advanced SIP services, Local Number Portability (LNP) providers, Canonical Name (CNAME) providers, fraud detection providers are relying on the OpenSIPS skills to interface with various DB engines and handle huge amounts of data (typical for their services). OpenSIPS can offer both, an efficient SIP frontend and a powerful backend to connect to DBs and other external tools.

With the OpenSIPS evolution in the Class 5 area, new capabilities such as Back-2-Back User Agent and Call Queuing were exploited by call center providers (inbound and outbound termination). When compared with the existing solutions, OpenSIPS-based call centers were able to handle large amounts of calls and offer, in a geo-distributed fashion, an all-in-one platform: call queuing, DID management, Public Switched Telephone Network (PSTN) routing, SIP peering, and others.

Nevertheless, being an open software, OpenSIPS offers a perfect study and research platform. Universities and research centers are using OpenSIPS to familiarize students with the VoIP/SIP world to build projects or research cases. It is important to mention here that this relation with the universities and research institutes is in the benefit of both parties as the OpenSIPS project gets a lot of traction and expansions from these study/research projects.

The project manages a list of OpenSIPS users, a list that is continuously growing: http://www.opensips.org/About/WhoIsUsing

The OpenSIPS design

Architecturally speaking, OpenSIPS is formed of two logical components: the core and modules.

The core is the application itself and it provides the low-level functionality of OpenSIPS, the definition of various interfaces and some generic resources.

The modules are shared libraries loaded on demand at the startup time. Each module implements a well-defined functionality for a specific routing algorithm or authentication method. There are mainly two types of modules in OpenSIPS:

  • The modules providing functionalities and functions directly for the routing script
  • The modules implementing a core defined interface (such as a module implementing the SQL interface will become a backend to a certain SQL server)

The architecture of OpenSIPS is shown in the following figure:

The OpenSIPS core

The OpenSIPS core is a minimal application. By itself, it is only able to proxy the SIP requests and reply in a stateless mode with very basic scripting capabilities. In most of the cases, the core is used in conjunction with several modules.

The OpenSIPS core provides the following:

  • The SIP transport layer
  • The SIP factory—the message parser and builder
  • The routing script parser and interpreter
  • The memory and locking manager
  • The core script functions and variables
  • A SQL interface definition (implementation provided by modules and not by the core itself)
  • A NoSQL interface definition
  • An AAA interface definition
  • A management interface
  • An events interface
  • A statistics interface

The SIP transport layer implements various SIP transport protocols. Currently, OpenSIPS supports UDP, TCP, Transport Layer Security (TLS), and WebSocket. The transport protocols that are to be used depend on the SIP listeners defined in the routing script. Multiple transport protocols may be used at the same time.

The SIP factory layer provides you with functions to parse and build the SIP messages. OpenSIPS implements a lazy but efficient SIP parser—this means that the parsing is done on demand (OpenSIPS parses as far as requested) and selectively. (The header bodies are parsed only if requested; otherwise, only the header name is parsed.) The parsing process is transparent at the script level; each function (core or modules) does its own parsing internally. When it comes to changing the message, it is very important to know that the changes you make in the script are not applied in real time over the message but stored and applied only when all the message processing is done.

Due to this offline handling of changes, you are not able to see your own changes over the message. For example, if you add a new SIP header and test its presence, you will not find it, or if you remove a SIP header and look again for it, you will find it.

Therouting script parser and interpreter is loading and parsing (to the memory) the routing script at the startup time; after this, the file is no longer needed. The routing script cannot be reloaded at runtime—OpenSIPS must be restarted in order to read the routing script again. Aside from various global settings, the routing script contains the routing logic—this logic is defined via a C/Shell-like language, custom to OpenSIPS. Configuring the routing logic in OpenSIPS is more like doing simple programming. This approach (writing your own program to route the traffic) gives OpenSIPS a tremendous flexibility when it comes to routing.

The memory and locking manager is a global resource in OpenSIPS. For performance reasons, OpenSIPS implements its own internal manager for the memory allocation and locking operations. This part is not visible at the route scripting level, but it may be configured at compiling time. (OpenSIPS has several implementations for the memory and locking managers.)

The OpenSIPS core provides its own script functions and script variables to be used from the routing script. When compared with the functions and variables exported by the modules, the core set is quite limited in number and functionality. The online manual lists and documents all the functions and variables provided by the OpenSIPS core.

The SQL interface is defined by the core but not implemented. The definition is done here in the OpenSIPS core for standardization reasons. Modules can use SQL services via the SQL interface without being aware of the underlying SQL driver. Additionally, the other modules may implement the SQL interface, offering drivers to various SQL DBs as MySQL, Postgres, Oracle, Berkeley, unixODBC, and many others. (See all the modules starting with the db_ prefix.) Even if the SQL interface is for internal usage (between modules), it is partially exposed at the script level by the avpops module:

avp_db_query("select first_name, last_name from subscribers where username='$rU' and domain='$rd'", "$avp(fname);$avp(lname)");

Similar, the NoSQL interface is defined to standardize the operations with the NoSQL databases. The OpenSIPS modules currently implement drivers to Redis, CouchBase, Cassandra, MongoDB, Memcached, and other databases. (See all the modules starting with the cachedb_ prefix.) The NoSQL interface is directly exposed by the OpenSIPS core via a simple set of functions:

cache_store("redis:cluster1", "key1", "$var(my_val)", 1200);
cache_fetch("redis:cluster1", "key1", "$var(my_val)");
cache_remove("redis:cluster1", "key1");

The AAA Interface defines the interfacing to the AAA servers in a similar way. Currently, OpenSIPS supports the RADIUS driver for the AAA interface, the Diameter driver being under heavy rework at this time. The AAA interface is not exposed at all at the routing script level, being exclusively used internally between modules.

The Management Interface (MI) is an OpenSIPS interface that allows the external applications to trigger predefined commands in OpenSIPS. Such commands typically allow an external application/script to do the following:

  • Push data in OpenSIPS (such as setting a debug level, registering a contact, and so on)
  • Fetch data from OpenSIPS (see registered users, ongoing calls, get statistics, and so on)
  • Trigger an internal action in OpenSIPS (reloading the data, sending a message, and so on)

The MI commands are provided by the OpenSIPS core (See the online documentation at http://www.opensips.org/Documentation/Interface-CoreMI-2-1.) and also by the modules. (Check the online module documentation to see the commands provided by each module at http://www.opensips.org/Documentation/Modules-2-1.)

For the MI, OpenSIPS supports the following drivers: XMLRPC, FIFO file, Datagrams, Json RPC, and HTTP. (See all the modules starting with the mi_ prefix.)

A simple example of interacting with OpenSIPS via MI interfaces is using the opensipsctl utility—it uses the FIFO or XMLRPC protocols to push MI commands into OpenSIPS. The opensipsctl utility allows you to run an MI command explicitly via the fifo file:

opensipsctl fifo ps
opensipsctl fifo debug 4

The following is a simple program in Python to trigger in order to run an MI command in OpenSIPS via the XMLRPC protocol:

#!/usr/bin/python
import xmlrpclib
opensips = xmlrpclib.ServerProxy('http://127.0.0.1:8080/RPC2')
print opensips.ps();

The event interface is an OpenSIPS interface that provides you with different ways to notify the external applications about certain events triggered in OpenSIPS. In order to notify an external application about OpenSIPS’ internal events, the event interface provides the following functions:

  • Managing the exported events
  • Managing the subscriptions from different applications
  • Exporting generic functions to raise an event (regardless of the transport protocol used)
  • Communicating with different transport protocols to send the events

Events can be triggered by the core activities (See the online documentation at http://www.opensips.org/Documentation/Interface-CoreEvents-2-1.), module activities (See the Exported Events section in the module documentation at http://www.opensips.org/Documentation/Modules-2-1.), or explicitly from the routing script via the raise_event() function:

raise_event("E_SCRIPT_EVENT", $avp(attributes), $avp(values));

To deliver the events, the OpenSIPS modules implement the following drivers: datagram, RabbitMQ, and XMLRPC. (See all the modules starting with the event_ prefix.)

The statistics interface provides you with access to various internal statistics of OpenSIPS. It provides valuable information on what is going on in OpenSIPS. This can be used by the external applications for the monitoring purposes, load evaluation, and real-time integration with other services. The values of statistics variables are exclusively numerical. OpenSIPS provides two types of statistics variables:

  • Counter-like: Variables that keep counting things that happened in OpenSIPS, such as received requests, processed dialogs, failed DB queries, and so on
  • Computed values: Variables that are calculated in real-time, such as how much memory is used, the current load, active dialogs, active transactions, and so on

Refer to http://www.opensips.org/Documentation/Interface-Statistics-1-10 for more information.

In OpenSIPS, the statistics variables are grouped in different sets depending on their purposes. For example, the OpenSIPS core provides shmem, load, net, and other groups (http://www.opensips.org/Documentation/Interface-CoreStatistics-2-1), while each OpenSIPS module provides its own group. (Typically, the group has the same name as the module.)

The statistics can be easily queried via the MI with the get_statistics command:

# get various statistic variables, by list of names
> opensipsctl fifo get_statistics rcv_requests inuse_transactions
> core:rcv_requests = 453
> tm:inuse_transactions = 10

The OpenSIPS modules

Each OpenSIPS module is a dynamic library that may be loaded on demand at OpenSIPS startup, if instructed so in the routing script.

The modules are identified by their names and they typically export various resources to be used in/from the routing script:

  • A set of module parameters (optional)—they allow the module to be configured at startup
  • A set of script functions (optional)—functions to be used from the routing script
  • A set of asynchronous script functions (optional)—functions to be used from the routing script, but in an asynchronous way via a resume route
  • A set of variables (optional)—variables that can be used from the routing script
  • A set of statistics variables (optional)—statistics specific to the module that can be read via the MI
  • A set of MI commands (optional)—commands specific to the module to be triggered via the MI outside OpenSIPS
  • A set of events (optional)—events that can be triggered by the module (and delivered by the event modules to the external applications)

Based on what they implement, there are three types of modules in OpenSIPS:

  • Modules implementing the functionalities to be used from the routing script, that is, authentication methods, routing algorithms, registration handling, and so on.
  • Modules implementing one of the interfaces defined by the core in order to provide a driver for a certain communication protocol, that is, MySQL driver for the SQL interface, RADIUS driver for the AAA interface, and others.
  • Modules implementing their own particular API; such an API is to be used directly (bypassing the core) by the other modules. This allows modules to use other modules, independent of the core. Such modules are the b2b_entities, the dialog module, TM module, and so on.

We can conclude that even if most of the modules provide functionalities to the routing script, there are modules providing functionalities to other modules via the core interfaces or their own APIs.

These are some examples:

  • The db_mysql module implements the SQL interface defined by the core; the auth_db module using the SQL interface to perform the SQL operations can transparently use any module implementing the SQL interface
  • The b2b_entities module defines and implements its own API (to manage SIP UASs and UACs); the b2b_logic module uses the API from the b2b_entities module directly in order to build even more complex functionalities (that are used later from the routing script)

This leads to the concept of module dependencies and an OpenSIPS module may depend on the following:

  • An external library at linking time, that is, b2b_logicdepends on the xml2 library
  • The core interface at startup time—if a module uses the SQL interface, you need to load one or more modules implementing an SQL driver
  • Another module—one module depends directly and explicitly on another module (that is, b2b_logic depends on b2b_entities)

The documentation of each module (the README file) contains the information on the module’s dependencies, what functions or parameters are exposed, and what MI commands or events are available. See the online module documentations at http://www.opensips.org/Documentation/Modules-2-1.

Summary

In this article, you have seen who is using OpenSIPS. From the internal perspective, you learned the design/structure of OpenSIPS, such as the OpenSIPS core and OpenSIPS modules and what they can provide.

Resources for Article:


Further resources on this subject:


LEAVE A REPLY

Please enter your comment!
Please enter your name here