Category Archives: Telecom Architectures

Network characteristics like architecture nodes and flows of Telecom Networks

Surajdroid ( Ramudroid v7 Solar Powered )

Ramudroid is an ingeniously build robot to clean outdoors and alleys inspired by Bharat Swachhata Abhiyaan . Read more

Prototype in Development

Frame and wheel

solar panel mounted

Algorithm Enhancements

Obstruction Detection

Stop Operation on Tray Weight reaching threshold

Pause operation and take Shelter in Rain

Equipment Cost

Power And Charge Devices

  1. Solar Panel MicroSun MS 12v 60 WP – 2500 INR
  2. Solar charger Controller – 600 INR
  3. Battery 11.1 V 2200 mAh – 500 INR

Frame and Motion Assembly

  1. Wheels 10 cm diameter – 50 INR x 4 ie 200 INR
  2. Tray – 400 INR
  3. Frame Assembly – 1000 INR
  4. Arduino to control Motors Drivers – 500 INR
  5. Motor Driver – 300 INR
  6. LCD display – 200 INR

Electronics , Communicating modules and Sensors

  1. Raspberry Pi Moddel B+ – to be replaced with low cost alternative – 2700 INR
  2. GPS module – 700 INR
  3. GSM module – 1400 INR
  4. Camera 5 MP Board Module – 450 INR

Total Cost to Develop – 12000 INR

Working Principle

The robot is divided into 2 parts – Cleaning Unit and driving unit

Driving Unit

consists of 4 wheel to drive the setup . Wheels must be tightly fixed inot position to prevent them from tilting, spreading outwards and imbalancing the load. 2 rear controller by 12 V 1 amp DC motors with 300 RPM and 2 front free wheels. Motors are conneted to Arduino for receving command for start , stop , left or right navigation.

There are three input pins for each motor, including Input1 (IN1), Input2 (IN2), and Enable1 (EN1) for Motor1 and Input3, Input4, and Enable2 for Motor2.
IN1 IN2 MOTOR
0 0 BRAKE
1 0 FORWARD
0 1 BACKWARD
1 1 BRAKE

Cleaning Unit

Uses 3 tough bristled brushes controlled by 3 5V DC gear motors with 60 RPM. The arrangement of the brushes is such that the bottom 2 brushes use clockwise and anticlockwise motion outwards to pull in the litter and push up with the flow of the air and bristles of the brush. The third brush combs the collected into the collector tray. The tray is attached to weight control system to stop operations when critical weight is reached to prevent overloading the robot

Solar specification

Maximum Power (Pmax) – 60 Wp
Voltage at Maximum Power (Vmpp) – 18.1 V
Current at Maximum Power (Impp) – 3.32 A
Open Circuit Voltage (Voc) – 22.32 V
Short Circuit Current (Isc) – 3.63 A
Standard Test Conditions (STC): air mass AM 1.5, irradiance 1000W/m2, cell temperature 25°C
Maximum System Voltage 1000 V

Electrical Data at NOCT
Temperature – 47±2 °C
Nominal Operating Cell Temperature (NOCT): 800W/m2, AM 1.5, windspeed 1m/s,ambient temperature 20°C

Thermal Ratings
Operating Temperature Range -20~90 °C
Temperature Coefficient of Pmax -0.43 %/°C
Temperature Coefficient of Voc -0.36 %/°C
Temperature Coefficient of Isc 0.66 %/°C

Material Data
Panel Dimension (H/W/D) 705x655x35 mm
Weight 6 kg
Cell Type Polycrystalline
Cell Size 156×156 mm
Cell Number 36
Encapsulant Type – EVA ( Ethylene vinyl acetate)
Frame Type Anodized Aluminium Alloy

Physical
Dimentions – 70mm x 655mm x 35mm
cells per module – 36
cell type – poly crystalline sIlicon
fuel cell dimention – 156mm x 156mm
Encapsulation – EVA
back cover – PV sheet

Ref : https://www.enfsolar.com/pv/panel-datasheet/crystalline/20863

Load

Solar panel weight – 5kg with annodixed alumium frame , 3 kg without the frame with just the toughened texture glass on panel
Frame and wheels – 2kg
Accessories – 1 kg
garbage holding capacity – 2 kg
Total Weight of the Robot : maximum upto 10Kg

Scenarios

Good Sunlight scenario : This 12 Volt solar panel provide about 2.5 Amps of current on average during daytime. In such a situtaion it is directly used to drive the machine’s motors for wheels and brushes and electrical components such as PI and arduino. In no motion of rest conditions the genrated power is used to charge the attached backup battery.

Shady / evening / morning scenario : When the panel is not receiving direct or strong sunlight, the power generated is less hence not sufficient to take the load of driving the wheels for movement. Hence is the power falls below a certain prespecified threhold, the current is drawn from battery backup.

Night / No sunlight Scenario : battery is used to power the setup. panel can be dismounted to lower the load.

Contributing to Ramudroid Project or Reuse

It is deigned and developed as an MIT licensed Opensourced product by a bunch of developers and engineers in Bangalore for greater good.

Advertisements

Opensips Modules



Dispatcher Module

This modules implements a dispatcher for destination addresses. It computes hashes over parts of the request and selects an address from a destination set. The selected address is used then as outbound proxy.
The module can be used as a stateless load balancer, having no guarantee of fair distribution.

Exported Parameters

list_file (string) – Path to the file with destination sets. Default value is “/etc/opensips/dispatcher.list” or “/usr/local/etc/opensips/dispatcher.list”.

modparam("dispatcher", "list_file", "/var/run/opensips/dispatcher.list")

db_url (string) – load the sets of gateways from the database you must set this parameter. Default value is “NULL” (disable DB support).

modparam("dispatcher", "db_url", "mysql://user:passwb@localhost/database")

table_name (string) – load the sets of gateways from the database you must set this parameter as the database name.
Default value is “dispatcher”.

modparam("dispatcher", "table_name", "my_dispatcher")

setid_col (string) – storing the gateway’s group id. Default value is “setid”.

modparam("dispatcher", "setid_col", "groupid")

destination_col (string) – destination’s sip uri.

modparam("dispatcher", "destination_col", "uri")

flags_col (string) – The column’s name in the database storing the flags for destination uri.

modparam("dispatcher", "flags_col", "dstflags")

force_dst (int) – If set to 1, force overwriting of destination address when that is already set. Default value is “0”.

modparam("dispatcher", "force_dst", 1)

flags (int) – affect dispatcher’s behaviour, defined as a bitmask on an integer value. If flag 1 is set only the username part of the uri will be used when computing an uri based hash. If no flags are set the username, hostname and port will be used The port is used only if different from 5060 (normal sip uri) or 5061 (in the sips case). If flag 2 is set, then the failover support is enabled. The functions exported by the module will store the rest of addresses from the destination set in AVP, and use these AVPs to contact next address when the current-tried fails. Default value is “0”.

modparam("dispatcher", "flags", 3)

use_default (int) – If the parameter is set to 1, the last address in destination set is used as last option to send the message. For example, it is good when wanting to send the call to an anouncement server saying: “the gateways are full, try later”. Default value is “0”.

modparam("dispatcher", "use_default", 1)

dst_avp (str) – The name of the avp which will hold the list with addresses, in the order they have been selected by the chosen algorithm. If use_default is 1, the value of last dst_avp_id is the last address in destination set. The first dst_avp_id is the selected destinations. All the other addresses from the destination set will be added in the avp list to be able to implement serial forking.

modparam("dispatcher", "dst_avp", "$avp(i:271)")

grp_avp (str) – The name of the avp storing the group id of the destination set. Good to have it for later usage or checks. Default is null.

modparam("dispatcher", "grp_avp", "$avp(i:272)")

cnt_avp (str) – The name of the avp storing the number of destination addresses kept in dst_avp avps.

modparam("dispatcher", "cnt_avp", "$avp(i:273)")

hash_pvar (str) – String with PVs used for the hashing algorithm like to do hashing over custom message parts.Default value is “null” – disabled.

modparam("dispatcher", "hash_pvar", "$avp(i:273)")

setid_pvar (str) – name of the PV where to store the set ID (group ID) when calling ds_is_from_list() with no parameter.

modparam("dispatcher", "setid_pvar", "$var(setid)")

ds_ping_method (string) – With this Method you can define, with which method you want to probe the failed gateways. This method is only available, if compiled with the probing of failed gateways enabled. Default value is “OPTIONS”.

modparam("dispatcher", "ds_ping_method", "INFO")

ds_ping_from (string) – With this Method you can define the “From:”-Line for the request, sent to the failed gateways. This method is only available, if compiled with the probing of failed gateways enabled. Default value is “sip:dispatcher@localhost”.

modparam("dispatcher", "ds_ping_from", "sip:proxy@sip.somehost.com")

ds_ping_interval (int – With this Method you can define the interval for sending a request to a failed gateway. This parameter is only used, when the TM-Module is loaded. If set to “0”, the pinging of failed requests is disabled.Default value is “10”.

modparam("dispatcher", "ds_ping_interval", 30)

ds_probing_threshhold (int) – If you want to set a gateway into probing mode, you will need a specific number of requests until it will change from “active” to probing. The number of attempts can be set with this parameter. Default value is “3”.

modparam("dispatcher", "ds_probing_threshhold", 10)

ds_probing_mode (int) – Controls what gateways are tested to see if they are reachable. If set to 0, only the gateways with state PROBING are tested, if set to 1, all gateways are tested. If set to 1 and the response is 407 (timeout), an active gateway is set to PROBING state. Default value is “0”.

modparam("dispatcher", "ds_probing_mode", 1)

options_reply_codes (str) – This parameter must contain a list of SIP reply codes separated by comma. The codes defined here will be considered as valid reply codes for OPTIONS messages used for pinging, apart for 200. Default value is “NULL”.

modparam("dispatcher", "options_reply_codes", "501, 403")

Exported Functions

ds_select_dst(set, alg) – The method selects a destination from addresses set.Meaning of the parameters is as follows:
set – the id of the set from where to pick up destination address. It is the first column in destination list file.
alg – the algorithm used to select the destination address.
“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 (Proxy-Authorization or “normal” authorization). If no username is found, round robin is used.
“6” – random (using rand()).
“7” – hash over the content of PVs string. Note: This works only when the parameter hash_pvar is set.
“X” – if the algorithm is not implemented, the first entry in set is chosen.

If the bit 2 in ‘flags’ is set, the rest of the addresses from the destination set is stored in AVP list. You can use ‘ds_next_dst()’ to use next address to achieve serial forking to all possible destinations. This function can be used from REQUEST_ROUTE.

ds_select_dst("1", "0");

ds_select_domain(set, alg)
The method selects a destination from addresses set and rewrites the host and port from R-URI. This function can be used from REQUEST_ROUTE.

ds_next_dst() – Takes the next destination address from the AVPs with id ‘dst_avp_id’ and sets the dst_uri (outbound proxy address). This function can be used from FAILURE_ROUTE.

ds_next_domain() – Takes the next destination address from the AVPs with id ‘dst_avp_id’ and sets the domain part of the request uri. This function can be used from FAILURE_ROUTE.

ds_mark_dst() – Mark the last used address from destination set as inactive, in order to be ingnored in the future. In this way it can be implemented an automatic detection of failed gateways. When an address is marked as inactive, it will be ignored by ‘ds_select_dst’ and ‘ds_select_domain’. This function can be used from FAILURE_ROUTE.

ds_mark_dst(“s”) – Mark the last used address from destination set as inactive (“i”/”I”/”0”), active (“a”/”A”/”1”) or probing (“p”/”P”/”2”). With this function, an automatic detection of failed gateways can be implemented. When an address is marked as inactive or probing, it will be ignored by ‘ds_select_dst’ and ‘ds_select_domain’. possible parameters:
“i”, “I” or “0” – the last destination should be set to inactive and will be ignored in future requests.
“a”, “A” or “1” – the last destination should be set to active.
“p”, “P” or “2” – the last destination will be set to probing. Note: You will need to call this function “threshhold”-times, before it will be actually set to probing.This function can be used from FAILURE_ROUTE.

ds_is_from_list() – This function returns true, if the current request comes from a host from the dispatcher-list; otherwise false. This function can be used from REQUEST_ROUTE, FAILURE_ROUTE, BRANCH_ROUTE and ONREPLY_ROUTE.

ds_is_from_list(“group”) – This function returns true, if the current request comes from a host in the given group of the dispatcher-list; otherwise false.

This function can be used from REQUEST_ROUTE, FAILURE_ROUTE, BRANCH_ROUTE and ONREPLY_ROUTE.

Exported MI Functions

ds_set_state – Sets the status for a destination address (can be use to mark the destination as active or inactive).
Parameters:
state : state of the destination address
“a”: active
“i”: inactive
“p”: probing
group: destination group id
address: address of the destination in the group

MI FIFO Command Format:
:ds_set_state:reply_fifo_file
state
group
address
empty_line

ds_list – It lists the groups and included destinations.

MI FIFO Command Format:
:ds_list:reply_fifo_file
empty_line

ds_reload – reloads the groups and included destinations.

MI DATAGRAM Command Format:

    ":ds_reload:\n."

Installation and Running

Destination List File – Each destination point must be on one line. First token is the set id, followed by destination address. Optionally, the third field can be flags value (1 – destination inactive, 2 – destination in probing mod — you can do bitwise OR to set both flags). The set id must be an integer value. Destination address must be a valid SIP URI. Empty lines or lines starting with “#” are ignored.

Exmaple of a dispatcher list file
line format
setit(integer) destination(sip uri) flags (integer, optional)

proxies
2 sip:127.0.0.1:5080
2 sip:127.0.0.1:5082

gateways
1 sip:127.0.0.1:7070
1 sip:127.0.0.1:7072
1 sip:127.0.0.1:7074

OpenSIPS config file

sample config file for dispatcher module

debug=9            debug level (cmd line: -dddddddddd)
fork=no
log_stderror=yes  (cmd line: -E)

children=2
check_via=no      (cmd. line: -v)
dns=off           (cmd. line: -r)
rev_dns=off       (cmd. line: -R)
port=5060

module loading

mpath="/usr/local/lib/opensips/modules/"
loadmodule "maxfwd.so"
loadmodule "sl.so"
loadmodule "dispatcher.so"

setting module-specific parameters

dispatcher params

modparam("dispatcher", "list_file", "../etc/dispatcher.list")
// modparam("dispatcher", "force_dst", 1)

route{
if ( !mf_process_maxfwd_header("10") )
{
sl_send_reply("483","To Many Hops");
drop();
};
ds_select_dst("2", "0");
forward();
// t_relay();
}

db_text Module

Implementation for a simplified database engine based on text files. It can be used by OpenSIPS DB interface instead of other database module (like MySQL). It keeps everything in memory.

The db_text database system architecture contains

  • a database is represented by a directory in the local file system. NOTE: when you use db_text in OpenSIPS, the database URL for modules must be the path to the directory where the table-files are located, prefixed by “text://”,
    e.g., “text:///var/dbtext/opensips”.
  • a table is represented by a text file inside database directory.

Internal format of a db_text table

column definition name(type,attr) where types can be int , double , str and attributes be auto , null ,
* each other line is a row with data. The line ends with “\n”.
* the fields are separated by “:”.
* no value between two ‘:’ (or between ‘:’ and start/end of a row) means “null” value.
* next characters must be escaped in strings: “\n”, “\r”, “\t”, “:”.
* 0 — the zero value must be escaped too.

Sample of a db_text table ,

id(int,auto) name(str) flag(double) desc(str,null)
1:nick:0.34:a\tgood\: friend
2:cole:-3.75:colleague
3:bob:2.50:

Minimal OpenSIPS location db_text table definition

username(str) contact(str) expires(int) q(double) callid(str) cseq(int)

Minimal OpenSIPS subscriber db_text table example

username(str) password(str) ha1(str) domain(str) ha1b(str)
suser:supasswd:xxx:alpha.org:xxx

This database interface don’t support the data insertion with default values. All such values specified in the database
template are ignored.

db_mode (integer) – Set caching mode (0 – default) or non-caching mode (1). In caching mode, data is loaded at startup. In non-caching mode, the module check every time a table is requested whether the correspondingfile on disk has changed, and if yes, will re-load table from file.

modparam("db_text", "db_mode", 1)

Exported MI Functions

dbt_dump – Write back to hard drive modified tables.

opensipsctl fifo dbt_dump

dbt_reload – Causes db_text module to reload cached tables from disk. Parameters:
1 db_name (optional) – database name to reload.
2 table_name (optional, but cannot be present without the
db_name parameter) – specific table to reload.

MI FIFO Command Format:
opensipsctl fifo dbt_reload
opensipsctl fifo dbt_reload /path/to/dbtext/database
opensipsctl fifo dbt_reload /path/to/dbtext/database table_name

Installation and Running

Compile the module and load it instead of mysql or other DB modules.

Load the db_text module

loadmodule "/path/to/opensips/modules/db_text.so"
modparam("module_name", "database_URL", "text:///path/to/dbtext/database
")

Using db_text with basic OpenSIPS configuration

Definition of ‘subscriber’ table (one line)

username(str) domain(str) password(str) first_name(str) last_name(str) phone(str) email_address(str) datetime_created(int) datetime_modified(int) confirmation(str) flag(str) sendnotification(str) greeting(str) ha1(str) ha1b(str) perms(str) allow_find(str) timezone(str,null) rpid(str,null)

Definition of ‘location’ and ‘aliases’ tables (one line)

username(str) domain(str,null) contact(str,null) received(str) expires(i
nt,null) q(double,null) callid(str,null) cseq(int,null) last_modified(st
r) flags(int) user_agent(str) socket(str)

Definition of ‘version’ table and sample records

table_name(str) table_version(int)
subscriber:3
location:6
aliases:6

Configuration file using dbtext databse for oersistant storage . Also using auth

<h1>debug_mode=yes</h1>
children=4

check_via=no    # (cmd. line: -v)
dns=no          # (cmd. line: -r)
rev_dns=no      # (cmd. line: -R)
listen=udp:10.100.100.1:5060

loadmodule "modules/dbtext/dbtext.so"
loadmodule "modules/sl/sl.so"
loadmodule "modules/tm/tm.so"
loadmodule "modules/rr/rr.so"
loadmodule "modules/maxfwd/maxfwd.so"
loadmodule "modules/usrloc/usrloc.so"
loadmodule "modules/registrar/registrar.so"
loadmodule "modules/textops/textops.so"
loadmodule "modules/textops/mi_fifo.so"
loadmodule "modules/auth/auth.so"
loadmodule "modules/auth_db/auth_db.so"

setting module-specific parameters

-- mi_fifo params --

modparam("mi_fifo", "fifo_name", "/tmp/opensips_fifo")

-- usrloc params --

modparam("usrloc", "db_mode", 2)
modparam("usrloc|auth_db", "db_url", "text:///tmp/opensipsdb")

modparam("auth_db", "calculate_ha1", 1)
modparam("auth_db", "password_column", "password")
modparam("auth_db", "user_column", "username")
modparam("auth_db", "domain_column", "domain")

route{
// initial sanity checks -- messages with max_forwards==0, or excessively long requests
if (!mf_process_maxfwd_header("10")) {
sl_send_reply("483","Too Many Hops");
exit;
};
if ($ml &gt;=  65535 ) {
sl_send_reply("513", "Message too big");
exit;
};

// we record-route all messages -- to make sure that subsequent messages will go through this proxy;
if (!$rm=="REGISTER") record_route();
<pre><code>// subsequent messages withing a dialog should take the path determined by record-routing
if (loose_route()) {
    // mark routing logic in request
    append_hf("P-hint: rr-enforced\r\n");
    route(1);
    exit;
};

if (!is_myself("$rd")) {
    // mark routing logic in request
    append_hf("P-hint: outbound\r\n");
    route(1);
    exit;
};

//if the request is for other domain use UsrLoc 
if (is_myself("$rd")) {
    if ($rm=="REGISTER") {
        # digest authentication
        if (!www_authorize("", "subscriber")) {
            www_challenge("", "0");
            exit;
        };

        save("location");
        exit;
    };

    lookup("aliases");
    if (!is_myself("$rd")) {
        append_hf("P-hint: outbound alias\r\n");
        route(1);
        exit;
    };

    # native SIP destinations are handled using our USRLOC DB
    if (!lookup("location")) {
        sl_send_reply("404", "Not Found");
        exit;
    };
};
append_hf("P-hint: usrloc applied\r\n");
route(1);</code></pre>
}

route[1]
{
if (!t_relay()) {
sl_reply_error();
};
}


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.

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. Some of the prominent features are,

  • 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

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 )

It has 3 main logical parts :

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

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

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).

  1. 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();
}
  1. 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();
}
}
  1. 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");
}
}
  1. 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");
}

5. 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;
}
  1. 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");
}
}
  1. 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)");
}
  1. 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);
}
  1. 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

2.1 INET – IPv4 connection.

2.2 INET6 – IPv6 connection.

2.3 TCP

2.4 UDP

2.5 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;
}

2.6 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");
};

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

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

3. Core parameters

3.1 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

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

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

3.4 alias – set alias hostnames for the server

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

3.5 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

3.8 cfg_file – Returns the name of the corresponding OpenSIPS config file

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

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

3.11 children – Number of worker processes (children) to be created for each UDP or SCTP interface you have defined.

children=16 // Default value is 8
3.12 chroot – If set, OpenSIPS will chroot (change root directory) to this valid path in the system value.

chroot=/other/diffroot

3.13 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).
3.14 db_version_table
The name of the table version to be used by the DB API to check the version of the used tables. Default value is “version”

db_version_table=”version_1_8″

3.15 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”

3.16 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 ]

db_max_async_connections=220


3.18 disable_503_translation – If ‘yes’, OpenSIPS will not translate the received 503 replies into 500 replies .
Default value is ‘no’ (do translation as per RFC 3261).
3.19 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'.

3.20 disable_dns_blacklist
The 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’).

3.21 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_dns_failover=yes

3.22 disable_stateless_fwd
Can be ‘yes’ or ‘no’. This parameter 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
Default value is ‘yes’.

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

3.24 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_time=3

3.25 dns_retr_no – Number of dns retransmissions before giving up.

dns_retr_no=3

3.26 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_servers_no=2

3.27 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_ipv6=yes

3.28 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_try_naptr=no

3.29 dns_use_search_list

dns_use_search_list=no

3.30 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 “evil” 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)

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

enable_asserts = true

3.32 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

3.33 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

3.34 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

3.35 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
3.38 include_file – load additional routes/blocks with file path

include_file “proxy_regs.cfg”

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

import_file “proxy_regs.cfg”

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

protocol: should be one of the transport modules loaded in the config file (e.g., udp, tcp, tls)
address: can be an IP address, a hostname, a network interface id, or the * wildcard which makes OpenSIPS listen on all possible interfaces for that protocol
port: optional, the port used by the listener – if absent, the default port exported by the transport module is used.
This parameter can be set multiple times in same configuration file, the server listening on all addresses specified.

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
3.45 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

3.46 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

3.47 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”
3.48 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.
Default value: off
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

3.49 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

3.50 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”

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

memdump=2

3.52 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)

memlog=2

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

mcast_loopback=yes

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

mcast_ttl=32

3.55 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

3.56 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> ...

3.57 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

3.58 poll_method – The 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

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

3.60 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

3.61 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

3.62 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

3.63 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.

3.64 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”

3.65 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))

3.66 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.

3.67 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.

3.68 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

3.69 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_children=4

3.70 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).

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

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

tcp_connect_timeout = 5

3.73 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

3.74 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

3.75 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

3.76 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

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

tcp_keepalive = 1

3.79 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_keepcount = 5

3.80 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

3.81 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

3.82 tls_ca_list

3.83 tls_certificate

3.84 tls_ciphers_list

3.85 tls_domain

3.86 tls_handshake_timeout

3.87 tls_log

3.88 tls_method

3.89 tls_port_no

3.90 tls_private_key

3.91 tls_require_certificate

3.92 tls_send_timeout

3.93 tls_verify

3.94 tos – The 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

3.96 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”

3.97 wdir – working directory used by OpenSIPS at runtime.

 wdir="/usr/local/opensips" 

3.98 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

3.99 xlog_force_color

xlog_force_color = true //Default value: false

3.100 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");
}

Ref :

VOIP Call Metric Monitoring

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).
For a R factor of 90 , Mos is 4.3 ( Excellent ) while for 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.

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.

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.

Packet Loss

packet loss percentage performed per RFC 3550 using RTP header sequence numbers.

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.

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

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

sipP

SIPp is an opensource (GNU GPL license) performance testing tool for the SIP protocol and is widely used for Quality assurabce of callflows in voip applications for UAC / UASs cenarios. It can emulate functioing of a sip phone such as REGISTER , establishes and releases multiple calls with
the INVITE and BYE methods , send other SIP requests and wait for reponsesbased on dafult of custom xml scenario files .

Plus factor is the dynamic display of statistics about running tests (call rate, round trip delay, and message statistics),
periodic CSV statistics dumps, TCP and UDP over multiple sockets or multiplexed with retransmission management,
regular expressions and variables in scenario files, and dynamically adjustable call rates.

sipp -sn uac -d 10000 -s 9876543210 127.0.0.1:5060  -l 10

It is widley used as aperformnace and load testing tool since it can test SIP equipements like SIP proxies, B2BUAs, SIP media servers, SIP/x gateways, and SIP PBXes and can also emulate thousands of user agents calling your SIP system.

Installation

Pre-requisites to compile SIPp are:
– C++ Compiler
– curses or ncurses library
– For TLS support: OpenSSL >= 0.9.8
– For pcap play support: libpcap and libnet
– For SCTP support: lksctp-tools
– For distributed pauses: Gnu Scientific Libraries

Download , extract and build with options like

tar -xvzf sipp-xxx.tar.gz
cd sipp
./configure --with-sctp --with-pcap --with-openssl
make

Verify installation
Run sipp with embedded server (uas) scenario:

sipp -sn uas

On the same host, run sipp with embedded client (uac) scenario:

sipp -sn uac 127.0.0.1 -trace_msg -trace_err
output for server 
# sipp -sn uas
------------------------------ Scenario Screen -------- [1-9]: Change Screen --
Port Total-time Total-calls Transport
5060 32.95 s 61 UDP
0 new calls during 0.874 s period      1 ms scheduler resolution
19 calls Peak was 41 calls, after 28 s
0 Running, 63 Paused, 12 Woken up
0 dead call msg (discarded)
3 open sockets
                             Messages  Retrans   Timeout   Unexpected-Msg

----------> INVITE 61 0 0 0
<---------- 180 61 0 <---------- 200 61 0 0 ----------> ACK E-RTD1 61 0 0 0

----------> BYE 61 0 0 0
<---------- 200 61 0
[ 4000ms] Pause 61 0
------------------------------ Test Terminated --------------------------------
----------------------------- Statistics Screen ------- [1-9]: Change Screen --
Start Time | 2019-02-04 13:04:32.108663 1549265672.108663
Last Reset Time | 2019-02-04 13:05:04.189720 1549265704.189720
Current Time | 2019-02-04 13:05:05.065119 1549265705.065119
-------------------------+---------------------------+--------------------------
Counter Name | Periodic value | Cumulative value
-------------------------+---------------------------+--------------------------
Elapsed Time | 00:00:00:875000 | 00:00:32:956000
Call Rate | 0.000 cps | 1.851 cps
-------------------------+---------------------------+--------------------------
Incoming call created | 0 | 61
OutGoi

traceings

———————————————– 2019-02-04 13:08:13.939148
UDP message sent (530 bytes):

INVITE sip:service@127.0.0.1:5060 SIP/2.0
Via: SIP/2.0/UDP 192.x.x.x:5061;branch=z9hG4bK-52422-25-0
From: sipp ;tag=52422SIPpTag0025
To: service
Call-ID: 25-52422@192.x.x.x
CSeq: 1 INVITE
Contact: sip:sipp@192.x.x.x:5061
Max-Forwards: 70
Subject: Performance Test
Content-Type: application/sdp
Content-Length: 135
v=0
o=user1 53655765 2353687637 IN IP4 192.x.x.x
s=-
c=IN IP4 192.x.x.x
t=0 0
m=audio 6004 RTP/AVP 0
a=rtpmap:0 PCMU/8000

———————————————– 2019-02-04 13:08:13.939310
UDP message received [321] bytes :

SIP/2.0 180 Ringing
Via: SIP/2.0/UDP 192.x.x.x:5061;branch=z9hG4bK-52422-1-0
From: sipp ;tag=52422SIPpTag001
To: service ;tag=52416SIPpTag011
Call-ID: 1-52422@192.x.x.x
CSeq: 1 INVITE
Contact:
Content-Length: 0

———————————————– 2019-02-04 13:08:13.939905
UDP message received [486] bytes :

SIP/2.0 200 OK
Via: SIP/2.0/UDP 192.x.x.x:5061;branch=z9hG4bK-52422-1-0
From: sipp ;tag=52422SIPpTag001
To: service ;tag=52416SIPpTag011
Call-ID: 1-52422@192.x.x.x
CSeq: 1 INVITE
Contact:
Content-Type: application/sdp
Content-Length: 135
v=0
o=user1 53655765 2353687637 IN IP4 192.x.x.x
s=-
c=IN IP4 192.x.x.x
t=0 0
m=audio 6000 RTP/AVP 0
a=rtpmap:0 PCMU/8000

———————————————– 2019-02-04 13:08:13.940159
UDP message sent (371 bytes):

ACK sip:service@127.0.0.1:5060 SIP/2.0
Via: SIP/2.0/UDP 192.x.x.x:5061;branch=z9hG4bK-52422-1-5
From: sipp ;tag=52422SIPpTag001
To: service ;tag=52416SIPpTag011
Call-ID: 1-52422@192.x.x.x
CSeq: 1 ACK
Contact: sip:sipp@192.x.x.x:5061
Max-Forwards: 70
Subject: Performance Test
Content-Length: 0

~ RTP

———————————————– 2019-02-04 13:08:13.941658
UDP message sent (371 bytes):

BYE sip:service@127.0.0.1:5060 SIP/2.0
Via: SIP/2.0/UDP 192.x.x.x:5061;branch=z9hG4bK-52422-1-7
From: sipp ;tag=52422SIPpTag001
To: service ;tag=52416SIPpTag011
Call-ID: 1-52422@192.x.x.x
CSeq: 2 BYE
Contact: sip:sipp@192.x.x.x:5061
Max-Forwards: 70
Subject: Performance Test
Content-Length: 0

———————————————– 2019-02-04 13:08:13.952888
UDP message received [313] bytes :

SIP/2.0 200 OK
Via: SIP/2.0/UDP 192.x.x.x:5061;branch=z9hG4bK-52422-1-7
From: sipp ;tag=52422SIPpTag001
To: service ;tag=52416SIPpTag011
Call-ID: 1-52422@192.x.x.x
CSeq: 2 BYE
Contact:
Content-Length: 0

Time

---------------------------- Repartition Screen ------- [1-9]: Change Screen --
Average Response Time Repartition 1
0 ms <= n < 10 ms : 293 10 ms <= n < 20 ms : 9 20 ms <= n < 30 ms : 0 30 ms <= n < 40 ms : 0 40 ms <= n < 50 ms : 0 50 ms <= n < 100 ms : 0 100 ms <= n < 150 ms : 0 150 ms <= n < 200 ms : 0 n >= 200 ms : 0
Average Call Length Repartition
0 ms <= n < 10 ms : 0 10 ms <= n < 50 ms : 0 50 ms <= n < 100 ms : 0 100 ms <= n < 500 ms : 0 500 ms <= n < 1000 ms : 0 1000 ms <= n < 5000 ms : 262 5000 ms <= n < 10000 ms : 0 n >= 10000 ms : 0
------------------------------ Sipp Server Mode -------------------------------

Output for client

uac.xml
SIPp UAC Remote
|(1) INVITE |
|------------------>|
|(2) 100 (optional) |
|<------------------|
|(3) 180 (optional) |
|<------------------|
|(4) 200 |
|<------------------|
|(5) ACK |
|------------------>|
| |
|(6) PAUSE |
| |
|(7) BYE |
|------------------>|
|(8) 200 |
|<------------------|

sipp -sn uac 127.0.0.1 -trace_msg -trace_err
Resolving remote host ‘127.0.0.1’… Done.
—————————— Scenario Screen ——– [1-9]: Change Screen —
Call-rate(length) Port Total-time Total-calls Remote-host
10.0(0 ms)/1.000s 5061 17.32 s 98 127.0.0.1:5060(UDP)

3 new calls during 0.286 s period 1 ms scheduler resolution
0 calls (limit 30) Peak was 25 calls, after 10 s
0 Running, 101 Paused, 7 Woken up
0 dead call msg (discarded) 0 out-of-call msg (discarded)
3 open sockets

                             Messages  Retrans   Timeout   Unexpected-Msg
  INVITE ---------->         98        0         0                  
     100 <----------         0         0         0         0        
     180 <----------         98        0         0         0        
     183 <----------         0         0         0         0        
     200          98        0                            
   Pause [      0ms]         98                            0        
     BYE ---------->         98        0         0                  
     200 <----------         98        0         0         0        

—————————— Test Terminated ——————————–

----------------------------- Statistics Screen ------- [1-9]: Change Screen --
Start Time | 2019-02-04 13:08:03.908208 1549265883.908208
Last Reset Time | 2019-02-04 13:08:20.954289 1549265900.954289
Current Time | 2019-02-04 13:08:21.241152 1549265901.241152
-------------------------+---------------------------+--------------------------
Counter Name | Periodic value | Cumulative value
-------------------------+---------------------------+--------------------------
Elapsed Time | 00:00:00:286000 | 00:00:17:332000
Call Rate

Tracings

———————————————– 2019-02-04 13:08:13.934840
UDP message received [527] bytes :

INVITE sip:service@127.0.0.1:5060 SIP/2.0
Via: SIP/2.0/UDP 192.x.x.x:5061;branch=z9hG4bK-52422-1-0
From: sipp ;tag=52422SIPpTag001
To: service
Call-ID: 1-52422@192.x.x.x
CSeq: 1 INVITE
Contact: sip:sipp@192.x.x.x:5061
Max-Forwards: 70
Subject: Performance Test
Content-Type: application/sdp
Content-Length: 135
v=0
o=user1 53655765 2353687637 IN IP4 192.x.x.x
s=-
c=IN IP4 192.x.x.x
t=0 0
m=audio 6004 RTP/AVP 0
a=rtpmap:0 PCMU/8000

———————————————– 2019-02-04 13:08:13.936616
UDP message sent (321 bytes):

SIP/2.0 180 Ringing
Via: SIP/2.0/UDP 192.x.x.x:5061;branch=z9hG4bK-52422-1-0
From: sipp ;tag=52422SIPpTag001
To: service ;tag=52416SIPpTag011
Call-ID: 1-52422@192.x.x.x
CSeq: 1 INVITE
Contact:
Content-Length: 0

———————————————– 2019-02-04 13:08:13.937003
UDP message sent (486 bytes):

SIP/2.0 200 OK
Via: SIP/2.0/UDP 192.x.x.x:5061;branch=z9hG4bK-52422-1-0
From: sipp ;tag=52422SIPpTag001
To: service ;tag=52416SIPpTag011
Call-ID: 1-52422@192.x.x.x
CSeq: 1 INVITE
Contact:
Content-Type: application/sdp
Content-Length: 135
v=0
o=user1 53655765 2353687637 IN IP4 192.x.x.x
s=-
c=IN IP4 192.x.x.x
t=0 0
m=audio 6000 RTP/AVP 0
a=rtpmap:0 PCMU/8000

———————————————– 2019-02-04 13:08:13.948679
UDP message received [371] bytes :

ACK sip:service@127.0.0.1:5060 SIP/2.0
Via: SIP/2.0/UDP 192.x.x.x:5061;branch=z9hG4bK-52422-1-5
From: sipp ;tag=52422SIPpTag001
To: service ;tag=52416SIPpTag011
Call-ID: 1-52422@192.x.x.x
CSeq: 1 ACK
Contact: sip:sipp@192.x.x.x:5061
Max-Forwards: 70
Subject: Performance Test
Content-Length: 0

~ RTP

———————————————– 2019-02-04 13:08:13.949168
UDP message received [371] bytes :

BYE sip:service@127.0.0.1:5060 SIP/2.0
Via: SIP/2.0/UDP 192.x.x.x:5061;branch=z9hG4bK-52422-1-7
From: sipp ;tag=52422SIPpTag001
To: service ;tag=52416SIPpTag011
Call-ID: 1-52422@192.x.x.x
CSeq: 2 BYE
Contact: sip:sipp@192.x.x.x:5061
Max-Forwards: 70
Subject: Performance Test
Content-Length: 0

———————————————– 2019-02-04 13:08:13.949245
UDP message sent (313 bytes):

SIP/2.0 200 OK
Via: SIP/2.0/UDP 192.x.x.x:5061;branch=z9hG4bK-52422-1-7
From: sipp ;tag=52422SIPpTag001
To: service ;tag=52416SIPpTag011
Call-ID: 1-52422@192.x.x.x
CSeq: 2 BYE
Contact:
Content-Length: 0

time

---------------------------- Repartition Screen ------- [1-9]: Change Screen --
Average Response Time Repartition 1
0 ms <= n < 10 ms : 657 10 ms <= n < 20 ms : 20 20 ms <= n < 30 ms : 0 30 ms <= n < 40 ms : 0 40 ms <= n < 50 ms : 0 50 ms <= n < 100 ms : 0 100 ms <= n < 150 ms : 0 150 ms <= n < 200 ms : 0 n >= 200 ms : 0
Average Call Length Repartition
0 ms <= n < 10 ms : 649 10 ms <= n < 50 ms : 28 50 ms <= n < 100 ms : 0 100 ms <= n < 500 ms : 0 500 ms <= n < 1000 ms : 0 1000 ms <= n < 5000 ms : 0 5000 ms <= n < 10000 ms : 0 n >= 10000 ms : 0
------ [+|-|*|/]: Adjust rate ---- [q]: Soft exit ---- [p]: Pause traffic -----

Last Error: Overload warning: the major watchdog timer 3000ms has been t…

Controlling sipp

  • [+|-|*|/]: Adjust rate
  • p Pause traffic
  • q Quit SIPp (after all calls complete, enter a second time to quit immediately)
  • Q Quit SIPp immediately s Dump screens to the log file (if -trace_screen is passed)

References :
https://media.readthedocs.org/pdf/sipp-wip/latest/sipp-wip.pdf

BlockChain programming

Blockchain is essentially a decentralized algorithm for distributed storage and processing , using a non immutable data structures and securing them with signatures and keys . These sequential chain of records called blocks , can contains almost anything from timestamped transactions , metadata , contracts , files etc just as long as they are chained using hash pointers to previous blocks  .

what is a hash ?

function f (x) = y , takes an i/o and give a determined o/p . example heaxadecimeal output of my name , md5(altanai bisht) = 2b9e76d57842ebafaf19fd33bb3573a3.

These are irreversible ie one cant find the i/p from o/p . For this u need to try every combination using brute force. Hence these are generally used for cross verification without revealing the information itself .

Who are miners ?

-tbd –

Application of block chain :

Market analysts and industry specialist have said that block-chain is a revolutionizing technology which will create a decentralized network for not just currency exchange but also many other aspects such as double spent problem , universal identities  , document management etc . Example : Bitcoin protocol , which contains a full record of every transaction ever executed with the currency at any time in past. It is also a solution to problem like black – money , double spending , tax evasions etc. Other areas include:

  • Decentralizing document keeping such as government records , digital assets , equity information , medical and health records etc . The system also provide data ownership and Intellectual property protection .
  • Fintech as AML( Anti money laundering) , eKYC ( Know Your customer )  , epay , loans, stock trading .
  • Smart contracts such as in ethereum . Allows to keep program code that would execute on an event.
  • Shared economy for a p2p payment system .
  • Crowdfunding , works on paradigm of  token owner’s voting and cooperation in decisions for crowd-sourced venture capital funds .
  • Micro payments / fractional concurrency for small amounts suits power selling and buying  such as on solar renewable power micro grid

Since a block chain is a ledger of facts shared across many peer nodes , all communication and inter node transaction uses the power of crypto to authenticate  each other and validate each others requests from the genesis block .

what is a genesis block ?

First block of blockchain which needs to be hard-coded into software . It is the only block which does not reference a previous block .

As any peer wants to add a fact to the ledger , a consensus needs to be obtained from the network. This way of network agreement ensures that fraudulent behavior is prevented .

Example : bitcoin’s genesis block

01000000 - version
0000000000000000000000000000000000000000000000000000000000000000 - prev block
3BA3EDFD7A7B12B27AC72C3E67768F617FC81BC3888A51323A9FB8AA4B1E5E4A - merkle root
29AB5F49 - timestamp
FFFF001D - bits
1DAC2B7C - nonce
01 - number of transactions
01000000 - version
01 - input
0000000000000000000000000000000000000000000000000000000000000000FFFFFFFF - prev output
4D - script length
04FFFF001D0104455468652054696D65732030332F4A616E2F32303039204368616E63656C6C6F72206F6E206272696E6B206F66207365636F6E64206261696C6F757420666F722062616E6B73 - scriptsig
FFFFFFFF - sequence
01 - outputs
00F2052A01000000 - 50 BTC
43 - pk_script length
4104678AFDB0FE5548271967F1A67130B7105CD6A828E03909A67962E0EA1F61DEB649F6BC3F4CEF38C4F35504E51EC112DE5C384DF7BA0B8D578A4C702B6BF11D5FAC - pk_script
00000000 - lock time

 

Forks 

There is only one path from top block on chain to genesis root , however  there can many forks upwards from genesis block . It is so because blocks may be created within a short span of time or be  under processing . One of the two block will be added to main chain and other will be orphaned or added to pool of queued transactions or even be lost.

Steps to Programming a simple block-chain application :

Lets assume we are creating a block chain for call records.

callstatus block chain

Structure of a block which is an object which typically looks like

block = {
"index" :1,
"timestamp " :20-02-2017/10:00
"callstatus " : [ { caller : sip:john@domain.com" ,
callee : "alice@domain.com ",
active call time : 3:00
]},
"proof" : 23897897
"previous hash ":"9868768"
}

Blocks have an index , timestamp , transactions ( in our case call status such as outgoing or incoming calls ) and the hash link of previous block , which enables the chain formation ,

Create a class , blockchain , for member function and variables. Create functions as :

  1. init() : create a new chain and transaction object
  1. createNewTranscation( ) : this creates the information which needs to be fed into the next mined block  and returns the index of the new block which the transaction will be added to .

function createNewTranscation(_caller , _callee , _calltime ){

current_transaction.append({
caller : _caller ,
callee : _callee,
activeCallTime : _calltime
})

return lastBlock['index'] +1;

}

 

 

  1. createNewBlock() : at first we need to create a genesis block

  2. fetchLastBlock() ,

  3. boolean isBlockValid ( newBlock , oldBlock) – checks if the oldblocks index is sequentially aligned with new block and whether old blocks hash is equal to new blocks previous hash . Also calculates whether hash of new block is actually same as the supplied hash value in new block ( give  below) .

  4. hashBlock( block ) –  to create the hashes we need to add in block. Basically a SHA 256 hash of concatenated arguments as index, timestamp, message , previous hash and a nonce . example pseudo code :

 

Consensus Algorithms

All block-chains a\re deterministic state machines and transactions act upon them . Consensus filters out the invalid ones and reaches on agreement with valid ones.

DPOS (Delegated Proof of Stake)

A consensus algorithm used for electing producers and scheduling them in a fair and democratic way . It works on the simple principle that longest chain wins therefore incases of multiple forks or network disruption also , if an honest peer finds out a  valid strictly longer chain  , it will switch from its current fork to the longer chain. We assume that in all conditions ,  no other chain forked can be longer if 2/3 of producers are honest as 2/3 + 1 confirmations are required .

In crypto we trust !

Block chain is primarily 3 things : p2p network, public key cryptography and distributed consensus .

The security and accountability of such a system is managed via mass surveillance of transactions and cryptographic evidence. Ensures that blocks are always in chronological order  since meddling with the blocks will change the hash for preceding blocks

Asymmetric keys and digital signatures

Verification of block uses ECDSA ( Elliptic Curve Digital Signature Algorithm ) to ensure that tokens are spend by their rightful owners only.

An ellipsis is a derived from the second degree equation like ax^2 + bcy + cy^2 + dx + ey +f =0 . Depending on attributes this could be hyperbola , parabola or even a circle . However elliptic curve cryptography uses a third degree equation  from either a pseudo -random curve  ( such as over prime  fields y^2=x^3+ax+b or binary fields y^2 + xy = x^3 + ax^2 + b ) or a special curve .

 

what is ECDSA ?

There are 2 types of auth schemes : Symmetric , relying on shared secret key and Asymmetric relying on private public keys . ECDSA is a asymmetric authentication scheme where in addition to sender and receiver , even 3rd party systems can be authenticated .  In this the sender uses his private key to sign the message and receiver uses the senders public key to verify the message’s signature .

ECDSA signature

Difficulty 

While publishing a block with pending facts  to be appended to a chain , the owner sends it to other nodes for confirmation on its validity. Once its approved , other nodes called miners add it to their copy of chains. However the new block has to be published after fixed time interval for fraud prevention ( example :  bitcoin blocks are published every 10 mins on avg ) .  This duration is dynamically recalculated as the network miners grow or shrink . A difficulty is a number metric that represents how difficult is it to find a hash for given target.

  • To force increase time for calculating the matching hash  , difficulty is increased for miners work harder and take longer to earn the block reward .
  • While  in case of  less miner participation , the block difficulty level is made lower

Ref :

 

Gstreamer

GStreamer ( LGPL )ia a media handling library written in C for applicatioan such as streaming , recording, playback , mixing and editing attributes etc. Even enhnaced applicaiosn such as tsrancoding , media ormat conversion , streaming servers for embeeded devices ( read more about Gstreamer in RPi in my srticle here).
It encompases various codecs, filters and is modular with plugins developement to enhance its capabilities. Media Streaming application developers use it as part of their framework at either the broadcaster’s end or as media player.

gst-launch-1.0 videotestsrc ! videoconvert ! autovideosink

To list all packages of Gstreamer

pkg-config --list-all | grep gstreamer
  • gstreamer-gl-1.0 GStreamer OpenGL Plugins Libraries – Streaming media framework, OpenGL plugins libraries
  • gstreamer-bad-video-1.0GStreamer bad video library – Bad video library for GStreamer elementsgstreamer-tag-1.0 GStreamer Tag Library – Tag base classes and helper functionsgstreamer-bad-base-1.0 GStreamer bad base classes – Bad base classes for GStreamer elements
  • gstreamer-net-1.0GStreamer networking library – Network-enabled GStreamer plug-ins and clockinggstreamer-sdp-1.0 GStreamer SDP Library – SDP helper functions
  • gstreamer-1.0 GStreamer – Streaming media framework
  • gstreamer-bad-audio-1.0 GStreamer bad audio library, uninstalled – Bad audio library for GStreamer elements, Not Installedgstreamer-allocators-1.0 GStreamer Allocators Library – Allocators implementation
  • gstreamer-player-1.0 GStreamer Player – GStreamer Player convenience library
  • gstreamer-insertbin-1.0 GStreamer Insert Bin – Bin to automatically and insertally link elements
  • gstreamer-plugins-base-1.0 GStreamer Base Plugins Libraries – Streaming media framework, base plugins libraries
  • gstreamer-vaapi-glx-1.0 GStreamer VA-API (GLX) Plugins Libraries – Streaming media framework, VA-API (GLX) plugins librariesgstreamer-codecparsers-1.0 GStreamer codec parsers – Bitstream parsers for GStreamer elementsgstreamer-base-1.0 GStreamer base classes – Base classes for GStreamer elements
  • gstreamer-app-1.0 GStreamer Application Library – Helper functions and base classes for application integration
  • gstreamer-vaapi-drm-1.0 GStreamer VA-API (DRM) Plugins Libraries – Streaming media framework, VA-API (DRM) plugins librariesgstreamer-check-1.0 GStreamer check unit testing – Unit testing helper library for GStreamer modules
  • gstreamer-vaapi-1.0 GStreamer VA-API Plugins Libraries – Streaming media framework, VA-API plugins libraries
  • gstreamer-controller-1.0 GStreamer controller – Dynamic parameter control for GStreamer elements
  • gstreamer-video-1.0 GStreamer Video Library – Video base classes and helper functions
  • gstreamer-vaapi-wayland-1.0 GStreamer VA-API (Wayland) Plugins Libraries – Streaming media framework, VA-API (Wayland) plugins libraries
  • gstreamer-fft-1.0 GStreamer FFT Library – FFT implementation
  • gstreamer-mpegts-1.0 GStreamer MPEG-TS – GStreamer MPEG-TS support
  • gstreamer-pbutils-1.0 GStreamer Base Utils Library – General utility functions
  • gstreamer-vaapi-x11-1.0 GStreamer VA-API (X11) Plugins Libraries – Streaming media framework, VA-API (X11) plugins libraries
  • gstreamer-rtp-1.0 GStreamer RTP Library – RTP base classes and helper functions
  • gstreamer-rtsp-1.0 GStreamer RTSP Library – RTSP base classes and helper functions
  • gstreamer-riff-1.0 GStreamer RIFF Library – RIFF helper functions
  • gstreamer-audio-1.0 GStreamer Audio library – Audio helper functions and base classes
  • gstreamer-plugins-bad-1.0 GStreamer Bad Plugin libraries – Streaming media framework, bad plugins libraries
  • gstreamer-rtsp-server-1.0 gst-rtsp-server – GStreamer based RTSP server

At the time of writing this article Gstreamer an much early version in 1.X , which was newer than its then stable version 0.x. Since then the library has updated many fold. summarising release highlights for major versions as the blog was updated over time .

Gstreamer 1.8.0 – 24 March 2016

  • Features Hardware-accelerated zero-copy video decoding on Android
  • New video capture source for Android using the android.hardware.Camera API
  • Windows Media reverse playback support (ASF/WMV/WMA)
  • tracing system provides support for more sophisticated debugging tools
  • high-level GstPlayer playback convenience API
  • Initial support for the new Vulkan API
  • Improved Opus audio codec support: Support for more than two channels; MPEG-TS demuxer/muxer can handle Opus; sample-accurate encoding/decoding/transmuxing with Ogg, Matroska, ISOBMFF (Quicktime/MP4), and MPEG-TS as container; new codec utility functions for Opus header and caps handling in pbutils library. The Opus encoder/decoder elements were also moved to gst-plugins-base (from -bad), and the opus RTP depayloader/payloader to -good.
  • Asset proxy support in the GStreamer Editing Services

GStreamer 1.16.0 – 19 April 2019.

  • GStreamer WebRTC stack gained support for data channels for peer-to-peer communication based on SCTP, BUNDLE support, as well as support for multiple TURN servers.
  • AV1 video codec support for Matroska and QuickTime/MP4 containers and more configuration options and supported input formats for the AOMedia AV1 encoder
  • Closed Captions and other Ancillary Data in video
  • planar (non-interleaved) raw audio
  • GstVideoAggregator, compositor and OpenGL mixer elements are now in -base
  • New alternate fields interlace mode where each buffer carries a single field
  • WebM and Matroska ContentEncryption support in the Matroska demuxer
  • new WebKit WPE-based web browser source element
  • Video4Linux: HEVC encoding and decoding, JPEG encoding, and improved dmabuf import/export
  • Hardware-accelerated Nvidia video decoder gained support for VP8/VP9 decoding, whilst the encoder gained support for H.265/HEVC encoding.
  • Many improvements to the Intel Media SDK based hardware-accelerated video decoder and encoder plugin (msdk): dmabuf import/export for zero-copy integration with other components; VP9 decoding; 10-bit HEVC encoding; video post-processing (vpp) support including deinterlacing; and the video decoder now handles dynamic resolution changes.
  • ASS/SSA subtitle overlay renderer can now handle multiple subtitles that overlap in time and will show them on screen simultaneously
  • Meson build feature-complete (with the exception of plugin docs) and it is now the recommended build system on all platforms. The Autotools build is scheduled to be removed in the next cycle.
  • GStreamer Rust bindings and Rust plugins module
  • GStreamer Editing Services allows directly playing back serialized edit list with playbin or (uri)decodebin

Ref : https://gstreamer.freedesktop.org

Setting up ubuntu ec2 t2 micro for webrtc and socketio

Setting up a ec2 instance on AWS for web real time communication platform over nodejs and socket.io using WebRTC .

Primarily a Web Call  , Chat and conference platform uses WebRTC for the media stream and socketio for the signalling . Additionally used technologies are nosql for session information storage , REST Apis foe getting sessions details to third parties.

Below is a comprehensive setup if ec2 t2.micro free tier instance  ,  installation with a webrtc project module and samples of customization and usuage .

Technologies used are listed below :

Server

  1. ec2 instance t2.micro covered under free tier
  2. domain name
  3. SSL certificate

Core module for Web Calling feature

  1. WebRTC
  2. Node.js
  3. socket.io

UI components

  1. javascript
  2. css
  3. html5
  4. bootstrap
  5. jquerry

Supporting setup for session management

  1. Code version-ing  and maintenance
  2. git
  3. npm

Amazon’s free tier ec2

Amazon EC2
ec2 instances are elastic compute general purpose storage servers that mean that they can resize the compute capacity in the cloud based on load .
750 hours per month of Linux, RHEL, or SLES t2.micro instance usage
Expires 12 months after sign-up.

Some other products are also covered under free tier which may come in handy for setting up the complete complatorm .Here is a quick summary

1.Amazon S3
it is a storage server. Can be used to store media file like image s, music , videos , recorded video etc .

2.Amazon RDS
It a relational database server . If one is using mysql or postgress for storing session information or user profile data . It is good option .

3.Amazon SES
email service. Can be used to send invites and notifications to users over mail for scheduled sessions or missed calls .

4.Amazon CloudFront
It is a CDN ( content delivery network ) . If one wants their libraries to be widly available without any overheads . CDN is a good choice .

Server Setup

Set up environment by installing nvm  , npm  and git ( source version control)

1. NVM ( node version manager )

cURL:

curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.31.1/install.sh | bash

or Wget:

wget -qO- https://raw.githubusercontent.com/creationix/nvm/v0.31.1/install.sh | bash&amp;amp;amp;amp;amp;amp;amp;amp;amp;lt;/code&amp;amp;amp;amp;amp;amp;amp;amp;amp;gt;

To check installation

command -v nvm
nvm

2. NPM( node package manager)

sudo apt-get install npm

Screenshot from 2016-05-16 12-41-42

2. Git

sudo apt-get install git

Screenshot from 2016-05-17 11-25-01

 SSL certificates

Since 2015 it has become mandatory to have only https origin request WebRTC’s getUserMedia API ie Voice, video, geolocation , screen sharing require https origins.
Note that this does not apply to case where its required to only serve peer’s media Stream or using Datachannels . Voice, video, geolocation , screen sharing now require https origins

For A POC purpose here is th way of generating a self signed certificate
Transport Layer Security and/or Secure Socket Layer( TLS/SSL) is a public/private key infrastructure.Following are the steps

1.create a private key
openssl genrsa -out webrtc-key.pem 2048

2.Create a “Certificate Signing Request” (CSR) file
openssl req -new -sha256 -key webrtc-key.pem -out webrtc-csr.pem

3.Now create a self-signed certificate with the CSR,
openssl x509 -req -in webrtc-csr.pem -signkey webrtc-key.pem -out webrtc-cert.pem

However in production or actual implementation it is highly recommended to use a signed certificate by CA as For examples include
Godaddy (https://ca.godaddy.com/web-security/ssl-certificate) , Comoddo (https://ssl.comodo.com/) , Global Sign (https://www.globalsign.com/en/ssl/managed-ssl/) , Symantec (https://www.symantec.com/ssl-certificates) etc .

Web Server

create https certificate using self generate or purchased SSL certificates using fs , node-static and https modules . To know how to create self generated SSL certificates follow section above on SSL certificates.

var fs = require(‘fs’);
var _static = require(‘node-static’);
var https = require(‘https’);

var file = new _static.Server(&amp;amp;amp;amp;amp;amp;amp;quot;./&amp;amp;amp;amp;amp;amp;amp;quot;, {
cache: 3600,
gzip: true,
indexFile: &amp;amp;amp;amp;amp;amp;amp;quot;index.html&amp;amp;amp;amp;amp;amp;amp;quot;
});

var options = {
key: fs.readFileSync(‘ssl_certs/webrtc-key.pem’),
cert: fs.readFileSync(‘ssl_certs/webrtc-cert.pem’),
ca: fs.readFileSync(‘ssl_certs/webrtc-csr.pem’),
requestCert: true,
rejectUnauthorized: false
};

var app = https.createServer(options, function(request, response){
request.addListener(‘end’, function () {
file.serve(request, response);
}).resume();
});

app.listen(&amp;amp;amp;amp;amp;amp;amp;quot;8080&amp;amp;amp;amp;amp;amp;amp;quot;);

Web servers work with the HTTP (and HTTPS) protocol which is TCP based. As a genral rule TCP establishes connection whereas UDP send data packets

 

Scoketio signalling server as npm

Socket.io determines which of the following real-time communication method is suited to the particular client and its network bandwidth .

  • WebSocket
  • Adobe Flash Socket
  • AJAX long polling
  • AJAX multipart streaming
  • Forever Iframe
  • JSONP Polling

The socket.io server needs a HTTP Server for initial handshake.

The general steps for socketio signalling server are:

1.require socket.io and keep the reference. like
var io = require(‘socket.io’)

2.Create your http / https server
outline in section on webserver

3.bind your http and https servers (.listen)
io.listen(app, {
log: false,
origins: ‘*:*’
});

4. Optionally set transport
io.set(‘transports’, [
‘websocket’
]);

4.setup io events as
io.sockets.on(‘connection’, function (socket) {

//Do domething
});

Note that Socket.io or websockets require an http server for the initial handshake.
&amp;amp;lt;pre&amp;amp;gt;Install ssocketio npm module&amp;amp;lt;/pre&amp;amp;gt;&amp;amp;lt;pre&amp;amp;gt;
npm install socket.io
[/sourcecode ]

Complete code for signalling server

var io = require(‘socket.io’).listen(app, {
log: false,
origins: ‘*:*’
});

io.set(‘transports’, [
‘websocket’
]);

var channels = {};

io.sockets.on(‘connection’, function (socket) {

console.log(&amp;amp;amp;amp;amp;amp;amp;quot;connection &amp;amp;amp;amp;amp;amp;amp;quot;);
var initiatorChannel = ”;

if (!io.isConnected) {
io.isConnected = true;
}

socket.on(‘namespace’,function(data){
onNewNamespace(data.channel, data.sender);
});

socket.on(‘new-channel’, function (data) {
if (!channels[data.channel]) {
initiatorChannel = data.channel;
}
console.log(&amp;amp;amp;amp;amp;amp;amp;quot;————new channel &amp;amp;amp;amp;amp;amp;amp;quot;, data.channel , &amp;amp;amp;amp;amp;amp;amp;quot; by &amp;amp;amp;amp;amp;amp;amp;quot; , data.sender);
channels[data.channel] = {
channel: data.channel,
users:[data.sender]
};

});

socket.on(‘join-channel’, function (data) {
console.log(&amp;amp;amp;amp;amp;amp;amp;quot;————join&amp;amp;amp;amp;amp;amp;amp;amp;nbsp;channel &amp;amp;amp;amp;amp;amp;amp;quot;, data.channel , &amp;amp;amp;amp;amp;amp;amp;quot; by &amp;amp;amp;amp;amp;amp;amp;quot; , data.sender);
channels[data.channel].users.push(data.sender);
});

socket.on(‘presence’, function (channel) {
var isChannelPresent = !! channels[channel.channel];
console.log(&amp;amp;amp;amp;amp;amp;amp;quot;presence for channel &amp;amp;amp;amp;amp;amp;amp;quot; ,isChannelPresent);
socket.emit(‘presence’, isChannelPresent);
});

socket.on(‘disconnect’, function (channel) {
});

socket.on(&amp;amp;amp;amp;amp;amp;amp;quot;admin_enquire&amp;amp;amp;amp;amp;amp;amp;quot;,function(data){
switch (data.ask){
case &amp;amp;amp;amp;amp;amp;amp;quot;channels&amp;amp;amp;amp;amp;amp;amp;quot;:
socket.emit(‘response_to_admin_enquire’, channels);
break;
case &amp;amp;amp;amp;amp;amp;amp;quot;channel_clients&amp;amp;amp;amp;amp;amp;amp;quot;:
socket.emit(‘response_to_admin_enquire’, io.of(‘/’ + data.channel).clients());
break;
default :
socket.emit(‘response_to_admin_enquire’, channels);
}

});

});

function onNewNamespace(channel, sender) {
console.log(&amp;amp;amp;amp;amp;amp;amp;quot; —–&amp;amp;amp;amp;amp;amp;amp;amp;gt; onNewNamespace &amp;amp;amp;amp;amp;amp;amp;quot;, channel);

io.of(‘/’ + channel).on(‘connection’, function (socket) {

var username;
if (io.isConnected) {
io.isConnected = false;
socket.emit(‘connect’, true);
}

socket.on(‘message’, function (data) {
if (data.sender == sender) {
if(!username) username = data.data.sender;
socket.broadcast.emit(‘message’, data.data);
}
});

socket.on(‘disconnect’, function() {
if(username) {
socket.broadcast.emit(‘user-left’, username);
username = null;
}
});
});
}

 

WebRTC main HTML5  project

This is the front  end section of the whole exercise . It contains JavaScript , css and html5 to make a webrtc call

<html lang=en>
<head>
<title>WebRTC Call</title>

<meta http-equiv=Content-Type content="text/html; charset=UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">

	<link rel=stylesheet href="https://ec2-54-193-124-35.us-west-1.compute.amazonaws.com:8084/minScripts/webrtcdevelopment_header.css">
<script src="https://ec2-54-193-124-35.us-west-1.compute.amazonaws.com:8084/minScripts/webrtcdevelopment_header.js"> </script>

<style type="text/css">
video{
width:100% !important;
}
body{
background: #2B2B2B;
}
</style>
</head>

<body id="pagebody">
<div id="elementToShare" class="container-fluid">
<!-- ................................ top panel ....................... -->
<div class="row topPanelClass" >
<div id="topIconHolder" >
<ul id="topIconHolder_ul">
	<li hidden> <span id="username" class="userName" hidden>a</span></li>
	<li hidden> <span id="numbersofusers" class="numbers-of-users" hidden></span></li>
	<li> <span id="HelpButton" class="btn btn-info glyphicon glyphicon-question-sign topPanelButton" data-toggle="modal" data-target="#helpModal" > Help </span></li>
</ul>
</div>
</div>
<!-- .............alerts................. -->
<div class="row" id="alertBox" hidden="true"></div>
<!-- .......................... Row ................................ -->
<div class="row thirdPanelClass">
<div class="col-xs-12 videoBox merge" id="videoHold">
<div class="row users-container merge" id="usersContainer" >
<div class="CardClass" id="card">

<!-- when no remote -->
<div id="local" class="row" hidden="">
<video name="localVideo" autoplay="autoplay" muted="true" />
</div>
<!-- when remote is connected -->
<div id ="remote" class="row" style="display:inline" hidden>
<div class="col-sm-6 merge" class="leftVideoClass" id="leftVideo">
<video name="video1" hidden autoplay="autoplay" muted="true" ></video>
</div>
<div class="col-sm-6 merge" class="rightVideoClass" id="rightVideo" >
<video name="video2" hidden autoplay="autoplay" ></video>
</div>
</div>
</div>
</div>
</div>
</div>
<!--modal help -->
<div class="modal fade" id="helpModal" role="dialog">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">&times;</button>
<h4 class="modal-title">Help</h4>
</div>
<div class="modal-body">
WebRTC Runs in only https due to getusermedia security contraints
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
</div>
</body>

	<link rel=stylesheet href="https://ec2-54-193-124-35.us-west-1.compute.amazonaws.com:8084/minScripts/webrtcdevelopment.css">
<script src="https://ec2-54-193-124-35.us-west-1.compute.amazonaws.com:8084/minScripts/webrtcdevelopment.js"> </script>

<script>
$('document').ready(function(){

 sessionid= init(true);

 var local={
 localVideo: "localVideo",
 videoClass:"",
 userDisplay:false,
 userMetaDisplay:false 
 };

 var remote={
 remotearr: ["video1" , "video2"],
 videoClass:"",
 userDisplay:false,
 userMetaDisplay:false 
 };

 webrtcdomobj= new WebRTCdom(
 local,remote
 );

 var session ={
 sessionid : sessionid,
 socketAddr: "https://localhost:8084/"
 };

 var webrtcdevobj = new WebRTCdev ( session, null, null , null );

 startcall();
});
</script>
</html>
Screenshot from 2016-05-17 12-12-37.png

Common known issues:

1.Opening page https://<web server ip>:< web server port>/index.html says insecure

This is beacuse the self signed certificates produced by open source openSSL is not recognized by a trusted third party Certificate Agency.
A CA ( Certificate Authority ) issues digital certificate to certify the ownership of a public key for a domain.

To solve the access issue goto https://<web server ip>:< web server port> and given access permission such as outlined in snapshot below

image

2.Already have given permission to Web Server , page loads but yet no activity .

if you open developer console ( ctrl+shift+I on google chrome ) you will notice that there migh be access related errros in red .
If you are using different server for web server and signalling server or even if same server but different ports you need to explicity go to the signalling server url and port and give access permission for the same reason as mentione above.
3.no webcam capture on opening the page

This could happen due to many reasons

  •  page is not loaded on https
  • browser is not webrtc compatible
  • Media permission to webcam are blocked
  • the machine does have any media capture devices attached
  •  Driver issues in the client machine while accessing webcams and mics .

4.socketio + code: 0, message: “Transport unknown”

Due to the version  v1.0.x of socket.io while performing handshake . To auto correct this , downgrade to v0.9.x

 

 

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.

SIP Server without RTP proxy
SIP Server with Media Proxy
RTP Engine Features

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
  • In-kernel packet forwarding for low-latency and low-CPU performance .

Source Code

There are 3 parts of the source code :

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. For example, if the command uname -r produces the output 3.9-1-amd64, then the kernel headers must be present in /lib/modules/3.9-1-amd64/build/. The last component of this path (build) is usually a symlink somewhere into /usr/src/, which is fine.

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 (which will result in an error if depending modules aren’t loaded, for example the x_tables module), but it’s 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

Installation

cd rtpengine
./debian/flavors/no_ngcp

Use dpkg-checkbuilddeps to find any missing dependencies

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 : 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=10.64.73.31 \
--listen-ng=127.0.0.1:2223 --tos=184 --pidfile=/run/rtpengine-10.pid --no-fallback
/usr/sbin/rtpengine --table=1 --interface=192.168.65.73 \
--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

a single interface:
interface = 123.234.345.456

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

for different advertised address:
interface = 12.23.34.45!23.34.45.56

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

[rtpengine-testing]

table = -1
interface = x.x.x.x
listen-ng = 2223
foreground = true
log-stderr = true
log-level = 7

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 192.168.1.23
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/rtpengine-meta-732597d6-6d96-485b-b6dc-7d93703c1405-d4da26d04ccd55f8.tmp
Writing recording file: /var/spool/rtpengine/pcaps/732597d6-6d96-485b-b6dc-7d93703c1405-d4da26d04ccd55f8.pcap
DDefault sink codec is PCMU/8000
Creating codec handler for PCMU/8000
Sink supports codec PCMU/8000
Creating codec handler for ILBC/8000
Creating codec handler for telephone-event/8000
DEBUG: [ID="732597d6-6d96-485b-b6dc-7d93703c1405"]: creating send_timer
message repeated 3 times: [creating send_timer]
set FILLED flag for stream 192.168.1.23:50754
set FILLED flag for stream 192.168.1.23:50755
RE-Establishing connection for Redis server 127.0.0.1:6379
Failed to connect to Redis 127.0.0.1:6379, error: Connection refused
Replying to 'offer' from :53888 (elapsed time 0.002499 sec)
Response dump for 'offer' to :53888: {
"recordings":[
"/var/spool/rtpengine/pcaps/732597d6-6d96-485b-b6dc-7d93703c1405-d4da26d04ccd55f8.pcap"
],
"sdp":"v=0
o=- 1554978148897419 1 IN IP4 35.173.134.94
s=Bria 3 release 3.5.5 stamp 71243
c=IN IP4 35.173.134.94
t=0 0
m=audio 10032 RTP/AVP 0 98 101
a=rtpmap:0 PCMU/8000
a=rtpmap:98 ILBC/8000
a=rtpmap:101 telephone-event/8000
a=fmtp:101 0-15
a=sendrecv
",
"result":"ok"
}

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,
ml0_remote_tag=(null),
payload_type=unknown,
ml0_midx1_rtp_endpoint_ip=,
ml0_midx1_rtp_endpoint_port=50754,
ml0_midx1_rtp_local_relay_ip=,
ml0_midx1_rtp_local_relay_port=10044,
ml0_midx1_rtp_relayed_packets=0,
ml0_midx1_rtp_relayed_bytes=0,
ml0_midx1_rtp_relayed_errors=0,
ml0_midx1_rtp_last_packet=1554978149,
ml0_midx1_rtp_in_tos_tclass=0,
ml0_midx1_rtcp_endpoint_ip=,
ml0_midx1_rtcp_endpoint_port=50755,
ml0_midx1_rtcp_local_relay_ip=,
ml0_midx1_rtcp_local_relay_port=10045,
ml0_midx1_rtcp_relayed_packets=0,
ml0_midx1_rtcp_relayed_bytes=0,
ml0_midx1_rtcp_relayed_errors=0,
ml0_midx1_rtcp_last_packet=1554978149,
ml0_midx1_rtcp_in_tos_tclass=0,
ml1_start_time=1554978149.643080,
ml1_end_time=1554978154.822681,
ml1_duration=5.179601,
ml1_termination=REGULAR,
ml1_local_tag=(null),
ml1_local_tag_type=UNKNOWN,
ml1_remote_tag=cb8a1e30,
payload_type=unknown,
ml1_midx1_rtp_endpoint_ip=(null),
ml1_midx1_rtp_endpoint_port=0,
ml1_midx1_rtp_local_relay_ip=,
ml1_midx1_rtp_local_relay_port=10032,
ml1_midx1_rtp_relayed_packets=0,
ml1_midx1_rtp_relayed_bytes=0,
ml1_midx1_rtp_relayed_errors=0,
ml1_midx1_rtp_last_packet=1554978149,
ml1_midx1_rtp_in_tos_tclass=0,
ml1_midx1_rtcp_endpoint_ip=(null),
ml1_midx1_rtcp_endpoint_port=0,
ml1_midx1_rtcp_local_relay_ip=,
ml1_midx1_rtcp_local_relay_port=10033,
ml1_midx1_rtcp_relayed_packets=0,
ml1_midx1_rtcp_relayed_bytes=0,
ml1_midx1_rtcp_relayed_errors=0,
ml1_midx1_rtcp_last_packet=1554978149,
ml1_midx1_rtcp_in_tos_tclass=0,

Moved metadata file “/var/spool/rtpengine/tmp/rtpengine-meta-732597d6-6d96-485b-b6dc-7d93703c1405-d4da26d04ccd55f8.tmp” to “/var/spool/rtpengine/metadata”
Replying to ‘delete’ from :57304 (elapsed time 0.004932 sec)
Response dump for ‘delete’ to :57304:{
“created”:1554978149,
“created_us”:640995,
“last signal”:1554978149,
“SSRC”:{
},
“tags”:{
“cb8a1e30”:{
“tag”:”cb8a1e30″,
“created”:1554978149,
“in dialogue with”:””,
“medias”:[
{
“index”:1,
“type”:”audio”,
“protocol”:”RTP/AVP”,
“streams”:[
{
“local port”:10044,
“endpoint”:{
“family”:”IPv4″,
“address”:””,
“port”:50754
},
“advertised endpoint”:{
“family”:”IPv4″,
“address”:””,
“port”:50754
},
“last packet”:1554978149,
“flags”:[
“RTP”,
“filled”
],
“stats”:{
“packets”:0,
“bytes”:0,
“errors”:0
}
},
{
“local port”:10045,
“endpoint”:{
“family”:”IPv4″,
“address”:””,
“port”:50755
},
“advertised endpoint”:{
“family”:”IPv4″,
“address”:””,
“port”:50755
},
“last packet”:1554978149,
“flags”:[
“RTCP”,
“filled”
],
“stats”:{
“packets”:0,
“bytes”:0,
“errors”:0
}
}
],
“flags”:[
“initialized”,
“send”,
“recv”
]
}
]
},
“”:{
“tag”:””,
“created”:1554978149,
“in dialogue with”:”cb8a1e30″,
“medias”:[
{
“index”:1,
“type”:”audio”,
“protocol”:”RTP/AVP”,
“streams”:[
{
“local port”:10032,
“endpoint”:{

}
},
“totals”:{
“RTP”:{
“packets”:0,
“bytes”:0,
“errors”:0
},
“RTCP”:{
“packets”:0,
“bytes”:0,
“errors”:0
}
},
“result”:”ok”
}},
“advertised endpoint”:{ },
“last packet”:1554978149,
“flags”:[
“RTP”
],
“stats”:{
“packets”:0,
“bytes”:0,
“errors”:0
}
},
{
“local port”:10033,
“endpoint”:{ },
“advertised endpoint”:{ },
“last packet”:1554978149,
“flags”:[
“RTCP”
],
“stats”:{
“packets”:0,
“bytes”:0,
“errors”:0
}
}
],
“flags”:[
“send”,
“recv”,
“ICE controlling”
]
}
]
}
},
“totals”:{
“RTP”:{
“packets”:0,
“bytes”:0,
“errors”:0
},
“RTCP”:{
“packets”:0,
“bytes”:0,
“errors”:0
}
},
“result”:”ok”
}






Wowza REST APIs and HTTP Providers

This article show the different ways to make calls to Wowza Media Engine from external applications and environments for various purposes  such as getting server status , listeners , connections , applications and its streams etc .

HTTP Providers

HTTP Providers are Java classes that are configured on a per-virtual host basis.

 

Some pre packaged HTTP providers that return data in XML  :

1. HTTPConnectionCountsXML

Returns connection information like Vhost , application , application instance , message in bytes rate , message out byte rates etc.

http://%5Bwowza-ip-address%5D:8086/connectioncounts

Screenshot from 2015-11-24 20:23:51

2. HTTPConnectionInfo
Returns detailed connection information such as

http://%5Bwowza-ip-address%5D:8086/connectioninfo

server=1

3. HTTPServerVersion

Returns the Wowza Media Server version and build number. It’s the default HTTP Provider on port 1935.

url : http://%5Bwowza-ip-address%5D:1935

Wowza Streaming Engine 4 Monthly Edition 4.1.1 build13180

4. HTTPLiveStreamRecord

gets the web interface to record online streams

url : http://%5Bwowza-ip-address%5D:8086/livestreamrecord

Screenshot from 2015-11-24 20:22:16

5. HTTPServerInfoXML

Returns server and connection information

url :http://%5Bwowza-ip-address%5D:8086/serverinfo

Screenshot from 2015-11-24 20:34:08

 

6. HTTPClientAccessPolicy .

It is used for fetching the Microsoft Silverlight clientaccesspolicy.xml from the conf folder.

7. HTTPCrossdomain

To get the Adobe Flash crossdomain.xml file from [install-dir]/conf folder.

8.HTTPProviderMediaList

Dynamic method for generating adaptive bitrate manifests and playlists from SMIL data.

9.HTTPStreamManager

The Stream Manager returns all applications and their stream in web interface.

url http://%5Bwowza-ip-address%5D:8086/streammanager).

 

Screenshot from 2015-11-24 20:38:32

10 .HTTPTranscoderThumbnail

Returns a bitmap image from the source stream being transcoded.

url: http://%5Bwowza-ip-address%5D:8086/transcoderthumbnail?application=%5Bapplication-name%5D&streamname=%5Bstream-name%5D&format=%5Bjpeg or png]&size=[widthxheight]

Each HTTP provider can be configured with different request filter and authentication method ( none , basic , digest).  We can even create our own substitutes for the HTTP providers as defined in the next section .

extending HTTProvider2Base

The following code snippet describes the process of creating a Wowza Web services that return a json containing all the values .

Imports to build a HTTP provider


import com.wowza.wms.application.*;
import com.wowza.wms.vhost.*;
import com.wowza.wms.http.*;
import com.wowza.wms.httpstreamer.model.*;

//since we want to return in json format

import org.json.simple.JSONObject;

The class declaration is as folllows


public class DCWS extends HTTProvider2Base
{

....

}

The code to extract application names

 


public JSONObject listChannels(){

JSONObject obj=new JSONObject();

//get params from virtual host and iterate through it
List&amp;lt;String&amp;gt; vhostNames = VHostSingleton.getVHostNames();
Iterator&amp;lt;String&amp;gt; iter = vhostNames.iterator();
while (iter.hasNext())
{
String vhostName = iter.next();
IVHost vhost = (IVHost)VHostSingleton.getInstance(vhostName);
List&amp;lt;String&amp;gt; appNames = vhost.getApplicationNames();
Iterator&amp;lt;String&amp;gt; appNameIterator = appNames.iterator();

int i=0;
while (appNameIterator.hasNext())
{
String applicationName = appNameIterator.next();

try {
String key = &quot;channel&quot;+ (++i);
obj.put(key, URLEncoder.encode(applicationName, &quot;UTF-8&quot;));
}

catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
}
return obj;
}

 

 

The code which responds to HTTP request

TBD..

 

Ref :

http://www.wowza.com/forums/content.php?30-http-providers

http://www.wowza.com/forums/content.php?642-wowza-streaming-engine-rest-api

XMPP Client Server Setup and Programming

XMPP is a open XML technology for real-time communication. Applications are instant messaging, presence, media negotiation, whiteboarding, collaboration, lightweight middleware, content syndication, and generalized XML routing according to XMPP standards Foundation (XSF) .

Extensible Messaging and Presence Protocol (XMPP) is a communications protocol for message-oriented middleware based on XML (Extensible Markup Language). – wikipedia

XMPP Server

Some popular servers on XMPP are ejabbred ( written in erlang licensed by GPL2) and openfire ( written in Java licensed by Apache ). This article will show the installation steps for openfire on Ubuntu version 15 64 bit system

1.Install the tar from http://www.igniterealtime.org/downloads/index.jsp

Screenshot from 2015-09-25 15:12:02

2. Extract and move the folder to /opt

3. Goto bin and run  openfire server  with ./openfire start

Screenshot from 2015-09-24 12:46:12 (copy)

4. Gotot the web admin url http://localhost:9090/ .  For first time  the setup screen will appear

Screenshot from 2015-09-24 12:46:31

5.  Proceed with installation  .

Screenshot from 2015-09-24 12:46:12

It will show screens to select the mysql driver and database . Create a empty db name called openfiredb and add that to mysql url in setup screen of openfire

It will also request a administrator username and password I choose to give admin admin as the username and password alike .

6. change the interface inside of openfire.xml file in location /opt/openfire/conf

<network>
<interface>127.0.0.1</interface>
</network>

we can also review the mysql connection string

<database>
<defaultProvider>
<driver>com.mysql.jdbc.Driver</driver>
<serverURL>jdbc:mysql://127.0.0.1:3306/openfiredb?rewriteBatchedStatements=true</serverURL>
<username encrypted=”true”><<someval>></username>
<password encrypted=”true”> <<someval>></password>
<testSQL>select 1</testSQL>
<testBeforeUse>false</testBeforeUse>
<testAfterUse>false</testAfterUse>
<minConnections>5</minConnections>
<maxConnections>25</maxConnections>
<connectionTimeout>1.0</connectionTimeout>
</defaultProvider>
</database>

7. After the installation login to the server admin console with the admin username and password which is admin admin in our case

Screenshot from 2015-09-24 12:54:08

8.  Review the server settings etc from the admin web console

Screenshot from 2015-09-24 13:16:29

9. Incase the server setup did not go as planned we can reinstall the server again by dropping the database , creating a fresh empty database and modifying the following from true to false in openfire.xml file in location /opt/openfire/conf

<setup>true</setup>

Test the XMPP Server Installation using Spark client

1.Spark can also be downloaded from the same url as was used to download server . Choose your operating system for download

2.Register a spark client with the server

Screenshot from 2015-09-24 14:41:04

3. after registering the client presence should be indicated in the user summary by online status

Screenshot from 2015-09-25 12:55:13

4.Register another client with the same conf except username and password and perform messaging between them

Screenshot from 2015-09-24 14:45:57

XMPP Java Client

Source Code for a Simple Java Application using Smack4 communicating with XMPP servers


package testxmppsmack;

import java.io.IOException;

import org.jivesoftware.smack.ConnectionConfiguration.SecurityMode;
import org.jivesoftware.smack.SmackException;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smack.SmackException.NotConnectedException;
import org.jivesoftware.smack.chat.Chat;
import org.jivesoftware.smack.chat.ChatManager;
import org.jivesoftware.smack.chat.ChatMessageListener;
import org.jivesoftware.smack.packet.Message;
import org.jivesoftware.smack.tcp.XMPPTCPConnection;
import org.jivesoftware.smack.tcp.XMPPTCPConnectionConfiguration;

public class JabberSmackAPI {
 
 public static void main(String argsp[]){
 
 XMPPTCPConnectionConfiguration config = XMPPTCPConnectionConfiguration.builder()
 .setServiceName("machine")
 .setUsernameAndPassword("admin", "admin")
 .setCompressionEnabled(false)
 .setHost("127.0.0.1")
 .setPort(5222) 
 .setSecurityMode(SecurityMode.disabled)
/* .setSecurityMode(SecurityMode.required) keep this commented */ 
 .setSendPresence(true) 
 .build();
 
 // Create a connection to the the local XMPP server as defined in config above.
 XMPPTCPConnection con = new XMPPTCPConnection(config);
 
 // Connect to the server code is encapsulated in try/catch block for exception handling
 try {
 con.connect();
 System.out.println("Connected "+con.isConnected());
 } catch (SmackException | IOException | XMPPException e1) {
 // TODO Auto-generated catch block
 e1.printStackTrace();
 }
 
 //Login before performing other tasks like messaging etc 
 try {
 con.login("altanai", "aaa");
 System.out.println("Loggedin "+con.isAuthenticated());
 } catch (XMPPException | SmackException | IOException e) {
 // TODO Auto-generated catch block
 e.printStackTrace();
 }
 
 
 // Start a new conversation with another account holder caled altanaibisht ( I created 2 user accounts one with my first name and another with fullname) 
 Chat chat = ChatManager.getInstanceFor(con).createChat("altanaibisht@localhost");
 
 try {
 chat.sendMessage("Did you try out the new code i send you last night ?");
 System.out.println("Chat Send ");
 } catch (NotConnectedException e) {
 // TODO Auto-generated catch block
 e.printStackTrace();
 }

 // Disconnect from the server
 con.disconnect();


}
}


Some errors and their resolution while building and running the above code as Java Application are as follows :

1. Cannot instantiate XMPPConnection
Use XMPPTCPConnection instead of XMPPConnection in Smack 4.

2. Caused by: java.lang.ClassNotFoundException: org.xmlpull.v1.XmlPullParserFactory

need to have XPP3 (XML Pull Parser 3) in your classpath. Smack 4 does no longer bundle it (unlike Smack 3).

Download the xpp3 from http://www.extreme.indiana.edu/dist/java-repository/xpp3/distributions/

ref :http://stackoverflow.com/questions/24196588/smack-throws-java-lang-classnotfoundexception-org-xmlpull-v1-xmlpullparserfact

3. Exception in thread “main” java.lang.NoClassDefFoundError: de/measite/minidns/DNSCache

http://mvnrepository.com/artifact/de.measite.minidns/minidns/0.1.3

4.  For the jxmpp-util-cache-0.5.0-alpha2.jar

Install it from http://mvnrepository.com/artifact/org.jxmpp/jxmpp-util-cache/0.5.0-alpha2

5.Exception in thread “main” java.lang.NoClassDefFoundError: org/jxmpp/util/XmppStringUtils

http://mvnrepository.com/artifact/org.jxmpp/jxmpp-core/0.4.1

6. Exception in thread “main” java.lang.NoClassDefFoundError: org/apache/http/conn/ssl/StrictHostnameVerifier

http://www.java2s.com/Code/Jar/a/Downloadapachehttpcomponentshttpclientjar.htm

7.Exception in thread “main” java.lang.NoClassDefFoundError: org/xbill/DNS/Lookup

http://www.java2s.com/Code/Jar/d/Downloaddnsjava211jar.htm

8.org.jivesoftware.smack.SmackException$ConnectionException: The following addresses failed: ‘machine:5222’ failed because java.net.ConnectException: Connection refused

.setHost(“127.0.0.1”)
.setPort(5222)

9. org.jivesoftware.smack.SmackException: javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

.setSecurityMode(SecurityMode.disabled)

Once the program build and runs succesfully connecting to the XMPP server ( which is running ofcourse ) , open a sapark client and test the application with it.

Screenshot from 2015-09-25 12:44:55

Summary

An alternative to XMPP messaging is the SIP for Instant Messaging and Presence Leveraging Extensions (SIMPLE) based on Session Initiation Protocol (SIP).

References :

1.XMPP.org
https://xmpp.org/

2.Getting started from Igniterealtime.org
https://www.igniterealtime.org/builds/smack/docs/latest/documentation/gettingstarted.html

3.IETF RFCs on XMPP ( 2004 ) –
RFC 3920 http://www.ietf.org/rfc/rfc3920.txt
RFC 3921 http://www.ietf.org/rfc/rfc3921.txt

4. Extensions on XMPP
http://xmpp.org/xmpp-protocols/xmpp-extensions/

5. XMPP API explanation by grepcode
http://grepcode.com/file/repo1.maven.org/maven2/org.igniterealtime.smack/smack-core/4.0.0-rc1/org/jivesoftware/smack/XMPPConnection.java

Wowza Secure URL params Authentication for streams in an application

To secure the publishers for a common application through username -password specific for streamnames , this post is useful . It  uses Module Core Security to prompt back the user for supplying credentials.

The detailed code to check the rtmp query-string for parameters  and performs the checks –  is user is allowed to connect and is user allowed to stream on given streamname is given below .

Initialize the hashmap containing publisher clients and IapplicationInstance

	HashMap <Integer, String> publisherClients =null;
	IApplicationInstance appInstance = null;

On app start initilaize the IapplicationInstance object .

	public void onAppStart(IApplicationInstance appInstance)
	{
		this.appInstance = appInstance;
	}

Onconnect is called called when any publisher tries to connects with media server. At this event collect the username and clientId from the client.
Check if publisherclient contains the userName which client has provided else reject the connection .


	public void onConnect(IClient client, RequestFunction function, AMFDataList params)
	{

		AMFDataObj obj = params.getObject(2);
		AMFData data = obj.get("app");

		if(data.toString().contains("?")){

			 String[] paramlist = data.toString().split();
			 String[] userParam = paramlist[1].split("=");
			 String userName = userParam[1];

			if(this.publisherClients==null){
				this.publisherClients = new HashMap<Integer, String>();
			}

			if(this.publisherClients.get(client.getClientId())==null){
				this.publisherClients.put(client.getClientId(),userName);
			} else {
				client.rejectConnection();
			}
		}
	}

AMFDataItem: class for marshalling data between Wowza Pro server and Flash client.

As the event user starts to publish a stream after sucessful connection Onpublishing function is called . It extracts the stream name from the client ( function extractStreamName() )and checks if user is allowed to stream on the given streamname (function isStreamNotAllowed()) .

	public void publish(IClient client, RequestFunction function, AMFDataList params)
	{
		String streamName = extractStreamName(client, function, params);
		if (isStreamNotAllowed(client, streamName))
		{
			sendClientOnStatusError(client, NetStream.Publish.Denied, "Stream name not allowed for the logged in user: "+streamName);
			client.rejectConnection();
		}
		else{
			 invokePrevious(client, function, params);
		}

	}

Function when publisher disconnects from server . It removes the client from publisherClients.

	public void onDisconnect(IClient client)
	{
		if(this.publisherClients!=null){
			this.publisherClients.remove(client.getClientId());
		}
	}

The function to extract a streamname is


public String extractStreamName(IClient client, RequestFunction function, AMFDataList params)
{
String streamName = params.getString(PARAM1);
if (streamName != null)
{
String streamExt = MediaStream.BASE_STREAM_EXT;

String[] streamDecode = ModuleUtils.decodeStreamExtension(streamName, streamExt);
streamName = streamDecode[0];
streamExt = streamDecode[1];
}

return streamName;
}

The fucntion to check if streamname is allowed for the given user


public boolean isStreamNotAllowed(IClient client, String streamName)
{
WMSProperties localWMSProperties = client.getAppInstance().getProperties();
String allowedStreamName = localWMSProperties.getPropertyStr(this.publisherClients.get(client.getClientId()));
String sName="";
if(streamName.contains("?"))
sName = streamName.substring(0, streamName.lastIndexOf(&amp;amp;quot;?&amp;amp;quot;));
else
sName = streamName;
return !sName.toLowerCase().equals(allowedStreamName.toLowerCase().toString()) ;
}

On adding the application to wowza server make sure that the ModuleCoreSecurity is present under Modules in Application.xml

<Module>
<Name>ModuleCoreSecurity</Name>
<Description>Core Security Module for Applications</Description>
<Class>com.wowza.wms.security.ModuleCoreSecurity</Class>
</Module>

Also ensure that property securityPublishRequirePassword is present under properties

<Property>
<Name>securityPublishRequirePassword</Name>
<Value>true</Value>
<Type>Boolean</Type>
</Property>

Add the user credentials as properties too. For example to give access to testuser with password 123456 to stream on myStream include the following ,

<Property>
<Name>testUser</Name>
<Value>myStream</Value>
<Type>String</Type>
</Property>

Also include the mapping of user and password inside of conf/publish.password file

# Publish password file (format [username][space][password])
#username password

testuser 123456

Remote machine control via Rpi

Raspberry pi

The Raspberry Pi is a series of credit card-sized single-board computers. It can be used to build hardware along with software system . It essentially acts like a mini computer where we can install our programs and work on them pretty much like a regular computer . However the applications of Rpi is really diversifies from making robots to kiosks , surveillance system to remote control agents etc .

Yes the new model B+ is out yet I have an old B model and I am trying ot most of the things using it before making the investment of purchasing a  new one .

2 3(images from : http://www.adafruit.com/products/998)

Configuration :

  • The design is based around a Broadcom BCM2835 SoC, which includes an ARM1176JZF-S 700 MHz processor, VideoCore IV GPU, and 512 Megabytes of RAM.
  • The design does not include a built-in hard disk or solid-state drive, instead relying on an SD card for booting and long-term storage.
  • This board is intended to run Linux kernel based operating systems.
  • Generic USB keyboards and mice are compatible with it .
  • It does not come with a real-time clock, so an OS must use a network time server, or ask the user for time information at boot time to get access to time and date info for file time and date stamping. However a real time clock (such as the DS1307) with battery backup can be easily added via the I2C interface.

Physical architecture :

rpib

Pin Model :

p1header

Rpi model B startup

Requirements for boot

  1. Power supply
  2. HDMI cable to connect to HDMI tv or HDMI to VGA adapterto connect to monitor
  3. power charger ( micro USB same as phone )
  4. SD card upto 8 GB ( in case its a micro SD card then SD card adpater as well)
  5. monitor
  6. keyboard
  7. mouse
  8. internet through ethernet
  9. ethernet wire

Steps:

top view of the board

top view of the board

HDMI connector for screen display from Rpi

HDMI connector for screen display from Rpi

NOOBS

NOOBS

Raspbian start

Raspbian start

rpi5 rpi6 rpi8 rpi9

Default id : pi  default password : raspberry

Default id : pi
default password : raspberry

OS boot up

OS boot up

rpi12

raspbian on Raspberry pi

raspbian on Raspberry pi

run sudo apt-get update

run sudo apt-get update


 RPI model B to LED glow using timers in python

Aim :

First time booting Raspbian on Raspberry pi Model B . Connecting it to LED ( series with resistor ) and controlling the on -off process using timer logic written in python .

Requirements :

  1. Rs(RaspberryPi)
  2. Power supply
  3. Ethernet wire(3m)
  4. SDcard or micro SD card with adpater
  5. Breadboard
  6. LED(7)
  7. resistors(1k )(7)
  8. button
  9. breadboard wires

Steps :

1. Manual ON and OFF of LED on Rpi GPIO

To manually make the LED turn ON and OFF ,  make a serial connection of two GPIO pins with a LED  and resistor ( shown in the picture )

rpi15

  • Open terminal and sudo su  to :/home/pi#
  • #echo25>/sys/class/gpio/export
  • File manager -> /home/pi -> sys -> class ->gpio -> gpiochip0 -> device -> gpio ->gpio25 , Change directory to this location
  • #cd /sys/class/gpio/gpiochip0/device/gpio/gpio25
  • List all files , with gpio#ls

To give output to LED through the pin 25 :

  • echo out>direction ( set this pin as output)
  • To tuen ON the LED , write 1 to the value of pin echo 1> value

To take input through pin 24 through a button

  • connect button to pin 24 of Rpi as earlier
  • echo in >direction
  • see the changes on pressing the button on cat value

2. GPIO control with WiringPi library

  • Install git , sudo apt-get innstall git-core
  • Get the sourcecode with :sudo git clone git://git.drogon.net/wiringpi
  • cd wiringPi
  • ./build
  • $gpio -v
  • $gpio readall

To turn ON or OFF the first LED wiring pin 0 , set the pin as an output  -> gpio mode 0 out

  • To turn ON LED  -> $gpio write 0 1
  • To turn OFF  -> $gpio write 0 0

To read from a digital switch on wiringPin no

  • $ gpio read 0

Applications:

1.  Timer based control

Following are the steps to make and execute a LED  control using timers in python .


 Machine control through RPi via Mobile app on Internet

Aim :

Controlling a machine via Rpi hub connected to internet . Users can control machine behavior through a web page or mobile app .

Steps:

1. Install Raspbian wheezy ( details of installation are provided in the 1fisrt application on this page )

2. Get win32 Disk-manager 0.25 and dump into raspberry

3. Connect the Rpi via Ethernet wire to internet router . Find IP address of Rpi client by checking the router default console .

4. Connect the Rpi to remote machine

For Linux remote machine OS –Install tightVNC server

  • ssh  raspberrypi_username@ipaddress
  • sudo apt-get updates
  • sudo apt-get install tightvncserver
  • During installation supply a username and password example , username pi  , password altanai.

The viewer for VNC could be Remmina VNC viewer on linux

  • Incoming VNC server .
  • Enter username and password

For Windows  remote machine OS –Install putty

  • Enter Rpi_ip:port
  • login as pi given password  for example altanai

5. For the webpage

  • Install a web server  :sudo apt-get install apache2 php5 libapache2-mod-php5
  • transfer the web page for machine control  to Rpi inside /var/www
  • index.phpo :  <?php phpinfo(); ?>
  • ctrl+ o to save , ctrl + x to exit
  • change permission fr user pi :  chown -R pi /var/www
  • test the webpage at http://rpi_address

6. For the android app

7. To control real machine like fan , tubelight , washing machine  , connect the output of Rpi to relay.

8. To control the machines from anywhere on the internet , this page need to be on public DNS . There fore host the website on public server like amazon Ec2 instance .

Light Fan control Rpi web

 


Ref :

  1. http://www.adafruit.com/products/998
  2. http://www.raspberrypi.org/
  3. http://www.instructables.com/id/Simple-and-intuitive-web-interface-for-your-Raspbe/

Telephony Solutions with Kamailio

Kamailio™ (former OpenSER) is an Open Source SIP Server released under GPL.

Kamailio primarily acts as a SIP server for VOIP and telecommunications platforms under various roles and can handle load of hight CPS ( Calls per second ) with custom call routing logic with the help of scripts .

Rich features set suiting to telephony domain that includes IMS extensions for VoLTE; ENUM; DID and least cost routing; load balancing; routing fail-over; Json and XMLRPC control interface, SNMP monitoring.

To integrate with a carrier grade telecom network as SBC / gateway / inbound/outbound proxy , it can act as IPv4-IPv6 gateway , UDP/TCP/SCTP/WS translator and even had NAT and anti DOS attack support .

If Kamailio is the central to the VoIP system it can also perform accounting with rich database extensions Mysql PostgreSQL UnixODBC Berkeley DB Oracle Redis, MongoDB Cassandra etc

  • Kamailio is SIP (RFC3261) compliant

It can work as Registrar or Location server. For SIP call logic it can become a Proxy or SIP Application server. Can also act like a Redirect , Dispatcher or simply a SIP over websocket server.

  • Kamailio is Customisable to suit business requirement and scale .

It can be embedded to devices as the binary file is small size. Additional modules can be appended for more functions with the same core.

Due to its modular architecture – core, internal libraries , module interface and ability to extend functionality with scripts such as LUA , Kamailio can be readily integrated to a VOIP ecosystem.

  • Call routing and control with Scripting and programming

Offers stateless and transactional stateful SIP Proxy processing ( suited for inbound gateways ) and serial and parallel forking.

Also NAT traversal support for SIP and RTP traffic ( suited to be WebRTC server )

Among other features it offers load balancing with many distribution algorithms and failover support , flexible least cost routing , routing failover and replication for High Availability (HA).

Can be readily integrated with external databases , caches, notification system ( SNS , APNS , GCM ), voip monitors , CDR processors, API systems etc for  efficient call processing.

  • Transport Layers supported 

    • UDP, TCP, TLS and SCTP
    • IPv4 and IPv6
    • gateways via (IPv4 to IPv6, UDP to TLS, a.s.o.)
    • SCTP multi-homing and multi-streaming
    • WebSocket for WebRTC 
  • Asynchronous TCP, UDP and SCTP,

asynchronous SIP message processing and  inter-process message queues communication system

  • Secure Communication ( TLS  + AAA)

    • Digest SIP User authentication
    • Authorization via ACL or group membership
    • IP and Network authentication
    • TLS support for SIP signaling
    • transparent handling of SRTP for secure audio
    • TLS domain name extension support
    • authentication and authorization against database (MySQL, PostgreSQL, UnixODBC, BerkeleyDB, Oracle, text files), RADIUS and DIAMETER
  • IP and DNS

    • support for SRV and NAPTR DNS lookups
    • SRV DNS failover
    • DNSsec support
    • ENUM support
    • internal DNS caching system – avoid DNS blocking
    • IP level Blacklists
    • multi-homed and multi-domain support
    • topology hiding – hide IP addresses in SIP headers to protect your network architecture
  • Accounting

Kamailio gives event based and configurable accounting data details. Can show multi-leg call accounting ( A leg to B leg ). It can store to database, Radius or Diameter based on module used . Has a prepaid engine.

  • External Interaction

text-based management interface via FIFO file, udp, xmlrpc and unix sockets.

RPC control interface – via XMLRPC, UDP or TCP

  • Rich Communication Services (RCS)

    • SIP SIMPLE Presence Server (rich presence)
    • Presence User Agent ( SUBSCRIBE , NOTIFY and PUBLSH)
    • XCAP client capabilities and Embedded XCAP Server
    • Presence DialogInfo support – SLA/BLA
    • Instant Messaging ( IM) 
    • Embedded MSRP relay
  • Monitoring and Troubleshooting

Support for SNMP – interface to Simple Network Management Protocol.  For Debugging it has config debugger , remote control via XMLRPC and error message logging system .Provides internal statistics exported via RPC and SNMP.

  • Extensibility APIs

The supported  one are Perl  , Java SIP Servlet Application Interface  , Lua  , Managed Code (C#) , Python

  • Multiple Database Backends

(MySQL, PostgreSQL, SQLite, UnixODBC, BerkeleyDB, Oracle, text files) and other database types which have unixodbc drivers. ‘

It can have connections pool and different backends  be used at same time (e.g., accounting to Oracle and authorization against MySQL).

Has connectors for Memcached, Redis , MongoDB and Cassandra no-SQL backends

  • Interconnectivity

Acts as SIP to PSTN gateway and gateway to sms or xmpp and other IM services. Has Interoperability with SIP enabled devices and applications such as SIP phones (Snom, Cisco, etc.), Media Servers (Asterisk, FreeSwitch, etc.)

  • IMS

    • diameter support and authentication
    • I-CSCF, P-CSCF, S-CSCF
    • charging, QOS, ISC
  • Miscellaneous

    • CPL – Call Processing Language (RFC3880)
    • Internal generic caching system
    • Memcached connector
    • Redis NoSQL database connector
    • CLI – kamctl and sercmd
    • Web Management Interface: Siremis
    • SIP-T and SIP-I
    • music on hold queue
    • message body compression/decompression (gzip-deflate)
  • Extensive documentation for both administrators and developers

Scalability:

  • Kamailio can run on embedded systems, with limited resources – the performances can be up to hundreds of call setups per second
  • used as load balancer in stateless mode, Kamailio can handle over 5000 call setups per second
  • on systems with 4GB memory, Kamailio can serve a population over 300 000 online subscribers
  • system can easily scale by adding more Kamailio servers
  • Kamailio can be used in geographic distributed VoIP platforms
  • Kamailio least-cost-routing scales up to millions of routing rules
  • straightforward failover and redundancy

Start Kamalio

service kamailo start

Logs

tail -f /var/log/kamailio

To Check if Kamailio instance is running

>ps -ax | grep “kamailio”

57411 ?        S      0:01 /usr/sbin/kamailio -f /etc/kamailio/kamailio.cfg -P /var/run/kamailio/kamailio.pid -m 4096 -M 128 -u root -g root

Installation and Configuration

Installing kamailio from git repo

clone kamailio from their github https://github.com/kamailio/kamailio

goto desired branch

The contents of clonned folder are

COPYING ChangeLog INSTALL ISSUES Makefile README README.md doc etc misc pkg test utils

run ‘make cfg’ which compiles using gcc abd created ‘src’ folder with contents

make cfg

Makefile Makefile.defs Makefile.groups Makefile.modules Makefile.rules Makefile.sources Makefile.utils core main.c modules.lst Makefile.cfg Makefile.dirs Makefile.libs Makefile.radius Makefile.shared Makefile.targets config.mak lib modules

Edit modules.lst to enable db_mysql and dialplan module

vim src/modules.lst

//the list of extra modules to compile
include_modules= db_mysql

Use ‘make’ command followed by make all . Make sure to have gcc bison and flex installed

make cfg
make all

Alternativey on debian system , use readymade measures like

apt install mysql-server
apt install kamailio kamailio-mysql-modules

To validate and verify the location of kamillio use ‘which kamailio’ which returns /usr/sbin/kamailio

For Modules installation , check all avaible modules with command ‘apt search kamailio’and to install a new module such as websockt module use ‘apt install kamailio-websocket-modules’

Database access
After installaing kamailio , edit the kamailio.cfg file in /etc/kamailio to set the reachabe SIP domain, database engine, username/password etc to connect to databaseand enable the kamdbctl script to run and create users and tables, etc.

SIP_DOMAIN=kamailio.org

SIP_DOMAIN=17.3.4.5

chrooted directory

$CHROOT_DIR=”/path/to/chrooted/directory”

database type: MYSQL, PGSQL, ORACLE, DB_BERKELEY, DBTEXT, or SQLITE by default none is loaded

DBENGINE=MYSQL

Run kamdbctl to create users and database now

kamdbctl create

the database created is name kamailio and its tables are

+---------------------+
 | Tables_in_kamailio  |
 +---------------------+
 | acc                 |
 | acc_cdrs            |
 | active_watchers     |
 | address             |
 | aliases             |
 | carrier_name        |
 | carrierfailureroute |
 | carrierroute        |
 | cpl                 |
 | dbaliases           |
 | dialog              |
 | dialog_vars         |
 | dialplan            |
 | dispatcher          |
 | domain              |
 | domain_attrs        |
 | domain_name         |
 | domainpolicy        |
 | globalblacklist     |
 | grp                 |
 | htable              |
 | imc_members         |
 | imc_rooms           |
 | lcr_gw              |
 | lcr_rule            |
 | lcr_rule_target     |
 | location            |
 | location_attrs      |
 | missed_calls        |
 | mohqcalls           |
 | mohqueues           |
 | mtree               |
 | mtrees              |
 | pdt                 |
 | pl_pipes            |
 | presentity          |
 | pua                 |
 | purplemap           |
 | re_grp              |
 | rls_presentity      |
 | rls_watchers        |
 | rtpproxy            |
 | sca_subscriptions   |
 | silo                |
 | sip_trace           |
 | speed_dial          |
 | subscriber          |
 | trusted             |
 | uacreg              |
 | uid_credentials     |
 | uid_domain          |
 | uid_domain_attrs    |
 | uid_global_attrs    |
 | uid_uri             |
 | uid_uri_attrs       |
 | uid_user_attrs      |
 | uri                 |
 | userblacklist       |
 | usr_preferences     |
 | version             |
 | watchers            |
 | xcap                |
 +---------------------+

Kamctlrc

The Kamailio configuration file for the control tools. Can set variables used in the kamctl and kamdbctl setup scripts. Per default all variables here are commented out, the control tools will use their internal default values. This file lets to edit  SIP domain, the database engine, username/password/ to connect to database, etc.

## your SIP domain
 SIP_DOMAIN=13.126.169.58
## chrooted directory
# $CHROOT_DIR="/path/to/chrooted/directory"
## database type: MYSQL, PGSQL, ORACLE, DB_BERKELEY, DBTEXT, or SQLITE
# by default none is loaded

# If you want to setup a database with kamdbctl, you must at least specify this parameter.

 DBENGINE=MYSQL
## database host
# DBHOST=localhost
## database host
# DBPORT=3306
## database name (for ORACLE this is TNS name)
# DBNAME=kamailio
# database path used by dbtext, db_berkeley or sqlite
# DB_PATH="/usr/local/etc/kamailio/dbtext"
database read/write user
# DBRWUSER="kamailio"
## password for database read/write user
# DBRWPW="kamailiorw"

database read only user

# DBROUSER="kamailioro"
## password for database read only user
# DBROPW="kamailioro"
## database access host (from where is kamctl used)
# DBACCESSHOST=192.168.0.1

database super user (for ORACLE this is ‘scheme-creator’ user)

# DBROOTUSER="root"
## password for database super user
## - important: this is insecure, targeting the use only for automatic testing
## - known to work for: mysql
# DBROOTPW="dbrootpw"
## database character set (used by MySQL when creating database)
#CHARSET="latin1"
## user name column
# USERCOL="username"
# SQL definitions

# If you change this definitions here, then you must change them
# in db/schema/entities.xml too.
# FIXME
# FOREVER="2030-05-28 21:32:15"
# DEFAULT_Q="1.0"
# Program to calculate a message-digest fingerprint
# MD5="md5sum"
# awk tool
# AWK="awk"
# gdb tool
# GDB="gdb"

# If you use a system with a grep and egrep that is not 100% gnu grep compatible,
# e.g. solaris, install the gnu grep (ggrep) and specify this below.

grep tool
# GREP="grep"
# egrep tool
# EGREP="egrep"
# sed tool
# SED="sed"
# tail tool
# LAST_LINE="tail -n 1"
# expr tool
# EXPR="expr"

Describe what additional tables to install. Valid values for the variables below are yes/no/ask. With ask (default) it will interactively ask the user for an answer, while yes/no allow for automated, unassisted installs.

#If to install tables for the modules in the EXTRA_MODULES variable.

# INSTALL_EXTRA_TABLES=ask
# If to install presence related tables.
# INSTALL_PRESENCE_TABLES=ask
# If to install uid modules related tables.
# INSTALL_DBUID_TABLES=ask

 Define what module tables should be installed.

If you use the postgres database and want to change the installed tables, then you must also adjust the STANDARD_TABLES or EXTRA_TABLES variable accordingly in the kamdbctl.base script.

standard modules

# STANDARD_MODULES="
standard acc lcr domain group permissions registrar usrloc msilo
alias_db uri_db speeddial avpops auth_db pdt dialog dispatcher
dialplan"

extra modules

# EXTRA_MODULES="
imc cpl siptrace domainpolicy carrierroute userblacklist htable purple sca"
 type of aliases used: DB - database aliases; UL - usrloc aliases
- default: none , ALIASES_TYPE="DB"
control engine: RPCFIFO
 - default RPCFIFO
 CTLENGINE="RPCFIFO"

## path to FIFO file for engine RPCFIFO
# RPCFIFOPATH="/var/run/kamailio/kamailio_rpc_fifo"

## check ACL names; default on (1); off (0)
# VERIFY_ACL=1

## ACL names - if VERIFY_ACL is set, only the ACL names from below list are accepted
# ACL_GROUPS="local ld int voicemail free-pstn"

## check if user exists (used by some commands such as acl);
## - default on (1); off (0)

# VERIFY_USER=1

## verbose - debug purposes - default '0'
# VERBOSE=1

## do (1) or don't (0) store plaintext passwords
## in the subscriber table - default '1'

# STORE_PLAINTEXT_PW=0

Kamailio START Options

PID file path – default is: /var/run/kamailio/kamailio.pid

# PID_FILE=/var/run/kamailio/kamailio.pid

Extra start options – default is: not set

# example: start Kamailio with 64MB share memory: STARTOPTIONS="-m 64"
# STARTOPTIONS=

Kamailio.cfg

config files are used to customize and deploy SIP services since each and every SIP packet is route based on policies specified in conf file ( routing blocks ). Location when installed from source – /usr/local/etc/kamailio/kamailio.cfg , when installed from package – /etc/kamailio/kamailio.cfg

The features in config file :-

  • User authentication

Kamailio doesn’t have user authentication by default , so to enable it one must

#!define WITH_MYSQL
#!define WITH_AUTH

kamdbctl tool is to be used for creating and managing the database.

kamdbctl create

Kamctl is used for adding subscriber information and password.

kamctl add altanai1 123
mysql: [Warning] Using a password on the command line interface can be insecure.
MySQL password for user 'kamailio@localhost': 
mysql: [Warning] Using a password on the command line interface can be insecure.
new user 'altanai1' added

More details in Tools section below .

  • IP authorization
  • accounting
  • registrar and location servicesTo have persisant location enabled so that records are not lost once kamailio are restarted , we need to save it to database and reload when restarting
#!define WITH_USRLOCDB
  • attacks detection and blocking (anti-flood protection)
  • NAT traversal

requires RTP proxy for RTP relay . NAT traversal support can be set by

#!define WITH_NAT
  • short dialing on server
  • multiple identities (aliases) for subscribers
  • multi-domain support
  • routing to a PSTN gateway
  • routing to a voicemail server
  • TLS encryption
  • instant messaging (pager mode with MESSAGE requests)
  • presence services

Kamailio (OpenSER) SIP Server v4.3- default configuration script

Several features can be enabled using ‘#!define WITH_FEATURE’ directives:

To run in debug mode: define WITH_DEBUG

To enable mysql: define WITH_MYSQL

To enable authentication execute: enable mysql and  define WITH_AUTH

To enable IP authentication execute: enable mysql ,  enable authentication ,  define WITH_IPAUTH and  add IP addresses with group id ‘1’ to ‘address’ table

To enable persistent user location execute:


enable mysql

define WITH_USRLOCDB

To enable presence server execute:


enable mysql

define WITH_PRESENCE

To enable nat traversal execute:

define WITH_NAT

Install RTPProxy: http://www.rtpproxy.org

start RTPProxy:

rtpproxy -l your_public_ip -s udp:localhost:7722

option for NAT SIP OPTIONS keepalives: WITH_NATSIPPING

To enable PSTN gateway routing execute:

define WITH_PSTN

set the value of pstn.gw_ip

check route[PSTN] for regexp routing condition

To enable database aliases lookup execute:


enable mysql

define WITH_ALIASDB

To enable speed dial lookup execute:


enable mysql

define WITH_SPEEDDIAL

To enable multi-domain support execute:


enable mysql

define WITH_MULTIDOMAIN

To enable TLS support execute:


adjust CFGDIR/tls.cfg as needed

define WITH_TLS

To enable XMLRPC support execute:


define WITH_XMLRPC

adjust route[XMLRPC] for access policy

To enable anti-flood detection execute:

adjust pike and htable=>ipban settings as needed (default is block if more than 16 requests in 2 seconds and ban for 300 seconds)

define WITH_ANTIFLOOD

To block 3XX redirect replies execute:

define WITH_BLOCK3XX

To enable VoiceMail routing execute:

define WITH_VOICEMAIL

set the value of voicemail.srv_ip

adjust the value of voicemail.srv_port

To enhance accounting execute:


enable mysql

define WITH_ACCDB

add following columns to database


define WITH_MYSQL

define WITH_AUTH

define WITH_USRLOCDB

#!ifdef ACCDB_COMMENT

ALTER TABLE acc ADD COLUMN src_user VARCHAR(64) NOT NULL DEFAULT '';

ALTER TABLE acc ADD COLUMN src_domain VARCHAR(128) NOT NULL DEFAULT '';

ALTER TABLE acc ADD COLUMN src_ip varchar(64) NOT NULL default '';

ALTER TABLE acc ADD COLUMN dst_ouser VARCHAR(64) NOT NULL DEFAULT '';

ALTER TABLE acc ADD COLUMN dst_user VARCHAR(64) NOT NULL DEFAULT '';

ALTER TABLE acc ADD COLUMN dst_domain VARCHAR(128) NOT NULL DEFAULT '';

ALTER TABLE missed_calls ADD COLUMN src_user VARCHAR(64) NOT NULL DEFAULT '';

ALTER TABLE missed_calls ADD COLUMN src_domain VARCHAR(128) NOT NULL DEFAULT '';

ALTER TABLE missed_calls ADD COLUMN src_ip varchar(64) NOT NULL default '';

ALTER TABLE missed_calls ADD COLUMN dst_ouser VARCHAR(64) NOT NULL DEFAULT '';

ALTER TABLE missed_calls ADD COLUMN dst_user VARCHAR(64) NOT NULL DEFAULT '';

ALTER TABLE missed_calls ADD COLUMN dst_domain VARCHAR(128) NOT NULL DEFAULT '';

#!endif

Include Local Config If Exists

import_file “kamailio-local.cfg”

Value defines – IDs used later in config #!ifdef WITH_MYSQL # – database URL – used to connect to database server by modules such # as: auth_db, acc, usrloc, a.s.o.

  
 #!ifndef DBURL 
 #!define DBURL "mysql://kamailio:kamailiorw@localhost/kamailio" 
  #!define DBURL "mysql://kamailio:kamailiorw@localhost/kamailio" 
# !endif

 #!ifdef WITH_MULTIDOMAIN# - the value for 'use_domain' paramete
 #!define MULTIDOMAIN 1
 #!else
 #!define MULTIDOMAIN 0
 #!endif

 # FLT_ - per transaction (message) flags 
 # FLB_ - per branch flags
 #!define FLT_ACC 1
 #!define FLT_ACCMISSED 2
 #!define FLT_ACCFAILED 3
 #!define FLT_NATS 5
 #!define FLB_NATB 6
 #!define FLB_NATSIPPING 

 !substdef "!MY_IP_ADDR!!g"
 #!substdef "!MY_DOMAIN!!g" 
 #!substdef "!MY_WS_PORT!8080!g"
 #!substdef "!MY_WSS_PORT!4443!g"
 #!substdef "!MY_WS_ADDR!tcp:MY_IP_ADDR:MY_WS_PORT!g"
 #!substdef "!MY_WSS_ADDR!tls:MY_IP_ADDR:MY_WSS_PORT!g"&lt;/pre&gt;
 
 #!define WITH_WEBSOCKETS
 #!ifdef WITH_DEBUG
 debug=4
 log_stderror=yes
 #!else
 debug=2
 log_stderror=no
 #!endif

 memdbg=5
 memlog=5
 log_facility=LOG_LOCAL0
 fork=yes
 children=4
 
disable TCP (default on)
 #disable_tcp=yes
 enable_sctp = 0

disable the auto discovery of local aliases based on reverse DNS on IPs (default on)
 #auto_aliases=no

add local domain aliases
#alias=”sip.mydomain.com”

// port to listen to can be specified more than once if needed to listen on many ports
port=5060
#!ifdef WITH_TLS
enable_tls=yes
#!endif

life time of TCP connection when there is no traffic – a bit higher than registration expires to cope with UA behind NAT

#!ifdef WITH_PSTN
# PSTN GW Routing
# - pstn.gw_ip: valid IP or hostname as string value, example:
# pstn.gw_ip = "10.0.0.101" desc "My PSTN GW Address"
# - by default is empty to avoid misrouting
pstn.gw_ip = "" desc "PSTN GW Address"
pstn.gw_port = "" desc "PSTN GW Port"
#!endif

ifdef WITH_VOICEMAIL
# VoiceMail Routing on offline, busy or no answer
# - by default Voicemail server IP is empty to avoid misrouting
voicemail.srv_ip = "" desc "VoiceMail IP Address"
voicemail.srv_port = "5060" desc "VoiceMail Port"
#!endif

Modules Section

set paths to location of modules (to sources or installation folders)

#!ifdef WITH_SRCPATH
mpath="modules/"
#!else
mpath="/usr/lib/x86_64-linux-gnu/kamailio/modules/"
#!endif

#!ifdef WITH_MYSQL
loadmodule "db_mysql.so"
#!endif

loadmodule "mi_fifo.so"
loadmodule "kex.so"
loadmodule "corex.so"
loadmodule "tm.so"
loadmodule "tmx.so"
loadmodule "sl.so"
loadmodule "rr.so"
loadmodule "pv.so"
loadmodule "maxfwd.so"
loadmodule "usrloc.so"
loadmodule "registrar.so"
loadmodule "textops.so"
loadmodule "siputils.so"
loadmodule "xlog.so"
loadmodule "sanity.so"
loadmodule "ctl.so"
loadmodule "cfg_rpc.so"
loadmodule "mi_rpc.so"
loadmodule "acc.so"

#!ifdef WITH_AUTH
loadmodule "auth.so"
loadmodule "auth_db.so"
#!ifdef WITH_IPAUTH
loadmodule "permissions.so"
#!endif
#!endif

#!ifdef WITH_ALIASDB
loadmodule "alias_db.so"
#!endif

#!ifdef WITH_SPEEDDIAL
loadmodule "speeddial.so"
#!endif

#!ifdef WITH_MULTIDOMAIN
loadmodule "domain.so"
#!endif

#!ifdef WITH_PRESENCE
loadmodule "presence.so"
loadmodule "presence_xml.so"
#!endif

#!ifdef WITH_NAT
loadmodule "nathelper.so"
loadmodule "rtpproxy.so"
#!endif

#!ifdef WITH_TLS
loadmodule "tls.so"
#!endif

#!ifdef WITH_ANTIFLOOD
loadmodule "htable.so"
loadmodule "pike.so"
#!endif

#!ifdef WITH_XMLRPC
loadmodule "xmlrpc.so"
#!endif

#!ifdef WITH_DEBUG
loadmodule "debugger.so"
#!endif

#!ifdef WITH_WEBSOCKETS
loadmodule "xhttp.so"
#loadmodule "websocket.so"
loadmodule "nathelper.so"
#!endif

----- mi_fifo params -----
#modparam("mi_fifo", "fifo_name", "/var/run/kamailio/kamailio_fifo")</pre>

----- ctl params -----
#modparam("ctl", "binrpc", "unix:/var/run/kamailio/kamailio_ctl")</pre>

----- tm params -----
# auto-discard branches from previous serial forking leg
modparam("tm", "failure_reply_mode", 3)
# default retransmission timeout: 30sec
modparam("tm", "fr_timer", 30000)
# default invite retransmission timeout after 1xx: 120sec
modparam("tm", "fr_inv_timer", 120000)</pre>

----- rr params -----
# set next param to 1 to add value to ;lr param (helps with some UAs)
modparam("rr", "enable_full_lr", 0)
# do not append from tag to the RR (no need for this script)
modparam("rr", "append_fromtag", 0)

registrar params


modparam("registrar", "method_filtering", 1)
/* uncomment the next line to disable parallel forking via location */
# modparam("registrar", "append_branches", 0)
/* uncomment the next line not to allow more than 10 contacts per AOR */
#modparam("registrar", "max_contacts", 10)
# max value for expires of registrations
modparam("registrar", "max_expires", 3600)
# set it to 1 to enable GRUU
modparam("registrar", "gruu_enabled", 0)</pre>

enhanced DB accounting


#!ifdef WITH_ACCDB

modparam("acc", "db_flag", FLT_ACC)

modparam("acc", "db_missed_flag", FLT_ACCMISSED)

modparam("acc", "db_url", DBURL)

modparam("acc", "db_extra",

"src_user=$fU;src_domain=$fd;src_ip=$si;"

"dst_ouser=$tU;dst_user=$rU;dst_domain=$rd")

#!endif

usrloc params – enable DB persistency for location entries


#!ifdef WITH_USRLOCDB

modparam("usrloc", "db_url", DBURL)

modparam("usrloc", "db_mode", 2)

modparam("usrloc", "use_domain", MULTIDOMAIN)

#!endif

auth_db params


#!ifdef WITH_AUTH

modparam("auth_db", "db_url", DBURL)

modparam("auth_db", "calculate_ha1", yes)

modparam("auth_db", "password_column", "password")

modparam("auth_db", "load_credentials", "")

modparam("auth_db", "use_domain", MULTIDOMAIN)

permissions params


#!ifdef WITH_IPAUTH

modparam("permissions", "db_url", DBURL)

modparam("permissions", "db_mode", 1)

#!endif

#!endif

alias_db params


#!ifdef WITH_ALIASDB

modparam("alias_db", "db_url", DBURL)

modparam("alias_db", "use_domain", MULTIDOMAIN)

#!endif

speeddial params


#!ifdef WITH_SPEEDDIAL

modparam("speeddial", "db_url", DBURL)

modparam("speeddial", "use_domain", MULTIDOMAIN)

#!endif

domain params

#!ifdef WITH_MULTIDOMAIN
modparam("domain", "db_url", DBURL)
modparam("domain", "register_myself", 1)
#!endif
#!ifdef WITH_PRESENCE

presence params

modparam("presence", "db_url", DBURL)

presence_xml params

modparam("presence_xml", "db_url", DBURL)
modparam("presence_xml", "force_active", 1)

WITH_NAT

rtpproxy params
modparam("rtpproxy", "rtpproxy_sock", "udp:127.0.0.1:7722")

nathelper params

 modparam("nathelper", "natping_interval", 30)
 modparam("nathelper", "ping_nated_only", 1)
 modparam("nathelper", "sipping_bflag", FLB_NATSIPPING)
 modparam("nathelper", "sipping_from", "sip:pinger@kamailio.org") 

params needed for NAT traversal in other modules

modparam("nathelper|registrar", "received_avp", "$avp(RECEIVED)")
modparam("usrloc", "nat_bflag", FLB_NATB)

tls params

#!ifdef WITH_TLS

modparam("tls", "config", "/etc/kamailio/tls.cfg")

#!endif

pike params

#!ifdef WITH_ANTIFLOOD

modparam("pike", "sampling_time_unit", 2)
modparam("pike", "reqs_density_per_unit", 16)
modparam("pike", "remove_latency", 4)

htable params

ip ban htable with autoexpire after 5 minutes

modparam("htable", "htable", "ipban=&gt;size=8;autoexpire=300;")

#!endif

xmlrpc params

modparam("xmlrpc", "route", "XMLRPC");
modparam("xmlrpc", "url_match", "^/RPC")

debugger params

#!ifdef WITH_DEBUGs
modparam("debugger", "cfgtrace", 1)
#!endif

nathelper params

#!ifdef WITH_WEBSOCKETS
modparam("nathelper|registrar", "received_avp", "$avp(RECEIVED)")
#!endif

Note: leaving NAT pings turned off here as nathelper is <em>only</em> being used for&nbsp;WebSocket connections. NAT pings are not needed as WebSockets have&nbsp;their own keep-alives.

Routing Logic

Main SIP request routing logic processing of any incoming SIP request starts with this route

request_route { 
# per request initial checks 
route(REQINIT);
 #!ifdef WITH_WEBSOCKETS 
    if (nat_uac_test(64)) {     
        force_rport();     
        if (is_method("REGISTER")) {          
            fix_nated_register();     
        } else {         
            fix_nated_contact();         
            if (!add_contact_alias()) {  
                   xlog("L_ERR", "Error aliasing contact \n");             
                   sl_send_reply("400", "Bad Request");                    exit;         }     } } 
#!endif 
# NAT detection 
route(NATDETECT); 
# CANCEL processing 
if (is_method("CANCEL")) {     
    if (t_check_trans()) {         
        route(RELAY);     
    }     
exit; 
} 

# handle requests within SIP dialogs 
route(WITHINDLG); 
### only initial requests (no To tag) 
# handle retransmissions 
if(t_precheck_trans()) { 
    t_check_trans(); 
    exit; 
} 
t_check_trans(); 

# authentication 
route(AUTH); 

# record routing for dialog forming requests (in case they are routed) - remove preloaded route headers 
remove_hf("Route"); 

if (is_method("INVITE|SUBSCRIBE")) 
record_route(); 

# account only INVITEs 
if (is_method("INVITE")) {     
    setflag(FLT_ACC); # do accounting 
}
# dispatch requests to foreign domains 
route(SIPOUT); 

### requests for my local domains 
# handle presence related requests 
route(PRESENCE); 

# handle registrations 
route(REGISTRAR); 
if ($rU==$null) {     
# request with no Username in RURI     sl_send_reply("484","Address Incomplete");     
exit; 
} 
# dispatch destinations to PSTN route(PSTN); 

# user location service 
route(LOCATION); }

Wrapper for relaying requests

enable additional event routes for forwarded requests – serial forking, RTP relaying handling, a.s.o.

route[RELAY] {
if (is_method(“INVITE|BYE|SUBSCRIBE|UPDATE”)) {
if(!t_is_set(“branch_route”))
t_on_branch(“MANAGE_BRANCH”);
}
if (is_method(“INVITE|SUBSCRIBE|UPDATE”)) {
if(!t_is_set(“onreply_route”))
t_on_reply(“MANAGE_REPLY”);
}
if (is_method(“INVITE”)) {
if(!t_is_set(“failure_route”))
t_on_failure(“MANAGE_FAILURE”);
}
if (!t_relay()) {
sl_reply_error();
}
exit;
}

Per SIP request initial checks

route[REQINIT] { #!ifdef WITH_ANTIFLOOD # flood detection from same IP and traffic ban for a while # be sure you exclude checking trusted peers, such as pstn gateways – local host excluded (e.g., loop to self) 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; } } if($ua =~ “friendly-scanner”) { sl_send_reply(“200”, “OK”); exit; } #!endif if (!mf_process_maxfwd_header(“10”)) { sl_send_reply(“483″,”Too Many Hops”); exit; } if(is_method(“OPTIONS”) && uri==myself && $rU==$null) { sl_send_reply(“200″,”Keepalive”); exit; } if(!sanity_check(“1511”, “7”)) { xlog(“Malformed SIP message from $si:$sp\n”); exit; } }

Handle requests within SIP dialogs

route[WITHINDLG] {
    if (!has_totag()) return;

    if (has_totag()) {

#sequential request withing a dialog should take the path determined by record-routing

        if (loose_route()) {
            #!ifdef WITH_WEBSOCKETS
            if ($du == "") {
                if (!handle_ruri_alias()) {
                    xlog("L_ERR", "Bad alias <$ru>\n");
                    sl_send_reply("400", "Bad Request");
                    exit;
                }
            }
            #!endif
         }
     exit;
     }

#sequential request within a dialog should  take the path determined by record-routing
    if (loose_route()) {
        route(DLGURI);
        if (is_method("BYE")) {
            setflag(FLT_ACC); # do accounting ...
            setflag(FLT_ACCFAILED); # ... even if the transaction fails
        }
        else if ( is_method("ACK") ) {
            # ACK is forwarded statelessy
            route(NATMANAGE);
        }
        else if ( is_method("NOTIFY") ) {
            # Add Record-Route for in-dialog NOTIFY as per RFC 6665.
            record_route();
        }
        route(RELAY);
        exit;
    }

    if (is_method("SUBSCRIBE") && uri == myself) {
    # in-dialog subscribe requests
        route(PRESENCE);
        exit;
    }

if ( is_method("ACK") ) {
    if ( t_check_trans() ) {
        # no loose-route, but stateful ACK;
        # must be an ACK after a 487
        # or e.g. 404 from upstream server
        route(RELAY);
        exit;
    } else {
        # ACK without matching transaction ... ignore and discard
        exit;
    }
}

sl_send_reply("404","Not here");
exit;
}


Handle SIP registrations





User location service

route[LOCATION] {

#!ifdef WITH_SPEEDDIAL
# search for short dialing - 2-digit extension
if($rU=~"^[0-9][0-9]$")
    if(sd_lookup("speed_dial"))
    route(SIPOUT);
#!endif

#!ifdef WITH_ALIASDB
# search in DB-based aliases
    if(alias_db_lookup("dbaliases"))
    route(SIPOUT);
#!endif

$avp(oexten) = $rU;
if (!lookup("location")) {
    $var(rc) = $rc;
    route(TOVOICEMAIL);
    t_newtran();
    switch ($var(rc)) {
        case -1:
        case -3:
           send_reply("404", "Not Found");
        exit;
        case -2:
           send_reply("405", "Method Not Allowed");
        exit;
    }
}

# when routing via usrloc, log the missed calls also
if (is_method("INVITE")) {
    setflag(FLT_ACCMISSED);
}

route(RELAY);
exit;
}

Presence server processing

route[PRESENCE] {

if(!is_method("PUBLISH|SUBSCRIBE"))
return;

if(is_method("SUBSCRIBE") && $hdr(Event)=="message-summary") {
    route(TOVOICEMAIL);
    # returns here if no voicemail server is configured
    sl_send_reply("404", "No voicemail service");
    exit;
}

#!ifdef WITH_PRESENCE
if (!t_newtran()) {
    sl_reply_error();
    exit;
}

if(is_method("PUBLISH")) {
    handle_publish();
    t_release();
} else if(is_method("SUBSCRIBE")) {
    handle_subscribe();
    t_release();
}
exit;
#!endif

# if presence enabled, this part will not be executed
if (is_method("PUBLISH") || $rU==$null) {
    sl_send_reply("404", "Not here");
    exit;
}
return;
}

IP authorization and user authentication

route[AUTH] {
#!ifdef WITH_AUTH

#!ifdef WITH_IPAUTH
if((!is_method("REGISTER")) && allow_source_address()) {
    # source IP allowed
    return;
}
#!endif

if (is_method("REGISTER") || from_uri==myself)
{
    # authenticate requests
    if (!auth_check("$fd", "subscriber", "1")) {
        auth_challenge("$fd", "0");
        exit;
    }

    # user authenticated - remove auth header
    if(!is_method("REGISTER|PUBLISH"))
        consume_credentials();
    }

# if caller is not local subscriber, then check if it calls
# a local destination, otherwise deny, not an open relay here
    if (from_uri!=myself && uri!=myself) {
        sl_send_reply("403","Not relaying");
        exit;
    }

#!endif
return;
}

Caller NAT detection

route[NATDETECT] {
#!ifdef WITH_NAT
force_rport();

if (nat_uac_test("19")) {
    if (is_method("REGISTER")) {
        fix_nated_register();
    } else {
        if(is_first_hop())
            set_contact_alias();
    }
    setflag(FLT_NATS);
}
#!endif
return;
}

RTPProxy control and signaling updates for NAT traversal

route[NATMANAGE] {

#!ifdef WITH_NAT
if (is_request()) {
    if(has_totag()) {
        if(check_route_param("nat=yes")) {
            setbflag(FLB_NATB);
        }
     }
}
if (!(isflagset(FLT_NATS) || isbflagset(FLB_NATB)))
return;

rtpproxy_manage("co");

if (is_request()) {
    if (!has_totag()) {
        if(t_is_branch_route()) {
            add_rr_param(";nat=yes");
        } 
    }
}

if (is_reply()) {
    if(isbflagset(FLB_NATB)) {
        if(is_first_hop())
        set_contact_alias();
    }
}

#!endif
return;
}

URI update for dialog requests

route[DLGURI] {
#!ifdef WITH_NAT
if(!isdsturiset()) {
    handle_ruri_alias();
}
#!endif
return;
}

Routing to foreign domains

route[SIPOUT] {
if (uri==myself) return;

append_hf("P-hint: outbound\r\n");
route(RELAY);
exit;
}

PSTN GW routing

route[PSTN] {
#!ifdef WITH_PSTN
# check if PSTN GW IP is defined
if (strempty($sel(cfg_get.pstn.gw_ip))) {
xlog("SCRIPT: PSTN routing enabled but pstn.gw_ip not defined\n");
return;
}

# route to PSTN dialed numbers starting with '+' or '00'
# (international format)
# - update the condition to match your dialing rules for PSTN routing
if(!($rU=~"^(\+|00)[1-9][0-9]{3,20}$"))
return;

# only local users allowed to call
if(from_uri!=myself) {
sl_send_reply("403", "Not Allowed");
exit;
}

if (strempty($sel(cfg_get.pstn.gw_port))) {
$ru = "sip:" + $rU + "@" + $sel(cfg_get.pstn.gw_ip);
} else {
$ru = "sip:" + $rU + "@" + $sel(cfg_get.pstn.gw_ip) + ":"
+ $sel(cfg_get.pstn.gw_port);
}

route(RELAY);
exit;
#!endif

return;
}

XMLRPC routing

#!ifdef WITH_XMLRPC
route[XMLRPC] {
# allow XMLRPC from localhost
if ((method=="POST" || method=="GET") && (src_ip==127.0.0.1)) {
# close connection only for xmlrpclib user agents
    if ($hdr(User-Agent) =~ "xmlrpclib")
        set_reply_close();
        set_reply_no_connect();
        dispatch_rpc();
    exit;
}
send_reply("403", "Forbidden");
exit;
}
#!endif

Routing to voicemail server

route[TOVOICEMAIL] {
#!ifdef WITH_VOICEMAIL
if(!is_method("INVITE|SUBSCRIBE"))
return;

# check if VoiceMail server IP is defined
if (strempty($sel(cfg_get.voicemail.srv_ip))) {
    xlog("SCRIPT: VoiceMail routing enabled but IP not defined\n");
    return;
}
if(is_method("INVITE")) {
    if($avp(oexten)==$null)
        return;
    $ru = "sip:" + $avp(oexten) + "@" + $sel(cfg_get.voicemail.srv_ip)+ ":" + $sel(cfg_get.voicemail.srv_port);
} else {
    if($rU==$null)
        return;
    $ru = "sip:" + $rU + "@" + $sel(cfg_get.voicemail.srv_ip)
+ ":" + $sel(cfg_get.voicemail.srv_port);
}
route(RELAY);
exit;
#!endif

return;
}

Manage outgoing branches

branch_route[MANAGE_BRANCH] {
    xdbg("new branch [$T_branch_idx] to $ru\n");
    route(NATMANAGE);
}

Manage incoming replies

onreply_route[MANAGE_REPLY] {
    xdbg("incoming reply\n");
    if(status=~"[12][0-9][0-9]")
        route(NATMANAGE);
}

Manage failure routing cases

failure_route[MANAGE_FAILURE] {
route(NATMANAGE);

if (t_is_canceled()) {
    exit;
}

#!ifdef WITH_BLOCK3XX
# block call redirect based on 3xx replies.
if (t_check_status("3[0-9][0-9]")) {
    t_reply("404","Not found");
    exit;
}
#!endif

#!ifdef WITH_VOICEMAIL
# serial forking
# - route to voicemail on busy or no answer (timeout)
if (t_check_status("486|408")) {
    $du = $null;
    route(TOVOICEMAIL);
    exit;
}
#!endif
}

Supports pseudo-variables to access and manage parts of the SIP messages and attributes specific to users and server.  Transformations to modify existing pseudo-variables, accessing only the wanted parts of the information. 

Already has over 1000 parameters, variables and functions exported to config file. Supports runtime update framework – to avoid restarting the SIP server when needing to change the config parameters

Tools

kamctl

Manage kamailio from command line, providing lots of operations, such as adding/removing/updating SIP users, controlling the ACL for users, managing the records for LCR or load balancing, viewing registered users and internal statistics, etc. When needed to interact with Kamailio, it does it via FIFO file created by mi_fifo module.

kamdbctl

Helps to configure and database needed by kamailio . First we need to select a database engine in the kamctlrc file by DBENGINE parameter .

Valid values are: MYSQL, PGSQL, ORACLE, DB_BERKELEY, DBTEXT.

The tool can be used to create and manage the database structure needed by Kamailio, therefore it should be immediately after Kamailio installation, in case you plan to run Kamailio with a database backend.

kamcmd

send RPC commands to Kamailio from command line , requires  ctl module

siremis

web management interface for Kamailio, written in PHP , AJAX , web 2.0 using MVC architecture

  • system and database administration tools for Kamailio SIP Server
  • subscriber, database aliases and speed dial management
  • location table view
  • dispatcher (load balancer), prefix-domain translation and least cost routing (lcr) management
  • access control lists (user groups) and permissions management
  • accounting records and missed calls vies
  • manage call data records (generated from acc records)
  • hash table, dial plan table and user preferences table management
  • offline message storage, presence service and sip trace views
  • communication with Kamailio SIP Server via XMLRPC ,  JSONRPC
  • communication with FreeSWITCH via event socket
  • create and display charts from statistic data stored by Kamailio
  • user location statistics charts
  • SIP traffic load charts
  • memory usage charts
  • accounting records charts and summary table
  • SQL-based CDR generation and rating billing engine

———————————–

Things covered in this article

  • Internal architecture
  • Configuration language
  • least cost routing
  • load balancing
  • traffic dispatching
  • DID routing
  • prefix based routing
  • SIP trunks and peering
  • traffic shaping
  • topology hiding
  • flood detection
  • scanning attacks prevention
  • anti-fraud policies

SQL and noSQL connectors

enum and DNS based routing

authentication and authorization

secure communication (TLS)

registration and location services

accounting and call data records

call control – redirect, forward, baring

redundancy and scalability

high availability and failover

websockets and webrtc

References :

Henning Westerholt – Kamailio project-1&1 Internet AG ( 2009 )

OTT ( Over the Top ) Communication applications

Market trends are really not in favor of Telecom Service /providers with increasing use of OTT ( Over The Top ) application like watsapp , Facebook messenger , Google hangouts , skype  , viber , etc .

OTT

OTT ( Over The Top ) Applications

What is an OTT ?

An Over The Top ( OTT ) application is one which provides communication services over Internet . Therefore these bypass the communication billing system setup by a Telecom Operator , resulting in no gain or loss of revenue to Telecom Operator who is providing the Internet service to user in first place .

Hence we see that OTT are major threat and concern for Telecom Operators whose traditional and obviously expensive ( when compared to OTTs free service ) billing models are facing disruption .


Telecom Regulatory bodies around the world

The telecom regulatory authorities in some of the countries are for example listed as :

  • Afghanistan Telecom Regulatory Authority (ATRA) – Afganistan
  • Australian Communications and Media Authority (ACMA) – Australia
  • Bangladesh Telecommunication Regulatory Commission (BTRC) – Bnagaladesh
  • Canadian Radio-television and Telecommunications Commission (CRTC) – Canada
  • Ministry of Information Industry (MII) – China
  • Autorité de Régulation des Communications Électroniques et des Postes (ARCEP) – France
  • Bundesnetzagentur (BNA) – Germany
  • Telecom Regulatory Authority of India (TRAI) – India
  • Ministry for Communications and Informatization of the Russian Federation (Minsvyaz) – Russia
  • Infocomm Development Authority of Singapore (IDA) – Singapore
  • Independent Communications Authority of South Africa (ICASA) – south Africa
  • Federal Communications Commission (FCC) , National Association of Regulatory Utility Commissioners (regulators of individual states) (NARUC) , CTIA – The Wireless Association (CTIA) – USA

Such telecom regulatory bodies get to decide whether to enforce differential price to end consumers for using OTT so that telecom service providers can benefit or keep the Internet fair and open by passing Net Neutrality Laws and Bills and amendments .

what is Net Neaurality ?

The fundamental principle of Net Neurality is that Telecom Operators should not block , slow down or charge consumers extra for using other services as their means of communication. This states that it is wrong to charge users above the regular data rates for using VOIP apps and other internet based communication services.

The following counteries have adopted principles of Net Neutrality by passing bills or making law .

  • Chile – Chile’s General Law of Telecommunications, “No [ISP] can block, interfere with, discriminate, hinder, nor restrict the right of any Internet user of using, send, receive, or offer any content, application, or legitimate service through the Internet, as well as any activity or legitimate use conducted through the Internet.”
  • Brazil – ” Internet Bill of Rights ” makes equal access to internet mandatory in Brazil .
  • Netherlands – Even European Union has adopted Netherlands’ Net Neutrality amendment which reads “traffic should be treated equally, without discrimination, restriction or interference, independent of the sender, receiver, type, content, device, service or application.”
  • USA – Citizens make ‘We the People’ platform to ‘Restore Net Neutrality By Directing the Federal Communications Commission (FCC) to Classify Internet Providers as ‘Common Carriers‘. Therefore not allowing them to either throttle speed by paid prioritization , discriminate in pricing or block any broadband access to legal content .  Above facts are from this tech.firstpost.com article.

Inspite of the fact that I Support Net Neutrality with all my heart , as a telecom engineer I understand the cost investment made by Telecom operators in providing am efficient communication network to its subscribers ( Access , Network and Application layers ). Therefor I do have my sympathies with the Telcos and to level out the wide ranging conflict between Telcos and  ISP ( Internet Service Providers ) , I pen down the following points which reflect the Telecom Operators Problems and also highlight the solutions that can be adopted to counteract the OTT threat .

Depleting revenue for Telco

  1. Messaging – OTT messaging cost operators $13.9 billion, or 9% of message revenue in 2013
  2. Voice – Voice services under threat from VOIP services like Skype, Viber
  3. OTT apps – Voice & Message apps have been the operator’s biggest headache. Its time Operator should launch its own OTT Services
  4. Data Traffic – The utilization is yet to reach its peak. Will face challenges from  WiFi access
  5. Critical Pain areas – Erosion of Operator’s revenue from voice and (especially) messaging

Telco’s OTT aPPLICATION

At this stage it is crucial for a telecom Service provider / Operator to enter the Apps market and bring forth a Messenger which is more powerful , interactive and awesome than a OTT application.  Fortunately the Operator can always couple this application with his background telecom infrastructure to provide the edge in performance and functionalists .

Road block while developing a OTT application for a Telecom Service Provider :

  • Investment in Data Network is not being utilized due to lack of service
  • Reuse of Existing business Logic and extending the service reach across devices and networks is tough
  • Operator already has full fledged network Infrastructure in Place
  • Desire for minimum CAPEX while investing in new technologies
  • compete with OTT players and open new revenue streams is a challenge

Next we find the way of solving the problems and integrating them together to form a Solution .

OTT Application for Telecom Service provider

  • Introduce new services to benefit from investment on Data Plans and Bandwidth
  • Expose REST API to enable 3trd party Integration with existing network Infrastructure
  • Partner with individual OTT players to make new services  that do not compete on core competencies like billing etc
  • Use protocols like SIP that reduce CAPEX and have goto market more quickly
  • Go for enriched service that lead to better user experience

This writeup outlines the process of creating a OTT application for a Telecom Service Provider . Components for the application include cloud Address Book , Video Chatting , Location share , Contact synchronization ,REST based thin  client , OS and device agnostic etc shown in the figure below

telco's OTT app

telco’s OTT app

The Application  is designed to close knit with Operator’s own infrastructure hence the crucial entities like Network Address Book , Location Service are synced and fetched from Backend Network .

OTT application Feature Overview

Smart Address Book

  • Automatic: Get contacts from Gmail, Facebook
  • Fast search by first, last name, frequently
  •   dialed number
  • Roadmap: View calendar events
  • Personal: Get image from Gmail and display in   contacts list

Geo Location

  • Share own location during chatting
  • Get map for calculating the distance between two chat users
  • Roadmap : Trigger device (say Switch on/off AC before reaching home) from a threshold distance away from home   location

Messaging

  • Ad-hoc Chat
  • Session Based Chat
  • Voice Input for texting
  • Presence information of contacts
  • RoadMap: Legacy message integration

Telephony

  • Voice call to mobile
  • Voice call to PSTN
  • Video call to other @imAll user
  • Share images during voice call to other

Device agnostic

  • Compatible with IOS, windows
  • Can run as native app on ipad
  • Can run as browser client on windows
  • RoadMap: native app for android, windows phone,blackberry10

Roadmap

  • To upgrade the application and provide enganced and enrich service support the I propose the following roadmap.
  • From plain vanilla voice and video calling ( supported by every other OTT application ) our application should progress towards  legacy telecom support whihc included PSTN , GSM , ISDN etc . This requires backbone of telecom network and a good setup for media codec conversion to suit various legacy media codecs .

Road Map  from Traditional to New age services 

  1. Voice and video calling
  2. Legacy services support like MMS and SMS
  3. Integration with 3rd party Vendors
  4. Give new enriched services like Multilingual support , file transfer , screen-sharing etc
  5. give facility to integrated web plugins for web calling

To keep the interest of customers it is essential that the application be supported on other popular OTT services like skype  , Gtalk . for exmaple a caller should be able to make call from Skype  / Gtalk to our application .Multilingual capabilities, support for larger protocol spectrum will just act like icing on the cake .

How does it benefit the Operator??

  1.  Saves on development cost and time
  2.  Device Agnostic OTT Applications
  3. Simplified Service deployment
  4. Saves licensing cost per client
  5. Reuses existing Messaging and   Address Book service logic.
  6. Open New Revenue Streams for operator
  7. No separate SIP stack required for the client
  8.  Faster Time to Market

Update : At the time of writing this post I did not anticipate the wave of change that bring focus on subjects like “net neutrality” , ” Save the internet” and “free internet” . However I see now that I had described this phenomenon way in advance for my time .