📄 osip.h
字号:
/* The oSIP library implements the Session Initiation Protocol (SIP -rfc3261-) Copyright (C) 2001,2002,2003 Aymeric MOIZARD jack@atosc.org This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA*/#ifndef _OSIP_H_#define _OSIP_H_#include <osip/const.h>#include <time.h>#ifdef __sun#include <sys/types.h>#endif#include <osip/smsg.h>#include <osip/fifo.h>/** * @file osip.h * @brief oSIP fsm Routines * * <H2>Introduction.</H2> * fsm stands for 'finite state machine'. The possible STATE of the state * machines are defined in the enum state. In oSIP, you can actually find * 4 different state machines. Those state machines definitions are directly * related to the definitions of transactions from the SIP specifications. * (See section: 17.1.1, 17.1.2, 17.2.1, 17.2.2). In the 4 drawings shown * in those sections, you'll find the possible STATES and the possible EVENTS * (sipevent_t) that can occur. EVENTS can be either TIMEOUT events and * SIP message (incoming and outgoing) events. * <H2>Why 4 finite state machines.</H2> * <BR>SIP has two different kind of transaction: INVITE and NON-INVITE ones. * Also, a SIP User Agent can act as a server and as a client. This simply * leads to 4 transactions state machines. * <BR> * <H2>Step 1: oSIP initialisation</H2> * <BR>To use oSIP, a program MUST first initialise internal elements in the * stack. The initialisation is shown below: * <pre><code> * osip_t *osip; * // initialise internal element first * if (0!=osip_global_init()) * return -1; * // allocate a global osip element. * if (0!=osip_init(&osip)) * return -1; * * // the next step is the initialisation of the callbacks used by the * // oSIP stack to announce events (when a transition occurs in the fsm) * * // This callback is somewhat special and is used by oSIP to inform * // the application that a message has to be sent. The message is * // sent by your application! oSIP has no ways to send it alone. * // Also, the method you supply will be called with default values where * // you should send the SIP message. You are not mandated to send the * // SIP message by using those default values. * // the callback MUST return 0 on success, 1 on ECONNREFUSED, -1 on error. * osip_setcb_send_message(osip, &application_cb_snd_message); * * // here is the long list of callback that you can register. Some * // of this callbacks are very useless (announcing a retransmission, * // or announcing that you have sent a SIP message which you may already * // know...). * * // those callbacks are mandatory. They are called when oSIP has decided * // that this transaction MUST no longer be handled by oSIP. (This is * // called in both successful or error cases scenario) * osip_setcb_ict_kill_transaction(osip,&application_cb_ict_kill_transaction); * osip_setcb_ist_kill_transaction(osip,&application_cb_ist_kill_transaction); * osip_setcb_nict_kill_transaction(osip,&application_cb_nict_kill_transaction); * osip_setcb_nist_kill_transaction(osip,&application_cb_nist_kill_transaction); * * // those callbacks are optional. The purpose is to announce retransmissions * // of SIP message decided by the oSIP stack. (They can be used for statistics?) * osip_setcb_ict_2xx_received2(osip,&application_cb_rcvresp_retransmission); * osip_setcb_ict_3456xx_received2(osip,&application_cb_rcvresp_retransmission); * osip_setcb_ict_invite_sent2(osip,&application_cb_sndreq_retransmission); * osip_setcb_ist_2xx_sent2(osip,&application_cb_sndresp_retransmission); * osip_setcb_ist_3456xx_sent2(osip,&application_cb_sndresp_retransmission); * osip_setcb_ist_invite_received2(osip,&application_cb_rcvreq_retransmission); * osip_setcb_nict_2xx_received2(osip,&application_cb_rcvresp_retransmission); * osip_setcb_nict_3456xx_received2(osip,&application_cb_rcvresp_retransmission); * osip_setcb_nict_request_sent2(osip,&application_cb_sndreq_retransmission); * osip_setcb_nist_2xx_sent2(osip,&application_cb_sndresp_retransmission); * osip_setcb_nist_3456xx_sent2(osip,&application_cb_sndresp_retransmission); * osip_setcb_nist_request_received2(osip,&application_cb_rcvreq_retransmission); * * // those callbacks are mandatory. They are used to announce network related * // errors (the return code of the network callback if it was not 0) * osip_setcb_ict_transport_error(osip,&application_cb_transport_error); * osip_setcb_ist_transport_error(osip,&application_cb_transport_error); * osip_setcb_nict_transport_error(osip,&application_cb_transport_error); * osip_setcb_nist_transport_error(osip,&application_cb_transport_error); * * // those callbacks are optional. They are used to announce the initial * // request sent for a newly created transaction. * osip_setcb_ict_invite_sent (osip,&application_cb_sndinvite); * osip_setcb_ict_ack_sent (osip,&application_cb_sndack); * osip_setcb_nict_register_sent(osip,&application_cb_sndregister); * osip_setcb_nict_bye_sent (osip,&application_cb_sndbye); * osip_setcb_nict_cancel_sent (osip,&application_cb_sndcancel); * osip_setcb_nict_info_sent (osip,&application_cb_sndinfo); * osip_setcb_nict_options_sent (osip,&application_cb_sndoptions); * osip_setcb_nict_subscribe_sent (osip,&application_cb_sndoptions); * osip_setcb_nict_notify_sent (osip,&application_cb_sndoptions); * osip_setcb_nict_unknown_sent(osip,&application_cb_sndunkrequest); * * // those callbacks are mandatory. They are used to announce the initial * // response received for a transaction. (for SIP response between 100 and 199, * // all responses are announced because this is not a retransmission case) * osip_setcb_ict_1xx_received(osip,&application_cb_rcv1xx); * osip_setcb_ict_2xx_received(osip,&application_cb_rcv2xx); * osip_setcb_ict_3xx_received(osip,&application_cb_rcv3xx); * osip_setcb_ict_4xx_received(osip,&application_cb_rcv4xx); * osip_setcb_ict_5xx_received(osip,&application_cb_rcv5xx); * osip_setcb_ict_6xx_received(osip,&application_cb_rcv6xx); * * // those callbacks are optional. They are used to announce the initial * // response sent for a transaction. (for SIP response between 100 and 199, * // all responses are announced because this is not a retransmission case) * osip_setcb_ist_1xx_sent(osip,&application_cb_snd1xx); * osip_setcb_ist_2xx_sent(osip,&application_cb_snd2xx); * osip_setcb_ist_3xx_sent(osip,&application_cb_snd3xx); * osip_setcb_ist_4xx_sent(osip,&application_cb_snd4xx); * osip_setcb_ist_5xx_sent(osip,&application_cb_snd5xx); * osip_setcb_ist_6xx_sent(osip,&application_cb_snd6xx); * * // those callbacks are mandatory. They are used to announce the initial * // response received for a transaction. (for SIP response between 100 and 199, * // all responses are announced because this is not a retransmission case) * osip_setcb_nict_1xx_received(osip,&application_cb_rcv1xx); * osip_setcb_nict_2xx_received(osip,&application_cb_rcv2xx); * osip_setcb_nict_3xx_received(osip,&application_cb_rcv3xx); * osip_setcb_nict_4xx_received(osip,&application_cb_rcv4xx); * osip_setcb_nict_5xx_received(osip,&application_cb_rcv5xx); * osip_setcb_nict_6xx_received(osip,&application_cb_rcv6xx); * * // those callbacks are optional. They are used to announce the initial * // response sent for a transaction. (for SIP response between 100 and 199, * // all responses are announced because this is not a retransmission case) * osip_setcb_nist_1xx_sent(osip,&application_cb_snd1xx); * osip_setcb_nist_2xx_sent(osip,&application_cb_snd2xx); * osip_setcb_nist_3xx_sent(osip,&application_cb_snd3xx); * osip_setcb_nist_4xx_sent(osip,&application_cb_snd4xx); * osip_setcb_nist_5xx_sent(osip,&application_cb_snd5xx); * osip_setcb_nist_6xx_sent(osip,&application_cb_snd6xx); * * // those callbacks are mandatory. They are used to announce the initial * // request received for a transaction. It is not useless to notice that * // a special behaviour exist for the 200 OK and the ACK in the case of * // a successful INVITE transaction. This will be discussed later. * osip_setcb_ist_invite_received (osip,&application_cb_rcvinvite); * osip_setcb_ist_ack_received (osip,&application_cb_rcvack); * // this callback is optional * osip_setcb_ist_ack_received2 (osip,&application_cb_rcvack2); * osip_setcb_nist_register_received(osip,&application_cb_rcvregister); * osip_setcb_nist_bye_received (osip,&application_cb_rcvbye); * osip_setcb_nist_cancel_received (osip,&application_cb_rcvcancel); * osip_setcb_nist_info_received (osip,&application_cb_rcvinfo); * osip_setcb_nist_options_received (osip,&application_cb_rcvoptions); * osip_setcb_nist_subscribe_received(osip,&application_cb_rcvoptions); * osip_setcb_nist_notify_received (osip,&application_cb_rcvoptions); * osip_setcb_nist_unknown_received (osip,&application_cb_rcvunkrequest); * * </code></pre> * <P> * <H2>Step 2: Initialising a new transaction.</H2> * <BR>Let's assume you want to implement a User Agent and you want to * start a REGISTER transaction. Using the parser library, you will first * have to build a SIP compliant message. (oSIP, as a low layer library * provides an interface to build SIP messages, but it's up to you to * correctly fill all the required fields.) * As soon as you have build the SIP message, you are ready to start a new * transaction. Here is the code: * <BR><pre><code> * osip_t *osip = your_global_osip_context; * transaction_t *transaction; * sip_t *sip_register_message; * sipevent_t *sipevent; * * application_build_register(&sip_register_message); * transaction_init(&transaction, * NICT, //a REGISTER is a Non-Invite-Client-Transaction * osip, * sip_register_message); * * // If you have a special context that you want to associate to that * // transaction, you can use a special method that associate your context * // to the transaction context. * * transaction_set_your_instance(transaction, my_context); * * // at this point, the transaction context exists in oSIP but you still have * // to give the SIP message to the finite state machine. * sipevent = osip_new_outgoing_sipmessage(msg); * sipevent->transactionid = transaction->transactionid; * transaction_add_event(transaction, sipevent); * // at this point, the event will be handled by oSIP. (The memory resource will * // also be handled by oSIP). Note that no action is taken there. * </pre></code> * <P>Adding new events in the fsm is made with similar code. * <P> * <H2>Step 3: Consuming events.</H2> * <BR>The previous step show how to create a transaction and one possible way * to add a new event. (Note, that some events -the TIMEOUT_* ones- will be * added by oSIP not by the application). In this step, we describe how the * oSIP stack will consume events. In fact, this is very simple, but you * should be aware that it's not always allowed to consume an event at any time! * The fsm MUST consume events sequentially within a transaction. This means * that when your are calling transaction_execute(), it is forbidden to call * this method again with the same transaction context until the first call * has returned. In a multi threaded application, if one thread handles one * transaction, the code will be the following: * <BR><pre><code> * while (1) * { * se = (sipevent_t *)fifo_get(transaction->transactionff); * if (se==NULL) * sthread_exit(); * if (transaction_execute(transaction,se)<1) // deletion asked * sthread_exit(); * } * </pre></code> * <P> * <H2>Step 4: How the stack will announce the events</H2> * Looking at the case of a usual outgoing REGISTER transaction, this behaviour * is expected. * <BR>When an event is seen as useful for the fsm, it means that a transition * from one state to another has to be done on the transaction context. If the * event is SND_REQUEST (this is the case for an outgoing REGISTER), the * callback previously registered to announce this action will be called. This * callback is useless for the application as no action has to be taken at this * step. A more interesting announcement will be made when consuming the * first final response received. If the callbacks associated to 2xx message * is called, then the transaction has succeeded. Inside this callback, you * will probably inform the user of the success of the registration if you want * to do so... * If the final response is not a 2xx, or the network callback is called, you'll * probably want to take some actions. For example, if you receive a 302, you'll * probably want to retry a registration at the new location. All that decision * is up to you. *//** * @defgroup oSIP_FSM oSIP fsm Handling * @ingroup oSIP * @{ */#ifdef __cplusplusextern "C"{#endif/** * Enumeration for transaction state. * <BR> * <BR>Here is the list of possible values for transactions: * <BR> ICT_PRE_CALLING, * <BR> ICT_CALLING, * <BR> ICT_PROCEEDING, * <BR> ICT_COMPLETED, * <BR> ICT_TERMINATED, * <BR> * <BR> IST_PRE_PROCEEDING, * <BR> IST_PROCEEDING, * <BR> IST_COMPLETED, * <BR> IST_CONFIRMED, * <BR> IST_TERMINATED, *<BR> * <BR> NICT_PRE_TRYING, * <BR> NICT_TRYING, * <BR> NICT_PROCEEDING, * <BR> NICT_COMPLETED, * <BR> NICT_TERMINATED, *<BR> * <BR> NIST_PRE_TRYING, * <BR> NIST_TRYING, * <BR> NIST_PROCEEDING, * <BR> NIST_COMPLETED, * <BR> NIST_TERMINATED, * */ typedef enum _state_t { /* STATES for invite client transaction */ ICT_PRE_CALLING, ICT_CALLING, ICT_PROCEEDING, ICT_COMPLETED, ICT_TERMINATED, /* STATES for invite server transaction */ IST_PRE_PROCEEDING, /* this is used to only announce once the INVITE */ IST_PROCEEDING, IST_COMPLETED, IST_CONFIRMED, IST_TERMINATED, /* STATES for NON-invite client transaction */ NICT_PRE_TRYING, NICT_TRYING, NICT_PROCEEDING, NICT_COMPLETED, NICT_TERMINATED, /* STATES for NON-invite server transaction */ NIST_PRE_TRYING, NIST_TRYING, NIST_PROCEEDING, NIST_COMPLETED, NIST_TERMINATED,#ifndef DOXYGEN DIALOG_EARLY, DIALOG_CONFIRMED, DIALOG_CLOSE /* ?? */#endif } state_t;/** * Enumeration for event type. * <BR>The list of values that you need to know is reduced to this: * <BR> RCV_REQINVITE, * <BR> RCV_REQACK, * <BR> RCV_REQUEST, * <BR> RCV_STATUS_1XX, * <BR> RCV_STATUS_2XX, * <BR> RCV_STATUS_3456XX, *<BR> * <BR> SND_REQINVITE, * <BR> SND_REQACK, * <BR> SND_REQUEST, * <BR> SND_STATUS_1XX, * <BR> SND_STATUS_2XX, * <BR> SND_STATUS_3456XX, */ typedef enum type_t {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -