⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 osip.h

📁 SIP协议栈实现
💻 H
📖 第 1 页 / 共 3 页
字号:
/*  The oSIP library implements the Session Initiation Protocol (SIP -rfc2543-)  Copyright (C) 2001  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 <osipparser2/osip_const.h>#include <time.h>#ifdef __sun#include <sys/types.h>#endif#include <osipparser2/osip_parser.h>#include <osip2/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 * (osip_event_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; * // 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_set_cb_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_set_kill_transaction_callback(osip ,OSIP_ICT_KILL_TRANSACTION,                                 &cb_ict_kill_transaction);  osip_set_kill_transaction_callback(osip ,OSIP_NIST_KILL_TRANSACTION,                                 &cb_ist_kill_transaction);  osip_set_kill_transaction_callback(osip ,OSIP_NICT_KILL_TRANSACTION,                                 &cb_nict_kill_transaction);  osip_set_kill_transaction_callback(osip ,OSIP_NIST_KILL_TRANSACTION,                                 &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_set_message_callback(osip ,OSIP_ICT_STATUS_2XX_RECEIVED_AGAIN,                        &cb_rcvresp_retransmission);  osip_set_message_callback(osip ,OSIP_ICT_STATUS_3456XX_RECEIVED_AGAIN,                        &cb_rcvresp_retransmission);  osip_set_message_callback(osip ,OSIP_ICT_INVITE_SENT_AGAIN,                        &cb_sndreq_retransmission);  osip_set_message_callback(osip ,OSIP_IST_STATUS_2XX_SENT_AGAIN,                        &cb_sndresp_retransmission);  osip_set_message_callback(osip ,OSIP_IST_STATUS_3456XX_SENT_AGAIN,                        &cb_sndresp_retransmission);  osip_set_message_callback(osip ,OSIP_IST_INVITE_RECEIVED_AGAIN,                        &cb_rcvreq_retransmission);  osip_set_message_callback(osip ,OSIP_NICT_STATUS_2XX_RECEIVED_AGAIN,                        &cb_rcvresp_retransmission);  osip_set_message_callback(osip ,OSIP_NICT_STATUS_3456XX_RECEIVED_AGAIN,                        &cb_rcvresp_retransmission);  osip_set_message_callback(osip ,OSIP_NICT_REQUEST_SENT_AGAIN,                        &cb_sndreq_retransmission);  osip_set_message_callback(osip ,OSIP_NIST_STATUS_2XX_SENT_AGAIN,                        &cb_sndresp_retransmission);  osip_set_message_callback(osip ,OSIP_NIST_STATUS_3456XX_SENT_AGAIN,                        &cb_sndresp_retransmission);  osip_set_message_callback(osip ,OSIP_NIST_REQUEST_RECEIVED_AGAIN,                        &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_set_transport_error_callback(osip ,OSIP_ICT_TRANSPORT_ERROR,                                    &cb_transport_error);  osip_set_transport_error_callback(osip ,OSIP_IST_TRANSPORT_ERROR,                                    &cb_transport_error);  osip_set_transport_error_callback(osip ,OSIP_NICT_TRANSPORT_ERROR,                                    &cb_transport_error);  osip_set_transport_error_callback(osip ,OSIP_NIST_TRANSPORT_ERROR,                                    &cb_transport_error); *   * // those callbacks are optional. They are used to announce the initial * // request sent for a newly created transaction.  osip_set_message_callback(osip ,OSIP_ICT_INVITE_SENT,     &cb_sndinvite);  osip_set_message_callback(osip ,OSIP_ICT_ACK_SENT,        &cb_sndack);  osip_set_message_callback(osip ,OSIP_NICT_REGISTER_SENT,  &cb_sndregister);  osip_set_message_callback(osip ,OSIP_NICT_BYE_SENT,       &cb_sndbye);  osip_set_message_callback(osip ,OSIP_NICT_CANCEL_SENT,    &cb_sndcancel);  osip_set_message_callback(osip ,OSIP_NICT_INFO_SENT,      &cb_sndinfo);  osip_set_message_callback(osip ,OSIP_NICT_OPTIONS_SENT,   &cb_sndoptions);  osip_set_message_callback(osip ,OSIP_NICT_SUBSCRIBE_SENT, &cb_sndsubscribe);  osip_set_message_callback(osip ,OSIP_NICT_NOTIFY_SENT,    &cb_sndnotify);  osip_set_message_callback(osip ,OSIP_NICT_UNKNOWN_REQUEST_SENT, &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_set_message_callback(osip ,OSIP_ICT_STATUS_1XX_RECEIVED, &cb_rcv1xx);  osip_set_message_callback(osip ,OSIP_ICT_STATUS_2XX_RECEIVED, &cb_rcv2xx);  osip_set_message_callback(osip ,OSIP_ICT_STATUS_3XX_RECEIVED, &cb_rcv3xx);  osip_set_message_callback(osip ,OSIP_ICT_STATUS_4XX_RECEIVED, &cb_rcv4xx);  osip_set_message_callback(osip ,OSIP_ICT_STATUS_5XX_RECEIVED, &cb_rcv5xx);  osip_set_message_callback(osip ,OSIP_ICT_STATUS_6XX_RECEIVED, &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_set_message_callback(osip ,OSIP_IST_STATUS_1XX_SENT, &cb_snd1xx);  osip_set_message_callback(osip ,OSIP_IST_STATUS_2XX_SENT, &cb_snd2xx);  osip_set_message_callback(osip ,OSIP_IST_STATUS_3XX_SENT, &cb_snd3xx);  osip_set_message_callback(osip ,OSIP_IST_STATUS_4XX_SENT, &cb_snd4xx);  osip_set_message_callback(osip ,OSIP_IST_STATUS_5XX_SENT, &cb_snd5xx);  osip_set_message_callback(osip ,OSIP_IST_STATUS_6XX_SENT, &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_set_message_callback(osip ,OSIP_NICT_STATUS_1XX_RECEIVED, &cb_rcv1xx);  osip_set_message_callback(osip ,OSIP_NICT_STATUS_2XX_RECEIVED, &cb_rcv2xx);  osip_set_message_callback(osip ,OSIP_NICT_STATUS_3XX_RECEIVED, &cb_rcv3xx);  osip_set_message_callback(osip ,OSIP_NICT_STATUS_4XX_RECEIVED, &cb_rcv4xx);  osip_set_message_callback(osip ,OSIP_NICT_STATUS_5XX_RECEIVED, &cb_rcv5xx);  osip_set_message_callback(osip ,OSIP_NICT_STATUS_6XX_RECEIVED, &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_set_message_callback(osip ,OSIP_NIST_STATUS_1XX_SENT, &cb_snd1xx);  osip_set_message_callback(osip ,OSIP_NIST_STATUS_2XX_SENT, &cb_snd2xx);  osip_set_message_callback(osip ,OSIP_NIST_STATUS_3XX_SENT, &cb_snd3xx);  osip_set_message_callback(osip ,OSIP_NIST_STATUS_4XX_SENT, &cb_snd4xx);  osip_set_message_callback(osip ,OSIP_NIST_STATUS_5XX_SENT, &cb_snd5xx);  osip_set_message_callback(osip ,OSIP_NIST_STATUS_6XX_SENT, &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_set_message_callback(osip ,OSIP_IST_INVITE_RECEIVED,     &cb_rcvinvite);  osip_set_message_callback(osip ,OSIP_IST_ACK_RECEIVED,        &cb_rcvack);  osip_set_message_callback(osip ,OSIP_IST_ACK_RECEIVED_AGAIN,  &cb_rcvack2);  osip_set_message_callback(osip ,OSIP_NIST_REGISTER_RECEIVED,  &cb_rcvregister);  osip_set_message_callback(osip ,OSIP_NIST_BYE_RECEIVED,       &cb_rcvbye);  osip_set_message_callback(osip ,OSIP_NIST_CANCEL_RECEIVED,    &cb_rcvcancel);  osip_set_message_callback(osip ,OSIP_NIST_INFO_RECEIVED,      &cb_rcvinfo);  osip_set_message_callback(osip ,OSIP_NIST_OPTIONS_RECEIVED,   &cb_rcvoptions);  osip_set_message_callback(osip ,OSIP_NIST_SUBSCRIBE_RECEIVED, &cb_rcvsubscribe);  osip_set_message_callback(osip ,OSIP_NIST_NOTIFY_RECEIVED,    &cb_rcvnotify);  osip_set_message_callback(osip ,OSIP_NIST_UNKNOWN_REQUEST_RECEIVED, &cb_sndunkrequest); * * </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; * osip_transaction_t *transaction; * osip_message_t     *sip_register_message; * osip_event_t       *sipevent; * * application_build_register(&sip_register_message); * osip_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. * * osip_transaction_set_your_instance(transaction, any_pointer); * * // 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; * osip_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 osip_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 = (osip_event_t *)osip_fifo_get(transaction->transactionff); *       if (se==NULL) * 	  osip_thread_exit(); *       if (osip_transaction_execute(transaction,se)<1)  // deletion asked * 	  osip_thread_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. * Those states are extracted from the diagram found in rfc3261.txt * */  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,    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  {    /* TIMEOUT EVENTS for ICT */    TIMEOUT_A,	 /**< Timer A */    TIMEOUT_B,	 /**< Timer B */    TIMEOUT_D,	 /**< Timer D */    /* TIMEOUT EVENTS for NICT */    TIMEOUT_E,	 /**< Timer E */    TIMEOUT_F,	 /**< Timer F */    TIMEOUT_K,	 /**< Timer K */    /* TIMEOUT EVENTS for IST */    TIMEOUT_G,	 /**< Timer G */    TIMEOUT_H,	 /**< Timer H */    TIMEOUT_I,	 /**< Timer I */    /* TIMEOUT EVENTS for NIST */    TIMEOUT_J,	 /**< Timer J */    /* FOR INCOMING MESSAGE */    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 */    UNKNOWN_EVT  }  type_t;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -