Osip/eXosip Source Code Analysis
This analysis s based on libosip2-2.2.3 and libeXosip2-2.2.3
1 osip Overview
1.1 How to use osip
call osip_init to init the osip library
create transport layer to handle the outgoing and incoming messages.
1.2 osip internal
It implements transaction layer which is defined by RFC3261
osip structure
struct osip
{
/* list of transactions for ict, ist, nict, nist */
osip_list_t *osip_ict_transactions; /**< list of ict transactions */
osip_list_t *osip_ist_transactions; /**< list of ist transactions */
osip_list_t *osip_nict_transactions; /**< list of nict transactions */
osip_list_t *osip_nist_transactions; /**< list of nist transactions */
osip_list_t *ixt_retransmissions; /**< list of ixt elements */
osip_message_cb_t msg_callbacks[OSIP_MESSAGE_CALLBACK_COUNT];
osip_kill_transaction_cb_t kill_callbacks[OSIP_KILL_CALLBACK_COUNT];
osip_transport_error_cb_t
tp_error_callbacks[OSIP_TRANSPORT_ERROR_CALLBACK_COUNT];
int (*cb_send_message) (osip_transaction_t *, osip_message_t *, char *,
int, int);
};
Transaction type:
ICT, /**< Invite Client (outgoing) Transaction */
IST, /**< Invite Server (incoming) Transaction */
NICT,/**< Non-Invite Client (outgoing) Transaction */
NIST /**< Non-Invite Server (incoming) Transaction */
Events:
RCV_REQINVITE, /**< Event is an incoming INVITE request */
RCV_REQACK, /**< Event is an incoming ACK request */
RCV_REQUEST, /**< Event is an incoming NON-INVITE and NON-ACK request */
RCV_STATUS_1XX, /**< Event is an incoming informational response */
RCV_STATUS_2XX, /**< Event is an incoming 2XX response */
RCV_STATUS_3456XX,/**< Event is an incoming final response (not 2XX) */
/* FOR OUTGOING MESSAGE */
SND_REQINVITE, /**< Event is an outgoing INVITE request */
SND_REQACK, /**< Event is an outgoing ACK request */
SND_REQUEST, /**< Event is an outgoing NON-INVITE and NON-ACK request */
SND_STATUS_1XX, /**< Event is an outgoing informational response */
SND_STATUS_2XX, /**< Event is an outgoing 2XX response */
SND_STATUS_3456XX,/**< Event is an outgoing final response (not 2XX) */
KILL_TRANSACTION, /**< Event to 'kill' the transaction before termination */
/* other timer event not listed here*/
Callback:
There are four kinds of callbacks upper layer need to set for osip library:
osip_message_cb_t msg_callbacks[OSIP_MESSAGE_CALLBACK_COUNT];
Osip lib will call message callbacks to notify upper layer some information
osip_kill_transaction_cb_t kill_callbacks[OSIP_KILL_CALLBACK_COUNT];
Osip lib will call these callbacks when a transaction is finished.
osip_transport_error_cb_t tp_error_callbacks[OSIP_TRANSPORT_ERROR_CALLBACK_COUNT];
Osip lib will call these callbacks when the transport layer meet error.
int (*cb_send_message) (osip_transaction_t *, osip_message_t *, char *,
int, int);
Osip lib will call this callback to do the real transportation of the message.
eXosip set these callbacks in eXosip_set_callbacks.
osip_init
init 4 types of transaction state machine:
set transition_t list:
typedef struct _transition_t
{
state_t state;
type_t type;
void (*method) (void *, void *);
}
transition_t;
It set the process method for a type of event in a type of state
for example, in __ict_load_fsm ():
transition = (transition_t *) osip_malloc (sizeof (transition_t));
transition->state = ICT_PRE_CALLING;
transition->type = SND_REQINVITE;
transition->method = (void (*)(void *, void *)) &ict_snd_invite;
osip_list_add (ict_fsm->transitions, transition, -1);
How to process the SIP message
TU calls some functions to queue osip_event to the fifo of the transaction.
TU calls funtions, such as osip_ict_execute, which calls osip_transaction_execute to handle the osip_event in fifo:
osip_transaction_execute first find the type of event, and then get that type of fsm, and then call fsm_callmethod
fsm_callmethod will find the transition according to event type and transaction state, and the call transition->method
2 eXosip Overview
2.1 How to use eXosip lib
call eXosip and eXosip_listen_addr
poll the event periodly
2.2 eXosip lib internal:
It’s based on osip lib. It implements transport layer which is defined by RFC3261
The eXosip doesn’t wrapp the osip library. It just provides a transport layer for supporting message transfer.
eXosip_t structure
struct eXosip_t
{
struct eXosip_net net_interfaces[3];
osip_list_t *j_transactions;
osip_t *j_osip;
int j_stop_ua;
void *j_thread;
jpipe_t *j_socketctl; // to notify an request from upper layer is queued to fifo of transaction
jpipe_t *j_socketctl_event; //to notify event to upper layer
osip_fifo_t *j_events; //save event which will be sent to upper layer
};
eXosip_init:
init the struct eXosip
call osip_init to init the struct osip which is a member of eXosip(eXosip.j_osip
set osip lib callback: eXosip_set_callbacks (osip):
cb_snd_message is most important callback
create two pipe(eXosip.j_socketctl and eXosip.j_socketctl_event)
init fifo: osip_fifo_init(eXosip.j_events)
j_stop_ua is used to indicate whether thread should be stopped (used in _eXosip_thread)
eXosip_listen_addr:
listen on a port for SIP message
call _eXosip_thread
_eXosip_thread:
eXosip_read_message use select to wait for the message from upper layer or network
call osip_timers_ict_execute, osip_timers_nict_execute osip_timers_ist_execute and osip_timers_nist_execute to handle transaction timeout
call osip_ict_execute ,osip_nict_execute, osip_ist_execute and osip_nist_execute to handle the event in transaction FIFO
eXosip_process_newrequest is used to init UAS transaction
(eXosip_call_send_initial_invite is used to init UAC transaction)
for outgoing message:
build SIP message, put to the transaction fifo by calling OSIP API
then write something to pipe to notify _eXosip_thread to handle transaction
for incoming message:
_eXosip_thread is listening to the incoming socket, if there is a incoming message,
the _eXosip_thread will be waken up to create a new transaction, and handle transaction.
3 The process to send an outgoing message
eXosip_call_build_initial_invite
eXosip_call_send_initial_invite
eXosip_call_init
osip_transaction_init to init a ICT transaction
osip_new_outgoing_sipmessage to create a osip event
osip_transaction_add_event to add event to transaction FIFO
__eXosip_wakeup to wake up _eXosip_thread to handle the event
_eXosip_thread call osip_ict_execute, osip_ict_execute call osip_transaction_execute to find the type of event, get that type of fsm, and then call fsm_callmethod to handle the event. As the above description, fsm_callmethod will find the transition according to event type and transaction state, and the call transition->method. For ICT transaction in ICT_PRE_CALLING state, __ict_load_fsm set method to ict_snd_invite
ict_snd_invite will call osip-> cb_send_message, which is set by eXosip_set_callbacks as cb_snd_message
cb_snd_message will send the message to remote peer. _eXosip_thread will wait for remote response, and call osip_ict_execute to handle the response. The transaction state machine will be changed to different state according to the response. Meanwhile, the state machine will call callback set by eXosip_set_callbacks to notify eXosip state change. When eXosip receive the notification, eXosip will send eXosip-defined event to upper layer by queuing it to j_events. Upper layer applilcation which should call eXosip_event_wait to wait for events will get event, and handle it. Please refer to the example application UCT IMS Client.
4 The process to receive an incoming message
It is processed in _eXosip_thread:
receives the incoming message
eXosip_process_newrequest to create a new transaction, put to transaction FIFO
osip_ist_execute will handle the event
the following process is similar to osip_ict_execute described on the section 3.