summaryrefslogtreecommitdiff
path: root/pjsip/include/pjsip/sip_transport.h
diff options
context:
space:
mode:
authorDavid M. Lee <dlee@digium.com>2013-01-07 14:24:28 -0600
committerDavid M. Lee <dlee@digium.com>2013-01-07 14:24:28 -0600
commitf3ab456a17af1c89a6e3be4d20c5944853df1cb0 (patch)
treed00e1a332cd038a6d906a1ea0ac91e1a4458e617 /pjsip/include/pjsip/sip_transport.h
Import pjproject-2.0.1
Diffstat (limited to 'pjsip/include/pjsip/sip_transport.h')
-rw-r--r--pjsip/include/pjsip/sip_transport.h1406
1 files changed, 1406 insertions, 0 deletions
diff --git a/pjsip/include/pjsip/sip_transport.h b/pjsip/include/pjsip/sip_transport.h
new file mode 100644
index 0000000..c8ea6fd
--- /dev/null
+++ b/pjsip/include/pjsip/sip_transport.h
@@ -0,0 +1,1406 @@
+/* $Id: sip_transport.h 4173 2012-06-20 10:39:05Z ming $ */
+/*
+ * 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_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 <pjsip/sip_resolve.h>
+#include <pj/sock.h>
+#include <pj/list.h>
+#include <pj/ioqueue.h>
+#include <pj/timer.h>
+
+PJ_BEGIN_DECL
+
+/**
+ * @defgroup PJSIP_TRANSPORT Transport
+ * @ingroup PJSIP_CORE
+ * @brief This is the transport framework.
+ *
+ * The transport framework is fully extensible. Please see
+ * <A HREF="/docs.htm">PJSIP Developer's Guide</A> PDF
+ * document for more information.
+ *
+ * Application MUST register at least one transport to PJSIP before any
+ * messages can be sent or received. Please see @ref PJSIP_TRANSPORT_UDP
+ * on how to create/register UDP transport to the transport framework.
+ *
+ * @{
+ */
+
+/*****************************************************************************
+ *
+ * GENERAL TRANSPORT (NAMES, TYPES, ETC.)
+ *
+ *****************************************************************************/
+
+/*
+ * Forward declaration for transport factory (since it is referenced by
+ * the transport factory itself).
+ */
+typedef struct pjsip_tpfactory pjsip_tpfactory;
+
+
+/**
+ * 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.
+ (it's also assumed to be
+ connectionless) */
+};
+
+/**
+ * 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)
+
+/**
+ * Register new transport type to PJSIP. The PJSIP transport framework
+ * contains the info for some standard transports, as declared by
+ * #pjsip_transport_type_e. Application may use non-standard transport
+ * with PJSIP, but before it does so, it must register the information
+ * about the new transport type to PJSIP by calling this function.
+ *
+ * @param tp_flag The flags describing characteristics of this
+ * transport type.
+ * @param tp_name Transport type name.
+ * @param def_port Default port to be used for the transport.
+ * @param p_tp_type On successful registration, it will be filled with
+ * the registered type. This argument is optional.
+ *
+ * @return PJ_SUCCESS if registration is successful, or
+ * PJSIP_ETYPEEXISTS if the same transport type has
+ * already been registered.
+ */
+PJ_DECL(pj_status_t) pjsip_transport_register_type(unsigned tp_flag,
+ const char *tp_name,
+ int def_port,
+ int *p_tp_type);
+
+
+/**
+ * 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 the socket address family of a given transport type.
+ *
+ * @param type Transport type.
+ *
+ * @return Transport type.
+ */
+PJ_DECL(int) pjsip_transport_type_get_af(pjsip_transport_type_e type);
+
+/**
+ * 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);
+
+/**
+ * Get longer description for the specified transport type.
+ *
+ * @param t Transport type.
+ *
+ * @return Transport description.
+ */
+PJ_DECL(const char*) pjsip_transport_get_type_desc(pjsip_transport_type_e t);
+
+
+
+/*****************************************************************************
+ *
+ * TRANSPORT SELECTOR.
+ *
+ *****************************************************************************/
+
+/**
+ * This structure describes the type of data in pjsip_tpselector.
+ */
+typedef enum pjsip_tpselector_type
+{
+ /** Transport is not specified. */
+ PJSIP_TPSELECTOR_NONE,
+
+ /** Use the specific transport to send request. */
+ PJSIP_TPSELECTOR_TRANSPORT,
+
+ /** Use the specific listener to send request. */
+ PJSIP_TPSELECTOR_LISTENER,
+
+} pjsip_tpselector_type;
+
+
+/**
+ * This structure describes the transport/listener preference to be used
+ * when sending outgoing requests.
+ *
+ * Normally transport will be selected automatically according to rules about
+ * sending requests. But some applications (such as proxies or B2BUAs) may
+ * want to explicitly use specific transport to send requests, for example
+ * when they want to make sure that outgoing request should go from a specific
+ * network interface.
+ *
+ * The pjsip_tpselector structure is used for that purpose, i.e. to allow
+ * application specificly request that a particular transport/listener
+ * should be used to send request. This structure is used when calling
+ * pjsip_tsx_set_transport() and pjsip_dlg_set_transport().
+ */
+typedef struct pjsip_tpselector
+{
+ /** The type of data in the union */
+ pjsip_tpselector_type type;
+
+ /** Union representing the transport/listener criteria to be used. */
+ union {
+ pjsip_transport *transport;
+ pjsip_tpfactory *listener;
+ void *ptr;
+ } u;
+
+} pjsip_tpselector;
+
+
+/**
+ * Add transport/listener reference in the selector to prevent the specified
+ * transport/listener from being destroyed while application still has
+ * reference to it.
+ *
+ * @param sel The transport selector.
+ */
+PJ_DECL(void) pjsip_tpselector_add_ref(pjsip_tpselector *sel);
+
+
+/**
+ * Decrement transport/listener reference in the selector.
+ * @param sel The transport selector
+ */
+PJ_DECL(void) pjsip_tpselector_dec_ref(pjsip_tpselector *sel);
+
+
+/*****************************************************************************
+ *
+ * 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; /**< ioqueue op_key. */
+ pjsip_rx_data *rdata; /**< rdata associated with this */
+} 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[PJ_INET6_ADDRSTRLEN];
+
+ /** 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;
+
+ /** "Require" header containing aggregates of all Require
+ * headers found in the message, or NULL.
+ */
+ pjsip_require_hdr *require;
+
+ /** "Supported" header containing aggregates of all Supported
+ * headers found in the message, or NULL.
+ */
+ pjsip_supported_hdr *supported;
+
+ /** 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
+{
+ /** ioqueue pending operation key. */
+ pj_ioqueue_op_key_t key;
+
+ /** Transmit data associated with this key. */
+ pjsip_tx_data *tdata;
+
+ /** Arbitrary token (attached by transport) */
+ void *token;
+
+ /** Callback to be called when pending transmit operation has
+ completed.
+ */
+ 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_send_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;
+
+ /** Strict route header saved by #pjsip_process_route_set(), to be
+ * restored by #pjsip_restore_strict_route_set().
+ */
+ pjsip_route_hdr *saved_strict_route;
+
+ /** 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;
+
+ /** Callback to be called when this tx_data has been transmitted. */
+ void (*cb)(void*, pjsip_tx_data*, pj_ssize_t);
+
+ /** Destination information, to be used to determine the network address
+ * of the message. For a request, this information is initialized when
+ * the request is sent with #pjsip_endpt_send_request_stateless() and
+ * network address is resolved. For CANCEL request, this information
+ * will be copied from the original INVITE to make sure that the CANCEL
+ * request goes to the same physical network address as the INVITE
+ * request.
+ */
+ struct
+ {
+ /** Server name.
+ */
+ pj_str_t name;
+
+ /** Server addresses resolved.
+ */
+ pjsip_server_addresses addr;
+
+ /** Current server address being tried.
+ */
+ unsigned cur_addr;
+
+ } dest_info;
+
+ /** 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[PJ_INET6_ADDRSTRLEN]; /**< Destination address. */
+ int dst_port; /**< Destination port. */
+ } tp_info;
+
+ /**
+ * Transport selector, to specify which transport to be used.
+ * The value here must be set with pjsip_tx_data_set_transport(),
+ * to allow reference counter to be set properly.
+ */
+ pjsip_tpselector tp_sel;
+
+ /**
+ * Special flag to indicate that this transmit data is a request that has
+ * been updated with proper authentication response and is ready to be
+ * sent for retry.
+ */
+ pj_bool_t auth_retry;
+
+ /**
+ * Arbitrary data attached by PJSIP modules.
+ */
+ void *mod_data[PJSIP_MAX_MODULE];
+
+ /**
+ * If via_addr is set, it will be used as the "sent-by" field of the
+ * Via header for outgoing requests as long as the request uses via_tp
+ * transport. Normally application should not use or access these fields.
+ */
+ pjsip_host_port via_addr; /**< Via address. */
+ const void *via_tp; /**< Via transport. */
+};
+
+
+/**
+ * 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_DECL(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 );
+
+/**
+ * Print the SIP message to transmit data buffer's internal buffer. This
+ * may allocate memory for the buffer, if the buffer has not been allocated
+ * yet, and encode the SIP message to that buffer.
+ *
+ * @param tdata The transmit buffer.
+ *
+ * @return PJ_SUCCESS on success of the appropriate error code.
+ */
+PJ_DECL(pj_status_t) pjsip_tx_data_encode(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 );
+
+/**
+ * Set the explicit transport to be used when sending this transmit data.
+ * Application should not need to call this function, but rather use
+ * pjsip_tsx_set_transport() and pjsip_dlg_set_transport() instead (which
+ * will call this function).
+ *
+ * @param tdata The transmit buffer.
+ * @param sel Transport selector.
+ *
+ * @return PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjsip_tx_data_set_transport(pjsip_tx_data *tdata,
+ const pjsip_tpselector *sel);
+
+
+/*****************************************************************************
+ *
+ * TRANSPORT
+ *
+ *****************************************************************************/
+/**
+ * Type of callback to receive transport operation status.
+ */
+typedef void (*pjsip_transport_callback)(pjsip_transport *tp, void *token,
+ pj_ssize_t sent_bytes);
+
+/**
+ * This structure describes transport key to be registered to hash table.
+ */
+typedef struct pjsip_transport_key
+{
+ /**
+ * Transport type.
+ */
+ long type;
+
+ /**
+ * Destination address.
+ */
+ pj_sockaddr rem_addr;
+
+} pjsip_transport_key;
+
+
+/**
+ * Enumeration of transport direction types.
+ */
+typedef enum pjsip_transport_dir
+{
+ PJSIP_TP_DIR_NONE, /**< Direction not set, normally used by
+ connectionless transports such as
+ UDP transport. */
+ PJSIP_TP_DIR_OUTGOING, /**< Outgoing connection or client mode,
+ this is only for connection-oriented
+ transports. */
+ PJSIP_TP_DIR_INCOMING, /**< Incoming connection or server mode,
+ this is only for connection-oriented
+ transports. */
+} pjsip_transport_dir;
+
+
+/**
+ * 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. */
+ pj_bool_t tracing; /**< Tracing enabled? */
+ pj_bool_t is_shutdown; /**< Being shutdown? */
+ pj_bool_t is_destroying; /**< Destroy in progress? */
+
+ /** Key for indexing this transport in hash table. */
+ pjsip_transport_key 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_transport_dir dir; /**< Connection direction. */
+
+ pjsip_endpoint *endpt; /**< Endpoint instance. */
+ pjsip_tpmgr *tpmgr; /**< Transport manager. */
+ pj_timer_entry idle_timer; /**< Timer when ref cnt is zero.*/
+
+ void *data; /**< Internal transport data. */
+
+ /**
+ * 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,
+ pjsip_transport_callback callback);
+
+ /**
+ * Instruct the transport to initiate graceful shutdown procedure.
+ * After all objects release their reference to this transport,
+ * the transport will be deleted.
+ *
+ * Note that application MUST use #pjsip_transport_shutdown() instead.
+ *
+ * @param transport The transport.
+ *
+ * @return PJ_SUCCESS on success.
+ */
+ pj_status_t (*do_shutdown)(pjsip_transport *transport);
+
+ /**
+ * Forcefully destroy this transport regardless whether there are
+ * objects that currently use this transport. This function should only
+ * be called by transport manager or other internal objects (such as the
+ * transport itself) who know what they're doing. Application should use
+ * #pjsip_transport_shutdown() instead.
+ *
+ * @param transport The transport.
+ *
+ * @return PJ_SUCCESS on success.
+ */
+ pj_status_t (*destroy)(pjsip_transport *transport);
+
+ /*
+ * Application may extend this structure..
+ */
+};
+
+
+/**
+ * Register a transport instance to the transport manager. This function
+ * is normally called by the transport instance when it is created
+ * by application.
+ *
+ * @param mgr The transport manager.
+ * @param tp The new transport to be registered.
+ *
+ * @return PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjsip_transport_register( pjsip_tpmgr *mgr,
+ pjsip_transport *tp );
+
+
+/**
+ * Start graceful shutdown procedure for this transport. After graceful
+ * shutdown has been initiated, no new reference can be obtained for
+ * the transport. However, existing objects that currently uses the
+ * transport may still use this transport to send and receive packets.
+ *
+ * After all objects release their reference to this transport,
+ * the transport will be destroyed immediately.
+ *
+ * @param tp The transport.
+ *
+ * @return PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjsip_transport_shutdown(pjsip_transport *tp);
+
+/**
+ * Destroy a transport when there is no object currently uses the transport.
+ * This function is normally called internally by transport manager or the
+ * transport itself. Application should use #pjsip_transport_shutdown()
+ * instead.
+ *
+ * @param tp The transport instance.
+ *
+ * @return PJ_SUCCESS on success or the appropriate error code.
+ * Some of possible errors are PJSIP_EBUSY if the
+ * transport's reference counter is not zero.
+ */
+PJ_DECL(pj_status_t) pjsip_transport_destroy( pjsip_transport *tp);
+
+/**
+ * Add reference counter to the specified transport. Any objects that wishes
+ * to keep the reference of the transport MUST increment the transport's
+ * reference counter to prevent it from being destroyed.
+ *
+ * @param tp The transport instance.
+ *
+ * @return PJ_SUCCESS on success or the appropriate error code.
+ */
+PJ_DECL(pj_status_t) pjsip_transport_add_ref( pjsip_transport *tp );
+
+/**
+ * Decrement reference counter of the specified transport. When an object no
+ * longer want to keep the reference to the transport, it must decrement the
+ * reference counter. When the reference counter of the transport reaches
+ * zero, the transport manager will start the idle timer to destroy the
+ * transport if no objects acquire the reference counter during the idle
+ * interval.
+ *
+ * @param tp The transport instance.
+ *
+ * @return PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjsip_transport_dec_ref( pjsip_transport *tp );
+
+
+/**
+ * This function is called by transport instances to report an incoming
+ * packet to the transport manager. The transport manager then would try to
+ * parse all SIP messages in the packet, and for each parsed SIP message, it
+ * would report the message to the SIP endpoint (#pjsip_endpoint).
+ *
+ * @param mgr The transport manager instance.
+ * @param rdata The receive data buffer containing the packet. The
+ * transport MUST fully initialize tp_info and pkt_info
+ * member of the rdata.
+ *
+ * @return The number of bytes successfully processed from the
+ * packet. If the transport is datagram oriented, the
+ * value will be equal to the size of the packet. For
+ * stream oriented transport (e.g. TCP, TLS), the value
+ * returned may be less than the packet size, if
+ * partial message is received. The transport then MUST
+ * keep the remainder part and report it again to
+ * this function once more data/packet is received.
+ */
+PJ_DECL(pj_ssize_t) pjsip_tpmgr_receive_packet(pjsip_tpmgr *mgr,
+ pjsip_rx_data *rdata);
+
+
+/*****************************************************************************
+ *
+ * TRANSPORT FACTORY
+ *
+ *****************************************************************************/
+
+
+/**
+ * A transport factory is normally used for connection oriented transports
+ * (such as TCP or TLS) to create instances of transports. It registers
+ * a new transport type to the transport manager, and the transport manager
+ * would ask the factory to create a transport instance when it received
+ * command from application to send a SIP message using the specified
+ * transport type.
+ */
+struct pjsip_tpfactory
+{
+ /** This list is managed by transport manager. */
+ PJ_DECL_LIST_MEMBER(struct pjsip_tpfactory);
+
+ char obj_name[PJ_MAX_OBJ_NAME]; /**< Name. */
+
+ pj_pool_t *pool; /**< Owned memory pool. */
+ pj_lock_t *lock; /**< Lock object. */
+
+ pjsip_transport_type_e type; /**< Transport type. */
+ char *type_name; /**< Type string name. */
+ unsigned flag; /**< Transport flag. */
+
+ pj_sockaddr local_addr; /**< Bound address. */
+ pjsip_host_port addr_name; /**< Published name. */
+
+ /**
+ * Create new outbound connection suitable for sending SIP message
+ * to specified remote address.
+ * 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);
+
+ /**
+ * Create new outbound connection suitable for sending SIP message
+ * to specified remote address by also considering outgoing SIP
+ * message data.
+ * Note that the factory is responsible for both creating the
+ * transport and registering it to the transport manager.
+ */
+ pj_status_t (*create_transport2)(pjsip_tpfactory *factory,
+ pjsip_tpmgr *mgr,
+ pjsip_endpoint *endpt,
+ const pj_sockaddr *rem_addr,
+ int addr_len,
+ pjsip_tx_data *tdata,
+ pjsip_transport **transport);
+
+ /**
+ * Destroy the listener.
+ */
+ pj_status_t (*destroy)(pjsip_tpfactory *factory);
+
+ /*
+ * Application may extend this structure..
+ */
+};
+
+
+
+/**
+ * Register a transport factory.
+ *
+ * @param mgr The transport manager.
+ * @param tpf 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.
+ *
+ * @param mgr The transport manager.
+ * @param tpf Transport factory.
+ *
+ * @return PJ_SUCCESS is sucessfully unregistered.
+ */
+PJ_DECL(pj_status_t) pjsip_tpmgr_unregister_tpfactory(pjsip_tpmgr *mgr,
+ pjsip_tpfactory *tpf);
+
+
+/*****************************************************************************
+ *
+ * TRANSPORT MANAGER
+ *
+ *****************************************************************************/
+
+/**
+ * Type of callback to be called when transport manager receives incoming
+ * SIP message.
+ *
+ * @param ep Endpoint.
+ * @param status Receiption status.
+ * @param rd Received packet.
+ */
+typedef void (*pjsip_rx_callback)(pjsip_endpoint *ep, pj_status_t status,
+ pjsip_rx_data *rd);
+
+/**
+ * Type of callback to be called before transport manager is about
+ * to transmit SIP message.
+ *
+ * @param ep Endpoint.
+ * @param td Transmit data.
+ */
+typedef pj_status_t (*pjsip_tx_callback)(pjsip_endpoint *ep, pjsip_tx_data*td);
+
+/**
+ * Create a transport manager. Normally application doesn't need to call
+ * this function directly, since a transport manager will be created and
+ * destroyed automatically by the SIP endpoint.
+ *
+ * @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,
+ pjsip_rx_callback rx_cb,
+ pjsip_tx_callback tx_cb,
+ pjsip_tpmgr **p_mgr);
+
+
+/**
+ * Find out the appropriate local address info (IP address and port) to
+ * advertise in Contact header based on the remote address to be
+ * contacted. The local address info would be the address name of the
+ * transport or listener which will be used to send the request.
+ *
+ * In this implementation, it will only select the transport based on
+ * the transport type in the request.
+ *
+ * @param tpmgr The transport manager.
+ * @param pool Pool to allocate memory for the IP address.
+ * @param type Destination address to contact.
+ * @param sel Optional pointer to prefered transport, if any.
+ * @param ip_addr Pointer to receive the IP address.
+ * @param port Pointer to receive the port number.
+ *
+ * @return PJ_SUCCESS, or the appropriate error code.
+ */
+PJ_DECL(pj_status_t) pjsip_tpmgr_find_local_addr( pjsip_tpmgr *tpmgr,
+ pj_pool_t *pool,
+ pjsip_transport_type_e type,
+ const pjsip_tpselector *sel,
+ pj_str_t *ip_addr,
+ int *port);
+
+/**
+ * Return number of transports currently registered to the transport
+ * manager.
+ *
+ * @param mgr The transport manager.
+ *
+ * @return Number of transports.
+ */
+PJ_DECL(unsigned) pjsip_tpmgr_get_transport_count(pjsip_tpmgr *mgr);
+
+
+/**
+ * Destroy a transport manager. Normally application doesn't need to call
+ * this function directly, since a transport manager will be created and
+ * destroyed automatically by the SIP endpoint.
+ *
+ * @param mgr The transport manager.
+ *
+ * @return PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjsip_tpmgr_destroy(pjsip_tpmgr *mgr);
+
+
+/**
+ * Dump transport info and status to log.
+ *
+ * @param mgr The transport manager.
+ */
+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.
+ *
+ * This is an internal function since normally application doesn't have access
+ * to transport manager. Application should use pjsip_endpt_acquire_transport()
+ * instead.
+ *
+ * @param mgr The transport manager instance.
+ * @param type The type of transport to be acquired.
+ * @param remote The remote address to send message to.
+ * @param addr_len Length of the remote address.
+ * @param sel Optional pointer to transport selector instance which is
+ * used to find explicit transport, if required.
+ * @param tp Pointer to receive the transport instance, if one is found.
+ *
+ * @return PJ_SUCCESS on success, or the appropriate error code.
+ */
+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,
+ const pjsip_tpselector *sel,
+ pjsip_transport **tp);
+
+/**
+ * Find suitable transport for sending SIP message to specified remote
+ * destination by also considering the outgoing SIP message. If no suitable
+ * transport is found, a new one will be created.
+ *
+ * This is an internal function since normally application doesn't have access
+ * to transport manager. Application should use pjsip_endpt_acquire_transport2()
+ * instead.
+ *
+ * @param mgr The transport manager instance.
+ * @param type The type of transport to be acquired.
+ * @param remote The remote address to send message to.
+ * @param addr_len Length of the remote address.
+ * @param sel Optional pointer to transport selector instance which is
+ * used to find explicit transport, if required.
+ * @param tdata Optional pointer to data to be sent.
+ * @param tp Pointer to receive the transport instance, if one is found.
+ *
+ * @return PJ_SUCCESS on success, or the appropriate error code.
+ */
+PJ_DECL(pj_status_t) pjsip_tpmgr_acquire_transport2(pjsip_tpmgr *mgr,
+ pjsip_transport_type_e type,
+ const pj_sockaddr_t *remote,
+ int addr_len,
+ const pjsip_tpselector *sel,
+ pjsip_tx_data *tdata,
+ pjsip_transport **tp);
+
+/**
+ * Type of callback to receive notification when message or raw data
+ * has been sent.
+ *
+ * @param token The token that was given when calling the function
+ * to send message or raw data.
+ * @param tdata The transmit buffer used to send the message.
+ * @param bytes_sent Number of bytes sent. On success, the value will be
+ * positive number indicating the number of bytes sent.
+ * On failure, the value will be a negative number of
+ * the error code (i.e. bytes_sent = -status).
+ */
+typedef void (*pjsip_tp_send_callback)(void *token, pjsip_tx_data *tdata,
+ pj_ssize_t bytes_sent);
+
+
+/**
+ * This is a low-level function to send a SIP message using the specified
+ * transport to the specified destination.
+ *
+ * @param tr The SIP transport to be used.
+ * @param tdata Transmit data buffer containing SIP message.
+ * @param addr Destination address.
+ * @param addr_len Length of destination address.
+ * @param token Arbitrary token to be returned back to callback.
+ * @param cb Optional callback to be called to notify caller about
+ * the completion status of the pending send operation.
+ *
+ * @return If the message has been sent successfully, this function
+ * will return PJ_SUCCESS and the callback will not be
+ * called. If message cannot be sent immediately, this
+ * function will return PJ_EPENDING, and application will
+ * be notified later about the completion via the callback.
+ * Any statuses other than PJ_SUCCESS or PJ_EPENDING
+ * indicates immediate failure, and in this case the
+ * callback will not be called.
+ */
+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,
+ pjsip_tp_send_callback cb);
+
+
+/**
+ * This is a low-level function to send raw data to a destination.
+ *
+ * See also #pjsip_endpt_send_raw() and #pjsip_endpt_send_raw_to_uri().
+ *
+ * @param mgr Transport manager.
+ * @param tp_type Transport type.
+ * @param sel Optional pointer to transport selector instance if
+ * application wants to use a specific transport instance
+ * rather then letting transport manager finds the suitable
+ * transport.
+ * @param tdata Optional transmit data buffer to be used. If this value
+ * is NULL, this function will create one internally. If
+ * tdata is specified, this function will decrement the
+ * reference counter upon completion.
+ * @param raw_data The data to be sent.
+ * @param data_len The length of the data.
+ * @param addr Destination address.
+ * @param addr_len Length of destination address.
+ * @param token Arbitrary token to be returned back to callback.
+ * @param cb Optional callback to be called to notify caller about
+ * the completion status of the pending send operation.
+ *
+ * @return If the message has been sent successfully, this function
+ * will return PJ_SUCCESS and the callback will not be
+ * called. If message cannot be sent immediately, this
+ * function will return PJ_EPENDING, and application will
+ * be notified later about the completion via the callback.
+ * Any statuses other than PJ_SUCCESS or PJ_EPENDING
+ * indicates immediate failure, and in this case the
+ * callback will not be called.
+ */
+PJ_DECL(pj_status_t) pjsip_tpmgr_send_raw(pjsip_tpmgr *mgr,
+ pjsip_transport_type_e tp_type,
+ const pjsip_tpselector *sel,
+ pjsip_tx_data *tdata,
+ const void *raw_data,
+ pj_size_t data_len,
+ const pj_sockaddr_t *addr,
+ int addr_len,
+ void *token,
+ pjsip_tp_send_callback cb);
+
+
+/**
+ * Enumeration of transport state types.
+ */
+typedef enum pjsip_transport_state
+{
+ PJSIP_TP_STATE_CONNECTED, /**< Transport connected, applicable only
+ to connection-oriented transports
+ such as TCP and TLS. */
+ PJSIP_TP_STATE_DISCONNECTED /**< Transport disconnected, applicable
+ only to connection-oriented
+ transports such as TCP and TLS. */
+} pjsip_transport_state;
+
+
+/**
+ * Definition of transport state listener key.
+ */
+typedef void pjsip_tp_state_listener_key;
+
+/**
+ * Structure of transport state info passed by #pjsip_tp_state_callback.
+ */
+typedef struct pjsip_transport_state_info {
+ /**
+ * The last error code related to the transport state.
+ */
+ pj_status_t status;
+
+ /**
+ * Optional extended info, the content is specific for each transport type.
+ */
+ void *ext_info;
+
+ /**
+ * Optional user data. In global transport state notification, this will
+ * always be NULL.
+ */
+ void *user_data;
+
+} pjsip_transport_state_info;
+
+
+/**
+ * Type of callback to receive transport state notifications, such as
+ * transport connected/disconnected. Application may shutdown the transport
+ * in this callback.
+ *
+ * @param tp The transport instance.
+ * @param state The transport state.
+ * @param info The transport state info.
+ */
+typedef void (*pjsip_tp_state_callback)(
+ pjsip_transport *tp,
+ pjsip_transport_state state,
+ const pjsip_transport_state_info *info);
+
+
+/**
+ * Set callback of global transport state notification. The caller will be
+ * notified whenever the state of any transport is changed. The type of events
+ * are defined in #pjsip_transport_state.
+ *
+ * Note that this function will override the existing callback, if any, so
+ * application is recommended to keep the old callback and manually forward
+ * the notification to the old callback, otherwise other component that
+ * concerns about the transport state will no longer receive transport state
+ * events.
+ *
+ * @param mgr Transport manager.
+ * @param cb Callback to be called to notify caller about transport
+ * state changing.
+ *
+ * @return PJ_SUCCESS on success, or the appropriate error code.
+ */
+PJ_DECL(pj_status_t) pjsip_tpmgr_set_state_cb(pjsip_tpmgr *mgr,
+ pjsip_tp_state_callback cb);
+
+
+/**
+ * Get the callback of global transport state notification.
+ *
+ * @param mgr Transport manager.
+ *
+ * @return The transport state callback or NULL if it is not set.
+ */
+PJ_DECL(pjsip_tp_state_callback) pjsip_tpmgr_get_state_cb(
+ const pjsip_tpmgr *mgr);
+
+
+/**
+ * Add a listener to the specified transport for transport state notification.
+ *
+ * @param tp The transport.
+ * @param cb Callback to be called to notify listener about transport
+ * state changing.
+ * @param user_data The user data.
+ * @param key Output key, used to remove this listener.
+ *
+ * @return PJ_SUCCESS on success, or the appropriate error code.
+ */
+PJ_DECL(pj_status_t) pjsip_transport_add_state_listener (
+ pjsip_transport *tp,
+ pjsip_tp_state_callback cb,
+ void *user_data,
+ pjsip_tp_state_listener_key **key);
+
+
+/**
+ * Remove a listener from the specified transport for transport state
+ * notification.
+ *
+ * @param tp The transport.
+ * @param key The listener key.
+ * @param user_data The user data, for validation purpose.
+ *
+ * @return PJ_SUCCESS on success, or the appropriate error code.
+ */
+PJ_DECL(pj_status_t) pjsip_transport_remove_state_listener (
+ pjsip_transport *tp,
+ pjsip_tp_state_listener_key *key,
+ const void *user_data);
+
+
+/**
+ * @}
+ */
+
+
+PJ_END_DECL
+
+#endif /* __PJSIP_SIP_TRANSPORT_H__ */
+