blob: ce256f096f357f9fc1b02ea20620d377f2fba0cf [file] [log] [blame]
/* $Id$ */
/*
* Copyright (C) 2003-2006 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_TRANSPORT_H__
#define __PJSIP_SIP_TRANSPORT_H__
/**
* @file sip_transport.h
* @brief SIP Transport
*/
#include <pjsip/sip_msg.h>
#include <pjsip/sip_parser.h>
#include <pj/sock.h>
#include <pj/list.h>
#include <pj/ioqueue.h>
#include <pj/timer.h>
PJ_BEGIN_DECL
/**
* @defgroup PJSIP_TRANSPORT SIP Transport
* @ingroup PJSIP
*
* This is the low-level transport layer. Application normally won't need to
* use this function, but instead can use transaction or higher layer API to
* send and receive messages.
*
* @{
*/
/*****************************************************************************
*
* GENERAL TRANSPORT (NAMES, TYPES, ETC.)
*
*****************************************************************************/
/**
* Flags for SIP transports.
*/
enum pjsip_transport_flags_e
{
PJSIP_TRANSPORT_RELIABLE = 1, /**< Transport is reliable. */
PJSIP_TRANSPORT_SECURE = 2, /**< Transport is secure. */
PJSIP_TRANSPORT_DATAGRAM = 4, /**< Datagram based transport. */
};
/**
* Check if transport tp is reliable.
*/
#define PJSIP_TRANSPORT_IS_RELIABLE(tp) \
((tp)->flag & PJSIP_TRANSPORT_RELIABLE)
/**
* Check if transport tp is secure.
*/
#define PJSIP_TRANSPORT_IS_SECURE(tp) \
((tp)->flag & PJSIP_TRANSPORT_SECURE)
/**
* Get the transport type from the transport name.
*
* @param name Transport name, such as "TCP", or "UDP".
*
* @return The transport type, or PJSIP_TRANSPORT_UNSPECIFIED if
* the name is not recognized as the name of supported
* transport.
*/
PJ_DECL(pjsip_transport_type_e)
pjsip_transport_get_type_from_name(const pj_str_t *name);
/**
* Get the transport type for the specified flags.
*
* @param flag The transport flag.
*
* @return Transport type.
*/
PJ_DECL(pjsip_transport_type_e)
pjsip_transport_get_type_from_flag(unsigned flag);
/**
* Get transport flag from type.
*
* @param type Transport type.
*
* @return Transport flags.
*/
PJ_DECL(unsigned)
pjsip_transport_get_flag_from_type( pjsip_transport_type_e type );
/**
* Get the default SIP port number for the specified type.
*
* @param type Transport type.
*
* @return The port number, which is the default SIP port number for
* the specified type.
*/
PJ_DECL(int)
pjsip_transport_get_default_port_for_type(pjsip_transport_type_e type);
/**
* Get transport type name.
*
* @param t Transport type.
*
* @return Transport name.
*/
PJ_DECL(const char*) pjsip_transport_get_type_name(pjsip_transport_type_e t);
/*****************************************************************************
*
* RECEIVE DATA BUFFER.
*
*****************************************************************************/
/**
* A customized ioqueue async operation key which is used by transport
* to locate rdata when a pending read operation completes.
*/
typedef struct pjsip_rx_data_op_key
{
pj_ioqueue_op_key_t op_key;
pjsip_rx_data *rdata;
} pjsip_rx_data_op_key;
/**
* Incoming message buffer.
* This structure keep all the information regarding the received message. This
* buffer lifetime is only very short, normally after the transaction has been
* called, this buffer will be deleted/recycled. So care must be taken when
* allocating storage from the pool of this buffer.
*/
struct pjsip_rx_data
{
/**
* tp_info is part of rdata that remains static for the duration of the
* buffer. It is initialized when the buffer was created by transport.
*/
struct
{
/** Memory pool for this buffer. */
pj_pool_t *pool;
/** The transport object which received this packet. */
pjsip_transport *transport;
/** Other transport specific data to be attached to this buffer. */
void *tp_data;
/** Ioqueue key. */
pjsip_rx_data_op_key op_key;
} tp_info;
/**
* pkt_info is initialized by transport when it receives an incoming
* packet.
*/
struct
{
/** Time when the message was received. */
pj_time_val timestamp;
/** Pointer to the original packet. */
char packet[PJSIP_MAX_PKT_LEN];
/** Zero termination for the packet. */
pj_uint32_t zero;
/** The length of the packet received. */
pj_ssize_t len;
/** The source address from which the packet was received. */
pj_sockaddr src_addr;
/** The length of the source address. */
int src_addr_len;
/** The IP source address string (NULL terminated). */
char src_name[16];
/** The IP source port number. */
int src_port;
} pkt_info;
/**
* msg_info is initialized by transport mgr (tpmgr) before this buffer
* is passed to endpoint.
*/
struct
{
/** Start of msg buffer. */
char *msg_buf;
/** Length fo message. */
int len;
/** The parsed message, if any. */
pjsip_msg *msg;
/** Short description about the message.
* Application should use #pjsip_rx_data_get_info() instead.
*/
char *info;
/** The Call-ID header as found in the message. */
pjsip_cid_hdr *cid;
/** The From header as found in the message. */
pjsip_from_hdr *from;
/** The To header as found in the message. */
pjsip_to_hdr *to;
/** The topmost Via header as found in the message. */
pjsip_via_hdr *via;
/** The CSeq header as found in the message. */
pjsip_cseq_hdr *cseq;
/** Max forwards header. */
pjsip_max_fwd_hdr *max_fwd;
/** The first route header. */
pjsip_route_hdr *route;
/** The first record-route header. */
pjsip_rr_hdr *record_route;
/** Content-type header. */
pjsip_ctype_hdr *ctype;
/** Content-length header. */
pjsip_clen_hdr *clen;
/** The first Require header. */
pjsip_require_hdr *require;
/** The list of error generated by the parser when parsing
this message.
*/
pjsip_parser_err_report parse_err;
} msg_info;
/**
* endpt_info is initialized by endpoint after this buffer reaches
* endpoint.
*/
struct
{
/**
* Data attached by modules to this message.
*/
void *mod_data[PJSIP_MAX_MODULE];
} endpt_info;
};
/**
* Get printable information about the message in the rdata.
*
* @param rdata The receive data buffer.
*
* @return Printable information.
*/
PJ_DECL(char*) pjsip_rx_data_get_info(pjsip_rx_data *rdata);
/*****************************************************************************
*
* TRANSMIT DATA BUFFER MANIPULATION.
*
*****************************************************************************/
/** Customized ioqueue async operation key, used by transport to keep
* callback parameters.
*/
typedef struct pjsip_tx_data_op_key
{
pj_ioqueue_op_key_t key;
pjsip_tx_data *tdata;
void *token;
void (*callback)(pjsip_transport*,void*,pj_ssize_t);
} pjsip_tx_data_op_key;
/**
* Data structure for sending outgoing message. Application normally creates
* this buffer by calling #pjsip_endpt_create_tdata.
*
* The lifetime of this buffer is controlled by the reference counter in this
* structure, which is manipulated by calling #pjsip_tx_data_add_ref and
* #pjsip_tx_data_dec_ref. When the reference counter has reached zero, then
* this buffer will be destroyed.
*
* A transaction object normally will add reference counter to this buffer
* when application calls #pjsip_tsx_on_tx_msg, because it needs to keep the
* message for retransmission. The transaction will release the reference
* counter once its state has reached final state.
*/
struct pjsip_tx_data
{
/** This is for transmission queue; it's managed by transports. */
PJ_DECL_LIST_MEMBER(struct pjsip_tx_data);
/** Memory pool for this buffer. */
pj_pool_t *pool;
/** A name to identify this buffer. */
char obj_name[PJ_MAX_OBJ_NAME];
/** Short information describing this buffer and the message in it.
* Application should use #pjsip_tx_data_get_info() instead of
* directly accessing this member.
*/
char *info;
/** For response message, this contains the reference to timestamp when
* the original request message was received. The value of this field
* is set when application creates response message to a request by
* calling #pjsip_endpt_create_response.
*/
pj_time_val rx_timestamp;
/** The transport manager for this buffer. */
pjsip_tpmgr *mgr;
/** Ioqueue asynchronous operation key. */
pjsip_tx_data_op_key op_key;
/** Lock object. */
pj_lock_t *lock;
/** The message in this buffer. */
pjsip_msg *msg;
/** Buffer to the printed text representation of the message. When the
* content of this buffer is set, then the transport will send the content
* of this buffer instead of re-printing the message structure. If the
* message structure has changed, then application must invalidate this
* buffer by calling #pjsip_tx_data_invalidate_msg.
*/
pjsip_buffer buf;
/** Reference counter. */
pj_atomic_t *ref_cnt;
/** Being processed by transport? */
int is_pending;
/** Transport manager internal. */
void *token;
void (*cb)(void*, pjsip_tx_data*, pj_ssize_t);
/** Transport information, only valid during on_tx_request() and
* on_tx_response() callback.
*/
struct
{
pjsip_transport *transport; /**< Transport being used. */
pj_sockaddr dst_addr; /**< Destination address. */
int dst_addr_len; /**< Length of address. */
char dst_name[16]; /**< Destination address. */
int dst_port; /**< Destination port. */
} tp_info;
};
/**
* Create a new, blank transmit buffer. The reference count is initialized
* to zero.
*
* @param mgr The transport manager.
* @param tdata Pointer to receive transmit data.
*
* @return PJ_SUCCESS, or the appropriate error code.
*
* @see pjsip_endpt_create_tdata
*/
pj_status_t pjsip_tx_data_create( pjsip_tpmgr *mgr,
pjsip_tx_data **tdata );
/**
* Add reference counter to the transmit buffer. The reference counter controls
* the life time of the buffer, ie. when the counter reaches zero, then it
* will be destroyed.
*
* @param tdata The transmit buffer.
*/
PJ_DECL(void) pjsip_tx_data_add_ref( pjsip_tx_data *tdata );
/**
* Decrement reference counter of the transmit buffer.
* When the transmit buffer is no longer used, it will be destroyed and
* caller is informed with PJSIP_EBUFDESTROYED return status.
*
* @param tdata The transmit buffer data.
* @return This function will always succeeded eventhough the return
* status is non-zero. A status PJSIP_EBUFDESTROYED will be
* returned to inform that buffer is destroyed.
*/
PJ_DECL(pj_status_t) pjsip_tx_data_dec_ref( pjsip_tx_data *tdata );
/**
* Check if transmit data buffer contains a valid message.
*
* @param tdata The transmit buffer.
* @return Non-zero (PJ_TRUE) if buffer contains a valid message.
*/
PJ_DECL(pj_bool_t) pjsip_tx_data_is_valid( pjsip_tx_data *tdata );
/**
* Invalidate the print buffer to force message to be re-printed. Call
* when the message has changed after it has been printed to buffer. The
* message is printed to buffer normally by transport when it is about to be
* sent to the wire. Subsequent sending of the message will not cause
* the message to be re-printed, unless application invalidates the buffer
* by calling this function.
*
* @param tdata The transmit buffer.
*/
PJ_DECL(void) pjsip_tx_data_invalidate_msg( pjsip_tx_data *tdata );
/**
* Get short printable info about the transmit data. This will normally return
* short information about the message.
*
* @param tdata The transmit buffer.
*
* @return Null terminated info string.
*/
PJ_DECL(char*) pjsip_tx_data_get_info( pjsip_tx_data *tdata );
/*****************************************************************************
*
* TRANSPORT
*
*****************************************************************************/
/**
* This structure represent the "public" interface of a SIP transport.
* Applications normally extend this structure to include transport
* specific members.
*/
struct pjsip_transport
{
char obj_name[PJ_MAX_OBJ_NAME]; /**< Name. */
pj_pool_t *pool; /**< Pool used by transport. */
pj_atomic_t *ref_cnt; /**< Reference counter. */
pj_lock_t *lock; /**< Lock object. */
int tracing; /**< Tracing enabled? */
/** Key for indexing this transport in hash table. */
struct {
pjsip_transport_type_e type; /**< Transport type. */
pj_sockaddr rem_addr; /**< Remote addr (zero for UDP) */
} key;
char *type_name; /**< Type name. */
unsigned flag; /**< #pjsip_transport_flags_e */
char *info; /**< Transport info/description.*/
int addr_len; /**< Length of addresses. */
pj_sockaddr local_addr; /**< Bound address. */
pjsip_host_port local_name; /**< Published name (eg. STUN). */
pjsip_host_port remote_name; /**< Remote address name. */
pjsip_endpoint *endpt; /**< Endpoint instance. */
pjsip_tpmgr *tpmgr; /**< Transport manager. */
pj_timer_entry idle_timer; /**< Timer when ref cnt is zero.*/
/**
* Function to be called by transport manager to send SIP message.
*
* @param transport The transport to send the message.
* @param packet The buffer to send.
* @param length The length of the buffer to send.
* @param op_key Completion token, which will be supplied to
* caller when pending send operation completes.
* @param rem_addr The remote destination address.
* @param addr_len Size of remote address.
* @param callback If supplied, the callback will be called
* once a pending transmission has completed. If
* the function completes immediately (i.e. return
* code is not PJ_EPENDING), the callback will not
* be called.
*
* @return Should return PJ_SUCCESS only if data has been
* succesfully queued to operating system for
* transmission. Otherwise it may return PJ_EPENDING
* if the underlying transport can not send the
* data immediately and will send it later, which in
* this case caller doesn't have to do anything
* except wait the calback to be called, if it
* supplies one.
* Other return values indicate the error code.
*/
pj_status_t (*send_msg)(pjsip_transport *transport,
pjsip_tx_data *tdata,
const pj_sockaddr_t *rem_addr,
int addr_len,
void *token,
void (*callback)(pjsip_transport *transport,
void *token,
pj_ssize_t sent_bytes));
/**
* Destroy this transport.
*/
pj_status_t (*destroy)(pjsip_transport *transport);
/*
* Application may extend this structure..
*/
};
/**
* Register a transport.
*/
PJ_DECL(pj_status_t) pjsip_transport_register( pjsip_tpmgr *mgr,
pjsip_transport *tp );
/**
* Unregister transport. This will eventually call the transport to
* destroy itself.
*/
PJ_DECL(pj_status_t) pjsip_transport_unregister( pjsip_tpmgr *mgr,
pjsip_transport *tp);
/**
* Add ref.
*/
PJ_DECL(pj_status_t) pjsip_transport_add_ref( pjsip_transport *tp );
/**
* Dec ref.
*/
PJ_DECL(pj_status_t) pjsip_transport_dec_ref( pjsip_transport *tp );
/**
* Call for incoming message.
*/
PJ_DECL(pj_ssize_t) pjsip_tpmgr_receive_packet(pjsip_tpmgr *mgr,
pjsip_rx_data *rdata);
/*****************************************************************************
*
* TRANSPORT FACTORY
*
*****************************************************************************/
/**
* Transport factory.
*/
typedef struct pjsip_tpfactory pjsip_tpfactory;
/**
* Transport factory.
*/
struct pjsip_tpfactory
{
/* This list is managed by transport manager. */
PJ_DECL_LIST_MEMBER(struct pjsip_tpfactory);
pj_pool_t *pool;
pj_lock_t *lock;
pjsip_transport_type_e type;
char type_name[8];
unsigned flag;
pj_sockaddr local_addr;
pjsip_host_port addr_name;
/**
* Create new outbound connection.
* Note that the factory is responsible for both creating the
* transport and registering it to the transport manager.
*/
pj_status_t (*create_transport)(pjsip_tpfactory *factory,
pjsip_tpmgr *mgr,
pjsip_endpoint *endpt,
const pj_sockaddr *rem_addr,
int addr_len,
pjsip_transport **transport);
/*
* Application may extend this structure..
*/
};
/**
* Register a transport factory.
*
* @param mgr The transport manager.
* @param factory Transport factory.
*
* @return PJ_SUCCESS if listener was successfully created.
*/
PJ_DECL(pj_status_t) pjsip_tpmgr_register_tpfactory(pjsip_tpmgr *mgr,
pjsip_tpfactory *tpf);
/**
* Unregister factory.
*/
PJ_DECL(pj_status_t) pjsip_tpmgr_unregister_tpfactory(pjsip_tpmgr *mgr,
pjsip_tpfactory *tpf);
/*****************************************************************************
*
* TRANSPORT MANAGER
*
*****************************************************************************/
/**
* Create a new transport manager.
*
* @param pool Pool.
* @param endpt Endpoint instance.
* @param rx_cb Callback to receive incoming message.
* @param tx_cb Callback to be called before transport manager is sending
* outgoing message.
* @param p_mgr Pointer to receive the new transport manager.
*
* @return PJ_SUCCESS or the appropriate error code on error.
*/
PJ_DECL(pj_status_t) pjsip_tpmgr_create( pj_pool_t *pool,
pjsip_endpoint * endpt,
void (*rx_cb)(pjsip_endpoint*,
pj_status_t,
pjsip_rx_data *),
pj_status_t (*tx_cb)(pjsip_endpoint*,
pjsip_tx_data*),
pjsip_tpmgr **p_mgr);
/**
* Destroy transport manager.
*/
PJ_DECL(pj_status_t) pjsip_tpmgr_destroy(pjsip_tpmgr *mgr);
/**
* Dump transport info.
*/
PJ_DECL(void) pjsip_tpmgr_dump_transports(pjsip_tpmgr *mgr);
/*****************************************************************************
*
* PUBLIC API
*
*****************************************************************************/
/**
* Find transport to be used to send message to remote destination. If no
* suitable transport is found, a new one will be created.
*/
PJ_DECL(pj_status_t) pjsip_tpmgr_acquire_transport(pjsip_tpmgr *mgr,
pjsip_transport_type_e type,
const pj_sockaddr_t *remote,
int addr_len,
pjsip_transport **tp);
/**
* Send a SIP message using the specified transport.
*/
PJ_DECL(pj_status_t) pjsip_transport_send( pjsip_transport *tr,
pjsip_tx_data *tdata,
const pj_sockaddr_t *addr,
int addr_len,
void *token,
void (*cb)(void *token,
pjsip_tx_data *tdata,
pj_ssize_t bytes_sent));
/**
* @}
*/
PJ_END_DECL
#endif /* __PJSIP_SIP_TRANSPORT_H__ */