558 lines
22 KiB
C
558 lines
22 KiB
C
/*
|
|
* Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
|
|
* Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
|
|
*
|
|
* 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_SIP_TRANSACTION_H__
|
|
#define __PJSIP_SIP_TRANSACTION_H__
|
|
|
|
/**
|
|
* @file sip_transaction.h
|
|
* @brief SIP Transaction
|
|
*/
|
|
|
|
#include <pjsip/sip_msg.h>
|
|
#include <pjsip/sip_util.h>
|
|
#include <pjsip/sip_transport.h>
|
|
#include <pj/timer.h>
|
|
|
|
PJ_BEGIN_DECL
|
|
|
|
/**
|
|
* @defgroup PJSIP_TRANSACT Transaction Layer
|
|
* @brief Provides statefull message processing.
|
|
*
|
|
* This module provides stateful processing to incoming or outgoing SIP
|
|
* messages.
|
|
* Before performing any stateful operations, application must register the
|
|
* transaction layer module by calling #pjsip_tsx_layer_init_module().
|
|
*
|
|
* Application should link with <b>pjsip-core</b> library to
|
|
* use the transaction layer.
|
|
*/
|
|
|
|
/**
|
|
* @defgroup PJSIP_TRANSACT_TRANSACTION Transaction
|
|
* @ingroup PJSIP_TRANSACT
|
|
* @brief Transaction instance for all types of SIP transactions.
|
|
* @{
|
|
* The pjsip_transaction describes SIP transaction, and is used for
|
|
* both INVITE and non-INVITE, UAC or UAS. Application must register the
|
|
* transaction layer module with #pjsip_tsx_layer_init_module() before
|
|
* performing any stateful operations.
|
|
*/
|
|
|
|
/**
|
|
* This enumeration represents transaction state.
|
|
*/
|
|
typedef enum pjsip_tsx_state_e
|
|
{
|
|
PJSIP_TSX_STATE_NULL, /**< For UAC, before any message is sent. */
|
|
PJSIP_TSX_STATE_CALLING, /**< For UAC, just after request is sent. */
|
|
PJSIP_TSX_STATE_TRYING, /**< For UAS, just after request is received.*/
|
|
PJSIP_TSX_STATE_PROCEEDING, /**< For UAS/UAC, after provisional response.*/
|
|
PJSIP_TSX_STATE_COMPLETED, /**< For UAS/UAC, after final response. */
|
|
PJSIP_TSX_STATE_CONFIRMED, /**< For UAS, after ACK is received. */
|
|
PJSIP_TSX_STATE_TERMINATED, /**< For UAS/UAC, before it's destroyed. */
|
|
PJSIP_TSX_STATE_DESTROYED, /**< For UAS/UAC, will be destroyed now. */
|
|
PJSIP_TSX_STATE_MAX /**< Number of states. */
|
|
} pjsip_tsx_state_e;
|
|
|
|
|
|
/**
|
|
* This structure describes SIP transaction object. The transaction object
|
|
* is used to handle both UAS and UAC transaction.
|
|
*/
|
|
struct pjsip_transaction
|
|
{
|
|
/*
|
|
* Administrivia
|
|
*/
|
|
pj_pool_t *pool; /**< Pool owned by the tsx. */
|
|
pjsip_module *tsx_user; /**< Transaction user. */
|
|
pjsip_endpoint *endpt; /**< Endpoint instance. */
|
|
pj_bool_t terminating; /**< terminate() was called */
|
|
pj_grp_lock_t *grp_lock; /**< Transaction grp lock. */
|
|
pj_mutex_t *mutex_b; /**< Second mutex to avoid
|
|
deadlock. It is used to
|
|
protect timer. */
|
|
|
|
/*
|
|
* Transaction identification.
|
|
*/
|
|
char obj_name[PJ_MAX_OBJ_NAME]; /**< Log info. */
|
|
pjsip_role_e role; /**< Role (UAS or UAC) */
|
|
pjsip_method method; /**< The method. */
|
|
pj_int32_t cseq; /**< The CSeq */
|
|
pj_str_t transaction_key;/**< Hash table key. */
|
|
pj_str_t transaction_key2;/**< Hash table key (2)
|
|
for merged requests
|
|
tsx lookup. */
|
|
pj_uint32_t hashed_key; /**< Key's hashed value. */
|
|
pj_uint32_t hashed_key2; /**< Key's hashed value (2).*/
|
|
pj_str_t branch; /**< The branch Id. */
|
|
|
|
/*
|
|
* State and status.
|
|
*/
|
|
int status_code; /**< Last status code seen. */
|
|
pj_str_t status_text; /**< Last reason phrase. */
|
|
pjsip_tsx_state_e state; /**< State. */
|
|
int handle_200resp; /**< UAS 200/INVITE retrsm.*/
|
|
int tracing; /**< Tracing enabled? */
|
|
|
|
/** Handler according to current state. */
|
|
pj_status_t (*state_handler)(struct pjsip_transaction *, pjsip_event *);
|
|
|
|
/*
|
|
* Transport.
|
|
*/
|
|
pjsip_transport *transport; /**< Transport to use. */
|
|
pj_bool_t is_reliable; /**< Transport is reliable. */
|
|
pj_sockaddr addr; /**< Destination address. */
|
|
int addr_len; /**< Address length. */
|
|
pjsip_response_addr res_addr; /**< Response address. */
|
|
unsigned transport_flag; /**< Miscelaneous flag. */
|
|
pj_status_t transport_err; /**< Internal error code. */
|
|
pjsip_tpselector tp_sel; /**< Transport selector. */
|
|
pjsip_tx_data *pending_tx; /**< Tdata which caused
|
|
pending transport flag
|
|
to be set on tsx. */
|
|
pjsip_tp_state_listener_key *tp_st_key; /**< Transport state listener
|
|
key. */
|
|
|
|
/*
|
|
* Messages and timer.
|
|
*/
|
|
pjsip_tx_data *last_tx; /**< Msg kept for retrans. */
|
|
int retransmit_count;/**< Retransmission count. */
|
|
pj_timer_entry retransmit_timer;/**< Retransmit timer. */
|
|
pj_timer_entry timeout_timer; /**< Timeout timer. */
|
|
|
|
/** Module specific data. */
|
|
void *mod_data[PJSIP_MAX_MODULE];
|
|
};
|
|
|
|
|
|
/**
|
|
* Create and register transaction layer module to the specified endpoint.
|
|
*
|
|
* @param endpt The endpoint instance.
|
|
*
|
|
* @return PJ_SUCCESS on success.
|
|
*/
|
|
PJ_DECL(pj_status_t) pjsip_tsx_layer_init_module(pjsip_endpoint *endpt);
|
|
|
|
/**
|
|
* Get the instance of the transaction layer module.
|
|
*
|
|
* @return The transaction layer module.
|
|
*/
|
|
PJ_DECL(pjsip_module*) pjsip_tsx_layer_instance(void);
|
|
|
|
/**
|
|
* Unregister and destroy transaction layer module.
|
|
*
|
|
* @return PJ_SUCCESS on success.
|
|
*/
|
|
PJ_DECL(pj_status_t) pjsip_tsx_layer_destroy(void);
|
|
|
|
/**
|
|
* Retrieve the current number of transactions currently registered
|
|
* in the hash table.
|
|
*
|
|
* @return Number of transactions.
|
|
*/
|
|
PJ_DECL(unsigned) pjsip_tsx_layer_get_tsx_count(void);
|
|
|
|
/**
|
|
* Find a transaction with the specified key. The transaction key normally
|
|
* is created by calling #pjsip_tsx_create_key() from an incoming message.
|
|
*
|
|
* IMPORTANT: To prevent deadlock, application should use
|
|
* #pjsip_tsx_layer_find_tsx2() instead which only adds a reference to
|
|
* the transaction instead of locking it.
|
|
*
|
|
* @param key The key string to find the transaction.
|
|
* @param lock If non-zero, transaction will be locked before the
|
|
* function returns, to make sure that it's not deleted
|
|
* by other threads.
|
|
*
|
|
* @return The matching transaction instance, or NULL if transaction
|
|
* can not be found.
|
|
*/
|
|
PJ_DECL(pjsip_transaction*) pjsip_tsx_layer_find_tsx( const pj_str_t *key,
|
|
pj_bool_t lock );
|
|
|
|
/**
|
|
* Find a transaction with the specified key. The transaction key normally
|
|
* is created by calling #pjsip_tsx_create_key() from an incoming message.
|
|
*
|
|
* @param key The key string to find the transaction.
|
|
* @param add_ref If non-zero, transaction's reference will be added
|
|
* by one before the function returns, to make sure that
|
|
* it's not deleted by other threads.
|
|
*
|
|
* @return The matching transaction instance, or NULL if transaction
|
|
* can not be found.
|
|
*/
|
|
PJ_DECL(pjsip_transaction*) pjsip_tsx_layer_find_tsx2( const pj_str_t *key,
|
|
pj_bool_t add_ref );
|
|
|
|
/**
|
|
* Create, initialize, and register a new transaction as UAC from the
|
|
* specified transmit data (\c tdata). The transmit data must have a valid
|
|
* \c Request-Line and \c CSeq header.
|
|
*
|
|
* If \c Via header does not exist, it will be created along with a unique
|
|
* \c branch parameter. If it exists and contains branch parameter, then
|
|
* the \c branch parameter will be used as is as the transaction key. If
|
|
* it exists but branch parameter doesn't exist, a unique branch parameter
|
|
* will be created.
|
|
*
|
|
* @param tsx_user Module to be registered as transaction user of the new
|
|
* transaction, which will receive notification from the
|
|
* transaction via on_tsx_state() callback.
|
|
* @param tdata The outgoing request message.
|
|
* @param p_tsx On return will contain the new transaction instance.
|
|
*
|
|
* @return PJ_SUCCESS if successfull.
|
|
*/
|
|
PJ_DECL(pj_status_t) pjsip_tsx_create_uac( pjsip_module *tsx_user,
|
|
pjsip_tx_data *tdata,
|
|
pjsip_transaction **p_tsx);
|
|
|
|
/**
|
|
* Variant of pjsip_tsx_create_uac() with additional parameter to specify
|
|
* the group lock to use. Group lock can be used to synchronize locking
|
|
* among several objects to prevent deadlock, and to synchronize the
|
|
* lifetime of objects sharing the same group lock.
|
|
*
|
|
* See pjsip_tsx_create_uac() for general info about this function.
|
|
*
|
|
* @param tsx_user Module to be registered as transaction user of the new
|
|
* transaction, which will receive notification from the
|
|
* transaction via on_tsx_state() callback.
|
|
* @param tdata The outgoing request message.
|
|
* @param grp_lock Optional group lock to use by this transaction. If
|
|
* the value is NULL, the transaction will create its
|
|
* own group lock.
|
|
* @param p_tsx On return will contain the new transaction instance.
|
|
*
|
|
* @return PJ_SUCCESS if successfull.
|
|
*/
|
|
PJ_DECL(pj_status_t) pjsip_tsx_create_uac2(pjsip_module *tsx_user,
|
|
pjsip_tx_data *tdata,
|
|
pj_grp_lock_t *grp_lock,
|
|
pjsip_transaction **p_tsx);
|
|
|
|
/**
|
|
* Create, initialize, and register a new transaction as UAS from the
|
|
* specified incoming request in \c rdata. After calling this function,
|
|
* application MUST call #pjsip_tsx_recv_msg() so that transaction
|
|
* moves from state NULL.
|
|
*
|
|
* @param tsx_user Module to be registered as transaction user of the new
|
|
* transaction, which will receive notification from the
|
|
* transaction via on_tsx_state() callback.
|
|
* @param rdata The received incoming request.
|
|
* @param p_tsx On return will contain the new transaction instance.
|
|
*
|
|
* @return PJ_SUCCESS if successfull.
|
|
*/
|
|
PJ_DECL(pj_status_t) pjsip_tsx_create_uas( pjsip_module *tsx_user,
|
|
pjsip_rx_data *rdata,
|
|
pjsip_transaction **p_tsx );
|
|
|
|
/**
|
|
* Variant of pjsip_tsx_create_uas() with additional parameter to specify
|
|
* the group lock to use. Group lock can be used to synchronize locking
|
|
* among several objects to prevent deadlock, and to synchronize the
|
|
* lifetime of objects sharing the same group lock.
|
|
*
|
|
* See pjsip_tsx_create_uas() for general info about this function.
|
|
*
|
|
* @param tsx_user Module to be registered as transaction user of the new
|
|
* transaction, which will receive notification from the
|
|
* transaction via on_tsx_state() callback.
|
|
* @param rdata The received incoming request.
|
|
* @param grp_lock Optional group lock to use by this transaction. If
|
|
* the value is NULL, the transaction will create its
|
|
* own group lock.
|
|
* @param p_tsx On return will contain the new transaction instance.
|
|
*
|
|
* @return PJ_SUCCESS if successfull.
|
|
*/
|
|
PJ_DECL(pj_status_t) pjsip_tsx_create_uas2(pjsip_module *tsx_user,
|
|
pjsip_rx_data *rdata,
|
|
pj_grp_lock_t *grp_lock,
|
|
pjsip_transaction **p_tsx );
|
|
|
|
/**
|
|
* Detect merged requests according to RFC 3261 section 8.2.2.2:
|
|
* If the request has no tag in the To header field, the function will
|
|
* check the request against ongoing transactions. If the From tag,
|
|
* Call-ID, and CSeq exactly match those associated with an ongoing
|
|
* transaction, but the request does not match that transaction based
|
|
* on the matching rules described in section 17.2.3, the function
|
|
* will return that transaction.
|
|
*
|
|
* @param rdata The received incoming request.
|
|
*
|
|
* @return The matching transaction, if any, or NULL.
|
|
*/
|
|
PJ_DECL(pjsip_transaction *)
|
|
pjsip_tsx_detect_merged_requests(pjsip_rx_data *rdata);
|
|
|
|
/**
|
|
* Lock/bind transaction to a specific transport/listener. This is optional,
|
|
* as normally transport will be selected automatically based on the
|
|
* destination of the message upon resolver completion.
|
|
*
|
|
* @param tsx The transaction.
|
|
* @param sel Transport selector containing the specification of
|
|
* transport or listener to be used by this transaction
|
|
* to send requests.
|
|
*
|
|
* @return PJ_SUCCESS on success, or the appropriate error code.
|
|
*/
|
|
PJ_DECL(pj_status_t) pjsip_tsx_set_transport(pjsip_transaction *tsx,
|
|
const pjsip_tpselector *sel);
|
|
|
|
/**
|
|
* Call this function to manually feed a message to the transaction.
|
|
* For UAS transaction, application MUST call this function after
|
|
* UAS transaction has been created.
|
|
*
|
|
* This function SHOULD only be called to pass initial request message
|
|
* to UAS transaction. Before this function returns, on_tsx_state()
|
|
* callback of the transaction user will be called. If response message
|
|
* is passed to this function, then on_rx_response() will also be called
|
|
* before on_tsx_state().
|
|
*
|
|
* @param tsx The transaction.
|
|
* @param rdata The message.
|
|
*/
|
|
PJ_DECL(void) pjsip_tsx_recv_msg( pjsip_transaction *tsx,
|
|
pjsip_rx_data *rdata);
|
|
|
|
/**
|
|
* Transmit message in tdata with this transaction. It is possible to
|
|
* pass NULL in tdata for UAC transaction, which in this case the last
|
|
* message transmitted, or the request message which was specified when
|
|
* calling #pjsip_tsx_create_uac(), will be sent.
|
|
*
|
|
* This function decrements the reference counter of the transmit buffer
|
|
* only when it returns PJ_SUCCESS;
|
|
*
|
|
* @param tsx The transaction.
|
|
* @param tdata The outgoing message. If NULL is specified, then the
|
|
* last message transmitted (or the message specified
|
|
* in UAC initialization) will be sent.
|
|
*
|
|
* @return PJ_SUCCESS if successfull.
|
|
*/
|
|
PJ_DECL(pj_status_t) pjsip_tsx_send_msg( pjsip_transaction *tsx,
|
|
pjsip_tx_data *tdata);
|
|
|
|
|
|
/**
|
|
* Manually retransmit the last message transmitted by this transaction,
|
|
* without updating the transaction state. This function is useful when
|
|
* TU wants to maintain the retransmision by itself (for example,
|
|
* retransmitting reliable provisional response).
|
|
*
|
|
* @param tsx The transaction.
|
|
* @param tdata The outgoing message. If NULL is specified, then the
|
|
* last message transmitted (or the message specified
|
|
* in UAC initialization) will be sent.
|
|
*
|
|
*
|
|
* @return PJ_SUCCESS if successful.
|
|
*/
|
|
PJ_DECL(pj_status_t) pjsip_tsx_retransmit_no_state(pjsip_transaction *tsx,
|
|
pjsip_tx_data *tdata);
|
|
|
|
|
|
/**
|
|
* Create transaction key, which is used to match incoming requests
|
|
* or response (retransmissions) against transactions.
|
|
*
|
|
* @param pool The pool
|
|
* @param key Output key.
|
|
* @param role The role of the transaction.
|
|
* @param method The method to be put as a key.
|
|
* @param rdata The received data to calculate.
|
|
*
|
|
* @return PJ_SUCCESS or the appropriate error code.
|
|
*/
|
|
PJ_DECL(pj_status_t) pjsip_tsx_create_key( pj_pool_t *pool,
|
|
pj_str_t *key,
|
|
pjsip_role_e role,
|
|
const pjsip_method *method,
|
|
const pjsip_rx_data *rdata );
|
|
|
|
/**
|
|
* Force terminate transaction.
|
|
*
|
|
* @param tsx The transaction.
|
|
* @param code The status code to report.
|
|
*
|
|
* @return PJ_SUCCESS or the appropriate error code.
|
|
*/
|
|
PJ_DECL(pj_status_t) pjsip_tsx_terminate( pjsip_transaction *tsx,
|
|
int code );
|
|
|
|
|
|
/**
|
|
* Force terminate transaction asynchronously, using the transaction
|
|
* internal timer.
|
|
*
|
|
* @param tsx The transaction.
|
|
* @param code The status code to report.
|
|
*
|
|
* @return PJ_SUCCESS or the appropriate error code.
|
|
*/
|
|
PJ_DECL(pj_status_t) pjsip_tsx_terminate_async(pjsip_transaction *tsx,
|
|
int code );
|
|
|
|
|
|
/**
|
|
* Cease retransmission on the UAC transaction. The UAC transaction is
|
|
* still considered running, and it will complete when either final
|
|
* response is received or the transaction times out.
|
|
*
|
|
* This operation normally is used for INVITE transaction only, when
|
|
* the transaction is cancelled before any provisional response has been
|
|
* received.
|
|
*
|
|
* @param tsx The transaction.
|
|
*
|
|
* @return PJ_SUCCESS or the appropriate error code.
|
|
*/
|
|
PJ_DECL(pj_status_t) pjsip_tsx_stop_retransmit(pjsip_transaction *tsx);
|
|
|
|
|
|
/**
|
|
* Start a timer to terminate transaction after the specified time
|
|
* has elapsed. This function is only valid for INVITE transaction,
|
|
* and only before final response is received for the INVITE transaction.
|
|
* It is normally called after the UAC has sent CANCEL for this
|
|
* INVITE transaction.
|
|
*
|
|
* The purpose of this function is to terminate the transaction if UAS
|
|
* does not send final response to this INVITE transaction even after
|
|
* it sends 200/OK to CANCEL (for example when the UAS complies to RFC
|
|
* 2543).
|
|
*
|
|
* Once this timer is set, the transaction will be terminated either when
|
|
* a final response is received or the timer expires.
|
|
*
|
|
* @param tsx The transaction.
|
|
* @param millisec Timeout value in milliseconds.
|
|
*
|
|
* @return PJ_SUCCESS or the appropriate error code.
|
|
*/
|
|
PJ_DECL(pj_status_t) pjsip_tsx_set_timeout(pjsip_transaction *tsx,
|
|
unsigned millisec);
|
|
|
|
|
|
/**
|
|
* Change timer values used by transaction layer. Currently scheduled
|
|
* timers will not be changed. Any value set to 0 will be left
|
|
* unchanged.
|
|
*
|
|
* @param t1 Transaction T1 timeout, in msec
|
|
* @param t2 Transaction T2 timeout, in msec
|
|
* @param t4 Transaction completed timer for non-INVITE, in msec
|
|
* @param td Transaction completed timer for INVITE, in msec
|
|
*/
|
|
PJ_DECL(void) pjsip_tsx_set_timers(unsigned t1, unsigned t2, unsigned t4,
|
|
unsigned td);
|
|
|
|
|
|
/**
|
|
* (Re)Initializes timer values from pjsip_cfg().
|
|
*/
|
|
PJ_DECL(void) pjsip_tsx_initialize_timer_values(void);
|
|
|
|
|
|
/**
|
|
* Set maximum retransmission count in transaction layer for outgoing
|
|
* requests. When retransmission counter reaches the specified number,
|
|
* the transaction will be considered timeout. This will affect any
|
|
* ongoing transactions immediately.
|
|
*
|
|
* By default (or when this is set to -1), retransmission number will
|
|
* not cause a transaction to be timeout, only the timer settings will
|
|
* cause transaction timeout. Also, this will not override the timer
|
|
* settings, i.e: if the timeout timer occurs before the maximum
|
|
* retransmission is reached, the transaction will still gets timeout.
|
|
*
|
|
* When this is set to zero or possitive number P, a transaction timeout
|
|
* will occur right before the retransmission number (P+1). For example,
|
|
* if this is set to 1 there will be two transmissions: the initial
|
|
* transmission and one retransmission, before the transaction gets timeout.
|
|
*
|
|
* @param max Maximum retransmission count.
|
|
*/
|
|
PJ_DECL(void) pjsip_tsx_set_max_retransmit_count(int max);
|
|
|
|
|
|
/**
|
|
* Get the transaction instance in the incoming message. If the message
|
|
* has a corresponding transaction, this function will return non NULL
|
|
* value.
|
|
*
|
|
* @param rdata The incoming message buffer.
|
|
*
|
|
* @return The transaction instance associated with this message,
|
|
* or NULL if the message doesn't match any transactions.
|
|
*/
|
|
PJ_DECL(pjsip_transaction*) pjsip_rdata_get_tsx( pjsip_rx_data *rdata );
|
|
|
|
|
|
/**
|
|
* @}
|
|
*/
|
|
|
|
/*
|
|
* Internal.
|
|
*/
|
|
|
|
/**
|
|
* Dump transaction layer.
|
|
*/
|
|
PJ_DECL(void) pjsip_tsx_layer_dump(pj_bool_t detail);
|
|
|
|
/**
|
|
* Get the string name for the state.
|
|
* @param state State
|
|
*/
|
|
PJ_DECL(const char *) pjsip_tsx_state_str(pjsip_tsx_state_e state);
|
|
|
|
/**
|
|
* Get the role name.
|
|
* @param role Role.
|
|
*/
|
|
PJ_DECL(const char *) pjsip_role_name(pjsip_role_e role);
|
|
|
|
|
|
PJ_END_DECL
|
|
|
|
#endif /* __PJSIP_TRANSACT_H__ */
|
|
|