?? osip.h
字號:
/* 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 + -