/* $Id$ */ /* * Copyright (C) 2003-2006 Benny Prijono * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef __PJSIP_DIALOG_H__ #define __PJSIP_DIALOG_H__ /** * @file dialog.h * @brief SIP Dialog abstraction */ #include #include #include PJ_BEGIN_DECL /** * @defgroup PJSUA_DIALOG SIP Dialog * @ingroup PJSUA * @{ * \brief * This file contains SIP dialog, a higher level abstraction of SIP session. * * \par Overview * A SIP dialog is an abstraction of communication session between two user * agents that persist for some time. The dialog facilitates sequencing of * messages between the user agents and proper routing of requests between both * of them. The dialog represents a context in which to interpret SIP messages. * However method independent User Agent processing for requests and responses * outside of a dialog exists, hence a dialog is not necessary for message * processing. * * A dialog is identified at each User Agent with a dialog Id, which consists * of a Call-Id value, a local tag and a remote tag. * * A dialog contains certain pieces of data needed for further message * transmissions within the dialog. This data consists of: * - Dialog Id - used to identify the dialog. * - Local sequence number - used to order requests from the UA to its peer. * - Remote sequence number - used to order requests from its peer to the UA. * - Local URI - the address of the local party. * - Remote URI - the address of the remote party. * - Remote target - the address from the Contact header field of the request * or response or refresh request or response. * - "secure" boolean - determines if the dialog is secure. * - Route set - an ordered list of URIs. The route set is the list of servers * that need to be traversed to send a request to the peer. * - Authentication info - array of authentication credentials to be used * by the dialog to authenticate to proxies and servers. * * \par Manipulating Dialog * Application should use functions declared in this file to do something with * the dialog. Among other things, application can: * - create outgoing dialog (#pjsip_dlg_init()). * - sends outgoing invitation (#pjsip_dlg_invite()). * - sends response (provisional and final) to incoming invitation * (#pjsip_dlg_answer()) * - disconnect dialog (#pjsip_dlg_disconnect()). * - send other request (#pjsip_dlg_create_request() and #pjsip_dlg_send_msg()) * * \par Getting Dialog's Notification * Dialog emits notification about various things that's happening to it (e.g. * a message is received, dialog state has changed, etc.). Normally it is in * the interest of the application to capture these notifications, by * supplying the function to be called when the event occurs in #pjsip_dlg_callback * structure, and register this structure to user agent by calling * #pjsip_ua_set_dialog_callback(). * * \par Incoming Invitation * Upon receiving a new incoming invitation, user agent will automatically create * a new dialog, and inform application via \b pjsip_dlg_callback. */ /** Forward declaration for user agent structure. */ typedef struct pjsip_user_agent pjsip_user_agent; /** Forward declaration for dialog structure. */ typedef struct pjsip_dlg pjsip_dlg; /** * \brief Type of events that are reported by the dialog to the application callback * function. */ typedef enum pjsip_dlg_event_e { /** Dialog state has changed. */ PJSIP_DIALOG_EVENT_STATE_CHANGED, /** Any mid-call messages (reinvitation, message, etc.). */ PJSIP_DIALOG_EVENT_MID_CALL_REQUEST, /** Other events (low level events). */ PJSIP_DIALOG_EVENT_OTHER, } pjsip_dlg_event_e; /** * \brief Structure registered by applications to receive dialog notifications * from the User Agent. * * Applications registers this structure to get notifications from the User Agent * about dialog state changes and other events. Application can set any of * the callback function to NULL if it doesn't want to handle the notification, * however, setting some callbacks to NULL probably will cause some undesired * result (such as setting \b on_incoming to NULL will cause the creation of * a lot of dialogs with no owner). */ struct pjsip_dlg_callback { /** * This is a low level, uninterpreted callback that is called by framework * for all kinds of events, such as transaction events, dialog events, etc. * @param dlg The dialog. * @param dlg_event The type of dialog event. * @param event The event descriptor. */ void (*on_all_events)(pjsip_dlg *dlg, pjsip_dlg_event_e dlg_event, pjsip_event *event ); /** * This is a low level callback that is called by the framework when the * underlying transaction is about to send outgoing message. This callback * is provided to allow application to modify the message before it is * transmitted. * @param dlg The dialog. * @param tsx The transaction that transmits the message. * @param tdata The transmission data, which contains the message. * @param retransmission The number of times this message has been sent. * Zero indicates the message is about to be sent the first time, * one indicates this is the first retransmission, etc. */ void (*on_before_tx)(pjsip_dlg *dlg, pjsip_transaction *tsx, pjsip_tx_data *tdata, pj_bool_t retransmission); /** * This is a low level callback that is called by the framework when the dialog * has sent a message. Note that a receive of retransmission will not trigger * this callback since retransmission is handled internally by transaction. * @param dlg The dialog. * @param tsx The transaction that transmits the message. * @param tdata The transmission data, which contains the message. */ void (*on_tx_msg)(pjsip_dlg *dlg, pjsip_transaction *tsx, pjsip_tx_data *tdata); /** * This is a low level callback that is called by the framework when the * dialog has received a message. Note that a receipt of retransmission * will not trigger this callback since retransmission is handled internally * by transaction. * @param dlg The dialog. * @param tsx The transaction that receives the message. * @param rdata The receive data, which contains the message. */ void (*on_rx_msg)(pjsip_dlg *dlg, pjsip_transaction *tsx, pjsip_rx_data *rdata); /** * This callback is called by the framework when the user agent * instance receives an incoming INVITE message. * @param dlg The new dialog that's just created to handle the incoming call. * @param tsx The INVITE transaction that's just created. * @param rdata The receive data, which contains the INVITE message. */ void (*on_incoming)(pjsip_dlg *dlg, pjsip_transaction *tsx, pjsip_rx_data *rdata); /** * This callback is called by the framework when the dialog is sending * the first outgoing INVITE message. * @param dlg The dialog. * @param tsx The INVITE transaction. * @param tdata The transmit data, which contains the INVITE message. */ void (*on_calling)(pjsip_dlg *dlg, pjsip_transaction *tsx, pjsip_tx_data *tdata); /** * This callback is called by the framework when the initial INVITE * transaction has sent/received provisional response. * @param dlg The dialog. * @param tsx The transaction. * @param event The event, which src_type will always be either * PJSIP_EVENT_RX_MSG or PJSIP_EVENT_TX_MSG. The provisional * response message itself will be in either \b rdata or \b tdata. * @see pjsip_event. */ void (*on_provisional)(pjsip_dlg *dlg, pjsip_transaction *tsx, pjsip_event *event); /** * This callback is called for both UAS and UAC dialog when 200 response * to INVITE is sent or received. * @param dlg The dialog. * @param event The event, which src_type can only be either * PJSIP_EVENT_TX_MSG or PJSIP_EVENT_RX_MSG. * @see pjsip_event */ void (*on_connecting)(pjsip_dlg *dlg, pjsip_event *event); /** * This callback is called for both UAS and UAC when an ACK request is * sent or received by the dialog. * @param dlg The dialog. * @param event The event, which src_type can only be either * PJSIP_EVENT_TX_MSG or PJSIP_EVENT_RX_MSG. * @see pjsip_event */ void (*on_established)(pjsip_dlg *dlg, pjsip_event *event); /** * This callback is called when the dialog is disconnected, i.e. upon * sending/receiving non-200 response to INVITE, sending/receiving * CANCEL to initial INVITE, and sending/receiving BYE. * * @param dlg The dialog. * @param event The event. * @see pjsip_event */ void (*on_disconnected)(pjsip_dlg *dlg, pjsip_event *event); /** * This callback is called when the dialog is about to be destroyed. * @param dlg The dialog. */ void (*on_terminated)(pjsip_dlg *dlg); /** * This callback will be called when the dialog receives mid call events * such as re-invitation or incoming pager. * * @param dlg The dialog. * @param event The event. */ void (*on_mid_call_events)(pjsip_dlg *dlg, pjsip_event *event); }; /* struct pjsip_dlg_callback */ /** * Dialog state. */ typedef enum pjsip_dlg_state_e { /** * State NULL is after the dialog is instantiated but before any * initialization is done. */ PJSIP_DIALOG_STATE_NULL, /** * State INCOMING is after the (callee) dialog has been initialized with * the incoming request, but before any responses is sent by the dialog. */ PJSIP_DIALOG_STATE_INCOMING, /** * State CALLING is after the (caller) dialog has sent outgoing invitation * but before any responses are received. */ PJSIP_DIALOG_STATE_CALLING, /** * State PROCEEDING is after the dialog sent/received provisional * responses, but before final response is sent/received. */ PJSIP_DIALOG_STATE_PROCEEDING, /** * State CONNECTING is after the dialog has sent/received final response * to the invitation, but before acknowledgement is sent. */ PJSIP_DIALOG_STATE_CONNECTING, /** * State ESTABLISHED occurs after the invitation has been accepted and * acknowledged. */ PJSIP_DIALOG_STATE_ESTABLISHED, /** * State DISCONNECTED occurs after either party successfully disconnect * the session. */ PJSIP_DIALOG_STATE_DISCONNECTED, /** * State TERMINATE occurs when the dialog is ready to be destroyed. */ PJSIP_DIALOG_STATE_TERMINATED, } pjsip_dlg_state_e; /** * Get the dialog string state. * * @param state Dialog state. * @return The string describing the state. */ const char *pjsip_dlg_state_str(pjsip_dlg_state_e state); /** * This structure is used to describe dialog's participants, which in this * case is local party (i.e. us) and remote party. */ typedef struct pjsip_dlg_party { pjsip_uri *target; /**< Target URL. */ pjsip_fromto_hdr *info; /**< URL in From/To header. */ pj_str_t tag; /**< Tag. */ pjsip_contact_hdr *contact; /**< URL in Contact. */ pj_sockaddr_in addr; /**< The current transport address. */ int cseq; /**< Sequence number counter. */ } pjsip_dlg_party; /** * This structure describes the dialog structure. */ struct pjsip_dlg { PJ_DECL_LIST_MEMBER(struct pjsip_dlg) char obj_name[PJ_MAX_OBJ_NAME]; /**< Log identification. */ pjsip_user_agent *ua; /**< User agent instance. */ pj_pool_t *pool; /**< Dialog's pool. */ pjsip_dlg_state_e state; /**< Dialog's call state. */ pjsip_role_e role; /**< Dialog's role. */ pj_mutex_t *mutex; /**< Dialog's mutex. */ pjsip_dlg_party local; /**< Local party info. */ pjsip_dlg_party remote; /**< Remote party info. */ pjsip_cid_hdr *call_id; /**< Call-ID */ pj_bool_t secure; /**< Use secure transport? */ pjsip_route_hdr route_set; /**< Dialog's route set. */ pjsip_transaction *invite_tsx; /**< Current INVITE transaction. */ int pending_tsx_count; /**< Total pending tsx count. */ int cred_count; /**< Number of credentials. */ pjsip_cred_info *cred_info; /**< Array of credentials. */ pjsip_auth_session auth_sess; /**< List of auth session. */ pjsip_msg_body *body; void *user_data; /**< Application's data. */ int (*handle_tsx_event)(struct pjsip_dlg *, /**< Internal state handler.*/ pjsip_transaction *, pjsip_event *); }; /** * Initialize dialog with local and remote info. This function is normally * called after application creates the dialog with #pjsip_ua_create_dialog * for UAC dialogs. * * This function will initialize local and remote info from the URL, generate * a globally unique Call-ID, initialize CSeq, and initialize other dialog's * internal attributes. * * @param dlg The dialog to initialize. * @param local_info URI/name address to be used as local info * (From and Contact headers). * @param remote_info URI/name address to be used as remote info (To header). * @param target URI for initial remote's target, or NULL to set the * initial target the same as remote_info. * * @return zero on success. */ PJ_DECL(pj_status_t) pjsip_dlg_init( pjsip_dlg *dlg, const pj_str_t *local_info, const pj_str_t *remote_info, const pj_str_t *target); /** * Set authentication credentials to be used by this dialog. * * If authentication credentials are set for the dialog, the dialog will try to * perform authentication automatically using the credentials supplied, and * also cache the last Authorization or Proxy-Authorization headers for next * requests. * * If none of the credentials are suitable or accepted by remote, then * the dialog will just pass the authorization failure response back to * application. * * @param dlg The dialog. * @param count Number of credentials in the array. * @param cred Array of credentials. * * @return Zero on success. */ PJ_DECL(pj_status_t) pjsip_dlg_set_credentials( pjsip_dlg *dlg, int count, const pjsip_cred_info cred[]); /** * Override local contact details. * * Call this function to change the contact details to be advertised in Contact * header. Application normally need to call this function for incoming calls * before answering the call with 200/OK, because for an incoming dialogs, the * initial local contact info are generated from the To header, which is * normally not the appropriate one. * * @param dlg The dialog. * @param contact The contact to use. * * @return Zero on success. */ PJ_DECL(pj_status_t) pjsip_dlg_set_contact( pjsip_dlg *dlg, const pj_str_t *contact ); /** * Set initial route set to be used by the dialog. This initial route set * governs where and how the initial INVITE request will be routed. This * initial route set will be overwritten with the route set found in the * 2xx response of INVITE. * * Application only needs to call this function if it wants to have custom * route for individual dialogs. If only a single route for all dialogs is * needed, then application can set the global route by calling function * #pjsip_endpt_set_proxies(). * * @param dlg The dialog. * @param route_set The route set list. * * @return Zero on success. */ PJ_DECL(pj_status_t) pjsip_dlg_set_route_set( pjsip_dlg *dlg, const pjsip_route_hdr *route_set ); /** * Variation of #pjsip_dlg_set_route_set where the headers will be used * as it is (i.e. without cloned). * * @param dlg The dialog. * @param route_set The route set list. * * @return Zero on success. */ PJ_DECL(pj_status_t) pjsip_dlg_set_route_set_np( pjsip_dlg *dlg, pjsip_route_hdr *route_set); /** * Create initial outgoing INVITE message. * * This function is just a simple wrapper to #pjsip_dlg_create_request(), * so it follows the same rule there. In addition, this function also adds * \b Allow header to the outgoing request. * * After the message is successfully created, application must call * #pjsip_dlg_send_msg() to actually send the message and update the dialog's * state. Note that upon return the reference counter of the transmit data * will be set to one. * * @param dlg The dialog. * * @return The dialog transmit data, or NULL. */ PJ_DECL(pjsip_tx_data*) pjsip_dlg_invite( pjsip_dlg *dlg ); /** * Answer incoming dialog invitation, with either provisional responses * or a final response. Application can only call this function when there's * a pending invitation to be answered. * * After the message is successfully created, application must call * #pjsip_dlg_send_msg() to actually send the message and update the dialog's * state. Note that upon return the reference counter of the transmit data * will be set to one. * * @param dlg The dialog. * @param code The response code, which can be: * - 100-199 Provisional response (application can issue multiple * provisional responses). * - 200-299 To answer the invitation (normally status code 200 * is sent). * - 300-699 To reject the invitation. * @return Transmit data if successfull. */ PJ_DECL(pjsip_tx_data*) pjsip_dlg_answer( pjsip_dlg *dlg, int code ); /** * High level function to create message to disconnect dialog. Depending * on dialog's state, this function will either create CANCEL, final response, * or BYE message. A status code must be supplied, which will be set if dialog * will be transmitting a final response to INVITE. * * After the message is successfully created, application must call * #pjsip_dlg_send_msg to actually send the message and update the dialog's * state. Note that upon return the reference counter of the transmit data * will be set to one. * * @param dlg The dialog. * @param status_code The status code for disconnection. * @return Transmit data if successfull. */ PJ_DECL(pjsip_tx_data*) pjsip_dlg_disconnect( pjsip_dlg *dlg, int status_code); /** * Create CANCEL message to cancel pending outgoing dialog invitation. * Normally application should call #pjsip_dlg_disconnect() instead, because * that function will create the correct message regardless of the state of * the dialog. * * Application can call this function at anytime after it issues outgoing * invitation and before receiving final response. However, there's no * guarantee that the invitation will be successfully cancelled, since the * CANCEL request and the final response can pass over in the wire. So the * application must prepare to have the dialog connected even after the * dialog is cancelled. * * The final state of the dialog will be reported in the dialog callback. * If the CANCEL request succeeded, then the dialog will be disconnected with * status code \a PJSIP_SC_REQUEST_TERMINATED. * * After the message is successfully created, application must call * #pjsip_dlg_send_msg() to actually send the message and update the dialog's * state. * * Upon return of this function, the reference counter of the transmit data * will be set to one. * * @param dlg The dialog. * @return The dialog transmit data containing the CANCEL message, * or NULL. */ PJ_DECL(pjsip_tx_data*) pjsip_dlg_cancel( pjsip_dlg *dlg ); /** * Create BYE message. Application shouldn't normally need to use this function, * but rather it's preferable to use #pjsip_dlg_disconnect() instead because * that function will work to disconnect the session no matter what the state * is. * * After the message is successfully created, application must call * #pjsip_dlg_send_msg() to actually send the message and update the dialog's * state. Note that upon return the reference counter of the transmit data * will be set to one. * * @param dlg The dialog. * @return The BYE message or NULL. */ PJ_DECL(pjsip_tx_data*) pjsip_dlg_bye( pjsip_dlg *dlg ); /** * This function is called by application to create new outgoing request * message for this dialog. After the request is created, application can * modify the message (such adding headers), and eventually send the request * by calling #pjsip_dlg_send_msg(). * * This function will initialize the request message with dialog's properties * as follows: * - the request line is initialized with the method and the target is * initialized from current remote target. * - \b From, \b To, \b Contact, and \b Call-Id headers will be added. * - An initial \b CSeq header will be provided (although the value will be * verified again when the message is actually sent with #pjsip_dlg_send_msg(). * - \b Route headers will be added from dialog's route set. * - Authentication headers (\b Authorization or \b Proxy-Authorization) will * be added from dialog's authorization cache. * * Note that upon return the reference counter of the transmit data * will be set to one. When the message is sent, #pjsip_dlg_send_msg() will * decrement the reference counter, and when the reference counter reach zero, * the message will be deleted. * * @param dlg The dialog. * @param method The request method. * @param cseq Specify CSeq, or -1 to let the dialog specify CSeq. * * @return Transmit data for the new request. * * @see pjsip_dlg_send_msg() */ PJ_DECL(pjsip_tx_data*) pjsip_dlg_create_request( pjsip_dlg *dlg, const pjsip_method *method, int cseq); /** * This function can be called by application to send outgoing message (request * or response) to remote party. Note that after calling this function, the * transmit data will be deleted regardless of the return status. To prevent * deletion, application must increase the reference count, but then it will * be responsible to delete this transmit data itself (by decreasing the * reference count). * * @param dlg The dialog. * @param tdata The transmit data, which contains the request message. * @return zero on success. */ PJ_DECL(pj_status_t) pjsip_dlg_send_msg( pjsip_dlg *dlg, pjsip_tx_data *tdata ); /** * @} */ PJ_END_DECL #endif /* __PJSIP_DIALOG_H__ */