pjproject/pjsip/include/pjsip/sip_transaction.h

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__ */