libosip  5.3.0
How-To manage dialogs.

Description.

Full API is there:

oSIP dialog Routines

Dialog management is a powerful facility given by oSIP. This feature is needed by SIP end point who has the capability to answer calls. (i.e. answering 200 OK to an INVITE).

A Dialog is a context for a call establishment in oSIP. It's not useless to say that ONE invite request can lead to several call establishment. This can happen if your call has been forked by a proxy and several user agent was contacted and replied at the same time. It is true that this case won't probably happen several times a month...

There is two ways of creating a dialog. In one case, you are the CALLER and in the other case, you will be the CALLEE.

Creating a dialog as a CALLER.

In this case, you have to create a dialog each time you receive an answer with a code between 101 and 299. The best place in oSIP to actually create a dialog is of course in the callback that announce such SIP messages. Of course, each time you receive a response, you have to check for an existing dialog associated to this INVITE that can have been created by earlier SIP answer coming from the same User Agent. The code in the callback will look like the following:

void cb_rcv1xx(osip_transaction_t *tr,osip_message_t *sip)
{
osip_dialog_t *dialog;
if (MSG_IS_RESPONSEFOR(sip, "INVITE")&&!MSG_TEST_CODE(sip, 100))
{
dialog = my_application_search_existing_dialog(sip);
if (dialog==NULL) //NO EXISTING DIALOG
{
i = osip_dialog_init_as_uac(&dialog, sip);
my_application_add_existing_dialog(dialog);
}
}
else
{
//no dialog establishment for other REQUEST
}
}
int osip_dialog_init_as_uac(osip_dialog_t **dialog, osip_message_t *response)
Definition: osip_dialog.c:455
#define MSG_TEST_CODE(msg, code)
Definition: osip_message.h:354
Definition: osip_dialog.h:54
Definition: osip_message.h:54
Definition: osip.h:364

Creating a dialog as a CALLEE

In this case, you will have to create a dialog upon receiving the first transmission of the INVITE request. The correct place to do that is inside the callback previously registered to announce new INVITE. First, you will build a SIP answer like 180 or 200 and you'll be able to create a dialog by calling the following code:

osip_dialog_t *dialog;
osip_dialog_init_as_uas(&dialog, original_invite, response_that_you_build);
int osip_dialog_init_as_uas(osip_dialog_t **dialog, osip_message_t *invite, osip_message_t *response)
Definition: osip_dialog.c:496

To make things working, you MUST create a VALID response: do not forget to create a new tag and put it in the 'To' header. The dialog management heavily depends on this tag.

Matching REQUEST against existing dialog.

if (osip_dialog_match_as_uas (jd->d_dialog, evt->sip) == 0)
break;
int osip_dialog_match_as_uas(osip_dialog_t *dlg, osip_message_t *request)
Definition: osip_dialog.c:242

Matching cancel against an INVITE.

Here is code that I use in eXosip2 to match incoming CANCEL against previous received INVITE. This is a bit different than dialog because CANCEL match a specific INVITE transaction, not a dialog:

static int
_cancel_match_invite (osip_transaction_t * invite, osip_message_t * cancel)
{
osip_via_t *via;
osip_via_param_get_byname (invite->topvia, "branch", &br);
via = osip_list_get (&cancel->vias, 0);
if (via == NULL)
return OSIP_SYNTAXERROR; // request without via?
osip_via_param_get_byname (via, "branch", &br2);
if (br != NULL && br2 == NULL)
return OSIP_UNDEFINED_ERROR;
if (br2 != NULL && br == NULL)
return OSIP_UNDEFINED_ERROR;
if (br2 != NULL && br != NULL) { // compliant UA :)
if (br->gvalue != NULL && br2->gvalue != NULL && 0 == strcmp (br->gvalue, br2->gvalue))
return OSIP_SUCCESS;
return OSIP_UNDEFINED_ERROR;
}
/old backward compatibility mechanism
if (0 != osip_call_id_match (invite->callid, cancel->call_id))
return OSIP_UNDEFINED_ERROR;
if (0 != osip_to_tag_match (invite->to, cancel->to))
return OSIP_UNDEFINED_ERROR;
if (0 != osip_from_tag_match (invite->from, cancel->from))
return OSIP_UNDEFINED_ERROR;
if (0 != osip_via_match (invite->topvia, via))
return OSIP_UNDEFINED_ERROR;
return OSIP_SUCCESS;
}
int osip_call_id_match(osip_call_id_t *callid1, osip_call_id_t *callid2)
Definition: osip_call_id.c:209
int osip_from_tag_match(osip_from_t *from1, osip_from_t *from2)
Definition: osip_from.c:744
void * osip_list_get(const osip_list_t *li, int pos)
Definition: osip_list.c:178
int osip_to_tag_match(osip_to_t *to1, osip_to_t *to2)
Definition: osip_to.c:93
int osip_via_match(osip_via_t *via1, osip_via_t *via2)
Definition: osip_via.c:515
#define osip_via_param_get_byname(header, name, dest)
Definition: osip_via.h:196
osip_to_t * to
Definition: osip_message.h:92
osip_list_t vias
Definition: osip_message.h:93
osip_call_id_t * call_id
Definition: osip_message.h:71
osip_from_t * from
Definition: osip_message.h:83
osip_via_t * topvia
Definition: osip.h:369
osip_call_id_t * callid
Definition: osip.h:372
osip_to_t * to
Definition: osip.h:371
osip_from_t * from
Definition: osip.h:370
Definition: osip_uri.h:55
char * gvalue
Definition: osip_uri.h:57
Definition: osip_via.h:46