libeXosip2  5.2.0
How-To initialize libeXosip2.

Initialize eXosip and prepare transport layer

When using eXosip, your first task is to initialize both eXosip context and libosip library (parser and state machines). This must be done prior to any use of libeXosip2.

Also, you need to prepare the transport layer and choose either UDP, TCP, TLS or DTLS.

Here is the basic mandatory setup:

#include <eXosip2/eXosip.h>
eXosip_t *ctx;
int i;
int port=5060;
TRACE_INITIALIZE (6, NULL);
ctx = eXosip_malloc();
if (ctx==NULL)
return -1;
i=eXosip_init(ctx);
if (i!=0)
return -1;
i = eXosip_listen_addr (ctx, IPPROTO_UDP, NULL, port, AF_INET, 0);
if (i!=0)
{
fprintf (stderr, "could not initialize transport layer\n");
return -1;
}

Choosing UDP, TCP, TLS or DTLS

If you wish to use other transport protocol, you can select:

Specific setup for TLS

TLS may requires specific setup. TLS introduce in fact two interesting features:

If you don't need server verification, TLS is very easy to setup. You don't need to configure any certificate, key or root certificate...

Here is the code to disable certificate verification:

int val=0;

If you require validation, a few work still needs to be done. What you need depends on your platform/os.

On windows, exosip has built-in support for "Windows Certificate Store". Thus, you only need to add your certifcate and keys in the official "Windows Certificate Store".

On macosx, exosip has built-in support for the certificate store.

Additionnal setup

A few options can be modified in eXosip2. However, most default are good values and if your sip service is configured correctly, no much settings beyond default would be required.

Here is a basic setup that might be appropriate for usual configuration:

int val;
eXosip_set_user_agent (ctx, "exosipdemo/0.0.0");
val=17000;
val=2;
val=1;
val=26;
eXosip_set_option (ctx, EXOSIP_OPT_SET_DSCP, (void*)&dscp_value);

NAT and Contact header

There would be much to say about this. Most being unrelated to the eXosip2 stack itself...

The most important feature with SIP is to be able to receive SIP requests. You wouldn't be glad if your phone remains silent. However, it's in theory not possible to guess what should contain the Contact headers we are creating.

Most proxy will repair our broken contact, no matter why eXosip2 or any SIP application has provided a wrong value. The SIP specification is not very clear on the various client and server behaviors for Contact verifications.

However:

  1. No matter, what eXosip2, most proxy will repair correctly.
  2. No matter what you think is right, some people think another way is right.
  3. No matter sip, proxy and people: NETWORK RULES ALWAYS APPLIES FIRST! ;)

Anyway, to avoid problems:

  1. You should always do your best to put correct information in Contact.
  2. Most of the time, you can't, but it should work anyway.

Conclusion:

  1. Without any configuration (NAT, STUN, etc), your proxy should be able to find out how to reach you (over the existing connection).
  2. If it can't (whatever the reason), you can try workarounds and options.

The options you have:

If you still have NAT issue, think about using TLS: broken NAT sometimes block SIP packets, but with encryption, broken NAT can't do anything!

About DNS

eXosip2 should be compiled with c-ares. This is very important as c-ares provides non blocking, portable and full support for all required SIP operation.

By default, SIP requires usage of specific DNS features to discover the IP address of a sip service.

For complete information, check rfc3263.txt: Locating SIP servers.

val=2;

If NAPTR is not set for the service you used which happens in many case, SRV record or normal DNS will be used as a fallback. It should not slow too much the procedure. However, it is still usefull in some case to disable NAPTR because there still exist a few DNS server that remains silent when sending NAPTR request. In that very specific use-case, this may lead to very slow fallback to normal DNS...

val=0;

Handle eXosip2 events (eXosip_event_t)

The eXosip_event contains all information you need:

Those identifiers are re-used in related eXosip2 API to make it simpler to control context. The request, answer and ack are fully duplicated so that you can access them without locking the eXosip2 context.

Now you have to handle eXosip events. Here is some code to get eXosip_event from the eXosip2 stack.

Note:* For advanced users, or more real time app, you may also use lower level API so that you can get woken up on a select call when an event occurs.

for (;;)
{
evt = eXosip_event_wait (ctx, 0, 50);
if (evt == NULL)
continue;
if (evt->type == EXOSIP_CALL_NEW)
{
....
....
}
else if (evt->type == EXOSIP_CALL_ACK)
{
....
....
}
else if (evt->type == EXOSIP_CALL_ANSWERED)
{
....
....
}
else .....
....
....
}

You will receive one event for each SIP message sent. Each event contains the original request of the affected transaction and the last response that triggers the event when available.

You can access all headers from those messages and store them in your own context for other actions or graphic displays.

For example, when you receive a REFER request for a call transfer, you'll typically retreive the "refer-To" header:

osip_header_t *referto_head = NULL;
i = osip_message_header_get_byname (evt->sip, "refer-to", 0, &referto_head);
if (referto_head == NULL || referto_head->hvalue == NULL)

Here are a few examples:

if (evt->type == EXOSIP_CALL_NEW)
{
eXosip_lock (ctx);
eXosip_call_send_answer (ctx, evt->tid, 180, NULL);
}
if (evt->type == EXOSIP_MESSAGE_NEW && osip_strcasecmp (minfo.method, "MESSAGE") == 0) {
{
osip_message_t *answer=NULL;
int i;
eXosip_lock (ctx);
i = eXosip_message_build_answer (ctx, evt->tid, 200, &answer);
i = eXosip_message_send_answer (ctx, evt->tid, 200, answer);
}
if (evt->type == EXOSIP_CALL_MESSAGE_NEW && osip_strcasecmp (minfo.method, "REFER") == 0) {
osip_header_t *refer_to = NULL;
eXosip_lock (ctx);
i = eXosip_call_build_answer (ctx, evt->tid, 202, &answer);
i = eXosip_call_send_answer (ctx, evt->tid, 202, answer);
i = osip_message_header_get_byname (evt->request, "refer-to", 0, &refer_to);
if (i >= 0) {
printf ("you must start call to: %s\n", refer_to->hvalue);
...
}
else {
}
eXosip_call_terminate (ctx, evt->cid, evt->did, 486);
}
eXosip_unlock
int eXosip_unlock(struct eXosip_t *excontext)
eXosip_automatic_action
void eXosip_automatic_action(struct eXosip_t *excontext)
EXOSIP_OPT_DNS_CAPABILITIES
#define EXOSIP_OPT_DNS_CAPABILITIES
Definition: eX_setup.h:120
EXOSIP_OPT_SET_IPV4_FOR_GATEWAY
#define EXOSIP_OPT_SET_IPV4_FOR_GATEWAY
Definition: eX_setup.h:115
eXosip.h
eXosip API
eXosip_event::request
osip_message_t * request
Definition: eXosip.h:380
eXosip_call_terminate
int eXosip_call_terminate(struct eXosip_t *excontext, int cid, int did)
EXOSIP_OPT_SET_DSCP
#define EXOSIP_OPT_SET_DSCP
Definition: eX_setup.h:121
eXosip_set_option
int eXosip_set_option(struct eXosip_t *excontext, int opt, const void *value)
EXOSIP_CALL_MESSAGE_NEW
@ EXOSIP_CALL_MESSAGE_NEW
Definition: eXosip.h:326
eXosip_call_build_answer
int eXosip_call_build_answer(struct eXosip_t *excontext, int tid, int status, osip_message_t **answer)
EXOSIP_MESSAGE_NEW
@ EXOSIP_MESSAGE_NEW
Definition: eXosip.h:340
eXosip_event::tid
int tid
Definition: eXosip.h:384
eXosip_event_wait
eXosip_event_t * eXosip_event_wait(struct eXosip_t *excontext, int tv_s, int tv_ms)
EXOSIP_OPT_SET_TLS_VERIFY_CERTIFICATE
#define EXOSIP_OPT_SET_TLS_VERIFY_CERTIFICATE
Definition: eX_setup.h:142
eXosip_masquerade_contact
void eXosip_masquerade_contact(struct eXosip_t *excontext, const char *public_address, int port)
eXosip_message_send_answer
int eXosip_message_send_answer(struct eXosip_t *excontext, int tid, int status, osip_message_t *answer)
eXosip_event::did
int did
Definition: eXosip.h:385
eXosip_call_send_answer
int eXosip_call_send_answer(struct eXosip_t *excontext, int tid, int status, osip_message_t *answer)
eXosip_event::type
eXosip_event_type_t type
Definition: eXosip.h:376
EXOSIP_CALL_ACK
@ EXOSIP_CALL_ACK
Definition: eXosip.h:321
eXosip_listen_addr
int eXosip_listen_addr(struct eXosip_t *excontext, int transport, const char *addr, int port, int family, int secure)
eXosip_message_build_answer
int eXosip_message_build_answer(struct eXosip_t *excontext, int tid, int status, osip_message_t **answer)
EXOSIP_OPT_USE_RPORT
#define EXOSIP_OPT_USE_RPORT
Definition: eX_setup.h:114
EXOSIP_CALL_ANSWERED
@ EXOSIP_CALL_ANSWERED
Definition: eXosip.h:316
eXosip_event_free
void eXosip_event_free(eXosip_event_t *je)
eXosip_init
int eXosip_init(struct eXosip_t *excontext)
eXosip_event
Definition: eXosip.h:375
eXosip_quit
void eXosip_quit(struct eXosip_t *excontext)
eXosip_set_user_agent
void eXosip_set_user_agent(struct eXosip_t *excontext, const char *user_agent)
eXosip_lock
int eXosip_lock(struct eXosip_t *excontext)
eXosip_malloc
struct eXosip_t * eXosip_malloc(void)
EXOSIP_OPT_UDP_KEEP_ALIVE
#define EXOSIP_OPT_UDP_KEEP_ALIVE
Definition: eX_setup.h:111
eXosip_event::cid
int cid
Definition: eXosip.h:388