Hosted IP-PBX and its SBC

SBC ( Session Borde Controllers ) are basically gateways that provide interconnectivity between the hosted IP-PBX of the enterprise to the outside world endpoints such as telco service provider, PSTN/ TDM , SIP trunking providers or even third party OTT provider apps like skype for business etc.

If you have a hosted IPPBX or PBX in your data-centre or on premise and you need controlled but heavy outflowing traffic, it is a good idea to integrate a resilient and efficient SBC to provide seamless interconnectivity.

Hosted PBX

For an enterprises such as an Trading floor or warehouse with multiple phone types , softphones , hardphones , turrets etc distributed across various geographies and zones a device agnostic architectural setup is prime . Listing the essentials for setting up such a system. Note supplementary services are data-services , logging , licensing etc are important but kept out of scope to keep focus on functional aspects .

An enterprise application usually is structured in tiers or layers

  • Client tier – the networks clients communication to the central java programs . Runs on client machines
  • web tier – state full communication between client and business tier . Runs in server machine.
  • business tier- handles the logic of the application. The business tier uses the Enterprise Java Bean (EJB) container, which manages the execution of the beans
  • data tier – encompasses DB drivers . Runs on separate machines for database storage

Event services for Line status notifications

providers lines status notification across enterprise for inter zone and softphone to hardphone .

Routing services

routing calls within enterprise and hardphone sites read more about resource zones later in the article

Call Control Manager (CCM)

consolidated set of all service and component that make up the VOIP platform besides media handlers . It includes SIP adapters , bridge managers , call processing frameworks , API frameworks , healthchecks etc .

Call processing framework ( CPF)

signalling and call routing logic , mostly in SIP and trunks . Manages identities such as Call Line information , Called Party Information , line status etc in shared memory.

Multiple shared Lines and their statuses

Incases where there is a need to process multiple calls from a single User agent device such as a softphone or hardphone ( common scenario for a turret phone) , the design involves assigning it multiple sip uris and each sip uri will establish a line.

When caller calls callee , the line is said to be BUSY , otherwise said to be IDLE. Transition of a shared sip line from IDLE to BUSY is transmitted to others via SIP PUBLISH as other UAs holding the same sip

Similarly any other event like transfer is propagated to other via SIP UPDATE

Clustering Call control managers (CCM)

A Call Communication manager (CCM) from various zones should be able to cowork on call and session management and advanced features such as routing from home guest zone to home zone , call transfer , refer , barge etc. Designing a clustered setup will also provide elasticity , fail-over and high availability. Can use clustered , HA compliant framework such as Oracle Communication Application Server , suited for enterprise level deployments.

Call Replication and distributed memory management

A node will store two types of data: active sessions and passive sessions. The active sessions are used by the node and stored in cache. The passive sessions are the replicas from the other nodes’ active sessions. The passives sessions are stored on a persistent storage.

Controlling Line Calls using AOR and Resource Zones

When dealing with many SIP endpoints , now referred to as resource, it is best to assign the resources to their respective zones. Thus a resource’s status updates will be only updated by its active resource zone while can be read by any resource zone.

Incoming request Zone vs Active Resource Zone

For an Incoming request such a INVITE , check whether the zone sending the request is its active resource zone or not .If the Active Resource Zone is the same zone on which the INVITE came in, then the call is handled by that zone. If the Active Resource Zone is a different zone, then the call needs to be forwarded to the Active Resource Zone.

Bridges for Local Media connections

Although call signalling is handled by a resources active resource zone only, we can still create media bridges in local zone of the resource .

Local MM bridges are used to auto answer an incoming sip line call and create trunk , especially from hardphones which do not support provisional responses.

Interzone proxy Handler

proxies call control messages between active and non active resource zones. Primarily mapping the sip messages with all custom headers inbetween the communication device interfaces.

Dial Trunk using multiple dedicated sip lines and connect via Media Bridge

To save up on call routing /connection time and to support te ability to add as many users on call at runtime , a dedicated media bridge is established for every call.

  • A sip line activated is auto-answered by MM , creates a trunk and waits for other endpoint to join the bridge. The flow is as follows :
  • As INVITE arrives for an IDLE sip line , it is connected to a trunk and auto answered by a local MM bridge .
  • Since the call is already answered , when caller dials number for callee , collect the DTMF digits over RTP using RFC 2833 DTMF events.
  • Run inter-digit timer for digit collection and detect end of dialing on timeout.
  • The dialed trunk connection is made and call is added to media bridge
  • When provisional responses are received on the trunk connection, generate in-band call progress tones (ringing, proceeding etc) via the MM
  • When the line answers, the progress tones have to be stopped and the called party gets bridged to the calling party via the media bridge.

Call Diversion involves forwarding calls from zone to another zone. joinjed parties get call UPDATE status and forward response .

Call barge is the processing of joining an ongoing call . The barge event is usually propagated to joined parities via SIP INFO. Private lines do not allow barge in and are exclusively reserved for only few users.

Interconnectivity provided by an SBC ( Session Border Controller)

Hold-Resume and Music on Hold in multi-line evironment

While a regular p2p call involves simple reinvite based hold and resume with varrying SDP, the scenario is slightly more detailed for hold resume on bridged trunk connection , as explained below.

As the calls made are on bridge , a hold signal involves a RE-INIVITE with held-SDP to media manager (MM). If hold status on trunk is 200 OK the hold status will be sent to other call interfaces connected on the trunk. Else if hold is denied ,403 is sent back to hold-initiates.

Music on hold is an one way RTP mostly from media server.

For a bridged scenarios , separate Music on hold bridges are kept on Media Managers. When an UA has to hold , it is removed from original bridge and place on music on hold bridge . To be unhold/ resume it is placed back into the orignal bridge from music on hold bridge .

Conference

user initiates conference, the conference feature can execute on the zone where the user was logged on, irrespective of zones where the other conference attendees join from . The Call processing framework of originators zone completes the SDP exchange to establish two-way speech path among all the parties.

Incases there are multiple connections from a zone , a local MM conference bridge can be created for them which would connect back to originators MM conf bridge . this two part conf bridge will be transparent to the sip line sand users .

For provisioning inputs and settings setup a Diagnostics , Administration and Configuration platform which can process APIs for data services , licences , alarms or do remote device control such as using SNMP

Session Border Controllers (SBC)

At network level SBC operations include

  • bridging multiple interfaces in different networks even between the IPv4 and IPv6 networks
  • auto NAT discovery and STUN
  • protocol conversion such as TLS to UDP etc
  • Flood detection and IP filtering

For SIP specific functionalities , SBC does

  • SIP validation involving checks on syntax and message contents also consistency checks are performed.
  • stateful and call aware. tracing, monitoring and checking for validitya and health of all the SIP messages
  • Topology hiding
  • Traffic filtering
  • Codec filtering , reordering , media pinning, transcoding, or call recording
  • Data replication brings High Availability (HA) with hot backups or even Active-Active solutions.

Traffic sharing and routing roles of SBC can include

  • IP-based and Digest-based authentication
  • limiting traffic by number of concurrent calls or calling rate.
  • Dialplan and/or Custom routing
  • Dispatching/Load-balancing to a backend cluster of servers

SBC’s can be physical hardware boxes or software based applications, as the name suggests their purpose is to control the session at border between the enterprise and external service provider.

SIP to PSTN – SIP is an IP protocol whereas PSTN is a TDM one , achieving interoperability is also the KRA of an SBC

SIP trunking – SBC provide a secure sip connectivity to connect calls to sip trunks which provide bulk calls functionality at a flat pricing.

support for various fixed or mobile endpoints – SBC ensure they are RFC compliant and can extend SIP to any kind of telecom endpoint like PSTN , GSM, fax , Skype , sipphone , IP phones etc.

NAT / Network address translator – To meet the packet routing challenges across a firewall or even during private -public mapping. A combo of DHCP servers and NAT provider comes very handy to reroute or perform hole punching such that signalling and media packets are not dropped and meet the required endpoint. More about NAT here – NAT traversal using STUN and TURN.

Load balancing – Reverse proxies and Load balancers is a much adopted industry practise to mask the inner IPs of the VoIP platform and also route traffic appropriately between control and media server .

Security , QoS and Regulatory compliance – since SBCs are required to typically support a large array of clients they adhere to regulatory and industry accepted standards ,which also involves security features like AAA, TLS/SSL and other means for quality of assurance like logging and fault detection, preventing DDoS etc . In many cases SBC can also encrypt / decrypt RTP streams for probing , tapping or lawful inspection .

Terminating at carriers , PSTN and IP gateways

Additional SBC features

Inaddition to above it is good to have if an SBC provides extra features like forking , emergency number dialing ( 911 ) or active directory integration . Real Time Analysis and monitoring of call and metrics are also expected from a SBC since they reside on edge of the network and are more vulnerable to threats . For example Dialogic Mediant SBC’s and gateways , Audio Codes SBCs

With the shift from on premise PBXs to cloud based VM or microservice architecture , SBC vendors adopt a lager umbrella of services also including automation scripts for checks , reporting tools / consoles , developer friendly APIs to manage sessions via SBC and even WebRTC gateways to connect browser endpoints .

Usage Scenarios

Any VOIP dependant system which deals with bulksome voice / video traffic from external endpoints is a usages scenarios. Listing few

  • Contact Call centres
  • Remote work / offsite monitoring
  • CRM solution for sales/marketing
  • Connecting webrtc click to dial from webpage to enterprise representatives
  • connecting enterprise UCC clients to PSTN endpoints

There are many more.

Kamailio DNS and NAT

DNS sub-system in Kamailio

To resolve hostname into ips it can do either of below

  • use libresolv and a combination of the locally configured DNS server /etc/hosts and the local Network Information Service (NIS/YP a.s.o)
  • or cache the query results and first look into internal cache

DNS failover – if destination resolves to multiple addresses tm can try all of them until it finds one to which it can successfully send the packet or it exhausts all of them , with internal DNS cache. Also used when the destination host doesn’t send any reply to a forwarded invite within the SIP timeout interval (tm fr_timer parameter).

DNS load balancing – SRV based load balancing with weight value in the DNS SRV record.

Drawbacks

  1. Only the locally configured DNS server (usually in /etc/resolv.conf) is
    used for the requests (/etc/hosts and the local Network Information Service are ignored).
    Workaround: disable the DNS cache (use_dns_cache=off or compile without -DUSE_DNS_CACHE).
  2. The DNS cache uses extra memory
    Workaround: disable the DNS cache.
  3. The DNS failover introduces a very small performance penalty
    Workaround: disable the DNS failover (use_dns_failover=off).
  4. The DNS failover increases the memory usage (the internal structures
    used to represent the transaction are bigger when the DNS failover support is compiled).
    Workaround: compile without DNS failover support (DUSE_DNS_FAILOVER).Turning it off from the config file is not enough in this case (the extra
    memory will still be used).

NAT ( Network Address Translation)

Network address translation replaces the IP address within packets with a different IP address which internet endpoints can relate with
Enables multiple hosts in a private subnet with their pwn private address ( 10.x.x.x or 192.x.x.x etc ) to share single public IP address interface, to access the Internet.

NAT ( Network Address Translation)

NAT is bidirectional- If the private ip:port got translated to public ip:port on the inside interface while entering outside internet, on arriving from outside interface it will get translated from public ip:port to private ip:port

For a SBC ( Session border controller ) or where the kamailio server is directly customer facing , where you dont have a private line or VPN to clients, then it is often encountered with NATed endpoints. Read more about NAT traversal using STUN and TURN here

Why is Nat important in SIP?

These characteristics of SIP design and operation flows demonstrate why NAT solutions are so important ,

  • RFC 3261 for SIP presumed end-to-end reachability and does not specify much around ANT issues .
  • No NLRI (Network Layer Reachability Information) translation layer exists, such as DNS or ARP
  • SIP is designed to used RTP which uses dynamically allocated ports to stream media.
    It is comparable to FTP which creates ephemeral connections on unpredictable dynamic ports to send multiplexed data and “metadata”, instead of protocol like HTTP where all data is sent on same connection.
  • UDP (default transport for SIP) is connection less and session tracking requires these be mapped onto a statelful flow, rigorous keepalives and other such techniques like using TCP instead have their own tradeoffs
  • since sip packets put network and transport information right on sip header they are limited by the rateability and awareness of their network interface thereby prevent other endpoint from reaching its ip or port

Types of NAT solutions

Client-side NAT traversal – clients are responsible for identifying their WAN NLRI and adding ip and port to navigate them in outside world

Server-side NAT traversal – SIP server should discover the client’s WAN addressing while clients continue to work transparently behind NAT. Requires that DIP server look at the source and destination ip and port of actual packets instead of relying on the encapsulated sip headers and SDP body.

ALG (Application Layer Gateways) – mostly applied at router itself. wodk by susbtitung public IP/port information inplace of provate and vice versa for return packets . Limitataions – they dont provide a fullproof fix example they may fix Via but not the Contact address or SDP body or RTP ports

NAT behaviours

Cone NAT

Local client performs an outbound connection to a remote UA and a dynamic rule is created for the destination IP tuple, allowing the remote machine to connect back. Further subdivied into:
– Full Cone NAT
– Restricted Cone NAT
– Port-Restricted Cone NAT

Symmetric NAT

Local client allows inbound connections from a specific source IP address and port, also NAT assigns a new random source port for each destination IP tuple

NAT behaviours

Cone NAT

Local client performs an outbound connection to a remote UA and a dynamic rule is created for the destination IP tuple, allowing the remote machine to connect back. Further subdivied into:
– Full Cone NAT
– Restricted Cone NAT – all requests from the same internal IP address and port are mapped to the same external IP address and port.
– Port-Restricted Cone NAT

Symmetric NAT

Local client allows inbound connections from a specific source IP address and port, also NAT assigns a new random source port for each destination IP tuple

RTP NAT

NAT not only applies to sip signalling packets but also to RTP. Even SIP packets are abel to transverse accross private -public network interfaces to the right place across a NAT’d connection, that doesn’t solve two-way media.
RTP performs RTP latching where client listens for at least one RTP frame arriving at the destination port it advertised, and harvests the source IP and port from that packet and uses that for the return RTP path. RTP latching works out of the box for puclin RTP endpoints but not for ones behind NAT.

It is thus recommended to use an intermediate RTP relay such as RTPengine on kamailio. It is controlled via a UDP control socket by kamailio as an external process. More on installation and descrition of RTP engine on kamailio is covered here. When RTPengine control module receives RTP offer /answer from akmailio , it opens a pair of RTP/RTCP ports to receive traffic and substitues in SDP. Doing so for both ends makes RTP engine come in media stream packets of both directions

Fixing NAT

when the client is behind NAT, following needs to be taken careof to provide smooth operation

  1. Ensuring Tranactional replies are sent to correct source address ( maybe using ;rport param and forcerport() method ) instead of just relying on via header transport protocol and port.
    example:
if (client_nat_test("3")){
    //CALL RE-INVITE/UPDATE Nat DETECTED $ci\n");
    force_rport();
    fix_contact();
    ...
}

also Change Media ip address to public IP

if(nat_uac_test("8") && search("Content-type: application/sdp")) {
        // RE-INVITE/UPDATE CALL fix SDP- NAT
        fix_nated_sdp("2");
}
  1. Any far-end NAT traversal solution ( TURN server) if employed should stay i path of entire Dialog not just for initial INVITE transaction which many times results in ACK being dropped. This can be achived by adding Record-Route header of rr module to the initial INVITE request itself
  2. set the advertised address of the public-facing inetrface to the Public NAT IP using “listen” parameter
  3. Ensure contact URI is NAT processed by using NATHelper modules which rewrites the domain portion of the Contact URI to contain the source IP and port of the request or reply. add_contact_alias([ip_addr, port, proto]) in NAThelper module which adds “;alias=ip~port~transport” parameter to the contact URI containing either received ip, port, and transport protocol or those given as parameters , so
    Contact:
    is turned into:
    Contact:
  4. implement RTP proxy which performs NAT for streams such as rtpengine module

NAT Traversal Module

Provides far-end NAT traversal to kamailio’s SIP signalling .
Its role is

  • detect user agents behind NAT
  • manipulate SIP headers so that user agents can continue working behind NAT transparently
  • keepalives to UA behind NAT to preserve their visibility in network

pros

  • even detect UAs behind multiple cascaded NAT boxes, complex distributed env with multiple proxies
  • handle env where incoming and outgoing paths are diff for SIP messages
  • handle cases when routing path may even change between consecutive dialogs
  • can work for other than registered UA’s also

cons

  • built for IPv4 NAT handling not adapted to support IPv6 session keepalives.

Why use keepalive when Registrations are already there for NATing ?

  1. NAT binding works for registered users who want incoming calls. However for cases like outgoing calls or for presence subscription notifications, failings registration implies inability to receive further in-dialog messages after the NAT binding expires. This artificial binding for registrations makes system unreliable and volatile as it doesnot guarantee the delivery of in-dialog messages for outgoing calls without registration renewal. Therefore keepalive are adopted which also works for unregistered users.
  2. Minimizes the traffic as only border proxies send keepalives which send keepalives statelessly, instead of having to relay messages generated by the registrars.
  3. Also for situations when DNS resolves diff proxies for outgoing or incoming path traditional register based keepalives fail to associate or dissociate correct routes.

How keepalives work for NATing ?

This mechanism works by sending a SIP request to a user agent behind NAT to make that user agent send back a reply. The purpose is to have packets sent from inside the NAT to the proxy often enough to prevent the NAT box from timing out the connection.

Module sends Keeplaives to preserve their visibility only in :

  • Registration – for user agent that have registered to for incoming calls, triggering keepalive for a REGISTER request.
  • Subscription – for presence agents that have subscribed to some events for receiving back notifications with SUBSCRIBE request.
  • Dialogs – for user agents that have initiated an outgoing call for receiving further in-dialog messages.
    When all the conditions to keepalive a NAT endpoint will disappear, that endpoint will be removed from the list with the NAT endpoints that need to be kept alive.

function nat_keepalive() :

  • the function needs to be called on proxy directly interacting with UA behind NAT.
  • call only once for the requests (REGISTER, SUBSCRIBE or outgoing INVITEs) that triggers the need for network visibility.
  • call before the request gets either a stateless reply or it is relayed with t_relay()
  • for outgoing INVITE , it triggers dialog tracing for that dialog and will use the dialog callbacks to detect changes in the dialog state.

Dependencies – sl , tm and dialog module

Params

keepalive_interval – time interval between sending a keepalive message to all the endpoints that need being kept alive. A negative value or zero will disable the keepalive functionality.

modparam("nat_traversal", "keepalive_interval", 30) // 30 seconds keeplaive inetrval

keepalive_method – SIP method to use to send keepalive messages.usual ones are NOTIFY and OPTIONS. Default value is “NOTIFY”.

modparam("nat_traversal", "keepalive_method", "OPTIONS")

keepalive_from – SIP URI to use in the From header of the keepalive requests. default sip:keepalive@proxy_ip,with IP address of the outgoing interface

modparam("nat_traversal", "keepalive_from", "sip:keepalive@altanai.com")

keepalive_extra_headers – extra headers that should be added to the keepalive messages. Header must also include the CRLF (\r\n) line separator. Multiple headers can be specified by concatenating with \r\n separator.

modparam("nat_traversal", "keepalive_extra_headers", "User-Agent: Kamailio\r\nX-MyHeader: some_value\r\n")

keepalive_state_file – filename where information about the NAT endpoints and the conditions for which they are being kept alive is saved . It is used when Kamailio starts to restore its internal state and continue to send keepalive messages to the NAT endpoints that have not expired in the meantime. Also used at kamailio restart as it avoids losing keepalive state information about the NAT endpoints.

modparam("nat_traversal", "keepalive_state_file", "/var/run/kamailio/keepalive_state")

Functions

client_nat_test – Check if the client is behind NAT. Tests to be performed gievn by int can be :
1 – tests if client has a private IP address or one from shared address space in the Contact field of the SIP message.
2 – tests if client has contacted Kamailio from an address that is different from the one in the Via field.
4 – tests if client has a private IP address or one from shared address space in the top Via field of the SIP message.

For example calling client_nat_test(“3”) will perform test 1 and test 2 and return true if at least one succeeds, otherwise false.

fix_contact() – replace the IP and port in the Contact header with the IP and port the SIP message was received from. Usually called after a succesfull call to client_nat_test(type)

if (client_nat_test("3")) {
    fix_contact();
}

nat_keepalive() – Triggers keepalive functionality for the source address of the request. When called it only sets some internal flags, which will trigger later the addition of the endpoint to the keepalive list if a positive reply is generated/received (for REGISTER and SUBSCRIBE) or when the dialog is started/replied (for INVITEs). For this reason, it can be called early or late in the script. The only condition is to call it before replying to the request or before sending it to another proxy. If the request needs to be sent to another proxy, t_relay() must be used to be able to intercept replies via TM or dialog callbacks.

If stateless forwarding is used, the keepalive functionality will not work. Also for outgoing INVITEs, record_route() should also be used to make sure the proxy that keeps the caller endpoint alive stays in the path.

if ((method=="REGISTER" || method=="SUBSCRIBE" ||
    (method=="INVITE" && !has_totag())) && client_nat_test("3"))
{
    nat_keepalive();
}

Pseudo Variables
$keepalive.socket(nat_endpoint)
$source_uri

Statistics

  • keepalive_endpoints – total number of NAT endpoints that are being kept alive.
  • registered_endpoints – NAT endpoints kept alive for registrations
  • subscribed_endpoints – NAT endpoints kept alive for subscriptions.
  • dialog_endpoints – Indicates how many of the NAT endpoints are kept alive for taking part in an INVITE dialog.

NATHelper Module

NAT traversal and reuse of TCP connections
Helps symmetric UAs who are not able to determine their public address.

NAT pinging types

UDP packet – 4 bytes (zero filled) UDP packets are sent to the contact address.
pros : low bandwitdh traffic, easy to generate by Kamailio;
cons : unidirectional traffic through NAT (inbound – from outside to inside); As many NATs do update the bind timeout only on outbound traffic, the bind may expire and closed.

SIP request – a stateless SIP request is sent to the UDP contact address.
pros : bidirectional traffic through NAT, since each PING request from Kamailio (inbound traffic) will force the SIP client to generate a SIP reply (outbound traffic) – the NAT bind will be surely kept open.
cons : higher bandwitdh traffic, more expensive (as time) to generate by Kamailio;

Dependencies – usrloc

Params

force_socket – Socket to be used when sending NAT pings for UDP communication.

modparam("nathelper", "force_socket", "127.0.0.1:5060")

natping_interval
ping_nated_only
natping_processes – How many timer processes should be created by the module for the exclusive task of sending the NAT pings.
natping_socket
received_avp – AVP) used to store the URI containing the received IP, port, and protocol by fix_nated_register
sipping_bflag
sipping_from
sipping_method
natping_disable_bflag
nortpproxy_str
keepalive_timeout
udpping_from_path
append_sdp_oldmediaip
filter_server_id

Functions

fix_nated_contact() – rewrites the “Contact” header field with request’s source address:port pair
fix_nated_sdp() – adds the active direction indication to SDP and updates ource ip address information too
add_rcv_param() – add a received parameter to the “Contact” header fields or the Contact URI.
fix_nated_register() exports the request’s source address:port into an AVP to be used during save()
nat_uac_test()- check if client’s request originated behind a nat
is_rfc1918()
add_contact_alias() – Adds an “;alias=ip~port~transport” parameter to the contact URI
handle_ruri_alias() – Checks if the Request URI has an “alias” parameter and if so, removes it and sets the “$du” based on its value.
set_contact_alias()

Pseudo Variables

$rr_count – Number of Record Routes in received SIP request or reply.
$rr_top_count – If topmost Record Route in received SIP request or reply is a double Record Route, value of $rr_top_count is 2.

RPC Commands

nathelper.enable_ping

Ref :

Kamailio WebRTC SIP Server

The purpose of this article if to demo the process of using Kamailio + RTP Engine to enable SIP based WebRTC call to a traditional SIP UA like Xlite. Kamailio Will thus provide not only call routing but also NATing , TLS and websocket support for webrtc endpoints.

For this bridging of SRTP from WebRTC endpoint like JSSIP to RTP for SIP UA like Xlite , we will use RTP engine .

Kamailio

Kamailio with modules like websocket , TLS , NATHelper which help it to support websocket based SIP which default kamailio configuration doesn’t.

Snippets from kamailio config to support webrtc endpoints is below . the detailed explanation is at kamailio config for webrtc

loadmodule "tm.so"
loadmodule "sl.so"
loadmodule "rr.so"
loadmodule "pv.so"
loadmodule "maxfwd.so"
loadmodule "usrloc.so"
loadmodule "textops.so"
loadmodule "siputils.so"
loadmodule "xlog.so"
loadmodule "sanity.so"
loadmodule "ctl.so"
loadmodule "kex.so"
loadmodule "corex.so"
loadmodule "tls.so"
loadmodule "xhttp.so"
loadmodule "websocket.so"
loadmodule "nathelper.so"

Configuration of some important modules

TLS module

To provide the SSL support which webrtc endpoints require Certificate Authority CA and provate certs signed by it

creating file paths

mkdir certs
mkdir certs/private
mkdir certs/newcerts
touch certs/index.txt
echo 01 >certs/serial
echo 01 >certs/crlnumber

list the files

/home/ubuntu/certs# ls
crlnumber  index.txt  newcerts  private  serial

create ca private key

openssl genrsa -out certs/private/cakey.pem 2048
chmod 600 certs/private/cakey.pem

create ca self signed certificate

openssl req -out certs/cacert.pem -x509 -new -key certs/private/cakey.pem

create server / client certificate, a private key (by name privkey.pem)

openssl req -out kamailio1_cert_req.pem -new -nodes
openssl ca -in kamailio1_cert_req.pem -out kamailio1_cert.pem

output should be like

Certificate is to be certified until Jun 25 11:02:41 2020 GMT (365 days)
Sign the certificate? [y/n]:y
1 out of 1 certificate requests certified, commit? [y/n]y
Write out database with 1 new entries
Data Base Updated

and files genrated shoudl look like

/home/ubuntu# ls 
 certs  kamailio1_cert.pem kamailio1_cert_req.pem privkey.pem

copy the newly created certs to their respective paths

mkdir /etc/pki/CA/
cp kamailio1_cert.pem /etc/pki/CA/
cp privkey.pem /etc/pki/CA/

make list of ca certs by finidng all cacerts accross root firectory and appending them to a catlist pem

find / -name cacert.pem
cat /usr/share/doc/libssl-doc/demos/cms/cacert.pem >> /home/ubuntu/catlist.pem
cat /usr/share/doc/libssl-doc/demos/smime/cacert.pem >> /home/ubuntu/catlist.pem
cat /home/ubuntu/kamailio_source_code/misc/tls-ca/rootCA/cacert.pem >> /home/ubuntu/catlist.pem
...
cp /home/ubuntu/catlist.pem /etc/pki/CA/

update kamailio.cfg

#!ifdef WITH_TLS
enable_tls=1
#!endif
...
modparam("tls", "tls_method", "SSLv23")
modparam("tls", "certificate", "/etc/pki/CA/kamailio1_cert.pem")
modparam("tls", "private_key", "/etc/pki/CA/privkey.pem")
modparam("tls", "ca_list", "/etc/pki/CA/calist.pem")

Websocket module

Websocket is considered a transport option just as TCP or UDP in kamailio config , hence just as one defines IP addr and ports for TCP, UDP protocol , we need to define the same for WS or WSS

#!substdef "!MY_WS_ADDR!tcp:MY_IP_ADDR:MY_WS_PORT!g"
#!substdef "!MY_WSS_ADDR!tls:MY_IP_ADDR:MY_WSS_PORT!g"
...
listen=MY_IP_ADDR
#!ifdef WITH_WEBSOCKETS
listen=MY_WS_ADDR
#!ifdef WITH_TLS
listen=MY_WSS_ADDR
#!endif
#!endif

check if port in R-URI meant for ws or wss, did not receive websocket or secure websocket

if (($Rp == MY_WS_PORT || $Rp == MY_WSS_PORT) && !(proto == WS || proto == WSS)) {
    xlog("L_WARN", "SIP request received on $Rp\n");
    sl_send_reply("403", "Forbidden");
    exit;
}

request_route for websocket , included checking is client is behind NAT using nat_uac_test methods from NAThelper. If it is then for REGISTER methods do fix_nated_register and for other add_contact_alias

#!ifdef WITH_WEBSOCKETS
if (nat_uac_test(64)) {
	# NAT traversal  WebSocket
	force_rport();
	if (is_method("REGISTER")) {
		fix_nated_register();
	} else {
		if (!add_contact_alias()) {
		xlog("L_ERR", "Error aliasing contact <$ct>\n");
		sl_send_reply("400", "Bad Request");
		exit;
		}
	}
}
#!endif

RTP engine

RTP relay and NAT helps with RTP packets

For detailed steps goto https://telecom.altanai.com/2018/04/03/rtp-engine-on-kamailio-sip-server/

dependencies

apt-get remove rtpproxy
sudo apt install debhelper iptables-dev libcurl4-openssl-dev libglib2.0-dev libxmlrpc-core-c3-dev libhiredis-dev markdown build-essential:native

source

git clone https://github.com/sipwise/rtpengine.git
cd rtpengine
 ./debian/flavors/no_ngcp

run

rtpengine --interface=54.86.35.95 --listen-ng=25061 --listen-cli=25062 --foreground --log-stderr --listen-udp=2222 --listen-tcp=25060

integrate with kamailio using

loadmodule "rtpengine.so"
...
modparam("rtpengine", "rtpengine_sock", "udp:localhost:7722")
modparam("nathelper", "received_avp", "$avp(s:rcv)")
...
tbd

JSSIP

Like most other WebRTC libraries , JSSIP is event driven and provides provide core WEBRTC API like getUserMedia and RTP PeerConnection providing STUN,ICE,DTLS, SRTP features. It also integrated with rtcninja to provide cross browser accessibility. The differentiators with JSSIP lies in the fact that it supports SIP stack over websockets

Building JSSIP client for kamailio

Can use CDN based https://cdnjs.cloudflare.com/ajax/libs/jssip/3.1.2/jssip.min.js

or can take a pull from JSSIP repo and build urself using gulp https://github.com/versatica/JsSIP

instantiate JSSIP websocket interface with kamailio IP

var socket = new JsSIP.WebSocketInterface('wss://<kamailio_ip>:443');

Add configuration for registeration . Note if not using kamailio as proxy to SBC, it is recommended to add regiseteration features to provide user reachability for incoming calls and NAT pings

var configuration = {
sockets : socket,
uri : 'sip:username@example.com',
password : 'password'
};

create UA and start

var ua = new JsSIP.UA(configuration);
ua.start();

SIP over WEBSOCKET messages and kamailio processing

REGISTER sip JSSIP UA with user altanai , domina voiptelcom.com

REGISTER sip:voiptelco.com SIP/2.0
Via: SIP/2.0/WSS 830p2l39g8bg.invalid;branch=z9hG4bK242397
Max-Forwards: 69
To: 
From: ;tag=3jaad0q8l8
Call-ID: fvn2cd1b9gqh6kd7nqdpj5
CSeq: 1 REGISTER
Contact: ;+sip.ice;reg-id=1;+sip.instance="";expires=600
Expires: 600
Allow: INVITE,ACK,CANCEL,BYE,UPDATE,MESSAGE,OPTIONS,REFER,INFO
Supported: path,gruu,outbound
User-Agent: JsSIP 3.1.2
Content-Length: 0

Processed by kamailio using REGISTRAR route block

route(REGISTRAR);
..
route[REGISTRAR] {
	if (is_method("REGISTER")) {
		if (!save("location")) {
			sl_reply_error();
		}
		exit;
	}
}
SIP/2.0 200 OK
Via: SIP/2.0/WSS 830p2l39g8bg.invalid;branch=z9hG4bK242397;rport=19035;received=x.x.x.x
To: ;tag=4dad943d40a0a309c33d64467664aa30.f6d3
From: ;tag=3jaad0q8l8
Call-ID: fvn2cd1b9gqh6kd7nqdpj5
CSeq: 1 REGISTER
Contact: ;expires=600;received="sip:x.x.x.x:19035;transport=ws";pub-gruu="sip:altanai@voiptelco.com;gr=urn:uuid:80fa65e7-1cd7-4e40-bbee-c07f7a1ae9a5";temp-gruu="sip:uloc-5d260578-4b58-c-eeac6bd6@voiptelco.com;gr";+sip.instance="";reg-id=1
Server: kamailio (5.2.3 (x86_64/linux))
Content-Length: 0

INVITE from user1 altanai to john , notice that TO header doesnt have tag . this will handy for recognizing whether it is first message of dialog of=r and indialog message such as ACK , RE-INVITE , BYE etc

INVITE sip:john@voiptelco.com SIP/2.0
Via: SIP/2.0/WSS ipoct61ao12v.invalid;branch=z9hG4bK4220209
Max-Forwards: 69
To: sip:john@voiptelco.com
From: sip:altanai@voiptelco.com;tag=2q0lecmbsn
Call-ID: s8bnv5869fp68d1ju8c1
CSeq: 1799 INVITE
Contact: 
Content-Type: application/sdp
Session-Expires: 90
Allow: INVITE,ACK,CANCEL,BYE,UPDATE,MESSAGE,OPTIONS,REFER,INFO
Supported: timer,gruu,ice,replaces,outbound
User-Agent: JsSIP 3.1.2
Content-Length: 1823

with SDP containing codecs and ICE details. Supporting audio over UDP/ TLS/RTL /SAVPF . Codecs beings

  • 111 OPUS
  • 103 ISAC/16000
  • 104 ISAC/32000
  • 9 G722
  • 0 PCMU / G.711u narrowband
  • 8 PCMA / G.711
  • 106 , 105 , 13 – CN / comfort noise
  • 110 , 112 , 113 , 126 – telephone-event / DTMF
v=0
o=- 4779000713447952953 2 IN IP4 127.0.0.1
s=-
t=0 0
a=group:BUNDLE 0
a=msid-semantic: WMS SFIXFrpsOUskJ5JQhp1mIARlDk6S3hVFTOBb
m=audio 55839 UDP/TLS/RTP/SAVPF 111 103 104 9 0 8 106 105 13 110 112 113 126
c=IN IP4 192.168.0.3
a=rtcp:9 IN IP4 0.0.0.0
a=candidate:3802297132 1 udp 2122260223 192.168.0.3 55839 typ host generation 0 network-id 1 network-cost 10
a=candidate:2887880668 1 tcp 1518280447 192.168.0.3 9 typ host tcptype active generation 0 network-id 1 network-cost 10
a=ice-ufrag:0PIq
a=ice-pwd:i7ccvGPXLDO5JqMwbCUqMcyN
a=ice-options:trickle
a=fingerprint:sha-256 AB:50:70:E3:57:E3:0C:7B:61:3B:03:5B:0F:54:14:14:9C:49:50:16:07:DC:E7:09:3E:4D:B5:A0:2B:EC:84:A1
a=setup:actpass
a=mid:0
a=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level
a=extmap:2 http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01
a=extmap:3 urn:ietf:params:rtp-hdrext:sdes:mid
a=extmap:4 urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id
a=extmap:5 urn:ietf:params:rtp-hdrext:sdes:repaired-rtp-stream-id
a=sendrecv
a=msid:SFIXFrpsOUskJ5JQhp1mIARlDk6S3hVFTOBb e803836d-249a-4b81-b73f-17e0f08dde5a
a=rtcp-mux
a=rtpmap:111 opus/48000/2
a=rtcp-fb:111 transport-cc
a=fmtp:111 minptime=10;useinbandfec=1
a=rtpmap:103 ISAC/16000
a=rtpmap:104 ISAC/32000
a=rtpmap:9 G722/8000
a=rtpmap:0 PCMU/8000
a=rtpmap:8 PCMA/8000
a=rtpmap:106 CN/32000
a=rtpmap:105 CN/16000
a=rtpmap:13 CN/8000
a=rtpmap:110 telephone-event/48000
a=rtpmap:112 telephone-event/32000
a=rtpmap:113 telephone-event/16000
a=rtpmap:126 telephone-event/8000
a=ssrc:2800821831 cname:kLWViBLDLVfCXY8x
a=ssrc:2800821831 msid:SFIXFrpsOUskJ5JQhp1mIARlDk6S3hVFTOBb e803836d-249a-4b81-b73f-17e0f08dde5a
a=ssrc:2800821831 mslabel:SFIXFrpsOUskJ5JQhp1mIARlDk6S3hVFTOBb
a=ssrc:2800821831 label:e803836d-249a-4b81-b73f-17e0f08dde5a

100 trying from callee . Note the to and from headers remain same for request or responses . This is send automatically by kamailio for INVITE.

SIP/2.0 100 trying -- your call is important to us
Via: SIP/2.0/WSS ipoct61ao12v.invalid;branch=z9hG4bK4220209;rport=17502;received=x.x.x.x
To: sip:john@voiptelco.com
From: sip:altanai@voiptelco.com;tag=2q0lecmbsn
Call-ID: s8bnv5869fp68d1ju8c1
CSeq: 1799 INVITE
Server: kamailio (5.2.3 (x86_64/linux))
Content-Length: 0

180 ringing from Callee , note the addition of contact header

SIP/2.0 180 Ringing
Record-Route: 
Via: SIP/2.0/WSS ipoct61ao12v.invalid;rport=17502;received=x.x.x.x;branch=z9hG4bK4220209
To: sip:john@voiptelco.com;tag=pvm73e3t89
From: sip:altanai@voiptelco.com;tag=2q0lecmbsn
Call-ID: s8bnv5869fp68d1ju8c1
CSeq: 1799 INVITE
Contact: sip:john@voiptelco.com;alias=x.x.x.x~17510~6;gr=urn:uuid:2e560b36-3ea8-41fd-80e3-ede66babb8a7
Supported: timer,gruu,ice,replaces,outbound
Content-Length: 0

200 OK with SDP

SIP/2.0 200 OK
Record-Route: 
Via: SIP/2.0/WSS ipoct61ao12v.invalid;rport=17502;received=x.x.x.x;branch=z9hG4bK4220209
To: sip:altanai@voiptelco.com;tag=pvm73e3t89
From: sip:john@voiptelco.com ;tag=2q0lecmbsn
Call-ID: s8bnv5869fp68d1ju8c1
CSeq: 1799 INVITE
Contact: sip:john@voiptelco.com;alias=x.x.x.x~17510~6;gr=urn:uuid:2e560b36-3ea8-41fd-80e3-ede66babb8a7
Session-Expires: 90;refresher=uas
Supported: timer,gruu,ice,replaces,outbound
Content-Type: application/sdp
Content-Length: 1477
v=0
o=- 4562215268128860297 2 IN IP4 127.0.0.1
s=-
t=0 0
a=group:BUNDLE 0
a=msid-semantic: WMS oxU77z9z9RfNL4CayvM1cMJKI0r7u6ZdqLBd
m=audio 55380 UDP/TLS/RTP/SAVPF 111 103 104 9 0 8 106 105 13 110 112 113 126
c=IN IP4 192.168.0.3
a=rtcp:9 IN IP4 0.0.0.0
a=candidate:3802297132 1 udp 2122260223 192.168.0.3 55380 typ host generation 0 network-id 1 network-cost 10
a=ice-ufrag:40h+
a=ice-pwd:6zJo50N7Bb2mqnrHq+jniukk
a=ice-options:trickle
a=fingerprint:sha-256 8A:F9:BE:8D:8A:80:FF:8C:89:3D:3A:D2:A1:36:B2:EC:11:53:81:7E:F4:53:E7:40:1E:B9:1E:A2:0F:D4:EA:2E
a=setup:active
a=mid:0
a=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level
a=extmap:2 http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01
a=extmap:3 urn:ietf:params:rtp-hdrext:sdes:mid
a=extmap:4 urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id
a=extmap:5 urn:ietf:params:rtp-hdrext:sdes:repaired-rtp-stream-id
a=sendrecv
a=msid:oxU77z9z9RfNL4CayvM1cMJKI0r7u6ZdqLBd cb6da6b5-d5b8-460e-88bc-1458ebc718e6
a=rtcp-mux
a=rtpmap:111 opus/48000/2
a=rtcp-fb:111 transport-cc
a=fmtp:111 minptime=10;useinbandfec=1
a=rtpmap:103 ISAC/16000
a=rtpmap:104 ISAC/32000
a=rtpmap:9 G722/8000
a=rtpmap:0 PCMU/8000
a=rtpmap:8 PCMA/8000
a=rtpmap:106 CN/32000
a=rtpmap:105 CN/16000
a=rtpmap:13 CN/8000
a=rtpmap:110 telephone-event/48000
a=rtpmap:112 telephone-event/32000
a=rtpmap:113 telephone-event/16000
a=rtpmap:126 telephone-event/8000
a=ssrc:3489110087 cname:oZ2LjwJD385qPHHH

Kamailio handling replies using reply_route

onreply_route {
     if (nat_uac_test(64)) {
         add_contact_alias();
     }
 }

Sending ACK .

ACK sip:john@voiptelco.com;alias=x.x.x.x~17510~6;gr=urn:uuid:2e560b36-3ea8-41fd-80e3-ede66babb8a7 SIP/2.0

Route: 
Via: SIP/2.0/WSS ipoct61ao12v.invalid;branch=z9hG4bK1876245
Max-Forwards: 69
To: sip:altanai@voiptelco.com ;tag=pvm73e3t89
From: sip:john@voiptelco.com;tag=2q0lecmbsn
Call-ID: s8bnv5869fp68d1ju8c1
CSeq: 1799 ACK
Allow: INVITE,ACK,CANCEL,BYE,UPDATE,MESSAGE,OPTIONS,REFER,INFO
Supported: outbound
User-Agent: JsSIP 3.1.2
Content-Length: 0

since ACK is a Within dialog message and sequential request withing a dialog should take the path determined by record-routing , we first check if it has to tag. Having a to tag validates that it is a in-dialog request .

After this validate if is loose_route() and has no destination URI $du , then try to add rui alias using handle_ruri_alias() , if that fails , reject the request .

If it is not loose_route() and method is ACK then check if the ACK matches a transaction t_check_trans() ie is stateful . If it is then relay otherwise reject.

route(WITHINDLG);
...
route[WITHINDLG] {
	if (has_totag()) {
		if (loose_route()) {
			if ($du == "") {
				if (!handle_ruri_alias()) {
				xlog("L_ERR", "Bad alias <$ru>\n");
				sl_send_reply("400", "Bad Request");
				exit;
				}
			}
			route(RELAY);
		} else {
			if ( is_method("ACK") ) {
				if ( t_check_trans() ) {
				t_relay();
				exit;
				} else {
				exit;
				}
			}
			sl_send_reply("404", "Not Found");
		}
		exit;
	}
}

Also required to convert ICE packet fromWebRTC to non ICE for Xlite.

Opensips

It is an multi-functional, multi-purpose SIP server especially used in VoIP landscape as standalone SIP server or SBC ( Session Border Controller ) for inbound and outbound traffic by carriers, telecoms backend layers or ITSPs for call routing and trunking solutions. It can be deployed with Class4/5 Platforms, SIP Trunking , hosted or IP PBX setup , existing gateways/ Session Border Controllers, Application Servers, proxy server, Front-End Load Balancers, IMS Platforms, Call Center etc.

Combination of opensips working scenarios scripts with code is at https://github.com/altanai/opensipsexamples.

Features

Due to its very flexible and customisable routing engine it can be used in number of scenarios such as an SIP proxy or a  router and due to its high throughput it is widely recommended as an enterprise grade inbound/outbound proxy server.

  • Registrar
  • Router / proxy (lcr, dynamic routing, dialplan features)
  • Redirect server
  • Presence agent
  • Back-to-back User Agent
  • IM server
  • SIP to SMS gateway (bidirectional)
  • SIP to XMPP gateway for presence and IM (bidirectional)
  • Load-balancer or dispatcher
  • Inbound/front end for gateways/asterisk
  • SIP NAT traversal unit
  • Application server with custom logic

Since Opensips has emerged as a resilent SIP server , it is also used in specific usecases such as
– DID ( Direct Inward dialling ) for SIP trunking solutions ,
– Local Number Portability (LNP) providers,
– Canonical Name (CNAME) providers etc

It can act as Registrar with NAT traversal abilities (STUN, TURN, SIP pinging)

UDP , TCP , TLS , SCTP and WS transports over both IPv4 and IPv6
Additionally it can be connected to multiple networks ( Multihomed ) and do IP authentication or IP blacklisting

Class 4 routing capabilities in opensips include SIP aliases, Direct Inward Dialing , Speed dial, CPL,vDialplan , dispatcher with various algorithms, prefix-based routing to multiple carriers , failover support,
Load balancing , ENUM-based or Geolocation-based routing etc.
Some of the Class 5 capabilities in opensips are B2B , call queuing
UAC registration , authentication, mangling, White/Black list

SIP SIMPLE features as messaging , Presence , Busy Lamp Field (BLF), Shared Call/Line Appearance (SCA) , Bridged Line Appearance (BLA) , Message Waiting notifications (MWI), XCAP , Resource List Server ( RLS ) , XMPP , SMS gateway (AT and SMPP)

Although opensips has no built-in media capabilities, but it modules for external media engines for Media relaying (RTPProxy, MediaProxy, RTPEngine), Media transcoding (Sangoma D1 cards) , Codec manipulation.

I have explained the usage of these server components in my previous article on  SIP entities and Server here https://telecom.altanai.com/2013/07/13/sip-entities/

Modular Arhitecture

Opensips has majorly 2 parts core and addon-modules.

Opensips Core part is only a proxy stateless SIP server . It contains

  • SIP transport layer which supports UDP, TCP, TLS and WS for SIP. As per the listener in routing script transport protocols is selected .
  • SIP factory — the message parser and builder which can be used to add new headers or remove existing ones.
  • Routing script parser and interpreter for the routing script which loads it to the memory at the startup time. To load a new script server restart is required.
  • Memory and locking manager for the memory allocation and locking to prevent deadlocks and starvation. Although these arn’t accesible by route scripting, it can be configured at compile time.
  • Core script functions and variables which can be used in routing scripts in addition to the functions exported by add-on modules.

Interfaces

Events Interface

Used to notify external applications about events triggered internal to OpenSIPS such as
core events – E_CORE_THRESHOLD ,E_CORE_PKG_THRESHOLD , E_CORE_SHM_THRESHOLD , modules events , or even a custom event using raise_event() command

Statistics Interface

Provide insights to statistics of opensips in numerical results which could be used for services like  monitoring, load evaluation, realtime integration etc. The statictsics can be of two kinds :
1. counter like – variables that keep counting things that happened in OpenSIPS, like received requests, processed dialogs, failed DB queries, etc
2. computed values – variables that are calculated in realtime, like how much memory is used, the current load, active dialogs, active transactions, etc

These variable would reset form 0 at start sometimes even during runtime.

Binary Internal Interface

Provider communication between individual OpenSIPS instances. Used in cases such as failovers where dialogs needs to persist for service continuity. Hence with this interface one can replicate all the events related to the runtime data (creation / updating / deletion) to a backup OpenSIPS instance.

SQL interface and NoSQL interface

SQL interfaces provides interaction with Sql DB drivers and services such as MySQL, Postgres, Oracle, Berkeley, unixODBC etc , while NoSQL interface provides access to Redis, CouchBase, Cassandra, MongoDB, Memcached, and other databases which are more frequently implemented as external caches.

AAA interface definition

Currently, OpenSIPS supports the RADIUS driver for the AAA interface with upcoming support for DIAMETER.

Management interface

Allows the external applications to trigger predefined commands
Push data like setting a debug level, registering a contact etc
Fetch data like registered users, ongoing calls, get statistics etc
Trigger an internal action as reloading the data, sending a message so on

1. Functional SIP modules

SIP signalling modules such as B2B_ENTITIES , B2B_LOGIC , CALL CENTER ( for Inbound call center system ) , DIALOG , NAT_TRAVERSAL , NATHELPER
OPTIONS , REGISTRAR ,SIGNALING , UAC_REGISTRANT
TM (Transaction/stateful module) , SL (Stateless replier ) , SMS (SIP-to-SMS IM gateway)

SIP Routing modules such as CARRIERROUTE ( routing extension suitable for carriers) , CPL_C ( Call Processing Langugage interpreter ) ,
DISPATCHER , DROUTING ( Dynamic Routing / LCR ) , EMERGENCY ,ENUM ,
JABBER (JABBER IM and PRESENCE interconnection ) , IMC ( Instant Messaging Conferencing ),
LOAD_BALANCER , MSILO (SIP message silo) , RR ( Record-Route) , SCRIPT_HELPER ( Embedded SIP routing logic and dialog management) , OSP ( Open Settlement Protocol )

SIP messaging related , COMPRESSION , DIVERSION , IDENTITY ,MAXFWD , MANGLER
PATH , SIPMSGOPS ( SIP operations ) , TOPOLOGY_HIDING ,
UAC , UAC_AUTH , UAC_REDIRECT
URI , SST ( SIP Session Timer support )

Presence Modules like PRESENCE , PRESENCE_CALLINFO , PRESENCE_DIALOGINFO, PRESENCE_MWI (for Message Waiting Indication ) , PRESENCE_XCAPDIFF (for XCAP-DIFF event) , PRESENCE_XML
PUA , PUA_BLA , PUA_DIALOGINFO , PUA_MI , PUA_USRLOC , PUA_XMPP
B2B_SCA ( Back-to-Back Shared Call ), RLS ( Resource List Server )
XCAP , XCAP_CLIENT

2. Scripting modules

Script helper modules such as JSON , CFGUTILS , EXEC , TEXTOPS , AVPOPS , REGEX, MATHOPS , BENCHMARK ,
CARRIERROUTE , GFLAGS (Global shared flags )
PYTHON , LUA ,PERL , MMGEOIP ( MaxMind GeoIP )

Auth modules such as AUTH , AUTH_AAA ,AUTH_DB , PERMISSIONS

Accounting & Billing modules aas ACC ,CALL CONTROL

Dialplan Modules like ALIAS_DB , DIALPLAN , DOMAIN ( Multi-domain support ) , DOMAINPOLICY ,
GROUP , USERBLACKLIST , SPEEDDIAL ,PEERING ( Radius peering )

Data caching as DNS_CACHE , USRLOC ,SQL_CACHER

Traffic shaping module as PIKE ( Flood detector module ), QOS ,RATELIMIT ,FRAUD_DETECTION

3. Database modules

For SQL – DB_BERKELEY , DB_CACHEDB , DB_FLATSTORE , DB_HTTP , DB_MYSQL , DB_ORACLE ,DB_PERLVDB , DB_POSTGRES , DB_SQLITE
DB_TEXT , DB_UNIXODBC , DB_VIRTUAL

For noSQL – CACHEDB_CASSANDRA ,CACHEDB_COUCHBASE ,CACHEDB_LOCAL ,CACHEDB_MEMCACHED , CACHEDB_MONGODB , CACHEDB_REDIS , CACHEDB_SQL

4. External Integration modules

OpenSIPS API as EVENT_DATAGRAM , EVENT_FLATSTORE ( Text/File backend for events ), EVENT_ROUTE ,EVENT_RABBITMQ
EVENT_VIRTUAL ( Aggregator of event backends failover & balancing), EVENT_XMLRPC
MI_DATAGRAM ( DATAGRAM unix and network support for Management Interface )
MI_FIFO , MI_HTTP , MI_JSON , MI_XMLRPC_NG
HTTPD , PI_HTTP ( Provisioning Interface ) , STATISTICS

Media Relays
MEDIAPROXY – NAT traversal module
RTPENGINE – Connector to RTPengine external RTP relay
RTPPROXY – Connector to RTPproxy external RTP relay

non-SIP protocols modules such as AAA_RADIUS , H350 , LDAP – LDAP connector , stable
REST_CLIENT , SEAS ( Sip Express Application Server interface module), SIPCAPTURE , SIPTRACE ,
SNGTC ( Voice Transcoding in OpenSIPS using Sangoma hardware ),
SNMPStats , STUN , XMPP ( SIP-to-XMPP Gateway )

5. OpenSIPS protocols and infrastructure

CLUSTERER , TLS_MGM , PROTO_BIN ( Binary INterface protocol module to implements inter-OPENSIPS communication )
PROTO_HEP , PROTO_SCTP , PROTO_TCP, PROTO_TLS , PROTO_UDP , PROTO_WS , PROTO_WSS

How to Install and use Opensips on your VoIP platform

Install from git repo

git clone git@github.com:OpenSIPS/opensips.git opensips_head
install gcc
make all

Install from apt

apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 049AD65B
echo "deb http://apt.opensips.org trusty 2.4-releases" >/etc/apt/sources.list.d/opensips.list

check if opensips is running

ps -uax|grep opensips

Configuration ( opensips.cfg )

configuring compilation flags for various compile time options use menuconfig.

For this first install the ncurses development library

apt-get install libncurses5-dev
make menuconfig

Running menuconfig post installation from path use osipsconfig

compiling modules

prerequisites

apt-get install build-essential openssl bison flex
make && make install

After succesfull installation check version

opensips -V
version: opensips 2.2.7 (x86_64/linux)
flags: STATS: On, DISABLE_NAGLE, USE_MCAST, SHM_MMAP, PKG_MALLOC, F_MALLOC, FAST_LOCK-ADAPTIVE_WAIT
ADAPTIVE_WAIT_LOOPS=1024, MAX_RECV_BUFFER_SIZE 262144, MAX_LISTEN 16, MAX_URI_SIZE 1024, BUF_SIZE 65535
poll method support: poll, epoll_lt, epoll_et, sigio_rt, select.
main.c compiled on  with gcc 4.8

A config file opensips.config has 3 main logical parts :

1.global parameters – network listeners, available transport protocols, forking (and number of processes), the logging

2.modules section – the modules that are to be loaded  with path to their .so file

3.routing logic – logic for routing sip traffic

Routes

OpenSIPS routing logic uses several types of routes. Each type of route is triggered by a certain event and allows you to process a certain type of message (request or reply).

route
SIP requests routing. The main ‘route’ block identified by ‘route{…}’ or ‘route[0]{…}’ is executed for each SIP request.
To send a reply or forward the request, explicit actions must be called inside the route block. in example below which sends 200 ok reply for each options request.

route {
if(is_method("OPTIONS")) {
sl_send_reply("200", "ok");
exit();
}
route(1);
}
route[1] {
forward();
}

branch_route
Handles different branches of a SIP request. if the branch is not dropped the branch will be automatically sent out. It is executed only by TM module after it was armed via t_on_branch(“branch_route_index”).

if (is_method("INVITE|BYE|SUBSCRIBE|UPDATE")) {
if(!t_is_set("branch_route")) t_on_branch("MANAGE_BRANCH");
}
branch_route[MANAGE_BRANCH] {
xdbg("new branch [$T_branch_idx] to $ru\n");
route(NATMANAGE);
}

or lookup location and discard branches where uri matches ip 1.2.3.4 by using drop()

route {
lookup("location");
t_on_branch("op3");
if(!t_relay()) {
sl_send_reply("500", "relaying failed");
}
}
branch_route[op3] {
if(uri=~"1\.2\.3\.4") {
drop();
}
}

failure_route
Failed transaction routing block. It contains a set of actions to be taken each transaction that received only negative replies (>=300) for all branches which completes the transaction. The ‘failure_route’ is executed only by TM module after it was armed via t_on_failure(“failure_route_index”).

if (is_method("INVITE")) {
if(!t_is_set("failure_route")) t_on_failure("MANAGE_FAILURE");
}

failure_route[MANAGE_FAILURE] {
route(NATMANAGE);
if (t_is_canceled()) {
exit;
}
}

or on failure relay to voice mail

route {
lookup("location");
t_on_failure("op1");
if(!t_relay()) {
sl_send_reply("500", "relaying failed");
}
}
failure_route[op1] {
if(is_method("INVITE")) {
t_relay("udp:voicemail.server.com:5060");
}
}

onreply_route
Reply routing block. It can be stateful (if bound to a transaction) or stateless (if global reply route).
If the reply is not dropped (only provisional replies can be), it will be injected and processed by the transaction engine. There are three types of onreply routes:

global – catches all replies and uses simple definition ‘onreply_route {…}’ or ‘onreply_route[0] {…}’.
Exmaple for “global” reply route set the whole transaction

route {
seturi("sip:bob@opensips.org");  first branch
append_branch("sip:alice@opensips.org");  second branch
t_on_reply("global");
t_on_branch("1");
t_relay();
}

onreply_route {
xlog("OpenSIPS received a reply from $si\n");
}

onreply_route[global] {
if (t_check_status("1[0-9][0-9]")) {
setflag(1);
log("provisional reply received\n");
if (t_check_status("183"))
drop;
}
}

per request/transaction – it catches all received replies belonging to a certain transaction and uses “t_on_reply()” at request time, in REQUEST ROUTE – named ‘onreply_route[N] {…}’.

per branch – it catches only the replies that belong to a certain branch from a transaction via “t_on_reply()” ) at request time, but in BRANCH ROUTE, when a certain outgoing branch is processed – named ‘onreply_route[N] {…}’.
Certain ‘onreply_route’ blocks can be executed by TM module for special replies. For this, the ‘onreply_route’ must be armed for the SIP requests whose replies should be processed within it, via t_on_reply(“onreply_route_index”).

Exmaple of reply route set for this branch only


branch_route[1] {
if ($rU=="alice")
t_on_reply("alice");
}

onreply_route[alice] {
xlog("received reply on the branch from alice\n");
}

error_route

executed automatically on meeting and error such as parsing error in SIP request processing, script assert failure. Performs error handling . The Default action is to discard request. In error_route, the following pseudo-variables are available to get access to error details:

$(err.class) - the class of error (now is '1' for parsing errors)
$(err.level) - severity level for the error
$(err.info) - text describing the error
$(err.rcode) - recommended reply code
$(err.rreason) - recommended reply reason phrase
error_route {
xlog("--- error route class=$(err.class) level=$(err.level)
info=$(err.info) rcode=$(err.rcode) rreason=$(err.rreason) ---\n");
xlog("--- error from [$si:$sp]\n+++++\n$mb\n++++\n");
sl_send_reply("$err.rcode", "$err.rreason");
exit;
}

local_route

executed automatically as TM created a new request, internally (no UAC side). This is a route intended to be used for message inspection, accounting and for applying last changes on the message headers. Routing and signaling functions are not allowed.

local_route {
if (is_method("INVITE") && $ru=~"@foreign.com") {
append_hf("P-hint: foreign request\r\n");
exit;
}
if (is_method("BYE") ) {
acc_log_request("internally generated BYE");
}
}

startup_route
Executed only once when OpenSIPS is started and before the processing of SIP messages begins. Used in initilization cases cases such as loading some data in the cache.

startup_route {
avp_db_query("select gwlist where ruleid==1",$avp(i:100));
cache_store("local", "rule1", "$avp(i:100)");
}

timer_route
Route executed periodically at a configured interval of time specified next to the name(in seconds).

timer_route[gw_update, 300] {
avp_db_query("select gwlist where ruleid==1",$avp(i:100));
$shv(i:100) =$avp(i:100);
}

event_route
execute script code when an event is triggered. If no way to handle the event specified, default will be synchronously.
Triggered by the event_route module when an event is raised by the OpenSIPS Event Interface such as event raised by the pike module when it decides an ip should be blocked called E_PIKE_BLOCKED or E_SCRIPT_EVENT etc ( checke events interface for more events)

event_route[E_PIKE_BLOCKED] {
xlog("The E_PIKE_BLOCKED event was raised\n");
}
event_route[E_PIKE_BLOCKED, async] {
xlog("The E_PIKE_BLOCKED event was raised\n");
}

Scripting Language

Opensips scripting provided more advanced controls

1. Core Keywords

Keywords specific to SIP messages which can be used mainly in ‘if’ expressions.
af – address family of the received SIP message. It is INET if the message was received over IPv4 or INET6 if the message was received over IPv6.

if(af==INET6) {
log("Message received over IPv6 link\n");
};

dst_ip – IP of the local interface where the SIP message was received.

if(dst_ip==127.0.0.1) {
log("message received on loopback interface\n");
};

dst_port – local port where the SIP packet was received

if(dst_port==5061)
{
log("message was received on port 5061\n");
};

from_uri – reference to the URI of ‘From’ header.

if(is_method("INVITE") &amp;amp;amp;amp;amp;amp;&amp;amp;amp;amp;amp;amp; from_uri=~".*@opensips.org")
{
log("the caller is from opensips.org\n");
};

method – SIP method of the message.

if(method=="REGISTER")
{
log("this SIP request is a REGISTER message\n");
};

msg:len – the size of the message

if(msg:len&amp;amp;amp;amp;amp;gt;2048)
{
sl_send_reply("413", "message too large");
exit;
};

$retcode – value returned by last function executed like $?. If tested after a call of a route, it is the value retuned by that route.

route {
route(1);
if($retcode==1)
{
log("The request is an INVITE\n");
};
}

route[1] {
if(is_method("INVITE"))
return(1);
return(2);
}

proto – transport protocol of the SIP message.

if(proto==UDP)
{
log("SIP message received over UDP\n");
};

status – status code of the reply.

if(status=="200")
{
log("this is a 200 OK reply\n");
};

1.10 src_ip – source IP address

if(src_ip==127.0.0.1)
{
log("the message was sent from localhost!\n");
};

1.11 src_port – source port of the SIP message (from which port the message was sent by previous hop).

if(src_port==5061)
{
log("message sent from port 5061\n");
}

1.12 to_uri – URI from To header.

if(to_uri=~"sip:.+@opensips.org")
{
log("this is a request for opensips.org users\n");
};

1.13 uri – request URI.

if(uri=~"sip:.+@opensips.org")
{
log("this is a request for opensips.org users\n");
};

2. Core Values

Values that can be used in ‘if’ expressions to check against Core Keywords

INET – IPv4 connection. , INET6 – IPv6 connection , TCP , UDP

max_len – test message’s size.

if(msg:len&amp;amp;amp;amp;amp;gt;max_len)
{
sl_send_reply("413", "message too large to be forwarded over UDP without fragmentation");
exit;
}

myself – reference to the list of local IP addresses, hostnames and aliases that has been set in OpenSIPS configuration file. This lists contain the domains served by OpenSIPS.

if(uri==myself) {
log("the request is for local processing\n");
};

null – reset the value of a per-script variable or to delete an avp.

$avp(i:12) = null;
$var(x) = null;

3. Core parameters

abort_on_assert – Set to true in order to make OpenSIPS shut down immediately in case a script assert fails.

abort_on_assert = true // default is false

advertised_address – address advertised in Via header and other destination lumps (e.g RR header).

advertised_port – port advertised in Via header and other destination lumps (e.g. RR).

alias – set alias hostnames for the server

alias=udp:company.tel.com:5060
alias=tcp:company.tel.com:5060

auto_aliases – to control if aliases should be automatically discovered from DNS lookup and added during fixing listening sockets.

auto_aliases=no // default value is no
auto_aliases=0

cfg_file – Returns the name of the corresponding OpenSIPS config file

cfg_line – corresponding line inside the OpenSIPS config file.
check_via – Check if the address in top most via of replies is local.

check_via=1 // Default value is 0 (check disabled)

children – Number of worker processes (children) to be created for each UDP or SCTP interface you have defined. children=16 // Default value is 8

chroot – If set, OpenSIPS will chroot (change root directory) to this valid path in the system value.

debug_mode – This option will automatically force:

  • staying in foreground
  • set logging level to 4 (debug)
  • set logging to standard error
  • enable core dumping
  • set UDP worker processes to 2
  • set TCP worker processes to 2
  • Default value is false/0 (disabled).

db_version_table – name of the table version to be used by the DB API to check the version of the used tables.

db_default_url – default DB URL to be used by modules if no per-module URL is given.

db_default_url=”mysql://opensips:opensipsrw@localhost/opensips”

db_max_async_connections – Maximum number of TCP connections opened from a single OpenSIPS worker to each individual SQL backend. Default value is 10.
Individual backends are determined from DB URLs as follows: [ scheme, user, pass, host, port, database ]

disable_503_translation – If ‘yes’, OpenSIPS will not translate the received 503 replies into 500 replies .
disable_core_dump – By default core dump limits are set to unlimited or a high enough value. Set this config variable to ‘yes’ to disable core dump-ing (will set core limits to 0).

disable_core_dump=yes //Default value is 'no'.

disable_dns_blacklist– DNS resolver, when configured with failover, can automatically store in a temporary blacklist the failed destinations. This will prevent (for a limited period of time) OpenSIPS to send requests to destination known as failed. So, the blacklist can be used as a memory for the DNS resolver.

The temporary blacklist created by DNS resolver is named “dns” and it is by default selected for usage (no need use the use_blacklist()) function. The rules from this list have a life time of 4 minutes – you can change it at compile time, from resolve.c . Can be ‘yes’ or ‘no’. By default the blacklist is disabled (Default value is ‘yes’).

disable_dns_failover – By default DNS-based failover is enabled. Set this config variable to ‘yes’ to disable the DNS-based failover. This is a global option, affecting the core and the modules also.

disable_stateless_fwd – controls the handling of stateless replies:

  • yes – drop stateless replies if stateless fwd functions (like forward) are not used in script
  • no – forward stateless replies

dns – controls if the SIP server should attempt to lookup its own domain name in DNS. Default is no.

dns_retr_time – Time in seconds before retrying a dns request. Default value is system specific, depends also on the ‘/etc/resolv.conf’ content (usually 5s).

dns_retr_no – Number of dns retransmissions before giving up.

dns_servers_no – How many dns servers from the ones defined in ‘/etc/resolv.conf’ will be used. Default value is to use all of them.

dns_try_ipv6 – If it is set to ‘yes’ and a DNS lookup fails, it will retry it for ipv6 (AAAA record). Default value is ‘no’.

dns_try_naptr – Disables the NAPTR lookups when doing DNS based routing for SIP requests – if disabled, the DNS lookup will start with SRV lookups. By default it is enabled, value ‘yes’.

dns_use_search_list

dst_blacklist – static (read-only) IP/destination blacklist. These lists can be selected from script (at runtime) to filter the outgoing requests, based on IP, protocol, port, etc.

filter out requests going to ips of my gws

dst_blacklist = gw:{( tcp , 192.168.2.200 , 5060 , "" ),( any , 192.168.2.201 , 0 , "" )}

block requests going to prohibited networks

dst_blacklist = net_filter:{ ( any , 192.168.1.120/255.255.255.0 , 0 , "" )}

block message requests with nasty words

dst_blacklist = msg_filter:{ ( any , 192.168.20.0/255.255.255.0 , 0 , "MESSAGE*ugly_word" )}

block requests not going to a specific subnet

dst_blacklist = net_filter2:{ !( any , 192.268.30.0/255.255.255.0 , 0 , "" )}

Each rule is defined by:

  • protocol : TCP, UDP, TLS or “any” for anything
  • port : number or 0 for any
  • ip/mask
  • test patter – is a filename like matching (see “man 3 fnmatch”) applied on the outgoing request buffer (first_line+hdrs+body)

enable_asserts – Set to true in order to enable the assert script statement.

event_pkg_threshold – A number representing the percentage threshold above which the E_CORE_PKG_THRESHOLD event is raised, warning about low amount of free private memory. It accepts integer values between 0 and 100. Default value is 0 ( event disabled ).

event_pkg_threshold = 90

event_shm_threshold
A number representing the percentage threshold above which the E_CORE_SHM_THRESHOLD event is raised, warning about low amount of free shared memory. It accepts integer values between 0 and 100.
Default value is 0 ( event disabled ).

event_shm_threshold = 90

exec_dns_threshold – A number representing the maximum number of microseconds a DNS query is expected to last. Anything above the set number will trigger a warning message to the logging facility. Default value is 0 ( logging disabled ).

exec_dns_threshold = 60000

exec_msg_threshold – A number representing the maximum number of microseconds the processing of a SIP msg is expected to last. Anything above the set number will trigger a warning message to the logging facility. Aside from the message and the processing time, the most time consuming function calls from the script will also be logged. Default value is 0 ( logging disabled ).

exec_msg_threshold = 60000

include_file – load additional routes/blocks with file path

include_file "proxy_regs.cfg"

import_file – Same as include_file but will not throw an error if file is not found.

import_file "proxy_regs.cfg"

listen – Set the network addresses the SIP server should listen to. syntax is protocol:address[:port]

The listen definition may accept several optional parameters for:

configuring an advertised IP and port only for an interface. Syntax “AS 11.22.33.44:5060”
setting a different number of children for this interface only (for UDP, SCTP and HEP_UDP interfaces only). This will override the global “children” parameter. Syntax “use_children 5”
Remember that the above parameters only affect the interface they are configured for; if they are not defined for a given interface, the global values will be used instead.

listen = udp:*
listen = udp:eth1
listen = tcp:eth1:5062
listen = tls:localhost:5061
listen = hep_udp:10.10.10.10:5064
listen = ws:127.0.0.1:5060 use_children 5
listen = sctp:127.0.0.1:5060 as 99.88.44.33:5060 use_children 3
On startup, OpenSIPS reports all the interfaces that it is listening on. The TCP engine processes will be created regardless if you specify only UDP interfaces here.
3.41 log_facility – control the facility for logging in syslog. Default value is LOG_DAEMON.

log_facility=LOG_LOCAL0

3.42 log_level – logging level (how verbose OpenSIPS should be). Higher values make OpenSIPS to print more messages.

log_level=1 — print only important messages (like errors or more critical situations) recommended for running proxy as daemon
log_level=4 — print a lot of debug messages use it only when doing debugging sessions

Actual values are:

-3 – Alert level
-2 – Critical level
-1 – Error level
1 – Warning level
2 – Notice level
3 – Info level
4 – Debug level
The ‘log_level’ parameter is usually used in concordance with ‘log_stderror’ parameter.

Value of ‘log_level’ parameter can also be get and set dynamically using log_level Core MI function or $log_level script variable.
3.43 log_name – Set the id to be printed in syslog. The value must be a string and has effect only when OpenSIPS runs in daemon mode (fork=yes), after daemonize. Default value is argv[0].

log_name=”osips-5070″

3.44 log_stderror – write log messages to standard error. Possible values are:
– “yes” – write the messages to standard error
– “no” – write the messages to syslog , also the default

max_while_loops – maximum loops that can be done within a “while”. Comes as a protection to avoid infinite loops in config file execution. Default is 100.

max_while_loops=200

maxbuffer – size in bytes not to be exceeded during the auto-probing procedure of discovering the maximum buffer size for receiving UDP messages. Default value is 262144.

maxbuffer=65536

mem-group – Defines a group of modules (by name) to get separate memory statistics.In order for the feature to work you have to run “make generate-mem-stats” and complile with the variable SHM_EXTRA_STATS defined and complile with the variable SHM_SHOW_DEFAULT_GROUP definedwill generate the statistics for the default group

mem-group = “interest”: “core” “tm”
mem-group = “runtime”: “dialog” “usrloc” “tm”

mem_warming – Only relevant when the HP_MALLOC compile flag is enabled. If set to “on”, on each startup, OpenSIPS will attempt to restore the memory fragmentation pattern it had before the stop/restart.
Memory warming is useful when dealing with high volumes of traffic (thousands of cps on multi-core machines – the more cores, the more useful), because processes must mutually exclude themselves when chopping up the initial big memory chunk. By performing fragmentation on startup, OpenSIPS will also behave optimally in the first minute(s) after a restart. Fragmentation usually lasts a few seconds (e.g. ~5 seconds on an 8GB shm pool and 2.4Ghz CPU) – traffic will not be processed at all during this period.

mem_warming = on

mem_warming_percentage – How much of OpenSIPS’s memory should be fragmented with the pattern of the previous run, upon a restart.

mem_warming_percentage = 50 //Default value: 75

mem_warming_pattern_file – Default value: “CFG_DIR/mem_warming_pattern”.The memory fragmentation pattern of a previous OpenSIPS run. Used at startup, if mem_warming is enabled.

mem_warming_pattern_file = “/var/tmp/my_memory_pattern”

memdump | mem_dump – Log level to print memory status information (runtime and shutdown). Default: memdump=L_DBG (4)

memlog | mem_lo – Log level to print memory debug info. It has to be less than the value of ‘log_level’ parameter if you want memory info to be logged. Default: memlog=L_DBG (4)

mcast_loopback – If set to ‘yes’, multicast datagram are sent over loopback. Default value is ‘no’.

mcast_loopback=yes

mcast_ttl – Set the value for multicast ttl. Default value is OS specific (usually 1).

mhomed – Set the server to try to locate outbound interface on multihomed host. By default is not (0) – it is rather time consuming.

mhomed=1

mpath – Set the module search path. This can be used to simplify the loadmodule parameter

mpath="/usr/local/lib/opensips/modules"<br> loadmodule "mysql.so"<br> loadmodule "uri.so"<br> loadmodule "uri_db.so"<br> loadmodule "sl.so"<br> loadmodule "tm.so"<br> ...

open_files_limit – If set and bigger than the current open file limit, OpenSIPS will try to increase its open file limit to this number. Note: OpenSIPS must be started as root to be able to increase a limit past the hard limit (which, for open files, is 1024 on most systems).

open_files_limit=2048

poll_method – (deprecated post 2.2) poll method to be used by the I/O internal reactor – by default the best one for the current OS is selected. The available types are: poll, epoll_lt, sigio_rt, select, kqueue, /dev/poll.

Starting with version 2.2, epoll_et is deprecated and if it is used in the script, it will be automatically replaced by epoll_lt.

poll_method=select

port – port the SIP server listens to. The default value for it is 5060.

reply_to_via – If it is set to 1, any local reply is sent to the address advertised in top most Via of the request. Default value is 0 (off).

reply_to_via=0

query_buffer_size -If set to a value greater than 1, inserts to DB will not be flushed one by one. Rows to be inserted will be kept in memory until until they gather up to query_buffer_size rows, and only then they will be flushed to the database.

query_buffer_size=5

query_flush_time – If query_buffer_size is set to a value greater than 1, a timer will trigger once every query_flush_time seconds, ensuring that no row will be kept for too long in memory.

query_flush_time=10

rev_dns – should the SIP server attempt to lookup its own IP address in DNS. If this parameter is set to yes and the IP address is not in DNS a warning is printed on syslog and a “received=” field is added to the via header. Default is no.

server_header – The body of Server header field generated by OpenSIPS when it sends a request as UAS. It defaults to “OpenSIPS (<version> (<arch>/<os>))”.

server_header="Server: My Company SIP Proxy"

server_signature – control “Server” header in any locally generated message. If it is enabled (default=yes) a header is generated as Server: OpenSIPS (0.9.5 (i386/linux))

shm_hash_split_percentage – Only relevant when the HP_MALLOC compile flag is enabled. It controls how many memory buckets will be optimized. (e.g. setting it to 2% will optimize the first 81 most used buckets as frequency). The default value is 1.

shm_secondary_hash_size – Only relevant when the HP_MALLOC compile flag is enabled. It represents the optimization factor of a single bucket (e.g. setting it to 4 will cause the optimized buckets to be further split into 4). The default value is 8.

sip_warning – Can be 0 or 1. If set to 1 (default value is 0) a ‘Warning’ header is added to each reply generated by OpenSIPS. The header contains several details that help troubleshooting using the network traffic dumps.

sip_warning=0

tcp_children – Number of children processes to be created for reading from TCP connections. If no value is explicitly set, the same number of TCP children as UDP children (see “children” parameter) will be used.

tcp_accept_aliases – If enabled, OpenSIPS will enforce RFC 5923 behaviour when detecting an “;alias” Via header field parameter and will reuse any TCP (or TLS, WS, WSS) connection opened for such SIP requests (source IP + Via port + proto) when sending other SIP requests backwards, towards the same (source IP + Via port + proto) pair. Default value 0 (disabled).

tcp_listen_backlog – maximum length for the queue of pending connections for the TCP listeners. Default configured value is 10.

tcp_connect_timeout – Time in milliseconds before an ongoing blocking attempt to connect will be aborted. Default value is 100ms.

tcp_connection_lifetime – Lifetime in seconds for TCP sessions. Default value is defined in tcp_conn.h: define DEFAULT_TCP_CONNECTION_LIFETIME 120.

tcp_connection_lifetime = 3600

tcp_max_connections – maximum number of tcp connections. Default is defined in tcp_conn.h: define DEFAULT_TCP_MAX_CONNECTIONS 2048

tcp_max_connections = 4096

tcp_max_msg_time – maximum number of seconds that a SIP message is expected to arrive via TCP. Default value is 4

tcp_max_msg_time = 8

tcp_no_new_conn_bflag -A branch flag to be used as marker to instruct OpenSIPS not to attempt to open a new TCP connection when delivering a request, but only to reuse an existing one (if available). If no existing conn, a generic send error will be returned.

This is intended to be used in NAT scenarios, where makes no sense to open a TCP connection towards a destination behind a NAT (like TCP connection created during registration was lost, so there is no way to contact the device until it re-REGISTER). Also this can be used to detect when a NATed registered user lost his TCP connection, so that opensips can disable his registration as useless.

 tcp_no_new_conn_bflag = TCP_NO_CONNECT<br> ...<br> route {<br> ...<br> if (isflagset(DST_NATED) &amp;&amp; $proto == "TCP")<br>     setbflag(TCP_NO_CONNECT);<br>     ...<br>     t_relay("0x02"); // no auto error reply<br>     $var(retcode) = $rc;<br>     if ($var(retcode) == -6) {<br>         xlog("unable to send request to destination");<br>         send_reply("404", "Not Found");<br>         exit;<br>     } else if ($var(retcode) &lt; 0) {<br>         sl_reply_error();<br>         exit;<br>     }<br> } 

3.77 tcp_threshold – A number representing the maximum number of microseconds sending of a TCP request is expected to last. Anything above the set number will trigger a warning message to the logging facility. Default value is 0 ( logging disabled ).

tcp_threshold = 60000

tcp_keepalive – Enable or disable TCP keepalive (OS level). Enabled by default.

tcp_keepcount -Number of keepalives to send before closing the connection (Linux only). Default value: 0 (not set). Setting tcp_keepcount to any value will enable tcp_keepalive.

tcp_keepidle – Amount of time before OpenSIPS will start to send keepalives if the connection is idle (Linux only).
Default value: 0 (not set)

tcp_keepidle = 30

tcp_keepinterval – Interval between keepalive probes, if the previous one failed (Linux only).Default value: 0 (not set). Setting tcp_keepinterval to any value will enable tcp_keepalive.

tcp_keepinterval = 10

tls_ca_list

tls_certificate

tls_ciphers_list

tls_domain

tls_handshake_timeout

tls_log

tls_method

tls_port_no

tls_private_key

tls_require_certificate

tls_send_timeout

tls_verify

tos – TOS (Type Of Service) to be used for the sent IP packages (both TCP and UDP).

 tos=IPTOS_LOWDELAY<br> tos=0x10<br> tos=IPTOS_RELIABILITY

user_agent_header – The body of User-Agent header field generated by OpenSIPS when it sends a request as UAC. It defaults to “OpenSIPS (<version> (<arch>/<os>))”.

user_agent_header=”User-Agent: My Company SIP Proxy”

wdir – working directory used by OpenSIPS at runtime.

 wdir="/usr/local/opensips" 

xlog_buf_size – Default value: 4096

Size of the buffer used to print a single line on the chosen logging facility of OpenSIPS. If the buffer is too small, an overflow error will be printed, and the concerned line will be skipped.

xlog_buf_size = 8388608 #given in bytes

xlog_force_color

xlog_default_level -Default value for the logging level of the xlog core function, when the log_level parameter is omitted.

xlog_default_level = 2 #L_NOTICE // Default value: -1

Routes

OpenSIPS routing logic uses several types of routes. Each type of route is triggered by a certain event and allows you to process a certain type of message (request or reply).

  • route
    SIP requests routing. The main ‘route’ block identified by ‘route{…}’ or ‘route[0]{…}’ is executed for each SIP request.
    To send a reply or forward the request, explicit actions must be called inside the route block. in example below which sends 200 ok reply for each options request.
route {
if(is_method("OPTIONS")) {
sl_send_reply("200", "ok");
exit();
}
route(1);
}
route[1] {
forward();
}
  • branch_route
    Handles different branches of a SIP request. if the branch is not dropped the branch will be automatically sent out. It is executed only by TM module after it was armed via t_on_branch(“branch_route_index”).
if (is_method("INVITE|BYE|SUBSCRIBE|UPDATE")) {
if(!t_is_set("branch_route")) t_on_branch("MANAGE_BRANCH");
}
branch_route[MANAGE_BRANCH] {
xdbg("new branch [$T_branch_idx] to $ru\n");
route(NATMANAGE);
}

or lookup location and discard branches where uri matches ip 1.2.3.4 by using drop()

route {
lookup("location");
t_on_branch("op3");
if(!t_relay()) {
sl_send_reply("500", "relaying failed");
}
}
branch_route[op3] {
if(uri=~"1\.2\.3\.4") {
drop();
}
}
  • failure_route
    Failed transaction routing block. It contains a set of actions to be taken each transaction that received only negative replies (>=300) for all branches which completes the transaction. The ‘failure_route’ is executed only by TM module after it was armed via t_on_failure(“failure_route_index”).
if (is_method("INVITE")) {
if(!t_is_set("failure_route")) t_on_failure("MANAGE_FAILURE");
}

failure_route[MANAGE_FAILURE] {
route(NATMANAGE);
if (t_is_canceled()) {
exit;
}
}

or on failure relay to voice mail

route {
lookup("location");
t_on_failure("op1");
if(!t_relay()) {
sl_send_reply("500", "relaying failed");
}
}
failure_route[op1] {
if(is_method("INVITE")) {
t_relay("udp:voicemail.server.com:5060");
}
}
  • onreply_route
    Reply routing block. It can be stateful (if bound to a transaction) or stateless (if global reply route).
    If the reply is not dropped (only provisional replies can be), it will be injected and processed by the transaction engine. There are three types of onreply routes:

global – catches all replies and uses simple definition ‘onreply_route {…}’ or ‘onreply_route[0] {…}’.
Exmaple for “global” reply route set the whole transaction

route {
seturi("sip:bob@opensips.org");  first branch
append_branch("sip:alice@opensips.org");  second branch
t_on_reply("global");
t_on_branch("1");
t_relay();
}

onreply_route {
xlog("OpenSIPS received a reply from $si\n");
}

onreply_route[global] {
if (t_check_status("1[0-9][0-9]")) {
setflag(1);
log("provisional reply received\n");
if (t_check_status("183"))
drop;
}
}

per request/transaction – it catches all received replies belonging to a certain transaction and uses “t_on_reply()” at request time, in REQUEST ROUTE – named ‘onreply_route[N] {…}’.

per branch – it catches only the replies that belong to a certain branch from a transaction via “t_on_reply()” ) at request time, but in BRANCH ROUTE, when a certain outgoing branch is processed – named ‘onreply_route[N] {…}’.
Certain ‘onreply_route’ blocks can be executed by TM module for special replies. For this, the ‘onreply_route’ must be armed for the SIP requests whose replies should be processed within it, via t_on_reply(“onreply_route_index”).

Exmaple of reply route set for this branch only


branch_route[1] {
if ($rU=="alice")
t_on_reply("alice");
}

onreply_route[alice] {
xlog("received reply on the branch from alice\n");
}
  • error_route

executed automatically on meeting and error such as parsing error in SIP request processing, script assert failure. Performs error handling . The Default action is to discard request. In error_route, the following pseudo-variables are available to get access to error details:

$(err.class) - the class of error (now is '1' for parsing errors)
$(err.level) - severity level for the error
$(err.info) - text describing the error
$(err.rcode) - recommended reply code
$(err.rreason) - recommended reply reason phrase
error_route {
xlog("--- error route class=$(err.class) level=$(err.level)
info=$(err.info) rcode=$(err.rcode) rreason=$(err.rreason) ---\n");
xlog("--- error from [$si:$sp]\n+++++\n$mb\n++++\n");
sl_send_reply("$err.rcode", "$err.rreason");
exit;
}
  • local_route

executed automatically as TM created a new request, internally (no UAC side). This is a route intended to be used for message inspection, accounting and for applying last changes on the message headers. Routing and signaling functions are not allowed.

local_route {
if (is_method("INVITE") && $ru=~"@foreign.com") {
append_hf("P-hint: foreign request\r\n");
exit;
}
if (is_method("BYE") ) {
acc_log_request("internally generated BYE");
}
}
  • startup_route
    Executed only once when OpenSIPS is started and before the processing of SIP messages begins. Used in initilization cases cases such as loading some data in the cache.
startup_route {
avp_db_query("select gwlist where ruleid==1",$avp(i:100));
cache_store("local", "rule1", "$avp(i:100)");
}
  • timer_route
    Route executed periodically at a configured interval of time specified next to the name(in seconds).
timer_route[gw_update, 300] {
avp_db_query("select gwlist where ruleid==1",$avp(i:100));
$shv(i:100) =$avp(i:100);
}
  • event_route
    execute script code when an event is triggered. If no way to handle the event specified, default will be synchronously.
    Triggered by the event_route module when an event is raised by the OpenSIPS Event Interface such as event raised by the pike module when it decides an ip should be blocked called E_PIKE_BLOCKED or E_SCRIPT_EVENT etc ( checke events interface for more events)
event_route[E_PIKE_BLOCKED] {
xlog("The E_PIKE_BLOCKED event was raised\n");
}
event_route[E_PIKE_BLOCKED, async] {
xlog("The E_PIKE_BLOCKED event was raised\n");
}

opensipsctlrc

opensipsctlrc file controls the opensipsctl and osipsconsole utilities. It is a shell script utility to manage opensips from command line

opensipsctl can manage

  • Start, stop, and restart
  • Show, grant, and revoke ACLs Add, remove, and list aliases
  • Add, remove, and configure an AVP
  • Low Cost Route (LCR)
  • Remote Party Identity (RPID)
  • Add, remove, and list subscribers
  • Add, remove, and show the usrloc table in-Random Access Memory (RAM)
  • Monitor

Ref :

VOIP Call Metric Monitoring and MOS ( Mean Opinion Score)

Metrics for monitoring a VOIP call can be obtained from any node in media path of the call flow . Essentially used for analysis via calculation and aggregation , and sometimes used for realtime performance tracking and rectification too .

Rating Factor (R-Factor) and Mean Opinion Score (MOS) are two commonly-used measurements of overall VoIP call quality.

R-Factor: A value derived from metrics such as latency, jitter, and packet loss per ITU‑T Recommendation G.107. It assess the quality-of-experience for VoIP calls on your network. Typical scores range from 50 (bad) to 90 (excellent).

  • R factor of 90 , Mos is 4.3 ( Excellent )
  • R factor 50 , Mos is 2.6 ( Bad)

MOS: It is derived from the R-Factor per ITU‑T Recommendation G.10 which measures VoIP call quality. PacketShaper measures MOS using a scale of 10-50. To convert to a standard MOS score (which uses a scale of 1-5), divide the PacketShaper MOS value by 10.

ITU ?
The International Telecommunication Union is the United Nations specialised agency in the field of telecommunications, information and communication technologies (ICTs).

ITU-T ?
TU Telecommunication Standardisation Sector is responsible for studying technical, operating and tariff questions and issuing Recommendations on them with a view to standardising telecommunications on a worldwide basis.

Read more about RTCP and RTCP / AVPF : RealTime Transport protocol (RTP) and RTP control protocol (RTCP )

MOS ( Mean Opinion Score )

MOS is terminology for audio, video and audiovisual quality expressions as per ITU-T P.800.1. It refers to listening, talking or conversational quality, whether they originate from subjective or objective models.

  • Very Good: 4.3-5.0
  • Bad: 3.1-3.6
  • Not Recommenced : 2.6-3.1
  • Very Bad: 1.0-2.6

It provides provisions for identifiers regarding the audio bandwidth, the type of interface (electrical or acoustical) and the video resolution too , such as
MOS-AVQE for audiovisual quality;
MOS-CQE is for estimated conversational quality;
MOS-LQE for listening quality;
MOS-TQE is used for talking quality;
MOS-VQE depicts video quality;

For Audio Signal Speech Quality/ AV
– N denotes audio signals upto narrow-band (300-3400 Hz)
– W is for audio signals upto wideband (50-7000 Hz)
– S for upto super-wideband (20-14000 Hz)
– F is obtained for fullband (10-20000 Hz)

For Listening quality LQO

  • electrical measurement
    performed at electrical interfaces only. In order to predict the listening quality as perceived by the user, assumptions for the terminals are made in terms of intermediate reference system (IRS) or corrected IRS frequency response. A sealed condition between the handset receiver and the user’s ear is assumed.
  • acoustical measurement
    performed at acoustical interfaces. In order to predict the listening quality as perceived by the user, this measurement includes the actual telephone set products provided by the manufacturer or vendor. In combination with the choice of the acoustical receiver in the laboratory test , there will be a more or less leaky condition between the handset’s receiver and the artificial ear.

Conversational Quality / CQ

Arithmetic mean value of subjective judgments on a 5-point ACR quality scale, is calculated.
Talking Quality / TQ

This describes the quality of a telephone call as it is perceived by the talking party only. Factors affecting TQ include echo signal , background noise , double talk etc. It is calculated based on the arithmetic mean value of judgments on a 5-point ACR quality scale.

Video Quality / VQ

To account for differentiation in perceived quality for mobile and fixed devices and to allow for proper handling of different use-cases as
– M for mobile screen such as a smartphone or tablet (approximately 25 cm or less)
– T for PC/TV monitors
It is calculated based on the arithmetic mean value of subjective judgments, typically on a 5-point quality scale

Audio Visual Quality / AVQ

Refers to quality of audio visual stream under corresponding networking conditions. It is also calculated based on the arithmetic mean value of judgments on a 5-point ACR quality scale.

Other parameters also contributing to VoIP metric Analysis

Latency

It is the time required for packets to travel from one end to another, in milliseconds.
If the sum of measured latency is 800 ms and the number of latency samples is 20, then the average latency is 40 ms.
Header of the RTP packets carry timestamps which later can also be used to calculate round-trip time.

Round Trip Time

time taken for data to travel to the target destination and back. It is calculated as when the packet was sent and when acknowledgment for it was received.

Measured in milliseconds (ms), high RTT indicates a poor network quality and would result in the audio lag issue.

RTT can represent full path network latency experienced by the packets and can do away with frequent ICMP ping/echo requests/probes to check network health .

They are used to calculates RTO ( Request transmission timeouts )in TCP transmission ie how much time the sender should wait before retrying to send an unacknowledged packet.

Packet Loss

When packet does not successfully make it to the destination. It could happen due to multiple reasons such as

  • network bandwidth unavailable or network congestion
  • overloading of the buffer such that they do not have enough space to queue the packets or high priority preferences
  • intentionally configuring ACL or firewalls to drop the packets or discarding packets above rate limit by internet service provider
  • CPU unable to cope up with high security networks encryption and decryption speed requirements
  • Low battery on device may cause cause underworking of devices and hence lead to packet loss
  • limitation on physical device like softphone , hardphone or bluetooth headsets or if the hardware is broken at router , switch or cabling
  • for bluetooth headsets distance range could also be problem for weak signals and consequently packets drops
  • network errors as shown under Simple Network Management Protocol (SNMP) issues like FCS Errors, Alignment Errors, Frame Too Longs, MAC Receive Errors, Symbol Errors, Collisions, Carrier Sense Errors, Outbound Errors, Outbound Discards, Inbound Discards, Inbound Errors, and Unknown Protocol errors.
  • radio frequency interference from high voltage systems or microwaves can also cause packet drop in wireless networks

such that the packet can either not arrive or arrive late and be dropped out by the codec . To the listener it would appear like chopped voice or complete dropout for moments .

Obtaining packet loss details

  • Packet loss percentage is performed as per RFC 3550 using RTP header sequence numbers. If packets are missing sequence the media stream monitors flags that as lost packet.
  • It can also be concluded from the difference between total packets and received packets from CDR
  • RTP-XR (RFC-3611) records report real-time drops

Jitter

The variation in the delay of received packets in a flow, measured by comparing the interval when RTP packets were sent to the interval at which they were received.
For instance, if packet #1 and packet #2 leave 30 milliseconds apart and arrive 50 milliseconds apart, then the jitter is 20 milliseconds or if packets transmitted every 15ms and reach destination at every 15ms then there is no variability and the jitter is 0.

Causes jitter

  • Frame bigger than jitter buffer size
  • algorithms to back-of collision by introducing delays in packet transmission in half duplex interfaces
  • even small jitter can get exponentially worse on slow or congestion links
  • jitter can be introduced due to bottlenecks near router buffer, rerouting / parallel routes to the same destination, load-sharing, or route tables changing the path

Handling jitter :

Jitter below 30ms is manageable with the help of jitter buffers in codecs however above that the codec starts to drop the late arrived packets and cannot reassemble / splice up the packets for a smooth media stream effectively, hence causing media quality issues like clipped audio

detecting jitter:

  • looking at inter packet gap in the direction of RTP stream in wireshark
  • RTP-XR (RFC-3611 & RFC-7005) for real-time jitter buffer usage and drops.
  • software based detection : Network sniffers wireshark , path analyser, Application Performance Monitoring (APM) Tools , CDR analyser , Simple Network Management Protocol (SNMP) Collector
MetricGoodAverageBad
Jitter<= 10ms10ms – 30ms>=30ms
Packet Loss< 0.5%0.5% – 0.9%>= 0.9%
Audio Level>-40dB-80dB to -40dB< -80dB
RTT< 200ms200ms – 300ms> 300ms
Range for good bad attributes for calculating mos score

Ref : ITU P.800.1 : Mean opinion score (MOS) terminology 

Methods for objective and subjective assessment of speech and video quality.

Mapping R-value to calculate MOS

To map MOS from R value using above defined metrics , a standard formula is used. First the latency and jitter are added and defined value for computation time is also added , resulting in effective latency

effectiveLatency = latency + jitter * latencyImpact + compTime

Subtracting effective latency from defined R

R = 93 – (effectiveLatency / factorLatencyBased)

Calculate percentage of packet loss

 R = R – (lostPackets * impact)
 MOS = ( (R - 60) * (100 – R) * 0.000007R) + 0.035R + 1)

MOS on RTP engine Kamailio

Minimum edge Values

mos_min_pv
minimum encountered MOS value for the call.
range – 1.0 to 5.0.

mos_min_at_pv
timestamp of when the minimum MOS value was encountered during the call

mos_min_packetloss_pv
amount of packetloss in percent at the time the minimum MOS value was encountered

mos_min_roundtrip_pv
packet round-trip time in milliseconds at the time the minimum MOS value was encountered

mos_min_jitter_pv
amount of jitter in milliseconds at the time the minimum MOS value was encountered

Maximum edge Values

mos_max_pv
maximum encountered MOS value for the call.

mos_max_at_pv
timestamp of when the maximum MOS value was encountered during the cal

mos_max_packetloss_pv
amount of packetloss in percent at maximum MOS moment

mos_max_roundtrip_pv
packet round-trip time in milliseconds at maximum MOS moment

mos_max_jitter_pv
amount of jitter in milliseconds at maximum moment

Average Values

mos_average_pv
average (median) MOS value for the call.
Range – 1.0 through 5.0.

mos_average_packetloss_pv
average (median) amount of packetloss in percent present throughout the call.

mos_average_jitter_pv
average (median) amount of jitter in milliseconds present throughout the call.

mos_average_roundtrip_pv

mos_average_samples_pv
number of samples used to determine the other “average” MOS data points.

Labels

mos_A_label_pv
custom label used in rtpengine signalling.
If set, all the statistics pseudovariables with the A suffix will be filled in with statistics only from the call legs that match the label given in this variable.

A label’s min
mos_min_A_pv
mos_min_at_A_pv
mos_min_packetloss_A_pv
mos_min_jitter_A_pv
mos_min_roundtrip_A_pv

A label’s max
mos_max_A_pv
mos_max_at_A_pv
mos_max_packetloss_A_pv
mos_max_jitter_A_pv
mos_max_roundtrip_A_pv

A label’s average
mos_average_A_pv
mos_average_packetloss_A_pv
mos_average_jitter_A_pv
mos_average_roundtrip_A_pv
mos_average_samples_A_pv

B labels’s min
mos_B_label_pv
mos_min_B_pv
mos_min_at_B_pv
mos_min_packetloss_B_pv
mos_min_jitter_B_pv
mos_min_roundtrip_B_pv

B label’s max
mos_max_B_pv
mos_max_at_B_pv
mos_max_packetloss_B_pv
mos_max_jitter_B_pv
mos_max_roundtrip_B_pv

B label’s average
mos_average_B_pv
mos_average_packetloss_B_pv
mos_average_jitter_B_pv
mos_average_roundtrip_B_pv
mos_average_samples_B_pv

Setting MOS collection on kamailio

set the kamailio config rtpengine params for names the variable the hold specific mos values

modparam("rtpengine", "mos_max_pv", "$avp(mos_max)")
modparam("rtpengine", "mos_average_pv", "$avp(mos_average)")
modparam("rtpengine", "mos_min_pv", "$avp(mos_min)")

modparam("rtpengine", "mos_average_packetloss_pv", "$avp(mos_average_packetloss)")
modparam("rtpengine", "mos_average_jitter_pv", "$avp(mos_average_jitter)")
modparam("rtpengine", "mos_average_roundtrip_pv", "$avp(mos_average_roundtrip)")
modparam("rtpengine", "mos_average_samples_pv", "$avp(mos_average_samples)")

modparam("rtpengine", "mos_min_pv", "$avp(mos_min)")
modparam("rtpengine", "mos_min_at_pv", "$avp(mos_min_at)")
modparam("rtpengine", "mos_min_packetloss_pv", "$avp(mos_min_packetloss)")
modparam("rtpengine", "mos_min_jitter_pv", "$avp(mos_min_jitter)")
modparam("rtpengine", "mos_min_roundtrip_pv", "$avp(mos_min_roundtrip)")

modparam("rtpengine", "mos_max_pv", "$avp(mos_max)")
modparam("rtpengine", "mos_max_at_pv", "$avp(mos_max_at)")
modparam("rtpengine", "mos_max_packetloss_pv", "$avp(mos_max_packetloss)")
modparam("rtpengine", "mos_max_jitter_pv", "$avp(mos_max_jitter)")
modparam("rtpengine", "mos_max_roundtrip_pv", "$avp(mos_max_roundtrip)")

modparam("rtpengine", "mos_A_label_pv", "$avp(mos_A_label)")
modparam("rtpengine", "mos_average_packetloss_A_pv", "$avp(mos_average_packetloss_A)")
modparam("rtpengine", "mos_average_jitter_A_pv", "$avp(mos_average_jitter_A)")
modparam("rtpengine", "mos_average_roundtrip_A_pv", "$avp(mos_average_roundtrip_A)")
modparam("rtpengine", "mos_average_A_pv", "$avp(mos_average_A)")

modparam("rtpengine", "mos_B_label_pv", "$avp(mos_B_label)")
modparam("rtpengine", "mos_average_packetloss_B_pv", "$avp(mos_average_packetloss_B)")
modparam("rtpengine", "mos_average_jitter_B_pv", "$avp(mos_average_jitter_B)")
modparam("rtpengine", "mos_average_roundtrip_B_pv", "$avp(mos_average_roundtrip_B)")
modparam("rtpengine", "mos_average_B_pv", "$avp(mos_average_B)")

For individual leg labbeling fill up the lables

KSR.pv.sets("$avp(mos_A_label)","Aleg_label")
KSR.pv.sets("$avp(mos_B_label)","Bleg_label")

Gather the mos stats from the code . Given exmaple is in Lua.
The values are filled in after invoking“rtpengine_delete”, “rtpengine_query”, or “rtpengine_manage” if the command resulted in a deletion of the call (or call branch).

KSR.log("info", " mos avg " .. KSR.pv.get("$avp(mos_average)"))
KSR.log("info", " mos max " .. KSR.pv.get("$avp(mos_max)"))
KSR.log("info", " mos min " .. KSR.pv.get("$avp(mos_min)"))

KSR.log("info", "mos_average_packetloss_pv" .. KSR.pv.get("$avp(mos_average_packetloss)"))
KSR.log("info", "mos_average_jitter_pv" .. KSR.pv.get("$avp(mos_average_jitter)"))
KSR.log("info", "mos_average_roundtrip_pv" .. KSR.pv.get("$avp(mos_average_roundtrip)"))
KSR.log("info", "mos_average_samples_pv" .. KSR.pv.get("$avp(mos_average_samples)"))

KSR.log("info", "mos_min_pv" .. KSR.pv.get("$avp(mos_min)"))
KSR.log("info", "mos_min_at_pv" .. KSR.pv.get("$avp(mos_min_at)"))
KSR.log("info", "mos_min_packetloss_pv" .. KSR.pv.get("$avp(mos_min_packetloss)"))
KSR.log("info", "mos_min_jitter_pv" .. KSR.pv.get("$avp(mos_min_jitter)"))
KSR.log("info", "mos_min_roundtrip_pv" .. KSR.pv.get("$avp(mos_min_roundtrip)"))

KSR.log("info", "mos_max_pv" .. KSR.pv.get("$avp(mos_max)"))
KSR.log("info", "mos_max_at_pv" .. KSR.pv.get("$avp(mos_max_at)"))
KSR.log("info", "mos_max_packetloss_pv" .. KSR.pv.get("$avp(mos_max_packetloss)"))
KSR.log("info", "mos_max_jitter_pv" .. KSR.pv.get("$avp(mos_max_jitter)"))
KSR.log("info", "mos_max_roundtrip_pv" .. KSR.pv.get("$avp(mos_max_roundtrip)"))

local mos_A_label = KSR.pv.get("$avp(mos_A_label)")
if not (mos_A_label == nil) then
    KSR.log("info", "mos_average_packetloss_A_pv" .. KSR.pv.get("$avp(mos_average_packetloss_A)"))
    KSR.log("info", "mos_average_jitter_A_pv" .. KSR.pv.get("$avp(mos_average_jitter_A)"))
    KSR.log("info", "mos_average_roundtrip_A_pv" .. KSR.pv.get("$avp(mos_average_roundtrip_A)"))
    KSR.log("info", "mos_average_A_pv" .. KSR.pv.get("$avp(mos_average_A)"))
end

local mos_B_label = KSR.pv.get("$avp(mos_B_label)")
if not (mos_B_label == nil) then
    KSR.log("info", "mos_average_packetloss_B_pv" .. KSR.pv.get("$avp(mos_average_packetloss_B)"))
    KSR.log("info", "mos_average_jitter_B_pv" .. KSR.pv.get("$avp(mos_average_jitter_B)"))
    KSR.log("info", "mos_average_roundtrip_B_pv" .. KSR.pv.get("$avp(mos_average_roundtrip_B)"))
    KSR.log("info", "mos_average_B_pv" .. KSR.pv.get("$avp(mos_average_B)"))
end

Sample obtained result for avg

INFO: [core/kemi.c:144]: sr_kemi_core_log(): mos avg 3.8 2(260)

CDR with MOS on freeswitch

<?xmlversion="1.0"?>
					
<cdr core-uuid="[UUID]" switchname="freeswitch">
<channel_data>
	<state>
	<direction>
	<state_number>
	<flags>	
	<caps>
</channel_data>
					
<call-stats>			
	<audio>	
		<inbound>
			<raw_bytes>	
			<media_bytes>
			<packet_count>
			<media_packet_count>		
			<skip_packet_count>
			<jitter_packet_count>
			<dtmf_packet_count>	
			<cng_packet_count>		
			<flush_packet_count>
			<largest_jb_size>
			<jitter_min_variance>
			<jitter_max_variance>
			<jitter_loss_rate>
			<jitter_burst_rate>
			<mean_interval>
			<flaw_total>
			<quality_percentage>
			<mos>
		</inbound>				
		<outbound>
			<raw_bytes>
			<media_bytes>
			<packet_count>
			<media_packet_count>
			<skip_packet_count>
			<dtmf_packet_count>
			<cng_packet_count>
			<rtcp_packet_count>
			<rtcp_octet_count>
		</outbound>	
</audio>
				
<video>	
	<inbound>
		<raw_bytes>
		<media_bytes>
		<packet_count>
		<media_packet_count>
		<skip_packet_count>
		<jitter_packet_count>
		<dtmf_packet_count>
		<cng_packet_count>
		<flush_packet_count>
		<largest_jb_size>
		<jitter_min_variance>
		<jitter_max_variance>
		<jitter_loss_rate>
		<jitter_burst_rate>
		<mean_interval>
		<flaw_total>
		<quality_percentage>
		<mos>
	</inbound>	
	<outbound>
		<raw_bytes>
		<media_bytes>
		<packet_count>
		<media_packet_count>
		<skip_packet_count>
		<dtmf_packet_count>
		<cng_packet_count>
		<rtcp_packet_count>
		<rtcp_octet_count>	
	</outbound>
</video>
</call-stats>
				
<variables>		
<is_outbound><uuid><session_id><text_media_flow><direction><ep_codec_string><channel_name><secondary_recovery_module><verto_dvar_email><verto_dvar_avatar><jsock_uuid_str><verto_user><presence_id><verto_client_address><chat_proto><verto_host><event_channel_cookie><verto_profile_name><record_stereo><default_areacode><transfer_fallback_extension><toll_allow><accountcode><user_context><effective_caller_id_name><effective_caller_id_number><outbound_caller_id_name><outbound_caller_id_number><callgroup><user_name><domain_name><Event-Name><Core-UUID><FreeSWITCH-Hostname><FreeSWITCH-Switchname><FreeSWITCH-IPv4><FreeSWITCH-IPv6><Event-Date-Local><Event-Date-GMT><Event-Date-Timestamp><Event-Calling-File><Event-Calling-Function><Event-Calling-Line-Number><Event-Sequence><verto_remote_caller_id_name><verto_remote_caller_id_number><switch_r_sdp><DP_MATCH><DP_MATCH><call_uuid><open><rtp_secure_media><export_vars><conference_enter_sound><conference_exit_sound><video_banner_text><rtp_use_codec_string><remote_audio_media_flow><audio_media_flow><rtp_audio_recv_pt><rtp_use_codec_name><rtp_use_codec_fmtp><rtp_use_codec_rate><rtp_use_codec_ptime><rtp_use_codec_channels><rtp_last_audio_codec_string><original_read_codec><original_read_rate><write_codec><write_rate><remote_audio_ip><remote_audio_port><remote_audio_rtcp_ip><remote_audio_rtcp_port><dtmf_type><remote_video_media_flow><video_media_flow><video_possible><rtp_video_pt><rtp_video_recv_pt><video_read_codec><video_read_rate><video_write_codec><video_write_rate><rtp_last_video_codec_string><rtp_use_video_codec_name><rtp_use_video_codec_rate><rtp_use_video_codec_ptime><remote_video_ip><remote_video_port><remote_video_rtcp_ip><remote_video_rtcp_port><local_media_ip><local_media_port><advertised_media_ip><rtp_use_timer_name><rtp_use_pt><rtp_use_ssrc><rtp_2833_send_payload><rtp_2833_recv_payload><remote_media_ip><remote_media_port><local_video_ip><local_video_port><rtp_use_video_pt><rtp_use_video_ssrc><rtp_local_sdp_str><current_application_data><current_application><send_silence_when_idle><rtp_has_crypto><endpoint_disposition><conference_name><conference_member_id><conference_moderator><conference_ghost><conference_uuid><video_width><video_height><video_fps><verto_hangup_disposition><read_codec><read_rate><hangup_cause><hangup_cause_q850><digits_dialed><start_stamp><profile_start_stamp><answer_stamp><progress_media_stamp><end_stamp><start_epoch><start_uepoch><profile_start_epoch><profile_start_uepoch><answer_epoch><answer_uepoch><bridge_epoch><bridge_uepoch><last_hold_epoch><last_hold_uepoch><hold_accum_seconds><hold_accum_usec><hold_accum_ms><resurrect_epoch><resurrect_uepoch><progress_epoch><progress_uepoch><progress_media_epoch><progress_media_uepoch><end_epoch><end_uepoch><last_app><last_arg><caller_id><duration><billsec><progresssec><answersec><waitsec><progress_mediasec><flow_billsec><mduration><billmsec><progressmsec><answermsec><waitmsec><progress_mediamsec><flow_billmsec><uduration><billusec><progressusec><answerusec><waitusec><progress_mediausec><flow_billusec><rtp_audio_in_raw_bytes><rtp_audio_in_media_bytes><rtp_audio_in_packet_count><rtp_audio_in_media_packet_count><rtp_audio_in_skip_packet_count><rtp_audio_in_jitter_packet_count><rtp_audio_in_dtmf_packet_count><rtp_audio_in_cng_packet_count><rtp_audio_in_flush_packet_count><rtp_audio_in_largest_jb_size><rtp_audio_in_jitter_min_variance><rtp_audio_in_jitter_max_variance><rtp_audio_in_jitter_loss_rate><rtp_audio_in_jitter_burst_rate><rtp_audio_in_mean_interval><rtp_audio_in_flaw_total><rtp_audio_in_quality_percentage><rtp_audio_in_mos><rtp_audio_out_raw_bytes><rtp_audio_out_media_bytes><rtp_audio_out_packet_count><rtp_audio_out_media_packet_count><rtp_audio_out_skip_packet_count><rtp_audio_out_dtmf_packet_count><rtp_audio_out_cng_packet_count><rtp_audio_rtcp_packet_count><rtp_audio_rtcp_octet_count><rtp_video_in_raw_bytes><rtp_video_in_media_bytes><rtp_video_in_packet_count><rtp_video_in_media_packet_count><rtp_video_in_skip_packet_count><rtp_video_in_jitter_packet_count><rtp_video_in_dtmf_packet_count><rtp_video_in_cng_packet_count><rtp_video_in_flush_packet_count><rtp_video_in_largest_jb_size><rtp_video_in_jitter_min_variance><rtp_video_in_jitter_max_variance><rtp_video_in_jitter_loss_rate><rtp_video_in_jitter_burst_rate><rtp_video_in_mean_interval><rtp_video_in_flaw_total><rtp_video_in_quality_percentage><rtp_video_in_mos><rtp_video_out_raw_bytes><rtp_video_out_media_bytes><rtp_video_out_packet_count><rtp_video_out_media_packet_count><rtp_video_out_skip_packet_count><rtp_video_out_dtmf_packet_count><rtp_video_out_cng_packet_count><rtp_video_rtcp_packet_count><rtp_video_rtcp_octet_count>

</variables>

<app_log>			
	<application app_name="..."app_data="...">
	<application app_name="..."app_data="...">
</app_log>
				
<callflow dialplan="XML" unique-id="[UUID]" profile_index="1">
	
	<extension name="myconference" number="3500">		
		<application app_name="..." app_data="...">
	</extension>	
	<caller_profile>
		<username>
		<dialplan>
		<caller_id_name>
		<caller_id_number>
		<callee_id_name>
		<callee_id_number>
		<ani>
		<aniii>
		<network_addr>
		<rdnis>
		<destination_number>
		<uuid>
		<source>
		<context>
		<chan_name>
	</caller_profile>
				
			
	<times>
		<created_time>
		<profile_created_time>
		<progress_time>	
		<progress_media_time>
		<answered_time>
		<bridged_time>
		<last_hold_time>	
		<hold_accum_time>
		<hangup_time>
		<resurrect_time>	
		<transfer_time>	
	</times>
</callflow>
				
</cdr>
			

References

RTP engine on kamailio SIP server

This article focuses on setting up sipwise rtpegine to proxy rtp traffic from kamailio app server. This is an updated version of the the old article .

RTPengine is a proxy for RTP traffic and other UDP based media traffic over either IPv4 or IPv6. It can even bridge between diff IP networks and interfaces . It can do TOS/QoS field setting. It is Multi-threaded , can advertise different addresses for operation behind NAT.

It bears in-kernel packet forwarding for low-latency and low-CPU performance .

When used with kamailio RTP engine module it adds more features . I wrote an article covering all relevant and important kamailio modules earlier including RTPProxy and RTP engine ;https://telecom.altanai.com/2014/11/18/kamailio-modules/.

  • Full SDP parsing and rewriting
  • Supports non-standard RTCP ports (RFC 3605)
  • ICE (RFC 5245):
    • Bridging between ICE-enabled and ICE-unaware user agents
    • Optionally acting only as additional ICE relay/candidate
    • Optionally forcing relay of media streams by removing other ICE candidates
  • SRTP (RFC 3711):
    • Support for SDES (RFC 4568) and DTLS-SRTP (RFC 5764)
    • AES-CM and AES-F8 ciphers, both in userspace and in kernel
    • HMAC-SHA1 packet authentication
    • Bridging between RTP and SRTP user agents
  • RTCP profile with feedback extensions (RTP/AVPF, RFC 4585 and 5124)
  • Arbitrary bridging between any of the supported RTP profiles (RTP/AVP, RTP/AVPF, RTP/SAVP, RTP/SAVPF)
  • RTP/RTCP multiplexing (RFC 5761) and demultiplexing
  • Breaking of BUNDLE’d media streams (draft-ietf-mmusic-sdp-bundle-negotiation)
  • Recording of media streams, decrypted if possible
  • Transcoding and repacketization
  • Playback of pre-recorded streams/announcements

Sipwise NGCP RTP Engine Source Code

There are 3 parts of the source structure in sipwise NGCP ( Next Generation communication Platform) rtpengine :

1.daemon

The userspace daemon and workhorse, minimum requirement for anything to work. Running make will compile the binary, which will be called rtpengine.

Required packages including their development headers are required to compile the daemon:

  • pkg-config
  • GLib including GThread and GLib-JSON version 2.x
  • zlib
  • OpenSSL
  • PCRE library
  • XMLRPC-C version 1.16.08 or higher
  • hiredis library
  • gperf
  • libcurl version 3.x or 4.x
  • libevent version 2.x
  • libpcap
  • libsystemd
  • MySQL or MariaDB client library (optional for media playback and call recording daemon)
  • libiptc library for iptables management (optional)
  • ffmpeg codec libraries for transcoding (optional) such as libavcodec, libavfilter, libswresample
  • bcg729 for full G.729 transcoding support (optional)

options for make – with_iptables_option , with_transcoding

 with_transcoding=no make 

2.iptables-extension

Required for in-kernel packet forwarding. With the iptables development headers installed, issuing make will compile the plugin for iptables and ip6tables. The file will be called libxt_RTPENGINE.so and needs to be copied into the xtables module directory. The location of this directory can be determined through pkg-config xtables –variable=xtlibdir on newer systems, and/or is usually either /lib/xtables/ or /usr/lib/x86_64-linux-gnu/xtables/.

3.kernel-module

Required for in-kernel packet forwarding. Compilation of the kernel module requires the kernel development headers to be installed in/lib/modules/$VERSION/build/, where $VERSION is the output of the command uname -r.

Successful compilation of the module will produce the file xt_RTPENGINE.ko. The module can be inserted into the running kernel manually through insmod xt_RTPENGINE.ko

It is recommended to copy the module into /lib/modules/$VERSION/updates/, followed by running depmod -a.

After this, the module can be loaded by issuing modprobe xt_RTPENGINE.

Installation

Follow instructions on https://gist.github.com/altanai/0d8cadbe6876d545fd63d6b3e79dcf73

Requirements

sudo su 
apt-get install debhelper iptables-dev libcurl4-openssl-dev libglib2.0-dev  libjson-glib-dev libxmlrpc-core-c3-dev libhiredis-dev build-essential:native
for pcap
apt install ibpcap-dev

some ffmpeg pakages like

apt install libavcodec-dev libavfilter-dev libavformat-dev libavresample-dev  libavutil-dev

for dpkg

libcrypt-openssl-rsa-perl libdigest-crc-perl libio-multiplex-perl libnet-interface-perl libsystemd-dev markdown

for debhelper>10

vi /etc/apt/sources.list

add line

deb http://archive.ubuntu.com/ubuntu xenial-backports main restricted universe multiverse
sudo apt update

check version

apt-cache policy debhelper dh-autoreconf
debhelper:
Installed: 9.20160115ubuntu3
Candidate: 9.20160115ubuntu3
Version table:
10.2.2ubuntu1~ubuntu16.04.1 100
100 http://us-east-1.ec2.archive.ubuntu.com/ubuntu xenial-backports/main amd64 Packages
100 http://archive.ubuntu.com/ubuntu xenial-backports/main amd64 Packages
*** 9.20160115ubuntu3 500
500 http://us-east-1.ec2.archive.ubuntu.com/ubuntu xenial/main amd64 Packages
100 /var/lib/dpkg/status
dh-autoreconf:
Installed: (none)
Candidate: 11
Version table:
12~ubuntu16.04.1 100
100 http://us-east-1.ec2.archive.ubuntu.com/ubuntu xenial-backports/main amd64 Packages
100 http://archive.ubuntu.com/ubuntu xenial-backports/main amd64 Packages
11 500
500 http://us-east-1.ec2.archive.ubuntu.com/ubuntu xenial/main amd64 Packages

Force installing the version from backports repo as it have low priority.

sudo apt install dh-autoreconf=12~ubuntu16.04.1 debhelper=10.2.2ubuntu1~ubuntu16.04.1

so now new priority will be

debhelper:

  Installed: 10.2.2ubuntu1~ubuntu16.04.1
  Candidate: 10.2.2ubuntu1~ubuntu16.04.1
  Version table:
 *** 10.2.2ubuntu1~ubuntu16.04.1 100
        100 http://us-east-1.ec2.archive.ubuntu.com/ubuntu xenial-backports/main amd64 Packages
        100 http://archive.ubuntu.com/ubuntu xenial-backports/main amd64 Packages
        100 /var/lib/dpkg/status
     9.20160115ubuntu3 500
        500 http://us-east-1.ec2.archive.ubuntu.com/ubuntu xenial/main amd64 Packages
dh-autoreconf:
  Installed: 12~ubuntu16.04.1
  Candidate: 12~ubuntu16.04.1
  Version table:
 *** 12~ubuntu16.04.1 100
        100 http://us-east-1.ec2.archive.ubuntu.com/ubuntu xenial-backports/main amd64 Packages
        100 http://archive.ubuntu.com/ubuntu xenial-backports/main amd64 Packages
        100 /var/lib/dpkg/status
     11 500
        500 http://us-east-1.ec2.archive.ubuntu.com/ubuntu xenial/main amd64 Packages

ref :https://askubuntu.com/questions/863221/need-help-building-debhelper-10-2-2-bpo8-from-source

Get sourcecode

cd /usr/local/src
git clone https://github.com/sipwise/rtpengine.git
cd rtpengine
 ./debian/flavors/no_ngcp

use dpkg-checkbuilddeps to find any missing dependices

For missing dependencies

dpkg-checkbuilddeps: error: Unmet build dependencies: libbcg729-dev
remove the encoder for G.729 which is not supported by ffmoeg by exporting varible

export DEB_BUILD_PROFILES="pkg.ngcp-rtpengine.nobcg729"

Ref :ref : https://github.com/sipwise/rtpengine#g729-support

for defaultlibmysqlclient-dev and libiptc-dev

vi debian/control
change from default-libmysqlclient-dev to libmysqlclient-dev, change from libiptcdata-dev to libiptc-dev and install the alternatives such as

apt install libmysqlclient-dev libiptcdata-dev 

Generated deb files should be outside the rtpegine home folder

generated ngcp-rtpegine deb files
cd ..
dpkg -i ngcp-rtpengine-daemon_7.3.0.0+0~mr7.3.0.0_amd64.deb
dpkg -i ngcp-rtpengine-iptables_7.3.0.0+0~mr7.3.0.0_amd64.deb
dpkg -i ngcp-rtpengine-kernel-dkms_7.3.0.0+0~mr7.3.0.0_all.deb
dpkg -i ngcp-rtpengine-kernel-source_7.3.0.0+0~mr7.3.0.0_all.deb
dpkg -i ngcp-rtpengine-recording-daemon_7.3.0.0+0~mr7.3.0.0_amd64.deb
dpkg -i ngcp-rtpengine-utils_7.3.0.0+0~mr7.3.0.0_all.deb
dpkg -i ngcp-rtpengine_7.3.0.0+0~mr7.3.0.0_all.deb
After depackaging

Manual installation and running all test cases

cd rtpengine
make check

If you dont find a package you are looking for , some alternatives are to do apt-cache search like

apt-cache search libavfilter
libavfilter-dev - FFmpeg library containing media filters - development files
libavfilter-ffmpeg5 - FFmpeg library containing media filters - runtime files

or to search in ubuntu packages web https://packages.ubuntu.com/

Running RTPEngine

rtpegine application options

  • -v, –version Print build time and exit
  • –config-file=FILE Load config from this file
  • –config-section=STRING Config file section to use
  • –log-facility=daemon|local0|…|local7 Syslog facility to use for logging
  • -L, –log-level=INT Mask log priorities above this level
  • -E, –log-stderr Log on stderr instead of syslog
  • –no-log-timestamps Drop timestamps from log lines to stderr
  • –log-mark-prefix Prefix for sensitive log info
  • –log-mark-suffix Suffix for sensitive log info
  • -p, –pidfile=FILE Write PID to file
  • -f, –foreground Don’t fork to background
  • -t, –table=INT Kernel table to use
  • -F, –no-fallback Only start when kernel module is available
  • -i, –interface=[NAME/]IP[!IP] Local interface for RTP
  • -k, –subscribe-keyspace=INT INT … Subscription keyspace list
  • -l, –listen-tcp=[IP:]PORT TCP port to listen on
  • -u, –listen-udp=[IP46|HOSTNAME:]PORT UDP port to listen on
  • -n, –listen-ng=[IP46|HOSTNAME:]PORT UDP port to listen on, NG protocol
  • -c, –listen-cli=[IP46|HOSTNAME:]PORT UDP port to listen on, CLI
  • -g, –graphite=IP46|HOSTNAME:PORT Address of the graphite server
  • -G, –graphite-interval=INT Graphite send interval in seconds
  • –graphite-prefix=STRING Prefix for graphite line
  • -T, –tos=INT Default TOS value to set on streams
  • –control-tos=INT Default TOS value to set on control-ng
  • -o, –timeout=SECS RTP timeout
  • -s, –silent-timeout=SECS RTP timeout for muted
  • -a, –final-timeout=SECS Call timeout
  • –offer-timeout=SECS Timeout for incomplete one-sided calls
  • -m, –port-min=INT Lowest port to use for RTP
  • -M, –port-max=INT Highest port to use for RTP
  • -r, –redis=[PW@]IP:PORT/INT Connect to Redis database
  • -w, –redis-write=[PW@]IP:PORT/INT Connect to Redis write database
  • –redis-num-threads=INT Number of Redis restore threads
  • –redis-expires=INT Expire time in seconds for redis keys
  • -q, –no-redis-required Start no matter of redis connection state
  • –redis-allowed-errors=INT Number of allowed errors before redis is temporarily disabled
  • –redis-disable-time=INT Number of seconds redis communication is disabled because of errors
  • –redis-cmd-timeout=INT Sets a timeout in milliseconds for redis commands
  • –redis-connect-timeout=INT Sets a timeout in milliseconds for redis connections
  • -b, –b2b-url=STRING XMLRPC URL of B2B UA
  • –log-facility-cdr=daemon|local0|…|local7 Syslog facility to use for logging CDRs
  • –log-facility-rtcp=daemon|local0|…|local7 Syslog facility to use for logging RTCP
  • –log-facility-dtmf=daemon|local0|…|local7 Syslog facility to use for logging DTMF
  • –log-format=default|parsable Log prefix format
  • -x, –xmlrpc-format=INT XMLRPC timeout request format to use. 0: SEMS DI, 1: call-id only, 2: Kamailio
  • –num-threads=INT Number of worker threads to create
  • –media-num-threads=INT Number of worker threads for media playback
  • -d, –delete-delay=INT Delay for deleting a session from memory.
  • –sip-source Use SIP source address by default
  • –dtls-passive Always prefer DTLS passive role
  • –max-sessions=INT Limit of maximum number of sessions
  • –max-load=FLOAT Reject new sessions if load averages exceeds this value
  • –max-cpu=FLOAT Reject new sessions if CPU usage (in percent) exceeds this value
  • –max-bandwidth=INT Reject new sessions if bandwidth usage (in bytes per second) exceeds this value
  • –homer=IP46|HOSTNAME:PORT Address of Homer server for RTCP stats
  • –homer-protocol=udp|tcp Transport protocol for Homer (default udp)
  • –homer-id=INT ‘Capture ID’ to use within the HEP protocol
  • –recording-dir=FILE Directory for storing pcap and metadata files
  • –recording-method=pcap|proc Strategy for call recording
  • –recording-format=raw|eth File format for stored pcap files
  • –iptables-chain=STRING Add explicit firewall rules to this iptables chain
  • –codecs Print a list of supported codecs and exit
  • –scheduling=default|none|fifo|rr|other|batch|idle Thread scheduling policy
  • –priority=INT Thread scheduling priority
  • –idle-scheduling=default|none|fifo|rr|other|batch|idle Idle thread scheduling policy
  • –idle-priority=INT Idle thread scheduling priority
  • –log-srtp-keys Log SRTP keys to error log
  • –mysql-host=HOST|IP MySQL host for stored media files
  • –mysql-port=INT MySQL port
  • –mysql-user=USERNAME MySQL connection credentials
  • –mysql-pass=PASSWORD MySQL connection credentials
  • –mysql-query=STRING MySQL select query
rtpengine --interface="10.10.10.10" --listen-ng=25061 --listen-cli=25062 --foreground --log-stderr --listen-udp=25060 --listen-tcp=25060

In-Kernal Packet Forwarding

To avoid the overhead involved in processing each individual RTP packet in userspace-only operation, especially as RTP traffic consists of many small packets at high rates, rtpengine provides a kernel module to offload the bulk of the packet forwarding duties from user space to kernel space. This also results in increasing the number of concurrent calls as CPU usage decreases.In-kernel packet forwarding is implemented as an iptables module (x_tables) and has 2 parts – xt_RTPENGINE and plugin to the iptables and ip6tables command-line utilities

Sequence of events for a newly established media stream is then:

  1. Kamailio as SIP proxy controls rtpengine and signals it about a newly established call.
  2. Rtpengine daemon allocates local UDP ports and sets up preliminary forward rules based on the info received from the SIP proxy.
  3. An RTP packet is received on the local port.
  4. It traverses the iptables chains and gets passed to the xt_RTPENGINE module.
  5. The module doesn’t recognize it as belonging to an established stream and thus ignores it.
  6. The packet continues normal processing and eventually ends up in the daemon’s receive queue.
  7. The daemon reads it, processes it and forwards it. It also updates some internal data.
  8. This userspace-only processing and forwarding continues for a little while, during which time information about additional streams and/or endpoints may be obtained from the SIP proxy.
  9. After a few seconds, when the daemon is satisfied with what it has learned about the media endpoints, it pushes the forwarding rules to the kernel.
  10. From this moment on, the kernel module will recognize incoming packets belonging to those streams and will forward them on its own. It will stop those packets from traversing the network stacks any further, so the daemon will not see them any more on its receive queues.
  11. In-kernel forwarding is allowed to cease to work at any given time, either accidentally (e.g. by removal of the iptablesrule) or deliberatly (the daemon will do so in case of a re-invite), in which case forwarding falls back to userspace-only operation.

The Kernel Module

The kernel module supports multiple forwarding tables, identified through their ID number , bydefault 0 to 63

Each running instance of the rtpengine daemon controls one such table. To load use

modprobe xt_RTPENGINE and to unload rmmod xt_RTPENGINE,. With the module loaded, a new directory will appear in /proc/, namely /proc/rtpengine/ , containing pseudo-files, control ( to create and delete forwarding tables) and list ( list of currently active forwarding tables)

To manually create a forwarding table with ID 33, the following command can be used:

echo ‘add 43’ > /proc/rtpengine/control

The iptables module

In order for the kernel module to be able to actually forward packets, an iptables rule must be set up to send packets into the module. Each such rule is associated with one forwarding table. In the simplest case, for forwarding table 33, this can be done through:

iptables -I INPUT -p udp -j RTPENGINE –id 33

To restrict the rules to the UDP port range used by rtpengine, e.g. by supplying a parameter like –dport 30000:40000. If the kernel module receives a packet that it doesn’t recognize as belonging to an active media stream, it will simply ignore it and hand it back to the network stack for normal processing.

A typical start-up sequence including in-kernel forwarding might look like this:

modprobe xt_RTPENGINE
iptables -I INPUT -p udp -j RTPENGINE --id 0
ip6tables -I INPUT -p udp -j RTPENGINE --id 0

ensure that the table we want to use doesn’t exist – usually needed after a daemon restart, otherwise will error

echo 'del 0' > /proc/rtpengine/control

start daemon

/usr/sbin/rtpengine --table=0 --interface=10.64.73.31 --interface=2001:db8::4f3:3d \
--listen-ng=127.0.0.1:2223 --tos=184 --pidfile=/run/rtpengine.pid --no-fallback

Running Multiple Instances

To run multiple instances of rtpengine on the same machine run multiple instances of the daemon using different command-line options ( local addresses and listening ports), together with multiple different kernel forwarding tables.

For example, if one local network interface has address 10.64.73.31 and another has address 192.168.65.73, then the start-up sequence might look like this:

modprobe xt_RTPENGINE
iptables -I INPUT -p udp -d 10.64.73.31 -j RTPENGINE --id 0
iptables -I INPUT -p udp -d 192.168.65.73 -j RTPENGINE --id 1
echo 'del 0' > /proc/rtpengine/control
echo 'del 1' > /proc/rtpengine/control
/usr/sbin/rtpengine --table=0 --interface=<ip> \
--listen-ng=127.0.0.1:2223 --tos=184 --pidfile=/run/rtpengine-10.pid --no-fallback
/usr/sbin/rtpengine --table=1 --interface=<ip_pvy>\
--listen-ng=127.0.0.1:2224 --tos=184 --pidfile=/run/rtpengine-192.pid --no-fallback

With this setup, the SIP proxy can choose which instance of rtpengine to talk to and thus which local interface to use by sending its control messages to either port 2223 or port 2224.

Transcoding

Currently transcoding is supported for audio streams. Can we turned off with with_transcoding=no option in makeFile

Normally rtpengine leaves codec negotiation up to the clients involved in the call and does not interfere. In this case, if the clients fail to agree on a codec, the call will fail.

transcoding options in the ng control protocol,  transcode or ptime . If a codec is requested via the transcode option that was not originally offered, transcoding will be engaged for that call. With transcoding active for a call, all unsupported codecs will be removed from the SDP.

Transcoding happens in userspace only, so in-kernel packet forwarding will not be available for transcoded codecs. Codecs that are supported by both sides will simply be passed through transparently (unless repacketization is active). In-kernel packet forwarding will still be available for these codecs.

codecs supported by rtpengine can be shown with –codecs options

  • rtpengine –codecs
  • PCMA: fully supported
  • PCMU: fully supported
  • G723: fully supported
  • G722: fully supported
  • QCELP: supported for decoding only
  • G729: supported for decoding only
  • speex: fully supported
  • GSM: fully supported
  • iLBC: not supported
  • opus: fully supported
  • vorbis: codec supported but lacks RTP definition
  • ac3: codec supported but lacks RTP definition
  • eac3: codec supported but lacks RTP definition
  • ATRAC3: supported for decoding only
  • ATRAC-X: supported for decoding only
  • AMR: supported for decoding only
  • AMR-WB: supported for decoding only
  • PCM-S16LE: codec supported but lacks RTP definition
  • PCM-U8: codec supported but lacks RTP definition
  • MP3: codec supported but lacks RTP definition

ng Control Protocol

advanced control protocol to pass SDP body from the SIP proxy to the rtpengine daemon, has the body rewritten in the daemon, and then pas back to the SIP proxy to embed into the SIP message. It is  based on the bencode standard and runs over UDP transport.

Each message passed between the SIP proxy and the media proxy contains of two parts: message cookie ( to match requests to responses, and retransmission detection) and bencoded dictionary

The dictionary of each request must contain at least one key called command and corresponding value must be a string and determines the type of message. Currently the following commands are defined:

  • ping
  • offer
  • answer
  • delete
  • query
  • start recording
  • stop recording
  • block DTMF
  • unblock DTMF
  • block media
  • unblock media
  • start forwarding
  • stop forwarding
  • play media
  • stop media

The response dictionary must contain at least one key called result. The value can be either ok (optional key warning) or error( to be accompanied by error-reason ). For the ping command, the additional value pong is allowed.

rtpengine.sample.conf

[rtpengine]

table = 0
no-fallback = false
for userspace forwarding only:
table = -1

// separate multiple interfaces with semicolons:
interface = internal/12.23.34.45;external/23.34.45.54

listen-ng = 127.0.0.1:2223
listen-tcp = 25060
listen-udp = 12222

timeout = 60
silent-timeout = 3600
tos = 184
control-tos = 184
delete-delay = 30
final-timeout = 10800

foreground = false
pidfile = /run/ngcp-rtpengine-daemon.pid
num-threads = 16

port-min = 30000
port-max = 40000
max-sessions = 5000

recording-dir = /var/spool/rtpengine
recording-method = proc
recording-format = raw

redis = 127.0.0.1:6379/5
redis-write = password@x.x.x.x:6379/42
redis-num-threads = 8
no-redis-required = false
redis-expires = 86400
redis-allowed-errors = -1
redis-disable-time = 10
redis-cmd-timeout = 0
redis-connect-timeout = 1000

b2b-url = http://127.0.0.1:8090/
xmlrpc-format = 0

log-level = 6
log-stderr = false
log-facility = daemon
log-facility-cdr = local0
log-facility-rtcp = local1

graphite = 127.0.0.1:9006
graphite-interval = 60
graphite-prefix = foobar.

homer = 123.234.345.456:65432
homer-protocol = udp
homer-id = 2001

sip-source = false
dtls-passive = false

To start the ngcp-rtpengine-daemon service

/etc/init.d/ngcp-rtpengine-daemon start
[ ok ] Starting ngcp-rtpengine-daemon (via systemctl): ngcp-rtpengine-daemon.service.

checking status ngcp-rtpengine-daemonservice

# systemctl status ngcp-rtpengine-daemon.service

● ngcp-rtpengine-daemon.service - NGCP RTP/media Proxy Daemon
   Loaded: loaded (/lib/systemd/system/ngcp-rtpengine-daemon.service; disabled; vendor preset: enabled)
   Active: active (running) since Thu 2019-04-11 10:16:20 UTC; 24s ago
  Process: 13751 ExecStopPost=/usr/sbin/ngcp-rtpengine-iptables-setup stop (code=exited, status=0/SUCCESS)
  Process: 13797 ExecStartPre=/usr/sbin/ngcp-rtpengine-iptables-setup start (code=exited, status=0/SUCCESS)
 Main PID: 13814 (rtpengine)
    Tasks: 19
   Memory: 10.5M
      CPU: 102ms
   CGroup: /system.slice/ngcp-rtpengine-daemon.service
           └─13814 /usr/sbin/rtpengine -f -E --no-log-timestamps --pidfile /run/ngcp-rtpengine-daemon.pid --config-file /etc/rtpengine/rtpengine.conf --table 0

To start recording service

/etc/init.d/ngcp-rtpengine-recording-daemon start

RTP engine receives command offer

Received command 'offer' from :53888
Dump for 'offer' from :53888: {  
    "sdp":"v=0 
 o=- 1554978148897419 1 IN IP4 pvt_ip 
 s=Bria 3 release 3.5.5 stamp 71243 
 c=IN IP4 192.168.1.23 
 t=0 0 
 m=audio 50754 RTP/AVP 0 98 101 
 a=rtpmap:98 ILBC/8000 
 a=rtpmap:101 telephone-event/8000 
 a=fmtp:101 0-15 
 a=sendrecv 
 ",
    "ICE":"remove",
    "record-call":"yes",
    "direction":[  
       "internal",
       "internal"
    ],
    "flags":[  
       "no-rtcp-attribute"
    ],
    "replace":[  
       "origin",
       "session-connection"
    ],
    "transport-protocol":"RTP/AVP",
    "call-id":"732597d6-6d96-485b-b6dc-7d93703c1405",
    "received-from":[  
       "IP4",
       ""
Creating new call
Turning on call recording.
Wrote metadata file to temporary path: /var/spool/rtpengine/tmp/
...

RTP engine receives command delete

Received command 'delete' from :57304
 Dump for 'delete' from :57304: { "call-id": "732597d6-6d96-485b-b6dc-7d93703c1405", "received-from": [ "IP4", "" ], "from-tag": "cb8a1e30", "command": "delete" }
Deleting call branch 'cb8a1e30' (via-branch '')
Call branch 'cb8a1e30' (via-branch '') deleted, no more branches remaining
  Deleting entire call
 INFO: [ID="732597d6-6d96-485b-b6dc-7d93703c1405"]: Final packet stats:
 --- Tag 'cb8a1e30', created 0:05 ago for branch '', in dialogue with ''
 ------ Media #1 (audio over RTP/AVP) using unknown codec
 --------- Port   :10044 <>    :50754, SSRC 0, 0 p, 0 b, 0 e, 5 ts
 freeing send_timer
 --------- Port   :10045 <>    :50755 (RTCP), SSRC 0, 0 p, 0 b, 0 e, 5 ts
 freeing send_timer
 --- Tag '', created 0:05 ago for branch '', in dialogue with 'cb8a1e30'
 ------ Media #1 (audio over RTP/AVP) using unknown codec
--------- Port   :10032 <>          (null):0    , SSRC 0, 0 p, 0 b, 0 e, 5 ts
freeing send_timer
--------- Port   :10033 <>          (null):0     (RTCP), SSRC 0, 0 p, 0 b, 0 e, 5 ts
freeing send_timer
 rtpengine: ci=732597d6-6d96-485b-b6dc-7d93703c1405, created_from=:53888, 
 last_signal=1554978149, 
 tos=0, 
 ml0_start_time=1554978149.645290, 
 ml0_end_time=1554978154.822680, 
 ml0_duration=5.177390, 
 ml0_termination=REGULAR, 
 ml0_local_tag=cb8a1e30, 
 ml0_local_tag_type=FROM_TAG, 
...




Kamailio as Inbound/Outbound proxy or Session Border Controller (SBC)

A typical voice core network consists of B2BUA SIP server with media proxy and media processing units / servers along with components for billing , user profile management , shared memory/ cache , transcoders , call routing logic etc . However a VOIP provider would not want to interface these critical servers to outside world directly , there for a SBC ( Session Border Controller ) comes into picture .

The role of an SBC is to shield the core network from external entities such as user agent’s , carrier network while also providing security , auth and accounting services . In many cases SBC also provides NAT traversal and policy control features ( such as rate limiting , ACL etc ) . In advanced cases transcoding, topology concealment and load balancing is also achievable via a SBC such as Kamailio .

Following sections are usecases / features kamailio can extend to. Routing scripts at https://github.com/altanai/kamailioexamples

Block user based on excessive REGISTER request  till an expiry time

For instance to block DDOS attacks , kamailio can check for the number of register requests a user sends and block above a threshold number subsequently .

if($sht(auth_block_list=>$au::auth_count)==30){
    $var(block) = $Ts - 900;
    $var(expire) = $Ts - 300;

    if($sht(auth_block_list=>$au::last_block) > $var(block)){
        xlog("L_INFO", "$fU@$fd - REGISTER - $au User Already Blocked for Exceeded Register Requests.\n");
        sl_send_reply("403", "Already Blocked Forbidden");
        exit;
    } else if($sht(auth_block_list=>$au::last_auth) > $var(expire)) {
        $sht(auth_block_list=>$au::last_block) = $Ts;
        xlog("L_INFO", "$fU@$fd - REGISTER - $au User Blocked for Exceeded Register Requests.\n");
        sl_send_reply("403", "Blocked Forbidden");
        exit;
    } else {
        $sht(auth_block_list=>$au::auth_count) = 0;
    } 
}

More information on kamailio security can be found on https://telecom.altanai.com/2018/02/17/kamailio-security/. It includes Sanity checks for incoming SIP requests ,Access Control Lists and Permissions , Hiding Topology Details,Anti Flood and Traffic Monitoring and Detection

Anti Flood with Pike Module

To be on edge of a voip pltform , a SIP server must keep trac of all incoming request and their sources. Blocking the ones which exceed the limit or appear like a dos attack. Pike module reports high traffic from an IP if detected.

A sample script to detect high traffic from an IP and add it to ban list for a while . But exclude the known ip sources such as PSTN gateways etc

#!ifdef WITH_ANTIFLOOD
loadmodule "htable.so"
loadmodule "pike.so"
#!endif
...
# ----- pike params -----
modparam("pike", "sampling_time_unit", 2)
modparam("pike", "reqs_density_per_unit", 16)
modparam("pike", "remove_latency", 4)
...
route[REQINIT] {
...
if(src_ip!=myself) {
	if($sht(ipban=>$si)!=$null) {
		# ip is already blocked
		xdbg("request from blocked IP - $rm from $fu (IP:$si:$sp)\n");
		exit;
	}
	if (!pike_check_req()) {
		xlog("L_ALERT","ALERT: pike blocking $rm from $fu (IP:$si:$sp)\n");
		$sht(ipban=>$si) = 1;
		exit;
	}
}

Access Control List with Permission Module

permission module handles ACL by storing permission rules in plaintext configuration files , hosts.allow and hosts.deby by tcpd.

#!ifdef WITH_IPAUTH
loadmodule "permissions.so"
#!endif
...
# ----- permissions params -----
#!ifdef WITH_IPAUTH
modparam("permissions", "db_url", DBURL)
modparam("permissions", "db_mode", 1)
#!endif
..
#!ifdef WITH_IPAUTH
    if((!is_method("REGISTER")) && allow_source_address()) {
        # source IP allowed
        return;
    }
#!endif

Functions

Call Routing

if (allow_routing("rules.allow", "rules.deny")) {
    t_relay();
};

Registration permissions

if (method=="REGISTER") {
    if (allow_register("register")) {
        save("location");
        exit;
    } else {
        sl_send_reply("403", "Forbidden");
    };
};

URI permissions

if (allow_uri("basename", "$rt")) {  // Check Refer-To URI
    t_relay();
};

Address permissions

// check if sourec ip/port is in group 1
if (!allow_address("1", "$si", "$sp")) {
    sl_send_reply("403", "Forbidden");
};

Trusted Requests

if (allow_trusted("$si", "$proto")) {
    t_relay();
};

checks protocols which could be one of the “any”, “udp, “tcp”, “tls”, “ws”, “wss” and “sctp”.

Perform Load Balancing with Dispatcher Module

Load balancing is critical to a production ready system to provide High availability and load sharing among available servers. This could be either stateless or stateful where they use call state tracking

Dispatcher module in Kamailio lends capabilities of SIP traffic dispatcher to it. It can load routes to gateways or destination sets from any storage source such as mysql , psql database or even plain text file (modparam("dispatcher", "db_url", <datasource_name>).

It can also assign priority for routing sip traffic to it ( modparam("dispatcher", "priority_col", "dstpriority"))

To discover active of inactive gateways it uses TM module. One can choose one among many algorithms to share the load , like

  • 0 – hash over callid
  • 1 – hash over from URI
  • 2 – hash over to URI
  • 3 – hash over request-URI
  • 4 – round-robin (next destination)
  • 5 – hash over authorization-username
  • 6 – random destination (using rand())
  • 7 – hash over the content of PVs string
  • 8 – select destination sorted by priority attribute value (serial forking ordered by priority).
  • 9 – use weight based load distribution . Needs attribute ‘weight’ per each address
  • 10 – call load distribution ie route to one that has the least number of calls associated
  • 11 – relative weight based load distribution(rweight)
  • 12 – dispatch to all destination in setid at once (parallel forking).
  • x – if the algorithm is not implemented, the first entry in set is chosen.

some attributes passed with each destination set

  • duid – identify a destination (gateway address). Practically the load within the group is associated with this value.
  • maxload – upper limit of active calls per destination
  • weight – percent of calls to be sent to that gateways
  • rweight – relative weight based load distribution.
  • socket – sending socket for the gateway including keepalives
  • ping_from – from URI in OPTIONS keepalives

Active host usage probability is, rweight/(SUM of all active host rweights in destination group). recalculation is fired as host enables or disables.

Every destination has congestion threshold(weight) and after enabling c (congestion control), rweight is also used to control congestion tolerance lowering the weight by 1 as congestion is detected.

EWMA ( exponential weighted moving average ) is speed at which the older samples are dampened.

nametypesizedefaultnullkeyextra
idunsigned int10noprimaryauto
increment
setidintnot specified0no
destinationstring192“”no
flagintnot specified“”no
priorityintnot specified0no
attrsstring1980no
descriptionstring64“”no

To insert into dispatcher

INSERT INTO "dispatcher" VALUES(1,1,'sip:192.168.0.1:5060',0,12,'rweight=50;weight=50;cc=1;','');

set ping gateway once per second

modparam("dispatcher", "ds_ping_interval", 1)

enabling congestion metrics

modparam("dispatcher", "ds_ping_latency_stats", 1)

latency estimator

modparam("dispatcher", "ds_latency_estimator_alpha", 900)
loadmodule "dispatcher.so"
...
# ----- dispatcher params ----- 
modparam("dispatcher", "db_url", DBURL) 
modparam("dispatcher", "table_name", "dispatcher") modparam("dispatcher", "flags", 2) 
modparam("dispatcher", "dst_avp", "$avp(AVP_DST)") modparam("dispatcher", "grp_avp", "$avp(AVP_GRP)") modparam("dispatcher", "cnt_avp", "$avp(AVP_CNT)") modparam("dispatcher", "sock_avp", "$avp(AVP_SOCK)")
...

request_route {
# do checks , indialog etc ...
# dispatch destinations 
route(DISPATCH); 
}

# Dispatch requests
route[DISPATCH] {
     # round robin dispatching on gateways group '1'
     if(!ds_select_dst("1", "4")) {
         send_reply("404", "No destination");
         exit;
     }
     xlog("L_DBG", "--- SCRIPT: going to <$ru> via <$du>\n");
     t_on_failure("RTF_DISPATCH");
     route(RELAY);
     exit;
 }


# Try next destinations in failure route, except if session gets cancelled 
failure_route[RTF_DISPATCH] {
     if (t_is_canceled()) {
         exit;
     }
     # next DST - only for 500 or local timeout
     if (t_check_status("500") or (t_branch_timeout() and !t_branch_replied())) {
         if(ds_next_dst()) {
             t_on_failure("RTF_DISPATCH");
             route(RELAY);
             exit;
         }
     }
 }

More on Kamailio Call routing and Control

PSTN gateway routing

-tbd

Kamailio basic setup as proxy for FreeSWITCH

I have added a detailed description of how kamalio based SIP servers can function as proxy / SBC for SIP Application server which could be an enterprise PBX or a full fledged Telecom Application Server such as Asterix , Freeswitch , Oracle Weblogic, telestax sip server etc

Kamailio basic setup as proxy for FreeSWITCH

References

Freeswitch PBX system

Setting up a in house hosted Enterprise PBX system for within enterprise communication .

Installation of Freeswitch on hosted server

source code

apt-get install git
git clone https://stash.freeswitch.org/scm/fs/freeswitch.git

verify installation by checking version

freeswitch -version
FreeSWITCH version: 1.9.0-742-8f1b7e0~64bit (-742-8f1b7e0 64bit)

post installation

optional arguments you can pass to freeswitch:
-nf — no forking
-reincarnate — restart the switch on an uncontrolled exit
-reincarnate-reexec — run execv on a restart (helpful for upgrades)
-u [user] — specify user to switch to
-g [group] — specify group to switch to
-core — dump cores
-help — this message
-version — print the version and exit
-rp — enable high(realtime) priority settings
-lp — enable low priority settings
-np — enable normal priority settings
-vg — run under valgrind
-nosql — disable internal sql scoreboard
-heavy-timer — Heavy Timer, possibly more accurate but at a cost
-nonat — disable auto nat detection
-nonatmap — disable auto nat port mapping
-nocal — disable clock calibration
-nort — disable clock clock_realtime
-stop — stop freeswitch
-nc — do not output to a console and background
-ncwait — do not output to a console and background but wait until the system is ready before exiting (implies -nc)
-c — output to a console and stay in the foreground

Options to control locations of files:
-base [basedir] — alternate prefix directory
-cfgname [filename] — alternate filename for FreeSWITCH main configuration file
-conf [confdir] — alternate directory for FreeSWITCH configuration files
-log [logdir] — alternate directory for logfiles
-run [rundir] — alternate directory for runtime files
-db [dbdir] — alternate directory for the internal database
-mod [moddir] — alternate directory for modules
-htdocs [htdocsdir] — alternate directory for htdocs
-scripts [scriptsdir] — alternate directory for scripts
-temp [directory] — alternate directory for temporary files
-grammar [directory] — alternate directory for grammar files
-certs [directory] — alternate directory for certificates
-recordings [directory] — alternate directory for recordings
-storage [directory] — alternate directory for voicemail storage
-cache [directory] — alternate directory for cache files
-sounds [directory] — alternate directory for sound files

Tracing SIP messages and Freeswitch processing for call from external user to internal user .Freeswitch acts as B2BUA

Receives incoming Call INVITE

recv 823 bytes from tcp/[caller_ip]:35365 at 09:55:07.936234:
   ------------------------------------------------------------------------
   INVITE sip:to_number@sometelco.com:5060 SIP/2.0
   Via: SIP/2.0/TCP 192.168.1.23:55934;branch=z9hG4bK-524287-1---cc11593581af6519;rport
   Max-Forwards: 70
   Contact: <sip:from_number@192.168.1.23:55934;transport=tcp>
   To: <sip:to_number@sometelco.com:5060>
   From: "from_number"<sip:from_number@sometelco.com:5060>;tag=47a61272
   Call-ID: 94385YTY3ODNlNzE1YjE5MmY4NmQ3ZWUyZDAzM2E0YzBkM2I
   CSeq: 1 INVITE
   Allow: OPTIONS, SUBSCRIBE, NOTIFY, INVITE, ACK, CANCEL, BYE, REFER, INFO
   Content-Type: application/sdp
   Supported: replaces
   User-Agent: X-Lite release 5.4.0 stamp 94385
   Content-Length: 208

   v=0
   o=- 1553248503383592 1 IN IP4 192.168.1.23
   s=X-Lite release 5.4.0 stamp 94385
   c=IN IP4 192.168.1.23
   t=0 0
   m=audio 49874 RTP/AVP 8 101
   a=rtpmap:101 telephone-event/8000
   a=fmtp:101 0-15
   a=sendrecv
   ------------------------------------------------------------------------

checks with ACL for permission and set NAT. Isolate SDP for processing.

New Channel sofia/internal/from_number@sometelco.com:5060 [a8a2003f-5755-40fe-ab63-aab2f5264886]

Running State Change CS_NEW (Cur 1 Tot 274)
receiving invite from caller_ip:35365 version: 1.9.0 -742-8f1b7e0 64bit
IP caller_ip Approved by acl "domains[]". Access Granted.
Setting NAT mode based on nat.auto
Channel sofia/internal/from_number@sometelco.com:5060 entering state [received][100]
Remote SDP:
v=0
o=- 1553248503383592 1 IN IP4 192.168.1.23
s=X-Lite release 5.4.0 stamp 94385
c=IN IP4 192.168.1.23
t=0 0
m=audio 49874 RTP/AVP 8 101
a=rtpmap:101 telephone-event/8000
a=fmtp:101 0-15

mainatin and Updates call-state (switch_core_state_machine ) CS_NEW -> CS_INIT -> CS_ROUTING -> RINGING and send 100 trying to caller

State Change CS_NEW -> CS_INIT
State NEW
Running State Change CS_INIT (Cur 1 Tot 274)
State INIT
SOFIA INIT
Standard INIT
State Change CS_INIT -> CS_ROUTING
State INIT going to sleep
Running State Change CS_ROUTING (Cur 1 Tot 274)
Change DOWN -> RINGING
State ROUTING
send 413 bytes to tcp/[caller_ip]:35365 at 09:55:07.937474:
   ------------------------------------------------------------------------
   SIP/2.0 100 Trying
   Via: SIP/2.0/TCP 192.168.1.23:55934;branch=z9hG4bK-524287-1---cc11593581af6519;rport=35365;received=caller_ip
   From: "from_number"<sip:from_number@sometelco.com:5060>;tag=47a61272
   To: <sip:to_number@sometelco.com:5060>
   Call-ID: 94385YTY3ODNlNzE1YjE5MmY4NmQ3ZWUyZDAzM2E0YzBkM2I
   CSeq: 1 INVITE
   User-Agent: FreeSWITCH-mod_sofia/1.9.0-742-8f1b7e0~64bit
   Content-Length: 0

   ------------------------------------------------------------------------

checks dialplan to route incoming call. In this case action is to bridge the incoming call to internal user

mod_sofia.c:154 sofia/internal/from_number@sometelco.com:5060 SOFIA ROUTING
switch_core_state_machine.c:236 sofia/internal/from_number@sometelco.com:5060 Standard ROUTING

mod_dialplan_xml.c:637 Processing from_number <from_number>->to_number in context public
Dialplan: sofia/internal/from_number@sometelco.com:5060 parsing [public->dialplan_cutsom] continue=false
Dialplan: sofia/internal/from_number@sometelco.com:5060 Regex (PASS) [dialplan_cutsom] destination_number(to_number) =~ /^(\d+)$/ break=on-false
Dialplan: sofia/internal/from_number@sometelco.com:5060 Action log(INFO ***** Forwarding calls to gateway ****** ) 
Dialplan: sofia/internal/from_number@sometelco.com:5060 Action bridge({sip_auth_username=user,sip_auth_password=pass,sip_route_uri=sip:to_number@ip_addr;transport=tls,sip_invite_req_uri=sip:to_number@sometelco.com;transport=tls}sofia/external/to_number@ip_addr) 

update call state CS_ROUTING -> CS_EXECUTE

State Change CS_ROUTING -> CS_EXECUTE
State ROUTING going to sleep
Running State Change CS_EXECUTE (Cur 1 Tot 274)
State EXECUTE
SOFIA EXECUTE

set the crypto and codecs for the new call

switch_ivr_originate.c:2159 Parsing global variables
switch_channel.c:1104 New Channel sofia/external/to_number@ip_addr [cc1ae238-9efd-4f51-93e9-05abd48bea4d]
mod_sofia.c:5026 (sofia/external/to_number@ip_addr) State Change CS_NEW -> CS_INIT
switch_core_state_machine.c:584 (sofia/external/to_number@ip_addr) Running State Change CS_INIT (Cur 2 Tot 275)
switch_core_state_machine.c:627 (sofia/external/to_number@ip_addr) State INIT
mod_sofia.c:93 sofia/external/to_number@ip_addr SOFIA INIT
Set Local audio crypto Key [1 AEAD_AES_256_GCM_8 inline:ZbEHd76sP6FZSO9AYcqryybaA4HY3O5p2Uo+e1gmmfVaZCEic6cvKyArhMU]
Set Local video crypto Key [1 AEAD_AES_256_GCM_8 inline:Ehr3LoDR8Ur+wtNAMqoqIDn3S7V2inE2/n++awxS6/1P2ijcqfk12+LM/Pc]
Set Local text crypto Key [1 AEAD_AES_256_GCM_8 inline:NVSfjOmSS5BaP/5yqg+SOXcqvEFTHHrC8R5AYkkClXLuNOXYoaUYlrIWeW0]
Set Local audio crypto Key [2 AEAD_AES_128_GCM_8 inline:ePH/F2Qw5+zi8c7tkBb6Y2AQE5uevp+jWUkjgQ]
Set Local video crypto Key [2 AEAD_AES_128_GCM_8 inline:YWdfNLSx6MqG9WQ3TmsV/cSBDqjRUAbHE0rRCg]
Set Local text crypto Key [2 AEAD_AES_128_GCM_8 inline:DFXOP2V2Ep6FoHNz5HIMrm0cu6Za8I5wOI/hUw]
Set Local audio crypto Key [3 AES_CM_256_HMAC_SHA1_80 inline:SG5rYx3GSR2imutYQ+LzqHufG9UkG3n/SfmFHFOG/r75v2pwf2lG7Qpup+J0mw]
Set Local video crypto Key [3 AES_CM_256_HMAC_SHA1_80 inline:LkU3i9MD25k2wtTfSXUvhlxo66GtMWnXkKoxSdgRZyANoeOhufYnXzbXDo+7+w]
Set Local text crypto Key [3 AES_CM_256_HMAC_SHA1_80 inline:AUgUOVmFunzotvwZ6KuMDnBRR2XKk1DsX2qg465MsT6OAxHc2qKBFpeQEpxrqA]
Set Local audio crypto Key [4 AES_CM_192_HMAC_SHA1_80 inline:2PVBBJEp4QcTzTf4Th8Ag/7KiVPmrYb/FCowiRb6yAuTO/kxQLc]
Set Local video crypto Key [4 AES_CM_192_HMAC_SHA1_80 inline:OiFbZQ6mWuf5sHJT1pFPU6EWxEvQAO/0rcp8uGMf79k7RSR3IQA]
Set Local text crypto Key [4 AES_CM_192_HMAC_SHA1_80 inline:XyednWJmzRfsWQOgdhKaMeOeE/OLmnwo6hVEZWl4OJdKdgK6TVc]
Set Local audio crypto Key [5 AES_CM_128_HMAC_SHA1_80 inline:Yd4L5Qi7A/8xay5ZHWR1jKk9j5Kvy9s2Zo3NOES2]
Set Local video crypto Key [5 AES_CM_128_HMAC_SHA1_80 inline:ImgbbD6cnhnH19O1knP5SSIUULsZTaNJJIUepxt0]
Set Local text crypto Key [5 AES_CM_128_HMAC_SHA1_80 inline:V7+IbSZmTdQNjh/upUZ5TFDSlgarhDTVfV+AcUA+]
Set Local audio crypto Key [6 AES_CM_256_HMAC_SHA1_32 inline:JI+s9uFdZ3JfZmRRfwHr0OrpyZdtUXmMC0WRIZow1EuXRB9xKFRBk6KmSWomqQ]
Set Local video crypto Key [6 AES_CM_256_HMAC_SHA1_32 inline:MX6CGCrMEioUCJsIOCxRqlHOx4mUYRw4DslpY25njZQAkH6MgG/9hp7G8xr44A]
Set Local text crypto Key [6 AES_CM_256_HMAC_SHA1_32 inline:ikCz2sYLGoMO+dlrZj+znlQ3djAkGSYzSLLu6Az8u2THWPgnkFJXVgXSxHOaHw]
Set Local audio crypto Key [7 AES_CM_192_HMAC_SHA1_32 inline:5JzlrMywFZhHuNLWPG/HBrUi/Zcg414Q7ZfSaJQnUF5N9APy+GQ]
Set Local video crypto Key [7 AES_CM_192_HMAC_SHA1_32 inline:K0dZtwH1Q7AuSMBPPUesy047c4nAF+QuFsVvGdf3fYJDOD0Uwxo]
Set Local text crypto Key [7 AES_CM_192_HMAC_SHA1_32 inline:96SwyWAdV1a+BU3UbiX1PHdkRlSS4RtmwPWNPbCR3NDm1MyBh58]
Set Local audio crypto Key [8 AES_CM_128_HMAC_SHA1_32 inline:/RLYPhZs07WCCBRY8tWNTJemT/IFq1VPHGHmGvnG]
Set Local video crypto Key [8 AES_CM_128_HMAC_SHA1_32 inline:mQlgScFq1iMKEW8vobzwhmN9TWSmVblAv9u7c1/c]
Set Local text crypto Key [8 AES_CM_128_HMAC_SHA1_32 inline:WAQveMfrQkPBcfqH2qLmuzY63VLfT+N30/YLyuqE]
Set Local audio crypto Key [9 AES_CM_128_NULL_AUTH inline:f2fx2ekxPG3GTwTYARtquNJ87qO0Q5ei47KYlo9K]
Set Local video crypto Key [9 AES_CM_128_NULL_AUTH inline:qpAkfc1bWnZ0Y/1ql+dNvhIGgxxWZoVltnRD5kqn]
Set Local text crypto Key [9 AES_CM_128_NULL_AUTH inline:LyhSlzI3X38WKPwZ83035Ddvse4J/2KnKoydo2FD]

set proxy route and create SDP for sending invite to bridged client

sofia_glue.c:1268 sip:to_number@ip_addr;transport=tls Setting proxy route to sofia/external/to_number@ip_addr
sofia_glue.c:1299 sofia/external/to_number@ip_addr sending invite version: 1.9.0 -742-8f1b7e0 64bit
Local SDP:
v=0
o=FreeSWITCH 1553228435 1553228436 IN IP4 via_addr
s=FreeSWITCH
c=IN IP4 via_addr
t=0 0
m=audio 20072 RTP/SAVP 8 101
a=rtpmap:8 PCMA/8000
a=rtpmap:101 telephone-event/8000
a=fmtp:101 0-16
a=crypto:1 AEAD_AES_256_GCM_8 inline:ZbEHd76sP6FZSO9AYcqryybaA4HY3O5p2Uo+e1gmmfVaZCEic6cvKyArhMU
a=crypto:2 AEAD_AES_128_GCM_8 inline:ePH/F2Qw5+zi8c7tkBb6Y2AQE5uevp+jWUkjgQ
a=crypto:3 AES_CM_256_HMAC_SHA1_80 inline:SG5rYx3GSR2imutYQ+LzqHufG9UkG3n/SfmFHFOG/r75v2pwf2lG7Qpup+J0mw
a=crypto:4 AES_CM_192_HMAC_SHA1_80 inline:2PVBBJEp4QcTzTf4Th8Ag/7KiVPmrYb/FCowiRb6yAuTO/kxQLc
a=crypto:5 AES_CM_128_HMAC_SHA1_80 inline:Yd4L5Qi7A/8xay5ZHWR1jKk9j5Kvy9s2Zo3NOES2
a=crypto:6 AES_CM_256_HMAC_SHA1_32 inline:JI+s9uFdZ3JfZmRRfwHr0OrpyZdtUXmMC0WRIZow1EuXRB9xKFRBk6KmSWomqQ
a=crypto:7 AES_CM_192_HMAC_SHA1_32 inline:5JzlrMywFZhHuNLWPG/HBrUi/Zcg414Q7ZfSaJQnUF5N9APy+GQ
a=crypto:8 AES_CM_128_HMAC_SHA1_32 inline:/RLYPhZs07WCCBRY8tWNTJemT/IFq1VPHGHmGvnG
a=crypto:9 AES_CM_128_NULL_AUTH inline:f2fx2ekxPG3GTwTYARtquNJ87qO0Q5ei47KYlo9K
a=ptime:20
a=sendrecv
m=audio 20072 RTP/AVP 8 101
a=rtpmap:8 PCMA/8000
a=rtpmap:101 telephone-event/8000
a=fmtp:101 0-16
a=ptime:20
a=sendrecv

attach the SDP to INVITE and proceed forwarding INVITE to callee

send 1988 bytes to tls/[ip_addr]:5061 at 09:55:07.939831:
   ------------------------------------------------------------------------
   INVITE sip:to_number@sometelco.com;transport=tls SIP/2.0
   Via: SIP/2.0/TLS via_addr:5080;rport;branch=z9hG4bK21Qm9U3eHX0Nc
   Max-Forwards: 69
   From: "from_number" <sip:from_number@via_addr>;tag=8jByBXa2pF1Fj
   To: <sip:to_number@ip_addr>
   Call-ID: 6a827514-c72b-1237-8aab-02a933b32da0
   CSeq: 2070461 INVITE
   Contact: <sip:mod_sofia@via_addr:5080>
   User-Agent: FreeSWITCH-mod_sofia/1.9.0-742-8f1b7e0~64bit
   Allow: INVITE, ACK, BYE, CANCEL, OPTIONS, MESSAGE, INFO, UPDATE, REGISTER, REFER, NOTIFY
   Supported: timer, path, replaces
   Allow-Events: talk, hold, conference, refer
   Content-Type: application/sdp
   Content-Disposition: session
   Content-Length: 1162
   X-FS-Support: update_display,send_info
   Remote-Party-ID: "from_number" <sip:from_number@via_addr>;party=calling;screen=yes;privacy=off

   v=0
   o=FreeSWITCH 1553228435 1553228436 IN IP4 via_addr
   s=FreeSWITCH
   c=IN IP4 via_addr
   t=0 0
   m=audio 20072 RTP/SAVP 8 101
   a=rtpmap:8 PCMA/8000
   a=rtpmap:101 telephone-event/8000
   a=fmtp:101 0-16
   a=crypto:1 AEAD_AES_256_GCM_8 inline:ZbEHd76sP6FZSO9AYcqryybaA4HY3O5p2Uo+e1gmmfVaZCEic6cvKyArhMU
   a=crypto:2 AEAD_AES_128_GCM_8 inline:ePH/F2Qw5+zi8c7tkBb6Y2AQE5uevp+jWUkjgQ
   a=crypto:3 AES_CM_256_HMAC_SHA1_80 inline:SG5rYx3GSR2imutYQ+LzqHufG9UkG3n/SfmFHFOG/r75v2pwf2lG7Qpup+J0mw
   a=crypto:4 AES_CM_192_HMAC_SHA1_80 inline:2PVBBJEp4QcTzTf4Th8Ag/7KiVPmrYb/FCowiRb6yAuTO/kxQLc
   a=crypto:5 AES_CM_128_HMAC_SHA1_80 inline:Yd4L5Qi7A/8xay5ZHWR1jKk9j5Kvy9s2Zo3NOES2
   a=crypto:6 AES_CM_256_HMAC_SHA1_32 inline:JI+s9uFdZ3JfZmRRfwHr0OrpyZdtUXmMC0WRIZow1EuXRB9xKFRBk6KmSWomqQ
   a=crypto:7 AES_CM_192_HMAC_SHA1_32 inline:5JzlrMywFZhHuNLWPG/HBrUi/Zcg414Q7ZfSaJQnUF5N9APy+GQ
   a=crypto:8 AES_CM_128_HMAC_SHA1_32 inline:/RLYPhZs07WCCBRY8tWNTJemT/IFq1VPHGHmGvnG
   a=crypto:9 AES_CM_128_NULL_AUTH inline:f2fx2ekxPG3GTwTYARtquNJ87qO0Q5ei47KYlo9K
   a=ptime:20
   m=audio 20072 RTP/AVP 8 101
   a=rtpmap:8 PCMA/8000
   a=rtpmap:101 telephone-event/8000
   a=fmtp:101 0-16
   a=ptime:20
   ------------------------------------------------------------------------

manage and update call state for this call leg too CS_INIT -> CS_ROUTING -> CS_CONSUME_MEDIA

Standard INIT
State Change CS_INIT -> CS_ROUTING
State INIT going to sleep
Running State Change CS_ROUTING (Cur 2 Tot 275)
Channel sofia/external/to_number@ip_addr entering state [calling][0]
State ROUTING
SOFIA ROUTING
State Change CS_ROUTING -> CS_CONSUME_MEDIA
State ROUTING going to sleep
Running State Change CS_CONSUME_MEDIA (Cur 2 Tot 275)
State CONSUME_MEDIA
State CONSUME_MEDIA going to sleep
recv 365 bytes from tls/[ip_addr]:5061 at 09:55:07.940977:
   ------------------------------------------------------------------------
   SIP/2.0 100 trying -- your call is important to us
   Via: SIP/2.0/TLS via_addr:5080;rport=59774;branch=z9hG4bK21Qm9U3eHX0Nc;received=via_addr
   From: "from_number" <sip:from_number@via_addr>;tag=8jByBXa2pF1Fj
   To: <sip:to_number@ip_addr>
   Call-ID: 6a827514-c72b-1237-8aab-02a933b32da0
   CSeq: 2070461 INVITE
   Server: ZenTrunk
   Content-Length: 0

   ------------------------------------------------------------------------

Callee from PBX throws auth challenge

recv 483 bytes from tls/[ip_addr]:5061 at 09:55:08.046934:
   ------------------------------------------------------------------------
   SIP/2.0 407 Proxy Authentication Required
   Via: SIP/2.0/TLS via_addr:5080;received=via_addr;rport=59774;branch=z9hG4bK21Qm9U3eHX0Nc
   From: "from_number" <sip:from_number@via_addr>;tag=8jByBXa2pF1Fj
   To: <sip:to_number@ip_addr>;tag=f1cff938000510c1d9006e5a2a4e240b-5736
   Call-ID: 6a827514-c72b-1237-8aab-02a933b32da0
   CSeq: 2070461 INVITE
   Proxy-Authenticate: Digest realm="domain.com", nonce="XJSyI1yUsPf0w1bAocvH4IOCayfWt3bX", qop="auth"
   Content-Length: 0

   ------------------------------------------------------------------------
send 387 bytes to tls/[ip_addr]:5061 at 09:55:08.047056:
   ------------------------------------------------------------------------
   ACK sip:to_number@sometelco.com;transport=tls SIP/2.0
   Via: SIP/2.0/TLS via_addr:5080;rport;branch=z9hG4bK21Qm9U3eHX0Nc
   Max-Forwards: 69
   From: "from_number" <sip:from_number@via_addr>;tag=8jByBXa2pF1Fj
   To: <sip:to_number@ip_addr>;tag=f1cff938000510c1d9006e5a2a4e240b-5736
   Call-ID: 6a827514-c72b-1237-8aab-02a933b32da0
   CSeq: 2070461 ACK
   Content-Length: 0

   ------------------------------------------------------------------------

calleer sends re-invit with auth details

Authenticating 'altanai' with 'Digest:"doamin.com":altanai:pass'.
send 2273 bytes to tls/[ip_addr]:5061 at 09:55:08.047387:
   ------------------------------------------------------------------------
   INVITE sip:to_number@sometelco.com;transport=tls SIP/2.0
   Via: SIP/2.0/TLS via_addr:5080;rport;branch=z9hG4bK3aHDBQmje6p8Q
   Max-Forwards: 69
   From: "from_number" <sip:from_number@via_addr>;tag=8jByBXa2pF1Fj
   To: <sip:to_number@ip_addr>
   Call-ID: 6a827514-c72b-1237-8aab-02a933b32da0
   CSeq: 2070462 INVITE
   Contact: <sip:mod_sofia@via_addr:5080>
   User-Agent: FreeSWITCH-mod_sofia/1.9.0-742-8f1b7e0~64bit
   Allow: INVITE, ACK, BYE, CANCEL, OPTIONS, MESSAGE, INFO, UPDATE, REGISTER, REFER, NOTIFY
   Supported: timer, path, replaces
   Allow-Events: talk, hold, conference, refer
   Proxy-Authorization: Digest username="altanai", realm="domain.com", nonce="XJSyI1yUsPf0w1bAocvH4IOCayfWt3bX", cnonce="apLWcMcrEjerigKpM7MtoA", algorithm=MD5, uri="sip:to_number@sometelco.com;transport=tls", response="0044b00a4d5026252b32eed619d70f9d", qop=auth, nc=00000001
   Content-Type: application/sdp
   Content-Disposition: session
   Content-Length: 1162
   X-FS-Support: update_display,send_info
   Remote-Party-ID: "from_number" <sip:from_number@via_addr>;party=calling;screen=yes;privacy=off

   v=0
   o=FreeSWITCH 1553228435 1553228436 IN IP4 via_addr
   s=FreeSWITCH
   c=IN IP4 via_addr
   t=0 0
   m=audio 20072 RTP/SAVP 8 101
   a=rtpmap:8 PCMA/8000
   a=rtpmap:101 telephone-event/8000
   a=fmtp:101 0-16
   a=crypto:1 AEAD_AES_256_GCM_8 inline:ZbEHd76sP6FZSO9AYcqryybaA4HY3O5p2Uo+e1gmmfVaZCEic6cvKyArhMU
   a=crypto:2 AEAD_AES_128_GCM_8 inline:ePH/F2Qw5+zi8c7tkBb6Y2AQE5uevp+jWUkjgQ
   a=crypto:3 AES_CM_256_HMAC_SHA1_80 inline:SG5rYx3GSR2imutYQ+LzqHufG9UkG3n/SfmFHFOG/r75v2pwf2lG7Qpup+J0mw
   a=crypto:4 AES_CM_192_HMAC_SHA1_80 inline:2PVBBJEp4QcTzTf4Th8Ag/7KiVPmrYb/FCowiRb6yAuTO/kxQLc
   a=crypto:5 AES_CM_128_HMAC_SHA1_80 inline:Yd4L5Qi7A/8xay5ZHWR1jKk9j5Kvy9s2Zo3NOES2
   a=crypto:6 AES_CM_256_HMAC_SHA1_32 inline:JI+s9uFdZ3JfZmRRfwHr0OrpyZdtUXmMC0WRIZow1EuXRB9xKFRBk6KmSWomqQ
   a=crypto:7 AES_CM_192_HMAC_SHA1_32 inline:5JzlrMywFZhHuNLWPG/HBrUi/Zcg414Q7ZfSaJQnUF5N9APy+GQ
   a=crypto:8 AES_CM_128_HMAC_SHA1_32 inline:/RLYPhZs07WCCBRY8tWNTJemT/IFq1VPHGHmGvnG
   a=crypto:9 AES_CM_128_NULL_AUTH inline:f2fx2ekxPG3GTwTYARtquNJ87qO0Q5ei47KYlo9K
   a=ptime:20
   m=audio 20072 RTP/AVP 8 101
   a=rtpmap:8 PCMA/8000
   a=rtpmap:101 telephone-event/8000
   a=fmtp:101 0-16
   a=ptime:20
   ------------------------------------------------------------------------
2019-03-22 09:55:08.041945 [DEBUG] sofia.c:7291 Channel sofia/external/to_number@ip_addr entering state [calling][0]
recv 365 bytes from tls/[ip_addr]:5061 at 09:55:08.048255:
   ------------------------------------------------------------------------
   SIP/2.0 100 trying -- your call is important to us
   Via: SIP/2.0/TLS via_addr:5080;rport=59774;branch=z9hG4bK3aHDBQmje6p8Q;received=via_addr
   From: "from_number" <sip:from_number@via_addr>;tag=8jByBXa2pF1Fj
   To: <sip:to_number@ip_addr>
   Call-ID: 6a827514-c72b-1237-8aab-02a933b32da0
   CSeq: 2070462 INVITE
   Server: ZenTrunk
   Content-Length: 0

   ------------------------------------------------------------------------

Call is accepted by callee , 200 OK is received by Freeswitch PBX

recv 1451 bytes from tls/[ip_addr]:5061 at 09:55:14.223460:
   ------------------------------------------------------------------------
   SIP/2.0 200 OK
   Via: SIP/2.0/TLS via_addr:5080;received=via_addr;rport=59774;branch=z9hG4bK3aHDBQmje6p8Q
   Record-Route: <sip:3.92.18.95:5060;lr;ftag=8jByBXa2pF1Fj>
   Record-Route: <sip:18.205.1.67;lr;ftag=8jByBXa2pF1Fj;did=fd.0971>
   Record-Route: <sip:ip_addr:5060;r2=on;lr;ftag=8jByBXa2pF1Fj;nat=yes>
   Record-Route: <sip:ip_addr:5061;transport=tls;r2=on;lr;ftag=8jByBXa2pF1Fj;nat=yes>
   From: "from_number" <sip:from_number@via_addr>;tag=8jByBXa2pF1Fj
   To: <sip:to_number@ip_addr>;tag=D0r5K6pp80Ujm
   Call-ID: 6a827514-c72b-1237-8aab-02a933b32da0
   CSeq: 2070462 INVITE
   Contact: <sip:to_number@34.201.27.78:5080;transport=udp>
   User-Agent: FreeSWITCH-mod_sofia/1.9.0-742-8f1b7e0~64bit
   Allow: INVITE, ACK, BYE, CANCEL, OPTIONS, MESSAGE, INFO, UPDATE, REGISTER, REFER, NOTIFY
   Supported: timer, path, replaces
   Allow-Events: talk, hold, conference, refer
   Content-Type: application/sdp
   Content-Disposition: session
   Content-Length: 380
   Remote-Party-ID: "to_number" <sip:to_number@34.201.27.78>;party=calling;privacy=off;screen=no

   v=0
   o=FreeSWITCH 1553215954 1553215955 IN IP4 18.212.123.47
   s=FreeSWITCH
   c=IN IP4 18.212.123.47
   t=0 0
   m=audio 33516 RTP/SAVP 8 101
   a=rtpmap:8 PCMA/8000
   a=rtpmap:101 telephone-event/8000
   a=fmtp:101 0-16
   a=sendrecv
   a=crypto:3 AES_CM_256_HMAC_SHA1_80 inline:/itE1k5BLMoTNzo7YEv6hCyM6R6wyHem3Coc5jjYVlKR2L3tEzBG5zx1QHgVSg==
   a=ptime:20
   m=audio 0 RTP/SAVP 19
   a=rtpmap:19 
   ------------------------------------------------------------------------

send ACK to callee

Update Callee ID to "to_number" <to_number>
Channel sofia/external/to_number@ip_addr entering state [completing][200]
sofia.c:7301 Remote SDP:
v=0
o=FreeSWITCH 1553215954 1553215955 IN IP4 18.212.123.47
s=FreeSWITCH
c=IN IP4 18.212.123.47
t=0 0
m=audio 33516 RTP/SAVP 8 101
a=rtpmap:8 PCMA/8000
a=rtpmap:101 telephone-event/8000
a=fmtp:101 0-16
a=crypto:3 AES_CM_256_HMAC_SHA1_80 inline:/itE1k5BLMoTNzo7YEv6hCyM6R6wyHem3Coc5jjYVlKR2L3tEzBG5zx1QHgVSg==
a=ptime:20
m=audio 0 RTP/SAVP 19

send 953 bytes to tls/[ip_addr]:5061 at 09:55:14.224320:
   ------------------------------------------------------------------------
   ACK sip:to_number@34.201.27.78:5080;transport=udp SIP/2.0
   Via: SIP/2.0/TLS via_addr:5080;rport;branch=z9hG4bK4Ka6cj5NBFDUK
   Route: <sip:ip_addr:5061;transport=tls;r2=on;lr;ftag=8jByBXa2pF1Fj;nat=yes>
   Route: <sip:ip_addr:5060;r2=on;lr;ftag=8jByBXa2pF1Fj;nat=yes>
   Route: <sip:18.205.1.67;lr;ftag=8jByBXa2pF1Fj;did=fd.0971>
   Route: <sip:3.92.18.95:5060;lr;ftag=8jByBXa2pF1Fj>
   Max-Forwards: 70
   From: "from_number" <sip:from_number@via_addr>;tag=8jByBXa2pF1Fj
   To: <sip:to_number@ip_addr>;tag=D0r5K6pp80Ujm
   Call-ID: 6a827514-c72b-1237-8aab-02a933b32da0
   CSeq: 2070462 ACK
   Contact: <sip:mod_sofia@via_addr:5080>
   Proxy-Authorization: Digest username="altanai", realm="domain.com", nonce="XJSyI1yUsPf0w1bAocvH4IOCayfWt3bX", cnonce="apLWcMcrEjerigKpM7MtoA", algorithm=MD5, uri="sip:to_number@sometelco.com;transport=tls", response="0044b00a4d5026252b32eed619d70f9d", qop=auth, nc=00000001
   Content-Length: 0

   ------------------------------------------------------------------------

set audio codecs, update call state CS_CONSUME_MEDIA -> CS_EXCHANGE_MEDIA

entering state [ready][200]
looking for crypto suite [AEAD_AES_256_GCM_8] in [3 AES_CM_256_HMAC_SHA1_80 inline:/itE1k5BLMoTNzo7YEv6hCyM6R6wyHem3Coc5jjYVlKR2L3tEzBG5zx1QHgVSg==]
looking for crypto suite [AEAD_AES_128_GCM_8] in [3 AES_CM_256_HMAC_SHA1_80 inline:/itE1k5BLMoTNzo7YEv6hCyM6R6wyHem3Coc5jjYVlKR2L3tEzBG5zx1QHgVSg==]
looking for crypto suite [AES_CM_256_HMAC_SHA1_80] in [3 AES_CM_256_HMAC_SHA1_80 inline:/itE1k5BLMoTNzo7YEv6hCyM6R6wyHem3Coc5jjYVlKR2L3tEzBG5zx1QHgVSg==]
Found suite AES_CM_256_HMAC_SHA1_80
Set Remote Key [3 AES_CM_256_HMAC_SHA1_80 inline:/itE1k5BLMoTNzo7YEv6hCyM6R6wyHem3Coc5jjYVlKR2L3tEzBG5zx1QHgVSg==]
Audio Codec Compare [PCMA:8:8000:20:64000:1]/[PCMA:8:8000:20:64000:1]
Audio Codec Compare [PCMA:8:8000:20:64000:1] ++++ is saved as a match
Set telephone-event payload to 101@8000
Set Codec sofia/external/to_number@ip_addr PCMA/8000 20 ms 160 samples 64000 bits 1 channels
sofia/external/to_number@ip_addr Original read codec set to PCMA:8
Set telephone-event payload to 101@8000
sofia/external/to_number@ip_addr Set 2833 dtmf send payload to 101 recv payload to 101
AUDIO RTP [sofia/external/to_number@ip_addr] 10.130.74.15 port 20072 -> 18.212.123.47 port 33516 codec: 8 ms: 20
Starting timer [soft] 160 bytes per 20ms
Set 2833 dtmf send payload to 101
Set 2833 dtmf receive payload to 101
Set rtp dtmf delay to 40
Activating audio Secure RTP SEND
srtp:sdes:AES_CM_256_HMAC_SHA1_80
Activating audio Secure RTP RECV
srtp:sdes:AES_CM_256_HMAC_SHA1_80
has been answered
Callstate Change DOWN -> ACTIVE
Audio Codec Compare [PCMA:8:8000:20:64000:1]/[PCMU:0:8000:20:64000:1]
Audio Codec Compare [PCMA:8:8000:20:64000:1]/[PCMA:8:8000:20:64000:1]
Audio Codec Compare [PCMA:8:8000:20:64000:1] ++++ is saved as a match
Set telephone-event payload to 101@8000
Set Codec sofia/internal/from_number@sometelco.com:5060 PCMA/8000 20 ms 160 samples 64000 bits 1 channels
sofia/internal/from_number@sometelco.com:5060 Original read codec set to PCMA:8
Set telephone-event payload to 101@8000
sofia/internal/from_number@sometelco.com:5060 Set 2833 dtmf send payload to 101 recv payload to 101
AUDIO RTP [sofia/internal/from_number@sometelco.com:5060] 10.130.74.15 port 29426 -> 192.168.1.23 port 49874 codec: 8 ms: 20
Starting timer [soft] 160 bytes per 20ms
Set 2833 dtmf send payload to 101
Set 2833 dtmf receive payload to 101
Set rtp dtmf delay to 40

send early media/ RTP to Callee

 Pre-Answer sofia/internal/from_number@sometelco.com:5060!
 Callstate Change RINGING -> EARLY
 2019-03-22 09:55:14.221933 [DEBUG] switch_core_media.c:8147 Audio params are unchanged for sofia/internal/from_number@sometelco.com:5060.
 2019-03-22 09:55:14.221933 [DEBUG] mod_sofia.c:881 Local SDP sofia/internal/from_number@sometelco.com:5060:
 v=0
 o=FreeSWITCH 1553219088 1553219089 IN IP4 via_addr
 s=FreeSWITCH
 c=IN IP4 via_addr
 t=0 0
 m=audio 29426 RTP/AVP 8 101
 a=rtpmap:8 PCMA/8000
 a=rtpmap:101 telephone-event/8000
 a=fmtp:101 0-16
 a=ptime:20
 a=sendrecv
Pre-Answer sofia/internal/from_number@sometelco.com:5060!
Callstate Change RINGING -> EARLY
2019-03-22 09:55:14.221933 [DEBUG] switch_core_media.c:8147 Audio params are unchanged for sofia/internal/from_number@sometelco.com:5060.
2019-03-22 09:55:14.221933 [DEBUG] mod_sofia.c:881 Local SDP sofia/internal/from_number@sometelco.com:5060:
v=0
o=FreeSWITCH 1553219088 1553219089 IN IP4 via_addr
s=FreeSWITCH
c=IN IP4 via_addr
t=0 0
m=audio 29426 RTP/AVP 8 101
a=rtpmap:8 PCMA/8000
a=rtpmap:101 telephone-event/8000
a=fmtp:101 0-16
a=ptime:20
a=sendrecv

send 1254 bytes to tcp/[caller_ip]:35365 at 09:55:14.232934:
   ------------------------------------------------------------------------
   SIP/2.0 200 OK
   Via: SIP/2.0/TCP 192.168.1.23:55934;branch=z9hG4bK-524287-1---cc11593581af6519;rport=35365;received=caller_ip
   From: "from_number"<sip:from_number@sometelco.com:5060>;tag=47a61272
   To: <sip:to_number@sometelco.com:5060>;tag=NjvKFKQaHp52e
   Call-ID: 94385YTY3ODNlNzE1YjE5MmY4NmQ3ZWUyZDAzM2E0YzBkM2I
   CSeq: 1 INVITE
   Contact: <sip:to_number@via_addr:5060;transport=tcp>
   User-Agent: FreeSWITCH-mod_sofia/1.9.0-742-8f1b7e0~64bit
   Accept: application/sdp
   Allow: INVITE, ACK, BYE, CANCEL, OPTIONS, MESSAGE, INFO, UPDATE, REGISTER, REFER, NOTIFY, PUBLISH, SUBSCRIBE
   Supported: timer, path, replaces
   Allow-Events: talk, hold, conference, presence, as-feature-event, dialog, line-seize, call-info, sla, include-session-description, presence.winfo, message-summary, refer
   Session-Expires: 120;refresher=uas
   Content-Type: application/sdp
   Content-Disposition: session
   Content-Length: 220
   Remote-Party-ID: "to_number" <sip:to_number@sometelco.com>;party=calling;privacy=off;screen=no

   v=0
   o=FreeSWITCH 1553219088 1553219089 IN IP4 via_addr
   s=FreeSWITCH
   c=IN IP4 via_addr
   t=0 0
   m=audio 29426 RTP/AVP 8 101
   a=rtpmap:8 PCMA/8000
   a=rtpmap:101 telephone-event/8000
   a=fmtp:101 0-16
   a=ptime:20
   ------------------------------------------------------------------------
entering state [completed][200]
Channel [sofia/internal/from_number@sometelco.com:5060] has been answered
Callstate Change EARLY -> ACTIVE
Originate Resulted in Success: [sofia/external/to_number@ip_addr]
State Change CS_CONSUME_MEDIA -> CS_EXCHANGE_MEDIA
Running State Change CS_EXCHANGE_MEDIA (Cur 2 Tot 275)
State EXCHANGE_MEDIA
SOFIA EXCHANGE_MEDIA
recv 507 bytes from tcp/[caller_ip]:35365 at 09:55:14.459247:
   ------------------------------------------------------------------------
   ACK sip:to_number@via_addr:5060;transport=tcp SIP/2.0
   Via: SIP/2.0/TCP 192.168.1.23:55934;branch=z9hG4bK-524287-1---104aee5ed0b7ca66;rport
   Max-Forwards: 70
   Contact: <sip:from_number@192.168.1.23:55934;transport=tcp>
   To: <sip:to_number@sometelco.com:5060>;tag=NjvKFKQaHp52e
   From: "from_number"<sip:from_number@sometelco.com:5060>;tag=47a61272
   Call-ID: 94385YTY3ODNlNzE1YjE5MmY4NmQ3ZWUyZDAzM2E0YzBkM2I
   CSeq: 1 ACK
   User-Agent: X-Lite release 5.4.0 stamp 94385
   Content-Length: 0

   ------------------------------------------------------------------------

Session Border controller for WebRTC

Unified communication services build around WebRTC should be vendor agnostic and multi-tenant and be supported by other Communication Service Providers (CSPs), SIP trunks, PBXs, Telecom Equipment Manufacturers (TEMs), and Communication Platform as a Service (CPaaS). This can happen if all endpoints adhere to SIP standards in most updated RFC. However since not all are on the boat , Session border controllers are a great way to mitigate the differences and provide seamless connectivity to signalling and media , which could be between WebRTC, SIP or PSTN, from TDM to IP .

Session Border Controllers ( SBC )  assist in controlling the signalling and usually also the media streams involved in calls and sessions.

They are often part of a VOIP network on the border where there are 2 peer networks of service providers such as backbone network and access network of corporate communication system which is behind firewall.

A more complex example is that of a large corporation where different departments have security needs for each location and perhaps for each kind of data. In this case, filtering routers or other network elements are used to control the flow of data streams. It is the job of a session border controller to assist policy administrators in managing the flow of session data across these borders. – wikipedia

SBC act like a SIP-aware firewall with proxy/B2BUA.

What is B2BUA?

A Back to back user agent ( B2BUA ) is a proxy-like server that splits a SIP transaction in two pieces:

  • on the side facing User Agent Client (UAC), it acts as server;
  • on the side facing User Agent Server (UAS) it acts as a client.

B2BUAs keep state information about active dialog. Read more here .

Remote Access

SBC mostly have public url address  for teleworkers and a internal IP for enterprise/ inner LAN . This enables users connected to enterprise LAN ( who do not have public address ) to make a call to user outside of their network. During this process SBC takes care of following while relaying packets .

  1. Security
  2. Connectivity
  3. Qos
  4. Regulatory
  5. Media Services
  6. Statistics and billing information

Topology hiding

SBC hides and anonymize secure information like IP ports before forwarding message to outside world . This helps protect the internal node of Operators such as PSTN gateways or SIP proxies from revealing outside.

Explaining the functions of SBC in detail

1. Security

SBCs are often used by corporations along with firewalls and intrusion prevention systems (IPS) to enable VoIP calls to and from a protected enterprise network. VoIP service providers use SBCs to allow the use of VoIP protocols from private networks with Internet connections using NAT, and also to implement strong security measures that are necessary to maintain a high quality of service. The security features includes :

  • Prevent malicious attacks on network such as DOS, DDos.
  • Intrusion detection
  • cryptographic authentication
  • Identity/URL based access control
  • Blacklisting bad endpoints
  • Malformed packet protection
  • Encryption of signaling (via TLS and IPSec) and media (SRTP)
  • Stateful signalling and Validation
  • Toll Fraud – detect who is intending to use the telecom services without paying up

2. Connectivity

As SBC offers IP-to-IP network boundary, it recives SIP request from users like REGISTER , INVITE  and routes them towards destination, making their IP. During this process it performs various operations like

  • NAT traversal
  • IPv4 to IPv6 inter-working
  • VPN connectivity
  • SIP normalization via SIP message and header manipulation
  • Multi vendor protocol normalization

Further Routing features includes  :
Least Cost Routing based on MoS ( Mean Opinion Score ) : Choosing a path based on MoS is better than chooisng any random path . 

Protocol translations between SIP, SIP-I, H.323.

In essence SBC achieve interoperability, overcoming some of the problems that firewalls and network address translators (NATs) present for VoIP calls.

Automatic Rerouting

connectivity loss from UA for whole branch is detected by timeouts . But they can also be detected by audio trough SIP OPTIONS by SBC .  In such connectivity loss , SBC decides rerouting or sending back 504 to caller .

SBC 2 (1)

4. QoS
To introduce performance optimization and business rules in call management QoS is very important . This includes the following :

  • Traffic policing
  • Resource allocation
  • Rate limiting
  • Call Admission Control (CAC)
  • ToS/DSCP bit setting
  • Recording and Audit of messages , voice calls , files
  • System and event logging

5. Regulatory

Govt policies ( such as ambulance , police ) and/ or enterprise policies may require some calls to be holding priority over others . This can also be configured under SBC as emergency calls and prioritization.
Some instances may require communication provider to comply with lawful bodies and provide session information or content , this is also called as Lawful interception (LI) . This enables security officials to collect specific information rather than examining all the traffic that passes through a particular router. This is also part of SBC.
6. Media services

Many of the new generation of SBCs also provide built-in digital signal processors (DSPs) to enable them to offer border-based media control and services such as- DTMF relay , Media transcoding , Tones and announcements etc.

WebRTC enabled SBC’s also provide conversion between DTLS-SRTP, to and from RTCP/RTP. Also transcoding for Opus into G7xx codecs
and ability to relay VP8/VP9 and H.264 codecs.

7. Statistics and billing information

SBC have an interface with and OSS/BSS systems for billing process , as almost all traffic that pass through the edge of the network passes via SBC. For this reason it is also used to gather Statistics and usage-based information like bandwidth, memory and CPU.  PCAP traces of both signaling and media information of specific sessions .

New feature rich SBCs also have built-in digital signal processors (DSPs). Thus able to provide more control over session’s media/voice . They also add services like Relay and Interworking, Media Transcoding, Tones and Announcements, DTMF etc.

Session Border Controller (SBC)
Session Border Controller for WebRTC , SIP , PSTN , IP PBX and Skype for business .

Diagram Component Description

Gateways provide compression or decompression, control signaling, call routing, and packetizing.

PSTN Gateway : Converts analog to VOIP and vice versa . Only audio no support for rich multimedia .

VOIP Gateway : A VoIP Gateway acts like a translator converting digital telecom lines to VoIP . VOIP gateway often also include voice and fax. They also have interfaces to Soft switches and network management systems.

WebRTC Gateway : They help in providing NAT with ICE-lite and STUN connectivity for peers behind policies and Firewall .

SIP trunking : Enterprises save on significant operation cost by switching to IP /SIP trunking in place of TDM (Time Division Multiplexing). Read more on SIP trunk and VPN  here. 

SIP Server : A Telecom application server ( SIP Server ) is useful for building VAS ( Value Added Services ) and other fine grained policies on real time services . Read more on SIP Servers here . 

VOIP/SIP service Provider :   There are many Worldwide SIP Service providers such as Verizon in USA , BT in europe, Swisscom in Switzerland etc .

Building a SBC

The latest trends in Telecommunications industry demand an open standardized SBC to cater to growing and large array of SIP Trunking, Unified Multimedia Communications UC&C, VoLTE, VoWi-Fi, RCS and OTT services worldwide . Building an SBC requires that it meet the following prime requirements :

  • software centric
  • Cloud Deploybale
  • Rich multimedia (audio , video , files etc) processing
  • open interfaces
  • The end product should be flexible to be deployed as COTS ( Commercial Off the shelf) product or as a virtual network function in the NFV cloud.
  • Multi Configuration , should be supported such as Hosted or Cloud deployed .
  • Overcome inconsistencies in SIP from different Vendors
  • Security and Lawful Interception
  • Carrier Grade Scaling

Flow Diagram 

SBC WebRTC to SIP

Thus we see how SBC became important part of comm systems developed over SIP and MGCP. SBC offer B2BUA ( Back to Back user agent) behavior to control both signalling and media traffic.


IPTV ( Internet Based Television )

We know the power of Internet protocol suit as it takes on the world of telecom . Alreday half of Communication has been transferred from legacy telecom signalling protocols like SS7 to IP based communication ( Skype , Hangouts , whatsapp , facebook call ) . The TV service providers too are largely investing in IP based systems like SIP and IMS to deliver their content over Telecom’s IP based network ( Packet switched ).

A consumer today wants HD media content anytime anywhere . The traditional TV solutions just dont match upto the expectations anymore . The IPTV provider in todays time must make investments to deliver content that is media-aware, and device-aware. Not only this it should be  personal, social, and interactive . after all its all about user  experience.

Few popular applications for IPTV solutions developers are

  • Menu overlay with detailed description of channels , categories , programs , movies
  • Replay option also referred to as timeshift . It allows a user to pause , resume and  record the show in his absence and view it later
  • Video on demand which concerns paying and viewing music albums , movies etc on demand
  • Live streaming of events such as president speech , tennis match etc .

Application that can be build around the IPTV context

  • Record and Playback content
  • Information overlay on streaming content
  • Social networking services integrated with IPTV content
  • Parental Control to realtime view , monitor and control what your child is watching on the IPTV
  • Watch the surveillance  footage from IP cameras anywhere
  • Real time communication on IPTV  with advanced features like call continuity , content sync .

Service Creation Environment (SCE ) for SIP Applications

I hoped of making a SIP application Development environment a year back and worked towards it earnestly . Sadly I wasn’t able to complete the job yet I have decided to share a few things about it here .

Aim :

Develop  a SCE ( Service Creation Environment ) to addresses all aspects of lifecycle of a Service, right from creation/development, orchestration, execution/delivery, Assurance and Migration/Upgrade of services.

Similar market products :

  • Open/cloud Rhino
  • Mobicents and Telestax

Limitations of open source/other market products:

  • Free versions of the Service Creation Environments do not offer High Availability.
  • High Cost of Deployment grade versions.

Solution Description

I propose a in-house Java based Service Creation Environment “SLC SCE”. The SLC SCE will enable creation of JAINSLEE based SIP  services. It can be used to develop and deploy carrier-grade applications that use SS7 and IMS based protocols such as INAP, CAP, Diameter and SIP as well as IT / Web protocols such as HTTP and XML.

Benefits:

  • Service Agility
  • Significantly Lower price points
  • Open Standards eliminate Legacy SCP Lock-in

Timeline

  • Java-based service creation environment (SCE) – 1.5 Months
  • Graphical User Interface (GUI) and schematic representations to help in the design, maintenance and support of applications – 1.5 months
  • SIP Resource Adapter – 1 month

Architecture

Service Creation Environment (SCE) for SIP Applications
Service Creation Environment (SCE) for SIP Applications

In essence it encompasses the idea of developing the following

  1. SIP stack
  2. Javascript API’s
  3. Java Libraries for calling SIP stack
  4. Eclipse plugin to work with the SIP application development process
  5. Visual Interface to view the logic of application and possible errors / flaws
  6. SDKs (  Service Development Kit) , which are development Environment themselves

Extra Effort required to put in to make the venture successful

  1. Demo applications for basic SIP logic like Call screening , call rerouting .
  2. tutorial to create , deploy and run application from scratch . Aimed at all sections ie web developer , telecom engineer , full stack developer etc .
  3. Some opensource implementation on public repositories like Github , Google code , SourceForge
  4. Perform active problem solving on Stackoverflow , CodeRanch , Google groups and  other forums .

—————————————————————

BEA Weblogic SIP server

Bea server is a old SIP servlet container ie application server which is used to embed control logic in a program . It is supported on jdk1.5 hence the system’s environment variables must match . Otherwise in later stages deploying applications throw class version error .

1. Install Bea Weblogic

2. Follow the Installation steps

Make domain

3. Goto the installation directory . Usually C:/bea/user_projects/mydomain/ .

click on startweblogic.cmd in windows. In case the system is linux run startweblogic.sh script

4. Open Web console on url : http://127.0.0.1:7001/console. Enter username password

default username password weblogic , weblogic .

It can also be customized for example my username and password are altanai , tcs@1234

5.  Make Converged SIP Servlet Application in any editor such as notepad , edit+ etc .

The project structure looks like

Call screening
src
build
src
web
build.xml

The SIP servlet are put side directory structure of src

For example : sample application for Call screening

package com.altanai.voice;
import java.io.IOException;
import javax.servlet.*;
import javax.servlet.sip.*;
import javax.servlet.sip.Proxy;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import java.util.*;
public class CallScreening extends SipServlet
{
private static SipFactory factory;
private static SipApplicationSession sas;
private static Proxy proxy;
public void init(ServletConfig config) throws ServletException
{
System.out.println(“Call screening SIP servlet initiated”);
super.init(config);
}
protected void doInvite(SipServletRequest req) throws java.lang.IllegalArgumentException,java.lang.IllegalStateException,javax.servlet.ServletException,java.io.IOException
{
System.out.println(“Received an Invite Request”);
if(req.getFrom().toString().indexOf(“alice”)!=-1)
{
req.createResponse(406).send();
System.out.println(“User is blocked”);
}
else
{
req.createResponse(200).send();
System.out.println(“User is not blocked”);
}
}
}

6. Build it with ant . For this go inside the application folder and run ant. Output will either be “failed to build “ or “build successfully” .

The ant  command generates the war file from SIP servlet Web application .

7. Incase of successful build . Add the application to Weblogic web console install section and activate it .

I will demonstrate this process in step by step manner . First  click on “ Lock and Edit “ Button on the left panel . Then goto Install button in the centre area and browser to the location of application war or sar we have build through ant ,

8. We can delete an application in exactly the same way . click on “ Lock and Edit “ Button on the left panel . Then goto the delete button after selecting the radio button alongside the application we want to delete.

8. For enhanced application building we can also refer to sample provided along with bea weblogic . file:///C:/bea/sipserver30/samples/sipserver/examples/src/index.html

Legacy Telecom Networks

I use the term legacy telecom system many a times , but have not really described what a legacy system actually is . In my conferences too I am asked to just exactly define a legacy system . Often my clients are surprised to hear what they have in current operation is actually fitted in our own version of definition of ” Legacy system ” . This write up is an attempt to describe the legacy landscape . It also describes its characteristics , elements and transformation .

Characteristics of Legacy Systems

1. Analog Signals

1G , introduced in 1980s , used analog signals as compared to digital in 2G onward. In 1G voice was modulated to higher frequency and then converted to digital while communication with radio towers .

2.Legacy system have ATM / Frame Relay transmission .

This  is basically Hardware  Specific and results in High Expenses.

3. Legacy systems have POTS / PSTN / ISDN as their access layer technology .

Access layer is the first layer of telecom architecture which is responsible for interacting directly with the end use / subscriber . Legacy system technologies are again Hardware  Specific , bear High Expenses and offer Low stability.

Physical transmission media include :

  • Twisted wire (modems)
  • Coaxial cable
  • Fiber optics and optical networks – Dense wavelength division multiplexing (DWDM)

4. Legacy system use Traditional Switches / ISDN in their Core Layer

Core layer is the main control hub of the entire telecom architecture . Using old fashioned switches render high CAPEX ( capital Expenditure ) and OPEX ( Operational Expenses ) .

5. In the service delivery front legacy system employ Traditional IN switches

These are very Hardware Centric.

Services part of Legacy Telecom Networks

a)Virtual Private Network (VPN)

An Intelligent Network (IN) service, which offers the functions of a private telephone network. The basic idea behind this service is that business customers are offered the benefits of a (physical) private network, but spared from owning and maintaining it

b)Access Screening(ASC):

 An IN service, which gives the operators the possibility to screen (allow/barring) the incoming traffic and decide the call routing, especially when the subscribers choose an alternate route/carrier/access network (also called Equal Access) for long distance calls on a call by call basis or pre-selected.

c)Number Portability(NP)

An IN service allows subscribers to retain their subscriber number while changing their service provider, location, equipment or type of subscribed telephony service. Both geographic numbers and non-geographic numbers are supported by the NP service.

Transformation towards IMS (Total IP)

The telecommunications industry has been going through a significant transformation over the past few years. At the outset incumbent operators used to focus on mainly basic voice services and still remained profitable due to the limited number of players in the space and requirement of huge amounts as initial investment.

However, with the advent of competitive vendors, rise in consumer base, and introduction of cost effective IP based technologies a major revolution has come about. This has enabled operators to come out of their traditional business models to maintain and enhance subscriber base by providing better and cheaper voice, multimedia and data services in order to grab the biggest possible share in this multi- billion dollar industry.

The evolution in Telecom industry has been accelerating all the time. The Next-Generation Operators wants to keep pace with the rapidly changing technology by, adapting to market needs and looking at the system and business process from multiple perspectives concurrently. Communication Service Providers (CSPs) need to consider several factors in mind before proposing any solution. They need to deploy solutions which are highly automated, highly flexible, caters to customer needs coupled with ultra low operating costs.

By hosting new services on the new platform and combining new and old services CSP‟s aim to provide service bundles that would generate new revenue streams. This process is largely dependant on IMS ( IP Multimedia Subsystem ) architecture .

Transformation towards IMS (Total IP)
Transformation towards IMS (Total IP)

Optimization in operator landscape evolve as result of synergistic technologies that come together to address the innovation and cost optimization needs of operator for better user experience. In following sections different technological evolutions that are affecting overall operator ecosystems have been discussed with focus towards Service Layer.

Legacy to IP transformation

This section broadly covered the aspects of migration from legacy IN solution to new age JAINSLEE framework based one. Applies to Legacy IN hosting voice based services mostly  such as VPN, Access Screening ,Number Portability, SIP-Trunking ,Call Gapping.

Most operator environments have seen a rise in the number of service delivery platforms. Also complexity of telecom networks have increased manifold hence CSPs are facing multiple challenges. Increased efforts and costs are required for maintaining all the SDP platforms. These platforms are generally of different vendors and cater to different technologies thereby greatly increase chances of limiting the scalability and flexibility of the operator landscape. More effort required for sustaining the life cycle of the platform and challenges in integrating non compatible SDPs due to proprietary design have been stumbling blocks in the progress of CSPs across the world.

To overcome these challenges there is trend in the market to move towards SDP consolidation wherein instead of maintaining several SDPs with their proprietary design CSPs prefer maintaining a single or less number of SDPs having standardized interfaces.

SDP consolidation SDP consolidation (1) SDP consolidation (2)

As illustrated in the above figure there is a transition that is taking place in the industry towards consolidation of service delivery session control. This would provide a cost effective sustenance of existing applications and the rapid creation and deployment of new services leading to increased revenue recognition by CSPs.

  • Agile Development
  • Innovative services
  • open SOA based architectures
  • IN/NGN Platform and Services
  • Reuse of existing investments in legacy service platforms
  • low cost of new service development
  • faster time to market
  • Monetize investment in Network Infrastructure uplift – SIP trunking, VoLTE etc.

Services that should be covered  in the Scope of Migration from fixed line to IP telephony are:

  • Virtual Private Network (VPN) : An Intelligent Network (IN) service, which offers the functions of a private telephone network. The basic idea behind this service is that business customers are offered the benefits of a (physical) private network, but spared from owning and maintaining it.
  • Access Screening(ASC): An IN service, which gives the operators the possibility to screen (allow/barring) the incoming traffic and decide the call routing, especially when the subscribers choose an alternate route/carrier/access network (also called Equal Access) for long distance calls on a call by call basis or pre-selected.
  • Number Portability(NP) : An IN service allows subscribers to retain their subscriber number while changing their service provider, location, equipment or type of subscribed telephony service. Both geographic numbers and non-geographic numbers are supported by the NP service.

WebRTC based Unified Communication platform

Using WebRTC Solution for Delivering In Context Voice which provides new monetizing benefits to the Enterprise customers of Service Providers. This includes following components:

  • WebRTC Gateway for implementation for inter-connect with SIP Legacy
  • Enhancement of WebRTC Client with new features like Cloud Address Book, Conferencing & Social Networking hooks.
  • Cloud based solutions

INtoJAISNLEE

Challenges in Migration to IMS  (Total IP )

Since long I have been advocating the benefits of migration to IMS  from a current fixed line / legacy/ proprietary VOIP / SS7 based system . However I decided to write this post on the challenges in migration to IMS system from a telecom provider’s view.  Though I could think of many , I have jot down the major 4 . they are as follows :

Data Migration challenges

  • Establishing a common data model definition
  • Data migration seamlessly
  • Configuration management
  • Extracting data from multiple sources and vendors , that includes legacy systems
  • Extracting data due to its large scale and volume

Training

  • Creating an effective knowledge share and transfer for live operations
  • Training in fallback plans, standards and policies .

Customer impact

  • Minimized customer outage
  • Enhance customer experience by delivering quality services on schedule
  • Ensuring security of customer’s confidential data
  • Transfer of customer services without any impact.

Testing in replicated environment

  • Physical pre-transfer test
  • Reducing cycle time
  • Verification and validation at every change in data environment
  • Detect production issues early in the test -lifecycle

Fallback plans

  • Pilot program and real network simulation for ensuring preparedness
  • Tracking changes in new network


Difference between WebRTC and plugin based communication

A lot of service providers ie telecom operators had deduced their own ways to provide Web based communication even before WebRTC was born . With time , as WebRTC has become stronger , more secure , resilient to failure they have come around to migrate their existing system from previous closed box native APIs to opensource WebRTC APIs.

The first figure ( given below ) depicts a communication platform build over plugins and proprietary APIs using HTTP REST based signaling .

2014-07-22_1212
Web Communication Service Architecture over HTTP/ REST API

As the migration took place the proprietary API components were replaced by Open standard based entities such as plugins were replaced by WebRTC APIs, HTTP REST based signalling was replaced by SIP ( Session Initiation Protocol ) .

Web Communication Service Architecture over WebRTC SIP
Web Communication Service Architecture over WebRTC SIP

Note telecom operator network did not had to face transformation by integration of WebRTC elements .