forked from altanai/kamailioexamples
-
Notifications
You must be signed in to change notification settings - Fork 7
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
stateful transaction handling readme
- Loading branch information
Showing
3 changed files
with
251 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
# Dialog stateful proxy | ||
|
||
stateful proxies keep transaction states in server | ||
Certain applications may benefit from an awareness of "calls" in the proxy ( dialog stateful ), not just SIP transactions such as setting CPS ( calls per second ) | ||
|
||
To create the dialog associated with an initial INVITE request, execute the function “dlg_manage()” or set the flag specified by parameter “dlg_flag” before creating the corresponding transaction. | ||
The dialog is automatically destroyed when a “BYE” is received or controlled via the default timeout and custom timeout params | ||
|
||
## dialog states | ||
|
||
1 : Unconfirmed dialog | ||
2 : Early dialog (ringing) | ||
3 : Confirmed dialog (waiting for ACK) | ||
4 : Confirmed dialog (active call) | ||
5 : Deleted dialog | ||
|
||
## dialog profiles | ||
|
||
classifying, sorting and keeping track of certain types of dialogs. Can be created by programmer according to any attribute like SIP msg , pseudo-variables, custom values etc . profile types : | ||
|
||
**with no value** - a dialog simply belongs to a profile (for instance, an outbound calls profile). There is no other additional information to describe the dialog beyond its membership in the profile per se. | ||
``` | ||
modparam("dialog", "profiles_no_value", "inbound ; outbound") | ||
``` | ||
setting and unsetting | ||
``` | ||
set_dlg_profile("inbound_call"); | ||
unset_dlg_profile("inbound_call"); | ||
``` | ||
check if current dialog belong to aprofile | ||
``` | ||
if (is_in_profile("inbound_call")) { | ||
log("this request belongs to a inbound call\n"); | ||
} | ||
``` | ||
|
||
**with value** - a dialog belongs to a profile having a certain value (like in a caller profile, where the value is the caller ID). | ||
``` | ||
modparam("dialog", "profiles_with_value", "caller ; my_profile") | ||
``` | ||
setting and unsetting the profile | ||
``` | ||
set_dlg_profile("caller","$fu"); | ||
unset_dlg_profile("caller","$fu"); | ||
``` | ||
check if current dialog belongs to profile | ||
``` | ||
if (is_in_profile("caller","XX")) { | ||
log("this request belongs to a call of user XX\n"); | ||
} | ||
``` | ||
|
||
Ref : https://kamailio.org/docs/modules/devel/modules/dialog.html |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,155 @@ | ||
# SIP transactions Handling | ||
|
||
SIP is a transaction protocol and transaction is sequence *one request and all its repsosnes* exchanged between SIP network elements. | ||
Kamailio can behave as a stateful proxy ( transaction states not dialog states) through the TM module | ||
|
||
## stateful vs stateless handling of trsansactions | ||
|
||
stateless - act like message forearders , stateless proxies do not take care of transactions. | ||
|
||
stateful - entities usually create a state associated with a transaction that is kept in the memory for the duration of the transaction. | ||
extracts and aminains a unique transaction identifier and tried to match all incoming messages to associate with existing transactions | ||
Branch parameter of Via header fields contains directly the transaction identifier. | ||
|
||
## stateful handling of new transactions | ||
|
||
Objective : | ||
It accepts all Register with 200 OK | ||
Creates a new transaction | ||
Due to a check for username altanai , cutom message hello is replied and any other username is printed a diff rejection reply | ||
|
||
Simulate local tarffic with sipp with username randomuser | ||
``` | ||
sipp -sn uac 127.0.0.1:5060 -m 1 -s randomuser -trace_err -trace_msg | ||
``` | ||
When condition matched | ||
``` | ||
2018-06-21 05:31:10:592 1561095070.592587: Aborting call on unexpected message for Call-Id '[email protected]': while expecting '100' (index 1), received 'SIP/2.0 409 Well , hello altanai ! | ||
Via: SIP/2.0/UDP 127.0.1.1:5061;branch=z9hG4bK-4064-1-0;received=127.0.0.1 | ||
From: sipp <sip:[email protected]:5061>;tag=4064SIPpTag001 | ||
To: sut <sip:[email protected]:5060>;tag=a6a1c5f60faecf035a1ae5b6e96e979a-26ca | ||
Call-ID: [email protected] | ||
CSeq: 1 INVITE | ||
Server: kamailio (5.1.8 (x86_64/linux)) | ||
Content-Length: 0 | ||
``` | ||
when condition on username doesnt match | ||
``` | ||
2018-06-21 05:28:31:754 1561094911.754929: Aborting call on unexpected message for Call-Id '[email protected]': while expecting '100' (index 1), received 'SIP/2.0 699 Do not proceed with this one | ||
Via: SIP/2.0/UDP 127.0.1.1:5061;branch=z9hG4bK-4004-1-0;received=127.0.0.1 | ||
From: sipp <sip:[email protected]:5061>;tag=4004SIPpTag001 | ||
To: sut <sip:[email protected]:5060>;tag=a6a1c5f60faecf035a1ae5b6e96e979a-894b | ||
Call-ID: [email protected] | ||
CSeq: 1 INVITE | ||
Server: kamailio (5.1.8 (x86_64/linux)) | ||
Content-Length: 0 | ||
``` | ||
|
||
### Note : | ||
ACK is considered part of INVITE trasnaction when non 2xx / negative final resposne is recived , When 2xx final / positive response is recievd than ACK is not considered part of the transaction. | ||
|
||
|
||
## Debugging | ||
|
||
**Issue1** relay methodINVITE | ||
1(26528) WARNING: sanity [sanity.c:233]: check_ruri_scheme(): failed to parse request uri [[email protected]] | ||
1(26528) CRITICAL: sl [../../core/ip_addr.h:455]: init_su(): unknown address family 0 | ||
1(26528) CRITICAL: <core> [core/parser/../ip_addr.h:644]: ip_addr2sbuf(): unknown address family 0 | ||
1(26528) CRITICAL: <core> [core/parser/../ip_addr.h:644]: ip_addr2sbuf(): unknown address family 0 | ||
1(26528) ERROR: <core> [core/parser/parse_via.c:1324]: parse_via_param(): failure parsing via param | ||
1(26528) ERROR: <core> [core/parser/parse_via.c:2704]: parse_via(): parsing via on: <SIP/2.0/UDP 127.0.1.1:5077;received= | ||
From: sipp <sip:[email protected]:5077>;tag=26427SIPpTag011 | ||
To: : <sip:2222222222@zƒ>;tag=e9b4f21d | ||
Call-ID: 99140ZDRlMjZiODJjZmJlZGMyZWEyMDM2OGIyZGRkZmNkOTQ | ||
Cseq: 2 BYE | ||
Server: fss | ||
Content-Length: 0 | ||
1(26528) ERROR: <core> [core/parser/parse_via.c:2708]: parse_via(): parse error, parsed so far:<SIP/2.0/UDP 127.0.1.1:5077;received= | ||
1(26528) ERROR: <core> [core/parser/msg_parser.c:125]: get_hdr_field(): bad via | ||
1(26528) ERROR: <core> [core/parser/msg_parser.c:331]: parse_headers(): bad header field [Via: SIP/2.0/UDP 127] | ||
1(26528) ERROR: <core> [core/parser/msg_parser.c:675]: parse_msg(): ERROR: parse_msg: message=<SIP/2.0 400 Bad Request URI | ||
Via: SIP/2.0/UDP 127.0.1.1:5077;received= | ||
From: sipp <sip:[email protected]:5077>;tag=26427SIPpTag011 | ||
To: : <sip:[email protected]>;tag=e9b4f21d | ||
Call-ID: 99140ZDRlMjZiODJjZmJlZGMyZWEyMDM2OGIyZGRkZmNkOTQ | ||
Cseq: 2 BYE | ||
Server: fss | ||
Content-Length: 0 | ||
**solution** review the sipp xml of uas | ||
Sample scipt whichs send BYE after reeiving INVITE and its ACK . Format of BYE to be sent from uas server should be as follows , | ||
```xml | ||
<?xml version="1.0" encoding="UTF-8" ?> | ||
<scenario name="Basic UAS responder"> | ||
|
||
<recv request="INVITE" crlf="true"> | ||
|
||
<action> | ||
<!-- since we need to send a request to the remote part --> | ||
<!-- we need to extract the Contact and the From header content --> | ||
<ereg regexp=".*" search_in="hdr" header="From" assign_to="remote_from"/> | ||
<!-- assign the content of the Contaact SIP URI to the remote_contact var --> | ||
<!-- first var of assign_to contains the whole match --> | ||
<ereg regexp="sip:(.*)>.*" search_in="hdr" header="Contact" assign_to="trash,remote_contact"/> | ||
</action> | ||
</recv> | ||
<Reference variables="trash"/> | ||
|
||
<send retrans="500"> | ||
<![CDATA[ | ||
SIP/2.0 200 OK | ||
[last_Via:] | ||
[last_From:] | ||
[last_To:];tag=[pid]SIPpTag01[call_number] | ||
[last_Call-ID:] | ||
[last_CSeq:] | ||
Contact: <sip:[local_ip]:[local_port];transport=[transport]> | ||
Content-Type: application/sdp | ||
Content-Length: [len] | ||
v=0 | ||
o=user1 53655765 2353687637 IN IP[local_ip_type] [local_ip] | ||
s=- | ||
c=IN IP[media_ip_type] [media_ip] | ||
t=0 0 | ||
m=audio [media_port] RTP/AVP 0 | ||
a=rtpmap:0 PCMU/8000 | ||
]]> | ||
</send> | ||
|
||
<recv request="ACK" crlf="true"> | ||
</recv> | ||
|
||
<send retrans="500"> | ||
<![CDATA[ | ||
BYE [$remote_contact] SIP/2.0 | ||
Via: SIP/2.0/[transport] [local_ip]:[local_port] | ||
From: sipp <sip:sipp@[local_ip]:[local_port]>;tag=[pid]SIPpTag01[call_number] | ||
To: [$remote_from] | ||
Call-ID: [call_id] | ||
Cseq: 1 BYE | ||
Contact: sip:sipp@[local_ip]:[local_port] | ||
Content-Length: 0 | ||
]]> | ||
</send> | ||
|
||
<recv response="200"> | ||
</recv> | ||
|
||
<CallLengthRepartition value="10, 50, 100, 500, 1000, 5000, 10000"/> | ||
</scenario> | ||
``` | ||
|
||
**Issue2** 3(8846) CRITICAL: sl [../../core/ip_addr.h:455]: init_su(): unknown address family 0 | ||
3(8846) CRITICAL: <core> [core/parser/../ip_addr.h:644]: ip_addr2sbuf(): unknown address family 0 | ||
3(8846) CRITICAL: <core> [core/parser/../ip_addr.h:644]: ip_addr2sbuf(): unknown address family 0 | ||
3(8846) ERROR: <core> [core/parser/parse_via.c:1324]: parse_via_param(): failure parsing via param | ||
**solution** set via params in UAS reposne | ||
``` | ||
[last_Via:] | ||
``` | ||
via param in UAS requests | ||
``` | ||
Via: SIP/2.0/[transport] [local_ip]:[local_port] | ||
``` | ||
|
||
|
43 changes: 43 additions & 0 deletions
43
stateful_transaction_handle/kamailio_statefull_transaction.cfg
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
# stateful handling of new transactions | ||
|
||
|
||
# ------------------ module loading ---------------------------------- | ||
|
||
loadmodule "sl.so" | ||
loadmodule "tm.so" | ||
|
||
|
||
# ------------------------- request routing logic ------------------- | ||
|
||
# main routing logic | ||
|
||
route{ | ||
# for testing purposes, simply okay all REGISTERs | ||
if (method=="REGISTER") { | ||
log("REGISTER"); | ||
sl_send_reply("200", "ok"); | ||
break; | ||
}; | ||
|
||
# create transaction state with t_newtran(); abort if error occurred | ||
if (t_newtran()){ | ||
log("New Transaction created"); | ||
} | ||
else { | ||
sl_reply_error(); | ||
break; | ||
}; | ||
|
||
log(1, "New Transaction Arrived\n"); | ||
|
||
# optional : add a check for matching username to print a cutom message with t_reply() | ||
if (uri=~"altanai@") { | ||
if (!t_reply("409", "Well , hello altanai !")) { | ||
sl_reply_error(); | ||
}; | ||
} else { | ||
if (!t_reply("699", "Do not proceed with this one")) { | ||
sl_reply_error(); | ||
}; | ||
}; | ||
} |