Skip to content

Commit

Permalink
stateful transaction handling readme
Browse files Browse the repository at this point in the history
  • Loading branch information
altanai committed Sep 18, 2019
1 parent b434e3d commit 668a2c2
Show file tree
Hide file tree
Showing 3 changed files with 251 additions and 0 deletions.
53 changes: 53 additions & 0 deletions stateful_dialog_handle/README.md
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
155 changes: 155 additions & 0 deletions stateful_transaction_handle/README.md
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 stateful_transaction_handle/kamailio_statefull_transaction.cfg
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();
};
};
}

0 comments on commit 668a2c2

Please sign in to comment.