summaryrefslogtreecommitdiff
path: root/pjsip/include
diff options
context:
space:
mode:
Diffstat (limited to 'pjsip/include')
-rw-r--r--pjsip/include/pjsip-simple/errno.h118
-rw-r--r--pjsip/include/pjsip-simple/evsub.h505
-rw-r--r--pjsip/include/pjsip-simple/evsub_msg.h119
-rw-r--r--pjsip/include/pjsip-simple/iscomposing.h135
-rw-r--r--pjsip/include/pjsip-simple/mwi.h208
-rw-r--r--pjsip/include/pjsip-simple/pidf.h178
-rw-r--r--pjsip/include/pjsip-simple/presence.h415
-rw-r--r--pjsip/include/pjsip-simple/publish.h349
-rw-r--r--pjsip/include/pjsip-simple/rpid.h149
-rw-r--r--pjsip/include/pjsip-simple/types.h31
-rw-r--r--pjsip/include/pjsip-simple/xpidf.h135
-rw-r--r--pjsip/include/pjsip-ua/sip_100rel.h245
-rw-r--r--pjsip/include/pjsip-ua/sip_inv.h963
-rw-r--r--pjsip/include/pjsip-ua/sip_regc.h416
-rw-r--r--pjsip/include/pjsip-ua/sip_replaces.h301
-rw-r--r--pjsip/include/pjsip-ua/sip_timer.h262
-rw-r--r--pjsip/include/pjsip-ua/sip_xfer.h208
-rw-r--r--pjsip/include/pjsip.h61
-rw-r--r--pjsip/include/pjsip/print_util.h141
-rw-r--r--pjsip/include/pjsip/sip_auth.h519
-rw-r--r--pjsip/include/pjsip/sip_auth_aka.h213
-rw-r--r--pjsip/include/pjsip/sip_auth_msg.h252
-rw-r--r--pjsip/include/pjsip/sip_auth_parser.h73
-rw-r--r--pjsip/include/pjsip/sip_autoconf.h.in39
-rw-r--r--pjsip/include/pjsip/sip_config.h1025
-rw-r--r--pjsip/include/pjsip/sip_dialog.h791
-rw-r--r--pjsip/include/pjsip/sip_endpoint.h584
-rw-r--r--pjsip/include/pjsip/sip_errno.h545
-rw-r--r--pjsip/include/pjsip/sip_event.h231
-rw-r--r--pjsip/include/pjsip/sip_module.h222
-rw-r--r--pjsip/include/pjsip/sip_msg.h2048
-rw-r--r--pjsip/include/pjsip/sip_multipart.h179
-rw-r--r--pjsip/include/pjsip/sip_parser.h416
-rw-r--r--pjsip/include/pjsip/sip_private.h32
-rw-r--r--pjsip/include/pjsip/sip_resolve.h291
-rw-r--r--pjsip/include/pjsip/sip_tel_uri.h84
-rw-r--r--pjsip/include/pjsip/sip_transaction.h414
-rw-r--r--pjsip/include/pjsip/sip_transport.h1406
-rw-r--r--pjsip/include/pjsip/sip_transport_loop.h147
-rw-r--r--pjsip/include/pjsip/sip_transport_tcp.h210
-rw-r--r--pjsip/include/pjsip/sip_transport_tls.h305
-rw-r--r--pjsip/include/pjsip/sip_transport_udp.h235
-rw-r--r--pjsip/include/pjsip/sip_types.h257
-rw-r--r--pjsip/include/pjsip/sip_ua_layer.h162
-rw-r--r--pjsip/include/pjsip/sip_uri.h468
-rw-r--r--pjsip/include/pjsip/sip_util.h861
-rw-r--r--pjsip/include/pjsip_auth.h38
-rw-r--r--pjsip/include/pjsip_simple.h46
-rw-r--r--pjsip/include/pjsip_ua.h32
-rw-r--r--pjsip/include/pjsua-lib/pjsua.h6346
-rw-r--r--pjsip/include/pjsua-lib/pjsua_internal.h805
-rw-r--r--pjsip/include/pjsua.h1
52 files changed, 24216 insertions, 0 deletions
diff --git a/pjsip/include/pjsip-simple/errno.h b/pjsip/include/pjsip-simple/errno.h
new file mode 100644
index 0000000..72450aa
--- /dev/null
+++ b/pjsip/include/pjsip-simple/errno.h
@@ -0,0 +1,118 @@
+/* $Id: errno.h 3553 2011-05-05 06:14:19Z nanang $ */
+/*
+ * 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_SIMPLE_ERRNO_H__
+#define __PJSIP_SIMPLE_ERRNO_H__
+
+#include <pjsip/sip_errno.h>
+
+PJ_BEGIN_DECL
+
+/**
+ * Start of error code relative to PJ_ERRNO_START_USER.
+ */
+#define PJSIP_SIMPLE_ERRNO_START (PJ_ERRNO_START_USER + PJ_ERRNO_SPACE_SIZE*2)
+
+
+/************************************************************
+ * EVENT PACKAGE ERRORS
+ ***********************************************************/
+/**
+ * @hideinitializer
+ * No event package with the specified name.
+ */
+#define PJSIP_SIMPLE_ENOPKG (PJSIP_SIMPLE_ERRNO_START+1) /*270001*/
+/**
+ * @hideinitializer
+ * Event package already exists.
+ */
+#define PJSIP_SIMPLE_EPKGEXISTS (PJSIP_SIMPLE_ERRNO_START+2) /*270002*/
+
+
+/************************************************************
+ * PRESENCE ERROR
+ ***********************************************************/
+/**
+ * @hideinitializer
+ * Expecting SUBSCRIBE request
+ */
+#define PJSIP_SIMPLE_ENOTSUBSCRIBE (PJSIP_SIMPLE_ERRNO_START+20) /*270020*/
+/**
+ * @hideinitializer
+ * No presence associated with subscription
+ */
+#define PJSIP_SIMPLE_ENOPRESENCE (PJSIP_SIMPLE_ERRNO_START+21) /*270021*/
+/**
+ * @hideinitializer
+ * No presence info in server subscription
+ */
+#define PJSIP_SIMPLE_ENOPRESENCEINFO (PJSIP_SIMPLE_ERRNO_START+22) /*270022*/
+/**
+ * @hideinitializer
+ * Bad Content-Type
+ */
+#define PJSIP_SIMPLE_EBADCONTENT (PJSIP_SIMPLE_ERRNO_START+23) /*270023*/
+/**
+ * @hideinitializer
+ * Bad PIDF Message
+ */
+#define PJSIP_SIMPLE_EBADPIDF (PJSIP_SIMPLE_ERRNO_START+24) /*270024*/
+/**
+ * @hideinitializer
+ * Bad XPIDF Message
+ */
+#define PJSIP_SIMPLE_EBADXPIDF (PJSIP_SIMPLE_ERRNO_START+25) /*270025*/
+/**
+ * @hideinitializer
+ * Bad RPID Message
+ */
+#define PJSIP_SIMPLE_EBADRPID (PJSIP_SIMPLE_ERRNO_START+26) /*270026*/
+
+
+/************************************************************
+ * ISCOMPOSING ERRORS
+ ***********************************************************/
+/**
+ * @hideinitializer
+ * Bad isComposing XML message.
+ */
+#define PJSIP_SIMPLE_EBADISCOMPOSE (PJSIP_SIMPLE_ERRNO_START+40) /*270040*/
+
+/**
+ * Get error message for the specified error code. Note that this
+ * function is only able to decode PJSIP-SIMPLE specific error code.
+ * Application should use pj_strerror(), which should be able to
+ * decode all error codes belonging to all subsystems (e.g. pjlib,
+ * pjmedia, pjsip, etc).
+ *
+ * @param status The error code.
+ * @param buffer The buffer where to put the error message.
+ * @param bufsize Size of the buffer.
+ *
+ * @return The error message as NULL terminated string,
+ * wrapped with pj_str_t.
+ */
+PJ_DECL(pj_str_t) pjsipsimple_strerror(pj_status_t status,
+ char *buffer, pj_size_t bufsize);
+
+
+PJ_END_DECL
+
+#endif /* __PJSIP_SIMPLE_ERRNO_H__ */
+
diff --git a/pjsip/include/pjsip-simple/evsub.h b/pjsip/include/pjsip-simple/evsub.h
new file mode 100644
index 0000000..5184a79
--- /dev/null
+++ b/pjsip/include/pjsip-simple/evsub.h
@@ -0,0 +1,505 @@
+/* $Id: evsub.h 3553 2011-05-05 06:14:19Z nanang $ */
+/*
+ * 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_SIMPLE_EVSUB_H__
+#define __PJSIP_SIMPLE_EVSUB_H__
+
+/**
+ * @file evsub.h
+ * @brief SIP Specific Event Notification Extension (RFC 3265)
+ */
+
+#include <pjsip-simple/types.h>
+
+
+/**
+ * @defgroup PJSIP_EVENT_NOT SIP Event Notification (RFC 3265) Module
+ * @ingroup PJSIP_SIMPLE
+ * @brief Core Event Subscription framework, used by presence, call transfer, etc.
+ * @{
+ *
+ * This module provides the implementation of SIP Extension for SIP Specific
+ * Event Notification (RFC 3265). It extends PJSIP by supporting SUBSCRIBE and
+ * NOTIFY methods.
+ *
+ * This module itself is extensible; new event packages can be registered to
+ * this module to handle specific extensions (such as presence).
+ */
+
+PJ_BEGIN_DECL
+
+
+/**
+ * Opaque type for event subscription session.
+ */
+typedef struct pjsip_evsub pjsip_evsub;
+
+
+/**
+ * This enumeration describes basic subscription state as described in the
+ * RFC 3265. The standard specifies that extensions may define additional
+ * states. In the case where the state is not known, the subscription state
+ * will be set to PJSIP_EVSUB_STATE_UNKNOWN, and the token will be kept
+ * in state_str member of the susbcription structure.
+ */
+enum pjsip_evsub_state
+{
+ PJSIP_EVSUB_STATE_NULL, /**< State is NULL. */
+ PJSIP_EVSUB_STATE_SENT, /**< Client has sent SUBSCRIBE request. */
+ PJSIP_EVSUB_STATE_ACCEPTED, /**< 2xx response to SUBSCRIBE has been
+ sent/received. */
+ PJSIP_EVSUB_STATE_PENDING, /**< Subscription is pending. */
+ PJSIP_EVSUB_STATE_ACTIVE, /**< Subscription is active. */
+ PJSIP_EVSUB_STATE_TERMINATED,/**< Subscription is terminated. */
+ PJSIP_EVSUB_STATE_UNKNOWN, /**< Subscription state can not be determined.
+ Application can query the state by
+ calling #pjsip_evsub_get_state_name().*/
+};
+
+/**
+ * @see pjsip_evsub_state
+ */
+typedef enum pjsip_evsub_state pjsip_evsub_state;
+
+
+/**
+ * Some options for the event subscription.
+ */
+enum
+{
+ /**
+ * If this flag is set, then outgoing request to create subscription
+ * will not have id in the Event header (e.g. in REFER request). But if
+ * there is an id in the incoming NOTIFY, that id will be used.
+ */
+ PJSIP_EVSUB_NO_EVENT_ID = 1,
+};
+
+
+/**
+ * This structure describes callback that is registered by application or
+ * package to receive notifications about subscription events.
+ */
+struct pjsip_evsub_user
+{
+ /**
+ * This callback is called when subscription state has changed.
+ * Application MUST be prepared to receive NULL event and events with
+ * type other than PJSIP_EVENT_TSX_STATE
+ *
+ * This callback is OPTIONAL.
+ *
+ * @param sub The subscription instance.
+ * @param event The event that has caused the state to change,
+ * which may be NULL or may have type other than
+ * PJSIP_EVENT_TSX_STATE.
+ */
+ void (*on_evsub_state)( pjsip_evsub *sub, pjsip_event *event);
+
+ /**
+ * This callback is called when transaction state has changed.
+ *
+ * @param sub The subscription instance.
+ * @param tsx Transaction.
+ * @param event The event.
+ */
+ void (*on_tsx_state)(pjsip_evsub *sub, pjsip_transaction *tsx,
+ pjsip_event *event);
+
+ /**
+ * This callback is called when incoming SUBSCRIBE (or any method that
+ * establishes the subscription in the first place) is received. It
+ * allows application to specify what response should be sent to
+ * remote, along with additional headers and message body to be put
+ * in the response.
+ *
+ * This callback is OPTIONAL.
+ *
+ * However, implementation MUST send NOTIFY request upon receiving this
+ * callback. The suggested behavior is to call
+ * #pjsip_evsub_current_notify(), since this function takes care
+ * about unsubscription request and calculates the appropriate expiration
+ * interval.
+ */
+ void (*on_rx_refresh)( pjsip_evsub *sub,
+ pjsip_rx_data *rdata,
+ int *p_st_code,
+ pj_str_t **p_st_text,
+ pjsip_hdr *res_hdr,
+ pjsip_msg_body **p_body);
+
+ /**
+ * This callback is called when client/subscriber received incoming
+ * NOTIFY request. It allows the application to specify what response
+ * should be sent to remote, along with additional headers and message
+ * body to be put in the response.
+ *
+ * This callback is OPTIONAL. When it is not implemented, the default
+ * behavior is to respond incoming NOTIFY request with 200 (OK).
+ *
+ * @param sub The subscription instance.
+ * @param rdata The received NOTIFY request.
+ * @param p_st_code Application MUST set the value of this argument with
+ * final status code (200-699) upon returning from the
+ * callback.
+ * @param p_st_text Custom status text, if any.
+ * @param res_hdr Upon return, application can put additional headers
+ * to be sent in the response in this list.
+ * @param p_body Application MAY specify message body to be sent in
+ * the response.
+ */
+ void (*on_rx_notify)(pjsip_evsub *sub,
+ pjsip_rx_data *rdata,
+ int *p_st_code,
+ pj_str_t **p_st_text,
+ pjsip_hdr *res_hdr,
+ pjsip_msg_body **p_body);
+
+ /**
+ * This callback is called when it is time for the client to refresh
+ * the subscription.
+ *
+ * This callback is OPTIONAL when PJSIP package such as presence or
+ * refer is used; the event package will refresh subscription by sending
+ * SUBSCRIBE with the interval set to current/last interval.
+ *
+ * @param sub The subscription instance.
+ */
+ void (*on_client_refresh)(pjsip_evsub *sub);
+
+ /**
+ * This callback is called when server doesn't receive subscription
+ * refresh after the specified subscription interval.
+ *
+ * This callback is OPTIONAL when PJSIP package such as presence or
+ * refer is used; the event package send NOTIFY to terminate the
+ * subscription.
+ */
+ void (*on_server_timeout)(pjsip_evsub *sub);
+
+};
+
+
+/**
+ * @see pjsip_evsub_user
+ */
+typedef struct pjsip_evsub_user pjsip_evsub_user;
+
+
+/**
+ * SUBSCRIBE method constant. @see pjsip_get_subscribe_method()
+ */
+PJ_DECL_DATA(const pjsip_method) pjsip_subscribe_method;
+
+/**
+ * NOTIFY method constant. @see pjsip_get_notify_method()
+ */
+PJ_DECL_DATA(const pjsip_method) pjsip_notify_method;
+
+/**
+ * SUBSCRIBE method constant.
+ */
+PJ_DECL(const pjsip_method*) pjsip_get_subscribe_method(void);
+
+/**
+ * NOTIFY method constant.
+ */
+PJ_DECL(const pjsip_method*) pjsip_get_notify_method(void);
+
+
+/**
+ * Initialize the event subscription module and register the module to the
+ * specified endpoint.
+ *
+ * @param endpt The endpoint instance.
+ *
+ * @return PJ_SUCCESS if module can be created and registered
+ * successfully.
+ */
+PJ_DECL(pj_status_t) pjsip_evsub_init_module(pjsip_endpoint *endpt);
+
+
+/**
+ * Get the event subscription module instance that was previously created
+ * and registered to endpoint.
+ *
+ * @return The event subscription module instance.
+ */
+PJ_DECL(pjsip_module*) pjsip_evsub_instance(void);
+
+
+/**
+ * Register event package to the event subscription framework.
+ *
+ * @param pkg_mod The module that implements the event package being
+ * registered.
+ * @param event_name Event package identification.
+ * @param expires Default subscription expiration time, in seconds.
+ * @param accept_cnt Number of strings in Accept array.
+ * @param accept Array of Accept value.
+ *
+ * @return PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjsip_evsub_register_pkg( pjsip_module *pkg_mod,
+ const pj_str_t *event_name,
+ unsigned expires,
+ unsigned accept_cnt,
+ const pj_str_t accept[]);
+
+/**
+ * Get the Allow-Events header. This header is built based on the packages
+ * that are registered to the evsub module.
+ *
+ * @param m Pointer to event subscription module instance, or
+ * NULL to use default instance (equal to
+ * #pjsip_evsub_instance()).
+ *
+ * @return The Allow-Events header.
+ */
+PJ_DECL(const pjsip_hdr*) pjsip_evsub_get_allow_events_hdr(pjsip_module *m);
+
+
+/**
+ * Create client subscription session.
+ *
+ * @param dlg The underlying dialog to use.
+ * @param user_cb Callback to receive event subscription notifications.
+ * @param event Event name.
+ * @param option Bitmask of options.
+ * @param p_evsub Pointer to receive event subscription instance.
+ *
+ * @return PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjsip_evsub_create_uac( pjsip_dialog *dlg,
+ const pjsip_evsub_user *user_cb,
+ const pj_str_t *event,
+ unsigned option,
+ pjsip_evsub **p_evsub);
+
+/**
+ * Create server subscription session.
+ *
+ * @param dlg The underlying dialog to use.
+ * @param user_cb Callback to receive event subscription notifications.
+ * @param rdata The incoming request that creates the event
+ * subscription, such as SUBSCRIBE or REFER.
+ * @param option Bitmask of options.
+ * @param p_evsub Pointer to receive event subscription instance.
+ *
+ * @return PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjsip_evsub_create_uas( pjsip_dialog *dlg,
+ const pjsip_evsub_user *user_cb,
+ pjsip_rx_data *rdata,
+ unsigned option,
+ pjsip_evsub **p_evsub);
+
+/**
+ * Forcefully destroy the subscription session. This function should only
+ * be called on special condition, such as when the subscription
+ * initialization has failed. For other conditions, application MUST terminate
+ * the subscription by sending the appropriate un(SUBSCRIBE) or NOTIFY.
+ *
+ * @param sub The event subscription.
+ * @param notify Specify whether the state notification callback
+ * should be called.
+ *
+ * @return PJ_SUCCESS if subscription session has been destroyed.
+ */
+PJ_DECL(pj_status_t) pjsip_evsub_terminate( pjsip_evsub *sub,
+ pj_bool_t notify );
+
+
+/**
+ * Get subscription state.
+ *
+ * @param sub Event subscription instance.
+ *
+ * @return Subscription state.
+ */
+PJ_DECL(pjsip_evsub_state) pjsip_evsub_get_state(pjsip_evsub *sub);
+
+
+/**
+ * Get the string representation of the subscription state.
+ *
+ * @param sub Event subscription instance.
+ *
+ * @return NULL terminated string.
+ */
+PJ_DECL(const char*) pjsip_evsub_get_state_name(pjsip_evsub *sub);
+
+
+/**
+ * Get subscription termination reason, if any. If remote did not
+ * send termination reason, this function will return empty string.
+ *
+ * @param sub Event subscription instance.
+ *
+ * @return NULL terminated string.
+ */
+PJ_DECL(const pj_str_t*) pjsip_evsub_get_termination_reason(pjsip_evsub *sub);
+
+
+/**
+ * Call this function to create request to initiate subscription, to
+ * refresh subcription, or to request subscription termination.
+ *
+ * @param sub Client subscription instance.
+ * @param method The method that establishes the subscription, such as
+ * SUBSCRIBE or REFER. If this argument is NULL, then
+ * SUBSCRIBE will be used.
+ * @param expires Subscription expiration. If the value is set to zero,
+ * this will request unsubscription. If the value is
+ * negative, default expiration as defined by the package
+ * will be used.
+ * @param p_tdata Pointer to receive the request.
+ *
+ * @return PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjsip_evsub_initiate( pjsip_evsub *sub,
+ const pjsip_method *method,
+ pj_int32_t expires,
+ pjsip_tx_data **p_tdata);
+
+
+/**
+ * Add a list of headers to the subscription instance. The list of headers
+ * will be added to outgoing presence subscription requests.
+ *
+ * @param sub Subscription instance.
+ * @param hdr_list List of headers to be added.
+ *
+ * @return PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjsip_evsub_add_header( pjsip_evsub *sub,
+ const pjsip_hdr *hdr_list );
+
+
+/**
+ * Accept the incoming subscription request by sending 2xx response to
+ * incoming SUBSCRIBE request.
+ *
+ * @param sub Server subscription instance.
+ * @param rdata The incoming subscription request message.
+ * @param st_code Status code, which MUST be final response.
+ * @param hdr_list Optional list of headers to be added in the response.
+ *
+ * @return PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjsip_evsub_accept( pjsip_evsub *sub,
+ pjsip_rx_data *rdata,
+ int st_code,
+ const pjsip_hdr *hdr_list );
+
+
+/**
+ * For notifier, create NOTIFY request to subscriber, and set the state
+ * of the subscription.
+ *
+ * @param sub The server subscription (notifier) instance.
+ * @param state New state to set.
+ * @param state_str The state string name, if state contains value other
+ * than active, pending, or terminated. Otherwise this
+ * argument is ignored.
+ * @param reason Specify reason if new state is terminated, otherwise
+ * put NULL.
+ * @param p_tdata Pointer to receive request message.
+ *
+ * @return PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjsip_evsub_notify( pjsip_evsub *sub,
+ pjsip_evsub_state state,
+ const pj_str_t *state_str,
+ const pj_str_t *reason,
+ pjsip_tx_data **p_tdata);
+
+
+/**
+ * For notifier, create a NOTIFY request that reflects current subscription
+ * status.
+ *
+ * @param sub The server subscription instance.
+ * @param p_tdata Pointer to receive the request messge.
+ *
+ * @return PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjsip_evsub_current_notify( pjsip_evsub *sub,
+ pjsip_tx_data **p_tdata );
+
+
+
+/**
+ * Send request message that was previously created with initiate(), notify(),
+ * or current_notify(). Application may also send request created with other
+ * functions, e.g. authentication. But the request MUST be either request
+ * that creates/refresh subscription or NOTIFY request.
+ *
+ * @param sub The event subscription object.
+ * @param tdata Request message to be send.
+ *
+ * @return PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjsip_evsub_send_request( pjsip_evsub *sub,
+ pjsip_tx_data *tdata);
+
+
+
+/**
+ * Get the event subscription instance associated with the specified
+ * transaction.
+ *
+ * @param tsx The transaction.
+ *
+ * @return The event subscription instance registered in the
+ * transaction, if any.
+ */
+PJ_DECL(pjsip_evsub*) pjsip_tsx_get_evsub(pjsip_transaction *tsx);
+
+
+/**
+ * Set event subscription's module data.
+ *
+ * @param sub The event subscription.
+ * @param mod_id The module id.
+ * @param data Arbitrary data.
+ */
+PJ_DECL(void) pjsip_evsub_set_mod_data( pjsip_evsub *sub, unsigned mod_id,
+ void *data );
+
+
+/**
+ * Get event subscription's module data.
+ *
+ * @param sub The event subscription.
+ * @param mod_id The module id.
+ *
+ * @return Data previously set at the specified id.
+ */
+PJ_DECL(void*) pjsip_evsub_get_mod_data( pjsip_evsub *sub, unsigned mod_id );
+
+
+
+PJ_END_DECL
+
+/**
+ * @}
+ */
+
+#endif /* __PJSIP_SIMPLE_EVSUB_H__ */
diff --git a/pjsip/include/pjsip-simple/evsub_msg.h b/pjsip/include/pjsip-simple/evsub_msg.h
new file mode 100644
index 0000000..64035e2
--- /dev/null
+++ b/pjsip/include/pjsip-simple/evsub_msg.h
@@ -0,0 +1,119 @@
+/* $Id: evsub_msg.h 3553 2011-05-05 06:14:19Z nanang $ */
+/*
+ * 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_SIMPLE_EVENT_NOTIFY_MSG_H__
+#define __PJSIP_SIMPLE_EVENT_NOTIFY_MSG_H__
+
+/**
+ * @file evsub_msg.h
+ * @brief SIP Event Notification Headers (RFC 3265)
+ */
+#include <pjsip/sip_msg.h>
+
+/**
+ * @defgroup PJSIP_EVENT_HDRS Additional Header Fields
+ * @ingroup PJSIP_EVENT_NOT
+ * @{
+ */
+
+PJ_BEGIN_DECL
+
+
+/** Max events in Allow-Events header. */
+#define PJSIP_MAX_ALLOW_EVENTS 16
+
+/**
+ * This structure describes Event header.
+ */
+typedef struct pjsip_event_hdr
+{
+ /** Standard header fields. */
+ PJSIP_DECL_HDR_MEMBER(struct pjsip_event_hdr);
+
+ pj_str_t event_type; /**< Event name. */
+ pj_str_t id_param; /**< Optional event ID parameter. */
+ pjsip_param other_param; /**< Other parameter. */
+} pjsip_event_hdr;
+
+/**
+ * Create an Event header.
+ *
+ * @param pool The pool.
+ *
+ * @return New Event header instance.
+ */
+PJ_DECL(pjsip_event_hdr*) pjsip_event_hdr_create(pj_pool_t *pool);
+
+
+/**
+ * This structure describes Allow-Events header.
+ */
+typedef pjsip_generic_array_hdr pjsip_allow_events_hdr;
+
+
+/**
+ * Create a new Allow-Events header.
+ *
+ * @param pool The pool.
+ *
+ * @return Allow-Events header.
+ */
+PJ_DECL(pjsip_allow_events_hdr*)
+pjsip_allow_events_hdr_create(pj_pool_t *pool);
+
+
+/**
+ * This structure describes Subscription-State header.
+ */
+typedef struct pjsip_sub_state_hdr
+{
+ /** Standard header fields. */
+ PJSIP_DECL_HDR_MEMBER(struct pjsip_sub_state_hdr);
+
+ pj_str_t sub_state; /**< Subscription state. */
+ pj_str_t reason_param; /**< Optional termination reason. */
+ int expires_param; /**< Expires param, or -1. */
+ int retry_after; /**< Retry after param, or -1. */
+ pjsip_param other_param; /**< Other parameters. */
+} pjsip_sub_state_hdr;
+
+/**
+ * Create new Subscription-State header.
+ *
+ * @param pool The pool.
+ *
+ * @return Subscription-State header.
+ */
+PJ_DECL(pjsip_sub_state_hdr*) pjsip_sub_state_hdr_create(pj_pool_t *pool);
+
+/**
+ * Initialize parser for event notify module.
+ */
+PJ_DECL(void) pjsip_evsub_init_parser(void);
+
+
+PJ_END_DECL
+
+
+/**
+ * @}
+ */
+
+#endif /* __PJSIP_SIMPLE_EVENT_NOTIFY_MSG_H__ */
+
diff --git a/pjsip/include/pjsip-simple/iscomposing.h b/pjsip/include/pjsip-simple/iscomposing.h
new file mode 100644
index 0000000..61d5c72
--- /dev/null
+++ b/pjsip/include/pjsip-simple/iscomposing.h
@@ -0,0 +1,135 @@
+/* $Id: iscomposing.h 3553 2011-05-05 06:14:19Z nanang $ */
+/*
+ * 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_SIMPLE_ISCOMPOSING_H__
+#define __PJSIP_SIMPLE_ISCOMPOSING_H__
+
+/**
+ * @file iscomposing.h
+ * @brief Support for Indication of Message Composition (RFC 3994)
+ */
+#include <pjsip-simple/types.h>
+#include <pjlib-util/xml.h>
+
+/**
+ * @defgroup PJSIP_ISCOMPOSING Message Composition Indication (RFC 3994)
+ * @ingroup PJSIP_SIMPLE
+ * @brief Support for Indication of Message Composition (RFC 3994)
+ * @{
+ *
+ * This implements message composition indication, as described in
+ * RFC 3994.
+ */
+
+PJ_BEGIN_DECL
+
+
+/**
+ * Create XML message with MIME type "application/im-iscomposing+xml"
+ * to indicate the message composition status.
+ *
+ * @param pool Pool to allocate memory.
+ * @param is_composing Message composition indication status. Set to
+ * PJ_TRUE (or non-zero) to indicate that application
+ * is currently composing an instant message.
+ * @param lst_actv Optional attribute to indicate time of last
+ * activity. If none is to be specified, the value
+ * MUST be set to NULL.
+ * @param content_tp Optional attribute to indicate the content type of
+ * message being composed. If none is to be specified,
+ * the value MUST be set to NULL.
+ * @param refresh Optional attribute to indicate the interval when
+ * next indication will be sent, only when
+ * is_composing is non-zero. If none is to be
+ * specified, the value MUST be set to -1.
+ *
+ * @return An XML message containing the message indication.
+ * NULL will be returned when there's not enough
+ * memory to allocate the message.
+ */
+PJ_DECL(pj_xml_node*) pjsip_iscomposing_create_xml(pj_pool_t *pool,
+ pj_bool_t is_composing,
+ const pj_time_val *lst_actv,
+ const pj_str_t *content_tp,
+ int refresh);
+
+
+/**
+ * Create message body with Content-Type "application/im-iscomposing+xml"
+ * to indicate the message composition status.
+ *
+ * @param pool Pool to allocate memory.
+ * @param is_composing Message composition indication status. Set to
+ * PJ_TRUE (or non-zero) to indicate that application
+ * is currently composing an instant message.
+ * @param lst_actv Optional attribute to indicate time of last
+ * activity. If none is to be specified, the value
+ * MUST be set to NULL.
+ * @param content_tp Optional attribute to indicate the content type of
+ * message being composed. If none is to be specified,
+ * the value MUST be set to NULL.
+ * @param refresh Optional attribute to indicate the interval when
+ * next indication will be sent, only when
+ * is_composing is non-zero. If none is to be
+ * specified, the value MUST be set to -1.
+ *
+ * @return The SIP message body containing XML message
+ * indication. NULL will be returned when there's not
+ * enough memory to allocate the message.
+ */
+PJ_DECL(pjsip_msg_body*) pjsip_iscomposing_create_body( pj_pool_t *pool,
+ pj_bool_t is_composing,
+ const pj_time_val *lst_actv,
+ const pj_str_t *content_tp,
+ int refresh);
+
+
+/**
+ * Parse the buffer and return message composition indication in the
+ * message.
+ *
+ * @param pool Pool to allocate memory for the parsing process.
+ * @param msg The message to be parsed.
+ * @param len Length of the message.
+ * @param p_is_composing Optional pointer to receive iscomposing status.
+ * @param p_last_active Optional pointer to receive last active attribute.
+ * @param p_content_type Optional pointer to receive content type attribute.
+ * @param p_refresh Optional pointer to receive refresh time.
+ *
+ * @return PJ_SUCCESS if message can be successfully parsed.
+ */
+PJ_DECL(pj_status_t) pjsip_iscomposing_parse( pj_pool_t *pool,
+ char *msg,
+ pj_size_t len,
+ pj_bool_t *p_is_composing,
+ pj_str_t **p_last_active,
+ pj_str_t **p_content_type,
+ int *p_refresh );
+
+
+/**
+ * @}
+ */
+
+
+PJ_END_DECL
+
+
+#endif /* __PJSIP_SIMPLE_ISCOMPOSING_H__ */
+
diff --git a/pjsip/include/pjsip-simple/mwi.h b/pjsip/include/pjsip-simple/mwi.h
new file mode 100644
index 0000000..4f59d40
--- /dev/null
+++ b/pjsip/include/pjsip-simple/mwi.h
@@ -0,0 +1,208 @@
+/* $Id: mwi.h 3553 2011-05-05 06:14:19Z nanang $ */
+/*
+ * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
+ *
+ * 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_SIMPLE_MWI_H__
+#define __PJSIP_SIMPLE_MWI_H__
+
+/**
+ * @file mwi.h
+ * @brief SIP Extension for MWI (RFC 3842)
+ */
+#include <pjsip-simple/evsub.h>
+#include <pjsip/sip_msg.h>
+
+
+PJ_BEGIN_DECL
+
+
+/**
+ * @defgroup mwi SIP Message Summary and Message Waiting Indication (RFC 3842)
+ * @ingroup PJSIP_SIMPLE
+ * @brief Support for SIP MWI Extension (RFC 3842)
+ * @{
+ *
+ * This module implements RFC 3842: A Message Summary and Message Waiting
+ * Indication Event Package for the Session Initiation Protocol (SIP).
+ * It uses the SIP Event Notification framework (evsub.h) and extends the
+ * framework by implementing "message-summary" event package.
+ */
+
+
+/**
+ * Initialize the MWI module and register it as endpoint module and
+ * package to the event subscription module.
+ *
+ * @param endpt The endpoint instance.
+ * @param mod_evsub The event subscription module instance.
+ *
+ * @return PJ_SUCCESS if the module is successfully
+ * initialized and registered to both endpoint
+ * and the event subscription module.
+ */
+PJ_DECL(pj_status_t) pjsip_mwi_init_module(pjsip_endpoint *endpt,
+ pjsip_module *mod_evsub);
+
+/**
+ * Get the MWI module instance.
+ *
+ * @return The MWI module instance.
+ */
+PJ_DECL(pjsip_module*) pjsip_mwi_instance(void);
+
+/**
+ * Create MWI client subscription session.
+ *
+ * @param dlg The underlying dialog to use.
+ * @param user_cb Pointer to callbacks to receive MWI subscription
+ * events.
+ * @param options Option flags. Currently only PJSIP_EVSUB_NO_EVENT_ID
+ * is recognized.
+ * @param p_evsub Pointer to receive the MWI subscription
+ * session.
+ *
+ * @return PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjsip_mwi_create_uac( pjsip_dialog *dlg,
+ const pjsip_evsub_user *user_cb,
+ unsigned options,
+ pjsip_evsub **p_evsub );
+
+/**
+ * Create MWI server subscription session.
+ *
+ * @param dlg The underlying dialog to use.
+ * @param user_cb Pointer to callbacks to receive MWI subscription
+ * events.
+ * @param rdata The incoming SUBSCRIBE request that creates the event
+ * subscription.
+ * @param p_evsub Pointer to receive the MWI subscription
+ * session.
+ *
+ * @return PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjsip_mwi_create_uas( pjsip_dialog *dlg,
+ const pjsip_evsub_user *user_cb,
+ pjsip_rx_data *rdata,
+ pjsip_evsub **p_evsub );
+
+/**
+ * Forcefully destroy the MWI subscription. This function should only
+ * be called on special condition, such as when the subscription
+ * initialization has failed. For other conditions, application MUST terminate
+ * the subscription by sending the appropriate un(SUBSCRIBE) or NOTIFY.
+ *
+ * @param sub The MWI subscription.
+ * @param notify Specify whether the state notification callback
+ * should be called.
+ *
+ * @return PJ_SUCCESS if subscription session has been destroyed.
+ */
+PJ_DECL(pj_status_t) pjsip_mwi_terminate( pjsip_evsub *sub,
+ pj_bool_t notify );
+
+/**
+ * Call this function to create request to initiate MWI subscription, to
+ * refresh subcription, or to request subscription termination.
+ *
+ * @param sub Client subscription instance.
+ * @param expires Subscription expiration. If the value is set to zero,
+ * this will request unsubscription.
+ * @param p_tdata Pointer to receive the request.
+ *
+ * @return PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjsip_mwi_initiate( pjsip_evsub *sub,
+ pj_int32_t expires,
+ pjsip_tx_data **p_tdata);
+
+/**
+ * Accept the incoming subscription request by sending 2xx response to
+ * incoming SUBSCRIBE request.
+ *
+ * @param sub Server subscription instance.
+ * @param rdata The incoming subscription request message.
+ * @param st_code Status code, which MUST be final response.
+ * @param hdr_list Optional list of headers to be added in the response.
+ *
+ * @return PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjsip_mwi_accept( pjsip_evsub *sub,
+ pjsip_rx_data *rdata,
+ int st_code,
+ const pjsip_hdr *hdr_list );
+
+/**
+ * For notifier, create NOTIFY request to subscriber, and set the state
+ * of the subscription.
+ *
+ * @param sub The server subscription (notifier) instance.
+ * @param state New state to set.
+ * @param state_str The state string name, if state contains value other
+ * than active, pending, or terminated. Otherwise this
+ * argument is ignored.
+ * @param reason Specify reason if new state is terminated, otherwise
+ * put NULL.
+ * @param mime_type MIME type/content type of the message body.
+ * @param body Message body to be included in the NOTIFY request.
+ * @param p_tdata Pointer to receive the request.
+ *
+ * @return PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjsip_mwi_notify( pjsip_evsub *sub,
+ pjsip_evsub_state state,
+ const pj_str_t *state_str,
+ const pj_str_t *reason,
+ const pjsip_media_type *mime_type,
+ const pj_str_t *body,
+ pjsip_tx_data **p_tdata);
+
+/**
+ * Create NOTIFY request containing message body from the last NOITFY
+ * message created.
+ *
+ * @param sub Server subscription object.
+ * @param p_tdata Pointer to receive request.
+ *
+ * @return PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjsip_mwi_current_notify( pjsip_evsub *sub,
+ pjsip_tx_data **p_tdata );
+
+
+/**
+ * Send request message that was previously created with initiate(), notify(),
+ * or current_notify(). Application may also send request created with other
+ * functions, e.g. authentication. But the request MUST be either request
+ * that creates/refresh subscription or NOTIFY request.
+ *
+ * @param sub The subscription object.
+ * @param tdata Request message to be sent.
+ *
+ * @return PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjsip_mwi_send_request( pjsip_evsub *sub,
+ pjsip_tx_data *tdata );
+
+/**
+ * @}
+ */
+
+PJ_END_DECL
+
+
+#endif /* __PJSIP_SIMPLE_MWI_H__ */
diff --git a/pjsip/include/pjsip-simple/pidf.h b/pjsip/include/pjsip-simple/pidf.h
new file mode 100644
index 0000000..6e26264
--- /dev/null
+++ b/pjsip/include/pjsip-simple/pidf.h
@@ -0,0 +1,178 @@
+/* $Id: pidf.h 3553 2011-05-05 06:14:19Z nanang $ */
+/*
+ * 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_SIMPLE_PIDF_H__
+#define __PJSIP_SIMPLE_PIDF_H__
+
+/**
+ * @file pidf.h
+ * @brief PIDF/Presence Information Data Format (RFC 3863)
+ */
+#include <pjsip-simple/types.h>
+#include <pjlib-util/xml.h>
+
+PJ_BEGIN_DECL
+
+
+/**
+ * @defgroup PJSIP_SIMPLE_PIDF PIDF/Presence Information Data Format (RFC 3863)
+ * @ingroup PJSIP_SIMPLE
+ * @brief Support for PIDF/Presence Information Data Format (RFC 3863)
+ * @{
+ *
+ * This file provides tools for manipulating Presence Information Data
+ * Format (PIDF) as described in RFC 3863.
+ */
+typedef struct pj_xml_node pjpidf_pres;
+typedef struct pj_xml_node pjpidf_tuple;
+typedef struct pj_xml_node pjpidf_status;
+typedef struct pj_xml_node pjpidf_note;
+
+typedef struct pjpidf_status_op
+{
+ void (*construct)(pj_pool_t*, pjpidf_status*);
+ pj_bool_t (*is_basic_open)(const pjpidf_status*);
+ void (*set_basic_open)(pjpidf_status*, pj_bool_t);
+} pjpidf_status_op;
+
+typedef struct pjpidf_tuple_op
+{
+ void (*construct)(pj_pool_t*, pjpidf_tuple*, const pj_str_t*);
+
+ const pj_str_t* (*get_id)(const pjpidf_tuple* );
+ void (*set_id)(pj_pool_t*, pjpidf_tuple *, const pj_str_t*);
+
+ pjpidf_status* (*get_status)(pjpidf_tuple* );
+
+ const pj_str_t* (*get_contact)(const pjpidf_tuple*);
+ void (*set_contact)(pj_pool_t*, pjpidf_tuple*, const pj_str_t*);
+ void (*set_contact_prio)(pj_pool_t*, pjpidf_tuple*, const pj_str_t*);
+ const pj_str_t* (*get_contact_prio)(const pjpidf_tuple*);
+
+ pjpidf_note* (*add_note)(pj_pool_t*, pjpidf_tuple*, const pj_str_t*);
+ pjpidf_note* (*get_first_note)(pjpidf_tuple*);
+ pjpidf_note* (*get_next_note)(pjpidf_tuple*, pjpidf_note*);
+
+ const pj_str_t* (*get_timestamp)(const pjpidf_tuple*);
+ void (*set_timestamp)(pj_pool_t*, pjpidf_tuple*, const pj_str_t*);
+ void (*set_timestamp_np)(pj_pool_t*,pjpidf_tuple*, pj_str_t*);
+
+} pjpidf_tuple_op;
+
+typedef struct pjpidf_pres_op
+{
+ void (*construct)(pj_pool_t*, pjpidf_pres*, const pj_str_t*);
+
+ pjpidf_tuple* (*add_tuple)(pj_pool_t*, pjpidf_pres*, const pj_str_t*);
+ pjpidf_tuple* (*get_first_tuple)(pjpidf_pres*);
+ pjpidf_tuple* (*get_next_tuple)(pjpidf_pres*, pjpidf_tuple*);
+ pjpidf_tuple* (*find_tuple)(pjpidf_pres*, const pj_str_t*);
+ void (*remove_tuple)(pjpidf_pres*, pjpidf_tuple*);
+
+ pjpidf_note* (*add_note)(pj_pool_t*, pjpidf_pres*, const pj_str_t*);
+ pjpidf_note* (*get_first_note)(pjpidf_pres*);
+ pjpidf_note* (*get_next_note)(pjpidf_pres*, pjpidf_note*);
+
+} pjpidf_pres_op;
+
+
+extern struct pjpidf_op_desc
+{
+ pjpidf_pres_op pres;
+ pjpidf_tuple_op tuple;
+ pjpidf_status_op status;
+} pjpidf_op;
+
+
+/******************************************************************************
+ * Top level API for managing presence document.
+ *****************************************************************************/
+PJ_DECL(pjpidf_pres*) pjpidf_create(pj_pool_t *pool, const pj_str_t *entity);
+PJ_DECL(pjpidf_pres*) pjpidf_parse(pj_pool_t *pool, char *text, int len);
+PJ_DECL(int) pjpidf_print(const pjpidf_pres* pres, char *buf, int len);
+
+
+/******************************************************************************
+ * API for managing Presence node.
+ *****************************************************************************/
+PJ_DECL(void) pjpidf_pres_construct(pj_pool_t *pool, pjpidf_pres *pres,
+ const pj_str_t *entity);
+PJ_DECL(pjpidf_tuple*) pjpidf_pres_add_tuple(pj_pool_t *pool, pjpidf_pres *pres,
+ const pj_str_t *id);
+PJ_DECL(pjpidf_tuple*) pjpidf_pres_get_first_tuple(pjpidf_pres *pres);
+PJ_DECL(pjpidf_tuple*) pjpidf_pres_get_next_tuple(pjpidf_pres *pres,
+ pjpidf_tuple *t);
+PJ_DECL(pjpidf_tuple*) pjpidf_pres_find_tuple(pjpidf_pres *pres,
+ const pj_str_t *id);
+PJ_DECL(void) pjpidf_pres_remove_tuple(pjpidf_pres *pres,
+ pjpidf_tuple*);
+
+PJ_DECL(pjpidf_note*) pjpidf_pres_add_note(pj_pool_t *pool, pjpidf_pres *pres,
+ const pj_str_t *text);
+PJ_DECL(pjpidf_note*) pjpidf_pres_get_first_note(pjpidf_pres *pres);
+PJ_DECL(pjpidf_note*) pjpidf_pres_get_next_note(pjpidf_pres*, pjpidf_note*);
+
+
+/******************************************************************************
+ * API for managing Tuple node.
+ *****************************************************************************/
+PJ_DECL(void) pjpidf_tuple_construct(pj_pool_t *pool, pjpidf_tuple *t,
+ const pj_str_t *id);
+PJ_DECL(const pj_str_t*) pjpidf_tuple_get_id(const pjpidf_tuple *t );
+PJ_DECL(void) pjpidf_tuple_set_id(pj_pool_t *pool, pjpidf_tuple *t,
+ const pj_str_t *id);
+
+PJ_DECL(pjpidf_status*) pjpidf_tuple_get_status(pjpidf_tuple *t);
+
+PJ_DECL(const pj_str_t*) pjpidf_tuple_get_contact(const pjpidf_tuple *t);
+PJ_DECL(void) pjpidf_tuple_set_contact(pj_pool_t *pool, pjpidf_tuple *t,
+ const pj_str_t *contact);
+PJ_DECL(void) pjpidf_tuple_set_contact_prio(pj_pool_t *pool, pjpidf_tuple *t,
+ const pj_str_t *prio);
+PJ_DECL(const pj_str_t*) pjpidf_tuple_get_contact_prio(const pjpidf_tuple *t);
+
+PJ_DECL(pjpidf_note*) pjpidf_tuple_add_note(pj_pool_t *pool, pjpidf_tuple *t,
+ const pj_str_t *text);
+PJ_DECL(pjpidf_note*) pjpidf_tuple_get_first_note(pjpidf_tuple *t);
+PJ_DECL(pjpidf_note*) pjpidf_tuple_get_next_note(pjpidf_tuple *t, pjpidf_note *n);
+
+PJ_DECL(const pj_str_t*) pjpidf_tuple_get_timestamp(const pjpidf_tuple *t);
+PJ_DECL(void) pjpidf_tuple_set_timestamp(pj_pool_t *pool, pjpidf_tuple *t,
+ const pj_str_t *ts);
+PJ_DECL(void) pjpidf_tuple_set_timestamp_np( pj_pool_t*, pjpidf_tuple *t,
+ pj_str_t *ts);
+
+
+/******************************************************************************
+ * API for managing Status node.
+ *****************************************************************************/
+PJ_DECL(void) pjpidf_status_construct(pj_pool_t*, pjpidf_status*);
+PJ_DECL(pj_bool_t) pjpidf_status_is_basic_open(const pjpidf_status*);
+PJ_DECL(void) pjpidf_status_set_basic_open(pjpidf_status*, pj_bool_t);
+
+
+/**
+ * @}
+ */
+
+
+PJ_END_DECL
+
+
+#endif /* __PJSIP_SIMPLE_PIDF_H__ */
diff --git a/pjsip/include/pjsip-simple/presence.h b/pjsip/include/pjsip-simple/presence.h
new file mode 100644
index 0000000..d266baa
--- /dev/null
+++ b/pjsip/include/pjsip-simple/presence.h
@@ -0,0 +1,415 @@
+/* $Id: presence.h 3553 2011-05-05 06:14:19Z nanang $ */
+/*
+ * 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_SIMPLE_PRESENCE_H__
+#define __PJSIP_SIMPLE_PRESENCE_H__
+
+/**
+ * @file presence.h
+ * @brief SIP Extension for Presence (RFC 3856)
+ */
+#include <pjsip-simple/evsub.h>
+#include <pjsip-simple/pidf.h>
+#include <pjsip-simple/xpidf.h>
+#include <pjsip-simple/rpid.h>
+
+
+PJ_BEGIN_DECL
+
+
+/**
+ * @defgroup PJSIP_SIMPLE_PRES SIP Extension for Presence (RFC 3856)
+ * @ingroup PJSIP_SIMPLE
+ * @brief Support for SIP Extension for Presence (RFC 3856)
+ * @{
+ *
+ * This module contains the implementation of SIP Presence Extension as
+ * described in RFC 3856. It uses the SIP Event Notification framework
+ * (evsub.h) and extends the framework by implementing "presence"
+ * event package.
+ */
+
+
+
+/**
+ * Initialize the presence module and register it as endpoint module and
+ * package to the event subscription module.
+ *
+ * @param endpt The endpoint instance.
+ * @param mod_evsub The event subscription module instance.
+ *
+ * @return PJ_SUCCESS if the module is successfully
+ * initialized and registered to both endpoint
+ * and the event subscription module.
+ */
+PJ_DECL(pj_status_t) pjsip_pres_init_module(pjsip_endpoint *endpt,
+ pjsip_module *mod_evsub);
+
+
+/**
+ * Get the presence module instance.
+ *
+ * @return The presence module instance.
+ */
+PJ_DECL(pjsip_module*) pjsip_pres_instance(void);
+
+
+/**
+ * Maximum presence status info.
+ */
+#define PJSIP_PRES_STATUS_MAX_INFO 8
+
+
+/**
+ * This structure describes presence status of a presentity.
+ */
+struct pjsip_pres_status
+{
+ unsigned info_cnt; /**< Number of info in the status. */
+ struct {
+
+ pj_bool_t basic_open; /**< Basic status/availability. */
+ pjrpid_element rpid; /**< Optional RPID info. */
+
+ pj_str_t id; /**< Tuple id. */
+ pj_str_t contact; /**< Optional contact address. */
+
+ pj_xml_node *tuple_node; /**< Pointer to tuple XML node of
+ parsed PIDF body received from
+ remote agent. Only valid for
+ client subscription. If the
+ last received NOTIFY request
+ does not contain any PIDF body,
+ this valud will be set to NULL */
+
+ } info[PJSIP_PRES_STATUS_MAX_INFO]; /**< Array of info. */
+
+ pj_bool_t _is_valid; /**< Internal flag. */
+};
+
+
+/**
+ * @see pjsip_pres_status
+ */
+typedef struct pjsip_pres_status pjsip_pres_status;
+
+
+/**
+ * Create presence client subscription session.
+ *
+ * @param dlg The underlying dialog to use.
+ * @param user_cb Pointer to callbacks to receive presence subscription
+ * events.
+ * @param options Option flags. Currently only PJSIP_EVSUB_NO_EVENT_ID
+ * is recognized.
+ * @param p_evsub Pointer to receive the presence subscription
+ * session.
+ *
+ * @return PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjsip_pres_create_uac( pjsip_dialog *dlg,
+ const pjsip_evsub_user *user_cb,
+ unsigned options,
+ pjsip_evsub **p_evsub );
+
+
+/**
+ * Create presence server subscription session.
+ *
+ * @param dlg The underlying dialog to use.
+ * @param user_cb Pointer to callbacks to receive presence subscription
+ * events.
+ * @param rdata The incoming SUBSCRIBE request that creates the event
+ * subscription.
+ * @param p_evsub Pointer to receive the presence subscription
+ * session.
+ *
+ * @return PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjsip_pres_create_uas( pjsip_dialog *dlg,
+ const pjsip_evsub_user *user_cb,
+ pjsip_rx_data *rdata,
+ pjsip_evsub **p_evsub );
+
+
+/**
+ * Forcefully destroy the presence subscription. This function should only
+ * be called on special condition, such as when the subscription
+ * initialization has failed. For other conditions, application MUST terminate
+ * the subscription by sending the appropriate un(SUBSCRIBE) or NOTIFY.
+ *
+ * @param sub The presence subscription.
+ * @param notify Specify whether the state notification callback
+ * should be called.
+ *
+ * @return PJ_SUCCESS if subscription session has been destroyed.
+ */
+PJ_DECL(pj_status_t) pjsip_pres_terminate( pjsip_evsub *sub,
+ pj_bool_t notify );
+
+
+
+/**
+ * Call this function to create request to initiate presence subscription, to
+ * refresh subcription, or to request subscription termination.
+ *
+ * @param sub Client subscription instance.
+ * @param expires Subscription expiration. If the value is set to zero,
+ * this will request unsubscription.
+ * @param p_tdata Pointer to receive the request.
+ *
+ * @return PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjsip_pres_initiate( pjsip_evsub *sub,
+ pj_int32_t expires,
+ pjsip_tx_data **p_tdata);
+
+
+/**
+ * Add a list of headers to the subscription instance. The list of headers
+ * will be added to outgoing presence subscription requests.
+ *
+ * @param sub Subscription instance.
+ * @param hdr_list List of headers to be added.
+ *
+ * @return PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjsip_pres_add_header( pjsip_evsub *sub,
+ const pjsip_hdr *hdr_list );
+
+
+/**
+ * Accept the incoming subscription request by sending 2xx response to
+ * incoming SUBSCRIBE request.
+ *
+ * @param sub Server subscription instance.
+ * @param rdata The incoming subscription request message.
+ * @param st_code Status code, which MUST be final response.
+ * @param hdr_list Optional list of headers to be added in the response.
+ *
+ * @return PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjsip_pres_accept( pjsip_evsub *sub,
+ pjsip_rx_data *rdata,
+ int st_code,
+ const pjsip_hdr *hdr_list );
+
+
+
+
+/**
+ * For notifier, create NOTIFY request to subscriber, and set the state
+ * of the subscription. Application MUST set the presence status to the
+ * appropriate state (by calling #pjsip_pres_set_status()) before calling
+ * this function.
+ *
+ * @param sub The server subscription (notifier) instance.
+ * @param state New state to set.
+ * @param state_str The state string name, if state contains value other
+ * than active, pending, or terminated. Otherwise this
+ * argument is ignored.
+ * @param reason Specify reason if new state is terminated, otherwise
+ * put NULL.
+ * @param p_tdata Pointer to receive the request.
+ *
+ * @return PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjsip_pres_notify( pjsip_evsub *sub,
+ pjsip_evsub_state state,
+ const pj_str_t *state_str,
+ const pj_str_t *reason,
+ pjsip_tx_data **p_tdata);
+
+
+/**
+ * Create NOTIFY request to reflect current subscription status.
+ *
+ * @param sub Server subscription object.
+ * @param p_tdata Pointer to receive request.
+ *
+ * @return PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjsip_pres_current_notify( pjsip_evsub *sub,
+ pjsip_tx_data **p_tdata );
+
+
+
+/**
+ * Send request message that was previously created with initiate(), notify(),
+ * or current_notify(). Application may also send request created with other
+ * functions, e.g. authentication. But the request MUST be either request
+ * that creates/refresh subscription or NOTIFY request.
+ *
+ * @param sub The subscription object.
+ * @param tdata Request message to be sent.
+ *
+ * @return PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjsip_pres_send_request( pjsip_evsub *sub,
+ pjsip_tx_data *tdata );
+
+
+/**
+ * Get the presence status. Client normally would call this function
+ * after receiving NOTIFY request from server.
+ *
+ * @param sub The client or server subscription.
+ * @param status The structure to receive presence status.
+ *
+ * @return PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjsip_pres_get_status( pjsip_evsub *sub,
+ pjsip_pres_status *status );
+
+
+/**
+ * Set the presence status. This operation is only valid for server
+ * subscription. After calling this function, application would need to
+ * send NOTIFY request to client.
+ *
+ * @param sub The server subscription.
+ * @param status Status to be set.
+ *
+ * @return PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjsip_pres_set_status( pjsip_evsub *sub,
+ const pjsip_pres_status *status );
+
+
+/**
+ * This is a utility function to create PIDF message body from PJSIP
+ * presence status (pjsip_pres_status).
+ *
+ * @param pool The pool to allocate memory for the message body.
+ * @param status Presence status to be converted into PIDF message
+ * body.
+ * @param entity The entity ID, which normally is equal to the
+ * presentity ID publishing this presence info.
+ * @param p_body Pointer to receive the SIP message body.
+ *
+ * @return PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjsip_pres_create_pidf( pj_pool_t *pool,
+ const pjsip_pres_status *status,
+ const pj_str_t *entity,
+ pjsip_msg_body **p_body );
+
+
+/**
+ * This is a utility function to create X-PIDF message body from PJSIP
+ * presence status (pjsip_pres_status).
+ *
+ * @param pool The pool to allocate memory for the message body.
+ * @param status Presence status to be converted into X-PIDF message
+ * body.
+ * @param entity The entity ID, which normally is equal to the
+ * presentity ID publishing this presence info.
+ * @param p_body Pointer to receive the SIP message body.
+ *
+ * @return PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjsip_pres_create_xpidf(pj_pool_t *pool,
+ const pjsip_pres_status *status,
+ const pj_str_t *entity,
+ pjsip_msg_body **p_body );
+
+
+
+/**
+ * This is a utility function to parse PIDF body into PJSIP presence status.
+ *
+ * @param rdata The incoming SIP message containing the PIDF body.
+ * @param pool Pool to allocate memory to copy the strings into
+ * the presence status structure.
+ * @param status The presence status to be initialized.
+ *
+ * @return PJ_SUCCESS on success.
+ *
+ * @see pjsip_pres_parse_pidf2()
+ */
+PJ_DECL(pj_status_t) pjsip_pres_parse_pidf(pjsip_rx_data *rdata,
+ pj_pool_t *pool,
+ pjsip_pres_status *status);
+
+/**
+ * This is a utility function to parse PIDF body into PJSIP presence status.
+ *
+ * @param body Text body, with one extra space at the end to place
+ * NULL character temporarily during parsing.
+ * @param body_len Length of the body, not including the NULL termination
+ * character.
+ * @param pool Pool to allocate memory to copy the strings into
+ * the presence status structure.
+ * @param status The presence status to be initialized.
+ *
+ * @return PJ_SUCCESS on success.
+ *
+ * @see pjsip_pres_parse_pidf()
+ */
+PJ_DECL(pj_status_t) pjsip_pres_parse_pidf2(char *body, unsigned body_len,
+ pj_pool_t *pool,
+ pjsip_pres_status *status);
+
+
+/**
+ * This is a utility function to parse X-PIDF body into PJSIP presence status.
+ *
+ * @param rdata The incoming SIP message containing the X-PIDF body.
+ * @param pool Pool to allocate memory to copy the strings into
+ * the presence status structure.
+ * @param status The presence status to be initialized.
+ *
+ * @return PJ_SUCCESS on success.
+ *
+ * @see pjsip_pres_parse_xpidf2()
+ */
+PJ_DECL(pj_status_t) pjsip_pres_parse_xpidf(pjsip_rx_data *rdata,
+ pj_pool_t *pool,
+ pjsip_pres_status *status);
+
+
+/**
+ * This is a utility function to parse X-PIDF body into PJSIP presence status.
+ *
+ * @param body Text body, with one extra space at the end to place
+ * NULL character temporarily during parsing.
+ * @param body_len Length of the body, not including the NULL termination
+ * character.
+ * @param pool Pool to allocate memory to copy the strings into
+ * the presence status structure.
+ * @param status The presence status to be initialized.
+ *
+ * @return PJ_SUCCESS on success.
+ *
+ * @see pjsip_pres_parse_xpidf()
+ */
+PJ_DECL(pj_status_t) pjsip_pres_parse_xpidf2(char *body, unsigned body_len,
+ pj_pool_t *pool,
+ pjsip_pres_status *status);
+
+
+
+/**
+ * @}
+ */
+
+PJ_END_DECL
+
+
+#endif /* __PJSIP_SIMPLE_PRESENCE_H__ */
diff --git a/pjsip/include/pjsip-simple/publish.h b/pjsip/include/pjsip-simple/publish.h
new file mode 100644
index 0000000..5940ab7
--- /dev/null
+++ b/pjsip/include/pjsip-simple/publish.h
@@ -0,0 +1,349 @@
+/* $Id: publish.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_SIMPLE_PUBLISH_H__
+#define __PJSIP_SIMPLE_PUBLISH_H__
+
+/**
+ * @file publish.h
+ * @brief SIP Extension for Event State Publication (PUBLISH, RFC 3903)
+ */
+
+#include <pjsip/sip_util.h>
+#include <pjsip/sip_auth.h>
+
+
+PJ_BEGIN_DECL
+
+
+/**
+ @defgroup PJSIP_SIMPLE_PUBLISH SIP Event State Publication (PUBLISH, RFC 3903)
+ @ingroup PJSIP_SIMPLE
+ @brief Support for SIP Event State Publication (PUBLISH, RFC 3903)
+ @{
+
+ This module contains the implementation of Session Initiation Protocol (SIP)
+ Extension for Event State Publication (PUBLISH) as defined by RFC 3903.
+ */
+
+/**
+ * The SIP PUBLISH method constant.
+ */
+extern const pjsip_method pjsip_publish_method;
+
+
+/*****************************************************************************
+ * @defgroup PJSIP_SIMPLE_PUBLISH_CLIENT SIP Event State Publication Client
+ * @ingroup PJSIP_SIMPLE
+ * @brief Event State Publication Clien
+ * @{
+ */
+
+
+/** Expiration not specified. */
+#define PJSIP_PUBC_EXPIRATION_NOT_SPECIFIED ((pj_uint32_t)0xFFFFFFFFUL)
+
+/**
+ * Opaque declaration for client side event publication session.
+ */
+typedef struct pjsip_publishc pjsip_publishc;
+
+
+/**
+ * Client publication options. Application should initialize this structure
+ * with its default values by calling #pjsip_publishc_opt_default()
+ */
+typedef struct pjsip_publishc_opt
+{
+ /**
+ * Specify whether the client publication session should queue the
+ * PUBLISH request should there be another PUBLISH transaction still
+ * pending. If this is set to false, the client will return error
+ * on the PUBLISH request if there is another PUBLISH transaction still
+ * in progress.
+ *
+ * Default: PJSIP_PUBLISHC_QUEUE_REQUEST
+ */
+ pj_bool_t queue_request;
+
+} pjsip_publishc_opt;
+
+
+/** Structure to hold parameters when calling application's callback.
+ * The application's callback is called when the client publication process
+ * has finished.
+ */
+struct pjsip_publishc_cbparam
+{
+ pjsip_publishc *pubc; /**< Client publication structure. */
+ void *token; /**< Arbitrary token. */
+ pj_status_t status; /**< Error status. */
+ int code; /**< SIP status code received. */
+ pj_str_t reason; /**< SIP reason phrase received. */
+ pjsip_rx_data *rdata; /**< The complete received response. */
+ int expiration;/**< Next expiration interval. If the
+ value is -1, it means the session
+ will not renew itself. */
+};
+
+
+/** Type declaration for callback to receive publication result. */
+typedef void pjsip_publishc_cb(struct pjsip_publishc_cbparam *param);
+
+
+/**
+ * Initialize client publication session option with default values.
+ *
+ * @param opt The option.
+ */
+PJ_DECL(void) pjsip_publishc_opt_default(pjsip_publishc_opt *opt);
+
+
+/**
+ * Initialize client publication module.
+ *
+ * @param endpt SIP endpoint.
+ *
+ * @return PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjsip_publishc_init_module(pjsip_endpoint *endpt);
+
+
+/**
+ * Create client publication structure.
+ *
+ * @param endpt Endpoint, used to allocate pool from.
+ * @param opt Options, or NULL to specify default options.
+ * @param token Opaque data to be associated with the client publication.
+ * @param cb Pointer to callback function to receive publication status.
+ * @param p_pubc Pointer to receive client publication structure.
+ *
+ * @return PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjsip_publishc_create( pjsip_endpoint *endpt,
+ const pjsip_publishc_opt *opt,
+ void *token,
+ pjsip_publishc_cb *cb,
+ pjsip_publishc **p_pubc);
+
+
+/**
+ * Destroy client publication structure. If a publication transaction is
+ * in progress, then the structure will be deleted only after a final response
+ * has been received, and in this case, the callback won't be called.
+ *
+ * @param pubc The client publication structure.
+ *
+ * @return PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjsip_publishc_destroy(pjsip_publishc *pubc);
+
+
+
+/**
+ * Get the memory pool associated with a publication client session.
+ *
+ * @param pubc The client publication structure.
+ * @return pool handle.
+ */
+PJ_DECL(pj_pool_t*) pjsip_publishc_get_pool(pjsip_publishc *pubc);
+
+
+/**
+ * Initialize client publication structure with various information needed to
+ * perform the publication.
+ *
+ * @param pubc The client publication structure.
+ * @param event The Event identification (e.g. "presence").
+ * @param target_uri The URI of the presentity which the which the status
+ * is being published.
+ * @param from_uri The URI of the endpoint who sends the event
+ * publication. Normally the value would be the same as
+ * target_uri.
+ * @param to_uri The URI to be put in To header. Normally the value
+ * would be the same as target_uri.
+ * @param expires The default expiration of the event publication.
+ * If the value PJSIP_PUBC_EXPIRATION_NOT_SPECIFIED is
+ * given, then no default expiration will be applied.
+ *
+ * @return PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjsip_publishc_init(pjsip_publishc *pubc,
+ const pj_str_t *event,
+ const pj_str_t *target_uri,
+ const pj_str_t *from_uri,
+ const pj_str_t *to_uri,
+ pj_uint32_t expires);
+
+
+/**
+ * Set authentication credentials to use by this publication.
+ *
+ * @param pubc The publication structure.
+ * @param count Number of credentials in the array.
+ * @param c Array of credentials.
+ *
+ * @return PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjsip_publishc_set_credentials(pjsip_publishc *pubc,
+ int count,
+ const pjsip_cred_info c[]);
+
+/**
+ * Set route set to be used for outgoing requests.
+ *
+ * @param pubc The client publication structure.
+ * @param rs List containing Route headers.
+ *
+ * @return PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjsip_publishc_set_route_set(pjsip_publishc *pubc,
+ const pjsip_route_hdr *rs);
+
+
+/**
+ * Set list of headers to be added to each PUBLISH request generated by
+ * the client publication session. Note that application can also add
+ * the headers to the request after calling #pjsip_publishc_publish()
+ * or #pjsip_publishc_unpublish(), but the benefit of this function is
+ * the headers will also be added to requests generated internally by
+ * the session, such as during session renewal/refresh.
+ *
+ * Note that calling this function will clear the previously added list
+ * of headers.
+ *
+ * @param pubc The client publication structure.
+ * @param hdr_list The list of headers.
+ *
+ * @return PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjsip_publishc_set_headers(pjsip_publishc *pubc,
+ const pjsip_hdr *hdr_list);
+
+/**
+ * Set the "sent-by" field of the Via header for outgoing requests.
+ *
+ * @param pubc The client publication structure.
+ * @param via_addr Set via_addr to use for the Via header or NULL to use
+ * the transport's published name.
+ * @param via_tp via_addr will only be used if we are using via_tp
+ * transport.
+ *
+ * @return PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjsip_publishc_set_via_sent_by(pjsip_publishc *pubc,
+ pjsip_host_port *via_addr,
+ pjsip_transport *via_tp);
+
+
+/**
+ * Create PUBLISH request for the specified client publication structure.
+ * Application can use this function to both create initial publication
+ * or to modify existing publication.
+ *
+ * After the PUBLISH request is created, application MUST fill in the
+ * body part of the request with the appropriate content for the Event
+ * being published.
+ *
+ * Note that publication refresh are handled automatically by the session
+ * (as long as auto_refresh argument below is non-zero), and application
+ * should not use this function to perform publication refresh.
+ *
+ * @param pubc The client publication session.
+ * @param auto_refresh If non zero, the library will automatically
+ * refresh the next publication until application
+ * unpublish.
+ * @param p_tdata Pointer to receive the PUBLISH request. Note that
+ * the request DOES NOT have a message body.
+ *
+ * @return PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjsip_publishc_publish(pjsip_publishc *pubc,
+ pj_bool_t auto_refresh,
+ pjsip_tx_data **p_tdata);
+
+
+/**
+ * Create PUBLISH request to unpublish the current client publication.
+ *
+ * @param pubc The client publication structure.
+ * @param p_tdata Pointer to receive the PUBLISH request.
+ *
+ * @return PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjsip_publishc_unpublish(pjsip_publishc *pubc,
+ pjsip_tx_data **p_tdata);
+
+
+/**
+ * Update the client publication expiration value. Note that this DOES NOT
+ * automatically send outgoing PUBLISH request to update the publication
+ * session. If application wants to do this, then it must construct a
+ * PUBLISH request and send it to the server.
+ *
+ * @param pubc The client publication structure.
+ * @param expires The new expires value.
+ *
+ * @return PU_SUCCESS on successfull.
+ */
+PJ_DECL(pj_status_t) pjsip_publishc_update_expires(pjsip_publishc *pubc,
+ pj_uint32_t expires );
+
+
+/**
+ * Sends outgoing PUBLISH request. The process will complete asynchronously,
+ * and application will be notified via the callback when the process
+ * completes.
+ *
+ * If the session has another PUBLISH request outstanding, the behavior
+ * depends on whether request queueing is enabled in the session (this was
+ * set by setting \a queue_request field of #pjsip_publishc_opt to true
+ * when calling #pjsip_publishc_create(). Default is true). If request
+ * queueing is enabled, the request will be queued and the function will
+ * return PJ_EPENDING. One the outstanding request is complete, the queued
+ * request will be sent automatically. If request queueing is disabled, the
+ * function will reject the request and return PJ_EBUSY.
+ *
+ * @param pubc The client publication structure.
+ * @param tdata Transmit data.
+ *
+ * @return - PJ_SUCCESS on success, or
+ * - PJ_EPENDING if request is queued, or
+ * - PJ_EBUSY if request is rejected because another PUBLISH
+ * request is in progress, or
+ * - other status code to indicate the error.
+ */
+PJ_DECL(pj_status_t) pjsip_publishc_send(pjsip_publishc *pubc,
+ pjsip_tx_data *tdata);
+
+
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+PJ_END_DECL
+
+
+#endif /* __PJSIP_SIMPLE_PUBLISH_H__ */
+
diff --git a/pjsip/include/pjsip-simple/rpid.h b/pjsip/include/pjsip-simple/rpid.h
new file mode 100644
index 0000000..1ee8982
--- /dev/null
+++ b/pjsip/include/pjsip-simple/rpid.h
@@ -0,0 +1,149 @@
+/* $Id: rpid.h 3553 2011-05-05 06:14:19Z nanang $ */
+/*
+ * 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_SIMPLE_RPID_H__
+#define __PJSIP_SIMPLE_RPID_H__
+
+/**
+ * @file rpid.h
+ * @brief RPID: Rich Presence Extensions to the PIDF (RFC 4480)
+ */
+#include <pjsip-simple/types.h>
+#include <pjsip-simple/pidf.h>
+
+PJ_BEGIN_DECL
+
+
+/**
+ * @defgroup PJSIP_SIMPLE_RPID RPID/Rich Presence Extensions to PIDF (RFC 4480)
+ * @ingroup PJSIP_SIMPLE
+ * @brief RPID/Rich Presence Extensions to PIDF (RFC 4480)
+ * @{
+ *
+ * This file provides tools for managing subset of RPID elements into
+ * PIDF document.
+ */
+
+/**
+ * This enumeration describes subset of standard activities as
+ * described by RFC 4880, RPID: Rich Presence Extensions to the
+ * Presence Information Data Format (PIDF).
+ */
+typedef enum pjrpid_activity
+{
+ /** Activity is unknown. The activity would then be conceived
+ * in the "note" field.
+ */
+ PJRPID_ACTIVITY_UNKNOWN,
+
+ /** The person is away */
+ PJRPID_ACTIVITY_AWAY,
+
+ /** The person is busy */
+ PJRPID_ACTIVITY_BUSY
+
+} pjrpid_activity;
+
+
+/**
+ * This enumeration describes types of RPID element.
+ */
+typedef enum pjrpid_element_type
+{
+ /** RPID <person> element */
+ PJRPID_ELEMENT_TYPE_PERSON
+
+} pjrpid_element_type;
+
+
+/**
+ * This structure describes person information in RPID document.
+ */
+typedef struct pjrpid_element
+{
+ /** Element type. */
+ pjrpid_element_type type;
+
+ /** Optional id to set on the element. */
+ pj_str_t id;
+
+ /** Activity type. */
+ pjrpid_activity activity;
+
+ /** Optional text describing the person/element. */
+ pj_str_t note;
+
+} pjrpid_element;
+
+
+/**
+ * Duplicate RPID element.
+ *
+ * @param pool Pool.
+ * @param dst Destination structure.
+ * @param src Source structure.
+ */
+PJ_DECL(void) pjrpid_element_dup(pj_pool_t *pool, pjrpid_element *dst,
+ const pjrpid_element *src);
+
+
+/**
+ * Add RPID element information into existing PIDF document. This will also
+ * add the appropriate XML namespace attributes into the presence's XML
+ * node, if the attributes are not already present, and also a <note> element
+ * to the first <tuple> element of the PIDF document.
+ *
+ * @param pres The PIDF presence document.
+ * @param pool Pool.
+ * @param options Currently unused, and must be zero.
+ * @param elem RPID element information to be added into the PIDF
+ * document.
+ *
+ * @return PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjrpid_add_element(pjpidf_pres *pres,
+ pj_pool_t *pool,
+ unsigned options,
+ const pjrpid_element *elem);
+
+/**
+ * Get RPID element information from PIDF document, if any.
+ *
+ * @param pres The PIDF document containing RPID elements.
+ * @param pool Pool to duplicate the information.
+ * @param elem Structure to receive the element information.
+ *
+ * @return PJ_SUCCESS if the document does contain RPID element
+ * and the information has been parsed successfully.
+ */
+PJ_DECL(pj_status_t) pjrpid_get_element(const pjpidf_pres *pres,
+ pj_pool_t *pool,
+ pjrpid_element *elem);
+
+
+/**
+ * @}
+ */
+
+
+PJ_END_DECL
+
+
+#endif /* __PJSIP_SIMPLE_RPID_H__ */
+
diff --git a/pjsip/include/pjsip-simple/types.h b/pjsip/include/pjsip-simple/types.h
new file mode 100644
index 0000000..74eee03
--- /dev/null
+++ b/pjsip/include/pjsip-simple/types.h
@@ -0,0 +1,31 @@
+/* $Id: types.h 3553 2011-05-05 06:14:19Z nanang $ */
+/*
+ * 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_SIMPLE_TYPES_H__
+#define __PJSIP_SIMPLE_TYPES_H__
+
+#include <pjsip/sip_types.h>
+
+
+#define PJSIP_EVSUB_POOL_LEN 4000
+#define PJSIP_EVSUB_POOL_INC 4000
+
+
+#endif /* __PJSIP_SIMPLE_TYPES_H__ */
+
diff --git a/pjsip/include/pjsip-simple/xpidf.h b/pjsip/include/pjsip-simple/xpidf.h
new file mode 100644
index 0000000..911a429
--- /dev/null
+++ b/pjsip/include/pjsip-simple/xpidf.h
@@ -0,0 +1,135 @@
+/* $Id: xpidf.h 3553 2011-05-05 06:14:19Z nanang $ */
+/*
+ * 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_SIMPLE_XPIDF_H__
+#define __PJSIP_SIMPLE_XPIDF_H__
+
+/**
+ * @file xpidf.h
+ * @brief XPIDF/Presence Information Data Format
+ */
+#include <pjsip-simple/types.h>
+#include <pjlib-util/xml.h>
+
+PJ_BEGIN_DECL
+
+/**
+ * @defgroup PJSIP_SIMPLE_XPIDF XPIDF/Presence Information Data Format
+ * @ingroup PJSIP_SIMPLE
+ * @brief Support for XPIDF/Presence Information Data Format
+ * @{
+ *
+ * This is an old presence data format as described in:
+ * draft-rosenberg-impp-pidf-00.txt.
+ *
+ * We won't support this format extensively here, as it seems there's not
+ * too many implementations support this anymore, as it shouldn't.
+ */
+
+/** Type definitions for XPIDF root document. */
+typedef pj_xml_node pjxpidf_pres;
+
+
+/**
+ * Create a new XPIDF document.
+ *
+ * @param pool Pool.
+ * @param uri URI to set in the XPIDF document.
+ *
+ * @return XPIDF document.
+ */
+PJ_DECL(pjxpidf_pres*) pjxpidf_create(pj_pool_t *pool, const pj_str_t *uri);
+
+
+/**
+ * Parse XPIDF document.
+ *
+ * @param pool Pool.
+ * @param text Input text.
+ * @param len Length of input text.
+ *
+ * @return XPIDF document.
+ */
+PJ_DECL(pjxpidf_pres*) pjxpidf_parse(pj_pool_t *pool, char *text, pj_size_t len);
+
+
+/**
+ * Print XPIDF document.
+ *
+ * @param pres The XPIDF document to print.
+ * @param text Buffer to place the output.
+ * @param len Length of the buffer.
+ *
+ * @return The length printed.
+ */
+PJ_DECL(int) pjxpidf_print( pjxpidf_pres *pres, char *text, pj_size_t len);
+
+
+/**
+ * Get URI in the XPIDF document
+ *
+ * @param pres XPIDF document
+ *
+ * @return The URI, or an empty string.
+ */
+PJ_DECL(pj_str_t*) pjxpidf_get_uri(pjxpidf_pres *pres);
+
+
+/**
+ * Set the URI of the XPIDF document.
+ *
+ * @param pool Pool.
+ * @param pres The XPIDF document.
+ * @param uri URI to set in the XPIDF document.
+ *
+ * @return Zero on success.
+ */
+PJ_DECL(pj_status_t) pjxpidf_set_uri(pj_pool_t *pool, pjxpidf_pres *pres,
+ const pj_str_t *uri);
+
+
+/**
+ * Get presence status in the XPIDF document.
+ *
+ * @param pres XPIDF document.
+ *
+ * @return True to indicate the contact is online.
+ */
+PJ_DECL(pj_bool_t) pjxpidf_get_status(pjxpidf_pres *pres);
+
+
+/**
+ * Set presence status in the XPIDF document.
+ *
+ * @param pres XPIDF document.
+ * @param status Status to set, True for online, False for offline.
+ *
+ * @return Zero on success.
+ */
+PJ_DECL(pj_status_t) pjxpidf_set_status(pjxpidf_pres *pres, pj_bool_t status);
+
+
+/**
+ * @}
+ */
+
+PJ_END_DECL
+
+
+#endif /* __PJSIP_SIMPLE_XPIDF_H__ */
diff --git a/pjsip/include/pjsip-ua/sip_100rel.h b/pjsip/include/pjsip-ua/sip_100rel.h
new file mode 100644
index 0000000..1b01d24
--- /dev/null
+++ b/pjsip/include/pjsip-ua/sip_100rel.h
@@ -0,0 +1,245 @@
+/* $Id: sip_100rel.h 3553 2011-05-05 06:14:19Z nanang $ */
+/*
+ * 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 __SIP_100REL_H__
+#define __SIP_100REL_H__
+
+/**
+ * @file sip_100rel.h
+ * @brief PRACK (Reliability of Provisional Responses)
+ */
+
+
+#include <pjsip-ua/sip_inv.h>
+
+
+/**
+ * @defgroup PJSIP_100REL 100rel/PRACK - Reliability of Provisional Responses
+ * @ingroup PJSIP_HIGH_UA
+ * @brief PRACK - Reliability of Provisional Responses
+ * @{
+ *
+ * This module provides management of Reliability of Provisional Responses
+ * (\a 100rel and \a PRACK), as described in RFC 3262.
+ *
+ * Other than the #pjsip_100rel_init_module() function, the 100rel API
+ * exported by this module are not intended to be used by application, but
+ * rather they will be invoked by the \ref PJSIP_INV.
+ *
+ * \section pjsip_100rel_using Using Reliable Provisional Response
+ *
+ * \subsection pjsip_100rel_init Initializing 100rel Module
+ *
+ * Application must explicitly initialize 100rel module by calling
+ * #pjsip_100rel_init_module() in application initialization function.
+ *
+ * Once the 100rel module is initialized, it will register \a PRACK method
+ * in \a Allow header, and \a 100rel tag in \a Supported header.
+ *
+ * \subsection pjsip_100rel_sess Using 100rel in a Session
+ *
+ * For UAC, \a 100rel support will be enabled in the session if \a 100rel
+ * support is enabled in the library (default is yes).
+ * Outgoing INVITE request will include \a 100rel tag in \a Supported
+ * header and \a PRACK method in \a Allow header. When callee endpoint
+ * sends reliable provisional responses, the UAC will automatically send
+ * \a PRACK request to acknowledge the response. If callee endpoint doesn't
+ * send reliable provisional response, the response will be handled using
+ * normal, non-100rel procedure (that is, \a PRACK will not be sent).
+ *
+ * If the UAC wants to <b>mandate</b> \a 100rel support, it can specify
+ * #PJSIP_INV_REQUIRE_100REL in the \a options argument when calling
+ * #pjsip_inv_create_uac(). In this case, PJSIP will add \a 100rel tag
+ * in the \a Require header of the outgoing INVITE request.
+ *
+ * For UAS, if it wants to support \a 100rel but not to mandate it,
+ * it must specify #PJSIP_INV_SUPPORT_100REL flag in the \a options
+ * argument when calling #pjsip_inv_verify_request(), and pass the same
+ * \a options variable when calling #pjsip_inv_verify_request. If UAC had
+ * specified \a 100rel in it's list of extensions in \a Require header,
+ * the UAS will send provisional responses reliably. If UAC only listed
+ * \a 100rel in its \a Supported header but not in \a Require header,
+ * or if UAC does not list \a 100rel support at all, the UAS WILL NOT
+ * send provisional responses reliably.
+ * The snippet below can be used to accomplish this task:
+ *
+ * \verbatim
+ unsigned options = 0;
+
+ options |= PJSIP_INV_SUPPORT_100REL;
+
+ status = pjsip_inv_verify_request(rdata, &options, answer, NULL,
+ endpt, &resp);
+ if (status != PJ_SUCCESS) {
+ // INVITE request cannot be handled.
+ // Reject the request with the response in resp.
+ ...
+ return;
+ }
+
+ // Create UAS dialog, populate Contact header, etc.
+ ...
+
+ // Create UAS invite session
+ status = pjsip_inv_create_uas( dlg, rdata, answer, options, &inv);
+
+ ..
+
+ \endverbatim
+ *
+ * For another requirement, if UAS wants to <b>mandate</b> \a 100rel support,
+ * it can specify #PJSIP_INV_REQUIRE_100REL flag when calling
+ * #pjsip_inv_verify_request(), and pass the \a options when calling
+ * #pjsip_inv_verify_request. In this case,
+ * \a 100rel extension will be used if UAC specifies \a 100rel in its
+ * \a Supported header. If UAC does not list \a 100rel in \a Supported header,
+ * the incoming INVITE request will be rejected with 421 (Extension Required)
+ * response. For the sample code, it should be identical to the snippet
+ * above, except that application must specify #PJSIP_INV_REQUIRE_100REL
+ * flag in the \a options instead of #PJSIP_INV_SUPPORT_100REL.
+ *
+ * For yet another requirement, if UAS <b>does not</b> want to support
+ * \a 100rel extension, it can reject incoming INVITE request with
+ * 420 (Bad Extension) response whenever incoming INVITE request has
+ * \a 100rel tag in its \a Require header. This can be done by specifying
+ * zero as the \a options when calling #pjsip_inv_verify_request().
+ */
+
+PJ_BEGIN_DECL
+
+
+/**
+ * PRACK method constant.
+ * @see pjsip_get_prack_method()
+ */
+PJ_DECL_DATA(const pjsip_method) pjsip_prack_method;
+
+
+/**
+ * Get #pjsip_invite_method constant.
+ */
+PJ_DECL(const pjsip_method*) pjsip_get_prack_method(void);
+
+
+/**
+ * Initialize 100rel module. This function must be called once during
+ * application initialization, to register 100rel module to SIP endpoint.
+ *
+ * @param endpt The SIP endpoint instance.
+ *
+ * @return PJ_SUCCESS if module is successfully initialized.
+ */
+PJ_DECL(pj_status_t) pjsip_100rel_init_module(pjsip_endpoint *endpt);
+
+
+/**
+ * Add 100rel support to the specified invite session. This function will
+ * be called internally by the invite session if it detects that the
+ * session needs 100rel support.
+ *
+ * @param inv The invite session.
+ *
+ * @return PJ_SUCCESS on successful.
+ */
+PJ_DECL(pj_status_t) pjsip_100rel_attach(pjsip_inv_session *inv);
+
+
+/**
+ * Check if incoming response has reliable provisional response feature.
+ *
+ * @param rdata Receive data buffer containing the response.
+ *
+ * @return PJ_TRUE if the provisional response is reliable.
+ */
+PJ_DECL(pj_bool_t) pjsip_100rel_is_reliable(pjsip_rx_data *rdata);
+
+
+/**
+ * Create PRACK request for the incoming reliable provisional response.
+ * Note that PRACK request MUST be sent using #pjsip_100rel_send_prack().
+ *
+ * @param inv The invite session.
+ * @param rdata The incoming reliable provisional response.
+ * @param p_tdata Upon return, it will be initialized with the
+ * PRACK request.
+ *
+ * @return PJ_SUCCESS on successful.
+ */
+PJ_DECL(pj_status_t) pjsip_100rel_create_prack(pjsip_inv_session *inv,
+ pjsip_rx_data *rdata,
+ pjsip_tx_data **p_tdata);
+
+/**
+ * Send PRACK request.
+ *
+ * @param inv The invite session.
+ * @param tdata The PRACK request.
+ *
+ * @return PJ_SUCCESS on successful.
+ */
+PJ_DECL(pj_status_t) pjsip_100rel_send_prack(pjsip_inv_session *inv,
+ pjsip_tx_data *tdata);
+
+
+/**
+ * Handle incoming PRACK request.
+ *
+ * @param inv The invite session.
+ * @param rdata Incoming PRACK request.
+ *
+ * @return PJ_SUCCESS on successful.
+ */
+PJ_DECL(pj_status_t) pjsip_100rel_on_rx_prack(pjsip_inv_session *inv,
+ pjsip_rx_data *rdata);
+
+
+/**
+ * Transmit INVITE response (provisional or final) reliably according to
+ * 100rel specification. The 100rel module will take care of retransmitting
+ * or enqueueing the response according to the current state of the
+ * reliable response processing. This function will be called internally
+ * by invite session.
+ *
+ * @param inv The invite session.
+ * @param tdata The INVITE response.
+ *
+ * @return PJ_SUCCESS on successful.
+ */
+PJ_DECL(pj_status_t) pjsip_100rel_tx_response(pjsip_inv_session *inv,
+ pjsip_tx_data *tdata);
+
+
+/**
+ * Notify 100rel module that the invite session has been disconnected.
+ *
+ * @param inv The invite session.
+ *
+ * @return PJ_SUCCESS on successful.
+ */
+PJ_DECL(pj_status_t) pjsip_100rel_end_session(pjsip_inv_session *inv);
+
+
+PJ_END_DECL
+
+/**
+ * @}
+ */
+
+
+#endif /* __SIP_100REL_H__ */
diff --git a/pjsip/include/pjsip-ua/sip_inv.h b/pjsip/include/pjsip-ua/sip_inv.h
new file mode 100644
index 0000000..f9f38ca
--- /dev/null
+++ b/pjsip/include/pjsip-ua/sip_inv.h
@@ -0,0 +1,963 @@
+/* $Id: sip_inv.h 3841 2011-10-24 09:28:13Z 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 __SIP_INVITE_SESSION_H__
+#define __SIP_INVITE_SESSION_H__
+
+/**
+ * @file sip_inv.h
+ * @brief INVITE sessions
+ */
+
+
+#include <pjsip/sip_dialog.h>
+#include <pjmedia/sdp_neg.h>
+
+
+/**
+ * @defgroup PJSIP_HIGH_UA User Agent Library
+ * @brief Mid-level User Agent Library.
+ *
+ * This is the high level user agent library, which consists of:
+ * - @ref PJSIP_INV, to encapsulate INVITE sessions and SDP
+ * negotiation in the session,
+ * - @ref PJSUA_REGC, high level client registration API, and
+ * - @ref PJSUA_XFER.
+ *
+ * More detailed information is explained in
+ * <A HREF="/docs.htm">PJSIP Developer's Guide</A>
+ * PDF document, and readers are encouraged to read the document to
+ * get the concept behind dialog, dialog usages, and INVITE sessions.
+ *
+ * The User Agent Library is implemented in <b>pjsip-ua</b> static
+ * library.
+ */
+
+/**
+ * @defgroup PJSIP_INV INVITE Session
+ * @ingroup PJSIP_HIGH_UA
+ * @brief Provides INVITE session management.
+ * @{
+ *
+ * The INVITE session uses the @ref PJSIP_DIALOG framework to manage
+ * the underlying dialog, and is one type of usages that can use
+ * a particular dialog instance (other usages are event subscription,
+ * discussed in @ref PJSIP_EVENT_NOT). The INVITE session manages
+ * the life-time of the session, and also manages the SDP negotiation.
+ *
+ * Application must link with <b>pjsip-ua</b> static library to use this API.
+ *
+ * More detailed information is explained in
+ * <A HREF="/docs.htm">PJSIP Developer's Guide</A>
+ * PDF document, and readers are encouraged to read the document to
+ * get the concept behind dialog, dialog usages, and INVITE sessions.
+ *
+ * The INVITE session does NOT manage media. If application wants to
+ * use API that encapsulates both signaling and media in a very easy
+ * to use API, it can use @ref PJSUA_LIB for this purpose.
+ */
+
+PJ_BEGIN_DECL
+
+
+/**
+ * @see pjsip_inv_session
+ */
+typedef struct pjsip_inv_session pjsip_inv_session;
+
+
+/**
+ * This enumeration describes invite session state.
+ */
+typedef enum pjsip_inv_state
+{
+ PJSIP_INV_STATE_NULL, /**< Before INVITE is sent or received */
+ PJSIP_INV_STATE_CALLING, /**< After INVITE is sent */
+ PJSIP_INV_STATE_INCOMING, /**< After INVITE is received. */
+ PJSIP_INV_STATE_EARLY, /**< After response with To tag. */
+ PJSIP_INV_STATE_CONNECTING, /**< After 2xx is sent/received. */
+ PJSIP_INV_STATE_CONFIRMED, /**< After ACK is sent/received. */
+ PJSIP_INV_STATE_DISCONNECTED, /**< Session is terminated. */
+} pjsip_inv_state;
+
+/**
+ * This structure contains callbacks to be registered by application to
+ * receieve notifications from the framework about various events in
+ * the invite session.
+ */
+typedef struct pjsip_inv_callback
+{
+ /**
+ * This callback is called when the invite sesion state has changed.
+ * Application should inspect the session state (inv_sess->state) to get
+ * the current state of the session.
+ *
+ * This callback is mandatory.
+ *
+ * @param inv The invite session.
+ * @param e The event which has caused the invite session's
+ * state to change.
+ */
+ void (*on_state_changed)(pjsip_inv_session *inv, pjsip_event *e);
+
+ /**
+ * This callback is called when the invite usage module has created
+ * a new dialog and invite because of forked outgoing request.
+ *
+ * This callback is mandatory.
+ *
+ * @param inv The new invite session.
+ * @param e The event which has caused the dialog to fork.
+ * The type of this event can be either
+ * PJSIP_EVENT_RX_MSG or PJSIP_EVENT_RX_200_MSG.
+ */
+ void (*on_new_session)(pjsip_inv_session *inv, pjsip_event *e);
+
+ /**
+ * This callback is called whenever any transactions within the session
+ * has changed their state. Application MAY implement this callback,
+ * e.g. to monitor the progress of an outgoing request, or to send
+ * response to unhandled incoming request (such as INFO).
+ *
+ * This callback is optional.
+ *
+ * @param inv The invite session.
+ * @param tsx The transaction, which state has changed.
+ * @param e The event which has caused the transation state's
+ * to change.
+ */
+ void (*on_tsx_state_changed)(pjsip_inv_session *inv,
+ pjsip_transaction *tsx,
+ pjsip_event *e);
+
+ /**
+ * This callback is called when the invite session has received
+ * new offer from peer. Application can inspect the remote offer
+ * in "offer", and set the SDP answer with #pjsip_inv_set_sdp_answer().
+ * When the application sends a SIP message to send the answer,
+ * this SDP answer will be negotiated with the offer, and the result
+ * will be sent with the SIP message.
+ *
+ * @param inv The invite session.
+ * @param offer Remote offer.
+ */
+ void (*on_rx_offer)(pjsip_inv_session *inv,
+ const pjmedia_sdp_session *offer);
+
+ /**
+ * This callback is optional, and it is used to ask the application
+ * to create a fresh offer, when the invite session has received
+ * re-INVITE without offer. This offer then will be sent in the
+ * 200/OK response to the re-INVITE request.
+ *
+ * If application doesn't implement this callback, the invite session
+ * will send the currently active SDP as the offer.
+ *
+ * @param inv The invite session.
+ * @param p_offer Pointer to receive the SDP offer created by
+ * application.
+ */
+ void (*on_create_offer)(pjsip_inv_session *inv,
+ pjmedia_sdp_session **p_offer);
+
+ /**
+ * This callback is called after SDP offer/answer session has completed.
+ * The status argument specifies the status of the offer/answer,
+ * as returned by pjmedia_sdp_neg_negotiate().
+ *
+ * This callback is optional (from the point of view of the framework),
+ * but all useful applications normally need to implement this callback.
+ *
+ * @param inv The invite session.
+ * @param status The negotiation status.
+ */
+ void (*on_media_update)(pjsip_inv_session *inv_ses,
+ pj_status_t status);
+
+ /**
+ * This callback is called when the framework needs to send
+ * ACK request after it receives incoming 2xx response for
+ * INVITE. It allows application to manually handle the
+ * transmission of ACK request, which is required by some 3PCC
+ * scenarios. If this callback is not implemented, the framework
+ * will handle the ACK transmission automatically.
+ *
+ * When this callback is overridden, application may delay the
+ * sending of the ACK request (for example, when it needs to
+ * wait for answer from the other call leg, in 3PCC scenarios).
+ *
+ * Application creates the ACK request
+ *
+ * Once it has sent the ACK request, the framework will keep
+ * this ACK request in the cache. Subsequent receipt of 2xx response
+ * will not cause this callback to be called, and instead automatic
+ * retransmission of this ACK request from the cache will be done
+ * by the framework.
+ *
+ * This callback is optional.
+ */
+ void (*on_send_ack)(pjsip_inv_session *inv, pjsip_rx_data *rdata);
+
+ /**
+ * This callback is called when the session is about to resend the
+ * INVITE request to the specified target, following the previously
+ * received redirection response.
+ *
+ * Application may accept the redirection to the specified target
+ * (the default behavior if this callback is implemented), reject
+ * this target only and make the session continue to try the next
+ * target in the list if such target exists, stop the whole
+ * redirection process altogether and cause the session to be
+ * disconnected, or defer the decision to ask for user confirmation.
+ *
+ * This callback is optional. If this callback is not implemented,
+ * the default behavior is to NOT follow the redirection response.
+ *
+ * @param inv The invite session.
+ * @param target The current target to be tried.
+ * @param e The event that caused this callback to be called.
+ * This could be the receipt of 3xx response, or
+ * 4xx/5xx response received for the INVITE sent to
+ * subsequent targets, or NULL if this callback is
+ * called from within #pjsip_inv_process_redirect()
+ * context.
+ *
+ * @return Action to be performed for the target. Set this
+ * parameter to one of the value below:
+ * - PJSIP_REDIRECT_ACCEPT: immediately accept the
+ * redirection to this target. When set, the
+ * session will immediately resend INVITE request
+ * to the target after this callback returns.
+ * - PJSIP_REDIRECT_REJECT: immediately reject this
+ * target. The session will continue retrying with
+ * next target if present, or disconnect the call
+ * if there is no more target to try.
+ * - PJSIP_REDIRECT_STOP: stop the whole redirection
+ * process and immediately disconnect the call. The
+ * on_state_changed() callback will be called with
+ * PJSIP_INV_STATE_DISCONNECTED state immediately
+ * after this callback returns.
+ * - PJSIP_REDIRECT_PENDING: set to this value if
+ * no decision can be made immediately (for example
+ * to request confirmation from user). Application
+ * then MUST call #pjsip_inv_process_redirect()
+ * to either accept or reject the redirection upon
+ * getting user decision.
+ */
+ pjsip_redirect_op (*on_redirected)(pjsip_inv_session *inv,
+ const pjsip_uri *target,
+ const pjsip_event *e);
+
+} pjsip_inv_callback;
+
+
+
+/**
+ * This enumeration shows various options that can be applied to a session.
+ * The bitmask combination of these options need to be specified when
+ * creating a session. After the dialog is established (including early),
+ * the options member of #pjsip_inv_session shows which capabilities are
+ * common in both endpoints.
+ */
+enum pjsip_inv_option
+{
+ /**
+ * Indicate support for reliable provisional response extension
+ */
+ PJSIP_INV_SUPPORT_100REL = 1,
+
+ /**
+ * Indicate support for session timer extension.
+ */
+ PJSIP_INV_SUPPORT_TIMER = 2,
+
+ /**
+ * Indicate support for UPDATE method. This is automatically implied
+ * when creating outgoing dialog. After the dialog is established,
+ * the options member of #pjsip_inv_session shows whether peer supports
+ * this method as well.
+ */
+ PJSIP_INV_SUPPORT_UPDATE = 4,
+
+ /**
+ * Indicate support for ICE
+ */
+ PJSIP_INV_SUPPORT_ICE = 8,
+
+ /**
+ * Require ICE support.
+ */
+ PJSIP_INV_REQUIRE_ICE = 16,
+
+ /**
+ * Require reliable provisional response extension.
+ */
+ PJSIP_INV_REQUIRE_100REL = 32,
+
+ /**
+ * Require session timer extension.
+ */
+ PJSIP_INV_REQUIRE_TIMER = 64,
+
+ /**
+ * Session timer extension will always be used even when peer doesn't
+ * support/want session timer.
+ */
+ PJSIP_INV_ALWAYS_USE_TIMER = 128
+
+};
+
+/* Forward declaration of Session Timers */
+struct pjsip_timer;
+
+/**
+ * This structure describes the invite session.
+ *
+ * Note regarding the invite session's pools. The inv_sess used to have
+ * only one pool, which is just a pointer to the dialog's pool. Ticket
+ * http://trac.pjsip.org/repos/ticket/877 has found that the memory
+ * usage will grow considerably everytime re-INVITE or UPDATE is
+ * performed.
+ *
+ * Ticket #877 then created two more memory pools for the inv_sess, so
+ * now we have three memory pools:
+ * - pool: to be used to allocate long term data for the session
+ * - pool_prov and pool_active: this is a flip-flop pools to be used
+ * interchangably during re-INVITE and UPDATE. pool_prov is
+ * "provisional" pool, used to allocate SDP offer or answer for
+ * the re-INVITE and UPDATE. Once SDP negotiation is done, the
+ * provisional pool will be made as the active pool, then the
+ * existing active pool will be reset, to release the memory
+ * back to the OS. So these pool's lifetime is synchronized to
+ * the SDP offer-answer negotiation.
+ *
+ * Higher level application such as PJSUA-LIB has been modified to
+ * make use of these flip-flop pools, i.e. by creating media objects
+ * from the provisional pool rather than from the long term pool.
+ *
+ * Other applications that want to use these pools must understand
+ * that the flip-flop pool's lifetimes are synchronized to the
+ * SDP offer-answer negotiation.
+ */
+struct pjsip_inv_session
+{
+ char obj_name[PJ_MAX_OBJ_NAME]; /**< Log identification */
+ pj_pool_t *pool; /**< Long term pool. */
+ pj_pool_t *pool_prov; /**< Provisional pool */
+ pj_pool_t *pool_active; /**< Active/current pool*/
+ pjsip_inv_state state; /**< Invite sess state. */
+ pj_bool_t cancelling; /**< CANCEL requested */
+ pj_bool_t pending_cancel; /**< Wait to send CANCEL*/
+ pjsip_status_code cause; /**< Disconnect cause. */
+ pj_str_t cause_text; /**< Cause text. */
+ pj_bool_t notify; /**< Internal. */
+ unsigned cb_called; /**< Cb has been called */
+ pjsip_dialog *dlg; /**< Underlying dialog. */
+ pjsip_role_e role; /**< Invite role. */
+ unsigned options; /**< Options in use. */
+ pjmedia_sdp_neg *neg; /**< Negotiator. */
+ pjsip_transaction *invite_tsx; /**< 1st invite tsx. */
+ pjsip_tx_data *invite_req; /**< Saved invite req */
+ pjsip_tx_data *last_answer; /**< Last INVITE resp. */
+ pjsip_tx_data *last_ack; /**< Last ACK request */
+ pj_int32_t last_ack_cseq; /**< CSeq of last ACK */
+ void *mod_data[PJSIP_MAX_MODULE];/**< Modules data. */
+ struct pjsip_timer *timer; /**< Session Timers. */
+};
+
+
+/**
+ * This structure represents SDP information in a pjsip_rx_data. Application
+ * retrieve this information by calling #pjsip_rdata_get_sdp_info(). This
+ * mechanism supports multipart message body.
+ */
+typedef struct pjsip_rdata_sdp_info
+{
+ /**
+ * Pointer and length of the text body in the incoming message. If
+ * the pointer is NULL, it means the message does not contain SDP
+ * body.
+ */
+ pj_str_t body;
+
+ /**
+ * This will contain non-zero if an invalid SDP body is found in the
+ * message.
+ */
+ pj_status_t sdp_err;
+
+ /**
+ * A parsed and validated SDP body.
+ */
+ pjmedia_sdp_session *sdp;
+
+} pjsip_rdata_sdp_info;
+
+
+/**
+ * Initialize the invite usage module and register it to the endpoint.
+ * The callback argument contains pointer to functions to be called on
+ * occurences of events in invite sessions.
+ *
+ * @param endpt The endpoint instance.
+ * @param cb Callback structure.
+ *
+ * @return PJ_SUCCESS on success, or the appropriate error code.
+ */
+PJ_DECL(pj_status_t) pjsip_inv_usage_init(pjsip_endpoint *endpt,
+ const pjsip_inv_callback *cb);
+
+/**
+ * Get the INVITE usage module instance.
+ *
+ * @return PJ_SUCCESS on success, or the appropriate error code.
+ */
+PJ_DECL(pjsip_module*) pjsip_inv_usage_instance(void);
+
+
+/**
+ * Dump user agent contents (e.g. all dialogs).
+ */
+PJ_DECL(void) pjsip_inv_usage_dump(void);
+
+
+/**
+ * Create UAC invite session for the specified dialog in dlg.
+ *
+ * @param dlg The dialog which will be used by this invite session.
+ * @param local_sdp If application has determined its media capability,
+ * it can specify the SDP here. Otherwise it can leave
+ * this to NULL, to let remote UAS specifies an offer.
+ * @param options The options argument is bitmask combination of SIP
+ * features in pjsip_inv_options enumeration.
+ * @param p_inv On successful return, the invite session will be put
+ * in this argument.
+ *
+ * @return The function will return PJ_SUCCESS if it can create
+ * the session. Otherwise the appropriate error status
+ * will be returned on failure.
+ */
+PJ_DECL(pj_status_t) pjsip_inv_create_uac(pjsip_dialog *dlg,
+ const pjmedia_sdp_session *local_sdp,
+ unsigned options,
+ pjsip_inv_session **p_inv);
+
+
+/**
+ * Application SHOULD call this function upon receiving the initial INVITE
+ * request in rdata before creating the invite session (or even dialog),
+ * to verify that the invite session can handle the INVITE request.
+ * This function verifies that local endpoint is capable to handle required
+ * SIP extensions in the request (i.e. Require header) and also the media,
+ * if media description is present in the request.
+ *
+ * @param rdata The incoming INVITE request.
+ *
+ * @param options Upon calling this function, the options argument
+ * MUST contain the desired SIP extensions to be
+ * applied to the session. Upon return, this argument
+ * will contain the SIP extension that will be applied
+ * to the session, after considering the Supported,
+ * Require, and Allow headers in the request.
+ *
+ * @param sdp If local media capability has been determined,
+ * and if application wishes to verify that it can
+ * handle the media offer in the incoming INVITE
+ * request, it SHOULD specify its local media capability
+ * in this argument.
+ * If it is not specified, media verification will not
+ * be performed by this function.
+ *
+ * @param dlg If tdata is not NULL, application needs to specify
+ * how to create the response. Either dlg or endpt
+ * argument MUST be specified, with dlg argument takes
+ * precedence when both are specified.
+ *
+ * If a dialog has been created prior to calling this
+ * function, then it MUST be specified in dlg argument.
+ * Otherwise application MUST specify the endpt argument
+ * (this is useful e.g. when application wants to send
+ * the response statelessly).
+ *
+ * @param endpt If tdata is not NULL, application needs to specify
+ * how to create the response. Either dlg or endpt
+ * argument MUST be specified, with dlg argument takes
+ * precedence when both are specified.
+ *
+ * @param tdata If this argument is not NULL, this function will
+ * create the appropriate non-2xx final response message
+ * when the verification fails.
+ *
+ * @return If everything has been negotiated successfully,
+ * the function will return PJ_SUCCESS. Otherwise it
+ * will return the reason of the failure as the return
+ * code.
+ *
+ * This function is capable to create the appropriate
+ * response message when the verification has failed.
+ * If tdata is specified, then a non-2xx final response
+ * will be created and put in this argument upon return,
+ * when the verification has failed.
+ *
+ * If a dialog has been created prior to calling this
+ * function, then it MUST be specified in dlg argument.
+ * Otherwise application MUST specify the endpt argument
+ * (this is useful e.g. when application wants to send
+ * the response statelessly).
+ *
+ * @see pjsip_inv_verify_request2()
+ */
+PJ_DECL(pj_status_t) pjsip_inv_verify_request( pjsip_rx_data *rdata,
+ unsigned *options,
+ const pjmedia_sdp_session *sdp,
+ pjsip_dialog *dlg,
+ pjsip_endpoint *endpt,
+ pjsip_tx_data **tdata);
+
+/**
+ * Variant of #pjsip_inv_verify_request() which allows application to specify
+ * the parsed SDP in the \a offer argument. This is useful to avoid having to
+ * re-parse the SDP in the incoming request.
+ *
+ * @see pjsip_inv_verify_request()
+ */
+PJ_DECL(pj_status_t) pjsip_inv_verify_request2( pjsip_rx_data *rdata,
+ unsigned *options,
+ const pjmedia_sdp_session *offer,
+ const pjmedia_sdp_session *answer,
+ pjsip_dialog *dlg,
+ pjsip_endpoint *endpt,
+ pjsip_tx_data **tdata);
+
+/**
+ * Variant of #pjsip_inv_verify_request() which allows application not to
+ * specify the rdata (i.e. pass NULL as the rdata parameter) and specify
+ * the parsed SDP in the \a offer argument and a temporary pool in the
+ * \a tmp_pool argument.
+ * This is useful if application no longer has access to the rdata.
+ *
+ * @see pjsip_inv_verify_request()
+ */
+PJ_DECL(pj_status_t) pjsip_inv_verify_request3( pjsip_rx_data *rdata,
+ pj_pool_t *tmp_pool,
+ unsigned *options,
+ const pjmedia_sdp_session *offer,
+ const pjmedia_sdp_session *answer,
+ pjsip_dialog *dlg,
+ pjsip_endpoint *endpt,
+ pjsip_tx_data **tdata);
+
+
+/**
+ * Create UAS invite session for the specified dialog in dlg. Application
+ * SHOULD call the verification function before calling this function,
+ * to ensure that it can create the session successfully.
+ *
+ * @param dlg The dialog to be used.
+ * @param rdata Application MUST specify the received INVITE request
+ * in rdata. The invite session needs to inspect the
+ * received request to see if the request contains
+ * features that it supports.
+ * @param local_sdp If application has determined its media capability,
+ * it can specify this capability in this argument.
+ * If SDP is received in the initial INVITE, the UAS
+ * capability specified in this argument doesn't have to
+ * match the received offer; the SDP negotiator is able
+ * to rearrange the media lines in the answer so that it
+ * matches the offer.
+ * @param options The options argument is bitmask combination of SIP
+ * features in pjsip_inv_options enumeration.
+ * @param p_inv Pointer to receive the newly created invite session.
+ *
+ * @return On successful, the invite session will be put in
+ * p_inv argument and the function will return PJ_SUCCESS.
+ * Otherwise the appropriate error status will be returned
+ * on failure.
+ */
+PJ_DECL(pj_status_t) pjsip_inv_create_uas(pjsip_dialog *dlg,
+ pjsip_rx_data *rdata,
+ const pjmedia_sdp_session *local_sdp,
+ unsigned options,
+ pjsip_inv_session **p_inv);
+
+
+/**
+ * Forcefully terminate and destroy INVITE session, regardless of
+ * the state of the session. Note that this function should only be used
+ * when there is failure in the INVITE session creation. After the
+ * invite session has been created and initialized, normally application
+ * SHOULD use #pjsip_inv_end_session() to end the INVITE session instead.
+ *
+ * Note also that this function may terminate the underlying dialog, if
+ * there are no other sessions in the dialog.
+ *
+ * @param inv The invite session.
+ * @param st_code Status code for the reason of the termination.
+ * @param notify If set to non-zero, then on_state_changed()
+ * callback will be called.
+ *
+ * @return PJ_SUCCESS if the INVITE session has been
+ * terminated.
+ */
+PJ_DECL(pj_status_t) pjsip_inv_terminate( pjsip_inv_session *inv,
+ int st_code,
+ pj_bool_t notify );
+
+
+/**
+ * Restart UAC session and prepare the session for a new initial INVITE.
+ * This function can be called for example when the application wants to
+ * follow redirection response with a new call reusing this session so
+ * that the new call will have the same Call-ID and From headers. After
+ * the session is restarted, application may create and send a new INVITE
+ * request.
+ *
+ * @param inv The invite session.
+ * @param new_offer Should be set to PJ_TRUE since the application will
+ * restart the session.
+ *
+ * @return PJ_SUCCESS on successful operation.
+ */
+PJ_DECL(pj_status_t) pjsip_inv_uac_restart(pjsip_inv_session *inv,
+ pj_bool_t new_offer);
+
+
+/**
+ * Accept or reject redirection response. Application MUST call this function
+ * after it signaled PJSIP_REDIRECT_PENDING in the \a on_redirected()
+ * callback, to notify the invite session whether to accept or reject the
+ * redirection to the current target. Application can use the combination of
+ * PJSIP_REDIRECT_PENDING command in \a on_redirected() callback and this
+ * function to ask for user permission before redirecting the call.
+ *
+ * Note that if the application chooses to reject or stop redirection (by
+ * using PJSIP_REDIRECT_REJECT or PJSIP_REDIRECT_STOP respectively), the
+ * session disconnection callback will be called before this function returns.
+ * And if the application rejects the target, the \a on_redirected() callback
+ * may also be called before this function returns if there is another target
+ * to try.
+ *
+ * @param inv The invite session.
+ * @param cmd Redirection operation. The semantic of this argument
+ * is similar to the description in the \a on_redirected()
+ * callback, except that the PJSIP_REDIRECT_PENDING is
+ * not accepted here.
+ * @param e Should be set to NULL.
+ *
+ * @return PJ_SUCCESS on successful operation.
+ */
+PJ_DECL(pj_status_t) pjsip_inv_process_redirect(pjsip_inv_session *inv,
+ pjsip_redirect_op cmd,
+ pjsip_event *e);
+
+
+/**
+ * Create the initial INVITE request for this session. This function can only
+ * be called for UAC session. If local media capability is specified when
+ * the invite session was created, then this function will put an SDP offer
+ * in the outgoing INVITE request. Otherwise the outgoing request will not
+ * contain SDP body.
+ *
+ * @param inv The UAC invite session.
+ * @param p_tdata The initial INVITE request will be put in this
+ * argument if it can be created successfully.
+ *
+ * @return PJ_SUCCESS if the INVITE request can be created.
+ */
+PJ_DECL(pj_status_t) pjsip_inv_invite( pjsip_inv_session *inv,
+ pjsip_tx_data **p_tdata );
+
+
+/**
+ * Create the initial response message for the incoming INVITE request in
+ * rdata with status code st_code and optional status text st_text. Use
+ * #pjsip_inv_answer() to create subsequent response message.
+ */
+PJ_DECL(pj_status_t) pjsip_inv_initial_answer( pjsip_inv_session *inv,
+ pjsip_rx_data *rdata,
+ int st_code,
+ const pj_str_t *st_text,
+ const pjmedia_sdp_session *sdp,
+ pjsip_tx_data **p_tdata);
+
+/**
+ * Create a response message to the initial INVITE request. This function
+ * can only be called for the initial INVITE request, as subsequent
+ * re-INVITE request will be answered automatically.
+ *
+ * @param inv The UAS invite session.
+ * @param st_code The st_code contains the status code to be sent,
+ * which may be a provisional or final response.
+ * @param st_text If custom status text is desired, application can
+ * specify the text in st_text; otherwise if this
+ * argument is NULL, default status text will be used.
+ * @param local_sdp If application has specified its media capability
+ * during creation of UAS invite session, the local_sdp
+ * argument MUST be NULL. This is because application
+ * can not perform more than one SDP offer/answer session
+ * in a single INVITE transaction.
+ * If application has not specified its media capability
+ * during creation of UAS invite session, it MAY or MUST
+ * specify its capability in local_sdp argument,
+ * depending whether st_code indicates a 2xx final
+ * response.
+ * @param p_tdata Pointer to receive the response message created by
+ * this function.
+ *
+ * @return PJ_SUCCESS if response message was created
+ * successfully.
+ */
+PJ_DECL(pj_status_t) pjsip_inv_answer( pjsip_inv_session *inv,
+ int st_code,
+ const pj_str_t *st_text,
+ const pjmedia_sdp_session *local_sdp,
+ pjsip_tx_data **p_tdata );
+
+
+/**
+ * Set local offer or answer depending on negotiator state (it may also
+ * create a negotiator if it doesn't exist yet).
+ *
+ * @param inv The invite session.
+ * @param sdp The SDP description which will be set as
+ * an offer/answer to remote.
+ *
+ * @return PJ_SUCCESS if local offer/answer can be accepted by
+ * SDP negotiator.
+ */
+PJ_DECL(pj_status_t) pjsip_inv_set_local_sdp(pjsip_inv_session *inv,
+ const pjmedia_sdp_session *sdp );
+
+
+/**
+ * Set local answer to respond to remote SDP offer, to be carried by
+ * subsequent response (or request).
+ *
+ * @param inv The invite session.
+ * @param sdp The SDP description which will be set as answer
+ * to remote.
+ *
+ * @return PJ_SUCCESS if local answer can be accepted by
+ * SDP negotiator.
+ */
+PJ_DECL(pj_status_t) pjsip_inv_set_sdp_answer(pjsip_inv_session *inv,
+ const pjmedia_sdp_session *sdp );
+
+
+/**
+ * Create a SIP message to initiate invite session termination. Depending on
+ * the state of the session, this function may return CANCEL request,
+ * a non-2xx final response, a BYE request, or even no request.
+ *
+ * For UAS, if the session has not answered the incoming INVITE, this function
+ * creates the non-2xx final response with the specified status code in
+ * \a st_code and optional status text in \a st_text.
+ *
+ * For UAC, if the original INVITE has not been answered with a final
+ * response, the behavior depends on whether provisional response has been
+ * received. If provisional response has been received, this function will
+ * create CANCEL request. If no provisional response has been received, the
+ * function will not create CANCEL request (the function will return
+ * PJ_SUCCESS but the \a p_tdata will contain NULL) because we cannot send
+ * CANCEL before receiving provisional response. If then a provisional
+ * response is received, the invite session will send CANCEL automatically.
+ *
+ * For both UAC and UAS, if the INVITE session has been answered with final
+ * response, a BYE request will be created.
+ *
+ * @param inv The invite session.
+ * @param st_code Status code to be used for terminating the session.
+ * @param st_text Optional status text.
+ * @param p_tdata Pointer to receive the message to be created. Note
+ * that it's possible to receive NULL here while the
+ * function returns PJ_SUCCESS, see the description.
+ *
+ * @return PJ_SUCCESS if termination is initiated.
+ */
+PJ_DECL(pj_status_t) pjsip_inv_end_session( pjsip_inv_session *inv,
+ int st_code,
+ const pj_str_t *st_text,
+ pjsip_tx_data **p_tdata );
+
+
+
+/**
+ * Create a re-INVITE request.
+ *
+ * @param inv The invite session.
+ * @param new_contact If application wants to update its local contact and
+ * inform peer to perform target refresh with a new
+ * contact, it can specify the new contact in this
+ * argument; otherwise this argument must be NULL.
+ * @param new_offer Application MAY initiate a new SDP offer/answer
+ * session in the request when there is no pending
+ * answer to be sent or received. It can detect this
+ * condition by observing the state of the SDP
+ * negotiator of the invite session. If new offer
+ * should be sent to remote, the offer must be specified
+ * in this argument, otherwise it must be NULL.
+ * @param p_tdata Pointer to receive the re-INVITE request message to
+ * be created.
+ *
+ * @return PJ_SUCCESS if a re-INVITE request with the specified
+ * characteristics (e.g. to contain new offer) can be
+ * created.
+ */
+PJ_DECL(pj_status_t) pjsip_inv_reinvite(pjsip_inv_session *inv,
+ const pj_str_t *new_contact,
+ const pjmedia_sdp_session *new_offer,
+ pjsip_tx_data **p_tdata );
+
+
+
+/**
+ * Create an UPDATE request to initiate new SDP offer.
+ *
+ * @param inv The invite session.
+ * @param new_contact If application wants to update its local contact
+ * and inform peer to perform target refresh with a new
+ * contact, it can specify the new contact in this
+ * argument; otherwise this argument must be NULL.
+ * @param offer Offer to be sent to remote. This argument is
+ * mandatory.
+ * @param p_tdata Pointer to receive the UPDATE request message to
+ * be created.
+ *
+ * @return PJ_SUCCESS if a UPDATE request with the specified
+ * characteristics (e.g. to contain new offer) can be
+ * created.
+ */
+PJ_DECL(pj_status_t) pjsip_inv_update ( pjsip_inv_session *inv,
+ const pj_str_t *new_contact,
+ const pjmedia_sdp_session *offer,
+ pjsip_tx_data **p_tdata );
+
+
+/**
+ * Create an ACK request. Normally ACK request transmission is handled
+ * by the framework. Application only needs to use this function if it
+ * handles the ACK transmission manually, by overriding \a on_send_ack()
+ * callback in #pjsip_inv_callback.
+ *
+ * Note that if the invite session has a pending offer to be answered
+ * (for example when the last 2xx response to INVITE contains an offer),
+ * application MUST have set the SDP answer with #pjsip_create_sdp_body()
+ * prior to creating the ACK request. In this case, the ACK request
+ * will be added with SDP message body.
+ *
+ * @param inv The invite session.
+ * @param cseq Mandatory argument to specify the CSeq of the
+ * ACK request. This value MUST match the value
+ * of the INVITE transaction to be acknowledged.
+ * @param p_tdata Pointer to receive the ACK request message to
+ * be created.
+ *
+ * @return PJ_SUCCESS if ACK request has been created.
+ */
+PJ_DECL(pj_status_t) pjsip_inv_create_ack(pjsip_inv_session *inv,
+ int cseq,
+ pjsip_tx_data **p_tdata);
+
+
+/**
+ * Send request or response message in tdata.
+ *
+ * @param inv The invite session.
+ * @param tdata The message to be sent.
+ *
+ * @return PJ_SUCCESS if transaction can be initiated
+ * successfully to send this message. Note that the
+ * actual final state of the transaction itself will
+ * be reported later, in on_tsx_state_changed()
+ * callback.
+ */
+PJ_DECL(pj_status_t) pjsip_inv_send_msg(pjsip_inv_session *inv,
+ pjsip_tx_data *tdata);
+
+
+/**
+ * Get the invite session for the dialog, if any.
+ *
+ * @param dlg The dialog which invite session is being queried.
+ *
+ * @return The invite session instance which has been
+ * associated with this dialog, or NULL.
+ */
+PJ_DECL(pjsip_inv_session*) pjsip_dlg_get_inv_session(pjsip_dialog *dlg);
+
+/**
+ * Get the invite session instance associated with transaction tsx, if any.
+ *
+ * @param tsx The transaction, which invite session is being
+ * queried.
+ *
+ * @return The invite session instance which has been
+ * associated with this transaction, or NULL.
+ */
+PJ_DECL(pjsip_inv_session*) pjsip_tsx_get_inv_session(pjsip_transaction *tsx);
+
+
+/**
+ * Get state names for INVITE session state.
+ *
+ * @param state The invite state.
+ *
+ * @return String describing the state.
+ */
+PJ_DECL(const char *) pjsip_inv_state_name(pjsip_inv_state state);
+
+
+/**
+ * This is a utility function to create SIP body for SDP content.
+ *
+ * @param pool Pool to allocate memory.
+ * @param sdp SDP session to be put in the SIP message body.
+ * @param p_body Pointer to receive SIP message body containing
+ * the SDP session.
+ *
+ * @return PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjsip_create_sdp_body(pj_pool_t *pool,
+ pjmedia_sdp_session *sdp,
+ pjsip_msg_body **p_body);
+
+/**
+ * Retrieve SDP information from an incoming message. Application should
+ * prefer to use this function rather than parsing the SDP manually since
+ * this function supports multipart message body.
+ *
+ * This function will only parse the SDP once, the first time it is called
+ * on the same message. Subsequent call on the same message will just pick
+ * up the already parsed SDP from the message.
+ *
+ * @param rdata The incoming message.
+ *
+ * @return The SDP info.
+ */
+PJ_DECL(pjsip_rdata_sdp_info*) pjsip_rdata_get_sdp_info(pjsip_rx_data *rdata);
+
+
+PJ_END_DECL
+
+/**
+ * @}
+ */
+
+
+#endif /* __SIP_INVITE_SESSION_H__ */
diff --git a/pjsip/include/pjsip-ua/sip_regc.h b/pjsip/include/pjsip-ua/sip_regc.h
new file mode 100644
index 0000000..826d45e
--- /dev/null
+++ b/pjsip/include/pjsip-ua/sip_regc.h
@@ -0,0 +1,416 @@
+/* $Id: sip_regc.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_REG_H__
+#define __PJSIP_SIP_REG_H__
+
+/**
+ * @file sip_regc.h
+ * @brief SIP Registration Client
+ */
+
+#include <pjsip/sip_types.h>
+#include <pjsip/sip_auth.h>
+#include <pjsip/sip_transport.h>
+
+
+/**
+ * @defgroup PJSUA_REGC Client Registration
+ * @ingroup PJSIP_HIGH_UA
+ * @brief High Layer API for performing client registration.
+ * @{
+ *
+ * This provides API for performing client registration. Application must
+ * link with <b>pjsip-ua</b> static library to use this API.
+
+ */
+
+
+PJ_BEGIN_DECL
+
+/** Typedef for client registration data. */
+typedef struct pjsip_regc pjsip_regc;
+
+/** Maximum contacts in registration. */
+#define PJSIP_REGC_MAX_CONTACT 10
+
+/** Expiration not specified. */
+#define PJSIP_REGC_EXPIRATION_NOT_SPECIFIED ((pj_uint32_t)0xFFFFFFFFUL)
+
+/** Buffer to hold all contacts. */
+#define PJSIP_REGC_CONTACT_BUF_SIZE 512
+
+/** Structure to hold parameters when calling application's callback.
+ * The application's callback is called when the client registration process
+ * has finished.
+ */
+struct pjsip_regc_cbparam
+{
+ pjsip_regc *regc; /**< Client registration structure. */
+ void *token; /**< Arbitrary token set by application */
+
+ /** Error status. If this value is non-PJ_SUCCESS, some error has occured.
+ * Note that even when this contains PJ_SUCCESS the registration might
+ * have failed; in this case the \a code field will contain non
+ * successful (non-2xx status class) code
+ */
+ pj_status_t status;
+ int code; /**< SIP status code received. */
+ pj_str_t reason; /**< SIP reason phrase received. */
+ pjsip_rx_data *rdata; /**< The complete received response. */
+ int expiration;/**< Next expiration interval. */
+ int contact_cnt;/**<Number of contacts in response. */
+ pjsip_contact_hdr *contact[PJSIP_REGC_MAX_CONTACT]; /**< Contacts. */
+};
+
+
+/** Type declaration for callback to receive registration result. */
+typedef void pjsip_regc_cb(struct pjsip_regc_cbparam *param);
+
+/**
+ * Client registration information.
+ */
+struct pjsip_regc_info
+{
+ pj_str_t server_uri; /**< Server URI, */
+ pj_str_t client_uri; /**< Client URI (From header). */
+ pj_bool_t is_busy; /**< Have pending transaction? */
+ pj_bool_t auto_reg; /**< Will register automatically? */
+ int interval; /**< Registration interval (seconds). */
+ int next_reg; /**< Time until next registration (seconds). */
+ pjsip_transport *transport; /**< Last transport used. */
+};
+
+/**
+ * @see pjsip_regc_info
+ */
+typedef struct pjsip_regc_info pjsip_regc_info;
+
+
+/**
+ * Get the module instance for client registration module.
+ *
+ * @return client registration module.
+ */
+PJ_DECL(pjsip_module*) pjsip_regc_get_module(void);
+
+
+/**
+ * Create client registration structure.
+ *
+ * @param endpt Endpoint, used to allocate pool from.
+ * @param token A data to be associated with the client registration struct.
+ * @param cb Pointer to callback function to receive registration status.
+ * @param p_regc Pointer to receive client registration structure.
+ *
+ * @return PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjsip_regc_create( pjsip_endpoint *endpt, void *token,
+ pjsip_regc_cb *cb,
+ pjsip_regc **p_regc);
+
+
+/**
+ * Destroy client registration structure. If a registration transaction is
+ * in progress, then the structure will be deleted only after a final response
+ * has been received, and in this case, the callback won't be called.
+ *
+ * @param regc The client registration structure.
+ *
+ * @return PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjsip_regc_destroy(pjsip_regc *regc);
+
+/**
+ * Get registration info.
+ *
+ * @param regc The client registration structure.
+ * @param info Client registration info.
+ *
+ * @return PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjsip_regc_get_info( pjsip_regc *regc,
+ pjsip_regc_info *info );
+
+
+/**
+ * Get the memory pool associated with a registration client handle.
+ *
+ * @param regc The client registration structure.
+ * @return pool handle.
+ */
+PJ_DECL(pj_pool_t*) pjsip_regc_get_pool(pjsip_regc *regc);
+
+/**
+ * Initialize client registration structure with various information needed to
+ * perform the registration.
+ *
+ * @param regc The client registration structure.
+ * @param srv_url Server URL.
+ * @param from_url The person performing the registration, must be a SIP URL type.
+ * @param to_url The address of record for which the registration is targetd, must
+ * be a SIP/SIPS URL.
+ * @param ccnt Number of contacts in the array.
+ * @param contact Array of contacts, each contact item must be formatted
+ * as described in RFC 3261 Section 20.10:
+ * When the header field value contains a display
+ * name, the URI including all URI parameters is
+ * enclosed in "<" and ">". If no "<" and ">" are
+ * present, all parameters after the URI are header
+ * parameters, not URI parameters. The display name
+ * can be tokens, or a quoted string, if a larger
+ * character set is desired.
+ * @param expires Default expiration interval (in seconds) to be applied for
+ * contact URL that doesn't have expiration settings. If the
+ * value PJSIP_REGC_EXPIRATION_NOT_SPECIFIED is given, then
+ * no default expiration will be applied.
+ * @return zero on success.
+ */
+PJ_DECL(pj_status_t) pjsip_regc_init(pjsip_regc *regc,
+ const pj_str_t *srv_url,
+ const pj_str_t *from_url,
+ const pj_str_t *to_url,
+ int ccnt,
+ const pj_str_t contact[],
+ pj_uint32_t expires);
+
+/**
+ * Set the "sent-by" field of the Via header for outgoing requests.
+ *
+ * @param regc The client registration structure.
+ * @param via_addr Set via_addr to use for the Via header or NULL to use
+ * the transport's published name.
+ * @param via_tp via_addr will only be used if we are using via_tp
+ * transport.
+ *
+ * @return PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjsip_regc_set_via_sent_by(pjsip_regc *regc,
+ pjsip_host_port *via_addr,
+ pjsip_transport *via_tp);
+
+/**
+ * Set the number of seconds to refresh the client registration before
+ * the registration expires.
+ *
+ * @param regc The registration structure.
+ * @param delay The number of seconds to refresh the client
+ * registration before the registration expires.
+ *
+ * @return PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t)
+pjsip_regc_set_delay_before_refresh( pjsip_regc *regc,
+ pj_uint32_t delay );
+
+
+/**
+ * Set authentication credentials to use by this registration.
+ *
+ * @param regc The registration structure.
+ * @param count Number of credentials in the array.
+ * @param cred Array of credentials.
+ *
+ * @return PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjsip_regc_set_credentials( pjsip_regc *regc,
+ int count,
+ const pjsip_cred_info cred[] );
+
+/**
+ * Set authentication preference.
+ *
+ * @param regc The registration structure.
+ * @param pref Authentication preference.
+ *
+ * @return PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjsip_regc_set_prefs( pjsip_regc *regc,
+ const pjsip_auth_clt_pref *pref);
+
+/**
+ * Set route set to be used for outgoing requests.
+ *
+ * @param regc The client registration structure.
+ * @param route_set List containing Route headers.
+ *
+ * @return PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjsip_regc_set_route_set(pjsip_regc *regc,
+ const pjsip_route_hdr*route_set);
+
+
+/**
+ * Lock/bind client registration to a specific transport/listener.
+ * This is optional, as normally transport will be selected automatically
+ * based on the destination of requests upon resolver completion.
+ * When the client registration is explicitly bound to the specific
+ * transport/listener, all UAC transactions originated by the client
+ * registration will use the specified transport/listener when sending
+ * outgoing requests.
+ *
+ * Note that this doesn't affect the Contact header set for this client
+ * registration. Application must manually update the Contact header if
+ * necessary, to adjust the address according to the transport being
+ * selected.
+ *
+ * @param regc The client registration instance.
+ * @param sel Transport selector containing the specification of
+ * transport or listener to be used by this session
+ * to send requests.
+ *
+ * @return PJ_SUCCESS on success, or the appropriate error code.
+ */
+PJ_DECL(pj_status_t) pjsip_regc_set_transport(pjsip_regc *regc,
+ const pjsip_tpselector *sel);
+
+/**
+ * Release the reference to current transport being used by the regc, if any.
+ * The regc keeps the reference to the last transport being used in order
+ * to prevent it from being destroyed. In some situation however, such as
+ * when the transport is disconnected, it is necessary to instruct the
+ * regc to release this reference so that the transport can be destroyed.
+ * See https://trac.pjsip.org/repos/ticket/1481 for background info.
+ *
+ * @param regc The client registration instance.
+ *
+ * @return PJ_SUCCESS on success, or the appropriate error code.
+ */
+PJ_DECL(pj_status_t) pjsip_regc_release_transport(pjsip_regc *regc);
+
+/**
+ * Add headers to be added to outgoing REGISTER requests.
+ *
+ * @param regc The client registration structure.
+ * @param hdr_list List containing SIP headers to be added for all outgoing
+ * REGISTER requests.
+ *
+ * @return PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjsip_regc_add_headers(pjsip_regc *regc,
+ const pjsip_hdr *hdr_list);
+
+
+/**
+ * Create REGISTER request for the specified client registration structure.
+ *
+ * After successfull registration, application can inspect the contacts in
+ * the client registration structure to list what contacts are associaciated
+ * with the address of record being targeted in the registration.
+ *
+ * @param regc The client registration structure.
+ * @param autoreg If non zero, the library will automatically refresh the
+ * next registration until application unregister.
+ * @param p_tdata Pointer to receive the REGISTER request.
+ *
+ * @return PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjsip_regc_register(pjsip_regc *regc, pj_bool_t autoreg,
+ pjsip_tx_data **p_tdata);
+
+
+/**
+ * Create REGISTER request to unregister the contacts that were previously
+ * registered by this client registration.
+ *
+ * @param regc The client registration structure.
+ * @param p_tdata Pointer to receive the REGISTER request.
+ *
+ * @return PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjsip_regc_unregister(pjsip_regc *regc,
+ pjsip_tx_data **p_tdata);
+
+/**
+ * Create REGISTER request to unregister all contacts from server records.
+ * Note that this will unregister all registered contact for the AOR
+ * including contacts registered by other user agents. To only unregister
+ * contact registered by this client registration instance, use
+ * #pjsip_regc_unregister() instead.
+ *
+ * @param regc The client registration structure.
+ * @param p_tdata Pointer to receive the REGISTER request.
+ *
+ * @return PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjsip_regc_unregister_all(pjsip_regc *regc,
+ pjsip_tx_data **p_tdata);
+
+/**
+ * Update Contact details in the client registration structure. For each
+ * contact, if the contact is not found in existing contact, it will be
+ * added to the Contact list. If it matches existing contact, nothing
+ * will be added. This function will also mark existing contacts which
+ * are not specified in the new contact list as to be removed, by adding
+ * "expires=0" parameter to these contacts.
+ *
+ * Once the contact list has been updated, application must update the
+ * registration by creating a new REGISTER request and send it to the
+ * registrar. This request will contain both old and new contacts; the
+ * old contacts will have it's expires parameter set to zero to instruct
+ * the registrar to remove the bindings.
+ *
+ * @param regc The client registration structure.
+ * @param ccnt Number of contacts.
+ * @param contact Array of contacts, each contact item must be formatted
+ * as described in RFC 3261 Section 20.10:
+ * When the header field value contains a display
+ * name, the URI including all URI parameters is
+ * enclosed in "<" and ">". If no "<" and ">" are
+ * present, all parameters after the URI are header
+ * parameters, not URI parameters. The display name
+ * can be tokens, or a quoted string, if a larger
+ * character set is desired.
+ * @return PJ_SUCCESS if sucessfull.
+ */
+PJ_DECL(pj_status_t) pjsip_regc_update_contact( pjsip_regc *regc,
+ int ccnt,
+ const pj_str_t contact[] );
+
+/**
+ * Update the expires value. The next REGISTER request will contain
+ * new expires value for the registration.
+ *
+ * @param regc The client registration structure.
+ * @param expires The new expires value.
+ * @return zero on successfull.
+ */
+PJ_DECL(pj_status_t) pjsip_regc_update_expires( pjsip_regc *regc,
+ pj_uint32_t expires );
+
+/**
+ * Sends outgoing REGISTER request.
+ * The process will complete asynchronously, and application
+ * will be notified via the callback when the process completes.
+ *
+ * @param regc The client registration structure.
+ * @param tdata Transmit data.
+ *
+ * @return PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjsip_regc_send(pjsip_regc *regc, pjsip_tx_data *tdata);
+
+
+PJ_END_DECL
+
+/**
+ * @}
+ */
+
+#endif /* __PJSIP_REG_H__ */
diff --git a/pjsip/include/pjsip-ua/sip_replaces.h b/pjsip/include/pjsip-ua/sip_replaces.h
new file mode 100644
index 0000000..6293b0f
--- /dev/null
+++ b/pjsip/include/pjsip-ua/sip_replaces.h
@@ -0,0 +1,301 @@
+/* $Id: sip_replaces.h 3553 2011-05-05 06:14:19Z nanang $ */
+/*
+ * 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_REPLACES_H__
+#define __PJSIP_REPLACES_H__
+
+
+/**
+ * @file sip_replaces.h
+ * @brief SIP Replaces support (RFC 3891 - SIP "Replaces" Header)
+ */
+#include <pjsip/sip_msg.h>
+
+/**
+ * @defgroup PJSIP_REPLACES SIP Replaces support (RFC 3891 - "Replaces" Header)
+ * @ingroup PJSIP_HIGH_UA
+ * @brief SIP Replaces support (RFC 3891 - "Replaces" Header)
+ * @{
+ *
+ * This module implements support for Replaces header in PJSIP. The Replaces
+ * specification is written in RFC 3891 - The Session Initiation Protocol (SIP)
+ * "Replaces" Header, and can be used to enable a variety of features,
+ * for example: "Attended Transfer" and "Call Pickup".
+ *
+ *
+ *
+ * \section PJSIP_REPLACES_USING_SEC Using PJSIP Replaces Support
+ *
+ * \subsection PJSIP_REPLACES_INIT_SUBSEC Initialization
+ *
+ * Application needs to call #pjsip_replaces_init_module() during application
+ * initialization stage to register "replaces" support in PJSIP.
+ *
+ *
+ *
+ * \subsection PJSIP_REPLACES_UAC_SUBSEC UAC Behavior: Sending a Replaces Header
+ *
+ * A User Agent that wishes to replace a single existing early or
+ * confirmed dialog with a new dialog of its own, MAY send the target
+ * User Agent an INVITE request containing a Replaces header field. The
+ * User Agent Client (UAC) places the Call-ID, to-tag, and from-tag
+ * information for the target dialog in a single Replaces header field
+ * and sends the new INVITE to the target.
+ *
+ * To initiate outgoing INVITE request with Replaces header, application
+ * would create the INVITE request with #pjsip_inv_invite(), then adds
+ * #pjsip_replaces_hdr instance into the request, filling up the Call-ID,
+ * To-tag, and From-tag properties of the header with the identification
+ * of the dialog to be replaced. Application may also optionally
+ * set the \a early_only property of the header to indicate that it only
+ * wants to replace early dialog.
+ *
+ * Note that when the outgoing INVITE request (with Replaces) is initiated
+ * from an incoming REFER request (as in Attended Call Transfer case),
+ * this process should be done rather more automatically by PJSIP. Upon
+ * receiving incoming incoming REFER request, normally these processes
+ * will be performed:
+ * - Application finds \a Refer-To header,
+ * - Application creates outgoing dialog/invite session, specifying
+ * the URI in the \a Refer-To header as the initial remote target,
+ * - The URI in the \a Refer-To header may contain header parameters such
+ * as \a Replaces and \a Require headers.
+ * - The dialog keeps the header fields in the header parameters
+ * of the URI, and the invite session would add these headers into
+ * the outgoing INVITE request. Because of this, the outgoing
+ * INVITE request will contain the \a Replaces and \a Require headers.
+ *
+ *
+ * For more information, please see the implementation of
+ * #pjsua_call_xfer_replaces() in \ref PJSUA_LIB source code.
+ *
+ *
+ * \subsection PJSIP_REPLACES_UAS_SUBSEC UAS Behavior: Receiving a Replaces Header
+ *
+ * The Replaces header contains information used to match an existing
+ * SIP dialog (call-id, to-tag, and from-tag). Upon receiving an INVITE
+ * with a Replaces header, the User Agent (UA) attempts to match this
+ * information with a confirmed or early dialog.
+ *
+ * In PJSIP, if application wants to process the Replaces header in the
+ * incoming INVITE request, it should call #pjsip_replaces_verify_request()
+ * before creating the INVITE session. The #pjsip_replaces_verify_request()
+ * function checks and verifies the request to see if Replaces request
+ * can be processed. To be more specific, it performs the following
+ * verification:
+ * - checks that Replaces header is present. If not, the function will
+ * return PJ_SUCCESS without doing anything.
+ * - checks that no duplicate Replaces headers are present, or otherwise
+ * it will return 400 "Bad Request" response.
+ * - checks for matching dialog and verifies that the invite session has
+ * the correct state, and may return 481 "Call/Transaction Does Not Exist",
+ * 603 "Declined", or 486 "Busy Here" according to the processing rules
+ * specified in RFC 3891.
+ * - if matching dialog with correct state is found, it will give PJ_SUCCESS
+ * status and return the matching dialog back to the application.
+ *
+ * The following pseudocode illustrates how application can process the
+ * incoming INVITE if it wants to support Replaces extension:
+ *
+ \code
+ // Incoming INVITE request handler
+ pj_bool_t on_rx_invite(pjsip_rx_data *rdata)
+ {
+ pjsip_dialog *dlg, *replaced_dlg;
+ pjsip_inv_session *inv;
+ pjsip_tx_data *response;
+ pj_status_t status;
+
+ // Check whether Replaces header is present in the request and process accordingly.
+ //
+ status = pjsip_replaces_verify_request(rdata, &replaced_dlg, PJ_FALSE, &response);
+ if (status != PJ_SUCCESS) {
+ // Something wrong with Replaces request.
+ //
+ if (response) {
+ pjsip_endpt_send_response(endpt, rdata, response, NULL, NULL);
+ } else {
+ // Respond with 500 (Internal Server Error)
+ pjsip_endpt_respond_stateless(endpt, rdata, 500, NULL, NULL, NULL);
+ }
+ }
+
+ // Create UAS Invite session as usual.
+ //
+ status = pjsip_dlg_create_uas(.., rdata, .., &dlg);
+ ..
+ status = pjsip_inv_create_uas(dlg, .., &inv);
+
+ // Send initial 100 "Trying" to the INVITE request
+ //
+ status = pjsip_inv_initial_answer(inv, rdata, 100, ..., &response);
+ if (status == PJ_SUCCESS)
+ pjsip_inv_send_msg(inv, response);
+
+
+ // This is where processing is different between normal call
+ // (without Replaces) and call with Replaces.
+ //
+ if (replaced_dlg) {
+ pjsip_inv_session *replaced_inv;
+
+ // Always answer the new INVITE with 200, regardless whether
+ // the replaced call is in early or confirmed state.
+ //
+ status = pjsip_inv_answer(inv, 200, NULL, NULL, &response);
+ if (status == PJ_SUCCESS)
+ pjsip_inv_send_msg(inv, response);
+
+
+ // Get the INVITE session associated with the replaced dialog.
+ //
+ replaced_inv = pjsip_dlg_get_inv_session(replaced_dlg);
+
+
+ // Disconnect the "replaced" INVITE session.
+ //
+ status = pjsip_inv_end_session(replaced_inv, PJSIP_SC_GONE, NULL, &tdata);
+ if (status == PJ_SUCCESS && tdata)
+ status = pjsip_inv_send_msg(replaced_inv, tdata);
+
+
+ // It's up to application to associate the new INVITE session
+ // with the old (now terminated) session. For example, application
+ // may assign the same User Interface object for the new INVITE
+ // session.
+
+ } else {
+ // Process normal INVITE without Replaces.
+ ...
+ }
+ }
+
+ \endcode
+ *
+ *
+ * For a complete sample implementation, please see \a pjsua_call_on_incoming()
+ * function of \ref PJSUA_LIB in \a pjsua_call.c file.
+ *
+ *
+ * \section PJSIP_REPLACES_REFERENCE References
+ *
+ * References:
+ * - <A HREF="http://www.ietf.org/rfc/rfc3891.txt">RFC 3891: The Session
+ * Initiation Protocol (SIP) "Replaces" Header</A>
+ * - \ref PJSUA_XFER
+ */
+
+PJ_BEGIN_DECL
+
+
+/**
+ * Declaration of SIP Replaces header (RFC 3891).
+ */
+typedef struct pjsip_replaces_hdr
+{
+ /** Standard header field. */
+ PJSIP_DECL_HDR_MEMBER(struct pjsip_replaces_hdr);
+
+ /** Call-Id */
+ pj_str_t call_id;
+
+ /** to-tag */
+ pj_str_t to_tag;
+
+ /** from-tag */
+ pj_str_t from_tag;
+
+ /** early-only? */
+ pj_bool_t early_only;
+
+ /** Other parameters */
+ pjsip_param other_param;
+
+} pjsip_replaces_hdr;
+
+
+
+/**
+ * Initialize Replaces support in PJSIP. This would, among other things,
+ * register the header parser for Replaces header.
+ *
+ * @param endpt The endpoint instance.
+ *
+ * @return PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjsip_replaces_init_module(pjsip_endpoint *endpt);
+
+
+/**
+ * Create Replaces header.
+ *
+ * @param pool Pool to allocate the header instance from.
+ *
+ * @return An empty Replaces header instance.
+ */
+PJ_DECL(pjsip_replaces_hdr*) pjsip_replaces_hdr_create(pj_pool_t *pool);
+
+
+/**
+ * Verify that incoming request with Replaces header can be processed.
+ * This function will perform all necessary checks according to RFC 3891
+ * Section 3 "User Agent Server Behavior: Receiving a Replaces Header".
+ *
+ * @param rdata The incoming request to be verified.
+ * @param p_dlg On return, it will be filled with the matching
+ * dialog.
+ * @param lock_dlg Specifies whether this function should acquire lock
+ * to the matching dialog. If yes (and should be yes!),
+ * then application will need to release the dialog's
+ * lock with #pjsip_dlg_dec_lock() when the function
+ * returns PJ_SUCCESS and the \a p_dlg parameter is filled
+ * with the dialog instance.
+ * @param p_tdata Upon error, it will be filled with the final response
+ * to be sent to the request sender.
+ *
+ * @return The function returns the following:
+ * - If the request doesn't contain Replaces header, the
+ * function returns PJ_SUCCESS and \a p_dlg parameter
+ * will be set to NULL.
+ * - If the request contains Replaces header and a valid,
+ * matching dialog is found, the function returns
+ * PJ_SUCCESS and \a p_dlg parameter will be set to the
+ * matching dialog instance.
+ * - Upon error condition (as described by RFC 3891), the
+ * function returns non-PJ_SUCCESS, and \a p_tdata
+ * parameter SHOULD be set with a final response message
+ * to be sent to the sender of the request.
+ */
+PJ_DECL(pj_status_t) pjsip_replaces_verify_request(pjsip_rx_data *rdata,
+ pjsip_dialog **p_dlg,
+ pj_bool_t lock_dlg,
+ pjsip_tx_data **p_tdata);
+
+
+
+PJ_END_DECL
+
+
+/**
+ * @}
+ */
+
+
+#endif /* __PJSIP_REPLACES_H__ */
+
diff --git a/pjsip/include/pjsip-ua/sip_timer.h b/pjsip/include/pjsip-ua/sip_timer.h
new file mode 100644
index 0000000..6ef7931
--- /dev/null
+++ b/pjsip/include/pjsip-ua/sip_timer.h
@@ -0,0 +1,262 @@
+/* $Id: sip_timer.h 3553 2011-05-05 06:14:19Z nanang $ */
+/*
+ * Copyright (C) 2009-2011 Teluu Inc. (http://www.teluu.com)
+ *
+ * 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_TIMER_H__
+#define __PJSIP_TIMER_H__
+
+
+/**
+ * @file sip_timer.h
+ * @brief SIP Session Timers support (RFC 4028 - Session Timer in SIP)
+ */
+
+#include <pjsip-ua/sip_inv.h>
+#include <pjsip/sip_msg.h>
+
+/**
+ * @defgroup PJSIP_TIMER SIP Session Timers support (RFC 4028 - Session Timers in SIP)
+ * @ingroup PJSIP_HIGH_UA
+ * @brief SIP Session Timers support (RFC 4028 - Session Timers in SIP)
+ * @{
+ *
+ * \section PJSIP_TIMER_REFERENCE References
+ *
+ * References:
+ * - <A HREF="http://www.ietf.org/rfc/rfc4028.txt">RFC 4028: Session Timers
+ * in the Session Initiation Protocol (SIP)</A>
+ */
+
+PJ_BEGIN_DECL
+
+/**
+ * Opaque declaration of Session Timers.
+ */
+typedef struct pjsip_timer pjsip_timer;
+
+
+/**
+ * This structure describes Session Timers settings in an invite session.
+ */
+typedef struct pjsip_timer_setting
+{
+ /**
+ * Specify minimum session expiration period, in seconds. Must not be
+ * lower than 90. Default is 90.
+ */
+ unsigned min_se;
+
+ /**
+ * Specify session expiration period, in seconds. Must not be lower than
+ * #min_se. Default is 1800.
+ */
+ unsigned sess_expires;
+
+} pjsip_timer_setting;
+
+
+/**
+ * SIP Session-Expires header (RFC 4028).
+ */
+typedef struct pjsip_sess_expires_hdr
+{
+ /** Standard header field. */
+ PJSIP_DECL_HDR_MEMBER(struct pjsip_sess_expires_hdr);
+
+ /** Session expiration period */
+ unsigned sess_expires;
+
+ /** Refresher */
+ pj_str_t refresher;
+
+ /** Other parameters */
+ pjsip_param other_param;
+
+} pjsip_sess_expires_hdr;
+
+
+/**
+ * SIP Min-SE header (RFC 4028).
+ */
+typedef struct pjsip_min_se_hdr
+{
+ /** Standard header field. */
+ PJSIP_DECL_HDR_MEMBER(struct pjsip_min_se_hdr);
+
+ /** Minimum session expiration period */
+ unsigned min_se;
+
+ /** Other parameters */
+ pjsip_param other_param;
+
+} pjsip_min_se_hdr;
+
+
+
+/**
+ * Initialize Session Timers module. This function must be called once during
+ * application initialization, to register this module to SIP endpoint.
+ *
+ * @param endpt The SIP endpoint instance.
+ *
+ * @return PJ_SUCCESS if module is successfully initialized.
+ */
+PJ_DECL(pj_status_t) pjsip_timer_init_module(pjsip_endpoint *endpt);
+
+
+/**
+ * Initialize Session Timers setting with default values.
+ *
+ * @param setting Session Timers setting to be initialized.
+ *
+ * @return PJ_SUCCESS on successful.
+ */
+PJ_DECL(pj_status_t) pjsip_timer_setting_default(pjsip_timer_setting *setting);
+
+
+/**
+ * Initialize Session Timers for an invite session. This function should be
+ * called by application to apply Session Timers setting, otherwise invite
+ * session will apply default setting to the Session Timers.
+ *
+ * @param inv The invite session.
+ * @param setting Session Timers setting, see @pjsip_timer_setting.
+ * If setting is NULL, default setting will be applied.
+ *
+ * @return PJ_SUCCESS on successful.
+ */
+PJ_DECL(pj_status_t) pjsip_timer_init_session(
+ pjsip_inv_session *inv,
+ const pjsip_timer_setting *setting);
+
+
+/**
+ * Create Session-Expires header.
+ *
+ * @param pool Pool to allocate the header instance from.
+ *
+ * @return An empty Session-Expires header instance.
+ */
+PJ_DECL(pjsip_sess_expires_hdr*) pjsip_sess_expires_hdr_create(
+ pj_pool_t *pool);
+
+
+/**
+ * Create Min-SE header.
+ *
+ * @param pool Pool to allocate the header instance from.
+ *
+ * @return An empty Min-SE header instance.
+ */
+PJ_DECL(pjsip_min_se_hdr*) pjsip_min_se_hdr_create(pj_pool_t *pool);
+
+
+/**
+ * Update outgoing request to insert Session Timers headers and also
+ * signal Session Timers capability in Supported and/or Require headers.
+ *
+ * This function will be called internally by the invite session if it
+ * detects that the session needs Session Timers support.
+ *
+ * @param inv The invite session.
+ * @param tdata Outgoing INVITE or UPDATE request.
+ *
+ * @return PJ_SUCCESS on successful.
+ */
+PJ_DECL(pj_status_t) pjsip_timer_update_req(pjsip_inv_session *inv,
+ pjsip_tx_data *tdata);
+
+
+/**
+ * Process Session Timers headers in incoming response, this function
+ * will only process incoming response with status code 422 (Session
+ * Interval Too Small) or 2xx (final response).
+ *
+ * This function will be called internally by the invite session if it
+ * detects that the session needs Session Timers support.
+ *
+ * @param inv The invite session.
+ * @param rdata Incoming response data.
+ * @param st_code Output buffer to store corresponding SIP status code
+ * when function returning non-PJ_SUCCESS.
+ *
+ * @return PJ_SUCCESS on successful.
+ */
+PJ_DECL(pj_status_t) pjsip_timer_process_resp(pjsip_inv_session *inv,
+ const pjsip_rx_data *rdata,
+ pjsip_status_code *st_code);
+
+
+/**
+ * Process Session Timers headers in incoming request, this function
+ * will only process incoming INVITE and UPDATE request.
+ *
+ * This function will be called internally by the invite session if it
+ * detects that the session needs Session Timers support.
+ *
+ * @param inv The invite session.
+ * @param rdata Incoming INVITE or UPDATE request.
+ * @param st_code Output buffer to store corresponding SIP status code
+ * when function returning non-PJ_SUCCESS.
+ *
+ * @return PJ_SUCCESS on successful.
+ */
+PJ_DECL(pj_status_t) pjsip_timer_process_req(pjsip_inv_session *inv,
+ const pjsip_rx_data *rdata,
+ pjsip_status_code *st_code);
+
+
+/**
+ * Update outgoing response to insert Session Timers headers and also
+ * signal Session Timers capability in Supported and/or Require headers.
+ * This function will only update outgoing response with status code
+ * 422 (Session Interval Too Small) or 2xx (final response).
+ *
+ * This function will be called internally by the invite session if it
+ * detects that the session needs Session Timers support.
+ *
+ * @param inv The invite session.
+ * @param tdata Outgoing 422/2xx response.
+ *
+ * @return PJ_SUCCESS on successful.
+ */
+PJ_DECL(pj_status_t) pjsip_timer_update_resp(pjsip_inv_session *inv,
+ pjsip_tx_data *tdata);
+
+/**
+ * End Session Timers in an invite session.
+ *
+ * This function will be called internally by the invite session if it
+ * detects that the session needs Session Timers support.
+ *
+ * @param inv The invite session.
+ *
+ * @return PJ_SUCCESS on successful.
+ */
+PJ_DECL(pj_status_t) pjsip_timer_end_session(pjsip_inv_session *inv);
+
+
+
+PJ_END_DECL
+
+
+/**
+ * @}
+ */
+
+
+#endif /* __PJSIP_TIMER_H__ */
diff --git a/pjsip/include/pjsip-ua/sip_xfer.h b/pjsip/include/pjsip-ua/sip_xfer.h
new file mode 100644
index 0000000..b7b68d9
--- /dev/null
+++ b/pjsip/include/pjsip-ua/sip_xfer.h
@@ -0,0 +1,208 @@
+/* $Id: sip_xfer.h 3553 2011-05-05 06:14:19Z nanang $ */
+/*
+ * 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_XFER_H__
+#define __PJSIP_XFER_H__
+
+
+
+/**
+ * @file sip_xfer.h
+ * @brief SIP Transfer (REFER, RFC 3515)
+ */
+#include <pjsip-simple/evsub.h>
+#include <pjsip/sip_msg.h>
+
+/**
+ * @defgroup PJSUA_XFER SIP REFER (RFC 3515) for Call Transfer etc.
+ * @ingroup PJSIP_HIGH_UA
+ * @brief SIP REFER dialog usage (call transfer, etc.)
+ * @{
+ *
+ * This describes a generic handling of SIP REFER request. The SIP REFER
+ * request is described in RFC 3515, and commonly used to perform call
+ * transfer functionality. Other types of SIP REFER usages are described
+ * in draft-worley-sip-many-refers-00 draft, for example:
+ * - Remote Dial: where UAC sends REFER to instruct REFER recipient to
+ * initiate an INVITE session to some target.
+ *
+ * A REFER request can be sent inside or outside existing dialog context,
+ * although for call transfer case, it is more common to send REFER inside
+ * existing INVITE session context. PJSIP supports both sending REFER request
+ * inside or outside dialog context.
+ *
+ * The REFER framework uses @ref PJSIP_EVENT_NOT to manage the event
+ * subscription created by the REFER request. Because of this, application
+ * must link with <b>pjsip-ua</b> AND <b>pjsip-simple</b> static libraries
+ * to use REFER functionality.
+ *
+ * Reference:
+ * - <A HREF="http://www.ietf.org/rfc/rfc3515.txt">RFC 3515: The Session
+ * Initiation Protocol (SIP) Refer Method</A>
+ * - @ref PJSIP_EVENT_NOT
+ */
+
+
+PJ_BEGIN_DECL
+
+
+/** Declaration for REFER method constant. */
+PJ_DECL_DATA(const pjsip_method) pjsip_refer_method;
+
+/** Get REFER method constant */
+PJ_DECL(const pjsip_method*) pjsip_get_refer_method(void);
+
+
+/**
+ * Initialize the REFER subsystem.
+ * This currently does very little (only register REFER as supported method).
+ */
+PJ_DECL(pj_status_t) pjsip_xfer_init_module(pjsip_endpoint *endpt);
+
+
+
+/**
+ * Create transferer (sender of REFER request).
+ *
+ * @param dlg The underlying dialog to use.
+ * @param user_cb Pointer to callbacks to receive presence subscription
+ * events.
+ * @param p_evsub Pointer to receive the presence subscription
+ * session.
+ *
+ * @return PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjsip_xfer_create_uac( pjsip_dialog *dlg,
+ const pjsip_evsub_user *user_cb,
+ pjsip_evsub **p_evsub );
+
+
+/**
+ * Create transferee (receiver of REFER request).
+ *
+ * @param dlg The underlying dialog to use.
+ * @param user_cb Pointer to callbacks to receive presence subscription
+ * events.
+ * @param rdata The incoming SUBSCRIBE request that creates the event
+ * subscription.
+ * @param p_evsub Pointer to receive the presence subscription
+ * session.
+ *
+ * @return PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjsip_xfer_create_uas( pjsip_dialog *dlg,
+ const pjsip_evsub_user *user_cb,
+ pjsip_rx_data *rdata,
+ pjsip_evsub **p_evsub );
+
+/**
+ * Call this function to create request to initiate REFER subscription,
+ * to refresh subscription, or to unsubscribe. For request other than
+ * the initial REFER request, "refer_to_uri" argument may be NULL.
+ *
+ * @param sub Client subscription instance.
+ * @param refer_to_uri URI to be put to the Refer-To header. This argument
+ * may be NULL for subsequent REFER requests.
+ * @param p_tdata Pointer to receive the request.
+ *
+ * @return PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjsip_xfer_initiate( pjsip_evsub *sub,
+ const pj_str_t *refer_to_uri,
+ pjsip_tx_data **p_tdata);
+
+
+/**
+ * Accept the incoming REFER request by sending 2xx response.
+ *
+ * @param sub Server subscription instance.
+ * @param rdata The incoming subscription request message.
+ * @param st_code Status code, which MUST be 2xx.
+ * @param hdr_list Optional list of headers to be added in the response.
+ *
+ * @return PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjsip_xfer_accept( pjsip_evsub *sub,
+ pjsip_rx_data *rdata,
+ int st_code,
+ const pjsip_hdr *hdr_list );
+
+
+/**
+ * For notifier, create NOTIFY request to subscriber, and set the state
+ * of the subscription.
+ *
+ * @param sub The server subscription (notifier) instance.
+ * @param state New state to set.
+ * @param xfer_st_code The call status code to be reported with the NOTIFY
+ * request.
+ * @param xfer_st_text Optional call status text to be reported with the
+ * NOTIFY request. If the value is NULL, default
+ * status text will be used.
+ * @param p_tdata Pointer to receive the request.
+ *
+ * @return PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjsip_xfer_notify( pjsip_evsub *sub,
+ pjsip_evsub_state state,
+ int xfer_st_code,
+ const pj_str_t *xfer_st_text,
+ pjsip_tx_data **p_tdata);
+
+
+/**
+ * Create NOTIFY request to reflect current subscription status. Application
+ * can only call this function after it has sent NOTIFY before.
+ * This will also re-send the last "message/sipfrag" body that was sent
+ * in the previous NOTIFY.
+ *
+ * @param sub Server subscription object.
+ * @param p_tdata Pointer to receive request.
+ *
+ * @return PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjsip_xfer_current_notify( pjsip_evsub *sub,
+ pjsip_tx_data **p_tdata );
+
+
+
+/**
+ * Send request message that was previously created with initiate(), notify(),
+ * or current_notify(). Application may also send request created with other
+ * functions, e.g. authentication. But the request MUST be either request
+ * that creates/refresh subscription or NOTIFY request.
+ *
+ *
+ * @param sub The event subscription object.
+ * @param tdata Request message to be send.
+ *
+ * @return PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjsip_xfer_send_request( pjsip_evsub *sub,
+ pjsip_tx_data *tdata);
+
+
+PJ_END_DECL
+
+/**
+ * @}
+ */
+
+#endif /* __PJSIP_XFER_H__ */
+
diff --git a/pjsip/include/pjsip.h b/pjsip/include/pjsip.h
new file mode 100644
index 0000000..a2021cd
--- /dev/null
+++ b/pjsip/include/pjsip.h
@@ -0,0 +1,61 @@
+/* $Id: pjsip.h 3553 2011-05-05 06:14:19Z nanang $ */
+/*
+ * 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_H__
+#define __PJSIP_H__
+
+/* Base types. */
+#include <pjsip/sip_types.h>
+#include <pjsip/sip_errno.h>
+
+/* Messaging and parsing. */
+#include <pjsip/sip_uri.h>
+#include <pjsip/sip_tel_uri.h>
+#include <pjsip/sip_msg.h>
+#include <pjsip/sip_multipart.h>
+#include <pjsip/sip_parser.h>
+
+/* Core */
+#include <pjsip/sip_event.h>
+#include <pjsip/sip_module.h>
+#include <pjsip/sip_endpoint.h>
+#include <pjsip/sip_util.h>
+
+/* Transport layer */
+#include <pjsip/sip_transport.h>
+#include <pjsip/sip_transport_udp.h>
+#include <pjsip/sip_transport_loop.h>
+#include <pjsip/sip_transport_tcp.h>
+#include <pjsip/sip_transport_tls.h>
+#include <pjsip/sip_resolve.h>
+
+/* Authentication. */
+#include <pjsip/sip_auth.h>
+#include <pjsip/sip_auth_aka.h>
+
+/* Transaction layer. */
+#include <pjsip/sip_transaction.h>
+
+/* UA Layer. */
+#include <pjsip/sip_ua_layer.h>
+#include <pjsip/sip_dialog.h>
+
+
+#endif /* __PJSIP_H__ */
+
diff --git a/pjsip/include/pjsip/print_util.h b/pjsip/include/pjsip/print_util.h
new file mode 100644
index 0000000..c27d14a
--- /dev/null
+++ b/pjsip/include/pjsip/print_util.h
@@ -0,0 +1,141 @@
+/* $Id: print_util.h 3553 2011-05-05 06:14:19Z nanang $ */
+/*
+ * 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_PRINT_H__
+#define __PJSIP_PRINT_H__
+
+#define copy_advance_check(buf,str) \
+ do { \
+ if ((str).slen >= (endbuf-buf)) return -1; \
+ pj_memcpy(buf, (str).ptr, (str).slen); \
+ buf += (str).slen; \
+ } while (0)
+
+#define copy_advance_pair_check(buf,str1,len1,str2) \
+ do { \
+ if (str2.slen) { \
+ printed = len1+str2.slen; \
+ if (printed >= (endbuf-buf)) return -1; \
+ pj_memcpy(buf,str1,len1); \
+ pj_memcpy(buf+len1, str2.ptr, str2.slen); \
+ buf += printed; \
+ } \
+ } while (0)
+
+#define copy_advance_pair_quote_check(buf,str1,len1,str2,quotebegin,quoteend) \
+ do { \
+ if (str2.slen) { \
+ printed = len1+str2.slen+2; \
+ if (printed >= (endbuf-buf)) return -1; \
+ pj_memcpy(buf,str1,len1); \
+ *(buf+len1)=quotebegin; \
+ pj_memcpy(buf+len1+1, str2.ptr, str2.slen); \
+ *(buf+printed-1) = quoteend; \
+ buf += printed; \
+ } \
+ } while (0)
+
+#define copy_advance_pair_quote(buf,str1,len1,str2,quotebegin,quoteend) \
+ do { \
+ printed = len1+str2.slen+2; \
+ if (printed >= (endbuf-buf)) return -1; \
+ pj_memcpy(buf,str1,len1); \
+ *(buf+len1)=quotebegin; \
+ pj_memcpy(buf+len1+1, str2.ptr, str2.slen); \
+ *(buf+printed-1) = quoteend; \
+ buf += printed; \
+ } while (0)
+
+#define copy_advance_pair_escape(buf,str1,len1,str2,unres) \
+ do { \
+ if (str2.slen) { \
+ if (len1+str2.slen >= (endbuf-buf)) return -1; \
+ pj_memcpy(buf,str1,len1); \
+ printed=pj_strncpy2_escape(buf+len1,&str2,(endbuf-buf-len1),&unres);\
+ if (printed < 0) return -1; \
+ buf += (printed+len1); \
+ } \
+ } while (0)
+
+
+#define copy_advance_no_check(buf,str) \
+ do { \
+ pj_memcpy(buf, (str).ptr, (str).slen); \
+ buf += (str).slen; \
+ } while (0)
+
+#define copy_advance_escape(buf,str,unres) \
+ do { \
+ printed = \
+ pj_strncpy2_escape(buf, &(str), (endbuf-buf), &(unres)); \
+ if (printed < 0) return -1; \
+ buf += printed; \
+ } while (0)
+
+#define copy_advance_pair_no_check(buf,str1,len1,str2) \
+ if (str2.slen) { \
+ pj_memcpy(buf,str1,len1); \
+ pj_memcpy(buf+len1, str2.ptr, str2.slen); \
+ buf += len1+str2.slen; \
+ }
+
+#define copy_advance copy_advance_check
+#define copy_advance_pair copy_advance_pair_check
+
+#define copy_advance_pair_quote_cond(buf,str1,len1,str2,quotebegin,quoteend) \
+ do { \
+ if (str2.slen && *str2.ptr!=quotebegin) \
+ copy_advance_pair_quote(buf,str1,len1,str2,quotebegin,quoteend); \
+ else \
+ copy_advance_pair(buf,str1,len1,str2); \
+ } while (0)
+
+/*
+ * Internal type declarations.
+ */
+typedef void* (*pjsip_hdr_clone_fptr)(pj_pool_t *, const void*);
+typedef int (*pjsip_hdr_print_fptr)(void *hdr, char *buf, pj_size_t len);
+
+typedef struct pjsip_hdr_name_info_t
+{
+ char *name;
+ unsigned name_len;
+ char *sname;
+} pjsip_hdr_name_info_t;
+
+extern const pjsip_hdr_name_info_t pjsip_hdr_names[];
+
+PJ_INLINE(void) init_hdr(void *hptr, pjsip_hdr_e htype, void *vptr)
+{
+ pjsip_hdr *hdr = (pjsip_hdr*) hptr;
+ hdr->type = htype;
+ hdr->name.ptr = pjsip_hdr_names[htype].name;
+ hdr->name.slen = pjsip_hdr_names[htype].name_len;
+ if (pjsip_hdr_names[htype].sname) {
+ hdr->sname.ptr = pjsip_hdr_names[htype].sname;
+ hdr->sname.slen = 1;
+ } else {
+ hdr->sname = hdr->name;
+ }
+ hdr->vptr = (pjsip_hdr_vptr*) vptr;
+ pj_list_init(hdr);
+}
+
+#endif /* __PJSIP_PRINT_H__ */
+
diff --git a/pjsip/include/pjsip/sip_auth.h b/pjsip/include/pjsip/sip_auth.h
new file mode 100644
index 0000000..613e0d5
--- /dev/null
+++ b/pjsip/include/pjsip/sip_auth.h
@@ -0,0 +1,519 @@
+/* $Id: sip_auth.h 3553 2011-05-05 06:14:19Z nanang $ */
+/*
+ * 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_AUTH_SIP_AUTH_H__
+#define __PJSIP_AUTH_SIP_AUTH_H__
+
+/**
+ * @file pjsip_auth.h
+ * @brief SIP Authorization Module.
+ */
+
+#include <pjsip/sip_config.h>
+#include <pjsip/sip_auth_msg.h>
+
+PJ_BEGIN_DECL
+
+/**
+ * @addtogroup PJSIP_AUTH
+ * @ingroup PJSIP_CORE
+ * @brief Client and server side authentication framework.
+ */
+
+/**
+ * @defgroup PJSIP_AUTH_API Authentication API's
+ * @ingroup PJSIP_AUTH
+ * @brief Structures and functions to perform authentication.
+ * @{
+ */
+
+/** Length of digest string. */
+#define PJSIP_MD5STRLEN 32
+
+
+/** Type of data in the credential information in #pjsip_cred_info. */
+typedef enum pjsip_cred_data_type
+{
+ PJSIP_CRED_DATA_PLAIN_PASSWD=0, /**< Plain text password. */
+ PJSIP_CRED_DATA_DIGEST =1, /**< Hashed digest. */
+
+ PJSIP_CRED_DATA_EXT_AKA =16 /**< Extended AKA info is available */
+
+} pjsip_cred_data_type;
+
+/** Authentication's quality of protection (qop) type. */
+typedef enum pjsip_auth_qop_type
+{
+ PJSIP_AUTH_QOP_NONE, /**< No quality of protection. */
+ PJSIP_AUTH_QOP_AUTH, /**< Authentication. */
+ PJSIP_AUTH_QOP_AUTH_INT, /**< Authentication with integrity protection. */
+ PJSIP_AUTH_QOP_UNKNOWN /**< Unknown protection. */
+} pjsip_auth_qop_type;
+
+
+/**
+ * Type of callback function to create authentication response.
+ * Application can specify this callback in \a cb field of the credential info
+ * (#pjsip_cred_info) and specifying PJSIP_CRED_DATA_DIGEST_CALLBACK as
+ * \a data_type. When this function is called, most of the fields in the
+ * \a auth authentication response will have been filled by the framework.
+ * Application normally should just need to calculate the response digest
+ * of the authentication response.
+ *
+ * @param pool Pool to allocate memory from if application needs to.
+ * @param chal The authentication challenge sent by server in 401
+ * or 401 response, in either Proxy-Authenticate or
+ * WWW-Authenticate header.
+ * @param cred The credential that has been selected by the framework
+ * to authenticate against the challenge.
+ * @param auth The authentication response which application needs to
+ * calculate the response digest.
+ *
+ * @return Application may return non-PJ_SUCCESS to abort the
+ * authentication process. When this happens, the
+ * framework will return failure to the original function
+ * that requested authentication.
+ */
+typedef pj_status_t (*pjsip_cred_cb)(pj_pool_t *pool,
+ const pjsip_digest_challenge *chal,
+ const pjsip_cred_info *cred,
+ const pj_str_t *method,
+ pjsip_digest_credential *auth);
+
+
+/**
+ * This structure describes credential information.
+ * A credential information is a static, persistent information that identifies
+ * username and password required to authorize to a specific realm.
+ *
+ * Note that since PJSIP 0.7.0.1, it is possible to make a credential that is
+ * valid for any realms, by setting the realm to star/wildcard character,
+ * i.e. realm = pj_str("*");.
+ */
+struct pjsip_cred_info
+{
+ pj_str_t realm; /**< Realm. Use "*" to make a credential that
+ can be used to authenticate against any
+ challenges. */
+ pj_str_t scheme; /**< Scheme (e.g. "digest"). */
+ pj_str_t username; /**< User name. */
+ int data_type; /**< Type of data (0 for plaintext passwd). */
+ pj_str_t data; /**< The data, which can be a plaintext
+ password or a hashed digest. */
+
+ /** Extended data */
+ union {
+ /** Digest AKA credential information. Note that when AKA credential
+ * is being used, the \a data field of this #pjsip_cred_info is
+ * not used, but it still must be initialized to an empty string.
+ * Please see \ref PJSIP_AUTH_AKA_API for more information.
+ */
+ struct {
+ pj_str_t k; /**< Permanent subscriber key. */
+ pj_str_t op; /**< Operator variant key. */
+ pj_str_t amf; /**< Authentication Management Field */
+ pjsip_cred_cb cb; /**< Callback to create AKA digest. */
+ } aka;
+
+ } ext;
+};
+
+/**
+ * This structure describes cached value of previously sent Authorization
+ * or Proxy-Authorization header. The authentication framework keeps a list
+ * of this structure and will resend the same header to the same server
+ * as long as the method, uri, and nonce stays the same.
+ */
+typedef struct pjsip_cached_auth_hdr
+{
+ /** Standard list member */
+ PJ_DECL_LIST_MEMBER(struct pjsip_cached_auth_hdr);
+
+ pjsip_method method; /**< To quickly see the method. */
+ pjsip_authorization_hdr *hdr; /**< The cached header. */
+
+} pjsip_cached_auth_hdr;
+
+
+/**
+ * This structure describes authentication information for the specified
+ * realm. Each instance of this structure describes authentication "session"
+ * between this endpoint and remote server. This "session" information is
+ * usefull to keep information that persists for more than one challenge,
+ * such as nonce-count and cnonce value.
+ *
+ * Other than that, this structure also keeps the last authorization headers
+ * that have been sent in the cache list.
+ */
+typedef struct pjsip_cached_auth
+{
+ /** Standard list member */
+ PJ_DECL_LIST_MEMBER(struct pjsip_cached_auth);
+
+ pj_str_t realm; /**< Realm. */
+ pj_bool_t is_proxy; /**< Server type (401/407) */
+ pjsip_auth_qop_type qop_value; /**< qop required by server. */
+ unsigned stale_cnt; /**< Number of stale retry. */
+#if PJSIP_AUTH_QOP_SUPPORT
+ pj_uint32_t nc; /**< Nonce count. */
+ pj_str_t cnonce; /**< Cnonce value. */
+#endif
+ pjsip_www_authenticate_hdr *last_chal; /**< Last challenge seen. */
+#if PJSIP_AUTH_HEADER_CACHING
+ pjsip_cached_auth_hdr cached_hdr;/**< List of cached header for
+ each method. */
+#endif
+
+} pjsip_cached_auth;
+
+
+/**
+ * This structure describes client authentication session preference.
+ * The preference can be set by calling #pjsip_auth_clt_set_prefs().
+ */
+typedef struct pjsip_auth_clt_pref
+{
+ /**
+ * If this flag is set, the authentication client framework will
+ * send an empty Authorization header in each initial request.
+ * Default is no.
+ */
+ pj_bool_t initial_auth;
+
+ /**
+ * Specify the algorithm to use when empty Authorization header
+ * is to be sent for each initial request (see above)
+ */
+ pj_str_t algorithm;
+
+} pjsip_auth_clt_pref;
+
+
+/**
+ * Duplicate a client authentication preference setting.
+ *
+ * @param pool The memory pool.
+ * @param dst Destination client authentication preference.
+ * @param src Source client authentication preference.
+ */
+PJ_DECL(void) pjsip_auth_clt_pref_dup(pj_pool_t *pool,
+ pjsip_auth_clt_pref *dst,
+ const pjsip_auth_clt_pref *src);
+
+
+/**
+ * This structure describes client authentication sessions. It keeps
+ * all the information needed to authorize the client against all downstream
+ * servers.
+ */
+typedef struct pjsip_auth_clt_sess
+{
+ pj_pool_t *pool; /**< Pool to use. */
+ pjsip_endpoint *endpt; /**< Endpoint where this belongs. */
+ pjsip_auth_clt_pref pref; /**< Preference/options. */
+ unsigned cred_cnt; /**< Number of credentials. */
+ pjsip_cred_info *cred_info; /**< Array of credential information*/
+ pjsip_cached_auth cached_auth; /**< Cached authorization info. */
+
+} pjsip_auth_clt_sess;
+
+
+/**
+ * Duplicate a credential info.
+ *
+ * @param pool The memory pool.
+ * @param dst Destination credential.
+ * @param src Source credential.
+ */
+PJ_DECL(void) pjsip_cred_info_dup(pj_pool_t *pool,
+ pjsip_cred_info *dst,
+ const pjsip_cred_info *src);
+
+/**
+ * Compare two credential infos.
+ *
+ * @param cred1 The credential info to compare.
+ * @param cred2 The credential info to compare.
+ *
+ * @return 0 if both credentials are equal.
+ */
+PJ_DECL(int) pjsip_cred_info_cmp(const pjsip_cred_info *cred1,
+ const pjsip_cred_info *cred2);
+
+
+/**
+ * Type of function to lookup credential for the specified name.
+ *
+ * @param pool Pool to initialize the credential info.
+ * @param realm Realm to find the account.
+ * @param acc_name Account name to look for.
+ * @param cred_info The structure to put the credential when it's found.
+ *
+ * @return The function MUST return PJ_SUCCESS when it found
+ * a correct credential for the specified account and
+ * realm. Otherwise it may return PJSIP_EAUTHACCNOTFOUND
+ * or PJSIP_EAUTHACCDISABLED.
+ */
+typedef pj_status_t pjsip_auth_lookup_cred( pj_pool_t *pool,
+ const pj_str_t *realm,
+ const pj_str_t *acc_name,
+ pjsip_cred_info *cred_info );
+
+/** Flag to specify that server is a proxy. */
+#define PJSIP_AUTH_SRV_IS_PROXY 1
+
+/**
+ * This structure describes server authentication information.
+ */
+typedef struct pjsip_auth_srv
+{
+ pj_str_t realm; /**< Realm to serve. */
+ pj_bool_t is_proxy; /**< Will issue 407 instead of 401 */
+ pjsip_auth_lookup_cred *lookup; /**< Lookup function. */
+
+} pjsip_auth_srv;
+
+
+/**
+ * Initialize client authentication session data structure, and set the
+ * session to use pool for its subsequent memory allocation. The argument
+ * options should be set to zero for this PJSIP version.
+ *
+ * @param sess The client authentication session.
+ * @param endpt Endpoint where this session belongs.
+ * @param pool Pool to use.
+ * @param options Must be zero.
+ *
+ * @return PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjsip_auth_clt_init( pjsip_auth_clt_sess *sess,
+ pjsip_endpoint *endpt,
+ pj_pool_t *pool,
+ unsigned options);
+
+
+/**
+ * Clone client initialization session.
+ *
+ * @param pool Pool to use.
+ * @param sess Structure to put the duplicated session.
+ * @param rhs The client session to be cloned.
+ *
+ * @return PJ_SUCCESS on success;
+ */
+PJ_DECL(pj_status_t) pjsip_auth_clt_clone( pj_pool_t *pool,
+ pjsip_auth_clt_sess *sess,
+ const pjsip_auth_clt_sess *rhs);
+
+/**
+ * Set the credentials to be used during the session. This will duplicate
+ * the specified credentials using client authentication's pool.
+ *
+ * @param sess The client authentication session.
+ * @param cred_cnt Number of credentials.
+ * @param c Array of credentials.
+ *
+ * @return PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjsip_auth_clt_set_credentials( pjsip_auth_clt_sess *sess,
+ int cred_cnt,
+ const pjsip_cred_info *c);
+
+
+/**
+ * Set the preference for the client authentication session.
+ *
+ * @param sess The client authentication session.
+ * @param p Preference.
+ *
+ * @return PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjsip_auth_clt_set_prefs(pjsip_auth_clt_sess *sess,
+ const pjsip_auth_clt_pref *p);
+
+
+/**
+ * Get the preference for the client authentication session.
+ *
+ * @param sess The client authentication session.
+ * @param p Pointer to receive the preference.
+ *
+ * @return PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjsip_auth_clt_get_prefs(pjsip_auth_clt_sess *sess,
+ pjsip_auth_clt_pref *p);
+
+/**
+ * Initialize new request message with authorization headers.
+ * This function will put Authorization/Proxy-Authorization headers to the
+ * outgoing request message. If caching is enabled (PJSIP_AUTH_HEADER_CACHING)
+ * and the session has previously sent Authorization/Proxy-Authorization header
+ * with the same method, then the same Authorization/Proxy-Authorization header
+ * will be resent from the cache only if qop is not present. If the stack is
+ * configured to automatically generate next Authorization/Proxy-Authorization
+ * headers (PJSIP_AUTH_AUTO_SEND_NEXT flag), then new Authorization/Proxy-
+ * Authorization headers are calculated and generated when they are not present
+ * in the case or if authorization session has qop.
+ *
+ * If both PJSIP_AUTH_HEADER_CACHING flag and PJSIP_AUTH_AUTO_SEND_NEXT flag
+ * are not set, this function will do nothing. The stack then will only send
+ * Authorization/Proxy-Authorization to respond 401/407 response.
+ *
+ * @param sess The client authentication session.
+ * @param tdata The request message to be initialized.
+ *
+ * @return PJ_SUCCESS if successfull.
+ */
+PJ_DECL(pj_status_t) pjsip_auth_clt_init_req( pjsip_auth_clt_sess *sess,
+ pjsip_tx_data *tdata );
+
+
+/**
+ * Call this function when a transaction failed with 401 or 407 response.
+ * This function will reinitialize the original request message with the
+ * authentication challenge found in the response message, and add the
+ * new authorization header in the authorization cache.
+ *
+ * Note that upon return the reference counter of the new transmit data
+ * will be set to 1.
+ *
+ * @param sess The client authentication session.
+ * @param rdata The response message containing 401/407 status.
+ * @param old_request The original request message, which will be re-
+ * created with authorization info.
+ * @param new_request Pointer to receive new request message which
+ * will contain all required authorization headers.
+ *
+ * @return PJ_SUCCESS if new request can be successfully
+ * created to respond all the authentication
+ * challenges.
+ */
+PJ_DECL(pj_status_t) pjsip_auth_clt_reinit_req( pjsip_auth_clt_sess *sess,
+ const pjsip_rx_data *rdata,
+ pjsip_tx_data *old_request,
+ pjsip_tx_data **new_request );
+
+/**
+ * Initialize server authorization session data structure to serve the
+ * specified realm and to use lookup_func function to look for the credential
+ * info.
+ *
+ * @param pool Pool used to initialize the authentication server.
+ * @param auth_srv The authentication server structure.
+ * @param realm Realm to be served by the server.
+ * @param lookup Account lookup function.
+ * @param options Options, bitmask of:
+ * - PJSIP_AUTH_SRV_IS_PROXY: to specify that the server
+ * will authorize clients as a proxy server (instead of
+ * as UAS), which means that Proxy-Authenticate will
+ * be used instead of WWW-Authenticate.
+ *
+ * @return PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjsip_auth_srv_init( pj_pool_t *pool,
+ pjsip_auth_srv *auth_srv,
+ const pj_str_t *realm,
+ pjsip_auth_lookup_cred *lookup,
+ unsigned options );
+
+
+/**
+ * Request the authorization server framework to verify the authorization
+ * information in the specified request in rdata.
+ *
+ * @param auth_srv The server authentication structure.
+ * @param rdata Incoming request to be authenticated.
+ * @param status_code When not null, it will be filled with suitable
+ * status code to be sent to the client.
+ *
+ * @return PJ_SUCCESS if request is successfully authenticated.
+ * Otherwise the function may return one of the
+ * following error codes:
+ * - PJSIP_EAUTHNOAUTH
+ * - PJSIP_EINVALIDAUTHSCHEME
+ * - PJSIP_EAUTHACCNOTFOUND
+ * - PJSIP_EAUTHACCDISABLED
+ * - PJSIP_EAUTHINVALIDREALM
+ * - PJSIP_EAUTHINVALIDDIGEST
+ */
+PJ_DECL(pj_status_t) pjsip_auth_srv_verify( pjsip_auth_srv *auth_srv,
+ pjsip_rx_data *rdata,
+ int *status_code );
+
+
+/**
+ * Add authentication challenge headers to the outgoing response in tdata.
+ * Application may specify its customized nonce and opaque for the challenge,
+ * or can leave the value to NULL to make the function fills them in with
+ * random characters.
+ *
+ * @param auth_srv The server authentication structure.
+ * @param qop Optional qop value.
+ * @param nonce Optional nonce value.
+ * @param opaque Optional opaque value.
+ * @param stale Stale indication.
+ * @param tdata The outgoing response message. The response must have
+ * 401 or 407 response code.
+ *
+ * @return PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjsip_auth_srv_challenge( pjsip_auth_srv *auth_srv,
+ const pj_str_t *qop,
+ const pj_str_t *nonce,
+ const pj_str_t *opaque,
+ pj_bool_t stale,
+ pjsip_tx_data *tdata);
+
+/**
+ * Helper function to create MD5 digest out of the specified
+ * parameters.
+ *
+ * @param result String to store the response digest. This string
+ * must have been preallocated by caller with the
+ * buffer at least PJSIP_MD5STRLEN (32 bytes) in size.
+ * @param nonce Optional nonce.
+ * @param nc Nonce count.
+ * @param cnonce Optional cnonce.
+ * @param qop Optional qop.
+ * @param uri URI.
+ * @param realm Realm.
+ * @param cred_info Credential info.
+ * @param method SIP method.
+ */
+PJ_DECL(void) pjsip_auth_create_digest(pj_str_t *result,
+ const pj_str_t *nonce,
+ const pj_str_t *nc,
+ const pj_str_t *cnonce,
+ const pj_str_t *qop,
+ const pj_str_t *uri,
+ const pj_str_t *realm,
+ const pjsip_cred_info *cred_info,
+ const pj_str_t *method);
+
+/**
+ * @}
+ */
+
+
+
+PJ_END_DECL
+
+
+#endif /* __PJSIP_AUTH_SIP_AUTH_H__ */
+
diff --git a/pjsip/include/pjsip/sip_auth_aka.h b/pjsip/include/pjsip/sip_auth_aka.h
new file mode 100644
index 0000000..0665bf2
--- /dev/null
+++ b/pjsip/include/pjsip/sip_auth_aka.h
@@ -0,0 +1,213 @@
+/* $Id: sip_auth_aka.h 3553 2011-05-05 06:14:19Z nanang $ */
+/*
+ * 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_AUTH_SIP_AUTH_AKA_H__
+#define __PJSIP_AUTH_SIP_AUTH_AKA_H__
+
+/**
+ * @file sip_auth_aka.h
+ * @brief SIP Digest AKA Authorization Module.
+ */
+
+#include <pjsip/sip_auth.h>
+
+PJ_BEGIN_DECL
+
+/**
+ * @defgroup PJSIP_AUTH_AKA_API Digest AKAv1 and AKAv2 Authentication API
+ * @ingroup PJSIP_AUTH_API
+ * @brief Digest AKAv1 and AKAv2 Authentication API
+ * @{
+ *
+ * This module implements HTTP digest authentication using Authentication
+ * and Key Agreement (AKA) version 1 and version 2 (AKAv1-MD5 and AKAv2-MD5),
+ * as specified in RFC 3310 and RFC 4169. SIP AKA authentication is used
+ * by 3GPP and IMS systems.
+ *
+ * @section pjsip_aka_using Using Digest AKA Authentication
+ *
+ * Support for digest AKA authentication is currently made optional, so
+ * application needs to declare \a PJSIP_HAS_DIGEST_AKA_AUTH to non-zero
+ * in <tt>config_site.h</tt> to enable AKA support:
+ *
+ @code
+ #define PJSIP_HAS_DIGEST_AKA_AUTH 1
+ @endcode
+
+ *
+ * In addition, application would need to link with <b>libmilenage</b>
+ * library from \a third_party directory.
+ *
+ * Application then specifies digest AKA credential by initializing the
+ * authentication credential as follows:
+ *
+ @code
+
+ pjsip_cred_info cred;
+
+ pj_bzero(&cred, sizeof(cred));
+
+ cred.scheme = pj_str("Digest");
+ cred.realm = pj_str("ims-domain.test");
+ cred.username = pj_str("user@ims-domain.test");
+ cred.data_type = PJSIP_CRED_DATA_PLAIN_PASSWD | PJSIP_CRED_DATA_EXT_AKA;
+ cred.data = pj_str("password");
+
+ // AKA extended info
+ cred.ext.aka.k = pj_str("password");
+ cred.ext.aka.cb = &pjsip_auth_create_aka_response
+
+ @endcode
+ *
+ * Description:
+ * - To support AKA, application adds \a PJSIP_CRED_DATA_EXT_AKA flag in the
+ * \a data_type field. This indicates that extended information specific to
+ * AKA authentication is available in the credential, and that response
+ * digest computation will use the callback function instead of the usual MD5
+ * digest computation.
+ *
+ * - The \a scheme for the credential is "Digest".
+ *
+ * - The \a realm is the expected realm in the challenge. Application may
+ * also specify wildcard realm ("*") if it wishes to respond to any realms
+ * in the challenge.
+ *
+ * - The \a data field is optional. Application may fill this with the password
+ * if it wants to support both MD5 and AKA MD5 in a single credential. The
+ * pjsip_auth_create_aka_response() function will use this field if the
+ * challenge indicates "MD5" as the algorithm instead of "AKAv1-MD5" or
+ * "AKAv2-MD5".
+ *
+ * - The \a ext.aka.k field specifies the permanent subscriber key to be used
+ * for AKA authentication. Application may specify binary password containing
+ * NULL character in this key, since the length of the key is indicated in
+ * the \a slen field of the string.
+ *
+ * - The \a ext.aka.cb field specifies the callback function to calculate the
+ * response digest. Application can specify pjsip_auth_create_aka_response()
+ * in this field to use PJSIP's implementation, but it's free to provide
+ * it's own function.
+ *
+ * - Optionally application may set \a ext.aka.op and \a ext.aka.amf in the
+ * credential to specify AKA Operator variant key and AKA Authentication
+ * Management Field information.
+ */
+
+/**
+ * Length of Authentication Key (AK) in bytes.
+ */
+#define PJSIP_AKA_AKLEN 6
+
+/**
+ * Length of Authentication Management Field (AMF) in bytes.
+ */
+#define PJSIP_AKA_AMFLEN 2
+
+/**
+ * Length of AUTN in bytes.
+ */
+#define PJSIP_AKA_AUTNLEN 16
+
+/**
+ * Length of Confidentiality Key (CK) in bytes.
+ */
+#define PJSIP_AKA_CKLEN 16
+
+/**
+ * Length of Integrity Key (AK) in bytes.
+ */
+#define PJSIP_AKA_IKLEN 16
+
+/**
+ * Length of permanent/subscriber Key (K) in bytes.
+ */
+#define PJSIP_AKA_KLEN 16
+
+/**
+ * Length of AKA authentication code in bytes.
+ */
+#define PJSIP_AKA_MACLEN 8
+
+/**
+ * Length of operator key in bytes.
+ */
+#define PJSIP_AKA_OPLEN 16
+
+/**
+ * Length of random challenge (RAND) in bytes.
+ */
+#define PJSIP_AKA_RANDLEN 16
+
+/**
+ * Length of response digest in bytes.
+ */
+#define PJSIP_AKA_RESLEN 8
+
+/**
+ * Length of sequence number (SQN) in bytes.
+ */
+#define PJSIP_AKA_SQNLEN 6
+
+/**
+ * This function creates MD5, AKAv1-MD5, or AKAv2-MD5 response for
+ * the specified challenge in \a chal, according to the algorithm
+ * specified in the challenge, and based on the information in the
+ * credential \a cred.
+ *
+ * Application may register this function as \a ext.aka.cb field of
+ * #pjsip_cred_info structure to make PJSIP automatically call this
+ * function to calculate the response digest. To do so, it needs to
+ * add \a PJSIP_CRED_DATA_EXT_AKA flag in the \a data_type field of
+ * the credential, and fills up other AKA specific information in
+ * the credential.
+ *
+ * @param pool Pool to allocate memory.
+ * @param chal The authentication challenge sent by server in 401
+ * or 401 response, as either Proxy-Authenticate or
+ * WWW-Authenticate header.
+ * @param cred The credential to be used.
+ * @param method The request method.
+ * @param auth The digest credential where the digest response
+ * will be placed to. Upon calling this function, the
+ * nonce, nc, cnonce, qop, uri, and realm fields of
+ * this structure must have been set by caller. Upon
+ * return, the \a response field will be initialized
+ * by this function.
+ *
+ * @return PJ_SUCCESS if response has been created successfully.
+ */
+PJ_DECL(pj_status_t) pjsip_auth_create_aka_response(
+ pj_pool_t *pool,
+ const pjsip_digest_challenge*chal,
+ const pjsip_cred_info *cred,
+ const pj_str_t *method,
+ pjsip_digest_credential *auth);
+
+
+/**
+ * @}
+ */
+
+
+
+PJ_END_DECL
+
+
+#endif /* __PJSIP_AUTH_SIP_AUTH_AKA_H__ */
+
diff --git a/pjsip/include/pjsip/sip_auth_msg.h b/pjsip/include/pjsip/sip_auth_msg.h
new file mode 100644
index 0000000..ee6da24
--- /dev/null
+++ b/pjsip/include/pjsip/sip_auth_msg.h
@@ -0,0 +1,252 @@
+/* $Id: sip_auth_msg.h 3553 2011-05-05 06:14:19Z nanang $ */
+/*
+ * 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_AUTH_SIP_AUTH_MSG_H__
+#define __PJSIP_AUTH_SIP_AUTH_MSG_H__
+
+#include <pjsip/sip_msg.h>
+
+PJ_BEGIN_DECL
+
+/**
+ * @addtogroup PJSIP_MSG_HDR
+ * @{
+ */
+
+/**
+ * Common credential structure represents common credential fields
+ * present in Authorization/Proxy-Authorization header.
+ */
+struct pjsip_common_credential
+{
+ pj_str_t realm; /**< Credential's realm. */
+ pjsip_param other_param; /**< Other parameters. */
+};
+
+/**
+ * @see pjsip_common_credential
+ */
+typedef struct pjsip_common_credential pjsip_common_credential;
+
+
+/**
+ * This structure describe credential used in Authorization and
+ * Proxy-Authorization header for digest authentication scheme.
+ */
+struct pjsip_digest_credential
+{
+ pj_str_t realm; /**< Realm of the credential */
+ pjsip_param other_param; /**< Other parameters. */
+ pj_str_t username; /**< Username parameter. */
+ pj_str_t nonce; /**< Nonce parameter. */
+ pj_str_t uri; /**< URI parameter. */
+ pj_str_t response; /**< Response digest. */
+ pj_str_t algorithm; /**< Algorithm. */
+ pj_str_t cnonce; /**< Cnonce. */
+ pj_str_t opaque; /**< Opaque value. */
+ pj_str_t qop; /**< Quality of protection. */
+ pj_str_t nc; /**< Nonce count. */
+};
+
+/**
+ * @see pjsip_digest_credential
+ */
+typedef struct pjsip_digest_credential pjsip_digest_credential;
+
+/**
+ * This structure describe credential used in Authorization and
+ * Proxy-Authorization header for PGP authentication scheme.
+ */
+struct pjsip_pgp_credential
+{
+ pj_str_t realm; /**< Realm. */
+ pjsip_param other_param; /**< Other parameters. */
+ pj_str_t version; /**< Version parameter. */
+ pj_str_t signature; /**< Signature parameter. */
+ pj_str_t signed_by; /**< Signed by parameter. */
+ pj_str_t nonce; /**< Nonce parameter. */
+};
+
+/**
+ * @see pjsip_pgp_credential
+ */
+typedef struct pjsip_pgp_credential pjsip_pgp_credential;
+
+/**
+ * This structure describes SIP Authorization header (and also SIP
+ * Proxy-Authorization header).
+ */
+struct pjsip_authorization_hdr
+{
+ /** Standard header fiends. */
+ PJSIP_DECL_HDR_MEMBER(struct pjsip_authorization_hdr);
+
+ /** Authorization scheme. */
+ pj_str_t scheme;
+
+ /** Type of credentials, depending on the scheme. */
+ union
+ {
+ pjsip_common_credential common; /**< Common fields. */
+ pjsip_digest_credential digest; /**< Digest credentials. */
+ pjsip_pgp_credential pgp; /**< PGP credentials. */
+ } credential;
+};
+
+/**
+ * @see pjsip_authorization_hdr.
+ */
+typedef struct pjsip_authorization_hdr pjsip_authorization_hdr;
+
+/** SIP Proxy-Authorization header shares the same structure as SIP
+ Authorization header.
+ */
+typedef struct pjsip_authorization_hdr pjsip_proxy_authorization_hdr;
+
+/**
+ * Create SIP Authorization header.
+ * @param pool Pool where memory will be allocated from.
+ * @return SIP Authorization header.
+ */
+PJ_DECL(pjsip_authorization_hdr*)
+pjsip_authorization_hdr_create(pj_pool_t *pool);
+
+/**
+ * Create SIP Proxy-Authorization header.
+ * @param pool Pool where memory will be allocated from.
+ * @return SIP Proxy-Authorization header.
+ */
+PJ_DECL(pjsip_proxy_authorization_hdr*)
+pjsip_proxy_authorization_hdr_create(pj_pool_t *pool);
+
+
+/**
+ * This structure describes common fields in authentication challenge
+ * headers (WWW-Authenticate and Proxy-Authenticate).
+ */
+struct pjsip_common_challenge
+{
+ pj_str_t realm; /**< Realm for the challenge. */
+ pjsip_param other_param; /**< Other parameters. */
+};
+
+/**
+ * @see pjsip_common_challenge
+ */
+typedef struct pjsip_common_challenge pjsip_common_challenge;
+
+/**
+ * This structure describes authentication challenge used in Proxy-Authenticate
+ * or WWW-Authenticate for digest authentication scheme.
+ */
+struct pjsip_digest_challenge
+{
+ pj_str_t realm; /**< Realm for the challenge. */
+ pjsip_param other_param; /**< Other parameters. */
+ pj_str_t domain; /**< Domain. */
+ pj_str_t nonce; /**< Nonce challenge. */
+ pj_str_t opaque; /**< Opaque value. */
+ int stale; /**< Stale parameter. */
+ pj_str_t algorithm; /**< Algorithm parameter. */
+ pj_str_t qop; /**< Quality of protection. */
+};
+
+/**
+ * @see pjsip_digest_challenge
+ */
+typedef struct pjsip_digest_challenge pjsip_digest_challenge;
+
+/**
+ * This structure describes authentication challenge used in Proxy-Authenticate
+ * or WWW-Authenticate for PGP authentication scheme.
+ */
+struct pjsip_pgp_challenge
+{
+ pj_str_t realm; /**< Realm for the challenge. */
+ pjsip_param other_param; /**< Other parameters. */
+ pj_str_t version; /**< PGP version. */
+ pj_str_t micalgorithm; /**< micalgorithm parameter. */
+ pj_str_t pubalgorithm; /**< pubalgorithm parameter. */
+ pj_str_t nonce; /**< Nonce challenge. */
+};
+
+/**
+ * @see pjsip_pgp_challenge
+ */
+typedef struct pjsip_pgp_challenge pjsip_pgp_challenge;
+
+/**
+ * This structure describe SIP WWW-Authenticate header (Proxy-Authenticate
+ * header also uses the same structure).
+ */
+struct pjsip_www_authenticate_hdr
+{
+ /** Standard header fields. */
+ PJSIP_DECL_HDR_MEMBER(struct pjsip_www_authenticate_hdr);
+
+ /** Authentication scheme */
+ pj_str_t scheme;
+
+ /** This union contains structures that are only relevant
+ depending on the value of the scheme being used.
+ */
+ union
+ {
+ pjsip_common_challenge common; /**< Common fields. */
+ pjsip_digest_challenge digest; /**< Digest challenge. */
+ pjsip_pgp_challenge pgp; /**< PGP challenge. */
+ } challenge;
+};
+
+/**
+ * WWW-Authenticate header.
+ */
+typedef struct pjsip_www_authenticate_hdr pjsip_www_authenticate_hdr;
+
+/**
+ * Proxy-Authenticate header.
+ */
+typedef struct pjsip_www_authenticate_hdr pjsip_proxy_authenticate_hdr;
+
+
+/**
+ * Create SIP WWW-Authenticate header.
+ *
+ * @param pool Pool where memory will be allocated from.
+ * @return SIP WWW-Authenticate header.
+ */
+PJ_DECL(pjsip_www_authenticate_hdr*)
+pjsip_www_authenticate_hdr_create(pj_pool_t *pool);
+
+/**
+ * Create SIP Proxy-Authenticate header.
+ *
+ * @param pool Pool where memory will be allocated from.
+ * @return SIP Proxy-Authenticate header.
+ */
+PJ_DECL(pjsip_proxy_authenticate_hdr*)
+pjsip_proxy_authenticate_hdr_create(pj_pool_t *pool);
+
+/**
+ * @}
+ */
+
+PJ_END_DECL
+
+#endif /* __PJSIP_AUTH_SIP_AUTH_MSG_H__ */
diff --git a/pjsip/include/pjsip/sip_auth_parser.h b/pjsip/include/pjsip/sip_auth_parser.h
new file mode 100644
index 0000000..703c52f
--- /dev/null
+++ b/pjsip/include/pjsip/sip_auth_parser.h
@@ -0,0 +1,73 @@
+/* $Id: sip_auth_parser.h 3553 2011-05-05 06:14:19Z nanang $ */
+/*
+ * 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_AUTH_SIP_AUTH_PARSER_H__
+#define __PJSIP_AUTH_SIP_AUTH_PARSER_H__
+
+/**
+ * @file sip_auth_parser.h
+ * @brief SIP Authorization Parser Module.
+ */
+
+#include <pj/types.h>
+
+PJ_BEGIN_DECL
+
+/**
+ * Initialize and register authorization parser module.
+ * This will register parser handler for various Authorization related headers
+ * such as Authorization, WWW-Authenticate, Proxy-Authorizization, and
+ * Proxy-Authenticate headers.
+ *
+ * This function is called automatically by the main SIP parser.
+ *
+ * @return PJ_SUCCESS or the appropriate status code.
+ */
+PJ_DECL(pj_status_t) pjsip_auth_init_parser(void);
+
+/**
+ * DeInitialize authorization parser module.
+ */
+PJ_DECL(void) pjsip_auth_deinit_parser();
+
+
+
+extern const pj_str_t pjsip_USERNAME_STR, /**< "username" string const. */
+ pjsip_REALM_STR, /**< "realm" string const. */
+ pjsip_NONCE_STR, /**< "nonce" string const. */
+ pjsip_URI_STR, /**< "uri" string const. */
+ pjsip_RESPONSE_STR, /**< "response" string const. */
+ pjsip_ALGORITHM_STR,/**< "algorithm" string const. */
+ pjsip_DOMAIN_STR, /**< "domain" string const. */
+ pjsip_STALE_STR, /**< "stale" string const. */
+ pjsip_QOP_STR, /**< "qop" string const. */
+ pjsip_CNONCE_STR, /**< "cnonce" string const. */
+ pjsip_OPAQUE_STR, /**< "opaque" string const. */
+ pjsip_NC_STR, /**< "nc" string const. */
+ pjsip_TRUE_STR, /**< "true" string const. */
+ pjsip_FALSE_STR, /**< "false" string const. */
+ pjsip_DIGEST_STR, /**< "digest" string const. */
+ pjsip_PGP_STR, /**< "pgp" string const. */
+ pjsip_MD5_STR, /**< "md5" string const. */
+ pjsip_AUTH_STR; /**< "auth" string const. */
+
+PJ_END_DECL
+
+#endif /* __PJSIP_AUTH_SIP_AUTH_PARSER_H__ */
+
diff --git a/pjsip/include/pjsip/sip_autoconf.h.in b/pjsip/include/pjsip/sip_autoconf.h.in
new file mode 100644
index 0000000..6cae772
--- /dev/null
+++ b/pjsip/include/pjsip/sip_autoconf.h.in
@@ -0,0 +1,39 @@
+/* $Id: sip_autoconf.h.in 3295 2010-08-25 12:51:29Z bennylp $ */
+/*
+ * Copyright (C) 2008-2009 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_AUTOCONF_H__
+#define __PJSIP_SIP_AUTOCONF_H__
+
+/**
+ * @file sip_autoconf.h
+ * @brief Describes operating system specifics (automatically detected by
+ * autoconf)
+ */
+
+/*
+ * Enable/disable TLS transport, as configured by autoconf.
+ * But only do this if user doesn't explicitly configure in pj/config_site.h.
+ */
+/* Since 1.5, the default setting will follow PJ_HAS_SSL_SOCK setting. */
+//#ifndef PJSIP_HAS_TLS_TRANSPORT
+//#undef PJSIP_HAS_TLS_TRANSPORT
+//#endif
+
+#endif /* __PJSIP_SIP_AUTOCONF_H__ */
+
diff --git a/pjsip/include/pjsip/sip_config.h b/pjsip/include/pjsip/sip_config.h
new file mode 100644
index 0000000..9035b1e
--- /dev/null
+++ b/pjsip/include/pjsip/sip_config.h
@@ -0,0 +1,1025 @@
+/* $Id: sip_config.h 4172 2012-06-19 14:35:18Z nanang $ */
+/*
+ * 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_CONFIG_H__
+#define __PJSIP_SIP_CONFIG_H__
+
+/**
+ * @file sip_config.h
+ * @brief Compile time configuration.
+ */
+#include <pj/types.h>
+
+/**
+ * @defgroup PJSIP_CORE Core SIP Library
+ * @brief The core framework from which all other SIP components depends on.
+ *
+ * The PJSIP Core library only provides transport framework, event
+ * dispatching/module framework, and SIP message representation and
+ * parsing. It doesn't do anything usefull in itself!
+ *
+ * If application wants the stack to do anything usefull at all,
+ * it must registers @ref PJSIP_MOD to the core library. Examples
+ * of modules are @ref PJSIP_TRANSACT and @ref PJSUA_UA.
+ */
+
+/**
+ * @defgroup PJSIP_BASE Base Types
+ * @ingroup PJSIP_CORE
+ * @brief Basic PJSIP types and configurations.
+ */
+
+/**
+ * @defgroup PJSIP_CONFIG PJSIP Configurations/Settings
+ * @ingroup PJSIP_BASE
+ * @brief PJSIP compile time configurations.
+ * @{
+ */
+
+/*
+ * Include sip_autoconf.h if autoconf is used (PJ_AUTOCONF is set)
+ */
+#if defined(PJ_AUTOCONF)
+# include <pjsip/sip_autoconf.h>
+#endif
+
+PJ_BEGIN_DECL
+
+/**
+ * This structure describes PJSIP run-time configurations/settings.
+ * Application may use #pjsip_cfg() function to modify the settings
+ * before creating the stack.
+ */
+typedef struct pjsip_cfg_t
+{
+ /** Global settings. */
+ struct {
+ /**
+ * Specify port number should be allowed to appear in To and From
+ * header. Note that RFC 3261 disallow this, see Table 1 in section
+ * 19.1.1 of the RFC. Default is PJSIP_ALLOW_PORT_IN_FROMTO_HDR.
+ */
+ pj_bool_t allow_port_in_fromto_hdr;
+
+ /**
+ * Disable rport in request.
+ */
+ pj_bool_t disable_rport;
+
+ /**
+ * Disable automatic switching from UDP to TCP if outgoing request
+ * is greater than 1300 bytes. See PJSIP_DONT_SWITCH_TO_TCP.
+ */
+ pj_bool_t disable_tcp_switch;
+
+ } endpt;
+
+ /** Transaction layer settings. */
+ struct {
+
+ /** Maximum number of transactions. The value is initialized with
+ * PJSIP_MAX_TSX_COUNT
+ */
+ unsigned max_count;
+
+ /* Timeout values: */
+
+ /** Transaction T1 timeout, in msec. Default value is PJSIP_T1_TIMEOUT
+ */
+ unsigned t1;
+
+ /** Transaction T2 timeout, in msec. Default value is PJSIP_T2_TIMEOUT
+ */
+ unsigned t2;
+
+ /** Transaction completed timer for non-INVITE, in msec. Default value
+ * is PJSIP_T4_TIMEOUT
+ */
+ unsigned t4;
+
+ /** Transaction completed timer for INVITE, in msec. Default value is
+ * PJSIP_TD_TIMEOUT.
+ */
+ unsigned td;
+
+ } tsx;
+
+ /* Dialog layer settings .. TODO */
+
+ /** Client registration settings. */
+ struct {
+ /**
+ * Specify whether client registration should check for its
+ * registered contact in Contact header of successful REGISTER
+ * response to determine whether registration has been successful.
+ * This setting may be disabled if non-compliant registrar is unable
+ * to return correct Contact header.
+ *
+ * Default is PJSIP_REGISTER_CLIENT_CHECK_CONTACT
+ */
+ pj_bool_t check_contact;
+
+ /**
+ * Specify whether client registration should add "x-uid" extension
+ * parameter in all Contact URIs that it registers to assist the
+ * matching of Contact URIs in the 200/OK REGISTER response, in
+ * case the registrar is unable to return exact Contact URI in the
+ * 200/OK response.
+ *
+ * Default is PJSIP_REGISTER_CLIENT_ADD_XUID_PARAM.
+ */
+ pj_bool_t add_xuid_param;
+
+ } regc;
+
+} pjsip_cfg_t;
+
+
+#ifdef PJ_DLL
+/**
+ * Get pjsip configuration instance. Application may modify the
+ * settings before creating the SIP endpoint and modules.
+ *
+ * @return Configuration instance.
+ */
+PJ_DECL(pjsip_cfg_t*) pjsip_cfg(void);
+
+#else /* PJ_DLL */
+
+extern pjsip_cfg_t pjsip_sip_cfg_var;
+
+/**
+ * Get pjsip configuration instance. Application may modify the
+ * settings before creating the SIP endpoint and modules.
+ *
+ * @return Configuration instance.
+ */
+PJ_INLINE(pjsip_cfg_t*) pjsip_cfg(void)
+{
+ return &pjsip_sip_cfg_var;
+}
+
+#endif /* PJ_DLL */
+
+
+/**
+ * Specify maximum transaction count in transaction hash table.
+ * For efficiency, the value should be 2^n-1 since it will be
+ * rounded up to 2^n.
+ *
+ * Default value is 1023
+ */
+#ifndef PJSIP_MAX_TSX_COUNT
+# define PJSIP_MAX_TSX_COUNT (1024-1)
+#endif
+
+/**
+ * Specify maximum number of dialogs in the dialog hash table.
+ * For efficiency, the value should be 2^n-1 since it will be
+ * rounded up to 2^n.
+ *
+ * Default value is 511.
+ */
+#ifndef PJSIP_MAX_DIALOG_COUNT
+# define PJSIP_MAX_DIALOG_COUNT (512-1)
+#endif
+
+
+/**
+ * Specify maximum number of transports.
+ * Default value is equal to maximum number of handles in ioqueue.
+ * See also PJSIP_TPMGR_HTABLE_SIZE.
+ */
+#ifndef PJSIP_MAX_TRANSPORTS
+# define PJSIP_MAX_TRANSPORTS (PJ_IOQUEUE_MAX_HANDLES)
+#endif
+
+
+/**
+ * Transport manager hash table size (must be 2^n-1).
+ * See also PJSIP_MAX_TRANSPORTS
+ */
+#ifndef PJSIP_TPMGR_HTABLE_SIZE
+# define PJSIP_TPMGR_HTABLE_SIZE 31
+#endif
+
+
+/**
+ * Specify maximum URL size.
+ * This constant is used mainly when printing the URL for logging purpose
+ * only.
+ */
+#ifndef PJSIP_MAX_URL_SIZE
+# define PJSIP_MAX_URL_SIZE 256
+#endif
+
+
+/**
+ * Specify maximum number of modules.
+ * This mainly affects the size of mod_data array in various components.
+ */
+#ifndef PJSIP_MAX_MODULE
+# define PJSIP_MAX_MODULE 32
+#endif
+
+
+/**
+ * Maximum packet length. We set it more than MTU since a SIP PDU
+ * containing presence information can be quite large (>1500).
+ */
+#ifndef PJSIP_MAX_PKT_LEN
+# define PJSIP_MAX_PKT_LEN 4000
+#endif
+
+
+/**
+ * RFC 3261 section 18.1.1:
+ * If a request is within 200 bytes of the path MTU, or if it is larger
+ * than 1300 bytes and the path MTU is unknown, the request MUST be sent
+ * using an RFC 2914 [43] congestion controlled transport protocol, such
+ * as TCP.
+ *
+ * Disable the behavior of automatic switching to TCP whenever UDP packet
+ * size exceeds the threshold defined in PJSIP_UDP_SIZE_THRESHOLD.
+ *
+ * This option can also be controlled at run-time by the \a disable_tcp_switch
+ * setting in pjsip_cfg_t.
+ *
+ * Default is 0 (no).
+ */
+#ifndef PJSIP_DONT_SWITCH_TO_TCP
+# define PJSIP_DONT_SWITCH_TO_TCP 0
+#endif
+
+
+/**
+ * This setting controls the threshold of the UDP packet, which if it's
+ * larger than this value the request will be sent with TCP. This setting
+ * is useful only when PJSIP_DONT_SWITCH_TO_TCP is set to 0.
+ *
+ * Default is 1300 bytes.
+ */
+#ifndef PJSIP_UDP_SIZE_THRESHOLD
+# define PJSIP_UDP_SIZE_THRESHOLD 1300
+#endif
+
+
+/**
+ * Encode SIP headers in their short forms to reduce size. By default,
+ * SIP headers in outgoing messages will be encoded in their full names.
+ * If this option is enabled, then SIP headers for outgoing messages
+ * will be encoded in their short forms, to reduce message size.
+ * Note that this does not affect the ability of PJSIP to parse incoming
+ * SIP messages, as the parser always supports parsing both the long
+ * and short version of the headers.
+ *
+ * Note that there is also an undocumented variable defined in sip_msg.c
+ * to control whether compact form should be used for encoding SIP
+ * headers. The default value of this variable is PJSIP_ENCODE_SHORT_HNAME.
+ * To change PJSIP behavior during run-time, application can use the
+ * following construct:
+ *
+ \verbatim
+ extern pj_bool_t pjsip_use_compact_form;
+
+ // enable compact form
+ pjsip_use_compact_form = PJ_TRUE;
+ \endverbatim
+ *
+ * Default is 0 (no)
+ */
+#ifndef PJSIP_ENCODE_SHORT_HNAME
+# define PJSIP_ENCODE_SHORT_HNAME 0
+#endif
+
+
+/**
+ * Send Allow header in dialog establishing requests?
+ * RFC 3261 Allow header SHOULD be included in dialog establishing
+ * requests to inform remote agent about which SIP requests are
+ * allowed within dialog.
+ *
+ * Note that there is also an undocumented variable defined in sip_dialog.c
+ * to control whether Allow header should be included. The default value
+ * of this variable is PJSIP_INCLUDE_ALLOW_HDR_IN_DLG.
+ * To change PJSIP behavior during run-time, application can use the
+ * following construct:
+ *
+ \verbatim
+ extern pj_bool_t pjsip_include_allow_hdr_in_dlg;
+
+ // do not transmit Allow header
+ pjsip_include_allow_hdr_in_dlg = PJ_FALSE;
+ \endverbatim
+ *
+ * Default is 1 (Yes)
+ */
+#ifndef PJSIP_INCLUDE_ALLOW_HDR_IN_DLG
+# define PJSIP_INCLUDE_ALLOW_HDR_IN_DLG 1
+#endif
+
+
+/**
+ * Allow SIP modules removal or insertions during operation?
+ * If yes, then locking will be employed when endpoint need to
+ * access module.
+ */
+#ifndef PJSIP_SAFE_MODULE
+# define PJSIP_SAFE_MODULE 1
+#endif
+
+
+/**
+ * Perform Via sent-by checking as specified in RFC 3261 Section 18.1.2,
+ * which says that UAC MUST silently discard responses with Via sent-by
+ * containing values that the UAC doesn't recognize as its transport
+ * address.
+ *
+ * In PJSIP, this will cause response to be discarded and a message is
+ * written to the log, saying something like:
+ * "Dropping response Response msg 200/INVITE/cseq=608594373 (rdata00A99EF4)
+ * from 1.2.3.4:5060 because sent-by is mismatch"
+ *
+ * The default behavior is yes, but when the UA supports IP address change
+ * for the SIP transport, it will need to turn this checking off since
+ * when the transport address is changed between request is sent and
+ * response is received, the response will be discarded since its Via
+ * sent-by now contains address that is different than the transport
+ * address.
+ */
+#ifndef PJSIP_CHECK_VIA_SENT_BY
+# define PJSIP_CHECK_VIA_SENT_BY 1
+#endif
+
+
+/**
+ * If non-zero, SIP parser will unescape the escape characters ('%')
+ * in the original message, which means that it will modify the
+ * original message. Otherwise the parser will create a copy of
+ * the string and store the unescaped string to the new location.
+ *
+ * Unescaping in-place is faster, but less elegant (and it may
+ * break certain applications). So normally it's disabled, unless
+ * when benchmarking (to show off big performance).
+ *
+ * Default: 0
+ */
+#ifndef PJSIP_UNESCAPE_IN_PLACE
+# define PJSIP_UNESCAPE_IN_PLACE 0
+#endif
+
+
+/**
+ * Specify port number should be allowed to appear in To and From
+ * header. Note that RFC 3261 disallow this, see Table 1 in section
+ * 19.1.1 of the RFC. This setting can also be altered at run-time
+ * via pjsip_cfg setting, see pjsip_cfg_t.allow_port_in_fromto_hdr
+ * field.
+ *
+ * Default: 0
+ */
+#ifndef PJSIP_ALLOW_PORT_IN_FROMTO_HDR
+# define PJSIP_ALLOW_PORT_IN_FROMTO_HDR 0
+#endif
+
+/**
+ * This macro controls maximum numbers of ioqueue events to be processed
+ * in a single pjsip_endpt_handle_events() poll. When PJSIP detects that
+ * there are probably more events available from the network and total
+ * events so far is less than this value, PJSIP will call pj_ioqueue_poll()
+ * again to get more events.
+ *
+ * Value 1 works best for ioqueue with select() back-end, while for IOCP it is
+ * probably best to set this value equal to PJSIP_MAX_TIMED_OUT_ENTRIES
+ * since IOCP only processes one event at a time.
+ *
+ * Default: 1
+ */
+#ifndef PJSIP_MAX_NET_EVENTS
+# define PJSIP_MAX_NET_EVENTS 1
+#endif
+
+
+/**
+ * Max entries to process in timer heap per poll.
+ *
+ * Default: 10
+ */
+#ifndef PJSIP_MAX_TIMED_OUT_ENTRIES
+# define PJSIP_MAX_TIMED_OUT_ENTRIES 10
+#endif
+
+
+/**
+ * Idle timeout interval to be applied to outgoing transports (i.e. client
+ * side) with no usage before the transport is destroyed. Value is in
+ * seconds.
+ *
+ * Note that if the value is put lower than 33 seconds, it may cause some
+ * pjsip test units to fail. See the comment on the following link:
+ * https://trac.pjsip.org/repos/ticket/1465#comment:4
+ *
+ * Default: 33
+ */
+#ifndef PJSIP_TRANSPORT_IDLE_TIME
+# define PJSIP_TRANSPORT_IDLE_TIME 33
+#endif
+
+
+/**
+ * Idle timeout interval to be applied to incoming transports (i.e. server
+ * side) with no usage before the transport is destroyed. Server typically
+ * should let client close the connection, hence set this interval to a large
+ * value. Value is in seconds.
+ *
+ * Default: 600
+ */
+#ifndef PJSIP_TRANSPORT_SERVER_IDLE_TIME
+# define PJSIP_TRANSPORT_SERVER_IDLE_TIME 600
+#endif
+
+
+/**
+ * Maximum number of usages for a transport before a new transport is
+ * created. This only applies for ephemeral transports such as TCP.
+ *
+ * Currently this is not used.
+ *
+ * Default: -1
+ */
+#ifndef PJSIP_MAX_TRANSPORT_USAGE
+# define PJSIP_MAX_TRANSPORT_USAGE ((unsigned)-1)
+#endif
+
+
+/**
+ * The TCP incoming connection backlog number to be set in accept().
+ *
+ * Default: 5
+ *
+ * @see PJSIP_TLS_TRANSPORT_BACKLOG
+ */
+#ifndef PJSIP_TCP_TRANSPORT_BACKLOG
+# define PJSIP_TCP_TRANSPORT_BACKLOG 5
+#endif
+
+
+/**
+ * Set the interval to send keep-alive packet for TCP transports.
+ * If the value is zero, keep-alive will be disabled for TCP.
+ *
+ * Default: 90 (seconds)
+ *
+ * @see PJSIP_TCP_KEEP_ALIVE_DATA
+ */
+#ifndef PJSIP_TCP_KEEP_ALIVE_INTERVAL
+# define PJSIP_TCP_KEEP_ALIVE_INTERVAL 90
+#endif
+
+
+/**
+ * Set the payload of the TCP keep-alive packet.
+ *
+ * Default: CRLF
+ */
+#ifndef PJSIP_TCP_KEEP_ALIVE_DATA
+# define PJSIP_TCP_KEEP_ALIVE_DATA { "\r\n\r\n", 4 }
+#endif
+
+
+/**
+ * Set the interval to send keep-alive packet for TLS transports.
+ * If the value is zero, keep-alive will be disabled for TLS.
+ *
+ * Default: 90 (seconds)
+ *
+ * @see PJSIP_TLS_KEEP_ALIVE_DATA
+ */
+#ifndef PJSIP_TLS_KEEP_ALIVE_INTERVAL
+# define PJSIP_TLS_KEEP_ALIVE_INTERVAL 90
+#endif
+
+
+/**
+ * Set the payload of the TLS keep-alive packet.
+ *
+ * Default: CRLF
+ */
+#ifndef PJSIP_TLS_KEEP_ALIVE_DATA
+# define PJSIP_TLS_KEEP_ALIVE_DATA { "\r\n\r\n", 4 }
+#endif
+
+
+/**
+ * This macro specifies whether full DNS resolution should be used.
+ * When enabled, #pjsip_resolve() will perform asynchronous DNS SRV and
+ * A (or AAAA, when IPv6 is supported) resolution to resolve the SIP
+ * domain.
+ *
+ * Note that even when this setting is enabled, asynchronous DNS resolution
+ * will only be done when application calls #pjsip_endpt_create_resolver(),
+ * configure the nameservers with pj_dns_resolver_set_ns(), and configure
+ * the SIP endpoint's DNS resolver with #pjsip_endpt_set_resolver(). If
+ * these steps are not followed, the domain will be resolved with normal
+ * pj_gethostbyname() function.
+ *
+ * Turning off this setting will save the footprint by about 16KB, since
+ * it should also exclude dns.o and resolve.o from PJLIB-UTIL.
+ *
+ * Default: 1 (enabled)
+ *
+ * @see PJSIP_MAX_RESOLVED_ADDRESSES
+ */
+#ifndef PJSIP_HAS_RESOLVER
+# define PJSIP_HAS_RESOLVER 1
+#endif
+
+
+/**
+ * Maximum number of addresses returned by the resolver. The number here
+ * will slightly affect stack usage, since each entry will occupy about
+ * 32 bytes of stack memory.
+ *
+ * Default: 8
+ *
+ * @see PJSIP_HAS_RESOLVER
+ */
+#ifndef PJSIP_MAX_RESOLVED_ADDRESSES
+# define PJSIP_MAX_RESOLVED_ADDRESSES 8
+#endif
+
+
+/**
+ * Enable TLS SIP transport support. For most systems this means that
+ * OpenSSL must be installed.
+ *
+ * Default: follow PJ_HAS_SSL_SOCK setting, which is 0 (disabled) by default.
+ */
+#ifndef PJSIP_HAS_TLS_TRANSPORT
+# define PJSIP_HAS_TLS_TRANSPORT PJ_HAS_SSL_SOCK
+#endif
+
+
+/**
+ * The TLS pending incoming connection backlog number to be set in accept().
+ *
+ * Default: 5
+ *
+ * @see PJSIP_TCP_TRANSPORT_BACKLOG
+ */
+#ifndef PJSIP_TLS_TRANSPORT_BACKLOG
+# define PJSIP_TLS_TRANSPORT_BACKLOG 5
+#endif
+
+
+
+/* Endpoint. */
+#define PJSIP_MAX_TIMER_COUNT (2*pjsip_cfg()->tsx.max_count + \
+ 2*PJSIP_MAX_DIALOG_COUNT)
+
+/**
+ * Initial memory block for the endpoint.
+ */
+#ifndef PJSIP_POOL_LEN_ENDPT
+# define PJSIP_POOL_LEN_ENDPT (4000)
+#endif
+
+/**
+ * Memory increment for endpoint.
+ */
+#ifndef PJSIP_POOL_INC_ENDPT
+# define PJSIP_POOL_INC_ENDPT (4000)
+#endif
+
+
+/* Transport related constants. */
+
+/**
+ * Initial memory block for rdata.
+ */
+#ifndef PJSIP_POOL_RDATA_LEN
+# define PJSIP_POOL_RDATA_LEN 4000
+#endif
+
+/**
+ * Memory increment for rdata.
+ */
+#ifndef PJSIP_POOL_RDATA_INC
+# define PJSIP_POOL_RDATA_INC 4000
+#endif
+
+#define PJSIP_POOL_LEN_TRANSPORT 512
+#define PJSIP_POOL_INC_TRANSPORT 512
+
+/**
+ * Initial memory block size for tdata.
+ */
+#ifndef PJSIP_POOL_LEN_TDATA
+# define PJSIP_POOL_LEN_TDATA 4000
+#endif
+
+/**
+ * Memory increment for tdata.
+ */
+#ifndef PJSIP_POOL_INC_TDATA
+# define PJSIP_POOL_INC_TDATA 4000
+#endif
+
+/**
+ * Initial memory size for UA layer
+ */
+#ifndef PJSIP_POOL_LEN_UA
+# define PJSIP_POOL_LEN_UA 512
+#endif
+
+/**
+ * Memory increment for UA layer.
+ */
+#ifndef PJSIP_POOL_INC_UA
+# define PJSIP_POOL_INC_UA 512
+#endif
+
+#define PJSIP_MAX_FORWARDS_VALUE 70
+
+#define PJSIP_RFC3261_BRANCH_ID "z9hG4bK"
+#define PJSIP_RFC3261_BRANCH_LEN 7
+
+/* Transaction related constants. */
+
+/**
+ * Initial memory size for transaction layer. The bulk of pool usage
+ * for transaction layer will be used to create the hash table, so
+ * setting this value too high will not help too much with reducing
+ * fragmentation and the memory will most likely be wasted.
+ */
+#ifndef PJSIP_POOL_TSX_LAYER_LEN
+# define PJSIP_POOL_TSX_LAYER_LEN 512
+#endif
+
+/**
+ * Memory increment for transaction layer. The bulk of pool usage
+ * for transaction layer will be used to create the hash table, so
+ * setting this value too high will not help too much with reducing
+ * fragmentation and the memory will most likely be wasted.
+ */
+#ifndef PJSIP_POOL_TSX_LAYER_INC
+# define PJSIP_POOL_TSX_LAYER_INC 512
+#endif
+
+/**
+ * Initial memory size for a SIP transaction object.
+ */
+#ifndef PJSIP_POOL_TSX_LEN
+# define PJSIP_POOL_TSX_LEN 1536 /* 768 */
+#endif
+
+/**
+ * Memory increment for transaction object.
+ */
+#ifndef PJSIP_POOL_TSX_INC
+# define PJSIP_POOL_TSX_INC 256
+#endif
+
+/**
+ * Delay for non-100 1xx retransmission, in seconds.
+ * Set to 0 to disable this feature.
+ *
+ * Default: 60 seconds
+ */
+#ifndef PJSIP_TSX_1XX_RETRANS_DELAY
+# define PJSIP_TSX_1XX_RETRANS_DELAY 60
+#endif
+
+#define PJSIP_MAX_TSX_KEY_LEN (PJSIP_MAX_URL_SIZE*2)
+
+/* User agent. */
+#define PJSIP_POOL_LEN_USER_AGENT 1024
+#define PJSIP_POOL_INC_USER_AGENT 1024
+
+/* Message/URL related constants. */
+#define PJSIP_MAX_CALL_ID_LEN pj_GUID_STRING_LENGTH()
+#define PJSIP_MAX_TAG_LEN pj_GUID_STRING_LENGTH()
+#define PJSIP_MAX_BRANCH_LEN (PJSIP_RFC3261_BRANCH_LEN + pj_GUID_STRING_LENGTH() + 2)
+#define PJSIP_MAX_HNAME_LEN 64
+
+/* Dialog related constants. */
+#define PJSIP_POOL_LEN_DIALOG 1200
+#define PJSIP_POOL_INC_DIALOG 512
+
+/* Maximum header types. */
+#define PJSIP_MAX_HEADER_TYPES 72
+
+/* Maximum URI types. */
+#define PJSIP_MAX_URI_TYPES 4
+
+/*****************************************************************************
+ * Default timeout settings, in miliseconds.
+ */
+
+/** Transaction T1 timeout value. */
+#if !defined(PJSIP_T1_TIMEOUT)
+# define PJSIP_T1_TIMEOUT 500
+#endif
+
+/** Transaction T2 timeout value. */
+#if !defined(PJSIP_T2_TIMEOUT)
+# define PJSIP_T2_TIMEOUT 4000
+#endif
+
+/** Transaction completed timer for non-INVITE */
+#if !defined(PJSIP_T4_TIMEOUT)
+# define PJSIP_T4_TIMEOUT 5000
+#endif
+
+/** Transaction completed timer for INVITE */
+#if !defined(PJSIP_TD_TIMEOUT)
+# define PJSIP_TD_TIMEOUT 32000
+#endif
+
+
+/*****************************************************************************
+ * Authorization
+ */
+
+/**
+ * If this flag is set, the stack will keep the Authorization/Proxy-Authorization
+ * headers that are sent in a cache. Future requests with the same realm and
+ * the same method will use the headers in the cache (as long as no qop is
+ * required by server).
+ *
+ * Turning on this flag will make authorization process goes faster, but
+ * will grow the memory usage undefinitely until the dialog/registration
+ * session is terminated.
+ *
+ * Default: 0
+ */
+#if !defined(PJSIP_AUTH_HEADER_CACHING)
+# define PJSIP_AUTH_HEADER_CACHING 0
+#endif
+
+/**
+ * If this flag is set, the stack will proactively send Authorization/Proxy-
+ * Authorization header for next requests. If next request has the same method
+ * with any of previous requests, then the last header which is saved in
+ * the cache will be used (if PJSIP_AUTH_CACHING is set). Otherwise a fresh
+ * header will be recalculated. If a particular server has requested qop, then
+ * a fresh header will always be calculated.
+ *
+ * If this flag is NOT set, then the stack will only send Authorization/Proxy-
+ * Authorization headers when it receives 401/407 response from server.
+ *
+ * Turning ON this flag will grow memory usage of a dialog/registration pool
+ * indefinitely until it is terminated, because the stack needs to keep the
+ * last WWW-Authenticate/Proxy-Authenticate challenge.
+ *
+ * Default: 0
+ */
+#if !defined(PJSIP_AUTH_AUTO_SEND_NEXT)
+# define PJSIP_AUTH_AUTO_SEND_NEXT 0
+#endif
+
+/**
+ * Support qop="auth" directive.
+ * This option also requires client to cache the last challenge offered by
+ * server.
+ *
+ * Default: 1
+ */
+#if !defined(PJSIP_AUTH_QOP_SUPPORT)
+# define PJSIP_AUTH_QOP_SUPPORT 1
+#endif
+
+
+/**
+ * Maximum number of stale retries when server keeps rejecting our request
+ * with stale=true.
+ *
+ * Default: 3
+ */
+#ifndef PJSIP_MAX_STALE_COUNT
+# define PJSIP_MAX_STALE_COUNT 3
+#endif
+
+
+/**
+ * Specify support for IMS/3GPP digest AKA authentication version 1 and 2
+ * (AKAv1-MD5 and AKAv2-MD5 respectively).
+ *
+ * Default: 0 (for now)
+ */
+#ifndef PJSIP_HAS_DIGEST_AKA_AUTH
+# define PJSIP_HAS_DIGEST_AKA_AUTH 0
+#endif
+
+
+/**
+ * Specify the number of seconds to refresh the client registration
+ * before the registration expires.
+ *
+ * Default: 5 seconds
+ */
+#ifndef PJSIP_REGISTER_CLIENT_DELAY_BEFORE_REFRESH
+# define PJSIP_REGISTER_CLIENT_DELAY_BEFORE_REFRESH 5
+#endif
+
+
+/**
+ * Specify whether client registration should check for its registered
+ * contact in Contact header of successful REGISTE response to determine
+ * whether registration has been successful. This setting may be disabled
+ * if non-compliant registrar is unable to return correct Contact header.
+ *
+ * This setting can be changed in run-time by settting \a regc.check_contact
+ * field of pjsip_cfg().
+ *
+ * Default is 1
+ */
+#ifndef PJSIP_REGISTER_CLIENT_CHECK_CONTACT
+# define PJSIP_REGISTER_CLIENT_CHECK_CONTACT 1
+#endif
+
+
+/**
+ * Specify whether client registration should add "x-uid" extension
+ * parameter in all Contact URIs that it registers to assist the
+ * matching of Contact URIs in the 200/OK REGISTER response, in
+ * case the registrar is unable to return exact Contact URI in the
+ * 200/OK response.
+ *
+ * This setting can be changed in run-time by setting
+ * \a regc.add_xuid_param field of pjsip_cfg().
+ *
+ * Default is 0.
+ */
+#ifndef PJSIP_REGISTER_CLIENT_ADD_XUID_PARAM
+# define PJSIP_REGISTER_CLIENT_ADD_XUID_PARAM 0
+#endif
+
+
+/*****************************************************************************
+ * SIP Event framework and presence settings.
+ */
+
+/**
+ * Specify the time (in seconds) to send SUBSCRIBE to refresh client
+ * subscription before the actual interval expires.
+ *
+ * Default: 5 seconds
+ */
+#ifndef PJSIP_EVSUB_TIME_UAC_REFRESH
+# define PJSIP_EVSUB_TIME_UAC_REFRESH 5
+#endif
+
+
+/**
+ * Specify the time (in seconds) to send PUBLISH to refresh client
+ * publication before the actual interval expires.
+ *
+ * Default: 5 seconds
+ */
+#ifndef PJSIP_PUBLISHC_DELAY_BEFORE_REFRESH
+# define PJSIP_PUBLISHC_DELAY_BEFORE_REFRESH 5
+#endif
+
+
+/**
+ * Specify the time (in seconds) to wait for the final NOTIFY from the
+ * server after client has sent un-SUBSCRIBE request.
+ *
+ * Default: 5 seconds
+ */
+#ifndef PJSIP_EVSUB_TIME_UAC_TERMINATE
+# define PJSIP_EVSUB_TIME_UAC_TERMINATE 5
+#endif
+
+
+/**
+ * Specify the time (in seconds) for client subscription to wait for another
+ * NOTIFY from the server, if it has rejected the last NOTIFY with non-2xx
+ * final response (such as 401). If further NOTIFY is not received within
+ * this period, the client will unsubscribe.
+ *
+ * Default: 5 seconds
+ */
+#ifndef PJSIP_EVSUB_TIME_UAC_WAIT_NOTIFY
+# define PJSIP_EVSUB_TIME_UAC_WAIT_NOTIFY 5
+#endif
+
+
+/**
+ * Specify the default expiration time for presence event subscription, for
+ * both client and server subscription. For client subscription, application
+ * can override this by specifying positive non-zero value in "expires"
+ * parameter when calling #pjsip_pres_initiate(). For server subscription,
+ * we would take the expiration value from the Expires header sent by client
+ * in the SUBSCRIBE request if the header exists and its value is less than
+ * this setting, otherwise this setting will be used.
+ *
+ * Default: 600 seconds (10 minutes)
+ */
+#ifndef PJSIP_PRES_DEFAULT_EXPIRES
+# define PJSIP_PRES_DEFAULT_EXPIRES 600
+#endif
+
+
+/**
+ * Specify the status code value to respond to bad message body in NOTIFY
+ * request for presence. Scenarios that are considered bad include non-
+ * PIDF/XML and non-XPIDF/XML body, multipart message bodies without PIDF/XML
+ * nor XPIDF/XML part, and bad (parsing error) PIDF and X-PIDF bodies
+ * themselves.
+ *
+ * Default value is 488. Application may change this to 200 to ignore the
+ * unrecognised content (this is useful if the application wishes to handle
+ * the content itself). Only non-3xx final response code is allowed here.
+ *
+ * Default: 488 (Not Acceptable Here)
+ */
+#ifndef PJSIP_PRES_BAD_CONTENT_RESPONSE
+# define PJSIP_PRES_BAD_CONTENT_RESPONSE 488
+#endif
+
+
+/**
+ * Add "timestamp" information in generated PIDF document for both server
+ * subscription and presence publication.
+ *
+ * Default: 1 (yes)
+ */
+#ifndef PJSIP_PRES_PIDF_ADD_TIMESTAMP
+# define PJSIP_PRES_PIDF_ADD_TIMESTAMP 1
+#endif
+
+
+/**
+ * Default session interval for Session Timer (RFC 4028) extension, in
+ * seconds. As specified in RFC 4028 Section 4, this value must not be
+ * less than the absolute minimum for the Session-Expires header field
+ * 90 seconds, and the recommended value is 1800 seconds.
+ *
+ * Default: 1800 seconds
+ */
+#ifndef PJSIP_SESS_TIMER_DEF_SE
+# define PJSIP_SESS_TIMER_DEF_SE 1800
+#endif
+
+
+/**
+ * Specify whether the client publication session should queue the
+ * PUBLISH request should there be another PUBLISH transaction still
+ * pending. If this is set to false, the client will return error
+ * on the PUBLISH request if there is another PUBLISH transaction still
+ * in progress.
+ *
+ * Default: 1 (yes)
+ */
+#ifndef PJSIP_PUBLISHC_QUEUE_REQUEST
+# define PJSIP_PUBLISHC_QUEUE_REQUEST 1
+#endif
+
+
+/**
+ * Specify the default expiration time for Message Waiting Indication
+ * (RFC 3842) event subscription, for both client and server subscription.
+ * For client subscription, application can override this by specifying
+ * positive non-zero value in "expires" parameter when calling
+ * #pjsip_mwi_initiate(). For server subscription, we would take the
+ * expiration value from the Expires header sent by client in the SUBSCRIBE
+ * request if the header exists and its value is less than this setting,
+ * otherwise this setting will be used.
+ *
+ * Default: 3600 seconds
+ */
+#ifndef PJSIP_MWI_DEFAULT_EXPIRES
+# define PJSIP_MWI_DEFAULT_EXPIRES 3600
+#endif
+
+
+PJ_END_DECL
+
+/**
+ * @}
+ */
+
+
+#include <pj/config.h>
+
+
+#endif /* __PJSIP_SIP_CONFIG_H__ */
+
diff --git a/pjsip/include/pjsip/sip_dialog.h b/pjsip/include/pjsip/sip_dialog.h
new file mode 100644
index 0000000..63e12ac
--- /dev/null
+++ b/pjsip/include/pjsip/sip_dialog.h
@@ -0,0 +1,791 @@
+/* $Id: sip_dialog.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_DIALOG_H__
+#define __PJSIP_SIP_DIALOG_H__
+
+
+/**
+ * @file sip_dialog.h
+ * @brief SIP Dialog abstraction
+ */
+
+#include <pjsip/sip_msg.h>
+#include <pjsip/sip_auth.h>
+#include <pjsip/sip_errno.h>
+#include <pjsip/sip_transport.h>
+#include <pjsip/sip_util.h>
+#include <pj/sock.h>
+#include <pj/assert.h>
+
+
+/**
+ * @defgroup PJSIP_DIALOG Base Dialog
+ * @ingroup PJSIP_UA
+ * @brief The base dialog framework to support dialog usages.
+ * @{
+ *
+ * The base dialog framework provides management for base dialog
+ * properties such as <b>From</b> header, <b>To</b> header, <b>CSeq</b>
+ * sequencing, <b>Call-ID</b> header, <b>Contact</b> header management,
+ * dialog <b>route-set</b> management, and common <b>authentication</b>.
+ * This basic dialog functionality will be shared by all <b>dialog
+ * usages</b> of a particular dialog.
+ *
+ * More detailed information is explained in
+ * <A HREF="/docs.htm">PJSIP Developer's Guide</A>
+ * PDF document, and readers are encouraged to read the document to
+ * get the concept behind dialog, dialog usages, and INVITE sessions.
+ *
+ * Application MUST initialize the user agent layer module by calling
+ * #pjsip_ua_init_module() before using any of the dialog API, and link
+ * the application with with <b>pjsip-core</b> library.
+ */
+
+PJ_BEGIN_DECL
+
+
+/**
+ * This structure is used to describe dialog's participants, which in this
+ * case is local party (i.e. us) and remote party.
+ */
+typedef struct pjsip_dlg_party
+{
+ pjsip_fromto_hdr *info; /**< From/To header, inc tag. */
+ pj_str_t info_str; /**< String rep of info header. */
+ pj_uint32_t tag_hval; /**< Hashed value of the tag. */
+ pjsip_contact_hdr *contact; /**< Contact header. */
+ pj_int32_t first_cseq;/**< First CSeq seen. */
+ pj_int32_t cseq; /**< Next sequence number. */
+} pjsip_dlg_party;
+
+
+/**
+ * Dialog state.
+ */
+typedef enum pjsip_dialog_state
+{
+ /** Dialog is not established. */
+ PJSIP_DIALOG_STATE_NULL,
+
+ /** Dialog has been established (probably early) */
+ PJSIP_DIALOG_STATE_ESTABLISHED
+} pjsip_dialog_state;
+
+
+/**
+ * Dialog capability status.
+ */
+typedef enum pjsip_dialog_cap_status
+{
+ /** Capability is unsupported. */
+ PJSIP_DIALOG_CAP_UNSUPPORTED = 0,
+
+ /** Capability is supported */
+ PJSIP_DIALOG_CAP_SUPPORTED = 1,
+
+ /**
+ * Unknown capability status. This is usually because we lack the
+ * capability info which is retrieved from capability header specified
+ * in the dialog messages.
+ */
+ PJSIP_DIALOG_CAP_UNKNOWN = 2
+} pjsip_dialog_cap_status;
+
+
+/**
+ * This structure describes the dialog structure. Application MUST NOT
+ * try to SET the values here directly, but instead it MUST use the
+ * appropriate dialog API. The dialog declaration only needs to be made
+ * visible because other PJSIP modules need to see it (e.g. INVITE session,
+ * the event framework, etc.).
+ *
+ * Application MAY READ the dialog contents directly after it acquires
+ * dialog lock.
+ *
+ * To acquire dialog lock, use #pjsip_dlg_inc_lock(), and to release it,
+ * use #pjsip_dlg_dec_lock(). DO NOT USE pj_mutex_lock()/pj_mutex_unlock()
+ * on the dialog's mutex directly, because this will not protect against
+ * dialog being destroyed.
+ */
+struct pjsip_dialog
+{
+ /** The dialog set list. */
+ PJ_DECL_LIST_MEMBER(pjsip_dialog);
+
+ /* Dialog's system properties. */
+ char obj_name[PJ_MAX_OBJ_NAME]; /**< Standard id. */
+ pj_pool_t *pool; /**< Dialog's pool. */
+ pj_mutex_t *mutex_; /**< Dialog's mutex. Do not call!!
+ Use pjsip_dlg_inc_lock() instead! */
+ pjsip_user_agent *ua; /**< User agent instance. */
+ pjsip_endpoint *endpt; /**< Endpoint instance. */
+
+ /** The dialog set which this dialog belongs (opaque type). */
+ void *dlg_set;
+
+ /* Dialog's session properties. */
+ pjsip_dialog_state state; /**< Dialog state. */
+ pjsip_uri *target; /**< Current target. */
+ pjsip_target_set target_set; /**< Target set, for UAC only. */
+ pjsip_hdr inv_hdr; /**< Headers from hparam in dest URL */
+ pjsip_dlg_party local; /**< Local party info. */
+ pjsip_dlg_party remote; /**< Remote party info. */
+ pjsip_hdr rem_cap_hdr;/**< List of remote capability header. */
+ pjsip_role_e role; /**< Initial role. */
+ pj_bool_t uac_has_2xx;/**< UAC has received 2xx response? */
+ pj_bool_t secure; /**< Use secure transport? */
+ pj_bool_t add_allow; /**< Add Allow header in requests? */
+ pjsip_cid_hdr *call_id; /**< Call-ID header. */
+ pjsip_route_hdr route_set; /**< Route set. */
+ pj_bool_t route_set_frozen; /**< Route set has been set. */
+ pjsip_auth_clt_sess auth_sess; /**< Client authentication session. */
+
+ /** Session counter. */
+ int sess_count; /**< Number of sessions. */
+
+ /** Transaction counter. */
+ int tsx_count; /**< Number of pending transactions. */
+
+ /** Transport selector. */
+ pjsip_tpselector tp_sel;
+
+ /* Dialog usages. */
+ unsigned usage_cnt; /**< Number of registered usages. */
+ pjsip_module *usage[PJSIP_MAX_MODULE]; /**< Array of usages,
+ priority sorted */
+
+ /** Module specific data. */
+ void *mod_data[PJSIP_MAX_MODULE]; /**< Module data. */
+
+ /**
+ * 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. */
+};
+
+
+/**
+ * This utility function returns PJ_TRUE if the specified method is a
+ * dialog creating request. This method property is used to determine
+ * whether Contact header should be included in outgoing request.
+ *
+ * @param m The SIP method.
+ *
+ * @return PJ_TRUE if the method creates a dialog.
+ */
+PJ_DECL(pj_bool_t) pjsip_method_creates_dialog(const pjsip_method *m);
+
+/**
+ * Create a new dialog and return the instance in p_dlg parameter.
+ * After creating the dialog, application can add modules as dialog usages
+ * by calling #pjsip_dlg_add_usage().
+ *
+ * If the request has To tag parameter, dialog's local tag will be initialized
+ * from this value. Otherwise a globally unique id generator will be invoked to
+ * create dialog's local tag.
+ *
+ * This function also initializes the dialog's route set based on the
+ * Record-Route headers in the request, if present.
+ *
+ * Note that initially, the session count in the dialog will be initialized
+ * to zero.
+ *
+ * @param ua The user agent module instance.
+ * @param local_uri Dialog local URI (i.e. From header).
+ * @param local_contact Optional dialog local Contact to be put as Contact
+ * header value, hence the format must follow
+ * RFC 3261 Section 20.10:
+ * When the header field value contains a display
+ * name, the URI including all URI parameters is
+ * enclosed in "<" and ">". If no "<" and ">" are
+ * present, all parameters after the URI are header
+ * parameters, not URI parameters. The display name
+ * can be tokens, or a quoted string, if a larger
+ * character set is desired.
+ * If this argument is NULL, the Contact will be taken
+ * from the local URI.
+ * @param remote_uri Dialog remote URI (i.e. To header).
+ * @param target Optional initial remote target. If this argument
+ * is NULL, the initial target will be set to
+ * remote URI.
+ * @param p_dlg Pointer to receive the dialog.
+ *
+ * @return PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjsip_dlg_create_uac( pjsip_user_agent *ua,
+ const pj_str_t *local_uri,
+ const pj_str_t *local_contact,
+ const pj_str_t *remote_uri,
+ const pj_str_t *target,
+ pjsip_dialog **p_dlg);
+
+
+/**
+ * Initialize UAS dialog from the information found in the incoming request
+ * that creates a dialog (such as INVITE, REFER, or SUBSCRIBE), and set the
+ * local Contact to contact. If contact is not specified, the local contact
+ * is initialized from the URI in the To header in the request.
+ *
+ * This function will also create UAS transaction for the incoming request,
+ * and associate the transaction to the rdata. Application can query the
+ * transaction used to handle this request by calling #pjsip_rdata_get_tsx()
+ * after this function returns.
+ *
+ * Note that initially, the session count in the dialog will be initialized
+ * to zero.
+ *
+ *
+ * @param ua The user agent module instance.
+ * @param rdata The incoming request that creates the dialog,
+ * such as INVITE, SUBSCRIBE, or REFER.
+ * @param contact Optional dialog local Contact to be put as Contact
+ * header value, hence the format must follow
+ * RFC 3261 Section 20.10:
+ * When the header field value contains a display
+ * name, the URI including all URI parameters is
+ * enclosed in "<" and ">". If no "<" and ">" are
+ * present, all parameters after the URI are header
+ * parameters, not URI parameters. The display name
+ * can be tokens, or a quoted string, if a larger
+ * character set is desired.
+ * If this argument is NULL, the local contact will be
+ * initialized from the value of To header in the
+ * request.
+ * @param p_dlg Pointer to receive the dialog.
+ *
+ * @return PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjsip_dlg_create_uas( pjsip_user_agent *ua,
+ pjsip_rx_data *rdata,
+ const pj_str_t *contact,
+ pjsip_dialog **p_dlg);
+
+
+/**
+ * Lock/bind dialog to a specific transport/listener. This is optional,
+ * as normally transport will be selected automatically based on the
+ * destination of messages upon resolver completion. When the dialog is
+ * explicitly bound to the specific transport/listener, all transactions
+ * originated by this dialog will use the specified transport/listener
+ * when sending outgoing requests.
+ *
+ * Note that this doesn't affect the Contact header generated by this
+ * dialog. Application must manually update the Contact header if
+ * necessary, to adjust the address according to the transport being
+ * selected.
+ *
+ * @param dlg The dialog instance.
+ * @param sel Transport selector containing the specification of
+ * transport or listener to be used by this dialog
+ * to send requests.
+ *
+ * @return PJ_SUCCESS on success, or the appropriate error code.
+ */
+PJ_DECL(pj_status_t) pjsip_dlg_set_transport(pjsip_dialog *dlg,
+ const pjsip_tpselector *sel);
+
+
+/**
+ * Set the "sent-by" field of the Via header for outgoing requests.
+ *
+ * @param dlg The dialog instance.
+ * @param via_addr Set via_addr to use for the Via header or NULL to use
+ * the transport's published name.
+ * @param via_tp via_addr will only be used if we are using via_tp
+ * transport.
+ *
+ * @return PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjsip_dlg_set_via_sent_by(pjsip_dialog *dlg,
+ pjsip_host_port *via_addr,
+ pjsip_transport *via_tp);
+
+
+/**
+ * Create a new (forked) dialog on receipt on forked response in rdata.
+ * The new dialog will be created from original_dlg, except that it will have
+ * new remote tag as copied from the To header in the response. Upon return,
+ * the new_dlg will have been registered to the user agent. Applications just
+ * need to add modules as dialog's usages.
+ *
+ * Note that initially, the session count in the dialog will be initialized
+ * to zero.
+ *
+ * @param original_dlg The original UAC dialog.
+ * @param rdata The incoming forked response message.
+ * @param new_dlg Pointer to receive the new dialog.
+ *
+ * @return PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjsip_dlg_fork(const pjsip_dialog *original_dlg,
+ const pjsip_rx_data *rdata,
+ pjsip_dialog **new_dlg );
+
+/**
+ * Forcefully terminate the dialog. Application can only call this function
+ * when there is no session associated to the dialog. If there are sessions
+ * that use this dialog, this function will refuse to terminate the dialog.
+ * For this case, application MUST call the appropriate termination function
+ * for each dialog session (e.g. #pjsip_inv_terminate() to terminate INVITE
+ * session).
+ *
+ * @param dlg The dialog.
+ *
+ * @return PJ_SUCCESS if dialog has been terminated.
+ */
+PJ_DECL(pj_status_t) pjsip_dlg_terminate( pjsip_dialog *dlg );
+
+
+/**
+ * Set dialog's initial route set to route_set list. This can only be called
+ * for UAC dialog, before any request is sent. After dialog has been
+ * established, the route set can not be changed.
+ *
+ * For UAS dialog,the route set will be initialized in pjsip_dlg_create_uas()
+ * from the Record-Route headers in the incoming request.
+ *
+ * The route_set argument is standard list of Route headers (i.e. with
+ * sentinel).
+ *
+ * @param dlg The UAC dialog.
+ * @param route_set List of Route header.
+ *
+ * @return PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjsip_dlg_set_route_set( pjsip_dialog *dlg,
+ const pjsip_route_hdr *route_set );
+
+/**
+ * Increment the number of sessions in the dialog. Note that initially
+ * (after created) the dialog has the session counter set to zero.
+ *
+ * @param dlg The dialog.
+ * @param mod The module that increments the session counter.
+ *
+ * @return PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjsip_dlg_inc_session( pjsip_dialog *dlg,
+ pjsip_module *mod);
+
+
+/**
+ * Decrement the number of sessions in the dialog. Once the session counter
+ * reach zero and there is no pending transaction, the dialog will be
+ * destroyed. Note that this function may destroy the dialog immediately
+ * if there is no pending transaction when this function is called.
+ *
+ * @param dlg The dialog.
+ * @param mod The module that decrements the session counter.
+ *
+ * @return PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjsip_dlg_dec_session( pjsip_dialog *dlg,
+ pjsip_module *mod);
+
+/**
+ * Add a module as dialog usage, and optionally set the module specific data.
+ *
+ * @param dlg The dialog.
+ * @param module The module to be registered as dialog usage.
+ * @param mod_data Optional arbitrary data to be attached to dialog's
+ * mod_data array at the module's index.
+ *
+ * @return PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjsip_dlg_add_usage( pjsip_dialog *dlg,
+ pjsip_module *module,
+ void *mod_data );
+
+/**
+ * Check if the specified module has been registered as usage to the dialog.
+ *
+ * @param dlg The dialog.
+ * @param module The module.
+ *
+ * @return PJ_TRUE if the specified module is currently
+ * registered as a usage to the dialog.
+ */
+PJ_DECL(pj_bool_t) pjsip_dlg_has_usage(pjsip_dialog *dlg,
+ pjsip_module *module);
+
+/**
+ * Attach module specific data to the dialog. Application can also set
+ * the value directly by accessing dlg->mod_data[module_id].
+ *
+ * @param dlg The dialog
+ * @param mod_id The ID of the module from which the data is to be
+ * set to the dialog.
+ * @param data Arbitrary data.
+ *
+ * @return PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjsip_dlg_set_mod_data( pjsip_dialog *dlg,
+ int mod_id,
+ void *data );
+
+/**
+ * Get module specific data previously attached to the dialog. Application
+ * can also get value directly by accessing dlg->mod_data[module_id].
+ *
+ * @param dlg The dialog
+ * @param mod_id The ID of the module from which the data is to be
+ * retrieved from the dialog.
+ *
+ * @return The data that was previously set, or NULL.
+ */
+PJ_DECL(void*) pjsip_dlg_get_mod_data( pjsip_dialog *dlg,
+ int mod_id);
+
+
+/**
+ * Lock dialog and increment session counter termporarily, to prevent it
+ * from being destroyed.
+ *
+ * @param dlg The dialog.
+ */
+PJ_DECL(void) pjsip_dlg_inc_lock( pjsip_dialog *dlg );
+
+/**
+ * Try to acquire dialog's lock, but return immediately if lock can not
+ * be acquired.
+ *
+ * @param dlg The dialog.
+ *
+ * @return PJ_SUCCESS if lock has been acquired.
+ */
+PJ_DECL(pj_status_t) pjsip_dlg_try_inc_lock( pjsip_dialog *dlg );
+
+/**
+ * Unlock dialog and decrement temporary session counter. After this function
+ * is called, dialog may be destroyed.
+ *
+ * @param dlg The dialog.
+ */
+PJ_DECL(void) pjsip_dlg_dec_lock( pjsip_dialog *dlg );
+
+
+/**
+ * Get the dialog instance in the incoming rdata. If an incoming message
+ * matches an existing dialog, the user agent must have put the matching
+ * dialog instance in the rdata, or otherwise this function will return
+ * NULL if the message didn't match any existing dialog.
+ *
+ * This function can only be called after endpoint distributes the message
+ * to the transaction layer or UA layer. In other words, application can
+ * only call this function in the context of module that runs in priority
+ * number higher than PJSIP_MOD_PRIORITY_UA_PROXY_LAYER.
+ *
+ * @param rdata Incoming message buffer.
+ *
+ * @return The dialog instance that "owns" the message.
+ */
+PJ_DECL(pjsip_dialog*) pjsip_rdata_get_dlg( pjsip_rx_data *rdata );
+
+/**
+ * Get the associated dialog for the specified transaction, if any.
+ *
+ * @param tsx The transaction.
+ *
+ * @return The dialog instance which has been registered
+ * to the transaction as transaction user, or
+ * NULL if the transaction is outside any dialogs.
+ */
+PJ_DECL(pjsip_dialog*) pjsip_tsx_get_dlg( pjsip_transaction *tsx );
+
+
+/**
+ * Create a basic/generic request with the specified method and optionally
+ * specify the cseq. Use value -1 for cseq to have the dialog automatically
+ * put next cseq number for the request. Otherwise for some requests,
+ * e.q. CANCEL and ACK, application must put the CSeq in the original
+ * INVITE request as the parameter.
+ *
+ * This function will also put Contact header where appropriate.
+ *
+ * @param dlg The dialog instance.
+ * @param method The method of the request.
+ * @param cseq Optional CSeq, which only needs to be specified
+ * when creating ACK and CANCEL. For other requests,
+ * specify -1 to use dialog's internal counter.
+ * @param tdata Pointer to receive the request's transmit
+ * data buffer.
+ *
+ * @return PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjsip_dlg_create_request( pjsip_dialog *dlg,
+ const pjsip_method *method,
+ int cseq,
+ pjsip_tx_data **tdata);
+
+
+/**
+ * Send request message to remote peer. If the request is not an ACK request,
+ * the dialog will send the request statefully, by creating an UAC transaction
+ * and send the request with the transaction.
+ *
+ * Also when the request is not ACK or CANCEL, the dialog will increment its
+ * local cseq number and update the cseq in the request according to dialog's
+ * cseq.
+ *
+ * If p_tsx is not null, this argument will be set with the transaction
+ * instance that was used to send the request.
+ *
+ * This function will decrement the transmit data's reference counter
+ * regardless the status of the operation.
+ *
+ * @param dlg The dialog.
+ * @param tdata The request message to be sent.
+ * @param mod_data_id Optional module data index to put an optional data
+ * into the transaction. If no module data is to be
+ * attached, this value should be -1.
+ * @param mod_data Optional module data to be attached to the
+ * transaction at mod_data_id index.
+ *
+ * @return PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjsip_dlg_send_request ( pjsip_dialog *dlg,
+ pjsip_tx_data *tdata,
+ int mod_data_id,
+ void *mod_data);
+
+
+/**
+ * Create a response message for the incoming request in rdata with status
+ * code st_code and optional status text st_text. This function is different
+ * than endpoint's API #pjsip_endpt_create_response() in that the dialog
+ * function adds Contact header and Record-Routes headers in the response
+ * where appropriate.
+ *
+ * @param dlg The dialog.
+ * @param rdata The incoming request message for which the
+ * response will be created.
+ * @param st_code Status code.
+ * @param st_text Optional string for custom status reason text.
+ * @param tdata Pointer to receive the response message transmit
+ * data buffer.
+ *
+ * @return PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjsip_dlg_create_response( pjsip_dialog *dlg,
+ pjsip_rx_data *rdata,
+ int st_code,
+ const pj_str_t *st_text,
+ pjsip_tx_data **tdata);
+
+
+/**
+ * Modify previously sent response with other status code. Contact header
+ * will be added when appropriate.
+ *
+ * @param dlg The dialog.
+ * @param tdata The transmit data buffer containing response
+ * message to be modified.
+ * @param st_code New status code to be set.
+ * @param st_text Optional string for custom status reason text.
+ *
+ * @return PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjsip_dlg_modify_response( pjsip_dialog *dlg,
+ pjsip_tx_data *tdata,
+ int st_code,
+ const pj_str_t *st_text);
+
+
+/**
+ * Send response message statefully. The transaction instance MUST be the
+ * transaction that was reported on on_rx_request() callback.
+ *
+ * This function decrements the transmit data's reference counter regardless
+ * the status of the operation.
+ *
+ * @param dlg The dialog.
+ * @param tsx The UAS transaction associated with the incoming
+ * request. If the request is within a dialog, or
+ * a dialog has been created for the request that
+ * creates the dialog, application can get the
+ * transaction instance for the request by calling
+ * #pjsip_rdata_get_tsx().
+ * @param tdata Response message to be sent.
+ *
+ * @return PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjsip_dlg_send_response( pjsip_dialog *dlg,
+ pjsip_transaction *tsx,
+ pjsip_tx_data *tdata);
+
+
+/**
+ * This composite function sends response message statefully to an incoming
+ * request message inside dialog.
+ *
+ * @param dlg The endpoint instance.
+ * @param rdata The incoming request message.
+ * @param st_code Status code of the response.
+ * @param st_text Optional status text of the response.
+ * @param hdr_list Optional header list to be added to the response.
+ * @param body Optional message body to be added to the response.
+ *
+ * @return PJ_SUCCESS if response message has successfully been
+ * sent.
+ */
+PJ_DECL(pj_status_t) pjsip_dlg_respond( pjsip_dialog *dlg,
+ pjsip_rx_data *rdata,
+ int st_code,
+ const pj_str_t *st_text,
+ const pjsip_hdr *hdr_list,
+ const pjsip_msg_body *body );
+
+
+/**
+ * Check if remote peer have the specified capability as published
+ * in the dialog messages from remote peer.
+ *
+ * Notes:
+ * - The capability \a token lookup will apply exact match, but not
+ * case-sensitive, for example: <tt>"text/html"</tt> will not match
+ * <tt>"text / html"</tt> (notice the spaces).
+ *
+ * @param dlg The dialog.
+ * @param htype The header type to be checked, which value may be:
+ * - PJSIP_H_ACCEPT
+ * - PJSIP_H_ALLOW
+ * - PJSIP_H_SUPPORTED
+ * @param hname If htype specifies PJSIP_H_OTHER, then the header name
+ * must be supplied in this argument. Otherwise the value
+ * must be set to NULL.
+ * @param token The capability token to check. For example, if \a htype
+ * is PJSIP_H_ALLOW, then \a token specifies the method
+ * names; if \a htype is PJSIP_H_SUPPORTED, then \a token
+ * specifies the extension names such as "100rel".
+ *
+ * @return PJSIP_DIALOG_CAP_SUPPORTED if the specified capability
+ * is explicitly supported, see @pjsip_dialog_cap_status
+ * for more info.
+ */
+PJ_DECL(pjsip_dialog_cap_status) pjsip_dlg_remote_has_cap(
+ pjsip_dialog *dlg,
+ int htype,
+ const pj_str_t *hname,
+ const pj_str_t *token);
+
+/**
+ * Get the specified capability header from the remote capability headers
+ * stored in the dialog.
+ *
+ * @param dlg The dialog.
+ * @param htype The header type to be retrieved, which value may be:
+ * - PJSIP_H_ACCEPT
+ * - PJSIP_H_ALLOW
+ * - PJSIP_H_SUPPORTED
+ * @param hname If htype specifies PJSIP_H_OTHER, then the header name
+ * must be supplied in this argument. Otherwise the value
+ * must be set to NULL.
+ *
+ * @return The appropriate header, or NULL if the header is not
+ * available.
+ */
+PJ_DECL(const pjsip_hdr*) pjsip_dlg_get_remote_cap_hdr(pjsip_dialog *dlg,
+ int htype,
+ const pj_str_t *hname);
+
+/**
+ * Set remote capability from a SIP header containing array of capability
+ * tags/values.
+ *
+ * @param dlg The dialog.
+ * @param cap_hdr The SIP header.
+ *
+ * @return PJ_SUCCESS when successful, otherwise the appropriate
+ * error code will be returned.
+ */
+PJ_DECL(pj_status_t) pjsip_dlg_set_remote_cap_hdr(
+ pjsip_dialog *dlg,
+ const pjsip_generic_array_hdr *cap_hdr);
+
+/**
+ * Remove a remote capability header.
+ *
+ * @param dlg The dialog.
+ * @param htype The header type to be removed, which value may be:
+ * - PJSIP_H_ACCEPT
+ * - PJSIP_H_ALLOW
+ * - PJSIP_H_SUPPORTED
+ * @param hname If htype specifies PJSIP_H_OTHER, then the header name
+ * must be supplied in this argument. Otherwise the value
+ * must be set to NULL.
+ *
+ * @return PJ_SUCCESS when successful, otherwise the appropriate
+ * error code will be returned.
+ */
+PJ_DECL(pj_status_t) pjsip_dlg_remove_remote_cap_hdr(pjsip_dialog *dlg,
+ int htype,
+ const pj_str_t *hname);
+
+/**
+ * Update remote capabilities from a received message. The header types
+ * to be updated from the message will only be \a PJSIP_H_ACCEPT,
+ * \a PJSIP_H_ALLOW, and \a PJSIP_H_SUPPORTED.
+ *
+ * @param dlg The dialog.
+ * @param msg The received message.
+ * @param strict If this is set to PJ_TRUE, any header types missing
+ * from the message will cause removal of existing
+ * header types in the capability list. Otherwise, the
+ * capability list will not be modified when any header
+ * type is missing.
+ *
+ * @return PJ_SUCCESS when successful, otherwise the appropriate
+ * error code will be returned.
+ */
+PJ_DECL(pj_status_t) pjsip_dlg_update_remote_cap(pjsip_dialog *dlg,
+ const pjsip_msg *msg,
+ pj_bool_t strict);
+
+
+
+/**
+ * @}
+ */
+
+/*
+ * Internal (called by sip_ua_layer.c)
+ */
+
+/* Receives transaction event (called by user_agent module) */
+void pjsip_dlg_on_tsx_state( pjsip_dialog *dlg,
+ pjsip_transaction *tsx,
+ pjsip_event *e );
+
+void pjsip_dlg_on_rx_request( pjsip_dialog *dlg,
+ pjsip_rx_data *rdata );
+
+void pjsip_dlg_on_rx_response( pjsip_dialog *dlg,
+ pjsip_rx_data *rdata );
+
+
+
+PJ_END_DECL
+
+
+#endif /* __PJSIP_SIP_DIALOG_H__ */
+
diff --git a/pjsip/include/pjsip/sip_endpoint.h b/pjsip/include/pjsip/sip_endpoint.h
new file mode 100644
index 0000000..ac3f525
--- /dev/null
+++ b/pjsip/include/pjsip/sip_endpoint.h
@@ -0,0 +1,584 @@
+/* $Id: sip_endpoint.h 4154 2012-06-05 10:41:17Z bennylp $ */
+/*
+ * 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_ENDPOINT_H__
+#define __PJSIP_SIP_ENDPOINT_H__
+
+/**
+ * @file sip_endpoint.h
+ * @brief SIP Endpoint.
+ */
+
+#include <pjsip/sip_transport.h>
+#include <pjsip/sip_resolve.h>
+
+/**
+ * @defgroup PJSIP_CORE_CORE At the Very Core
+ * @ingroup PJSIP_CORE
+ * @brief The very core of PJSIP.
+ */
+
+PJ_BEGIN_DECL
+
+/**
+ * @defgroup PJSIP_ENDPT Endpoint
+ * @ingroup PJSIP_CORE_CORE
+ * @brief The master, owner of all objects
+ *
+ * SIP Endpoint instance (pjsip_endpoint) can be viewed as the master/owner of
+ * all SIP objects in an application. It performs the following roles:
+ * - it manages the allocation/deallocation of memory pools for all objects.
+ * - it manages listeners and transports, and how they are used by
+ * transactions.
+ * - it receives incoming messages from transport layer and automatically
+ * dispatches them to the correct transaction (or create a new one).
+ * - it has a single instance of timer management (timer heap).
+ * - it manages modules, which is the primary means of extending the library.
+ * - it provides single polling function for all objects and distributes
+ * events.
+ * - it automatically handles incoming requests which can not be handled by
+ * existing modules (such as when incoming request has unsupported method).
+ * - and so on..
+ *
+ * Application should only instantiate one SIP endpoint instance for every
+ * process.
+ *
+ * @{
+ */
+
+
+/**
+ * Type of callback to register to pjsip_endpt_atexit().
+ */
+typedef void (*pjsip_endpt_exit_callback)(pjsip_endpoint *endpt);
+
+
+/**
+ * Create an instance of SIP endpoint from the specified pool factory.
+ * The pool factory reference then will be kept by the endpoint, so that
+ * future memory allocations by SIP components will be taken from the same
+ * pool factory.
+ *
+ * @param pf Pool factory that will be used for the lifetime of
+ * endpoint.
+ * @param name Optional name to be specified for the endpoint.
+ * If this parameter is NULL, then the name will use
+ * local host name.
+ * @param endpt Pointer to receive endpoint instance.
+ *
+ * @return PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjsip_endpt_create(pj_pool_factory *pf,
+ const char *name,
+ pjsip_endpoint **endpt);
+
+/**
+ * Destroy endpoint instance. Application must make sure that all pending
+ * transactions have been terminated properly, because this function does not
+ * check for the presence of pending transactions.
+ *
+ * @param endpt The SIP endpoint to be destroyed.
+ */
+PJ_DECL(void) pjsip_endpt_destroy(pjsip_endpoint *endpt);
+
+/**
+ * Get endpoint name.
+ *
+ * @param endpt The SIP endpoint instance.
+ *
+ * @return Endpoint name, as was registered during endpoint
+ * creation. The string is NULL terminated.
+ */
+PJ_DECL(const pj_str_t*) pjsip_endpt_name(const pjsip_endpoint *endpt);
+
+/**
+ * Poll for events. Application must call this function periodically to ensure
+ * that all events from both transports and timer heap are handled in timely
+ * manner. This function, like all other endpoint functions, is thread safe,
+ * and application may have more than one thread concurrently calling this function.
+ *
+ * @param endpt The endpoint.
+ * @param max_timeout Maximum time to wait for events, or NULL to wait forever
+ * until event is received.
+ *
+ * @return PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjsip_endpt_handle_events( pjsip_endpoint *endpt,
+ const pj_time_val *max_timeout);
+
+
+/**
+ * Handle events with additional info about number of events that
+ * have been handled.
+ *
+ * @param endpt The endpoint.
+ * @param max_timeout Maximum time to wait for events, or NULL to wait forever
+ * until event is received.
+ * @param count Optional argument to receive the number of events that
+ * have been handled by the function.
+ *
+ * @return PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjsip_endpt_handle_events2(pjsip_endpoint *endpt,
+ const pj_time_val *max_timeout,
+ unsigned *count);
+/**
+ * Schedule timer to endpoint's timer heap. Application must poll the endpoint
+ * periodically (by calling #pjsip_endpt_handle_events) to ensure that the
+ * timer events are handled in timely manner. When the timeout for the timer
+ * has elapsed, the callback specified in the entry argument will be called.
+ * This function, like all other endpoint functions, is thread safe.
+ *
+ * @param endpt The endpoint.
+ * @param entry The timer entry.
+ * @param delay The relative delay of the timer.
+ * @return PJ_OK (zero) if successfull.
+ */
+#if PJ_TIMER_DEBUG
+#define pjsip_endpt_schedule_timer(ept,ent,d) \
+ pjsip_endpt_schedule_timer_dbg(ept, ent, d, \
+ __FILE__, __LINE__)
+
+PJ_DECL(pj_status_t) pjsip_endpt_schedule_timer_dbg(pjsip_endpoint *endpt,
+ pj_timer_entry *entry,
+ const pj_time_val *delay,
+ const char *src_file,
+ int src_line);
+#else
+PJ_DECL(pj_status_t) pjsip_endpt_schedule_timer( pjsip_endpoint *endpt,
+ pj_timer_entry *entry,
+ const pj_time_val *delay );
+#endif
+
+/**
+ * Cancel the previously registered timer.
+ * This function, like all other endpoint functions, is thread safe.
+ *
+ * @param endpt The endpoint.
+ * @param entry The timer entry previously registered.
+ */
+PJ_DECL(void) pjsip_endpt_cancel_timer( pjsip_endpoint *endpt,
+ pj_timer_entry *entry );
+
+/**
+ * Get the timer heap instance of the SIP endpoint.
+ *
+ * @param endpt The endpoint.
+ *
+ * @return The timer heap instance.
+ */
+PJ_DECL(pj_timer_heap_t*) pjsip_endpt_get_timer_heap(pjsip_endpoint *endpt);
+
+
+/**
+ * Register new module to the endpoint.
+ * The endpoint will then call the load and start function in the module to
+ * properly initialize the module, and assign a unique module ID for the
+ * module.
+ *
+ * @param endpt The endpoint.
+ * @param module The module to be registered.
+ *
+ * @return PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjsip_endpt_register_module( pjsip_endpoint *endpt,
+ pjsip_module *module );
+
+/**
+ * Unregister a module from the endpoint.
+ * The endpoint will then call the stop and unload function in the module to
+ * properly shutdown the module.
+ *
+ * @param endpt The endpoint.
+ * @param module The module to be registered.
+ *
+ * @return PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjsip_endpt_unregister_module( pjsip_endpoint *endpt,
+ pjsip_module *module );
+
+
+/**
+ * Create pool from the endpoint. All SIP components should allocate their
+ * memory pool by calling this function, to make sure that the pools are
+ * allocated from the same pool factory. This function, like all other endpoint
+ * functions, is thread safe.
+ *
+ * @param endpt The SIP endpoint.
+ * @param pool_name Name to be assigned to the pool.
+ * @param initial The initial size of the pool.
+ * @param increment The resize size.
+ * @return Memory pool, or NULL on failure.
+ *
+ * @see pj_pool_create
+ */
+PJ_DECL(pj_pool_t*) pjsip_endpt_create_pool( pjsip_endpoint *endpt,
+ const char *pool_name,
+ pj_size_t initial,
+ pj_size_t increment );
+
+/**
+ * Return back pool to endpoint to be released back to the pool factory.
+ * This function, like all other endpoint functions, is thread safe.
+ *
+ * @param endpt The endpoint.
+ * @param pool The pool to be destroyed.
+ */
+PJ_DECL(void) pjsip_endpt_release_pool( pjsip_endpoint *endpt,
+ pj_pool_t *pool );
+
+/**
+ * Find transaction in endpoint's transaction table by the transaction's key.
+ * This function normally is only used by modules. The key for a transaction
+ * can be created by calling #pjsip_tsx_create_key.
+ *
+ * @param endpt The endpoint instance.
+ * @param key Transaction key, as created with #pjsip_tsx_create_key.
+ *
+ * @return The transaction, or NULL if it's not found.
+ */
+PJ_DECL(pjsip_transaction*) pjsip_endpt_find_tsx( pjsip_endpoint *endpt,
+ const pj_str_t *key );
+
+/**
+ * Register the transaction to the endpoint's transaction table.
+ * This function should only be used internally by the stack.
+ *
+ * @param endpt The SIP endpoint.
+ * @param tsx The transaction.
+ */
+PJ_DECL(void) pjsip_endpt_register_tsx( pjsip_endpoint *endpt,
+ pjsip_transaction *tsx);
+
+/**
+ * Forcefull destroy the transaction. This function should only be used
+ * internally by the stack.
+ *
+ * @param endpt The endpoint.
+ * @param tsx The transaction to destroy.
+ */
+PJ_DECL(void) pjsip_endpt_destroy_tsx( pjsip_endpoint *endpt,
+ pjsip_transaction *tsx);
+
+/**
+ * Create a new transmit data buffer.
+ * This function, like all other endpoint functions, is thread safe.
+ *
+ * @param endpt The endpoint.
+ * @param p_tdata Pointer to receive transmit data buffer.
+ *
+ * @return PJ_SUCCESS or the appropriate error code.
+ */
+PJ_DECL(pj_status_t) pjsip_endpt_create_tdata( pjsip_endpoint *endpt,
+ pjsip_tx_data **p_tdata);
+
+/**
+ * Create the DNS resolver instance. Application creates the DNS
+ * resolver instance, set the nameserver to be used by the DNS
+ * resolver, then set the DNS resolver to be used by the endpoint
+ * by calling #pjsip_endpt_set_resolver().
+ *
+ * @param endpt The SIP endpoint instance.
+ * @param p_resv Pointer to receive the DNS resolver instance.
+ *
+ * @return PJ_SUCCESS on success, or the appropriate error
+ * code.
+ */
+PJ_DECL(pj_status_t) pjsip_endpt_create_resolver(pjsip_endpoint *endpt,
+ pj_dns_resolver **p_resv);
+
+/**
+ * Set DNS resolver to be used by the SIP resolver. Application can set
+ * the resolver instance to NULL to disable DNS resolution (perhaps
+ * temporarily). When DNS resolver is disabled, the endpoint will resolve
+ * hostnames with the normal pj_gethostbyname() function.
+ *
+ * @param endpt The SIP endpoint instance.
+ * @param resv The resolver instance to be used by the SIP
+ * endpoint.
+ *
+ * @return PJ_SUCCESS on success, or the appropriate error
+ * code.
+ */
+PJ_DECL(pj_status_t) pjsip_endpt_set_resolver(pjsip_endpoint *endpt,
+ pj_dns_resolver *resv);
+
+/**
+ * Get the DNS resolver being used by the SIP resolver.
+ *
+ * @param endpt The SIP endpoint instance.
+ *
+ * @return The DNS resolver instance currently being used
+ * by the SIP endpoint.
+ */
+PJ_DECL(pj_dns_resolver*) pjsip_endpt_get_resolver(pjsip_endpoint *endpt);
+
+/**
+ * Asynchronously resolve a SIP target host or domain according to rule
+ * specified in RFC 3263 (Locating SIP Servers). When the resolving operation
+ * has completed, the callback will be called.
+ *
+ * @param endpt The endpoint instance.
+ * @param pool The pool to allocate resolver job.
+ * @param target The target specification to be resolved.
+ * @param token A user defined token to be passed back to callback function.
+ * @param cb The callback function.
+ */
+PJ_DECL(void) pjsip_endpt_resolve( pjsip_endpoint *endpt,
+ pj_pool_t *pool,
+ pjsip_host_info *target,
+ void *token,
+ pjsip_resolver_callback *cb);
+
+/**
+ * Get transport manager instance.
+ *
+ * @param endpt The endpoint.
+ *
+ * @return Transport manager instance.
+ */
+PJ_DECL(pjsip_tpmgr*) pjsip_endpt_get_tpmgr(pjsip_endpoint *endpt);
+
+/**
+ * Get ioqueue instance.
+ *
+ * @param endpt The endpoint.
+ *
+ * @return The ioqueue.
+ */
+PJ_DECL(pj_ioqueue_t*) pjsip_endpt_get_ioqueue(pjsip_endpoint *endpt);
+
+/**
+ * Find a SIP transport suitable for sending SIP message to the specified
+ * address. If transport selector ("sel") is set, then the function will
+ * check if the transport selected is suitable to send requests to the
+ * specified address.
+ *
+ * @see pjsip_tpmgr_acquire_transport
+ *
+ * @param endpt The SIP endpoint 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 p_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_endpt_acquire_transport( pjsip_endpoint *endpt,
+ pjsip_transport_type_e type,
+ const pj_sockaddr_t *remote,
+ int addr_len,
+ const pjsip_tpselector *sel,
+ pjsip_transport **p_tp);
+
+
+/**
+ * Find a SIP transport suitable for sending SIP message to the specified
+ * address by also considering the outgoing SIP message data. If transport
+ * selector ("sel") is set, then the function will check if the transport
+ * selected is suitable to send requests to the specified address.
+ *
+ * @see pjsip_tpmgr_acquire_transport
+ *
+ * @param endpt The SIP endpoint 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 SIP message data to be sent.
+ * @param p_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_endpt_acquire_transport2(pjsip_endpoint *endpt,
+ pjsip_transport_type_e type,
+ const pj_sockaddr_t *remote,
+ int addr_len,
+ const pjsip_tpselector *sel,
+ pjsip_tx_data *tdata,
+ pjsip_transport **p_tp);
+
+
+/*****************************************************************************
+ *
+ * Capabilities Management
+ *
+ * Modules may implement new capabilities to the stack. These capabilities
+ * are indicated by the appropriate SIP header fields, such as Accept,
+ * Accept-Encoding, Accept-Language, Allow, Supported, etc.
+ *
+ * When a module provides new capabilities to the stack, it registers these
+ * capabilities to the endpoint by supplying new tags (strings) to the
+ * appropriate header fields. Application (or other modules) can then query
+ * these header fields to get the list of supported capabilities, and may
+ * include these headers in the outgoing message.
+ *****************************************************************************
+ */
+
+/**
+ * Get the value of the specified capability header field.
+ *
+ * @param endpt The endpoint.
+ * @param htype The header type to be retrieved, which value may be:
+ * - PJSIP_H_ACCEPT
+ * - PJSIP_H_ALLOW
+ * - PJSIP_H_SUPPORTED
+ * @param hname If htype specifies PJSIP_H_OTHER, then the header name
+ * must be supplied in this argument. Otherwise the value
+ * must be set to NULL.
+ *
+ * @return The appropriate header, or NULL if the header is not
+ * available.
+ */
+PJ_DECL(const pjsip_hdr*) pjsip_endpt_get_capability( pjsip_endpoint *endpt,
+ int htype,
+ const pj_str_t *hname);
+
+
+/**
+ * Check if we have the specified capability.
+ *
+ * @param endpt The endpoint.
+ * @param htype The header type to be retrieved, which value may be:
+ * - PJSIP_H_ACCEPT
+ * - PJSIP_H_ALLOW
+ * - PJSIP_H_SUPPORTED
+ * @param hname If htype specifies PJSIP_H_OTHER, then the header name
+ * must be supplied in this argument. Otherwise the value
+ * must be set to NULL.
+ * @param token The capability token to check. For example, if \a htype
+ * is PJSIP_H_ALLOW, then \a token specifies the method
+ * names; if \a htype is PJSIP_H_SUPPORTED, then \a token
+ * specifies the extension names such as "100rel".
+ *
+ * @return PJ_TRUE if the specified capability is supported,
+ * otherwise PJ_FALSE..
+ */
+PJ_DECL(pj_bool_t) pjsip_endpt_has_capability( pjsip_endpoint *endpt,
+ int htype,
+ const pj_str_t *hname,
+ const pj_str_t *token);
+
+
+/**
+ * Add or register new capabilities as indicated by the tags to the
+ * appropriate header fields in the endpoint.
+ *
+ * @param endpt The endpoint.
+ * @param mod The module which registers the capability.
+ * @param htype The header type to be set, which value may be:
+ * - PJSIP_H_ACCEPT
+ * - PJSIP_H_ALLOW
+ * - PJSIP_H_SUPPORTED
+ * @param hname If htype specifies PJSIP_H_OTHER, then the header name
+ * must be supplied in this argument. Otherwise the value
+ * must be set to NULL.
+ * @param count The number of tags in the array.
+ * @param tags Array of tags describing the capabilities or extensions
+ * to be added to the appropriate header.
+ *
+ * @return PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjsip_endpt_add_capability( pjsip_endpoint *endpt,
+ pjsip_module *mod,
+ int htype,
+ const pj_str_t *hname,
+ unsigned count,
+ const pj_str_t tags[]);
+
+/**
+ * Get list of additional headers to be put in outgoing request message.
+ * Currently only Max-Forwards are defined.
+ *
+ * @param e The endpoint.
+ *
+ * @return List of headers.
+ */
+PJ_DECL(const pjsip_hdr*) pjsip_endpt_get_request_headers(pjsip_endpoint *e);
+
+
+/**
+ * Dump endpoint status to the log. This will print the status to the log
+ * with log level 3.
+ *
+ * @param endpt The endpoint.
+ * @param detail If non zero, then it will dump a detailed output.
+ * BEWARE that this option may crash the system because
+ * it tries to access all memory pools.
+ */
+PJ_DECL(void) pjsip_endpt_dump( pjsip_endpoint *endpt, pj_bool_t detail );
+
+
+/**
+ * Register cleanup function to be called by SIP endpoint when
+ * #pjsip_endpt_destroy() is called. Note that application should not
+ * use or access any endpoint resource (such as pool, ioqueue, timer heap)
+ * from within the callback as such resource may have been released when
+ * the callback function is invoked.
+ *
+ * @param endpt The SIP endpoint.
+ * @param func The function to be registered.
+ *
+ * @return PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjsip_endpt_atexit(pjsip_endpoint *endpt,
+ pjsip_endpt_exit_callback func);
+
+
+/**
+ * @}
+ */
+
+
+/**
+ * Log an error.
+ */
+PJ_DECL(void) pjsip_endpt_log_error( pjsip_endpoint *endpt,
+ const char *sender,
+ pj_status_t error_code,
+ const char *format,
+ ... );
+
+#define PJSIP_ENDPT_LOG_ERROR(expr) \
+ pjsip_endpt_log_error expr
+
+#define PJSIP_ENDPT_TRACE(tracing,expr) \
+ do { \
+ if ((tracing)) \
+ PJ_LOG(4,expr); \
+ } while (0)
+
+/*
+ * Internal functions.
+ */
+/*
+ * Receive transaction events from transactions and put in the event queue
+ * to be processed later.
+ */
+void pjsip_endpt_send_tsx_event( pjsip_endpoint *endpt, pjsip_event *evt );
+
+PJ_END_DECL
+
+#endif /* __PJSIP_SIP_ENDPOINT_H__ */
+
diff --git a/pjsip/include/pjsip/sip_errno.h b/pjsip/include/pjsip/sip_errno.h
new file mode 100644
index 0000000..26e326e
--- /dev/null
+++ b/pjsip/include/pjsip/sip_errno.h
@@ -0,0 +1,545 @@
+/* $Id: sip_errno.h 3553 2011-05-05 06:14:19Z nanang $ */
+/*
+ * 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_ERRNO_H__
+#define __PJSIP_SIP_ERRNO_H__
+
+/**
+ * @file sip_errno.h
+ * @brief PJSIP Specific Error Code
+ */
+
+#include <pj/errno.h>
+
+PJ_BEGIN_DECL
+
+/**
+ * @defgroup PJSIP_CORE_ERRNO PJSIP Specific Error Code
+ * @ingroup PJSIP_BASE
+ * @brief PJSIP specific error constants.
+ * @{
+ */
+
+/*
+ * PJSIP error codes occupies 170000 - 219000, and mapped as follows:
+ * - 170100 - 170799: mapped to SIP status code in response msg.
+ * - 171000 - 171999: mapped to errors generated from PJSIP core.
+ */
+
+/**
+ * Start of error code relative to PJ_ERRNO_START_USER.
+ */
+#define PJSIP_ERRNO_START (PJ_ERRNO_START_USER)
+
+/**
+ * Create error value from SIP status code.
+ * @param code SIP status code.
+ * @return Error code in pj_status_t namespace.
+ */
+#define PJSIP_ERRNO_FROM_SIP_STATUS(code) (PJSIP_ERRNO_START+code)
+
+/**
+ * Get SIP status code from error value.
+ * If conversion to SIP status code is not available, a SIP status code
+ * 599 will be returned.
+ *
+ * @param status Error code in pj_status_t namespace.
+ * @return SIP status code.
+ */
+#define PJSIP_ERRNO_TO_SIP_STATUS(status) \
+ ((status>=PJSIP_ERRNO_FROM_SIP_STATUS(100) && \
+ status<PJSIP_ERRNO_FROM_SIP_STATUS(800)) ? \
+ status-PJSIP_ERRNO_FROM_SIP_STATUS(0) : 599)
+
+
+/**
+ * Start of PJSIP generated error code values.
+ */
+#define PJSIP_ERRNO_START_PJSIP (PJSIP_ERRNO_START + 1000)
+
+/************************************************************
+ * GENERIC/GENERAL SIP ERRORS
+ ***********************************************************/
+/**
+ * @hideinitializer
+ * SIP object is busy.
+ */
+#define PJSIP_EBUSY (PJSIP_ERRNO_START_PJSIP + 1) /* 171001 */
+/**
+ * @hideinitializer
+ * SIP object with the same type already exists.
+ */
+#define PJSIP_ETYPEEXISTS (PJSIP_ERRNO_START_PJSIP + 2) /* 171002 */
+/**
+ * @hideinitializer
+ * SIP stack is shutting down.
+ */
+#define PJSIP_ESHUTDOWN (PJSIP_ERRNO_START_PJSIP + 3) /* 171003 */
+/**
+ * @hideinitializer
+ * SIP object is not initialized.
+ */
+#define PJSIP_ENOTINITIALIZED (PJSIP_ERRNO_START_PJSIP + 4) /* 171004 */
+/**
+ * @hideinitializer
+ * Missing route set (for tel: URI)
+ */
+#define PJSIP_ENOROUTESET (PJSIP_ERRNO_START_PJSIP + 5) /* 171005 */
+
+
+/************************************************************
+ * MESSAGING ERRORS
+ ***********************************************************/
+/**
+ * @hideinitializer
+ * General invalid message error (e.g. syntax error)
+ */
+#define PJSIP_EINVALIDMSG (PJSIP_ERRNO_START_PJSIP + 20) /* 171020 */
+/**
+ * @hideinitializer
+ * Expecting request message.
+ */
+#define PJSIP_ENOTREQUESTMSG (PJSIP_ERRNO_START_PJSIP + 21) /* 171021 */
+/**
+ * @hideinitializer
+ * Expecting response message.
+ */
+#define PJSIP_ENOTRESPONSEMSG (PJSIP_ERRNO_START_PJSIP + 22) /* 171022 */
+/**
+ * @hideinitializer
+ * Message too long. See also PJSIP_ERXOVERFLOW.
+ */
+#define PJSIP_EMSGTOOLONG (PJSIP_ERRNO_START_PJSIP + 23) /* 171023 */
+/**
+ * @hideinitializer
+ * Message not completely received.
+ */
+#define PJSIP_EPARTIALMSG (PJSIP_ERRNO_START_PJSIP + 24) /* 171024 */
+
+/**
+ * @hideinitializer
+ * Status code is invalid.
+ */
+#define PJSIP_EINVALIDSTATUS (PJSIP_ERRNO_START_PJSIP + 30) /* 171030 */
+
+/**
+ * @hideinitializer
+ * General Invalid URI error.
+ */
+#define PJSIP_EINVALIDURI (PJSIP_ERRNO_START_PJSIP + 39) /* 171039 */
+/**
+ * @hideinitializer
+ * Unsupported URL scheme.
+ */
+#define PJSIP_EINVALIDSCHEME (PJSIP_ERRNO_START_PJSIP + 40) /* 171040 */
+/**
+ * @hideinitializer
+ * Missing Request-URI.
+ */
+#define PJSIP_EMISSINGREQURI (PJSIP_ERRNO_START_PJSIP + 41) /* 171041 */
+/**
+ * @hideinitializer
+ * Invalid request URI.
+ */
+#define PJSIP_EINVALIDREQURI (PJSIP_ERRNO_START_PJSIP + 42) /* 171042 */
+/**
+ * @hideinitializer
+ * URI is too long.
+ */
+#define PJSIP_EURITOOLONG (PJSIP_ERRNO_START_PJSIP + 43) /* 171043 */
+
+/**
+ * @hideinitializer
+ * Missing required header(s).
+ */
+#define PJSIP_EMISSINGHDR (PJSIP_ERRNO_START_PJSIP + 50) /* 171050 */
+/**
+ * @hideinitializer
+ * Invalid header field.
+ */
+#define PJSIP_EINVALIDHDR (PJSIP_ERRNO_START_PJSIP + 51) /* 171051 */
+/**
+ * @hideinitializer
+ * Invalid Via header in response (sent-by, etc).
+ */
+#define PJSIP_EINVALIDVIA (PJSIP_ERRNO_START_PJSIP + 52) /* 171052 */
+/**
+ * @hideinitializer
+ * Multiple Via headers in response.
+ */
+#define PJSIP_EMULTIPLEVIA (PJSIP_ERRNO_START_PJSIP + 53) /* 171053 */
+/**
+ * @hideinitializer
+ * Missing message body.
+ */
+#define PJSIP_EMISSINGBODY (PJSIP_ERRNO_START_PJSIP + 54) /* 171054 */
+/**
+ * @hideinitializer
+ * Invalid/unexpected method.
+ */
+#define PJSIP_EINVALIDMETHOD (PJSIP_ERRNO_START_PJSIP + 55) /* 171055 */
+
+
+/************************************************************
+ * TRANSPORT ERRORS
+ ***********************************************************/
+/**
+ * @hideinitializer
+ * Unsupported transport type.
+ */
+#define PJSIP_EUNSUPTRANSPORT (PJSIP_ERRNO_START_PJSIP + 60) /* 171060 */
+/**
+ * @hideinitializer
+ * Buffer is being sent, operation still pending.
+ */
+#define PJSIP_EPENDINGTX (PJSIP_ERRNO_START_PJSIP + 61) /* 171061 */
+/**
+ * @hideinitializer
+ * Rx buffer overflow. See also PJSIP_EMSGTOOLONG.
+ */
+#define PJSIP_ERXOVERFLOW (PJSIP_ERRNO_START_PJSIP + 62) /* 171062 */
+/**
+ * @hideinitializer
+ * This is not really an error, it just informs application that
+ * transmit data has been deleted on return of pjsip_tx_data_dec_ref().
+ */
+#define PJSIP_EBUFDESTROYED (PJSIP_ERRNO_START_PJSIP + 63) /* 171063 */
+/**
+ * @hideinitializer
+ * Unsuitable transport selected. This error occurs when application
+ * has explicitly requested to use a particular transport/listener,
+ * but the selected transport is not suitable to send request to
+ * the specified destination.
+ */
+#define PJSIP_ETPNOTSUITABLE (PJSIP_ERRNO_START_PJSIP + 64) /* 171064 */
+/**
+ * @hideinitializer
+ * Transport not available. This error occurs for example when the SIP stack
+ * is trying to use a SIP transport while the transport is being paused by
+ * application.
+ */
+#define PJSIP_ETPNOTAVAIL (PJSIP_ERRNO_START_PJSIP + 65) /* 171065 */
+
+/************************************************************
+ * TRANSACTION ERRORS
+ ***********************************************************/
+/**
+ * @hideinitializer
+ * Transaction has just been destroyed.
+ */
+#define PJSIP_ETSXDESTROYED (PJSIP_ERRNO_START_PJSIP + 70) /* 171070 */
+/**
+ * @hideinitializer
+ * No transaction.
+ */
+#define PJSIP_ENOTSX (PJSIP_ERRNO_START_PJSIP + 71) /* 171071 */
+
+
+/************************************************************
+ * URI COMPARISON RESULTS
+ ***********************************************************/
+/**
+ * @hideinitializer
+ * Scheme mismatch.
+ */
+#define PJSIP_ECMPSCHEME (PJSIP_ERRNO_START_PJSIP + 80) /* 171080 */
+/**
+ * @hideinitializer
+ * User part mismatch.
+ */
+#define PJSIP_ECMPUSER (PJSIP_ERRNO_START_PJSIP + 81) /* 171081 */
+/**
+ * @hideinitializer
+ * Password part mismatch.
+ */
+#define PJSIP_ECMPPASSWD (PJSIP_ERRNO_START_PJSIP + 82) /* 171082 */
+/**
+ * @hideinitializer
+ * Host part mismatch.
+ */
+#define PJSIP_ECMPHOST (PJSIP_ERRNO_START_PJSIP + 83) /* 171083 */
+/**
+ * @hideinitializer
+ * Port part mismatch.
+ */
+#define PJSIP_ECMPPORT (PJSIP_ERRNO_START_PJSIP + 84) /* 171084 */
+/**
+ * @hideinitializer
+ * Transport parameter part mismatch.
+ */
+#define PJSIP_ECMPTRANSPORTPRM (PJSIP_ERRNO_START_PJSIP + 85) /* 171085 */
+/**
+ * @hideinitializer
+ * TTL parameter part mismatch.
+ */
+#define PJSIP_ECMPTTLPARAM (PJSIP_ERRNO_START_PJSIP + 86) /* 171086 */
+/**
+ * @hideinitializer
+ * User parameter part mismatch.
+ */
+#define PJSIP_ECMPUSERPARAM (PJSIP_ERRNO_START_PJSIP + 87) /* 171087 */
+/**
+ * @hideinitializer
+ * Method parameter part mismatch.
+ */
+#define PJSIP_ECMPMETHODPARAM (PJSIP_ERRNO_START_PJSIP + 88) /* 171088 */
+/**
+ * @hideinitializer
+ * Maddr parameter part mismatch.
+ */
+#define PJSIP_ECMPMADDRPARAM (PJSIP_ERRNO_START_PJSIP + 89) /* 171089 */
+/**
+ * @hideinitializer
+ * Parameter part in other_param mismatch.
+ */
+#define PJSIP_ECMPOTHERPARAM (PJSIP_ERRNO_START_PJSIP + 90) /* 171090 */
+/**
+ * @hideinitializer
+ * Parameter part in header_param mismatch.
+ */
+#define PJSIP_ECMPHEADERPARAM (PJSIP_ERRNO_START_PJSIP + 91) /* 171091 */
+
+
+/************************************************************
+ * AUTHENTICATION FRAMEWORK
+ ***********************************************************/
+/**
+ * @hideinitializer
+ * Credential failed to authenticate. For this failure, right credential
+ * for the realm has been found and used to authenticate against the challenge,
+ * but the server has rejected the authorization request with 401/407 response
+ * (either with no stale parameter or with "stale=false" parameter). In most
+ * cases, this indicates that the username/password combination is incorrect.
+ */
+#define PJSIP_EFAILEDCREDENTIAL (PJSIP_ERRNO_START_PJSIP + 100) /* 171100 */
+/**
+ * @hideinitializer
+ * No suitable credential is found to authenticate the request against
+ * the received authentication challenge in 401/407 response. This often
+ * is caused by different realm supplied in the credential than the realm
+ * found in the challenge.
+ */
+#define PJSIP_ENOCREDENTIAL (PJSIP_ERRNO_START_PJSIP + 101) /* 171101 */
+/**
+ * @hideinitializer
+ * Invalid/unsupported algorithm.
+ */
+#define PJSIP_EINVALIDALGORITHM (PJSIP_ERRNO_START_PJSIP + 102) /* 171102 */
+/**
+ * @hideinitializer
+ * Invalid/unsupported qop.
+ */
+#define PJSIP_EINVALIDQOP (PJSIP_ERRNO_START_PJSIP + 103) /* 171103 */
+/**
+ * @hideinitializer
+ * Invalid/unsupported authentication scheme.
+ */
+#define PJSIP_EINVALIDAUTHSCHEME (PJSIP_ERRNO_START_PJSIP + 104)/* 171104 */
+/**
+ * @hideinitializer
+ * No previous challenge.
+ */
+#define PJSIP_EAUTHNOPREVCHAL (PJSIP_ERRNO_START_PJSIP + 105) /* 171105 */
+/**
+ * @hideinitializer
+ * No authorization is found.
+ */
+#define PJSIP_EAUTHNOAUTH (PJSIP_ERRNO_START_PJSIP + 106) /* 171106 */
+/**
+ * @hideinitializer
+ * Account not found.
+ */
+#define PJSIP_EAUTHACCNOTFOUND (PJSIP_ERRNO_START_PJSIP + 107) /* 171107 */
+/**
+ * @hideinitializer
+ * Account is disabled.
+ */
+#define PJSIP_EAUTHACCDISABLED (PJSIP_ERRNO_START_PJSIP + 108) /* 171108 */
+/**
+ * @hideinitializer
+ * Invalid realm.
+ */
+#define PJSIP_EAUTHINVALIDREALM (PJSIP_ERRNO_START_PJSIP + 109) /* 171109 */
+/**
+ * @hideinitializer
+ * Invalid digest.
+ */
+#define PJSIP_EAUTHINVALIDDIGEST (PJSIP_ERRNO_START_PJSIP+110) /* 171110 */
+/**
+ * @hideinitializer
+ * Maximum number of stale retries exceeded. This happens when server
+ * keeps rejecting our authorization request with stale=true.
+ */
+#define PJSIP_EAUTHSTALECOUNT (PJSIP_ERRNO_START_PJSIP + 111) /* 171111 */
+/**
+ * @hideinitializer
+ * Invalid nonce value in the challenge.
+ */
+#define PJSIP_EAUTHINNONCE (PJSIP_ERRNO_START_PJSIP + 112) /* 171112 */
+/**
+ * @hideinitializer
+ * Invalid AKA credential.
+ */
+#define PJSIP_EAUTHINAKACRED (PJSIP_ERRNO_START_PJSIP + 113) /* 171113 */
+/**
+ * No challenge is found in the challenge.
+ */
+#define PJSIP_EAUTHNOCHAL (PJSIP_ERRNO_START_PJSIP + 114) /* 171114 */
+
+/************************************************************
+ * UA AND DIALOG ERRORS
+ ***********************************************************/
+/**
+ * @hideinitializer
+ * Missing From/To tag.
+ */
+#define PJSIP_EMISSINGTAG (PJSIP_ERRNO_START_PJSIP+120) /* 171120 */
+/**
+ * @hideinitializer
+ * Expecting REFER method
+ */
+#define PJSIP_ENOTREFER (PJSIP_ERRNO_START_PJSIP+121) /* 171121 */
+/**
+ * @hideinitializer
+ * Not associated with REFER subscription
+ */
+#define PJSIP_ENOREFERSESSION (PJSIP_ERRNO_START_PJSIP+122) /* 171122 */
+
+/************************************************************
+ * INVITE SESSIONS ERRORS
+ ***********************************************************/
+/**
+ * @hideinitializer
+ * Session already terminated.
+ */
+#define PJSIP_ESESSIONTERMINATED (PJSIP_ERRNO_START_PJSIP+140) /* 171140 */
+/**
+ * @hideinitializer
+ * Invalid session state for the specified operation.
+ */
+#define PJSIP_ESESSIONSTATE (PJSIP_ERRNO_START_PJSIP+141) /* 171141 */
+/**
+ * @hideinitializer
+ * The feature being requested requires the use of secure session or
+ * transport.
+ */
+#define PJSIP_ESESSIONINSECURE (PJSIP_ERRNO_START_PJSIP+142) /* 171142 */
+
+/************************************************************
+ * TLS TRANSPORT ERRORS
+ ***********************************************************/
+/**
+ * @hideinitializer
+ * Unknown TLS error
+ */
+#define PJSIP_TLS_EUNKNOWN (PJSIP_ERRNO_START_PJSIP+160) /* 171160 */
+/**
+ * @hideinitializer
+ * Invalid SSL protocol method.
+ */
+#define PJSIP_TLS_EINVMETHOD (PJSIP_ERRNO_START_PJSIP+161) /* 171161 */
+/**
+ * @hideinitializer
+ * Error loading/verifying SSL CA list file.
+ */
+#define PJSIP_TLS_ECACERT (PJSIP_ERRNO_START_PJSIP+162) /* 171162 */
+/**
+ * @hideinitializer
+ * Error loading SSL certificate chain file.
+ */
+#define PJSIP_TLS_ECERTFILE (PJSIP_ERRNO_START_PJSIP+163) /* 171163 */
+/**
+ * @hideinitializer
+ * Error adding private key from SSL certificate file.
+ */
+#define PJSIP_TLS_EKEYFILE (PJSIP_ERRNO_START_PJSIP+164) /* 171164 */
+/**
+ * @hideinitializer
+ * Error setting SSL cipher list.
+ */
+#define PJSIP_TLS_ECIPHER (PJSIP_ERRNO_START_PJSIP+165) /* 171165 */
+/**
+ * @hideinitializer
+ * Error creating SSL context.
+ */
+#define PJSIP_TLS_ECTX (PJSIP_ERRNO_START_PJSIP+166) /* 171166 */
+/**
+ * @hideinitializer
+ * Error creating SSL connection object.
+ */
+#define PJSIP_TLS_ESSLCONN (PJSIP_ERRNO_START_PJSIP+167) /* 171167 */
+/**
+ * @hideinitializer
+ * Unknown error when performing SSL connect().
+ */
+#define PJSIP_TLS_ECONNECT (PJSIP_ERRNO_START_PJSIP+168) /* 171168 */
+/**
+ * @hideinitializer
+ * Unknown error when performing SSL accept().
+ */
+#define PJSIP_TLS_EACCEPT (PJSIP_ERRNO_START_PJSIP+169) /* 171169 */
+/**
+ * @hideinitializer
+ * Unknown error when sending SSL data
+ */
+#define PJSIP_TLS_ESEND (PJSIP_ERRNO_START_PJSIP+170) /* 171170 */
+/**
+ * @hideinitializer
+ * Unknown error when reading SSL data
+ */
+#define PJSIP_TLS_EREAD (PJSIP_ERRNO_START_PJSIP+171) /* 171171 */
+/**
+ * @hideinitializer
+ * SSL negotiation has exceeded the maximum configured timeout.
+ */
+#define PJSIP_TLS_ETIMEDOUT (PJSIP_ERRNO_START_PJSIP+172) /* 171172 */
+/**
+ * @hideinitializer
+ * SSL certificate verification error.
+ */
+#define PJSIP_TLS_ECERTVERIF (PJSIP_ERRNO_START_PJSIP+173) /* 171173 */
+
+
+/**
+ * Get error message for the specified error code. Note that this
+ * function is only able to decode PJSIP specific error code.
+ * Application should use pj_strerror(), which should be able to
+ * decode all error codes belonging to all subsystems (e.g. pjlib,
+ * pjmedia, pjsip, etc).
+ *
+ * @param status The error code.
+ * @param buffer The buffer where to put the error message.
+ * @param bufsize Size of the buffer.
+ *
+ * @return The error message as NULL terminated string,
+ * wrapped with pj_str_t.
+ */
+PJ_DECL(pj_str_t) pjsip_strerror(pj_status_t status,
+ char *buffer, pj_size_t bufsize);
+
+
+PJ_END_DECL
+
+
+/**
+ * @}
+ */
+
+#endif /* __PJSIP_SIP_ERRNO_H__ */
+
diff --git a/pjsip/include/pjsip/sip_event.h b/pjsip/include/pjsip/sip_event.h
new file mode 100644
index 0000000..d6c90af
--- /dev/null
+++ b/pjsip/include/pjsip/sip_event.h
@@ -0,0 +1,231 @@
+/* $Id: sip_event.h 4154 2012-06-05 10:41:17Z bennylp $ */
+/*
+ * 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_EVENT_H__
+#define __PJSIP_SIP_EVENT_H__
+
+/**
+ * @file sip_event.h
+ * @brief SIP Event
+ */
+
+PJ_BEGIN_DECL
+
+/**
+ * @defgroup PJSIP_EVENT Event
+ * @ingroup PJSIP_CORE_CORE
+ * @brief Representation of events as they are distributed among modules.
+ * @{
+ */
+#include <pj/types.h>
+#include <pj/timer.h>
+
+
+/**
+ * Event IDs.
+ */
+typedef enum pjsip_event_id_e
+{
+ /** Unidentified event. */
+ PJSIP_EVENT_UNKNOWN,
+
+ /** Timer event, normally only used internally in transaction. */
+ PJSIP_EVENT_TIMER,
+
+ /** Message transmission event. */
+ PJSIP_EVENT_TX_MSG,
+
+ /** Message received event. */
+ PJSIP_EVENT_RX_MSG,
+
+ /** Transport error event. */
+ PJSIP_EVENT_TRANSPORT_ERROR,
+
+ /** Transaction state changed event. */
+ PJSIP_EVENT_TSX_STATE,
+
+ /** Indicates that the event was triggered by user action. */
+ PJSIP_EVENT_USER
+
+} pjsip_event_id_e;
+
+
+/**
+ * This structure describe event descriptor to fully identify a SIP event.
+ *
+ * Events are the only way for a lower layer object to inform something
+ * to higher layer objects. Normally this is achieved by means of callback,
+ * i.e. the higher layer objects register a callback to handle the event on
+ * the lower layer objects.
+ *
+ * This event descriptor is used for example by transactions, to inform
+ * endpoint about events, and by transports, to inform endpoint about
+ * unexpected transport error.
+ */
+struct pjsip_event
+{
+ /** This is necessary so that we can put events as a list. */
+ PJ_DECL_LIST_MEMBER(struct pjsip_event);
+
+ /** The event type, can be any value of \b pjsip_event_id_e.
+ */
+ pjsip_event_id_e type;
+
+ /**
+ * The event body as union, which fields depends on the event type.
+ * By convention, the first member of each struct in the union must be
+ * the pointer which is relevant to the event.
+ */
+ union
+ {
+ /** Timer event. */
+ struct
+ {
+ pj_timer_entry *entry; /**< The timer entry. */
+ } timer;
+
+ /** Transaction state has changed event. */
+ struct
+ {
+ union
+ {
+ pjsip_rx_data *rdata; /**< The incoming message. */
+ pjsip_tx_data *tdata; /**< The outgoing message. */
+ pj_timer_entry *timer; /**< The timer. */
+ pj_status_t status;/**< Transport error status. */
+ void *data; /**< Generic data. */
+ } src;
+ pjsip_transaction *tsx; /**< The transaction. */
+ int prev_state; /**< Previous state. */
+ pjsip_event_id_e type; /**< Type of event source:
+ * - PJSIP_EVENT_TX_MSG
+ * - PJSIP_EVENT_RX_MSG,
+ * - PJSIP_EVENT_TRANSPORT_ERROR
+ * - PJSIP_EVENT_TIMER
+ * - PJSIP_EVENT_USER
+ */
+ } tsx_state;
+
+ /** Message transmission event. */
+ struct
+ {
+ pjsip_tx_data *tdata; /**< The transmit data buffer. */
+
+ } tx_msg;
+
+ /** Transmission error event. */
+ struct
+ {
+ pjsip_tx_data *tdata; /**< The transmit data. */
+ pjsip_transaction *tsx; /**< The transaction. */
+ } tx_error;
+
+ /** Message arrival event. */
+ struct
+ {
+ pjsip_rx_data *rdata; /**< The receive data buffer. */
+ } rx_msg;
+
+ /** User event. */
+ struct
+ {
+ void *user1; /**< User data 1. */
+ void *user2; /**< User data 2. */
+ void *user3; /**< User data 3. */
+ void *user4; /**< User data 4. */
+ } user;
+
+ } body;
+};
+
+/**
+ * Init timer event.
+ */
+#define PJSIP_EVENT_INIT_TIMER(event,pentry) \
+ do { \
+ (event).type = PJSIP_EVENT_TIMER; \
+ (event).body.timer.entry = pentry; \
+ } while (0)
+
+/**
+ * Init tsx state event.
+ */
+#define PJSIP_EVENT_INIT_TSX_STATE(event,ptsx,ptype,pdata,prev) \
+ do { \
+ (event).type = PJSIP_EVENT_TSX_STATE; \
+ (event).body.tsx_state.tsx = ptsx; \
+ (event).body.tsx_state.type = ptype; \
+ (event).body.tsx_state.src.data = pdata; \
+ (event).body.tsx_state.prev_state = prev; \
+ } while (0)
+
+/**
+ * Init tx msg event.
+ */
+#define PJSIP_EVENT_INIT_TX_MSG(event,ptdata) \
+ do { \
+ (event).type = PJSIP_EVENT_TX_MSG; \
+ (event).body.tx_msg.tdata = ptdata; \
+ } while (0)
+
+/**
+ * Init rx msg event.
+ */
+#define PJSIP_EVENT_INIT_RX_MSG(event,prdata) \
+ do { \
+ (event).type = PJSIP_EVENT_RX_MSG; \
+ (event).body.rx_msg.rdata = prdata; \
+ } while (0)
+
+/**
+ * Init transport error event.
+ */
+#define PJSIP_EVENT_INIT_TRANSPORT_ERROR(event,ptsx,ptdata) \
+ do { \
+ (event).type = PJSIP_EVENT_TRANSPORT_ERROR; \
+ (event).body.tx_error.tsx = ptsx; \
+ (event).body.tx_error.tdata = ptdata; \
+ } while (0)
+
+/**
+ * Init user event.
+ */
+#define PJSIP_EVENT_INIT_USER(event,u1,u2,u3,u4) \
+ do { \
+ (event).type = PJSIP_EVENT_USER; \
+ (event).body.user.user1 = (void*)u1; \
+ (event).body.user.user2 = (void*)u2; \
+ (event).body.user.user3 = (void*)u3; \
+ (event).body.user.user4 = (void*)u4; \
+ } while (0)
+
+/**
+ * Get the event string from the event ID.
+ * @param e the event ID.
+ * @note defined in sip_util.c
+ */
+PJ_DECL(const char *) pjsip_event_str(pjsip_event_id_e e);
+
+/**
+ * @}
+ */
+
+PJ_END_DECL
+
+#endif /* __PJSIP_SIP_EVENT_H__ */
diff --git a/pjsip/include/pjsip/sip_module.h b/pjsip/include/pjsip/sip_module.h
new file mode 100644
index 0000000..45884cc
--- /dev/null
+++ b/pjsip/include/pjsip/sip_module.h
@@ -0,0 +1,222 @@
+/* $Id: sip_module.h 3553 2011-05-05 06:14:19Z nanang $ */
+/*
+ * 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_MODULE_H__
+#define __PJSIP_SIP_MODULE_H__
+
+/**
+ * @file sip_module.h
+ * @brief Module helpers
+ */
+#include <pjsip/sip_types.h>
+#include <pj/list.h>
+
+PJ_BEGIN_DECL
+
+/**
+ * @defgroup PJSIP_MOD Modules
+ * @ingroup PJSIP_CORE_CORE
+ * @brief Modules are the primary means to extend PJSIP!
+ * @{
+ * Modules are the primary means to extend PJSIP. Without modules, PJSIP
+ * would not know how to handle messages, and will simply discard all
+ * incoming messages.
+ *
+ * Modules are registered by creating and initializing #pjsip_module
+ * structure, and register the structure to PJSIP with
+ * #pjsip_endpt_register_module().
+ *
+ * The <A HREF="/docs.htm">PJSIP Developer's Guide</A>
+ * has a thorough discussion on this subject, and readers are encouraged
+ * to read the document for more information.
+ */
+
+/**
+ * The declaration for SIP module. This structure would be passed to
+ * #pjsip_endpt_register_module() to register the module to PJSIP.
+ */
+struct pjsip_module
+{
+ /** To allow chaining of modules in the endpoint. */
+ PJ_DECL_LIST_MEMBER(struct pjsip_module);
+
+ /**
+ * Module name to identify the module.
+ *
+ * This field MUST be initialized before registering the module.
+ */
+ pj_str_t name;
+
+ /**
+ * Module ID. Application must initialize this field with -1 before
+ * registering the module to PJSIP. After the module is registered,
+ * this field will contain a unique ID to identify the module.
+ */
+ int id;
+
+ /**
+ * Integer number to identify module initialization and start order with
+ * regard to other modules. Higher number will make the module gets
+ * initialized later.
+ *
+ * This field MUST be initialized before registering the module.
+ */
+ int priority;
+
+ /**
+ * Optional function to be called to initialize the module. This function
+ * will be called by endpoint during module registration. If the value
+ * is NULL, then it's equal to returning PJ_SUCCESS.
+ *
+ * @param endpt The endpoint instance.
+ * @return Module should return PJ_SUCCESS to indicate success.
+ */
+ pj_status_t (*load)(pjsip_endpoint *endpt);
+
+ /**
+ * Optional function to be called to start the module. This function
+ * will be called by endpoint during module registration. If the value
+ * is NULL, then it's equal to returning PJ_SUCCESS.
+ *
+ * @return Module should return zero to indicate success.
+ */
+ pj_status_t (*start)(void);
+
+ /**
+ * Optional function to be called to deinitialize the module before
+ * it is unloaded. This function will be called by endpoint during
+ * module unregistration. If the value is NULL, then it's equal to
+ * returning PJ_SUCCESS.
+ *
+ * @return Module should return PJ_SUCCESS to indicate success.
+ */
+ pj_status_t (*stop)(void);
+
+ /**
+ * Optional function to be called to deinitialize the module before
+ * it is unloaded. This function will be called by endpoint during
+ * module unregistration. If the value is NULL, then it's equal to
+ * returning PJ_SUCCESS.
+ *
+ * @param mod The module.
+ *
+ * @return Module should return PJ_SUCCESS to indicate success.
+ */
+ pj_status_t (*unload)(void);
+
+ /**
+ * Optional function to be called to process incoming request message.
+ *
+ * @param rdata The incoming message.
+ *
+ * @return Module should return PJ_TRUE if it handles the request,
+ * or otherwise it should return PJ_FALSE to allow other
+ * modules to handle the request.
+ */
+ pj_bool_t (*on_rx_request)(pjsip_rx_data *rdata);
+
+ /**
+ * Optional function to be called to process incoming response message.
+ *
+ * @param rdata The incoming message.
+ *
+ * @return Module should return PJ_TRUE if it handles the
+ * response, or otherwise it should return PJ_FALSE to
+ * allow other modules to handle the response.
+ */
+ pj_bool_t (*on_rx_response)(pjsip_rx_data *rdata);
+
+ /**
+ * Optional function to be called when transport layer is about to
+ * transmit outgoing request message.
+ *
+ * @param tdata The outgoing request message.
+ *
+ * @return Module should return PJ_SUCCESS in all cases.
+ * If non-zero (or PJ_FALSE) is returned, the message
+ * will not be sent.
+ */
+ pj_status_t (*on_tx_request)(pjsip_tx_data *tdata);
+
+ /**
+ * Optional function to be called when transport layer is about to
+ * transmit outgoing response message.
+ *
+ * @param tdata The outgoing response message.
+ *
+ * @return Module should return PJ_SUCCESS in all cases.
+ * If non-zero (or PJ_FALSE) is returned, the message
+ * will not be sent.
+ */
+ pj_status_t (*on_tx_response)(pjsip_tx_data *tdata);
+
+ /**
+ * Optional function to be called when this module is acting as
+ * transaction user for the specified transaction, when the
+ * transaction's state has changed.
+ *
+ * @param tsx The transaction.
+ * @param event The event which has caused the transaction state
+ * to change.
+ */
+ void (*on_tsx_state)(pjsip_transaction *tsx, pjsip_event *event);
+
+};
+
+
+/**
+ * Module priority guidelines.
+ */
+enum pjsip_module_priority
+{
+ /**
+ * This is the priority used by transport layer.
+ */
+ PJSIP_MOD_PRIORITY_TRANSPORT_LAYER = 8,
+
+ /**
+ * This is the priority used by transaction layer.
+ */
+ PJSIP_MOD_PRIORITY_TSX_LAYER = 16,
+
+ /**
+ * This is the priority used by the user agent and proxy layer.
+ */
+ PJSIP_MOD_PRIORITY_UA_PROXY_LAYER = 32,
+
+ /**
+ * This is the priority used by the dialog usages.
+ */
+ PJSIP_MOD_PRIORITY_DIALOG_USAGE = 48,
+
+ /**
+ * This is the recommended priority to be used by applications.
+ */
+ PJSIP_MOD_PRIORITY_APPLICATION = 64
+};
+
+
+/**
+ * @}
+ */
+
+PJ_END_DECL
+
+#endif /* __PJSIP_SIP_MODULE_H__ */
+
diff --git a/pjsip/include/pjsip/sip_msg.h b/pjsip/include/pjsip/sip_msg.h
new file mode 100644
index 0000000..9031fa2
--- /dev/null
+++ b/pjsip/include/pjsip/sip_msg.h
@@ -0,0 +1,2048 @@
+/* $Id: sip_msg.h 3553 2011-05-05 06:14:19Z nanang $ */
+/*
+ * 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_MSG_H__
+#define __PJSIP_SIP_MSG_H__
+
+/**
+ * @file pjsip/sip_msg.h
+ * @brief SIP Message Structure.
+ */
+
+#include <pjsip/sip_types.h>
+#include <pjsip/sip_uri.h>
+#include <pj/list.h>
+
+PJ_BEGIN_DECL
+
+/**
+ * @defgroup PJSIP_MSG Messaging Elements
+ * @ingroup PJSIP_CORE
+ * @brief Various SIP message elements such as methods, headers, URIs, etc.
+ * @{
+ */
+
+/* **************************************************************************/
+/**
+ * @defgroup PJSIP_MSG_METHOD Methods
+ * @brief Method names and manipulation.
+ * @ingroup PJSIP_MSG
+ * @{
+ */
+
+/**
+ * This enumeration declares SIP methods as described by RFC3261. Additional
+ * methods do exist, and they are described by corresponding RFCs for the SIP
+ * extentensions. Since they won't alter the characteristic of the processing
+ * of the message, they don't need to be explicitly mentioned here.
+ */
+typedef enum pjsip_method_e
+{
+ PJSIP_INVITE_METHOD, /**< INVITE method, for establishing dialogs. */
+ PJSIP_CANCEL_METHOD, /**< CANCEL method, for cancelling request. */
+ PJSIP_ACK_METHOD, /**< ACK method. */
+ PJSIP_BYE_METHOD, /**< BYE method, for terminating dialog. */
+ PJSIP_REGISTER_METHOD, /**< REGISTER method. */
+ PJSIP_OPTIONS_METHOD, /**< OPTIONS method. */
+
+ PJSIP_OTHER_METHOD /**< Other method. */
+
+} pjsip_method_e;
+
+
+
+/**
+ * This structure represents a SIP method.
+ * Application must always use either #pjsip_method_init or #pjsip_method_set
+ * to make sure that method name is initialized correctly. This way, the name
+ * member will always contain a valid method string regardless whether the ID
+ * is recognized or not.
+ */
+struct pjsip_method
+{
+ pjsip_method_e id; /**< Method ID, from \a pjsip_method_e. */
+ pj_str_t name; /**< Method name, which will always contain the
+ method string. */
+};
+
+
+/*
+ * For convenience, standard method structures are defined in the library.
+ */
+/** INVITE method constant. @see pjsip_get_invite_method() */
+PJ_DECL_DATA(const pjsip_method) pjsip_invite_method;
+
+/** CANCEL method constant. @see pjsip_get_cancel_method() */
+PJ_DECL_DATA(const pjsip_method) pjsip_cancel_method;
+
+/** ACK method constant. @see pjsip_get_ack_method() */
+PJ_DECL_DATA(const pjsip_method) pjsip_ack_method;
+
+/** BYE method constant. @see pjsip_get_bye_method() */
+PJ_DECL_DATA(const pjsip_method) pjsip_bye_method;
+
+/** REGISTER method constant. @see pjsip_get_register_method() */
+PJ_DECL_DATA(const pjsip_method) pjsip_register_method;
+
+/** OPTIONS method constant. @see pjsip_get_options_method() */
+PJ_DECL_DATA(const pjsip_method) pjsip_options_method;
+
+/*
+ * Accessor functions for standard SIP methods.
+ */
+/** Get INVITE method constant. */
+PJ_DECL(const pjsip_method*) pjsip_get_invite_method(void);
+/** Get CANCEL method constant. */
+PJ_DECL(const pjsip_method*) pjsip_get_cancel_method(void);
+/** Get ACK method constant. */
+PJ_DECL(const pjsip_method*) pjsip_get_ack_method(void);
+/** Get BYE method constant. */
+PJ_DECL(const pjsip_method*) pjsip_get_bye_method(void);
+/** Get REGISTER method constant.*/
+PJ_DECL(const pjsip_method*) pjsip_get_register_method(void);
+/** Get OPTIONS method constant. */
+PJ_DECL(const pjsip_method*) pjsip_get_options_method(void);
+
+
+/*
+ * Accessor functions
+ */
+
+/**
+ * Initialize the method structure from a string.
+ * This function will check whether the method is a known method then set
+ * both the id and name accordingly.
+ *
+ * @param m The method to initialize.
+ * @param pool Pool where memory allocation will be allocated from, if required.
+ * @param str The method string.
+ */
+PJ_DECL(void) pjsip_method_init( pjsip_method *m,
+ pj_pool_t *pool,
+ const pj_str_t *str);
+
+/**
+ * Initialize the method structure from a string, without cloning the string.
+ * See #pjsip_method_init.
+ *
+ * @param m The method structure to be initialized.
+ * @param str The method string.
+ */
+PJ_DECL(void) pjsip_method_init_np( pjsip_method *m,
+ pj_str_t *str);
+
+/**
+ * Set the method with the predefined method ID.
+ * This function will also set the name member of the structure to the correct
+ * string according to the method.
+ *
+ * @param m The method structure.
+ * @param id The method ID.
+ */
+PJ_DECL(void) pjsip_method_set( pjsip_method *m, pjsip_method_e id );
+
+
+/**
+ * Copy one method structure to another. If the method is of the known methods,
+ * then memory allocation is not required.
+ *
+ * @param pool Pool to allocate memory from, if required.
+ * @param method The destination method to copy to.
+ * @param rhs The source method to copy from.
+ */
+PJ_DECL(void) pjsip_method_copy( pj_pool_t *pool,
+ pjsip_method *method,
+ const pjsip_method *rhs );
+
+/**
+ * Compare one method with another, and conveniently determine whether the
+ * first method is equal, less than, or greater than the second method.
+ *
+ * @param m1 The first method.
+ * @param m2 The second method.
+ *
+ * @return Zero if equal, otherwise will return -1 if less or +1 if greater.
+ */
+PJ_DECL(int) pjsip_method_cmp( const pjsip_method *m1, const pjsip_method *m2);
+
+/**
+ * @}
+ */
+
+/* **************************************************************************/
+/**
+ * @defgroup PJSIP_MSG_HDR Header Fields
+ * @brief Declarations for various SIP header fields.
+ * @ingroup PJSIP_MSG
+ * @{
+ */
+
+/**
+ * Header types, as defined by RFC3261.
+ */
+typedef enum pjsip_hdr_e
+{
+ /*
+ * These are the headers documented in RFC3261. Headers not documented
+ * there must have type PJSIP_H_OTHER, and the header type itself is
+ * recorded in the header name string.
+ *
+ * DO NOT CHANGE THE VALUE/ORDER OF THE HEADER IDs!!!.
+ */
+ PJSIP_H_ACCEPT,
+ PJSIP_H_ACCEPT_ENCODING_UNIMP, /* N/A, use pjsip_generic_string_hdr */
+ PJSIP_H_ACCEPT_LANGUAGE_UNIMP, /* N/A, use pjsip_generic_string_hdr */
+ PJSIP_H_ALERT_INFO_UNIMP, /* N/A, use pjsip_generic_string_hdr */
+ PJSIP_H_ALLOW,
+ PJSIP_H_AUTHENTICATION_INFO_UNIMP, /* N/A, use pjsip_generic_string_hdr */
+ PJSIP_H_AUTHORIZATION,
+ PJSIP_H_CALL_ID,
+ PJSIP_H_CALL_INFO_UNIMP, /* N/A, use pjsip_generic_string_hdr */
+ PJSIP_H_CONTACT,
+ PJSIP_H_CONTENT_DISPOSITION_UNIMP, /* N/A, use pjsip_generic_string_hdr */
+ PJSIP_H_CONTENT_ENCODING_UNIMP, /* N/A, use pjsip_generic_string_hdr */
+ PJSIP_H_CONTENT_LANGUAGE_UNIMP, /* N/A, use pjsip_generic_string_hdr */
+ PJSIP_H_CONTENT_LENGTH,
+ PJSIP_H_CONTENT_TYPE,
+ PJSIP_H_CSEQ,
+ PJSIP_H_DATE_UNIMP, /* N/A, use pjsip_generic_string_hdr */
+ PJSIP_H_ERROR_INFO_UNIMP, /* N/A, use pjsip_generic_string_hdr */
+ PJSIP_H_EXPIRES,
+ PJSIP_H_FROM,
+ PJSIP_H_IN_REPLY_TO_UNIMP, /* N/A, use pjsip_generic_string_hdr */
+ PJSIP_H_MAX_FORWARDS,
+ PJSIP_H_MIME_VERSION_UNIMP, /* N/A, use pjsip_generic_string_hdr */
+ PJSIP_H_MIN_EXPIRES,
+ PJSIP_H_ORGANIZATION_UNIMP, /* N/A, use pjsip_generic_string_hdr */
+ PJSIP_H_PRIORITY_UNIMP, /* N/A, use pjsip_generic_string_hdr */
+ PJSIP_H_PROXY_AUTHENTICATE,
+ PJSIP_H_PROXY_AUTHORIZATION,
+ PJSIP_H_PROXY_REQUIRE_UNIMP, /* N/A, use pjsip_generic_string_hdr */
+ PJSIP_H_RECORD_ROUTE,
+ PJSIP_H_REPLY_TO_UNIMP, /* N/A, use pjsip_generic_string_hdr */
+ PJSIP_H_REQUIRE,
+ PJSIP_H_RETRY_AFTER,
+ PJSIP_H_ROUTE,
+ PJSIP_H_SERVER_UNIMP, /* N/A, use pjsip_generic_string_hdr */
+ PJSIP_H_SUBJECT_UNIMP, /* N/A, use pjsip_generic_string_hdr */
+ PJSIP_H_SUPPORTED,
+ PJSIP_H_TIMESTAMP_UNIMP, /* N/A, use pjsip_generic_string_hdr */
+ PJSIP_H_TO,
+ PJSIP_H_UNSUPPORTED,
+ PJSIP_H_USER_AGENT_UNIMP, /* N/A, use pjsip_generic_string_hdr */
+ PJSIP_H_VIA,
+ PJSIP_H_WARNING_UNIMP, /* N/A, use pjsip_generic_string_hdr */
+ PJSIP_H_WWW_AUTHENTICATE,
+
+ PJSIP_H_OTHER
+
+} pjsip_hdr_e;
+
+/**
+ * This structure provides the pointer to basic functions that are needed
+ * for generic header operations. All header fields will have pointer to
+ * this structure, so that they can be manipulated uniformly.
+ */
+typedef struct pjsip_hdr_vptr
+{
+ /**
+ * Function to clone the header.
+ *
+ * @param pool Memory pool to allocate the new header.
+ * @param hdr Header to clone.
+ *
+ * @return A new instance of the header.
+ */
+ void *(*clone)(pj_pool_t *pool, const void *hdr);
+
+ /**
+ * Pointer to function to shallow clone the header.
+ * Shallow cloning will just make a memory copy of the original header,
+ * thus all pointers in original header will be kept intact. Because the
+ * function does not need to perform deep copy, the operation should be
+ * faster, but the application must make sure that the original header
+ * is still valid throughout the lifetime of new header.
+ *
+ * @param pool Memory pool to allocate the new header.
+ * @param hdr The header to clone.
+ */
+ void *(*shallow_clone)(pj_pool_t *pool, const void *hdr);
+
+ /** Pointer to function to print the header to the specified buffer.
+ * Returns the length of string written, or -1 if the remaining buffer
+ * is not enough to hold the header.
+ *
+ * @param hdr The header to print.
+ * @param buf The buffer.
+ * @param len The size of the buffer.
+ *
+ * @return The size copied to buffer, or -1 if there's not enough space.
+ */
+ int (*print_on)(void *hdr, char *buf, pj_size_t len);
+
+} pjsip_hdr_vptr;
+
+
+/**
+ * Generic fields for all SIP headers are declared using this macro, to make
+ * sure that all headers will have exactly the same layout in their start of
+ * the storage. This behaves like C++ inheritance actually.
+ */
+#define PJSIP_DECL_HDR_MEMBER(hdr) \
+ /** List members. */ \
+ PJ_DECL_LIST_MEMBER(hdr); \
+ /** Header type */ \
+ pjsip_hdr_e type; \
+ /** Header name. */ \
+ pj_str_t name; \
+ /** Header short name version. */ \
+ pj_str_t sname; \
+ /** Virtual function table. */ \
+ pjsip_hdr_vptr *vptr
+
+
+/**
+ * Generic SIP header structure, for generic manipulation for headers in the
+ * message. All header fields can be typecasted to this type.
+ */
+struct pjsip_hdr
+{
+ PJSIP_DECL_HDR_MEMBER(struct pjsip_hdr);
+};
+
+
+/**
+ * This generic function will clone any header, by calling "clone" function
+ * in header's virtual function table.
+ *
+ * @param pool The pool to allocate memory from.
+ * @param hdr The header to clone.
+ *
+ * @return A new instance copied from the original header.
+ */
+PJ_DECL(void*) pjsip_hdr_clone( pj_pool_t *pool, const void *hdr );
+
+
+/**
+ * This generic function will clone any header, by calling "shallow_clone"
+ * function in header's virtual function table.
+ *
+ * @param pool The pool to allocate memory from.
+ * @param hdr The header to clone.
+ *
+ * @return A new instance copied from the original header.
+ */
+PJ_DECL(void*) pjsip_hdr_shallow_clone( pj_pool_t *pool, const void *hdr );
+
+/**
+ * This generic function will print any header, by calling "print"
+ * function in header's virtual function table.
+ *
+ * @param hdr The header to print.
+ * @param buf The buffer.
+ * @param len The size of the buffer.
+ *
+ * @return The size copied to buffer, or -1 if there's not enough space.
+ */
+PJ_DECL(int) pjsip_hdr_print_on( void *hdr, char *buf, pj_size_t len);
+
+/**
+ * @}
+ */
+
+/* **************************************************************************/
+/**
+ * @defgroup PJSIP_MSG_LINE Request and Status Line.
+ * @brief Request and status line structures and manipulation.
+ * @ingroup PJSIP_MSG
+ * @{
+ */
+
+/**
+ * This structure describes SIP request line.
+ */
+typedef struct pjsip_request_line
+{
+ pjsip_method method; /**< Method for this request line. */
+ pjsip_uri *uri; /**< URI for this request line. */
+} pjsip_request_line;
+
+
+/**
+ * This structure describes SIP status line.
+ */
+typedef struct pjsip_status_line
+{
+ int code; /**< Status code. */
+ pj_str_t reason; /**< Reason string. */
+} pjsip_status_line;
+
+
+/**
+ * This enumeration lists standard SIP status codes according to RFC 3261.
+ * In addition, it also declares new status class 7xx for errors generated
+ * by the stack. This status class however should not get transmitted on the
+ * wire.
+ */
+typedef enum pjsip_status_code
+{
+ PJSIP_SC_TRYING = 100,
+ PJSIP_SC_RINGING = 180,
+ PJSIP_SC_CALL_BEING_FORWARDED = 181,
+ PJSIP_SC_QUEUED = 182,
+ PJSIP_SC_PROGRESS = 183,
+
+ PJSIP_SC_OK = 200,
+ PJSIP_SC_ACCEPTED = 202,
+
+ PJSIP_SC_MULTIPLE_CHOICES = 300,
+ PJSIP_SC_MOVED_PERMANENTLY = 301,
+ PJSIP_SC_MOVED_TEMPORARILY = 302,
+ PJSIP_SC_USE_PROXY = 305,
+ PJSIP_SC_ALTERNATIVE_SERVICE = 380,
+
+ PJSIP_SC_BAD_REQUEST = 400,
+ PJSIP_SC_UNAUTHORIZED = 401,
+ PJSIP_SC_PAYMENT_REQUIRED = 402,
+ PJSIP_SC_FORBIDDEN = 403,
+ PJSIP_SC_NOT_FOUND = 404,
+ PJSIP_SC_METHOD_NOT_ALLOWED = 405,
+ PJSIP_SC_NOT_ACCEPTABLE = 406,
+ PJSIP_SC_PROXY_AUTHENTICATION_REQUIRED = 407,
+ PJSIP_SC_REQUEST_TIMEOUT = 408,
+ PJSIP_SC_GONE = 410,
+ PJSIP_SC_REQUEST_ENTITY_TOO_LARGE = 413,
+ PJSIP_SC_REQUEST_URI_TOO_LONG = 414,
+ PJSIP_SC_UNSUPPORTED_MEDIA_TYPE = 415,
+ PJSIP_SC_UNSUPPORTED_URI_SCHEME = 416,
+ PJSIP_SC_BAD_EXTENSION = 420,
+ PJSIP_SC_EXTENSION_REQUIRED = 421,
+ PJSIP_SC_SESSION_TIMER_TOO_SMALL = 422,
+ PJSIP_SC_INTERVAL_TOO_BRIEF = 423,
+ PJSIP_SC_TEMPORARILY_UNAVAILABLE = 480,
+ PJSIP_SC_CALL_TSX_DOES_NOT_EXIST = 481,
+ PJSIP_SC_LOOP_DETECTED = 482,
+ PJSIP_SC_TOO_MANY_HOPS = 483,
+ PJSIP_SC_ADDRESS_INCOMPLETE = 484,
+ PJSIP_AC_AMBIGUOUS = 485,
+ PJSIP_SC_BUSY_HERE = 486,
+ PJSIP_SC_REQUEST_TERMINATED = 487,
+ PJSIP_SC_NOT_ACCEPTABLE_HERE = 488,
+ PJSIP_SC_BAD_EVENT = 489,
+ PJSIP_SC_REQUEST_UPDATED = 490,
+ PJSIP_SC_REQUEST_PENDING = 491,
+ PJSIP_SC_UNDECIPHERABLE = 493,
+
+ PJSIP_SC_INTERNAL_SERVER_ERROR = 500,
+ PJSIP_SC_NOT_IMPLEMENTED = 501,
+ PJSIP_SC_BAD_GATEWAY = 502,
+ PJSIP_SC_SERVICE_UNAVAILABLE = 503,
+ PJSIP_SC_SERVER_TIMEOUT = 504,
+ PJSIP_SC_VERSION_NOT_SUPPORTED = 505,
+ PJSIP_SC_MESSAGE_TOO_LARGE = 513,
+ PJSIP_SC_PRECONDITION_FAILURE = 580,
+
+ PJSIP_SC_BUSY_EVERYWHERE = 600,
+ PJSIP_SC_DECLINE = 603,
+ PJSIP_SC_DOES_NOT_EXIST_ANYWHERE = 604,
+ PJSIP_SC_NOT_ACCEPTABLE_ANYWHERE = 606,
+
+ PJSIP_SC_TSX_TIMEOUT = PJSIP_SC_REQUEST_TIMEOUT,
+ /*PJSIP_SC_TSX_RESOLVE_ERROR = 702,*/
+ PJSIP_SC_TSX_TRANSPORT_ERROR = PJSIP_SC_SERVICE_UNAVAILABLE,
+
+ /* This is not an actual status code, but rather a constant
+ * to force GCC to use 32bit to represent this enum, since
+ * we have a code in PJSUA-LIB that assigns an integer
+ * to this enum (see pjsua_acc_get_info() function).
+ */
+ PJSIP_SC__force_32bit = 0x7FFFFFFF
+
+} pjsip_status_code;
+
+/**
+ * Get the default status text for the status code.
+ *
+ * @param status_code SIP Status Code
+ *
+ * @return textual message for the status code.
+ */
+PJ_DECL(const pj_str_t*) pjsip_get_status_text(int status_code);
+
+/**
+ * This macro returns non-zero (TRUE) if the specified status_code is
+ * in the same class as the code_class.
+ *
+ * @param status_code The status code.
+ * @param code_class The status code in the class (for example 100, 200).
+ */
+#define PJSIP_IS_STATUS_IN_CLASS(status_code, code_class) \
+ (status_code/100 == code_class/100)
+
+/**
+ * @}
+ */
+
+/* **************************************************************************/
+/**
+ * @addtogroup PJSIP_MSG_MEDIA Media/MIME Type
+ * @brief Media/MIME type declaration and manipulations.
+ * @ingroup PJSIP_MSG
+ * @{
+ */
+
+/**
+ * This structure describes SIP media type, as used for example in
+ * Accept and Content-Type header..
+ */
+typedef struct pjsip_media_type
+{
+ pj_str_t type; /**< Media type. */
+ pj_str_t subtype; /**< Media subtype. */
+ pjsip_param param; /**< Media type parameters */
+} pjsip_media_type;
+
+
+/**
+ * Initialize the media type with the specified type and subtype string.
+ *
+ * @param mt The media type.
+ * @param type Optionally specify the media type.
+ * @param subtype Optionally specify the media subtype.
+ */
+PJ_DECL(void) pjsip_media_type_init(pjsip_media_type *mt,
+ pj_str_t *type,
+ pj_str_t *subtype);
+
+/**
+ * Initialize the media type with the specified type and subtype string.
+ *
+ * @param mt The media type.
+ * @param type Optionally specify the media type.
+ * @param subtype Optionally specify the media subtype.
+ */
+PJ_DECL(void) pjsip_media_type_init2(pjsip_media_type *mt,
+ char *type,
+ char *subtype);
+
+/**
+ * Compare two media types.
+ *
+ * @param mt1 The first media type.
+ * @param mt2 The second media type.
+ * @param cmp_param Specify how to compare the media type parameters:
+ * - 0: do not compare parameters
+ * - 1: compare parameters but ignore parameters that
+ * only appear in one of the media type.
+ * - 2: compare the parameters.
+ *
+ * @return Zero if both media types are equal, -1 if mt1 < mt2,
+ * 1 if mt1 > mt2.
+ */
+PJ_DECL(int) pjsip_media_type_cmp(const pjsip_media_type *mt1,
+ const pjsip_media_type *mt2,
+ int cmp_param);
+
+/**
+ * Copy SIP media type to another.
+ *
+ * @param pool Pool to duplicate strings.
+ * @param dst Destination structure.
+ * @param src Source structure.
+ */
+PJ_DECL(void) pjsip_media_type_cp(pj_pool_t *pool,
+ pjsip_media_type *dst,
+ const pjsip_media_type *src);
+
+/**
+ * Print media type to the specified buffer.
+ *
+ * @param buf Destination buffer.
+ * @param len Length of the buffer.
+ * @param mt The media type to be printed.
+ *
+ * @return The number of characters printed to the buffer, or -1
+ * if there's not enough space in the buffer.
+ */
+PJ_DECL(int) pjsip_media_type_print(char *buf, unsigned len,
+ const pjsip_media_type *mt);
+
+/**
+ * @}
+ */
+
+/* **************************************************************************/
+/**
+ * @addtogroup PJSIP_MSG_BODY Message Body
+ * @brief SIP message body structures and manipulation.
+ * @ingroup PJSIP_MSG
+ * @{
+ */
+
+/**
+ * Generic abstraction to message body.
+ * When an incoming message is parsed (pjsip_parse_msg()), the parser fills in
+ * all members with the appropriate value. The 'data' and 'len' member will
+ * describe portion of incoming packet which denotes the message body.
+ * When application needs to attach message body to outgoing SIP message, it
+ * must fill in all members of this structure.
+ */
+struct pjsip_msg_body
+{
+ /** MIME content type.
+ * For incoming messages, the parser will fill in this member with the
+ * content type found in Content-Type header.
+ *
+ * For outgoing messages, application may fill in this member with
+ * appropriate value, because the stack will generate Content-Type header
+ * based on the value specified here.
+ *
+ * If the content_type is empty, no Content-Type AND Content-Length header
+ * will be added to the message. The stack assumes that application adds
+ * these headers themselves.
+ */
+ pjsip_media_type content_type;
+
+ /** Pointer to buffer which holds the message body data.
+ * For incoming messages, the parser will fill in this member with the
+ * pointer to the body string.
+ *
+ * When sending outgoing message, this member doesn't need to point to the
+ * actual message body string. It can be assigned with arbitrary pointer,
+ * because the value will only need to be understood by the print_body()
+ * function. The stack itself will not try to interpret this value, but
+ * instead will always call the print_body() whenever it needs to get the
+ * actual body string.
+ */
+ void *data;
+
+ /** The length of the data.
+ * For incoming messages, the parser will fill in this member with the
+ * actual length of message body.
+ *
+ * When sending outgoing message, again just like the "data" member, the
+ * "len" member doesn't need to point to the actual length of the body
+ * string.
+ */
+ unsigned len;
+
+ /** Pointer to function to print this message body.
+ * Application must set a proper function here when sending outgoing
+ * message.
+ *
+ * @param msg_body This structure itself.
+ * @param buf The buffer.
+ * @param size The buffer size.
+ *
+ * @return The length of the string printed, or -1 if there is
+ * not enough space in the buffer to print the whole
+ * message body.
+ */
+ int (*print_body)(struct pjsip_msg_body *msg_body,
+ char *buf, pj_size_t size);
+
+ /** Clone the data part only of this message body. Note that this only
+ * duplicates the data part of the body instead of the whole message
+ * body. If application wants to duplicate the entire message body
+ * structure, it must call #pjsip_msg_body_clone().
+ *
+ * @param pool Pool used to clone the data.
+ * @param data The data inside message body, to be cloned.
+ * @param len The length of the data.
+ *
+ * @return New data duplicated from the original data.
+ */
+ void* (*clone_data)(pj_pool_t *pool, const void *data, unsigned len);
+
+};
+
+/**
+ * General purpose function to textual data in a SIP body. Attach this function
+ * in a SIP message body only if the data in pjsip_msg_body is a textual
+ * message ready to be embedded in a SIP message. If the data in the message
+ * body is not a textual body, then application must supply a custom function
+ * to print that body.
+ *
+ * @param msg_body The message body.
+ * @param buf Buffer to copy the message body to.
+ * @param size The size of the buffer.
+ *
+ * @return The length copied to the buffer, or -1.
+ */
+PJ_DECL(int) pjsip_print_text_body( pjsip_msg_body *msg_body,
+ char *buf, pj_size_t size);
+
+/**
+ * General purpose function to clone textual data in a SIP body. Attach this
+ * function as "clone_data" member of the SIP body only if the data type
+ * is a text (i.e. C string, not pj_str_t), and the length indicates the
+ * length of the text.
+ *
+ * @param pool Pool used to clone the data.
+ * @param data Textual data.
+ * @param len The length of the string.
+ *
+ * @return New text duplicated from the original text.
+ */
+PJ_DECL(void*) pjsip_clone_text_data( pj_pool_t *pool, const void *data,
+ unsigned len);
+
+
+/**
+ * Clone the message body in src_body to the dst_body. This will duplicate
+ * the contents of the message body using the \a clone_data member of the
+ * source message body.
+ *
+ * @param pool Pool to use to duplicate the message body.
+ * @param dst_body Destination message body.
+ * @param src_body Source message body to duplicate.
+ *
+ * @return PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjsip_msg_body_copy( pj_pool_t *pool,
+ pjsip_msg_body *dst_body,
+ const pjsip_msg_body *src_body );
+
+
+/**
+ * Create cloned message body. This will duplicate the contents of the message
+ * body using the \a clone_data member of the source message body.
+ *
+ * @param pool Pool to use to duplicate the message body.
+ * @param body Source message body to duplicate.
+ *
+ * @return The cloned message body on successfull.
+ */
+PJ_DECL(pjsip_msg_body*) pjsip_msg_body_clone( pj_pool_t *pool,
+ const pjsip_msg_body *body );
+
+
+/**
+ * Create a text message body. Use this function to create message body when
+ * the content is a simple text. For non-text message body (e.g.
+ * pjmedia_sdp_session or pj_xml_node), application must construct the message
+ * manually.
+ *
+ * @param pool Pool to allocate message body and its contents.
+ * @param type MIME type (e.g. "text").
+ * @param subtype MIME subtype (e.g. "plain").
+ * @param text The text content to be put in the message body.
+ *
+ * @return A new message body with the specified Content-Type and
+ * text.
+ */
+PJ_DECL(pjsip_msg_body*) pjsip_msg_body_create( pj_pool_t *pool,
+ const pj_str_t *type,
+ const pj_str_t *subtype,
+ const pj_str_t *text );
+
+/**
+ * @}
+ */
+
+/* **************************************************************************/
+/**
+ * @defgroup PJSIP_MSG_MSG Message Structure
+ * @brief SIP message (request and response) structure and operations.
+ * @ingroup PJSIP_MSG
+ * @{
+ */
+
+/**
+ * Message type (request or response).
+ */
+typedef enum pjsip_msg_type_e
+{
+ PJSIP_REQUEST_MSG, /**< Indicates request message. */
+ PJSIP_RESPONSE_MSG /**< Indicates response message. */
+} pjsip_msg_type_e;
+
+
+/**
+ * This structure describes a SIP message.
+ */
+struct pjsip_msg
+{
+ /** Message type (ie request or response). */
+ pjsip_msg_type_e type;
+
+ /** The first line of the message can be either request line for request
+ * messages, or status line for response messages. It is represented here
+ * as a union.
+ */
+ union
+ {
+ /** Request Line. */
+ struct pjsip_request_line req;
+
+ /** Status Line. */
+ struct pjsip_status_line status;
+ } line;
+
+ /** List of message headers. */
+ pjsip_hdr hdr;
+
+ /** Pointer to message body, or NULL if no message body is attached to
+ * this mesage.
+ */
+ pjsip_msg_body *body;
+};
+
+
+/**
+ * Create new request or response message.
+ *
+ * @param pool The pool.
+ * @param type Message type.
+ * @return New message, or THROW exception if failed.
+ */
+PJ_DECL(pjsip_msg*) pjsip_msg_create( pj_pool_t *pool, pjsip_msg_type_e type);
+
+
+/**
+ * Perform a deep clone of a SIP message.
+ *
+ * @param pool The pool for creating the new message.
+ * @param msg The message to be duplicated.
+ *
+ * @return New message, which is duplicated from the original
+ * message.
+ */
+PJ_DECL(pjsip_msg*) pjsip_msg_clone( pj_pool_t *pool, const pjsip_msg *msg);
+
+
+/**
+ * Find a header in the message by the header type.
+ *
+ * @param msg The message.
+ * @param type The header type to find.
+ * @param start The first header field where the search should begin.
+ * If NULL is specified, then the search will begin from the
+ * first header, otherwise the search will begin at the
+ * specified header.
+ *
+ * @return The header field, or NULL if no header with the specified
+ * type is found.
+ */
+PJ_DECL(void*) pjsip_msg_find_hdr( const pjsip_msg *msg,
+ pjsip_hdr_e type, const void *start);
+
+/**
+ * Find a header in the message by its name.
+ *
+ * @param msg The message.
+ * @param name The header name to find.
+ * @param start The first header field where the search should begin.
+ * If NULL is specified, then the search will begin from the
+ * first header, otherwise the search will begin at the
+ * specified header.
+ *
+ * @return The header field, or NULL if no header with the specified
+ * type is found.
+ */
+PJ_DECL(void*) pjsip_msg_find_hdr_by_name( const pjsip_msg *msg,
+ const pj_str_t *name,
+ const void *start);
+
+/**
+ * Find a header in the message by its name and short name version.
+ *
+ * @param msg The message.
+ * @param name The header name to find.
+ * @param sname The short name version of the header name.
+ * @param start The first header field where the search should begin.
+ * If NULL is specified, then the search will begin from the
+ * first header, otherwise the search will begin at the
+ * specified header.
+ *
+ * @return The header field, or NULL if no header with the specified
+ * type is found.
+ */
+PJ_DECL(void*) pjsip_msg_find_hdr_by_names(const pjsip_msg *msg,
+ const pj_str_t *name,
+ const pj_str_t *sname,
+ const void *start);
+
+/**
+ * Find and remove a header in the message.
+ *
+ * @param msg The message.
+ * @param hdr The header type to find.
+ * @param start The first header field where the search should begin,
+ * or NULL to search from the first header in the message.
+ *
+ * @return The header field, or NULL if not found.
+ */
+PJ_DECL(void*) pjsip_msg_find_remove_hdr( pjsip_msg *msg,
+ pjsip_hdr_e hdr, void *start);
+
+/**
+ * Add a header to the message, putting it last in the header list.
+ *
+ * @param msg The message.
+ * @param hdr The header to add.
+ *
+ * @bug Once the header is put in a list (or message), it can not be put in
+ * other list (or message). Otherwise Real Bad Thing will happen.
+ */
+PJ_INLINE(void) pjsip_msg_add_hdr( pjsip_msg *msg, pjsip_hdr *hdr )
+{
+ pj_list_insert_before(&msg->hdr, hdr);
+}
+
+/**
+ * Add header field to the message, putting it in the front of the header list.
+ *
+ * @param msg The message.
+ * @param hdr The header to add.
+ *
+ * @bug Once the header is put in a list (or message), it can not be put in
+ * other list (or message). Otherwise Real Bad Thing will happen.
+ */
+PJ_INLINE(void) pjsip_msg_insert_first_hdr( pjsip_msg *msg, pjsip_hdr *hdr )
+{
+ pj_list_insert_after(&msg->hdr, hdr);
+}
+
+/**
+ * Print the message to the specified buffer.
+ *
+ * @param msg The message to print.
+ * @param buf The buffer
+ * @param size The size of the buffer.
+ *
+ * @return The length of the printed characters (in bytes), or NEGATIVE
+ * value if the message is too large for the specified buffer.
+ */
+PJ_DECL(pj_ssize_t) pjsip_msg_print(const pjsip_msg *msg,
+ char *buf, pj_size_t size);
+
+
+/*
+ * Some usefull macros to find common headers.
+ */
+
+
+/**
+ * Find Call-ID header.
+ *
+ * @param msg The message.
+ * @return Call-ID header instance.
+ */
+#define PJSIP_MSG_CID_HDR(msg) \
+ ((pjsip_cid_hdr*)pjsip_msg_find_hdr(msg, PJSIP_H_CALL_ID, NULL))
+
+/**
+ * Find CSeq header.
+ *
+ * @param msg The message.
+ * @return CSeq header instance.
+ */
+#define PJSIP_MSG_CSEQ_HDR(msg) \
+ ((pjsip_cseq_hdr*)pjsip_msg_find_hdr(msg, PJSIP_H_CSEQ, NULL))
+
+/**
+ * Find From header.
+ *
+ * @param msg The message.
+ * @return From header instance.
+ */
+#define PJSIP_MSG_FROM_HDR(msg) \
+ ((pjsip_from_hdr*)pjsip_msg_find_hdr(msg, PJSIP_H_FROM, NULL))
+
+/**
+ * Find To header.
+ *
+ * @param msg The message.
+ * @return To header instance.
+ */
+#define PJSIP_MSG_TO_HDR(msg) \
+ ((pjsip_to_hdr*)pjsip_msg_find_hdr(msg, PJSIP_H_TO, NULL))
+
+
+/**
+ * @}
+ */
+
+/* **************************************************************************/
+/**
+ * @addtogroup PJSIP_MSG_HDR
+ * @{
+ */
+
+/**
+ * Generic SIP header, which contains hname and a string hvalue.
+ * Note that this header is not supposed to be used as 'base' class for headers.
+ */
+typedef struct pjsip_generic_string_hdr
+{
+ /** Standard header field. */
+ PJSIP_DECL_HDR_MEMBER(struct pjsip_generic_string_hdr);
+ /** hvalue */
+ pj_str_t hvalue;
+} pjsip_generic_string_hdr;
+
+
+/**
+ * Create a new instance of generic header. A generic header can have an
+ * arbitrary header name.
+ *
+ * @param pool The pool.
+ * @param hname The header name to be assigned to the header, or NULL to
+ * assign the header name with some string.
+ * @param hvalue Optional string to be assigned as the value.
+ *
+ * @return The header, or THROW exception.
+ */
+PJ_DECL(pjsip_generic_string_hdr*)
+pjsip_generic_string_hdr_create( pj_pool_t *pool,
+ const pj_str_t *hname,
+ const pj_str_t *hvalue);
+
+
+/**
+ * Initialize a preallocated memory with the header structure. This function
+ * should only be called when application uses its own memory allocation to
+ * allocate memory block for the specified header (e.g. in C++, when the
+ * header is allocated with "new" operator).
+ * For normal applications, they should use pjsip_xxx_hdr_create() instead,
+ * which allocates memory and initialize it in one go.
+ *
+ * @param pool Pool for additional memory allocation if required.
+ * @param mem Pre-allocated memory to be initialized as the header.
+ * @param hname The header name to be assigned to the header, or NULL to
+ * assign the header name with some string later.
+ * @param hvalue Optional string to be assigned as the value.
+ *
+ * @return The header instance, which points to the same memory
+ * location as the mem argument.
+ */
+PJ_DECL(pjsip_generic_string_hdr*)
+pjsip_generic_string_hdr_init( pj_pool_t *pool,
+ void *mem,
+ const pj_str_t *hname,
+ const pj_str_t *hvalue);
+
+
+/**
+ * Construct a generic string header without allocating memory from the pool.
+ * This function is useful to create a temporary header which life-time is
+ * very short (for example, creating the header in the stack to be passed
+ * as argument to a function which will copy the header).
+ *
+ * @param h The header to be initialized.
+ * @param hname The header name to be assigned to the header, or NULL to
+ * assign the header name with some string.
+ * @param hvalue Optional string to be assigned as the value.
+ *
+ * @return The header, or THROW exception.
+ */
+PJ_DECL(void) pjsip_generic_string_hdr_init2(pjsip_generic_string_hdr *h,
+ pj_str_t *hname,
+ pj_str_t *hvalue);
+
+
+/* **************************************************************************/
+
+/**
+ * Generic SIP header, which contains hname and a string hvalue.
+ */
+typedef struct pjsip_generic_int_hdr
+{
+ PJSIP_DECL_HDR_MEMBER(struct pjsip_generic_int_hdr); /**< Standard header field. */
+ pj_int32_t ivalue; /**< ivalue */
+} pjsip_generic_int_hdr;
+
+
+/**
+ * Create a new instance of generic header. A generic header can have an
+ * arbitrary header name.
+ *
+ * @param pool The pool.
+ * @param hname The header name to be assigned to the header, or NULL to
+ * assign the header name with some string.
+ * @param hvalue The value to be assigned to the header.
+ *
+ * @return The header, or THROW exception.
+ */
+PJ_DECL(pjsip_generic_int_hdr*) pjsip_generic_int_hdr_create( pj_pool_t *pool,
+ const pj_str_t *hname,
+ int hvalue );
+
+
+/**
+ * Initialize a preallocated memory with the header structure. This function
+ * should only be called when application uses its own memory allocation to
+ * allocate memory block for the specified header (e.g. in C++, when the
+ * header is allocated with "new" operator).
+ * For normal applications, they should use pjsip_xxx_hdr_create() instead,
+ * which allocates memory and initialize it in one go.
+ *
+ * @param pool Pool for additional memory allocation if required.
+ * @param mem Pre-allocated memory to be initialized as the header.
+ * @param hname The header name to be assigned to the header, or NULL to
+ * assign the header name with some string later.
+ * @param value Value to be assigned to the header.
+ *
+ * @return The header instance, which points to the same memory
+ * location as the mem argument.
+ */
+PJ_DECL(pjsip_generic_int_hdr*) pjsip_generic_int_hdr_init( pj_pool_t *pool,
+ void *mem,
+ const pj_str_t *hname,
+ int value );
+
+/* **************************************************************************/
+
+/** Maximum elements in the header array. */
+#define PJSIP_GENERIC_ARRAY_MAX_COUNT 32
+
+/**
+ * Generic array of string header.
+ */
+typedef struct pjsip_generic_array_hdr
+{
+ /** Standard header fields. */
+ PJSIP_DECL_HDR_MEMBER(struct pjsip_generic_array_hdr);
+
+ /** Number of tags/elements. */
+ unsigned count;
+
+ /** Tags/elements. */
+ pj_str_t values[PJSIP_GENERIC_ARRAY_MAX_COUNT];
+
+} pjsip_generic_array_hdr;
+
+/**
+ * Create generic array header.
+ *
+ * @param pool Pool to allocate memory from.
+ * @param hname Header name.
+ *
+ * @return New generic array header.
+ */
+PJ_DECL(pjsip_generic_array_hdr*) pjsip_generic_array_hdr_create(pj_pool_t *pool,
+ const pj_str_t *hname);
+
+/**
+ * Initialize a preallocated memory with the header structure. This function
+ * should only be called when application uses its own memory allocation to
+ * allocate memory block for the specified header (e.g. in C++, when the
+ * header is allocated with "new" operator).
+ * For normal applications, they should use pjsip_xxx_hdr_create() instead,
+ * which allocates memory and initialize it in one go.
+ *
+ * @param pool Pool for additional memory allocation if required.
+ * @param mem Pre-allocated memory to be initialized as the header.
+ * @param hname The header name to be assigned to the header, or NULL to
+ * assign the header name with some string later.
+ *
+ * @return The header instance, which points to the same memory
+ * location as the mem argument.
+ */
+PJ_DECL(pjsip_generic_array_hdr*) pjsip_generic_array_hdr_init(pj_pool_t *pool,
+ void *mem,
+ const pj_str_t *hname);
+
+
+/* **************************************************************************/
+
+/** Accept header. */
+typedef pjsip_generic_array_hdr pjsip_accept_hdr;
+
+/** Maximum fields in Accept header. */
+#define PJSIP_MAX_ACCEPT_COUNT PJSIP_GENERIC_ARRAY_MAX_COUNT
+
+/**
+ * Create new Accept header instance.
+ *
+ * @param pool The pool.
+ *
+ * @return New Accept header instance.
+ */
+PJ_DECL(pjsip_accept_hdr*) pjsip_accept_hdr_create(pj_pool_t *pool);
+
+/**
+ * Initialize a preallocated memory with the header structure. This function
+ * should only be called when application uses its own memory allocation to
+ * allocate memory block for the specified header (e.g. in C++, when the
+ * header is allocated with "new" operator).
+ * For normal applications, they should use pjsip_xxx_hdr_create() instead,
+ * which allocates memory and initialize it in one go.
+ *
+ * @param pool Pool for additional memory allocation if required.
+ * @param mem Pre-allocated memory to be initialized as the header.
+ *
+ * @return The header instance, which points to the same memory
+ * location as the mem argument.
+ */
+PJ_DECL(pjsip_accept_hdr*) pjsip_accept_hdr_init( pj_pool_t *pool,
+ void *mem );
+
+
+/* **************************************************************************/
+
+/**
+ * Allow header.
+ */
+typedef pjsip_generic_array_hdr pjsip_allow_hdr;
+
+/**
+ * Create new Allow header instance.
+ *
+ * @param pool The pool.
+ *
+ * @return New Allow header instance.
+ */
+PJ_DECL(pjsip_allow_hdr*) pjsip_allow_hdr_create(pj_pool_t *pool);
+
+
+
+/**
+ * Initialize a preallocated memory with the header structure. This function
+ * should only be called when application uses its own memory allocation to
+ * allocate memory block for the specified header (e.g. in C++, when the
+ * header is allocated with "new" operator).
+ * For normal applications, they should use pjsip_xxx_hdr_create() instead,
+ * which allocates memory and initialize it in one go.
+ *
+ * @param pool Pool for additional memory allocation if required.
+ * @param mem Pre-allocated memory to be initialized as the header.
+ *
+ * @return The header instance, which points to the same memory
+ * location as the mem argument.
+ */
+PJ_DECL(pjsip_allow_hdr*) pjsip_allow_hdr_init( pj_pool_t *pool,
+ void *mem );
+
+/* **************************************************************************/
+
+/**
+ * Call-ID header.
+ */
+typedef struct pjsip_cid_hdr
+{
+ PJSIP_DECL_HDR_MEMBER(struct pjsip_cid_hdr);
+ pj_str_t id; /**< Call-ID string. */
+} pjsip_cid_hdr;
+
+
+/**
+ * Create new Call-ID header.
+ *
+ * @param pool The pool.
+ *
+ * @return new Call-ID header.
+ */
+PJ_DECL(pjsip_cid_hdr*) pjsip_cid_hdr_create( pj_pool_t *pool );
+
+
+/**
+ * Initialize a preallocated memory with the header structure. This function
+ * should only be called when application uses its own memory allocation to
+ * allocate memory block for the specified header (e.g. in C++, when the
+ * header is allocated with "new" operator).
+ * For normal applications, they should use pjsip_xxx_hdr_create() instead,
+ * which allocates memory and initialize it in one go.
+ *
+ * @param pool Pool for additional memory allocation if required.
+ * @param mem Pre-allocated memory to be initialized as the header.
+ *
+ * @return The header instance, which points to the same memory
+ * location as the mem argument.
+ */
+PJ_DECL(pjsip_cid_hdr*) pjsip_cid_hdr_init( pj_pool_t *pool,
+ void *mem );
+
+
+
+/* **************************************************************************/
+/**
+ * Content-Length header.
+ */
+typedef struct pjsip_clen_hdr
+{
+ PJSIP_DECL_HDR_MEMBER(struct pjsip_clen_hdr);
+ int len; /**< Content length. */
+} pjsip_clen_hdr;
+
+/**
+ * Create new Content-Length header.
+ *
+ * @param pool the pool.
+ * @return A new Content-Length header instance.
+ */
+PJ_DECL(pjsip_clen_hdr*) pjsip_clen_hdr_create( pj_pool_t *pool );
+
+/**
+ * Initialize a preallocated memory with the header structure. This function
+ * should only be called when application uses its own memory allocation to
+ * allocate memory block for the specified header (e.g. in C++, when the
+ * header is allocated with "new" operator).
+ * For normal applications, they should use pjsip_xxx_hdr_create() instead,
+ * which allocates memory and initialize it in one go.
+ *
+ * @param pool Pool for additional memory allocation if required.
+ * @param mem Pre-allocated memory to be initialized as the header.
+ *
+ * @return The header instance, which points to the same memory
+ * location as the mem argument.
+ */
+PJ_DECL(pjsip_clen_hdr*) pjsip_clen_hdr_init( pj_pool_t *pool,
+ void *mem );
+
+
+/* **************************************************************************/
+/**
+ * CSeq header.
+ */
+typedef struct pjsip_cseq_hdr
+{
+ PJSIP_DECL_HDR_MEMBER(struct pjsip_cseq_hdr);
+ pj_int32_t cseq; /**< CSeq number. */
+ pjsip_method method; /**< CSeq method. */
+} pjsip_cseq_hdr;
+
+
+/** Create new CSeq header.
+ *
+ * @param pool The pool.
+ * @return A new CSeq header instance.
+ */
+PJ_DECL(pjsip_cseq_hdr*) pjsip_cseq_hdr_create( pj_pool_t *pool );
+
+/**
+ * Initialize a preallocated memory with the header structure. This function
+ * should only be called when application uses its own memory allocation to
+ * allocate memory block for the specified header (e.g. in C++, when the
+ * header is allocated with "new" operator).
+ * For normal applications, they should use pjsip_xxx_hdr_create() instead,
+ * which allocates memory and initialize it in one go.
+ *
+ * @param pool Pool for additional memory allocation if required.
+ * @param mem Pre-allocated memory to be initialized as the header.
+ *
+ * @return The header instance, which points to the same memory
+ * location as the mem argument.
+ */
+PJ_DECL(pjsip_cseq_hdr*) pjsip_cseq_hdr_init( pj_pool_t *pool,
+ void *mem );
+
+/* **************************************************************************/
+/**
+ * Contact header.
+ * In this library, contact header only contains single URI. If a message has
+ * multiple URI in the Contact header, the URI will be put in separate Contact
+ * headers.
+ */
+typedef struct pjsip_contact_hdr
+{
+ PJSIP_DECL_HDR_MEMBER(struct pjsip_contact_hdr);
+ int star; /**< The contact contains only a '*' character */
+ pjsip_uri *uri; /**< URI in the contact. */
+ int q1000; /**< The "q" value times 1000 (to avoid float) */
+ pj_int32_t expires; /**< Expires parameter, otherwise -1 if not present. */
+ pjsip_param other_param; /**< Other parameters, concatenated in a single string. */
+} pjsip_contact_hdr;
+
+
+/**
+ * Create a new Contact header.
+ *
+ * @param pool The pool.
+ * @return A new instance of Contact header.
+ */
+PJ_DECL(pjsip_contact_hdr*) pjsip_contact_hdr_create( pj_pool_t *pool );
+
+/**
+ * Initialize a preallocated memory with the header structure. This function
+ * should only be called when application uses its own memory allocation to
+ * allocate memory block for the specified header (e.g. in C++, when the
+ * header is allocated with "new" operator).
+ * For normal applications, they should use pjsip_xxx_hdr_create() instead,
+ * which allocates memory and initialize it in one go.
+ *
+ * @param pool Pool for additional memory allocation if required.
+ * @param mem Pre-allocated memory to be initialized as the header.
+ *
+ * @return The header instance, which points to the same memory
+ * location as the mem argument.
+ */
+PJ_DECL(pjsip_contact_hdr*) pjsip_contact_hdr_init( pj_pool_t *pool,
+ void *mem );
+
+
+/* **************************************************************************/
+/**
+ * Content-Type.
+ */
+typedef struct pjsip_ctype_hdr
+{
+ PJSIP_DECL_HDR_MEMBER(struct pjsip_ctype_hdr);
+ pjsip_media_type media; /**< Media type. */
+} pjsip_ctype_hdr;
+
+
+/**
+ * Create a nwe Content Type header.
+ *
+ * @param pool The pool.
+ * @return A new Content-Type header.
+ */
+PJ_DECL(pjsip_ctype_hdr*) pjsip_ctype_hdr_create( pj_pool_t *pool );
+
+/**
+ * Initialize a preallocated memory with the header structure. This function
+ * should only be called when application uses its own memory allocation to
+ * allocate memory block for the specified header (e.g. in C++, when the
+ * header is allocated with "new" operator).
+ * For normal applications, they should use pjsip_xxx_hdr_create() instead,
+ * which allocates memory and initialize it in one go.
+ *
+ * @param pool Pool for additional memory allocation if required.
+ * @param mem Pre-allocated memory to be initialized as the header.
+ *
+ * @return The header instance, which points to the same memory
+ * location as the mem argument.
+ */
+PJ_DECL(pjsip_ctype_hdr*) pjsip_ctype_hdr_init( pj_pool_t *pool,
+ void *mem );
+
+/* **************************************************************************/
+/** Expires header. */
+typedef pjsip_generic_int_hdr pjsip_expires_hdr;
+
+/**
+ * Create a new Expires header.
+ *
+ * @param pool The pool.
+ * @param value The expiration value.
+ *
+ * @return A new Expires header.
+ */
+PJ_DECL(pjsip_expires_hdr*) pjsip_expires_hdr_create( pj_pool_t *pool,
+ int value);
+
+/**
+ * Initialize a preallocated memory with the header structure. This function
+ * should only be called when application uses its own memory allocation to
+ * allocate memory block for the specified header (e.g. in C++, when the
+ * header is allocated with "new" operator).
+ * For normal applications, they should use pjsip_xxx_hdr_create() instead,
+ * which allocates memory and initialize it in one go.
+ *
+ * @param pool Pool for additional memory allocation if required.
+ * @param mem Pre-allocated memory to be initialized as the header.
+ * @param value The expiration value.
+ *
+ * @return The header instance, which points to the same memory
+ * location as the mem argument.
+ */
+PJ_DECL(pjsip_expires_hdr*) pjsip_expires_hdr_init( pj_pool_t *pool,
+ void *mem,
+ int value );
+
+
+
+/* **************************************************************************/
+/**
+ * To or From header.
+ */
+typedef struct pjsip_fromto_hdr
+{
+ PJSIP_DECL_HDR_MEMBER(struct pjsip_fromto_hdr);
+ pjsip_uri *uri; /**< URI in From/To header. */
+ pj_str_t tag; /**< Header "tag" parameter. */
+ pjsip_param other_param; /**< Other params, concatenated as a single string. */
+} pjsip_fromto_hdr;
+
+/** Alias for From header. */
+typedef pjsip_fromto_hdr pjsip_from_hdr;
+
+/** Alias for To header. */
+typedef pjsip_fromto_hdr pjsip_to_hdr;
+
+/**
+ * Create a From header.
+ *
+ * @param pool The pool.
+ * @return New instance of From header.
+ */
+PJ_DECL(pjsip_from_hdr*) pjsip_from_hdr_create( pj_pool_t *pool );
+
+/**
+ * Initialize a preallocated memory with the header structure. This function
+ * should only be called when application uses its own memory allocation to
+ * allocate memory block for the specified header (e.g. in C++, when the
+ * header is allocated with "new" operator).
+ * For normal applications, they should use pjsip_xxx_hdr_create() instead,
+ * which allocates memory and initialize it in one go.
+ *
+ * @param pool Pool for additional memory allocation if required.
+ * @param mem Pre-allocated memory to be initialized as the header.
+ *
+ * @return The header instance, which points to the same memory
+ * location as the mem argument.
+ */
+PJ_DECL(pjsip_from_hdr*) pjsip_from_hdr_init( pj_pool_t *pool,
+ void *mem );
+
+/**
+ * Create a To header.
+ *
+ * @param pool The pool.
+ * @return New instance of To header.
+ */
+PJ_DECL(pjsip_to_hdr*) pjsip_to_hdr_create( pj_pool_t *pool );
+
+/**
+ * Initialize a preallocated memory with the header structure. This function
+ * should only be called when application uses its own memory allocation to
+ * allocate memory block for the specified header (e.g. in C++, when the
+ * header is allocated with "new" operator).
+ * For normal applications, they should use pjsip_xxx_hdr_create() instead,
+ * which allocates memory and initialize it in one go.
+ *
+ * @param pool Pool for additional memory allocation if required.
+ * @param mem Pre-allocated memory to be initialized as the header.
+ *
+ * @return The header instance, which points to the same memory
+ * location as the mem argument.
+ */
+PJ_DECL(pjsip_to_hdr*) pjsip_to_hdr_init( pj_pool_t *pool,
+ void *mem );
+
+/**
+ * Convert the header to a From header.
+ *
+ * @param hdr The generic from/to header.
+ * @return "From" header.
+ */
+PJ_DECL(pjsip_from_hdr*) pjsip_fromto_hdr_set_from( pjsip_fromto_hdr *hdr );
+
+/**
+ * Convert the header to a To header.
+ *
+ * @param hdr The generic from/to header.
+ * @return "To" header.
+ */
+PJ_DECL(pjsip_to_hdr*) pjsip_fromto_hdr_set_to( pjsip_fromto_hdr *hdr );
+
+
+/* **************************************************************************/
+/**
+ * Max-Forwards header.
+ */
+typedef pjsip_generic_int_hdr pjsip_max_fwd_hdr;
+
+/**
+ * Create new Max-Forwards header instance.
+ *
+ * @param pool The pool.
+ * @param value The Max-Forwards value.
+ *
+ * @return New Max-Forwards header instance.
+ */
+PJ_DECL(pjsip_max_fwd_hdr*)
+pjsip_max_fwd_hdr_create(pj_pool_t *pool, int value);
+
+
+/**
+ * Initialize a preallocated memory with the header structure. This function
+ * should only be called when application uses its own memory allocation to
+ * allocate memory block for the specified header (e.g. in C++, when the
+ * header is allocated with "new" operator).
+ * For normal applications, they should use pjsip_xxx_hdr_create() instead,
+ * which allocates memory and initialize it in one go.
+ *
+ * @param pool Pool for additional memory allocation if required.
+ * @param mem Pre-allocated memory to be initialized as the header.
+ * @param value The Max-Forwards value.
+ *
+ * @return The header instance, which points to the same memory
+ * location as the mem argument.
+ */
+PJ_DECL(pjsip_max_fwd_hdr*)
+pjsip_max_fwd_hdr_init( pj_pool_t *pool, void *mem, int value );
+
+
+/* **************************************************************************/
+/**
+ * Min-Expires header.
+ */
+typedef pjsip_generic_int_hdr pjsip_min_expires_hdr;
+
+/**
+ * Create new Min-Expires header instance.
+ *
+ * @param pool The pool.
+ * @param value The Min-Expires value.
+ *
+ * @return New Min-Expires header instance.
+ */
+PJ_DECL(pjsip_min_expires_hdr*) pjsip_min_expires_hdr_create(pj_pool_t *pool,
+ int value);
+
+
+/**
+ * Initialize a preallocated memory with the header structure. This function
+ * should only be called when application uses its own memory allocation to
+ * allocate memory block for the specified header (e.g. in C++, when the
+ * header is allocated with "new" operator).
+ * For normal applications, they should use pjsip_xxx_hdr_create() instead,
+ * which allocates memory and initialize it in one go.
+ *
+ * @param pool Pool for additional memory allocation if required.
+ * @param mem Pre-allocated memory to be initialized as the header.
+ * @param value The Min-Expires value.
+ *
+ * @return The header instance, which points to the same memory
+ * location as the mem argument.
+ */
+PJ_DECL(pjsip_min_expires_hdr*) pjsip_min_expires_hdr_init( pj_pool_t *pool,
+ void *mem,
+ int value );
+
+
+/* **************************************************************************/
+/**
+ * Record-Route and Route headers.
+ */
+typedef struct pjsip_routing_hdr
+{
+ PJSIP_DECL_HDR_MEMBER(struct pjsip_routing_hdr); /**< Generic header fields. */
+ pjsip_name_addr name_addr; /**< The URL in the Route/Record-Route header. */
+ pjsip_param other_param; /**< Other parameter. */
+} pjsip_routing_hdr;
+
+/** Alias for Record-Route header. */
+typedef pjsip_routing_hdr pjsip_rr_hdr;
+
+/** Alias for Route header. */
+typedef pjsip_routing_hdr pjsip_route_hdr;
+
+
+/**
+ * Create new Record-Route header from the pool.
+ *
+ * @param pool The pool.
+ * @return A new instance of Record-Route header.
+ */
+PJ_DECL(pjsip_rr_hdr*) pjsip_rr_hdr_create( pj_pool_t *pool );
+
+/**
+ * Initialize a preallocated memory with the header structure. This function
+ * should only be called when application uses its own memory allocation to
+ * allocate memory block for the specified header (e.g. in C++, when the
+ * header is allocated with "new" operator).
+ * For normal applications, they should use pjsip_xxx_hdr_create() instead,
+ * which allocates memory and initialize it in one go.
+ *
+ * @param pool Pool for additional memory allocation if required.
+ * @param mem Pre-allocated memory to be initialized as the header.
+ *
+ * @return The header instance, which points to the same memory
+ * location as the mem argument.
+ */
+PJ_DECL(pjsip_rr_hdr*) pjsip_rr_hdr_init( pj_pool_t *pool,
+ void *mem );
+
+/**
+ * Create new Route header from the pool.
+ *
+ * @param pool The pool.
+ * @return A new instance of "Route" header.
+ */
+PJ_DECL(pjsip_route_hdr*) pjsip_route_hdr_create( pj_pool_t *pool );
+
+/**
+ * Initialize a preallocated memory with the header structure. This function
+ * should only be called when application uses its own memory allocation to
+ * allocate memory block for the specified header (e.g. in C++, when the
+ * header is allocated with "new" operator).
+ * For normal applications, they should use pjsip_xxx_hdr_create() instead,
+ * which allocates memory and initialize it in one go.
+ *
+ * @param pool Pool for additional memory allocation if required.
+ * @param mem Pre-allocated memory to be initialized as the header.
+ *
+ * @return The header instance, which points to the same memory
+ * location as the mem argument.
+ */
+PJ_DECL(pjsip_route_hdr*) pjsip_route_hdr_init( pj_pool_t *pool,
+ void *mem );
+
+/**
+ * Convert generic routing header to Record-Route header.
+ *
+ * @param r The generic routing header, or a "Routing" header.
+ * @return Record-Route header.
+ */
+PJ_DECL(pjsip_rr_hdr*) pjsip_routing_hdr_set_rr( pjsip_routing_hdr *r );
+
+/**
+ * Convert generic routing header to "Route" header.
+ *
+ * @param r The generic routing header, or a "Record-Route" header.
+ * @return "Route" header.
+ */
+PJ_DECL(pjsip_route_hdr*) pjsip_routing_hdr_set_route( pjsip_routing_hdr *r );
+
+/* **************************************************************************/
+/**
+ * Require header.
+ */
+typedef pjsip_generic_array_hdr pjsip_require_hdr;
+
+/**
+ * Create new Require header instance.
+ *
+ * @param pool The pool.
+ *
+ * @return New Require header instance.
+ */
+PJ_DECL(pjsip_require_hdr*) pjsip_require_hdr_create(pj_pool_t *pool);
+
+/**
+ * Initialize a preallocated memory with the header structure. This function
+ * should only be called when application uses its own memory allocation to
+ * allocate memory block for the specified header (e.g. in C++, when the
+ * header is allocated with "new" operator).
+ * For normal applications, they should use pjsip_xxx_hdr_create() instead,
+ * which allocates memory and initialize it in one go.
+ *
+ * @param pool Pool for additional memory allocation if required.
+ * @param mem Pre-allocated memory to be initialized as the header.
+ *
+ * @return The header instance, which points to the same memory
+ * location as the mem argument.
+ */
+PJ_DECL(pjsip_require_hdr*) pjsip_require_hdr_init( pj_pool_t *pool,
+ void *mem );
+
+
+/* **************************************************************************/
+/**
+ * Retry-After header.
+ */
+typedef struct pjsip_retry_after_hdr
+{
+ /** Standard header field. */
+ PJSIP_DECL_HDR_MEMBER(struct pjsip_retry_after_hdr);
+ pj_int32_t ivalue; /**< Retry-After value */
+ pjsip_param param; /**< Optional parameters */
+ pj_str_t comment; /**< Optional comments. */
+} pjsip_retry_after_hdr;
+
+
+/**
+ * Create new Retry-After header instance.
+ *
+ * @param pool The pool.
+ * @param value The Retry-After value.
+ *
+ * @return New Retry-After header instance.
+ */
+PJ_DECL(pjsip_retry_after_hdr*) pjsip_retry_after_hdr_create(pj_pool_t *pool,
+ int value);
+
+/**
+ * Initialize a preallocated memory with the header structure.
+ *
+ * @param pool Pool for additional memory allocation if required.
+ * @param mem Pre-allocated memory to be initialized as the header.
+ * @param value The Retry-After value.
+ *
+ * @return The header instance, which points to the same memory
+ * location as the mem argument.
+ */
+PJ_DECL(pjsip_retry_after_hdr*) pjsip_retry_after_hdr_init( pj_pool_t *pool,
+ void *mem,
+ int value );
+
+
+/* **************************************************************************/
+/**
+ * Supported header.
+ */
+typedef pjsip_generic_array_hdr pjsip_supported_hdr;
+
+/**
+ * Create new Supported header instance.
+ *
+ * @param pool The pool.
+ *
+ * @return New Supported header instance.
+ */
+PJ_DECL(pjsip_supported_hdr*) pjsip_supported_hdr_create(pj_pool_t *pool);
+
+/**
+ * Initialize a preallocated memory with the header structure.
+ *
+ * @param pool Pool for additional memory allocation if required.
+ * @param mem Pre-allocated memory to be initialized as the header.
+ *
+ * @return The header instance, which points to the same memory
+ * location as the mem argument.
+ */
+PJ_DECL(pjsip_supported_hdr*) pjsip_supported_hdr_init( pj_pool_t *pool,
+ void *mem );
+
+/* **************************************************************************/
+/**
+ * Unsupported header.
+ */
+typedef pjsip_generic_array_hdr pjsip_unsupported_hdr;
+
+/**
+ * Create new Unsupported header instance.
+ *
+ * @param pool The pool.
+ *
+ * @return New Unsupported header instance.
+ */
+PJ_DECL(pjsip_unsupported_hdr*) pjsip_unsupported_hdr_create(pj_pool_t *pool);
+
+/**
+ * Initialize a preallocated memory with the header structure.
+ *
+ * @param pool Pool for additional memory allocation if required.
+ * @param mem Pre-allocated memory to be initialized as the header.
+ *
+ * @return The header instance, which points to the same memory
+ * location as the mem argument.
+ */
+PJ_DECL(pjsip_unsupported_hdr*) pjsip_unsupported_hdr_init( pj_pool_t *pool,
+ void *mem );
+
+/* **************************************************************************/
+/**
+ * SIP Via header.
+ * In this implementation, Via header can only have one element in each header.
+ * If a message arrives with multiple elements in a single Via, then they will
+ * be split up into multiple Via headers.
+ */
+typedef struct pjsip_via_hdr
+{
+ PJSIP_DECL_HDR_MEMBER(struct pjsip_via_hdr);
+ pj_str_t transport; /**< Transport type. */
+ pjsip_host_port sent_by; /**< Host and optional port */
+ int ttl_param; /**< TTL parameter, or -1 if it's not specified. */
+ int rport_param; /**< "rport" parameter, 0 to specify without
+ port number, -1 means doesn't exist. */
+ pj_str_t maddr_param; /**< "maddr" parameter. */
+ pj_str_t recvd_param; /**< "received" parameter. */
+ pj_str_t branch_param; /**< "branch" parameter. */
+ pjsip_param other_param; /**< Other parameters, concatenated as single string. */
+ pj_str_t comment; /**< Comment. */
+} pjsip_via_hdr;
+
+/**
+ * Create a new Via header.
+ *
+ * @param pool The pool.
+ * @return A new "Via" header instance.
+ */
+PJ_DECL(pjsip_via_hdr*) pjsip_via_hdr_create( pj_pool_t *pool );
+
+/**
+ * Initialize a preallocated memory with the header structure.
+ *
+ * @param pool Pool for additional memory allocation if required.
+ * @param mem Pre-allocated memory to be initialized as the header.
+ *
+ * @return The header instance, which points to the same memory
+ * location as the mem argument.
+ */
+PJ_DECL(pjsip_via_hdr*) pjsip_via_hdr_init( pj_pool_t *pool,
+ void *mem );
+
+/* **************************************************************************/
+/**
+ * SIP Warning header.
+ * In this version, Warning header is just a typedef for generic string
+ * header.
+ */
+typedef pjsip_generic_string_hdr pjsip_warning_hdr;
+
+/**
+ * Create a warning header with the specified contents.
+ *
+ * @param pool Pool to allocate memory from.
+ * @param code Warning code, 300-399.
+ * @param host The host portion of the Warning header.
+ * @param text The warning text, which MUST not be quoted with
+ * double quote.
+ *
+ * @return The Warning header field.
+ */
+PJ_DECL(pjsip_warning_hdr*) pjsip_warning_hdr_create( pj_pool_t *pool,
+ int code,
+ const pj_str_t *host,
+ const pj_str_t *text);
+
+/**
+ * Create a warning header and initialize the contents from the error
+ * message for the specified status code. The warning code will be
+ * set to 399.
+ *
+ * @param pool Pool to allocate memory from.
+ * @param host The host portion of the Warning header.
+ * @param status The error status code, which error text will be
+ * put in as the Warning text.
+ *
+ * @return The Warning header field.
+ */
+PJ_DECL(pjsip_warning_hdr*)
+pjsip_warning_hdr_create_from_status( pj_pool_t *pool,
+ const pj_str_t *host,
+ pj_status_t status);
+
+/* **************************************************************************/
+/** Accept-Encoding header. */
+typedef pjsip_generic_string_hdr pjsip_accept_encoding_hdr;
+
+/** Create Accept-Encoding header. */
+#define pjsip_accept_encoding_hdr_create pjsip_generic_string_hdr_create
+
+/** Accept-Language header. */
+typedef pjsip_generic_string_hdr pjsip_accept_lang_hdr;
+
+/** Create Accept-Language header. */
+#define pjsip_accept_lang_hdr_create pjsip_generic_string_hdr_create
+
+/** Alert-Info header. */
+typedef pjsip_generic_string_hdr pjsip_alert_info_hdr;
+
+/** Create Alert-Info header. */
+#define pjsip_alert_info_hdr_create pjsip_generic_string_hdr_create
+
+/** Authentication-Info header. */
+typedef pjsip_generic_string_hdr pjsip_auth_info_hdr;
+
+/** Create Authentication-Info header. */
+#define pjsip_auth_info_hdr_create pjsip_generic_string_hdr_create
+
+/** Call-Info header. */
+typedef pjsip_generic_string_hdr pjsip_call_info_hdr;
+
+/** Create Call-Info header. */
+#define pjsip_call_info_hdr_create pjsip_generic_string_hdr_create
+
+/** Content-Disposition header. */
+typedef pjsip_generic_string_hdr pjsip_content_disposition_hdr;
+
+/** Create Content-Disposition header. */
+#define pjsip_content_disposition_hdr_create pjsip_generic_string_hdr_create
+
+/** Content-Encoding header. */
+typedef pjsip_generic_string_hdr pjsip_content_encoding_hdr;
+
+/** Create Content-Encoding header. */
+#define pjsip_content_encoding_hdr_create pjsip_generic_string_hdr_create
+
+/** Content-Language header. */
+typedef pjsip_generic_string_hdr pjsip_content_lang_hdr;
+
+/** Create Content-Language header. */
+#define pjsip_content_lang_hdr_create pjsip_generic_string_hdr_create
+
+/** Date header. */
+typedef pjsip_generic_string_hdr pjsip_date_hdr;
+
+/** Create Date header. */
+#define pjsip_date_hdr_create pjsip_generic_string_hdr_create
+
+/** Error-Info header. */
+typedef pjsip_generic_string_hdr pjsip_err_info_hdr;
+
+/** Create Error-Info header. */
+#define pjsip_err_info_hdr_create pjsip_generic_string_hdr_create
+
+/** In-Reply-To header. */
+typedef pjsip_generic_string_hdr pjsip_in_reply_to_hdr;
+
+/** Create In-Reply-To header. */
+#define pjsip_in_reply_to_hdr_create pjsip_generic_string_hdr_create
+
+/** MIME-Version header. */
+typedef pjsip_generic_string_hdr pjsip_mime_version_hdr;
+
+/** Create MIME-Version header. */
+#define pjsip_mime_version_hdr_create pjsip_generic_string_hdr_create
+
+/** Organization header. */
+typedef pjsip_generic_string_hdr pjsip_organization_hdr;
+
+/** Create Organization header. */
+#define pjsip_organization_hdr_create pjsip_genric_string_hdr_create
+
+/** Priority header. */
+typedef pjsip_generic_string_hdr pjsip_priority_hdr;
+
+/** Create Priority header. */
+#define pjsip_priority_hdr_create pjsip_generic_string_hdr_create
+
+/** Proxy-Require header. */
+typedef pjsip_generic_string_hdr pjsip_proxy_require_hdr;
+
+/** Reply-To header. */
+typedef pjsip_generic_string_hdr pjsip_reply_to_hdr;
+
+/** Create Reply-To header. */
+#define pjsip_reply_to_hdr_create pjsip_generic_string_hdr_create
+
+/** Server header. */
+typedef pjsip_generic_string_hdr pjsip_server_hdr;
+
+/** Create Server header. */
+#define pjsip_server_hdr_create pjsip_generic_string_hdr_create
+
+/** Subject header. */
+typedef pjsip_generic_string_hdr pjsip_subject_hdr;
+
+/** Create Subject header. */
+#define pjsip_subject_hdr_create pjsip_generic_string_hdr_create
+
+/** Timestamp header. */
+typedef pjsip_generic_string_hdr pjsip_timestamp_hdr;
+
+/** Create Timestamp header. */
+#define pjsip_timestamp_hdr_create pjsip_generic_string_hdr_create
+
+/** User-Agent header. */
+typedef pjsip_generic_string_hdr pjsip_user_agent_hdr;
+
+/** Create User-Agent header. */
+#define pjsip_user_agent_hdr_create pjsip_generic_string_hdr_create
+
+
+/**
+ * @}
+ */
+
+/**
+ * @} PJSIP_MSG
+ */
+
+
+PJ_END_DECL
+
+#endif /* __PJSIP_SIP_MSG_H__ */
+
diff --git a/pjsip/include/pjsip/sip_multipart.h b/pjsip/include/pjsip/sip_multipart.h
new file mode 100644
index 0000000..be8ae26
--- /dev/null
+++ b/pjsip/include/pjsip/sip_multipart.h
@@ -0,0 +1,179 @@
+/* $Id: sip_multipart.h 3553 2011-05-05 06:14:19Z nanang $ */
+/*
+ * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
+ *
+ * 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_MULTIPART_H__
+#define __PJSIP_SIP_MULTIPART_H__
+
+/**
+ * @file pjsip/sip_multipart.h
+ * @brief Multipart support.
+ */
+
+#include <pjsip/sip_msg.h>
+
+PJ_BEGIN_DECL
+
+/**
+ * @defgroup PJSIP_MULTIPART Multipart message bodies.
+ * @ingroup PJSIP_MSG
+ * @brief Support for multipart message bodies.
+ * @{
+ */
+
+/**
+ * This structure describes the individual body part inside a multipart
+ * message body. It mainly contains the message body itself and optional
+ * headers.
+ */
+typedef struct pjsip_multipart_part
+{
+ /**
+ * Standard list element.
+ */
+ PJ_DECL_LIST_MEMBER(struct pjsip_multipart_part);
+
+ /**
+ * Optional message headers.
+ */
+ pjsip_hdr hdr;
+
+ /**
+ * Pointer to the message body.
+ */
+ pjsip_msg_body *body;
+
+} pjsip_multipart_part;
+
+/**
+ * Create an empty multipart body.
+ *
+ * @param pool Memory pool to allocate memory from.
+ * @param ctype Optional MIME media type of the multipart
+ * bodies. If not specified, "multipart/mixed"
+ * will be used.
+ * @param boundary Optional string to be set as part boundary.
+ * The boundary string excludes the leading
+ * hyphens. If this parameter is NULL or empty,
+ * a random boundary will be generated.
+ *
+ * @return Multipart body instance with no part.
+ */
+PJ_DECL(pjsip_msg_body*) pjsip_multipart_create(pj_pool_t *pool,
+ const pjsip_media_type *ctype,
+ const pj_str_t *boundary);
+
+/**
+ * Create an empty multipart part.
+ *
+ * @param pool The memory pool.
+ *
+ * @return The multipart part.
+ */
+PJ_DECL(pjsip_multipart_part*) pjsip_multipart_create_part(pj_pool_t *pool);
+
+
+/**
+ * Perform a deep clone to a multipart part.
+ *
+ * @param pool The memory pool.
+ * @param part The part to be duplicated.
+ *
+ * @return Copy of the multipart part.
+ */
+PJ_DECL(pjsip_multipart_part*)
+pjsip_multipart_clone_part(pj_pool_t *pool,
+ const pjsip_multipart_part *part);
+
+/**
+ * Add a part into multipart bodies.
+ *
+ * @param pool The memory pool.
+ * @param mp The multipart bodies.
+ * @param part The part to be added into the bodies.
+ *
+ * @return PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjsip_multipart_add_part(pj_pool_t *pool,
+ pjsip_msg_body *mp,
+ pjsip_multipart_part *part);
+
+/**
+ * Get the first part of multipart bodies.
+ *
+ * @param mp The multipart bodies.
+ *
+ * @return The first part, or NULL if the multipart
+ * bodies currently doesn't hold any elements.
+ */
+PJ_DECL(pjsip_multipart_part*)
+pjsip_multipart_get_first_part(const pjsip_msg_body *mp);
+
+/**
+ * Get the next part after the specified part.
+ *
+ * @param mp The multipart bodies.
+ * @param part The part.
+ *
+ * @return The next part, or NULL if there is no other part after
+ * the part.
+ */
+PJ_DECL(pjsip_multipart_part*)
+pjsip_multipart_get_next_part(const pjsip_msg_body *mp,
+ pjsip_multipart_part *part);
+
+/**
+ * Find a body inside multipart bodies which has the specified content type.
+ *
+ * @param mp The multipart body.
+ * @param content_type Content type to find.
+ * @param start If specified, the search will begin at
+ * start->next. Otherwise it will begin at
+ * the first part in the multipart bodies.
+ *
+ * @return The first part with the specified content type
+ * if found, or NULL.
+ */
+PJ_DECL(pjsip_multipart_part*)
+pjsip_multipart_find_part( const pjsip_msg_body *mp,
+ const pjsip_media_type *content_type,
+ const pjsip_multipart_part *start);
+
+/**
+ * Parse multipart message.
+ *
+ * @param pool Memory pool.
+ * @param buf Input buffer.
+ * @param len The buffer length.
+ * @param ctype Content type of the multipart body.
+ * @param options Parsing options, must be zero for now.
+ *
+ * @return Multipart message body.
+ */
+PJ_DECL(pjsip_msg_body*) pjsip_multipart_parse(pj_pool_t *pool,
+ char *buf, pj_size_t len,
+ const pjsip_media_type *ctype,
+ unsigned options);
+
+/**
+ * @} PJSIP_MULTIPART
+ */
+
+
+PJ_END_DECL
+
+#endif /* __PJSIP_SIP_MULTIPART_H__ */
diff --git a/pjsip/include/pjsip/sip_parser.h b/pjsip/include/pjsip/sip_parser.h
new file mode 100644
index 0000000..bc341d0
--- /dev/null
+++ b/pjsip/include/pjsip/sip_parser.h
@@ -0,0 +1,416 @@
+/* $Id: sip_parser.h 3553 2011-05-05 06:14:19Z nanang $ */
+/*
+ * 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_PARSER_H__
+#define __PJSIP_SIP_PARSER_H__
+
+/**
+ * @file sip_parser.h
+ * @brief SIP Message Parser
+ */
+
+#include <pjsip/sip_msg.h>
+#include <pjlib-util/scanner.h>
+#include <pj/list.h>
+
+PJ_BEGIN_DECL
+
+/**
+ * @defgroup PJSIP_PARSER Parser
+ * @ingroup PJSIP_MSG
+ * @brief Message and message elements parsing.
+ * @{
+ */
+
+/**
+ * URI Parsing options.
+ */
+enum
+{
+ /** If this option is specified, function #pjsip_parse_uri will return
+ * the URI object as pjsip_name_addr instead of the corresponding
+ * URI object.
+ */
+ PJSIP_PARSE_URI_AS_NAMEADDR = 1,
+
+ /** If this option is specified, function #pjsip_parse_uri and other
+ * internal functions that this function calls will parse URI according
+ * to convention for parsing From/To/Contact header. For example, when
+ * the URI is not enclosed in brackets ("<" and ">"), all parameters
+ * are treated as header parameters (not URI parameters).
+ */
+ PJSIP_PARSE_URI_IN_FROM_TO_HDR = 2
+};
+
+/**
+ * Parser syntax error exception value.
+ */
+extern int PJSIP_SYN_ERR_EXCEPTION;
+
+/**
+ * This structure is used to get error reporting from parser.
+ */
+typedef struct pjsip_parser_err_report
+{
+ /** Standard header fields. */
+ PJ_DECL_LIST_MEMBER(struct pjsip_parser_err_report);
+ int except_code; /**< Error exception (e.g. PJSIP_SYN_ERR_EXCEPTION) */
+ int line; /**< Line number. */
+ int col; /**< Column number. */
+ pj_str_t hname; /**< Header name, if any. */
+} pjsip_parser_err_report;
+
+
+/**
+ * Parsing context, the default argument for parsing functions.
+ */
+typedef struct pjsip_parse_ctx
+{
+ pj_scanner *scanner; /**< The scanner. */
+ pj_pool_t *pool; /**< The pool. */
+ pjsip_rx_data *rdata; /**< Optional rdata. */
+} pjsip_parse_ctx;
+
+
+/**
+ * Type of function to parse header. The parsing function must follow these
+ * specification:
+ * - It must not modify the input text.
+ * - The hname and HCOLON has been parsed prior to invoking the handler.
+ * - It returns the header instance on success.
+ * - For error reporting, it must throw PJSIP_SYN_ERR_EXCEPTION exception
+ * instead of just returning NULL.
+ * When exception is thrown, the return value is ignored.
+ * - It must read the header separator after finished reading the header
+ * body. The separator types are described below, and if they don't exist,
+ * exception must be thrown. Header separator can be a:
+ * - newline, such as when the header is part of a SIP message.
+ * - ampersand, such as when the header is part of an URI.
+ * - for the last header, these separator is optional since parsing
+ * can be terminated when seeing EOF.
+ */
+typedef pjsip_hdr* (pjsip_parse_hdr_func)(pjsip_parse_ctx *context);
+
+/**
+ * Type of function to parse URI scheme.
+ * Most of the specification of header parser handler (pjsip_parse_hdr_func)
+ * also applies here (except the separator part).
+ */
+typedef void* (pjsip_parse_uri_func)(pj_scanner *scanner, pj_pool_t *pool,
+ pj_bool_t parse_params);
+
+/**
+ * Register header parser handler. The parser handler MUST follow the
+ * specification of header parser handler function. New registration
+ * overwrites previous registration with the same name.
+ *
+ * @param hname The header name.
+ * @param hshortname The short header name or NULL.
+ * @param fptr The pointer to function to parser the header.
+ *
+ * @return PJ_SUCCESS if success, or the appropriate error code.
+ */
+PJ_DECL(pj_status_t) pjsip_register_hdr_parser( const char *hname,
+ const char *hshortname,
+ pjsip_parse_hdr_func *fptr);
+
+/**
+ * Unregister previously registered header parser handler.
+ * All the arguments MUST exactly equal to the value specified upon
+ * registration of the handler.
+ *
+ * @param hname The header name registered.
+ * @param hshortname The short header name registered, or NULL.
+ * @param fptr Previously registered function to parse the header.
+ *
+ * @return zero if unregistration was successfull.
+ */
+PJ_DECL(pj_status_t) pjsip_unregister_hdr_parser( const char *hname,
+ const char *hshortname,
+ pjsip_parse_hdr_func *fptr);
+
+/**
+ * Register URI scheme parser handler.
+ *
+ * @param scheme The URI scheme registered.
+ * @param func The URI parser function.
+ *
+ * @return zero on success.
+ */
+PJ_DECL(pj_status_t) pjsip_register_uri_parser( char *scheme,
+ pjsip_parse_uri_func *func);
+
+/**
+ * Unregister URI scheme parser handler.
+ * All the arguments MUST exactly equal to the value specified upon
+ * registration of the handler.
+ *
+ * @param scheme The URI scheme as registered previously.
+ * @param func The function handler as registered previously.
+ *
+ * @return zero if the registration was successfull.
+ */
+PJ_DECL(pj_status_t) pjsip_unregister_uri_parser( const char *scheme,
+ pjsip_parse_uri_func *func);
+
+/**
+ * Parse an URI in the input and return the correct instance of URI.
+ *
+ * @param pool The pool to get memory allocations.
+ * @param buf The input buffer, which MUST be NULL terminated.
+ * @param size The length of the string (not counting NULL terminator).
+ * @param options If no options are given (value is zero), the object
+ * returned is dependent on the syntax of the URI,
+ * eg. basic SIP URL, TEL URL, or name address.
+ * If option PJSIP_PARSE_URI_AS_NAMEADDR is given,
+ * then the returned object is always name address object,
+ * with the relevant URI object contained in the name
+ * address object.
+ * @return The URI or NULL when failed. No exception is thrown by
+ * this function (or any public parser functions).
+ */
+PJ_DECL(pjsip_uri*) pjsip_parse_uri( pj_pool_t *pool,
+ char *buf, pj_size_t size,
+ unsigned options);
+
+/**
+ * Parse SIP status line.
+ *
+ * @param buf Text buffer to parse, which MUST be NULL terminated.
+ * @param size The size of the buffer, excluding the NULL character.
+ * @param status_line Structure to receive the parsed elements.
+ *
+ * @return PJ_SUCCESS if a status line is parsed successfully.
+ */
+PJ_DECL(pj_status_t) pjsip_parse_status_line(char *buf, pj_size_t size,
+ pjsip_status_line *status_line);
+
+
+/**
+ * Parse a packet buffer and build a full SIP message from the packet. This
+ * function parses all parts of the message, including request/status line,
+ * all headers, and the message body. The message body however is only
+ * treated as a text block, ie. the function will not try to parse the content
+ * of the body.
+ *
+ * @param pool The pool to allocate memory.
+ * @param buf The input buffer, which MUST be NULL terminated.
+ * @param size The length of the string (not counting NULL terminator).
+ * @param err_list If this parameter is not NULL, then the parser will
+ * put error messages during parsing in this list.
+ *
+ * @return The message or NULL when failed. No exception is thrown
+ * by this function (or any public parser functions).
+ */
+PJ_DECL(pjsip_msg *) pjsip_parse_msg( pj_pool_t *pool,
+ char *buf, pj_size_t size,
+ pjsip_parser_err_report *err_list);
+
+
+/**
+ * Parse a packet buffer and build a rdata. The resulting message will be
+ * stored in \c msg field in the \c rdata. This behaves pretty much like
+ * #pjsip_parse_msg(), except that it will also initialize the header fields
+ * in the \c rdata.
+ *
+ * This function is normally called by the transport layer.
+ *
+ * @param buf The input buffer, which MUST be NULL terminated.
+ * @param size The length of the string (not counting NULL terminator).
+ * @param rdata The receive data buffer to store the message and
+ * its elements.
+ *
+ * @return The message inside the rdata if successfull, or NULL.
+ */
+PJ_DECL(pjsip_msg *) pjsip_parse_rdata( char *buf, pj_size_t size,
+ pjsip_rx_data *rdata );
+
+/**
+ * Check incoming packet to see if a (probably) valid SIP message has been
+ * received.
+ *
+ * @param buf The input buffer, which must be NULL terminated.
+ * @param size The buffer size.
+ * @param is_datagram Put non-zero if transport is datagram oriented.
+ * @param msg_size [out] If message is valid, this parameter will contain
+ * the size of the SIP message (including body, if any).
+ *
+ * @return PJ_SUCCESS if a message is found, or an error code.
+ */
+PJ_DECL(pj_status_t) pjsip_find_msg(const char *buf,
+ pj_size_t size,
+ pj_bool_t is_datagram,
+ pj_size_t *msg_size);
+
+/**
+ * Parse the content of a header and return the header instance.
+ * This function parses the content of a header (ie. part after colon) according
+ * to the expected name, and will return the correct instance of header.
+ *
+ * @param pool Pool to allocate memory for the header.
+ * @param hname Header name which is used to find the correct function
+ * to parse the header.
+ * @param line Header content, which must be NULL terminated.
+ * @param size The length of the string (not counting NULL terminator,
+ * if any).
+ * @param parsed_len If the value is not NULL, then upon return the function
+ * will fill the pointer with the length of the string
+ * that has been parsed. This is usefull for two purposes,
+ * one is when the string may contain more than one header
+ * lines, and two when an error happen the value can
+ * pinpoint the location of the error in the buffer.
+ *
+ * @return The instance of the header if parsing was successful,
+ * or otherwise a NULL pointer will be returned.
+ */
+PJ_DECL(void*) pjsip_parse_hdr( pj_pool_t *pool, const pj_str_t *hname,
+ char *line, pj_size_t size,
+ int *parsed_len);
+
+/**
+ * Parse header line(s). Multiple headers can be parsed by this function.
+ * When there are multiple headers, the headers MUST be separated by either
+ * a newline (as in SIP message) or ampersand mark (as in URI). This separator
+ * is optional for the last header.
+ *
+ * @param pool The pool.
+ * @param input The input text to parse, which must be NULL terminated.
+ * @param size The text length.
+ * @param hlist The header list to store the parsed headers.
+ * This list must have been initialized before calling
+ * this function.
+ * @param options Specify 1 here to make parsing stop when error is
+ * encountered when parsing the header. Otherwise the
+ * error is silently ignored and parsing resumes to the
+ * next line.
+ * @return zero if successfull, or -1 if error is encountered.
+ * Upon error, the \a hlist argument MAY contain
+ * successfully parsed headers.
+ */
+PJ_DECL(pj_status_t) pjsip_parse_headers( pj_pool_t *pool, char *input,
+ pj_size_t size, pjsip_hdr *hlist,
+ unsigned options);
+
+
+/**
+ * @}
+ */
+
+
+#ifdef _MSC_VER
+# pragma warning(push)
+# pragma warning(disable:4510) // default constructor could not be generated
+# pragma warning(disable:4512) // assignment operator could not be generated
+# pragma warning(disable:4610) // user defined constructor required
+#endif
+
+/**
+ * Parser constants. @see pjsip_parser_const()
+ */
+typedef struct pjsip_parser_const_t
+{
+ const pj_str_t pjsip_USER_STR; /**< "user" string constant. */
+ const pj_str_t pjsip_METHOD_STR; /**< "method" string constant */
+ const pj_str_t pjsip_TRANSPORT_STR; /**< "transport" string const. */
+ const pj_str_t pjsip_MADDR_STR; /**< "maddr" string const. */
+ const pj_str_t pjsip_LR_STR; /**< "lr" string const. */
+ const pj_str_t pjsip_SIP_STR; /**< "sip" string constant. */
+ const pj_str_t pjsip_SIPS_STR; /**< "sips" string constant. */
+ const pj_str_t pjsip_TEL_STR; /**< "tel" string constant. */
+ const pj_str_t pjsip_BRANCH_STR; /**< "branch" string constant. */
+ const pj_str_t pjsip_TTL_STR; /**< "ttl" string constant. */
+ const pj_str_t pjsip_RECEIVED_STR; /**< "received" string const. */
+ const pj_str_t pjsip_Q_STR; /**< "q" string constant. */
+ const pj_str_t pjsip_EXPIRES_STR; /**< "expires" string constant. */
+ const pj_str_t pjsip_TAG_STR; /**< "tag" string constant. */
+ const pj_str_t pjsip_RPORT_STR; /**< "rport" string const. */
+
+ pj_cis_t pjsip_HOST_SPEC; /**< For scanning host part. */
+ pj_cis_t pjsip_DIGIT_SPEC; /**< Decimal digits */
+ pj_cis_t pjsip_ALPHA_SPEC; /**< Alpha (A-Z, a-z) */
+ pj_cis_t pjsip_ALNUM_SPEC; /**< Decimal + Alpha. */
+ pj_cis_t pjsip_TOKEN_SPEC; /**< Token. */
+ pj_cis_t pjsip_TOKEN_SPEC_ESC; /**< Token without '%' character */
+ pj_cis_t pjsip_VIA_PARAM_SPEC; /**< Via param is token + ":" for
+ IPv6. */
+ pj_cis_t pjsip_VIA_PARAM_SPEC_ESC; /**< .. as above without '%' */
+ pj_cis_t pjsip_HEX_SPEC; /**< Hexadecimal digits. */
+ pj_cis_t pjsip_PARAM_CHAR_SPEC; /**< For scanning pname (or pvalue
+ when it's not quoted.) in URI */
+ pj_cis_t pjsip_PARAM_CHAR_SPEC_ESC; /**< Variant without the escape ('%')
+ char */
+ pj_cis_t pjsip_HDR_CHAR_SPEC; /**< Chars in hname/havalue in URL. */
+ pj_cis_t pjsip_HDR_CHAR_SPEC_ESC; /**< Variant without the escape ('%')
+ char */
+ pj_cis_t pjsip_PROBE_USER_HOST_SPEC;/**< Hostname characters. */
+ pj_cis_t pjsip_PASSWD_SPEC; /**< Password. */
+ pj_cis_t pjsip_PASSWD_SPEC_ESC; /**< Variant without the escape ('%')
+ char */
+ pj_cis_t pjsip_USER_SPEC; /**< User */
+ pj_cis_t pjsip_USER_SPEC_ESC; /**< Variant without the escape ('%')
+ char */
+ pj_cis_t pjsip_USER_SPEC_LENIENT; /**< User, with additional '#' char */
+ pj_cis_t pjsip_USER_SPEC_LENIENT_ESC;/**< pjsip_USER_SPEC_ESC with '#' */
+ pj_cis_t pjsip_NOT_NEWLINE; /**< For eating up header, basically
+ any chars except newlines or
+ zero. */
+ pj_cis_t pjsip_NOT_COMMA_OR_NEWLINE;/**< Array elements. */
+ pj_cis_t pjsip_DISPLAY_SPEC; /**< Used when searching for display
+ name. */
+ pj_cis_t pjsip_OTHER_URI_CONTENT; /**< Generic URI content. */
+
+} pjsip_parser_const_t;
+
+#ifdef _MSC_VER
+# pragma warning(pop)
+#endif
+
+
+/**
+ * Get parser constants.
+ */
+PJ_DECL(const pjsip_parser_const_t*) pjsip_parser_const(void);
+
+
+/*
+ * Parser utilities.
+ */
+enum
+{
+ PJSIP_PARSE_REMOVE_QUOTE = 1
+};
+
+/* Parse parameter in header (matching the character as token) */
+PJ_DECL(void) pjsip_parse_param_imp(pj_scanner *scanner, pj_pool_t *pool,
+ pj_str_t *pname, pj_str_t *pvalue,
+ unsigned opt);
+/* Parse parameter in URL (matching the character as paramchar) */
+PJ_DECL(void) pjsip_parse_uri_param_imp(pj_scanner *scanner, pj_pool_t *pool,
+ pj_str_t *pname, pj_str_t *pvalue,
+ unsigned opt);
+PJ_DECL(void) pjsip_concat_param_imp(pj_str_t *param, pj_pool_t *pool,
+ const pj_str_t *pname,
+ const pj_str_t *pvalue,
+ int sepchar);
+PJ_DECL(void) pjsip_parse_end_hdr_imp ( pj_scanner *scanner );
+
+PJ_END_DECL
+
+#endif /* __PJSIP_SIP_PARSER_H__ */
+
diff --git a/pjsip/include/pjsip/sip_private.h b/pjsip/include/pjsip/sip_private.h
new file mode 100644
index 0000000..e139fa6
--- /dev/null
+++ b/pjsip/include/pjsip/sip_private.h
@@ -0,0 +1,32 @@
+/* $Id: sip_private.h 3553 2011-05-05 06:14:19Z nanang $ */
+/*
+ * 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_PRIVATE_H__
+#define __PJSIP_SIP_PRIVATE_H__
+
+/**
+ * @file sip_private.h
+ * @brief Private structures and functions for PJSIP Library.
+ */
+
+#include <pjsip/sip_types.h>
+
+
+#endif /* __PJSIP_PRIVATE_I_H__ */
+
diff --git a/pjsip/include/pjsip/sip_resolve.h b/pjsip/include/pjsip/sip_resolve.h
new file mode 100644
index 0000000..6f578a1
--- /dev/null
+++ b/pjsip/include/pjsip/sip_resolve.h
@@ -0,0 +1,291 @@
+/* $Id: sip_resolve.h 3553 2011-05-05 06:14:19Z nanang $ */
+/*
+ * 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_RESOLVE_H__
+#define __PJSIP_SIP_RESOLVE_H__
+
+/**
+ * @file sip_resolve.h
+ * @brief
+ * This module contains the mechanism to resolve server address as specified by
+ * RFC 3263 - Locating SIP Servers
+ */
+
+#include <pjsip/sip_types.h>
+#include <pjlib-util/resolver.h>
+#include <pj/sock.h>
+
+PJ_BEGIN_DECL
+
+/**
+ * @defgroup PJSIP_RESOLVE SIP SRV Server Resolution (RFC 3263 - Locating SIP Servers)
+ * @ingroup PJSIP_TRANSPORT
+ * @brief Framework to resolve SIP servers based on RFC 3263.
+ * @{
+ * \section PJSIP_RESOLVE_FEATURES Features
+ *
+ * This is the SIP server resolution framework, which is modelled after
+ * RFC 3263 - Locating SIP Servers document. The SIP server resolution
+ * framework is asynchronous; callback will be called once the server
+ * address has been resolved (successfully or with errors).
+ *
+ * \subsection PJSIP_RESOLVE_CONFORMANT Conformance to RFC 3263
+ *
+ * The SIP server resolution framework is modelled after RFC 3263 (Locating
+ * SIP Servers) document, and it provides a single function (#pjsip_resolve())
+ * to resolve a domain into actual IP addresses of the servers, by querying
+ * DNS SRV record and DNS A record where necessary.
+ *
+ * The #pjsip_resolve() function performs the server resolution according
+ * to RFC 3263 with some additional fallback mechanisms, as follows:
+ * - if the target name is an IP address, the callback will be called
+ * immediately with the IP address. If port number was specified, this
+ * port number will be used, otherwise the default port number for the
+ * transport will be used (5060 for TCP/UDP, 5061 for TLS) if the transport
+ * is specified. If the transport is not specified, UDP with port number
+ * 5060 will be used.
+ * - if target name is not an IP address but it contains port number,
+ * then the target name is resolved with DNS A (or AAAA, when IPv6 is
+ * supported in the future) query, and the port is taken from the
+ * port number argument. The callback will be called once the DNS A
+ * resolution completes. If the DNS A resolution returns multiple IP
+ * addresses, these IP addresses will be returned to the caller.
+ * - if target name is not an IP address and port number is not specified,
+ * DNS SRV resolution will be performed for the specified name and
+ * transport type (or UDP when transport is not specified),
+ * then followed by DNS A (or AAAA, when IPv6 is supported)
+ * resolution for each target in the SRV record. If DNS SRV
+ * resolution returns error, DNS A (or AAAA) resolution will be
+ * performed for the original target (it is assumed that the target domain
+ * does not support SRV records). Upon successful completion,
+ * application callback will be called with each IP address of the
+ * target selected based on the load-balancing and fail-over criteria
+ * below.
+ *
+ * The above server resolution procedure differs from RFC 3263 in these
+ * regards:
+ * - currently #pjsip_resolve() doesn't support DNS NAPTR record.
+ * - if transport is not specified, it is assumed to be UDP (the proper
+ * behavior is to query the NAPTR record, but we don't support this
+ * yet).
+ *
+ *
+ * \subsection PJSIP_SIP_RESOLVE_FAILOVER_LOADBALANCE Load-Balancing and Fail-Over
+ *
+ * When multiple targets are returned in the DNS SRV response, server entries
+ * are selected based on the following rule (which is described in RFC 2782):
+ * - targets will be sorted based on the priority first.
+ * - for targets with the same priority, #pjsip_resolve() will select
+ * only one target according to its weight. To select this one target,
+ * the function associates running-sum for all targets, and generates
+ * a random number between zero and the total running-sum (inclusive).
+ * The target selected is the first target with running-sum greater than
+ * or equal to this random number.
+ *
+ * The above procedure will select one target for each priority, allowing
+ * application to fail-over to the next target when the previous target fails.
+ * These targets are returned in the #pjsip_server_addresses structure
+ * argument of the callback.
+ *
+ * \subsection PJSIP_SIP_RESOLVE_SIP_FEATURES SIP SRV Resolver Features
+ *
+ * Some features of the SIP resolver:
+ * - DNS SRV entries are returned on sorted order based on priority
+ * to allow failover to the next appropriate server.
+ * - The procedure in RFC 2782 is used to select server with the same
+ * priority to load-balance the servers load.
+ * - A single function (#pjsip_resolve()) performs all server resolution
+ * works, from resolving the SRV records to getting the actual IP addresses
+ * of the servers with DNS A (or AAAA) resolution.
+ * - When multiple DNS SRV records are returned, parallel DNS A (or AAAA)
+ * queries will be issued simultaneously.
+ * - The PJLIB-UTIL DNS resolver provides additional functionality such as
+ * response caching, query aggregation, parallel nameservers, fallback
+ * nameserver, etc., which will be described below.
+ *
+ *
+ * \subsection PJSIP_RESOLVE_DNS_FEATURES DNS Resolver Features
+ *
+ * The PJSIP server resolution framework uses PJLIB-UTIL DNS resolver engine
+ * for performing the asynchronous DNS request. The PJLIB-UTIL DNS resolver
+ * has some useful features, such as:
+ * - queries are asynchronous with configurable timeout,
+ * - query aggregation to combine multiple pending queries to the same
+ * DNS target into a single DNS request (to save message round-trip and
+ * processing),
+ * - response caching with TTL negotiated between the minimum TTL found in
+ * the response and the maximum TTL allowed in the configuration,
+ * - multiple nameservers, with active nameserver is selected from nameserver
+ * which provides the best response time,
+ * - fallback nameserver, with periodic detection of which name servers are
+ * active or down.
+ * - etc.
+ *
+ * Please consult PJLIB-UTIL DNS resolver documentation for more details.
+ *
+ *
+ * \section PJSIP_RESOLVE_USING Using the Resolver
+ *
+ * To maintain backward compatibility, the resolver MUST be enabled manually.
+ * With the default settings, the resolver WILL NOT perform DNS SRV resolution,
+ * as it will just resolve the name with standard pj_gethostbyname() function.
+ *
+ * Application can enable the SRV resolver by creating the PJLIB-UTIL DNS
+ * resolver with #pjsip_endpt_create_resolver(), configure the
+ * nameservers of the PJLIB-UTIL DNS resolver object by calling
+ * pj_dns_resolver_set_ns() function, and pass the DNS resolver object to
+ * #pjsip_resolver_set_resolver() function.
+ *
+ * Once the resolver is set, it will be used automatically by PJSIP everytime
+ * PJSIP needs to send SIP request/response messages.
+ *
+ *
+ * \section PJSIP_RESOLVE_REFERENCE Reference
+ *
+ * Reference:
+ * - RFC 2782: A DNS RR for specifying the location of services (DNS SRV)
+ * - RFC 3263: Locating SIP Servers
+ */
+
+/**
+ * The server addresses returned by the resolver.
+ */
+typedef struct pjsip_server_addresses
+{
+ /** Number of address records. */
+ unsigned count;
+
+ /** Address records. */
+ struct
+ {
+ /** Preferable transport to be used to contact this address. */
+ pjsip_transport_type_e type;
+
+ /** Server priority (the lower the higher the priority). */
+ unsigned priority;
+
+ /** Server weight (the higher the more load it can handle). */
+ unsigned weight;
+
+ /** The server's address. */
+ pj_sockaddr addr;
+
+ /** Address length. */
+ int addr_len;
+
+ } entry[PJSIP_MAX_RESOLVED_ADDRESSES];
+
+} pjsip_server_addresses;
+
+
+/**
+ * The type of callback function to be called when resolver finishes the job.
+ *
+ * @param status The status of the operation, which is zero on success.
+ * @param token The token that was associated with the job when application
+ * call the resolve function.
+ * @param addr The addresses resolved by the operation.
+ */
+typedef void pjsip_resolver_callback(pj_status_t status,
+ void *token,
+ const struct pjsip_server_addresses *addr);
+
+/**
+ * Create SIP resolver engine. Note that this function is normally called
+ * internally by pjsip_endpoint instance.
+ *
+ * @param pool Pool to allocate memory from.
+ * @param p_res Pointer to receive SIP resolver instance.
+ *
+ * @return PJ_SUCCESS when resolver can be successfully created.
+ */
+PJ_DECL(pj_status_t) pjsip_resolver_create(pj_pool_t *pool,
+ pjsip_resolver_t **p_res);
+
+/**
+ * Set the DNS resolver instance of the SIP resolver engine. Before the
+ * DNS resolver is set, the SIP resolver will use standard pj_gethostbyname()
+ * to resolve addresses.
+ *
+ * Note that application normally will use #pjsip_endpt_set_resolver() instead
+ * since it does not normally have access to the SIP resolver instance.
+ *
+ * @param res The SIP resolver engine.
+ * @param dns_res The DNS resolver instance to be used by the SIP resolver.
+ * This argument can be NULL to reset the internal DNS
+ * instance.
+ *
+ * @return PJ_SUCCESS on success, or the appropriate error code.
+ */
+PJ_DECL(pj_status_t) pjsip_resolver_set_resolver(pjsip_resolver_t *res,
+ pj_dns_resolver *dns_res);
+
+
+/**
+ * Get the DNS resolver instance of the SIP resolver engine.
+ *
+ * Note that application normally will use #pjsip_endpt_get_resolver() instead
+ * since it does not normally have access to the SIP resolver instance.
+ *
+ * @param res The SIP resolver engine.
+ *
+ * @return The DNS resolver instance (may be NULL)
+ */
+PJ_DECL(pj_dns_resolver*) pjsip_resolver_get_resolver(pjsip_resolver_t *res);
+
+/**
+ * Destroy resolver engine. Note that this will also destroy the internal
+ * DNS resolver inside the engine. If application doesn't want the internal
+ * DNS resolver to be destroyed, it should set the internal DNS resolver
+ * to NULL before calling this function.
+ *
+ * Note that this function will normally called by the SIP endpoint instance
+ * when the SIP endpoint instance is destroyed.
+ *
+ * @param resolver The resolver.
+ */
+PJ_DECL(void) pjsip_resolver_destroy(pjsip_resolver_t *resolver);
+
+/**
+ * Asynchronously resolve a SIP target host or domain according to rule
+ * specified in RFC 3263 (Locating SIP Servers). When the resolving operation
+ * has completed, the callback will be called.
+ *
+ * Note that application normally will use #pjsip_endpt_resolve() instead
+ * since it does not normally have access to the SIP resolver instance.
+ *
+ * @param resolver The resolver engine.
+ * @param pool The pool to allocate resolver job.
+ * @param target The target specification to be resolved.
+ * @param token A user defined token to be passed back to callback function.
+ * @param cb The callback function.
+ */
+PJ_DECL(void) pjsip_resolve( pjsip_resolver_t *resolver,
+ pj_pool_t *pool,
+ const pjsip_host_info *target,
+ void *token,
+ pjsip_resolver_callback *cb);
+
+/**
+ * @}
+ */
+
+PJ_END_DECL
+
+#endif /* __PJSIP_SIP_RESOLVE_H__ */
diff --git a/pjsip/include/pjsip/sip_tel_uri.h b/pjsip/include/pjsip/sip_tel_uri.h
new file mode 100644
index 0000000..f85ec74
--- /dev/null
+++ b/pjsip/include/pjsip/sip_tel_uri.h
@@ -0,0 +1,84 @@
+/* $Id: sip_tel_uri.h 3553 2011-05-05 06:14:19Z nanang $ */
+/*
+ * 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_TEL_URI_H__
+#define __PJSIP_TEL_URI_H__
+
+/**
+ * @file sip_tel_uri.h
+ * @brief Tel: URI
+ */
+
+#include <pjsip/sip_uri.h>
+
+/**
+ * @addtogroup PJSIP_TEL_URI tel URI Scheme
+ * @ingroup PJSIP_URI
+ * @brief Support for "tel:" URI scheme.
+ * @{
+ */
+
+
+PJ_BEGIN_DECL
+
+/**
+ * tel: URI.
+ */
+typedef struct pjsip_tel_uri
+{
+ pjsip_uri_vptr *vptr; /**< Pointer to virtual function table. */
+ pj_str_t number; /**< Global or local phone number */
+ pj_str_t context; /**< Phone context (for local number). */
+ pj_str_t ext_param; /**< Extension param. */
+ pj_str_t isub_param; /**< ISDN sub-address param. */
+ pjsip_param other_param;/**< Other parameter. */
+} pjsip_tel_uri;
+
+
+/**
+ * Create a new tel: URI.
+ *
+ * @param pool The pool.
+ *
+ * @return New instance of tel: URI.
+ */
+PJ_DECL(pjsip_tel_uri*) pjsip_tel_uri_create(pj_pool_t *pool);
+
+/**
+ * This function compares two numbers for equality, according to rules as
+ * specified in RFC 3966.
+ *
+ * @param nb1 The first number.
+ * @param nb2 The second number.
+ *
+ * @return Zero if equal, -1 if nb1 is less than nb2, or +1 if
+ * nb1 is greater than nb2.
+ */
+PJ_DECL(int) pjsip_tel_nb_cmp(const pj_str_t *nb1, const pj_str_t *nb2);
+
+
+PJ_END_DECL
+
+
+/**
+ * @}
+ */
+
+
+#endif /* __PJSIP_TEL_URI_H__ */
diff --git a/pjsip/include/pjsip/sip_transaction.h b/pjsip/include/pjsip/sip_transaction.h
new file mode 100644
index 0000000..1a75a7c
--- /dev/null
+++ b/pjsip/include/pjsip/sip_transaction.h
@@ -0,0 +1,414 @@
+/* $Id: sip_transaction.h 3553 2011-05-05 06:14:19Z nanang $ */
+/*
+ * 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_mutex_t *mutex; /**< Mutex for this tsx. */
+ 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_uint32_t hashed_key; /**< Key's hashed value. */
+ 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.
+ *
+ * @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 );
+
+/**
+ * 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);
+
+/**
+ * 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 );
+
+
+/**
+ * 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.
+ */
+PJ_DECL(pj_status_t) pjsip_tsx_terminate( 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);
+
+
+/**
+ * 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__ */
+
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__ */
+
diff --git a/pjsip/include/pjsip/sip_transport_loop.h b/pjsip/include/pjsip/sip_transport_loop.h
new file mode 100644
index 0000000..1883a02
--- /dev/null
+++ b/pjsip/include/pjsip/sip_transport_loop.h
@@ -0,0 +1,147 @@
+/* $Id: sip_transport_loop.h 3553 2011-05-05 06:14:19Z nanang $ */
+/*
+ * 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_TRANSPORT_LOOP_H__
+#define __PJSIP_TRANSPORT_LOOP_H__
+
+
+/**
+ * @file sip_transport_loop.h
+ * @brief
+ * Loopback transport (for debugging)
+ */
+
+
+#include <pjsip/sip_transport.h>
+
+/**
+ * @defgroup PJSIP_TRANSPORT_LOOP Loop Transport
+ * @ingroup PJSIP_TRANSPORT
+ * @brief Loopback transport (for testing purposes).
+ * @{
+ * The loopback transport simply bounce back outgoing messages as
+ * incoming messages. This feature is used mostly during automated
+ * testing, to provide controlled behavior.
+ */
+
+PJ_BEGIN_DECL
+
+/**
+ * Create and start datagram loop transport.
+ *
+ * @param endpt The endpoint instance.
+ * @param transport Pointer to receive the transport instance.
+ *
+ * @return PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjsip_loop_start( pjsip_endpoint *endpt,
+ pjsip_transport **transport);
+
+
+/**
+ * Enable/disable flag to discard any packets sent using the specified
+ * loop transport.
+ *
+ * @param tp The loop transport.
+ * @param discard If non-zero, any outgoing packets will be discarded.
+ * @param prev_value Optional argument to receive previous value of
+ * the discard flag.
+ *
+ * @return PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjsip_loop_set_discard( pjsip_transport *tp,
+ pj_bool_t discard,
+ pj_bool_t *prev_value );
+
+
+/**
+ * Enable/disable flag to simulate network error. When this flag is set,
+ * outgoing transmission will return either immediate error or error via
+ * callback. If error is to be notified via callback, then the notification
+ * will occur after some delay, which is controlled by #pjsip_loop_set_delay().
+ *
+ * @param tp The loop transport.
+ * @param fail_flag If set to 1, the transport will return fail to deliver
+ * the message. If delay is zero, failure will occur
+ * immediately; otherwise it will be reported in callback.
+ * If set to zero, the transport will successfully deliver
+ * the packet.
+ * @param prev_value Optional argument to receive previous value of
+ * the failure flag.
+ *
+ * @return PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjsip_loop_set_failure( pjsip_transport *tp,
+ int fail_flag,
+ int *prev_value );
+
+
+/**
+ * Set delay (in miliseconds) before packet is received by the other end
+ * of the loop transport. This will also
+ * control the delay for error notification callback.
+ *
+ * @param tp The loop transport.
+ * @param delay Delay, in miliseconds.
+ * @param prev_value Optional argument to receive previous value of the
+ * delay.
+ *
+ * @return PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjsip_loop_set_recv_delay( pjsip_transport *tp,
+ unsigned delay,
+ unsigned *prev_value);
+
+
+/**
+ * Set delay (in miliseconds) before send notification is delivered to sender.
+ * This will also control the delay for error notification callback.
+ *
+ * @param tp The loop transport.
+ * @param delay Delay, in miliseconds.
+ * @param prev_value Optional argument to receive previous value of the
+ * delay.
+ *
+ * @return PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjsip_loop_set_send_callback_delay( pjsip_transport *tp,
+ unsigned delay,
+ unsigned *prev_value);
+
+
+/**
+ * Set both receive and send notification delay.
+ *
+ * @param tp The loop transport.
+ * @param delay Delay, in miliseconds.
+ *
+ * @return PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjsip_loop_set_delay( pjsip_transport *tp,
+ unsigned delay );
+
+
+PJ_END_DECL
+
+/**
+ * @}
+ */
+
+#endif /* __PJSIP_TRANSPORT_LOOP_H__ */
+
diff --git a/pjsip/include/pjsip/sip_transport_tcp.h b/pjsip/include/pjsip/sip_transport_tcp.h
new file mode 100644
index 0000000..285c6b6
--- /dev/null
+++ b/pjsip/include/pjsip/sip_transport_tcp.h
@@ -0,0 +1,210 @@
+/* $Id: sip_transport_tcp.h 3553 2011-05-05 06:14:19Z nanang $ */
+/*
+ * 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_TRANSPORT_TCP_H__
+#define __PJSIP_TRANSPORT_TCP_H__
+
+/**
+ * @file sip_transport_tcp.h
+ * @brief SIP TCP Transport.
+ */
+
+#include <pjsip/sip_transport.h>
+#include <pj/sock_qos.h>
+
+
+/* Only declare the API if PJ_HAS_TCP is true */
+#if defined(PJ_HAS_TCP) && PJ_HAS_TCP!=0
+
+
+PJ_BEGIN_DECL
+
+/**
+ * @defgroup PJSIP_TRANSPORT_TCP TCP Transport
+ * @ingroup PJSIP_TRANSPORT
+ * @brief API to create and register TCP transport.
+ * @{
+ * The functions below are used to create TCP transport and register
+ * the transport to the framework.
+ */
+
+/**
+ * Settings to be specified when creating the TCP transport. Application
+ * should initialize this structure with its default values by calling
+ * pjsip_tcp_transport_cfg_default().
+ */
+typedef struct pjsip_tcp_transport_cfg
+{
+ /**
+ * Address family to use. Valid values are pj_AF_INET() and
+ * pj_AF_INET6(). Default is pj_AF_INET().
+ */
+ int af;
+
+ /**
+ * Optional address to bind the socket to. Default is to bind to
+ * PJ_INADDR_ANY and to any available port.
+ */
+ pj_sockaddr bind_addr;
+
+ /**
+ * Optional published address, which is the address to be
+ * advertised as the address of this SIP transport.
+ * By default the bound address will be used as the published address.
+ */
+ pjsip_host_port addr_name;
+
+ /**
+ * Number of simultaneous asynchronous accept() operations to be
+ * supported. It is recommended that the number here corresponds to
+ * the number of processors in the system (or the number of SIP
+ * worker threads).
+ *
+ * Default: 1
+ */
+ unsigned async_cnt;
+
+ /**
+ * QoS traffic type to be set on this transport. When application wants
+ * to apply QoS tagging to the transport, it's preferable to set this
+ * field rather than \a qos_param fields since this is more portable.
+ *
+ * Default is QoS not set.
+ */
+ pj_qos_type qos_type;
+
+ /**
+ * Set the low level QoS parameters to the transport. This is a lower
+ * level operation than setting the \a qos_type field and may not be
+ * supported on all platforms.
+ *
+ * Default is QoS not set.
+ */
+ pj_qos_params qos_params;
+
+} pjsip_tcp_transport_cfg;
+
+
+/**
+ * Initialize pjsip_tcp_transport_cfg structure with default values for
+ * the specifed address family.
+ *
+ * @param cfg The structure to initialize.
+ * @param af Address family to be used.
+ */
+PJ_DECL(void) pjsip_tcp_transport_cfg_default(pjsip_tcp_transport_cfg *cfg,
+ int af);
+
+
+/**
+ * Register support for SIP TCP transport by creating TCP listener on
+ * the specified address and port. This function will create an
+ * instance of SIP TCP transport factory and register it to the
+ * transport manager.
+ *
+ * @param endpt The SIP endpoint.
+ * @param local Optional local address to bind, or specify the
+ * address to bind the server socket to. Both IP
+ * interface address and port fields are optional.
+ * If IP interface address is not specified, socket
+ * will be bound to PJ_INADDR_ANY. If port is not
+ * specified, socket will be bound to any port
+ * selected by the operating system.
+ * @param async_cnt Number of simultaneous asynchronous accept()
+ * operations to be supported. It is recommended that
+ * the number here corresponds to the number of
+ * processors in the system (or the number of SIP
+ * worker threads).
+ * @param p_factory Optional pointer to receive the instance of the
+ * SIP TCP transport factory just created.
+ *
+ * @return PJ_SUCCESS when the transport has been successfully
+ * started and registered to transport manager, or
+ * the appropriate error code.
+ */
+PJ_DECL(pj_status_t) pjsip_tcp_transport_start(pjsip_endpoint *endpt,
+ const pj_sockaddr_in *local,
+ unsigned async_cnt,
+ pjsip_tpfactory **p_factory);
+
+
+
+/**
+ * A newer variant of #pjsip_tcp_transport_start(), which allows specifying
+ * the published/public address of the TCP transport.
+ *
+ * @param endpt The SIP endpoint.
+ * @param local Optional local address to bind, or specify the
+ * address to bind the server socket to. Both IP
+ * interface address and port fields are optional.
+ * If IP interface address is not specified, socket
+ * will be bound to PJ_INADDR_ANY. If port is not
+ * specified, socket will be bound to any port
+ * selected by the operating system.
+ * @param a_name Optional published address, which is the address to be
+ * advertised as the address of this SIP transport.
+ * If this argument is NULL, then the bound address
+ * will be used as the published address.
+ * @param async_cnt Number of simultaneous asynchronous accept()
+ * operations to be supported. It is recommended that
+ * the number here corresponds to the number of
+ * processors in the system (or the number of SIP
+ * worker threads).
+ * @param p_factory Optional pointer to receive the instance of the
+ * SIP TCP transport factory just created.
+ *
+ * @return PJ_SUCCESS when the transport has been successfully
+ * started and registered to transport manager, or
+ * the appropriate error code.
+ */
+PJ_DECL(pj_status_t) pjsip_tcp_transport_start2(pjsip_endpoint *endpt,
+ const pj_sockaddr_in *local,
+ const pjsip_host_port *a_name,
+ unsigned async_cnt,
+ pjsip_tpfactory **p_factory);
+
+/**
+ * Another variant of #pjsip_tcp_transport_start().
+ *
+ * @param endpt The SIP endpoint.
+ * @param cfg TCP transport settings. Application should initialize
+ * this setting with #pjsip_tcp_transport_cfg_default().
+ * @param p_factory Optional pointer to receive the instance of the
+ * SIP TCP transport factory just created.
+ *
+ * @return PJ_SUCCESS when the transport has been successfully
+ * started and registered to transport manager, or
+ * the appropriate error code.
+ */
+PJ_DECL(pj_status_t) pjsip_tcp_transport_start3(
+ pjsip_endpoint *endpt,
+ const pjsip_tcp_transport_cfg *cfg,
+ pjsip_tpfactory **p_factory
+ );
+
+
+PJ_END_DECL
+
+/**
+ * @}
+ */
+
+#endif /* PJ_HAS_TCP */
+
+#endif /* __PJSIP_TRANSPORT_TCP_H__ */
diff --git a/pjsip/include/pjsip/sip_transport_tls.h b/pjsip/include/pjsip/sip_transport_tls.h
new file mode 100644
index 0000000..cbc1d75
--- /dev/null
+++ b/pjsip/include/pjsip/sip_transport_tls.h
@@ -0,0 +1,305 @@
+/* $Id: sip_transport_tls.h 3999 2012-03-30 07:10:13Z bennylp $ */
+/*
+ * 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_TRANSPORT_TLS_H__
+#define __PJSIP_TRANSPORT_TLS_H__
+
+/**
+ * @file sip_transport_tls.h
+ * @brief SIP TLS Transport.
+ */
+
+#include <pjsip/sip_transport.h>
+#include <pj/pool.h>
+#include <pj/ssl_sock.h>
+#include <pj/string.h>
+#include <pj/sock_qos.h>
+
+
+PJ_BEGIN_DECL
+
+/**
+ * @defgroup PJSIP_TRANSPORT_TLS TLS Transport
+ * @ingroup PJSIP_TRANSPORT
+ * @brief API to create and register TLS transport.
+ * @{
+ * The functions below are used to create TLS transport and register
+ * the transport to the framework.
+ */
+
+/**
+ * The default SSL method to be used by PJSIP.
+ * Default is PJSIP_TLSV1_METHOD
+ */
+#ifndef PJSIP_SSL_DEFAULT_METHOD
+# define PJSIP_SSL_DEFAULT_METHOD PJSIP_TLSV1_METHOD
+#endif
+
+/** SSL protocol method constants. */
+typedef enum pjsip_ssl_method
+{
+ PJSIP_SSL_UNSPECIFIED_METHOD= 0, /**< Default protocol method. */
+ PJSIP_TLSV1_METHOD = 31, /**< Use SSLv1 method. */
+ PJSIP_SSLV2_METHOD = 20, /**< Use SSLv2 method. */
+ PJSIP_SSLV3_METHOD = 30, /**< Use SSLv3 method. */
+ PJSIP_SSLV23_METHOD = 23 /**< Use SSLv23 method. */
+} pjsip_ssl_method;
+
+
+
+
+/**
+ * TLS transport settings.
+ */
+typedef struct pjsip_tls_setting
+{
+ /**
+ * Certificate of Authority (CA) list file.
+ */
+ pj_str_t ca_list_file;
+
+ /**
+ * Public endpoint certificate file, which will be used as client-
+ * side certificate for outgoing TLS connection, and server-side
+ * certificate for incoming TLS connection.
+ */
+ pj_str_t cert_file;
+
+ /**
+ * Optional private key of the endpoint certificate to be used.
+ */
+ pj_str_t privkey_file;
+
+ /**
+ * Password to open private key.
+ */
+ pj_str_t password;
+
+ /**
+ * TLS protocol method from #pjsip_ssl_method, which can be:
+ * - PJSIP_SSL_UNSPECIFIED_METHOD(0): default (which will use
+ * PJSIP_SSL_DEFAULT_METHOD)
+ * - PJSIP_TLSV1_METHOD(1): TLSv1
+ * - PJSIP_SSLV2_METHOD(2): SSLv2
+ * - PJSIP_SSLV3_METHOD(3): SSL3
+ * - PJSIP_SSLV23_METHOD(23): SSL23
+ *
+ * Default is PJSIP_SSL_UNSPECIFIED_METHOD (0), which in turn will
+ * use PJSIP_SSL_DEFAULT_METHOD, which default value is
+ * PJSIP_TLSV1_METHOD.
+ */
+ int method;
+
+ /**
+ * Number of ciphers contained in the specified cipher preference.
+ * If this is set to zero, then default cipher list of the backend
+ * will be used.
+ *
+ * Default: 0 (zero).
+ */
+ unsigned ciphers_num;
+
+ /**
+ * Ciphers and order preference. The #pj_ssl_cipher_get_availables()
+ * can be used to check the available ciphers supported by backend.
+ */
+ pj_ssl_cipher *ciphers;
+
+ /**
+ * Specifies TLS transport behavior on the server TLS certificate
+ * verification result:
+ * - If \a verify_server is disabled (set to PJ_FALSE), TLS transport
+ * will just notify the application via #pjsip_tp_state_callback with
+ * state PJSIP_TP_STATE_CONNECTED regardless TLS verification result.
+ * - If \a verify_server is enabled (set to PJ_TRUE), TLS transport
+ * will be shutdown and application will be notified with state
+ * PJSIP_TP_STATE_DISCONNECTED whenever there is any TLS verification
+ * error, otherwise PJSIP_TP_STATE_CONNECTED will be notified.
+ *
+ * In any cases, application can inspect #pjsip_tls_state_info in the
+ * callback to see the verification detail.
+ *
+ * Default value is PJ_FALSE.
+ */
+ pj_bool_t verify_server;
+
+ /**
+ * Specifies TLS transport behavior on the client TLS certificate
+ * verification result:
+ * - If \a verify_client is disabled (set to PJ_FALSE), TLS transport
+ * will just notify the application via #pjsip_tp_state_callback with
+ * state PJSIP_TP_STATE_CONNECTED regardless TLS verification result.
+ * - If \a verify_client is enabled (set to PJ_TRUE), TLS transport
+ * will be shutdown and application will be notified with state
+ * PJSIP_TP_STATE_DISCONNECTED whenever there is any TLS verification
+ * error, otherwise PJSIP_TP_STATE_CONNECTED will be notified.
+ *
+ * In any cases, application can inspect #pjsip_tls_state_info in the
+ * callback to see the verification detail.
+ *
+ * Default value is PJ_FALSE.
+ */
+ pj_bool_t verify_client;
+
+ /**
+ * When acting as server (incoming TLS connections), reject inocming
+ * connection if client doesn't supply a TLS certificate.
+ *
+ * This setting corresponds to SSL_VERIFY_FAIL_IF_NO_PEER_CERT flag.
+ * Default value is PJ_FALSE.
+ */
+ pj_bool_t require_client_cert;
+
+ /**
+ * TLS negotiation timeout to be applied for both outgoing and
+ * incoming connection. If both sec and msec member is set to zero,
+ * the SSL negotiation doesn't have a timeout.
+ */
+ pj_time_val timeout;
+
+ /**
+ * QoS traffic type to be set on this transport. When application wants
+ * to apply QoS tagging to the transport, it's preferable to set this
+ * field rather than \a qos_param fields since this is more portable.
+ *
+ * Default value is PJ_QOS_TYPE_BEST_EFFORT.
+ */
+ pj_qos_type qos_type;
+
+ /**
+ * Set the low level QoS parameters to the transport. This is a lower
+ * level operation than setting the \a qos_type field and may not be
+ * supported on all platforms.
+ *
+ * By default all settings in this structure are disabled.
+ */
+ pj_qos_params qos_params;
+
+ /**
+ * Specify if the transport should ignore any errors when setting the QoS
+ * traffic type/parameters.
+ *
+ * Default: PJ_TRUE
+ */
+ pj_bool_t qos_ignore_error;
+
+} pjsip_tls_setting;
+
+
+/**
+ * This structure defines TLS transport extended info in <tt>ext_info</tt>
+ * field of #pjsip_transport_state_info for the transport state notification
+ * callback #pjsip_tp_state_callback.
+ */
+typedef struct pjsip_tls_state_info
+{
+ /**
+ * SSL socket info.
+ */
+ pj_ssl_sock_info *ssl_sock_info;
+
+} pjsip_tls_state_info;
+
+
+/**
+ * Initialize TLS setting with default values.
+ *
+ * @param tls_opt The TLS setting to be initialized.
+ */
+PJ_INLINE(void) pjsip_tls_setting_default(pjsip_tls_setting *tls_opt)
+{
+ pj_memset(tls_opt, 0, sizeof(*tls_opt));
+ tls_opt->qos_type = PJ_QOS_TYPE_BEST_EFFORT;
+ tls_opt->qos_ignore_error = PJ_TRUE;
+}
+
+
+/**
+ * Copy TLS setting.
+ *
+ * @param pool The pool to duplicate strings etc.
+ * @param dst Destination structure.
+ * @param src Source structure.
+ */
+PJ_INLINE(void) pjsip_tls_setting_copy(pj_pool_t *pool,
+ pjsip_tls_setting *dst,
+ const pjsip_tls_setting *src)
+{
+ pj_memcpy(dst, src, sizeof(*dst));
+ pj_strdup_with_null(pool, &dst->ca_list_file, &src->ca_list_file);
+ pj_strdup_with_null(pool, &dst->cert_file, &src->cert_file);
+ pj_strdup_with_null(pool, &dst->privkey_file, &src->privkey_file);
+ pj_strdup_with_null(pool, &dst->password, &src->password);
+ if (src->ciphers_num) {
+ unsigned i;
+ dst->ciphers = (pj_ssl_cipher*) pj_pool_calloc(pool, src->ciphers_num,
+ sizeof(pj_ssl_cipher));
+ for (i=0; i<src->ciphers_num; ++i)
+ dst->ciphers[i] = src->ciphers[i];
+ }
+}
+
+
+/**
+ * Register support for SIP TLS transport by creating TLS listener on
+ * the specified address and port. This function will create an
+ * instance of SIP TLS transport factory and register it to the
+ * transport manager.
+ *
+ * @param endpt The SIP endpoint.
+ * @param opt Optional TLS settings.
+ * @param local Optional local address to bind, or specify the
+ * address to bind the server socket to. Both IP
+ * interface address and port fields are optional.
+ * If IP interface address is not specified, socket
+ * will be bound to PJ_INADDR_ANY. If port is not
+ * specified, socket will be bound to any port
+ * selected by the operating system.
+ * @param a_name Optional published address, which is the address to be
+ * advertised as the address of this SIP transport.
+ * If this argument is NULL, then the bound address
+ * will be used as the published address.
+ * @param async_cnt Number of simultaneous asynchronous accept()
+ * operations to be supported. It is recommended that
+ * the number here corresponds to the number of
+ * processors in the system (or the number of SIP
+ * worker threads).
+ * @param p_factory Optional pointer to receive the instance of the
+ * SIP TLS transport factory just created.
+ *
+ * @return PJ_SUCCESS when the transport has been successfully
+ * started and registered to transport manager, or
+ * the appropriate error code.
+ */
+PJ_DECL(pj_status_t) pjsip_tls_transport_start(pjsip_endpoint *endpt,
+ const pjsip_tls_setting *opt,
+ const pj_sockaddr_in *local,
+ const pjsip_host_port *a_name,
+ unsigned async_cnt,
+ pjsip_tpfactory **p_factory);
+
+
+
+PJ_END_DECL
+
+/**
+ * @}
+ */
+
+#endif /* __PJSIP_TRANSPORT_TLS_H__ */
diff --git a/pjsip/include/pjsip/sip_transport_udp.h b/pjsip/include/pjsip/sip_transport_udp.h
new file mode 100644
index 0000000..f58d1e6
--- /dev/null
+++ b/pjsip/include/pjsip/sip_transport_udp.h
@@ -0,0 +1,235 @@
+/* $Id: sip_transport_udp.h 3553 2011-05-05 06:14:19Z nanang $ */
+/*
+ * 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_TRANSPORT_UDP_H__
+#define __PJSIP_TRANSPORT_UDP_H__
+
+/**
+ * @file sip_transport_udp.h
+ * @brief SIP UDP Transport.
+ */
+
+#include <pjsip/sip_transport.h>
+
+PJ_BEGIN_DECL
+
+/**
+ * @defgroup PJSIP_TRANSPORT_UDP UDP Transport
+ * @ingroup PJSIP_TRANSPORT
+ * @brief API to create and register UDP transport.
+ * @{
+ * The functions below are used to create UDP transport and register
+ * the transport to the framework.
+ */
+
+/**
+ * Flag that can be specified when calling #pjsip_udp_transport_pause() or
+ * #pjsip_udp_transport_restart().
+ */
+enum
+{
+ /**
+ * This flag tells the transport to keep the existing/internal socket
+ * handle.
+ */
+ PJSIP_UDP_TRANSPORT_KEEP_SOCKET = 1,
+
+ /**
+ * This flag tells the transport to destroy the existing/internal socket
+ * handle. Naturally this flag and PJSIP_UDP_TRANSPORT_KEEP_SOCKET are
+ * mutually exclusive.
+ */
+ PJSIP_UDP_TRANSPORT_DESTROY_SOCKET = 2
+};
+
+
+/**
+ * Start UDP transport.
+ *
+ * @param endpt The SIP endpoint.
+ * @param local Optional local address to bind. If this argument
+ * is NULL, the UDP transport will be bound to arbitrary
+ * UDP port.
+ * @param a_name Published address (only the host and port portion is
+ * used). If this argument is NULL, then the bound address
+ * will be used as the published address.
+ * @param async_cnt Number of simultaneous async operations.
+ * @param p_transport Pointer to receive the transport.
+ *
+ * @return PJ_SUCCESS when the transport has been successfully
+ * started and registered to transport manager, or
+ * the appropriate error code.
+ */
+PJ_DECL(pj_status_t) pjsip_udp_transport_start(pjsip_endpoint *endpt,
+ const pj_sockaddr_in *local,
+ const pjsip_host_port *a_name,
+ unsigned async_cnt,
+ pjsip_transport **p_transport);
+
+/**
+ * Start IPv6 UDP transport.
+ */
+PJ_DECL(pj_status_t) pjsip_udp_transport_start6(pjsip_endpoint *endpt,
+ const pj_sockaddr_in6 *local,
+ const pjsip_host_port *a_name,
+ unsigned async_cnt,
+ pjsip_transport **p_transport);
+
+
+/**
+ * Attach IPv4 UDP socket as a new transport and start the transport.
+ *
+ * @param endpt The SIP endpoint.
+ * @param sock UDP socket to use.
+ * @param a_name Published address (only the host and port portion is
+ * used).
+ * @param async_cnt Number of simultaneous async operations.
+ * @param p_transport Pointer to receive the transport.
+ *
+ * @return PJ_SUCCESS when the transport has been successfully
+ * started and registered to transport manager, or
+ * the appropriate error code.
+ */
+PJ_DECL(pj_status_t) pjsip_udp_transport_attach(pjsip_endpoint *endpt,
+ pj_sock_t sock,
+ const pjsip_host_port *a_name,
+ unsigned async_cnt,
+ pjsip_transport **p_transport);
+
+
+/**
+ * Attach IPv4 or IPv6 UDP socket as a new transport and start the transport.
+ *
+ * @param endpt The SIP endpoint.
+ * @param type Transport type, which is PJSIP_TRANSPORT_UDP for IPv4
+ * or PJSIP_TRANSPORT_UDP6 for IPv6 socket.
+ * @param sock UDP socket to use.
+ * @param a_name Published address (only the host and port portion is
+ * used).
+ * @param async_cnt Number of simultaneous async operations.
+ * @param p_transport Pointer to receive the transport.
+ *
+ * @return PJ_SUCCESS when the transport has been successfully
+ * started and registered to transport manager, or
+ * the appropriate error code.
+ */
+PJ_DECL(pj_status_t) pjsip_udp_transport_attach2(pjsip_endpoint *endpt,
+ pjsip_transport_type_e type,
+ pj_sock_t sock,
+ const pjsip_host_port *a_name,
+ unsigned async_cnt,
+ pjsip_transport **p_transport);
+
+/**
+ * Retrieve the internal socket handle used by the UDP transport. Note
+ * that this socket normally is registered to ioqueue, so if application
+ * wants to make use of this socket, it should temporarily pause the
+ * transport.
+ *
+ * @param transport The UDP transport.
+ *
+ * @return The socket handle, or PJ_INVALID_SOCKET if no socket
+ * is currently being used (for example, when transport
+ * is being paused).
+ */
+PJ_DECL(pj_sock_t) pjsip_udp_transport_get_socket(pjsip_transport *transport);
+
+
+/**
+ * Temporarily pause or shutdown the transport. When transport is being
+ * paused, it cannot be used by the SIP stack to send or receive SIP
+ * messages.
+ *
+ * Two types of operations are supported by this function:
+ * - to temporarily make this transport unavailable for SIP uses, but
+ * otherwise keep the socket handle intact. Application then can
+ * retrieve the socket handle with #pjsip_udp_transport_get_socket()
+ * and use it to send/receive application data (for example, STUN
+ * messages). In this case, application should specify
+ * PJSIP_UDP_TRANSPORT_KEEP_SOCKET when calling this function, and
+ * also to specify this flag when calling #pjsip_udp_transport_restart()
+ * later.
+ * - to temporarily shutdown the transport, including closing down
+ * the internal socket handle. This is useful for example to
+ * temporarily suspend the application for an indefinite period. In
+ * this case, application should specify PJSIP_UDP_TRANSPORT_DESTROY_SOCKET
+ * flag when calling this function, and specify a new socket when
+ * calling #pjsip_udp_transport_restart().
+ *
+ * @param transport The UDP transport.
+ * @param option Pause option.
+ *
+ * @return PJ_SUCCESS if transport is paused successfully,
+ * or the appropriate error code.
+ */
+PJ_DECL(pj_status_t) pjsip_udp_transport_pause(pjsip_transport *transport,
+ unsigned option);
+
+/**
+ * Restart the transport. Several operations are supported by this function:
+ * - if transport was made temporarily unavailable to SIP stack with
+ * pjsip_udp_transport_pause() and PJSIP_UDP_TRANSPORT_KEEP_SOCKET,
+ * application can make the transport available to the SIP stack
+ * again, by specifying PJSIP_UDP_TRANSPORT_KEEP_SOCKET flag here.
+ * - if application wants to replace the internal socket with a new
+ * socket, it must specify PJSIP_UDP_TRANSPORT_DESTROY_SOCKET when
+ * calling this function, so that the internal socket will be destroyed
+ * if it hasn't been closed. In this case, application has two choices
+ * on how to create the new socket: 1) to let the transport create
+ * the new socket, in this case the \a sock option should be set
+ * to \a PJ_INVALID_SOCKET and optionally the \a local parameter can be
+ * filled with the desired address and port where the new socket
+ * should be bound to, or 2) to specify its own socket to be used
+ * by this transport, by specifying a valid socket in \a sock argument
+ * and set the \a local argument to NULL. In both cases, application
+ * may specify the published address of the socket in \a a_name
+ * argument.
+ *
+ * @param transport The UDP transport.
+ * @param option Restart option.
+ * @param sock Optional socket to be used by the transport.
+ * @param local The address where the socket should be bound to.
+ * If this argument is NULL, socket will be bound
+ * to any available port.
+ * @param a_name Optionally specify the published address for
+ * this transport. If the socket is not replaced
+ * (PJSIP_UDP_TRANSPORT_KEEP_SOCKET flag is
+ * specified), then if this argument is NULL, the
+ * previous value will be used. If the socket is
+ * replaced and this argument is NULL, the bound
+ * address will be used as the published address
+ * of the transport.
+ *
+ * @return PJ_SUCCESS if transport can be restarted, or
+ * the appropriate error code.
+ */
+PJ_DECL(pj_status_t) pjsip_udp_transport_restart(pjsip_transport *transport,
+ unsigned option,
+ pj_sock_t sock,
+ const pj_sockaddr_in *local,
+ const pjsip_host_port *a_name);
+
+
+PJ_END_DECL
+
+/**
+ * @}
+ */
+
+#endif /* __PJSIP_TRANSPORT_UDP_H__ */
diff --git a/pjsip/include/pjsip/sip_types.h b/pjsip/include/pjsip/sip_types.h
new file mode 100644
index 0000000..8cd98ae
--- /dev/null
+++ b/pjsip/include/pjsip/sip_types.h
@@ -0,0 +1,257 @@
+/* $Id: sip_types.h 3553 2011-05-05 06:14:19Z nanang $ */
+/*
+ * 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_TYPES_H__
+#define __PJSIP_SIP_TYPES_H__
+
+
+/*
+ * My note: Doxygen PJSIP and PJSIP_CORE group is declared in
+ * sip_config.h
+ */
+
+/**
+ * @file sip_types.h
+ * @brief Basic PJSIP types.
+ */
+
+#include <pjsip/sip_config.h>
+#include <pj/types.h>
+
+/**
+ * @addtogroup PJSIP_BASE
+ */
+
+/* @defgroup PJSIP_TYPES Basic Data Types
+ * @ingroup PJSIP_BASE
+ * @brief Basic data types.
+ * @{
+ */
+
+
+
+/**
+ * Forward declaration for SIP transport.
+ */
+typedef struct pjsip_transport pjsip_transport;
+
+/**
+ * Forward declaration for transport manager.
+ */
+typedef struct pjsip_tpmgr pjsip_tpmgr;
+
+/**
+ * Transport types.
+ */
+typedef enum pjsip_transport_type_e
+{
+ /** Unspecified. */
+ PJSIP_TRANSPORT_UNSPECIFIED,
+
+ /** UDP. */
+ PJSIP_TRANSPORT_UDP,
+
+ /** TCP. */
+ PJSIP_TRANSPORT_TCP,
+
+ /** TLS. */
+ PJSIP_TRANSPORT_TLS,
+
+ /** SCTP. */
+ PJSIP_TRANSPORT_SCTP,
+
+ /** Loopback (stream, reliable) */
+ PJSIP_TRANSPORT_LOOP,
+
+ /** Loopback (datagram, unreliable) */
+ PJSIP_TRANSPORT_LOOP_DGRAM,
+
+ /** Start of user defined transport */
+ PJSIP_TRANSPORT_START_OTHER,
+
+ /** Start of IPv6 transports */
+ PJSIP_TRANSPORT_IPV6 = 128,
+
+ /** UDP over IPv6 */
+ PJSIP_TRANSPORT_UDP6 = PJSIP_TRANSPORT_UDP + PJSIP_TRANSPORT_IPV6,
+
+ /** TCP over IPv6 */
+ PJSIP_TRANSPORT_TCP6 = PJSIP_TRANSPORT_TCP + PJSIP_TRANSPORT_IPV6
+
+} pjsip_transport_type_e;
+
+
+/**
+ * Forward declaration for endpoint (sip_endpoint.h).
+ */
+typedef struct pjsip_endpoint pjsip_endpoint;
+
+/**
+ * Forward declaration for transactions (sip_transaction.h).
+ */
+typedef struct pjsip_transaction pjsip_transaction;
+
+/**
+ * Forward declaration for events (sip_event.h).
+ */
+typedef struct pjsip_event pjsip_event;
+
+/**
+ * Forward declaration for transmit data/buffer (sip_transport.h).
+ */
+typedef struct pjsip_tx_data pjsip_tx_data;
+
+/**
+ * Forward declaration for receive data/buffer (sip_transport.h).
+ */
+typedef struct pjsip_rx_data pjsip_rx_data;
+
+/**
+ * Forward declaration for message (sip_msg.h).
+ */
+typedef struct pjsip_msg pjsip_msg;
+
+/**
+ * Forward declaration for message body (sip_msg.h).
+ */
+typedef struct pjsip_msg_body pjsip_msg_body;
+
+/**
+ * Forward declaration for header field (sip_msg.h).
+ */
+typedef struct pjsip_hdr pjsip_hdr;
+
+/**
+ * Forward declaration for URI (sip_uri.h).
+ */
+typedef struct pjsip_uri pjsip_uri;
+
+/**
+ * Forward declaration for SIP method (sip_msg.h)
+ */
+typedef struct pjsip_method pjsip_method;
+
+/**
+ * Opaque data type for the resolver engine (sip_resolve.h).
+ */
+typedef struct pjsip_resolver_t pjsip_resolver_t;
+
+/**
+ * Forward declaration for credential.
+ */
+typedef struct pjsip_cred_info pjsip_cred_info;
+
+
+/**
+ * Forward declaration for module (sip_module.h).
+ */
+typedef struct pjsip_module pjsip_module;
+
+
+/**
+ * Forward declaration for user agent type (sip_ua_layer.h).
+ */
+typedef pjsip_module pjsip_user_agent;
+
+/**
+ * Forward declaration for dialog (sip_dialog.h).
+ */
+typedef struct pjsip_dialog pjsip_dialog;
+
+/**
+ * Transaction role.
+ */
+typedef enum pjsip_role_e
+{
+ PJSIP_ROLE_UAC, /**< Role is UAC. */
+ PJSIP_ROLE_UAS, /**< Role is UAS. */
+
+ /* Alias: */
+
+ PJSIP_UAC_ROLE = PJSIP_ROLE_UAC, /**< Role is UAC. */
+ PJSIP_UAS_ROLE = PJSIP_ROLE_UAS /**< Role is UAS. */
+
+} pjsip_role_e;
+
+
+/**
+ * General purpose buffer.
+ */
+typedef struct pjsip_buffer
+{
+ /** The start of the buffer. */
+ char *start;
+
+ /** Pointer to current end of the buffer, which also indicates the position
+ of subsequent buffer write.
+ */
+ char *cur;
+
+ /** The absolute end of the buffer. */
+ char *end;
+
+} pjsip_buffer;
+
+
+/**
+ * General host:port pair, used for example as Via sent-by.
+ */
+typedef struct pjsip_host_port
+{
+ pj_str_t host; /**< Host part or IP address. */
+ int port; /**< Port number. */
+} pjsip_host_port;
+
+/**
+ * Host information.
+ */
+typedef struct pjsip_host_info
+{
+ unsigned flag; /**< Flags of pjsip_transport_flags_e. */
+ pjsip_transport_type_e type; /**< Transport type. */
+ pjsip_host_port addr; /**< Address information. */
+} pjsip_host_info;
+
+
+/**
+ * Convert exception ID into pj_status_t status.
+ *
+ * @param exception_id Exception Id.
+ *
+ * @return Error code for the specified exception Id.
+ */
+PJ_DECL(pj_status_t) pjsip_exception_to_status(int exception_id);
+
+/**
+ * Return standard pj_status_t status from current exception.
+ */
+#define PJSIP_RETURN_EXCEPTION() pjsip_exception_to_status(PJ_GET_EXCEPTION())
+
+/**
+ * Attributes to inform that the function may throw exceptions.
+ */
+#define PJSIP_THROW_SPEC(list)
+
+
+/**
+ * @}
+ */
+
+#endif /* __PJSIP_SIP_TYPES_H__ */
+
diff --git a/pjsip/include/pjsip/sip_ua_layer.h b/pjsip/include/pjsip/sip_ua_layer.h
new file mode 100644
index 0000000..4c69e45
--- /dev/null
+++ b/pjsip/include/pjsip/sip_ua_layer.h
@@ -0,0 +1,162 @@
+/* $Id: sip_ua_layer.h 3553 2011-05-05 06:14:19Z nanang $ */
+/*
+ * 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_UA_LAYER_H__
+#define __PJSIP_SIP_UA_LAYER_H__
+
+/**
+ * @file sip_ua_layer.h
+ * @brief SIP User Agent Layer Module
+ */
+#include <pjsip/sip_types.h>
+
+
+PJ_BEGIN_DECL
+
+/**
+ * @defgroup PJSIP_UA Base User Agent Layer/Common Dialog Layer
+ * @brief Dialog management.
+ *
+ * This module provides basic dialog management, which is used by higher
+ * layer dialog usages such as INVITE sessions and SIP Event Subscription
+ * framework (RFC 3265). Application should link with <b>pjsip-core</b>
+ * library to use this base UA layer. The base UA layer module is initialized
+ * with #pjsip_ua_init_module().
+ */
+
+/**
+ * @defgroup PJSUA_UA SIP User Agent Module
+ * @ingroup PJSIP_UA
+ * @brief Provides dialog management.
+ * @{
+ *
+ * Application MUST initialize the user agent layer module by calling
+ * #pjsip_ua_init_module() before using any of the dialog API, and link
+ * the application with with <b>pjsip-core</b> library.
+ */
+
+/** User agent initialization parameter. */
+typedef struct pjsip_ua_init_param
+{
+ /** Callback to be called when the UA layer detects that outgoing
+ * dialog has forked.
+ */
+ pjsip_dialog* (*on_dlg_forked)(pjsip_dialog *first_set, pjsip_rx_data *res);
+} pjsip_ua_init_param;
+
+/**
+ * Initialize user agent layer and register it to the specified endpoint.
+ *
+ * @param endpt The endpoint where the user agent will be
+ * registered.
+ * @param prm UA initialization parameter.
+ *
+ * @return PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjsip_ua_init_module(pjsip_endpoint *endpt,
+ const pjsip_ua_init_param *prm);
+
+/**
+ * Get the instance of the user agent.
+ *
+ * @return The user agent module instance.
+ */
+PJ_DECL(pjsip_user_agent*) pjsip_ua_instance(void);
+
+
+/**
+ * Retrieve the current number of dialog-set currently registered
+ * in the hash table. Note that dialog-set is different than dialog
+ * when the request forks. In this case, all dialogs created from
+ * the original request will belong to the same dialog set. When
+ * no forking occurs, the number of dialog sets will be equal to
+ * the number of dialogs.
+ *
+ * @return Number of dialog sets.
+ */
+PJ_DECL(pj_uint32_t) pjsip_ua_get_dlg_set_count(void);
+
+
+/**
+ * Find a dialog with the specified Call-ID and tags properties. This
+ * function may optionally lock the matching dialog instance before
+ * returning it back to the caller.
+ *
+ * @param call_id The call ID to be matched.
+ * @param local_tag The local tag to be matched.
+ * @param remote_tag The remote tag to be matched.
+ * @param lock_dialog If non-zero, instruct the function to lock the
+ * matching dialog with #pjsip_dlg_inc_lock().
+ * Application is responsible to release the dialog's
+ * lock after it has finished manipulating the dialog,
+ * by calling #pjsip_dlg_dec_lock().
+ *
+ * @return The matching dialog instance, or NULL if no matching
+ * dialog is found.
+ */
+PJ_DECL(pjsip_dialog*) pjsip_ua_find_dialog(const pj_str_t *call_id,
+ const pj_str_t *local_tag,
+ const pj_str_t *remote_tag,
+ pj_bool_t lock_dialog);
+
+/**
+ * Destroy the user agent layer.
+ *
+ * @return PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjsip_ua_destroy(void);
+
+/**
+ * Dump user agent contents (e.g. all dialogs).
+ *
+ * @param detail If non-zero, list of dialogs will be printed.
+ */
+PJ_DECL(void) pjsip_ua_dump(pj_bool_t detail);
+
+/**
+ * Get the endpoint instance of a user agent module.
+ *
+ * @param ua The user agent instance.
+ *
+ * @return The endpoint instance where the user agent is
+ * registered.
+ */
+PJ_DECL(pjsip_endpoint*) pjsip_ua_get_endpt(pjsip_user_agent *ua);
+
+
+/**
+ * @}
+ */
+
+
+/*
+ * Internal (called by sip_dialog.c).
+ */
+
+PJ_DECL(pj_status_t) pjsip_ua_register_dlg( pjsip_user_agent *ua,
+ pjsip_dialog *dlg );
+PJ_DECL(pj_status_t) pjsip_ua_unregister_dlg(pjsip_user_agent *ua,
+ pjsip_dialog *dlg );
+
+
+PJ_END_DECL
+
+
+#endif /* __PJSIP_SIP_UA_LAYER_H__ */
+
diff --git a/pjsip/include/pjsip/sip_uri.h b/pjsip/include/pjsip/sip_uri.h
new file mode 100644
index 0000000..849392f
--- /dev/null
+++ b/pjsip/include/pjsip/sip_uri.h
@@ -0,0 +1,468 @@
+/* $Id: sip_uri.h 3553 2011-05-05 06:14:19Z nanang $ */
+/*
+ * 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_URI_H__
+#define __PJSIP_SIP_URI_H__
+
+/**
+ * @file sip_uri.h
+ * @brief SIP URL Structures and Manipulations
+ */
+
+#include <pjsip/sip_types.h>
+#include <pjsip/sip_config.h>
+#include <pj/list.h>
+#include <pjlib-util/scanner.h>
+
+PJ_BEGIN_DECL
+
+
+/**
+ * @defgroup PJSIP_URI URI
+ * @brief URI types and manipulations.
+ * @ingroup PJSIP_MSG
+ */
+
+/**
+ * @addtogroup PJSIP_URI_PARAM URI Parameter Container
+ * @ingroup PJSIP_URI
+ * @brief Generic parameter elements container.
+ * @{
+ */
+
+/**
+ * Generic parameter, normally used in other_param or header_param.
+ */
+typedef struct pjsip_param
+{
+ PJ_DECL_LIST_MEMBER(struct pjsip_param); /**< Generic list member. */
+ pj_str_t name; /**< Param/header name. */
+ pj_str_t value; /**< Param/header value. */
+} pjsip_param;
+
+
+/**
+ * Find the specified parameter name in the list. The name will be compared
+ * in case-insensitive comparison.
+ *
+ * @param param_list List of parameters to find.
+ * @param name Parameter/header name to find.
+ *
+ * @return The parameter if found, or NULL.
+ */
+PJ_DECL(pjsip_param*) pjsip_param_find( const pjsip_param *param_list,
+ const pj_str_t *name );
+
+
+/**
+ * Alias for pjsip_param_find()
+ */
+PJ_INLINE(pjsip_param*) pjsip_param_cfind(const pjsip_param *param_list,
+ const pj_str_t *name)
+{
+ return pjsip_param_find(param_list, name);
+}
+
+/**
+ * Compare two parameter lists.
+ *
+ * @param param_list1 First parameter list.
+ * @param param_list2 Second parameter list.
+ * @param ig_nf If set to 1, do not compare parameters that only
+ * appear in one of the list.
+ *
+ * @return Zero if the parameter list are equal, non-zero
+ * otherwise.
+ */
+PJ_DECL(int) pjsip_param_cmp(const pjsip_param *param_list1,
+ const pjsip_param *param_list2,
+ pj_bool_t ig_nf);
+
+/**
+ * Duplicate the parameters.
+ *
+ * @param pool Pool to allocate memory from.
+ * @param dst_list Destination list.
+ * @param src_list Source list.
+ */
+PJ_DECL(void) pjsip_param_clone(pj_pool_t *pool, pjsip_param *dst_list,
+ const pjsip_param *src_list);
+
+/**
+ * Duplicate the parameters.
+ *
+ * @param pool Pool to allocate memory from.
+ * @param dst_list Destination list.
+ * @param src_list Source list.
+ */
+PJ_DECL(void) pjsip_param_shallow_clone(pj_pool_t *pool,
+ pjsip_param *dst_list,
+ const pjsip_param *src_list);
+
+/**
+ * Print parameters.
+ *
+ * @param param_list The parameter list.
+ * @param buf Buffer.
+ * @param size Size of buffer.
+ * @param pname_unres Specification of allowed characters in pname.
+ * @param pvalue_unres Specification of allowed characters in pvalue.
+ * @param sep Separator character (either ';', ',', or '?').
+ * When separator is set to '?', this function will
+ * automatically adjust the separator character to
+ * '&' after the first parameter is printed.
+ *
+ * @return The number of bytes printed, or -1 on errr.
+ */
+PJ_DECL(pj_ssize_t) pjsip_param_print_on(const pjsip_param *param_list,
+ char *buf, pj_size_t size,
+ const pj_cis_t *pname_unres,
+ const pj_cis_t *pvalue_unres,
+ int sep);
+
+/**
+ * @}
+ */
+
+/**
+ * @defgroup PJSIP_URI_GENERIC Generic URI
+ * @ingroup PJSIP_URI
+ * @brief Generic representation for all types of URI.
+ * @{
+ */
+
+/**
+ * URI context.
+ */
+typedef enum pjsip_uri_context_e
+{
+ PJSIP_URI_IN_REQ_URI, /**< The URI is in Request URI. */
+ PJSIP_URI_IN_FROMTO_HDR, /**< The URI is in From/To header. */
+ PJSIP_URI_IN_CONTACT_HDR, /**< The URI is in Contact header. */
+ PJSIP_URI_IN_ROUTING_HDR, /**< The URI is in Route/Record-Route header. */
+ PJSIP_URI_IN_OTHER /**< Other context (web page, business card, etc.) */
+} pjsip_uri_context_e;
+
+/**
+ * URI 'virtual' function table.
+ * All types of URI in this library (such as sip:, sips:, tel:, and name-addr)
+ * will have pointer to this table as their first struct member. This table
+ * provides polimorphic behaviour to the URI.
+ */
+typedef struct pjsip_uri_vptr
+{
+ /**
+ * Get URI scheme.
+ * @param uri the URI (self).
+ * @return the URI scheme.
+ */
+ const pj_str_t* (*p_get_scheme)(const void *uri);
+
+ /**
+ * Get the URI object contained by this URI, or the URI itself if
+ * it doesn't contain another URI.
+ * @param uri the URI (self).
+ */
+ void* (*p_get_uri)(void *uri);
+
+ /**
+ * Print URI components to the buffer, following the rule of which
+ * components are allowed for the context.
+ * @param context the context where the URI will be placed.
+ * @param uri the URI (self).
+ * @param buf the buffer.
+ * @param size the size of the buffer.
+ * @return the length printed.
+ */
+ pj_ssize_t (*p_print)(pjsip_uri_context_e context,
+ const void *uri,
+ char *buf, pj_size_t size);
+
+ /**
+ * Compare two URIs according to the context.
+ * @param context the context.
+ * @param uri1 the first URI (self).
+ * @param uri2 the second URI.
+ * @return PJ_SUCCESS if equal, or otherwise the error status which
+ * should point to the mismatch part.
+ */
+ pj_status_t (*p_compare)(pjsip_uri_context_e context,
+ const void *uri1, const void *uri2);
+
+ /**
+ * Clone URI.
+ * @param pool the pool.
+ * @param the URI to clone (self).
+ * @return new URI.
+ */
+ void *(*p_clone)(pj_pool_t *pool, const void *uri);
+
+} pjsip_uri_vptr;
+
+
+/**
+ * The declaration of 'base class' for all URI scheme.
+ */
+struct pjsip_uri
+{
+ /** All URIs must have URI virtual function table as their first member. */
+ pjsip_uri_vptr *vptr;
+};
+
+/**
+ * This macro checks that the URL is a "sip:" or "sips:" URL.
+ * @param url The URL (pointer to)
+ * @return non-zero if TRUE.
+ */
+#define PJSIP_URI_SCHEME_IS_SIP(url) \
+ (pj_strnicmp2(pjsip_uri_get_scheme(url), "sip", 3)==0)
+
+/**
+ * This macro checks that the URL is a "sips:" URL (not SIP).
+ * @param url The URL (pointer to)
+ * @return non-zero if TRUE.
+ */
+#define PJSIP_URI_SCHEME_IS_SIPS(url) \
+ (pj_strnicmp2(pjsip_uri_get_scheme(url), "sips", 4)==0)
+
+/**
+ * This macro checks that the URL is a "tel:" URL.
+ * @param url The URL (pointer to)
+ * @return non-zero if TRUE.
+ */
+#define PJSIP_URI_SCHEME_IS_TEL(url) \
+ (pj_strnicmp2(pjsip_uri_get_scheme(url), "tel", 3)==0)
+
+
+/**
+ * Generic function to get the URI scheme.
+ * @param uri the URI object.
+ * @return the URI scheme.
+ */
+PJ_INLINE(const pj_str_t*) pjsip_uri_get_scheme(const void *uri)
+{
+ return (*((pjsip_uri*)uri)->vptr->p_get_scheme)(uri);
+}
+
+/**
+ * Generic function to get the URI object contained by this URI, or the URI
+ * itself if it doesn't contain another URI.
+ *
+ * @param uri the URI.
+ * @return the URI.
+ */
+PJ_INLINE(void*) pjsip_uri_get_uri(const void *uri)
+{
+ return (*((pjsip_uri*)uri)->vptr->p_get_uri)((void*)uri);
+}
+
+/**
+ * Generic function to compare two URIs.
+ *
+ * @param context Comparison context.
+ * @param uri1 The first URI.
+ * @param uri2 The second URI.
+ * @return PJ_SUCCESS if equal, or otherwise the error status which
+ * should point to the mismatch part.
+ */
+PJ_INLINE(pj_status_t) pjsip_uri_cmp(pjsip_uri_context_e context,
+ const void *uri1, const void *uri2)
+{
+ return (*((const pjsip_uri*)uri1)->vptr->p_compare)(context, uri1, uri2);
+}
+
+/**
+ * Generic function to print an URI object.
+ *
+ * @param context Print context.
+ * @param uri The URI to print.
+ * @param buf The buffer.
+ * @param size Size of the buffer.
+ * @return Length printed.
+ */
+PJ_INLINE(int) pjsip_uri_print(pjsip_uri_context_e context,
+ const void *uri,
+ char *buf, pj_size_t size)
+{
+ return (*((const pjsip_uri*)uri)->vptr->p_print)(context, uri, buf, size);
+}
+
+/**
+ * Generic function to clone an URI object.
+ *
+ * @param pool Pool.
+ * @param uri URI to clone.
+ * @return New URI.
+ */
+PJ_INLINE(void*) pjsip_uri_clone( pj_pool_t *pool, const void *uri )
+{
+ return (*((const pjsip_uri*)uri)->vptr->p_clone)(pool, uri);
+}
+
+
+
+/**
+ * @}
+ */
+
+/**
+ * @defgroup PJSIP_SIP_URI SIP URI Scheme and Name address
+ * @ingroup PJSIP_URI
+ * @brief SIP URL structure ("sip:" and "sips:")
+ * @{
+ */
+
+
+/**
+ * SIP and SIPS URL scheme.
+ */
+typedef struct pjsip_sip_uri
+{
+ pjsip_uri_vptr *vptr; /**< Pointer to virtual function table.*/
+ pj_str_t user; /**< Optional user part. */
+ pj_str_t passwd; /**< Optional password part. */
+ pj_str_t host; /**< Host part, always exists. */
+ int port; /**< Optional port number, or zero. */
+ pj_str_t user_param; /**< Optional user parameter */
+ pj_str_t method_param; /**< Optional method parameter. */
+ pj_str_t transport_param; /**< Optional transport parameter. */
+ int ttl_param; /**< Optional TTL param, or -1. */
+ int lr_param; /**< Optional loose routing param, or zero */
+ pj_str_t maddr_param; /**< Optional maddr param */
+ pjsip_param other_param; /**< Other parameters grouped together. */
+ pjsip_param header_param; /**< Optional header parameter. */
+} pjsip_sip_uri;
+
+
+/**
+ * SIP name-addr, which typically appear in From, To, and Contact header.
+ * The SIP name-addr contains a generic URI and a display name.
+ */
+typedef struct pjsip_name_addr
+{
+ /** Pointer to virtual function table. */
+ pjsip_uri_vptr *vptr;
+
+ /** Optional display name. */
+ pj_str_t display;
+
+ /** URI part. */
+ pjsip_uri *uri;
+
+} pjsip_name_addr;
+
+
+/**
+ * Create new SIP URL and initialize all fields with zero or NULL.
+ * @param pool The pool.
+ * @param secure Flag to indicate whether secure transport should be used.
+ * @return SIP URL.
+ */
+PJ_DECL(pjsip_sip_uri*) pjsip_sip_uri_create( pj_pool_t *pool,
+ pj_bool_t secure );
+
+/**
+ * Change the SIP URI scheme to sip or sips based on the secure flag.
+ * This would not change anything except the scheme.
+ * @param uri The URI
+ * @param secure Non-zero if sips is wanted.
+ */
+PJ_DECL(void) pjsip_sip_uri_set_secure( pjsip_sip_uri *uri,
+ pj_bool_t secure );
+
+/**
+ * Initialize SIP URL (all fields are set to NULL or zero).
+ * @param url The URL.
+ * @param secure Create sips URI?
+ */
+PJ_DECL(void) pjsip_sip_uri_init(pjsip_sip_uri *url, pj_bool_t secure);
+
+/**
+ * Perform full assignment to the SIP URL.
+ * @param pool The pool.
+ * @param url Destination URL.
+ * @param rhs The source URL.
+ */
+PJ_DECL(void) pjsip_sip_uri_assign(pj_pool_t *pool, pjsip_sip_uri *url,
+ const pjsip_sip_uri *rhs);
+
+/**
+ * Create new instance of name address and initialize all fields with zero or
+ * NULL.
+ * @param pool The pool.
+ * @return New SIP name address.
+ */
+PJ_DECL(pjsip_name_addr*) pjsip_name_addr_create(pj_pool_t *pool);
+
+/**
+ * Initialize with default value.
+ * @param name_addr The name address.
+ */
+PJ_DECL(void) pjsip_name_addr_init(pjsip_name_addr *name_addr);
+
+/**
+ * Perform full assignment to the name address.
+ * @param pool The pool.
+ * @param addr The destination name address.
+ * @param rhs The source name address.
+ */
+PJ_DECL(void) pjsip_name_addr_assign(pj_pool_t *pool,
+ pjsip_name_addr *addr,
+ const pjsip_name_addr *rhs);
+
+/**
+ * @}
+ */
+
+/**
+ * @defgroup PJSIP_OTHER_URI Other URI schemes
+ * @ingroup PJSIP_URI
+ * @brief Container for non SIP/tel URI scheme (e.g. "http:", "mailto:")
+ * @{
+ */
+
+/**
+ * Generic URI container for non SIP/tel URI scheme.
+ */
+typedef struct pjsip_other_uri
+{
+ pjsip_uri_vptr *vptr; /**< Pointer to virtual function table. */
+ pj_str_t scheme; /**< The URI scheme (e.g. "mailto") */
+ pj_str_t content; /**< The whole URI content */
+} pjsip_other_uri;
+
+
+/**
+ * Create a generic URI object.
+ *
+ * @param pool The pool to allocate memory from.
+ *
+ * @return The URI instance.
+ */
+PJ_DECL(pjsip_other_uri*) pjsip_other_uri_create(pj_pool_t *pool);
+
+
+/**
+ * @}
+ */
+
+PJ_END_DECL
+
+#endif /* __PJSIP_URL_H__ */
+
diff --git a/pjsip/include/pjsip/sip_util.h b/pjsip/include/pjsip/sip_util.h
new file mode 100644
index 0000000..6efa45f
--- /dev/null
+++ b/pjsip/include/pjsip/sip_util.h
@@ -0,0 +1,861 @@
+/* $Id: sip_util.h 3553 2011-05-05 06:14:19Z nanang $ */
+/*
+ * 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_MISC_H__
+#define __PJSIP_SIP_MISC_H__
+
+#include <pjsip/sip_msg.h>
+#include <pjsip/sip_transport.h>
+#include <pjsip/sip_resolve.h>
+
+PJ_BEGIN_DECL
+
+/**
+ * @defgroup PJSIP_ENDPT_TARGET_URI Target URI Management
+ * @ingroup PJSIP_CORE_CORE
+ * @brief Management of target URI's in case of redirection
+ * @{
+ * This module provides utility functions to manage target set for UAC.
+ * The target set is provided as pjsip_target_set structure. Initially,
+ * the target set for UAC contains only one target, that is the target of
+ * the initial request. When 3xx/redirection class response is received,
+ * the UAC can use the functionality of this module to add the URI's listed
+ * in the Contact header(s) in the response to the target set, and retry
+ * sending the request to the next destination/target. The UAC may retry
+ * this sequentially until one of the target answers with succesful/2xx
+ * response, or one target returns global error/6xx response, or all targets
+ * are exhausted.
+ *
+ * This module is currently used by the \ref PJSIP_INV.
+ */
+
+/**
+ * This structure describes a target, which can be chained together to form
+ * a target set. Each target contains an URI, priority (as q-value), and
+ * the last status code and reason phrase received from the target, if the
+ * target has been contacted. If the target has not been contacted, the
+ * status code field will be zero.
+ */
+typedef struct pjsip_target
+{
+ PJ_DECL_LIST_MEMBER(struct pjsip_target);/**< Standard list element */
+ pjsip_uri *uri; /**< The target URI */
+ int q1000; /**< q-value multiplied by 1000 */
+ pjsip_status_code code; /**< Last status code received */
+ pj_str_t reason; /**< Last reason phrase received */
+} pjsip_target;
+
+
+/**
+ * This describes a target set. A target set contains a linked-list of
+ * pjsip_target.
+ */
+typedef struct pjsip_target_set
+{
+ pjsip_target head; /**< Target linked-list head */
+ pjsip_target *current; /**< Current target. */
+} pjsip_target_set;
+
+
+/**
+ * These enumerations specify the action to be performed to a redirect
+ * response.
+ */
+typedef enum pjsip_redirect_op
+{
+ /**
+ * Reject the redirection to the current target. The UAC will
+ * select the next target from the target set if exists.
+ */
+ PJSIP_REDIRECT_REJECT,
+
+ /**
+ * Accept the redirection to the current target. The INVITE request
+ * will be resent to the current target.
+ */
+ PJSIP_REDIRECT_ACCEPT,
+
+ /**
+ * Defer the redirection decision, for example to request permission
+ * from the end user.
+ */
+ PJSIP_REDIRECT_PENDING,
+
+ /**
+ * Stop the whole redirection process altogether. This will cause
+ * the invite session to be disconnected.
+ */
+ PJSIP_REDIRECT_STOP
+
+} pjsip_redirect_op;
+
+
+/**
+ * Initialize target set. This will empty the list of targets in the
+ * target set.
+ *
+ * @param tset The target set.
+ */
+PJ_INLINE(void) pjsip_target_set_init(pjsip_target_set *tset)
+{
+ pj_list_init(&tset->head);
+ tset->current = NULL;
+}
+
+
+/**
+ * Add an URI to the target set, if the URI is not already in the target set.
+ * The URI comparison rule of pjsip_uri_cmp() will be used to determine the
+ * equality of this URI compared to existing URI's in the target set. The
+ * URI will be cloned using the specified memory pool before it is added to
+ * the list.
+ *
+ * The first URI added to the target set will also be made current target
+ * by this function.
+ *
+ * @param tset The target set.
+ * @param pool The memory pool to be used to duplicate the URI.
+ * @param uri The URI to be checked and added.
+ * @param q1000 The q-value multiplied by 1000.
+ *
+ * @return PJ_SUCCESS if the URI was added to the target set,
+ * or PJ_EEXISTS if the URI already exists in the target
+ * set, or other error codes.
+ */
+PJ_DECL(pj_status_t) pjsip_target_set_add_uri(pjsip_target_set *tset,
+ pj_pool_t *pool,
+ const pjsip_uri *uri,
+ int q1000);
+
+/**
+ * Extract URI's in the Contact headers of the specified (response) message
+ * and add them to the target set. This function will also check if the
+ * URI's already exist in the target set before adding them to the list.
+ *
+ * @param tset The target set.
+ * @param pool The memory pool to be used to duplicate the URI's.
+ * @param msg SIP message from which the Contact headers will be
+ * scanned and the URI's to be extracted, checked, and
+ * added to the target set.
+ *
+ * @return PJ_SUCCESS if at least one URI was added to the
+ * target set, or PJ_EEXISTS if all URI's in the message
+ * already exists in the target set or if the message
+ * doesn't contain usable Contact headers, or other error
+ * codes.
+ */
+PJ_DECL(pj_status_t) pjsip_target_set_add_from_msg(pjsip_target_set *tset,
+ pj_pool_t *pool,
+ const pjsip_msg *msg);
+
+/**
+ * Get the next target to be retried. This function will scan the target set
+ * for target which hasn't been tried, and return one target with the
+ * highest q-value, if such target exists. This function will return NULL
+ * if there is one target with 2xx or 6xx code or if all targets have been
+ * tried.
+ *
+ * @param tset The target set.
+ *
+ * @return The next target to be tried, or NULL if all targets have
+ * been tried or at least one target returns 2xx or 6xx
+ * response.
+ */
+PJ_DECL(pjsip_target*)
+pjsip_target_set_get_next(const pjsip_target_set *tset);
+
+
+/**
+ * Set the specified target as the current target in the target set. The
+ * current target may be used by application to keep track on which target
+ * is currently being operated on.
+ *
+ * @param tset The target set.
+ * @param target The target to be set as current target.
+ *
+ * @return PJ_SUCCESS or the appropriate error code.
+ */
+PJ_DECL(pj_status_t) pjsip_target_set_set_current(pjsip_target_set *tset,
+ pjsip_target *target);
+
+
+/**
+ * Set the status code and reason phrase of the specified target.
+ *
+ * @param target The target.
+ * @param pool The memory pool to be used to duplicate the reason phrase.
+ * @param code The SIP status code to be set to the target.
+ * @param reason The reason phrase to be set to the target.
+ *
+ * @return PJ_SUCCESS on successful operation or the appropriate
+ * error code.
+ */
+PJ_DECL(pj_status_t) pjsip_target_assign_status(pjsip_target *target,
+ pj_pool_t *pool,
+ int status_code,
+ const pj_str_t *reason);
+
+/**
+ * @}
+ */
+
+/**
+ * @defgroup PJSIP_ENDPT_STATELESS Message Creation and Stateless Operations
+ * @ingroup PJSIP_CORE_CORE
+ * @brief Utilities to create various messages and base function to send messages.
+ * @{
+ */
+
+/**
+ * Create an independent request message. This can be used to build any
+ * request outside a dialog, such as OPTIONS, MESSAGE, etc. To create a request
+ * inside a dialog, application should use #pjsip_dlg_create_request.
+ *
+ * This function adds the following headers in the request:
+ * - From, To, Call-ID, and CSeq,
+ * - Contact header, if contact is specified.
+ * - A blank Via header.
+ * - Additional request headers (such as Max-Forwards) which are copied
+ * from endpoint configuration.
+ *
+ * In addition, the function adds a unique tag in the From header.
+ *
+ * Once a transmit data is created, the reference counter is initialized to 1.
+ *
+ * @param endpt Endpoint instance.
+ * @param method SIP Method.
+ * @param target Target URI.
+ * @param from URL to put in From header.
+ * @param to URL to put in To header.
+ * @param contact Contact to be put as Contact header value, hence
+ * the format must follow RFC 3261 Section 20.10:
+ * When the header field value contains a display
+ * name, the URI including all URI parameters is
+ * enclosed in "<" and ">". If no "<" and ">" are
+ * present, all parameters after the URI are header
+ * parameters, not URI parameters. The display name
+ * can be tokens, or a quoted string, if a larger
+ * character set is desired.
+ * @param call_id Optional Call-ID (put NULL to generate unique Call-ID).
+ * @param cseq Optional CSeq (put -1 to generate random CSeq).
+ * @param text Optional text body (put NULL to omit body).
+ * @param p_tdata Pointer to receive the transmit data.
+ *
+ * @return PJ_SUCCESS, or the appropriate error code.
+ */
+PJ_DECL(pj_status_t) pjsip_endpt_create_request( pjsip_endpoint *endpt,
+ const pjsip_method *method,
+ const pj_str_t *target,
+ const pj_str_t *from,
+ const pj_str_t *to,
+ const pj_str_t *contact,
+ const pj_str_t *call_id,
+ int cseq,
+ const pj_str_t *text,
+ pjsip_tx_data **p_tdata);
+
+/**
+ * Create an independent request message from the specified headers. This
+ * function will clone the headers and put them in the request.
+ *
+ * This function adds the following headers in the request:
+ * - From, To, Call-ID, and CSeq,
+ * - Contact header, if contact is specified.
+ * - A blank Via header.
+ * - Additional request headers (such as Max-Forwards) which are copied
+ * from endpoint configuration.
+ *
+ * In addition, the function adds a unique tag in the From header.
+ *
+ * Once a transmit data is created, the reference counter is initialized to 1.
+ *
+ * @param endpt Endpoint instance.
+ * @param method SIP Method.
+ * @param target Target URI.
+ * @param from From header.
+ * @param to To header.
+ * @param contact Contact header.
+ * @param call_id Optional Call-ID (put NULL to generate unique Call-ID).
+ * @param cseq Optional CSeq (put -1 to generate random CSeq).
+ * @param text Optional text body (put NULL to omit body).
+ * @param p_tdata Pointer to receive the transmit data.
+ *
+ * @return PJ_SUCCESS, or the appropriate error code.
+ */
+PJ_DECL(pj_status_t)
+pjsip_endpt_create_request_from_hdr( pjsip_endpoint *endpt,
+ const pjsip_method *method,
+ const pjsip_uri *target,
+ const pjsip_from_hdr *from,
+ const pjsip_to_hdr *to,
+ const pjsip_contact_hdr *contact,
+ const pjsip_cid_hdr *call_id,
+ int cseq,
+ const pj_str_t *text,
+ pjsip_tx_data **p_tdata);
+
+/**
+ * Construct a minimal response message for the received request. This function
+ * will construct all the Via, Record-Route, Call-ID, From, To, CSeq, and
+ * Call-ID headers from the request.
+ *
+ * Note: the txdata reference counter is set to ZERO!.
+ *
+ * @param endpt The endpoint.
+ * @param rdata The request receive data.
+ * @param st_code Status code to be put in the response.
+ * @param st_text Optional status text, or NULL to get the default text.
+ * @param p_tdata Pointer to receive the transmit data.
+ *
+ * @return PJ_SUCCESS, or the appropriate error code.
+ */
+PJ_DECL(pj_status_t) pjsip_endpt_create_response( pjsip_endpoint *endpt,
+ const pjsip_rx_data *rdata,
+ int st_code,
+ const pj_str_t *st_text,
+ pjsip_tx_data **p_tdata);
+
+/**
+ * Construct a full ACK request for the received non-2xx final response.
+ * This utility function is normally called by the transaction to construct
+ * an ACK request to 3xx-6xx final response.
+ * The generation of ACK message for 2xx final response is different than
+ * this one.
+ *
+ * @param endpt The endpoint.
+ * @param tdata This contains the original INVITE request
+ * @param rdata The final response.
+ * @param ack The ACK request created.
+ *
+ * @return PJ_SUCCESS, or the appropriate error code.
+ */
+PJ_DECL(pj_status_t) pjsip_endpt_create_ack( pjsip_endpoint *endpt,
+ const pjsip_tx_data *tdata,
+ const pjsip_rx_data *rdata,
+ pjsip_tx_data **ack);
+
+
+/**
+ * Construct CANCEL request for the previously sent request.
+ *
+ * @param endpt The endpoint.
+ * @param tdata The transmit buffer for the request being cancelled.
+ * @param p_tdata Pointer to receive the transmit data.
+ *
+ * @return PJ_SUCCESS, or the appropriate error code.
+ */
+PJ_DECL(pj_status_t) pjsip_endpt_create_cancel( pjsip_endpoint *endpt,
+ const pjsip_tx_data *tdata,
+ pjsip_tx_data **p_tdata);
+
+
+/**
+ * Find which destination to be used to send the request message, based
+ * on the request URI and Route headers in the message. The procedure
+ * used here follows the guidelines on sending the request in RFC 3261
+ * chapter 8.1.2.
+ *
+ * Note there was a change in the behavior of this function since version
+ * 0.5.10.2. Previously this function may modify the request when strict
+ * route is present (to update request URI and route-set). This is no
+ * longer the case now, and this process is done in separate function
+ * (see #pjsip_process_route_set()).
+ *
+ * @param tdata The transmit data containing the request message.
+ * @param dest_info On return, it contains information about destination
+ * host to contact, along with the preferable transport
+ * type, if any. Caller will then normally proceed with
+ * resolving this host with server resolution procedure
+ * described in RFC 3263.
+ *
+ * @return PJ_SUCCESS, or the appropriate error code.
+ *
+ * @see pjsip_process_route_set
+ */
+PJ_DECL(pj_status_t) pjsip_get_request_dest(const pjsip_tx_data *tdata,
+ pjsip_host_info *dest_info );
+
+
+/**
+ * Process route-set found in the request and calculate destination to be
+ * used to send the request message, based on the request URI and Route
+ * headers in the message. The procedure used here follows the guidelines
+ * on sending the request in RFC 3261 chapter 8.1.2.
+ *
+ * This function may modify the message (request line and Route headers),
+ * if the Route information specifies strict routing and the request
+ * URI in the message is different than the calculated target URI. In that
+ * case, the target URI will be put as the request URI of the request and
+ * current request URI will be put as the last entry of the Route headers.
+ *
+ * @param tdata The transmit data containing the request message.
+ * @param dest_info On return, it contains information about destination
+ * host to contact, along with the preferable transport
+ * type, if any. Caller will then normally proceed with
+ * resolving this host with server resolution procedure
+ * described in RFC 3263.
+ *
+ * @return PJ_SUCCESS, or the appropriate error code.
+ *
+ * @see pjsip_get_request_addr
+ */
+PJ_DECL(pj_status_t) pjsip_process_route_set(pjsip_tx_data *tdata,
+ pjsip_host_info *dest_info );
+
+
+/**
+ * Swap the request URI and strict route back to the original position
+ * before #pjsip_process_route_set() function is called. If no strict
+ * route URI was found by #pjsip_process_route_set(), this function will
+ * do nothing.
+ *
+ * This function should only used internally by PJSIP client authentication
+ * module.
+ *
+ * @param tdata Transmit data containing request message.
+ */
+PJ_DECL(void) pjsip_restore_strict_route_set(pjsip_tx_data *tdata);
+
+
+/**
+ * This structure holds the state of outgoing stateless request.
+ */
+typedef struct pjsip_send_state
+{
+ /** Application token, which was specified when the function
+ * #pjsip_endpt_send_request_stateless() is called.
+ */
+ void *token;
+
+ /** Endpoint instance.
+ */
+ pjsip_endpoint *endpt;
+
+ /** Transmit data buffer being sent.
+ */
+ pjsip_tx_data *tdata;
+
+ /** Current transport being used.
+ */
+ pjsip_transport *cur_transport;
+
+ /** The application callback which was specified when the function
+ * #pjsip_endpt_send_request_stateless() was called.
+ */
+ void (*app_cb)(struct pjsip_send_state*,
+ pj_ssize_t sent,
+ pj_bool_t *cont);
+} pjsip_send_state;
+
+
+/**
+ * Declaration for callback function to be specified in
+ * #pjsip_endpt_send_request_stateless(), #pjsip_endpt_send_response(), or
+ * #pjsip_endpt_send_response2().
+ *
+ * @param st Structure to keep transmission state.
+ * @param sent Number of bytes sent.
+ * @param cont When current transmission fails, specify whether
+ * the function should fallback to next destination.
+ */
+typedef void (*pjsip_send_callback)(pjsip_send_state *st, pj_ssize_t sent,
+ pj_bool_t *cont);
+
+/**
+ * Send outgoing request statelessly The function will take care of which
+ * destination and transport to use based on the information in the message,
+ * taking care of URI in the request line and Route header.
+ *
+ * This function is different than #pjsip_transport_send() in that this
+ * function adds/modify the Via header as necessary.
+ *
+ * @param endpt The endpoint instance.
+ * @param tdata The transmit data to be sent.
+ * @param token Arbitrary token to be given back on the callback.
+ * @param cb Optional callback to notify transmission status (also
+ * gives chance for application to discontinue retrying
+ * sending to alternate address).
+ *
+ * @return PJ_SUCCESS, or the appropriate error code.
+ */
+PJ_DECL(pj_status_t)
+pjsip_endpt_send_request_stateless( pjsip_endpoint *endpt,
+ pjsip_tx_data *tdata,
+ void *token,
+ pjsip_send_callback cb);
+
+/**
+ * This is a low-level function to send raw data to a destination.
+ *
+ * See also #pjsip_endpt_send_raw_to_uri().
+ *
+ * @param endpt The SIP endpoint instance.
+ * @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 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_endpt_send_raw(pjsip_endpoint *endpt,
+ pjsip_transport_type_e tp_type,
+ const pjsip_tpselector *sel,
+ const void *raw_data,
+ pj_size_t data_len,
+ const pj_sockaddr_t *addr,
+ int addr_len,
+ void *token,
+ pjsip_tp_send_callback cb);
+
+/**
+ * Send raw data to the specified destination URI. The actual destination
+ * address will be calculated from the URI, using normal SIP URI to host
+ * resolution.
+ *
+ * See also #pjsip_endpt_send_raw().
+ *
+ * @param endpt The SIP endpoint instance.
+ * @param dst_uri Destination address URI.
+ * @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 raw_data The data to be sent.
+ * @param data_len The length of the data.
+ * @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_endpt_send_raw_to_uri(pjsip_endpoint *endpt,
+ const pj_str_t *dst_uri,
+ const pjsip_tpselector *sel,
+ const void *raw_data,
+ pj_size_t data_len,
+ void *token,
+ pjsip_tp_send_callback cb);
+
+/**
+ * This structure describes destination information to send response.
+ * It is initialized by calling #pjsip_get_response_addr().
+ *
+ * If the response message should be sent using transport from which
+ * the request was received, then transport, addr, and addr_len fields
+ * are initialized.
+ *
+ * The dst_host field is also initialized. It should be used when server
+ * fails to send the response using the transport from which the request
+ * was received, or when the transport is NULL, which means server
+ * must send the response to this address (this situation occurs when
+ * maddr parameter is set, or when rport param is not set in the request).
+ */
+typedef struct pjsip_response_addr
+{
+ pjsip_transport *transport; /**< Immediate transport to be used. */
+ pj_sockaddr addr; /**< Immediate address to send to. */
+ int addr_len; /**< Address length. */
+ pjsip_host_info dst_host; /**< Destination host to contact. */
+} pjsip_response_addr;
+
+/**
+ * Determine which address (and transport) to use to send response message
+ * based on the received request. This function follows the specification
+ * in section 18.2.2 of RFC 3261 and RFC 3581 for calculating the destination
+ * address and transport.
+ *
+ * The information about destination to send the response will be returned
+ * in res_addr argument. Please see #pjsip_response_addr for more info.
+ *
+ * @param pool The pool.
+ * @param rdata The incoming request received by the server.
+ * @param res_addr On return, it will be initialized with information about
+ * destination address and transport to send the response.
+ *
+ * @return zero (PJ_OK) if successfull.
+ */
+PJ_DECL(pj_status_t) pjsip_get_response_addr(pj_pool_t *pool,
+ pjsip_rx_data *rdata,
+ pjsip_response_addr *res_addr);
+
+/**
+ * Send response in tdata statelessly. The function will take care of which
+ * response destination and transport to use based on the information in the
+ * Via header (such as the presence of rport, symmetric transport, etc.).
+ *
+ * This function will create a new ephemeral transport if no existing
+ * transports can be used to send the message to the destination. The ephemeral
+ * transport will be destroyed after some period if it is not used to send any
+ * more messages.
+ *
+ * The behavior of this function complies with section 18.2.2 of RFC 3261
+ * and RFC 3581.
+ *
+ * @param endpt The endpoint instance.
+ * @param res_addr The information about the address and transport to send
+ * the response to. Application can get this information
+ * by calling #pjsip_get_response_addr().
+ * @param tdata The response message to be sent.
+ * @param token Token to be passed back when the callback is called.
+ * @param cb Optional callback to notify the transmission status
+ * to application, and to inform whether next address or
+ * transport will be tried.
+ *
+ * @return PJ_SUCCESS if response has been successfully created and
+ * sent to transport layer, or a non-zero error code.
+ * However, even when it returns PJ_SUCCESS, there is no
+ * guarantee that the response has been successfully sent.
+ */
+PJ_DECL(pj_status_t) pjsip_endpt_send_response( pjsip_endpoint *endpt,
+ pjsip_response_addr *res_addr,
+ pjsip_tx_data *tdata,
+ void *token,
+ pjsip_send_callback cb);
+
+/**
+ * This is a convenient function which wraps #pjsip_get_response_addr() and
+ * #pjsip_endpt_send_response() in a single function.
+ *
+ * @param endpt The endpoint instance.
+ * @param rdata The original request to be responded.
+ * @param tdata The response message to be sent.
+ * @param token Token to be passed back when the callback is called.
+ * @param cb Optional callback to notify the transmission status
+ * to application, and to inform whether next address or
+ * transport will be tried.
+ *
+ * @return PJ_SUCCESS if response has been successfully created and
+ * sent to transport layer, or a non-zero error code.
+ * However, even when it returns PJ_SUCCESS, there is no
+ * guarantee that the response has been successfully sent.
+ */
+PJ_DECL(pj_status_t) pjsip_endpt_send_response2(pjsip_endpoint *endpt,
+ pjsip_rx_data *rdata,
+ pjsip_tx_data *tdata,
+ void *token,
+ pjsip_send_callback cb);
+
+/**
+ * This composite function sends response message statelessly to an incoming
+ * request message. Internally it calls #pjsip_endpt_create_response() and
+ * #pjsip_endpt_send_response().
+ *
+ * @param endpt The endpoint instance.
+ * @param rdata The incoming request message.
+ * @param st_code Status code of the response.
+ * @param st_text Optional status text of the response.
+ * @param hdr_list Optional header list to be added to the response.
+ * @param body Optional message body to be added to the response.
+ *
+ * @return PJ_SUCCESS if response message has successfully been
+ * sent.
+ */
+PJ_DECL(pj_status_t) pjsip_endpt_respond_stateless(pjsip_endpoint *endpt,
+ pjsip_rx_data *rdata,
+ int st_code,
+ const pj_str_t *st_text,
+ const pjsip_hdr *hdr_list,
+ const pjsip_msg_body *body);
+
+/**
+ * @}
+ */
+
+/**
+ * @defgroup PJSIP_TRANSACT_UTIL Stateful Operations
+ * @ingroup PJSIP_TRANSACT
+ * @brief Utility function to send requests/responses statefully.
+ * @{
+ */
+
+/**
+ * This composite function creates and sends response statefully for the
+ * incoming request.
+ *
+ * @param endpt The endpoint instance.
+ * @param tsx_user The module to be registered as transaction user.
+ * @param rdata The incoming request message.
+ * @param st_code Status code of the response.
+ * @param st_text Optional status text of the response.
+ * @param hdr_list Optional header list to be added to the response.
+ * @param body Optional message body to be added to the response.
+ * @param p_tsx Optional pointer to receive the transaction which was
+ * created to send the response.
+ *
+ * @return PJ_SUCCESS if response message has successfully been
+ * created.
+ */
+PJ_DECL(pj_status_t) pjsip_endpt_respond( pjsip_endpoint *endpt,
+ pjsip_module *tsx_user,
+ pjsip_rx_data *rdata,
+ int st_code,
+ const pj_str_t *st_text,
+ const pjsip_hdr *hdr_list,
+ const pjsip_msg_body *body,
+ pjsip_transaction **p_tsx );
+
+/**
+ * Type of callback to be specified in #pjsip_endpt_send_request().
+ *
+ * @param token The token that was given in #pjsip_endpt_send_request()
+ * @param e Completion event.
+ */
+typedef void (*pjsip_endpt_send_callback)(void *token, pjsip_event *e);
+
+/**
+ * Send outgoing request and initiate UAC transaction for the request.
+ * This is an auxiliary function to be used by application to send arbitrary
+ * requests outside a dialog. To send a request within a dialog, application
+ * should use #pjsip_dlg_send_request instead.
+ *
+ * @param endpt The endpoint instance.
+ * @param tdata The transmit data to be sent.
+ * @param timeout Optional timeout for final response to be received, or -1
+ * if the transaction should not have a timeout restriction.
+ * The value is in miliseconds.
+ * @param token Optional token to be associated with the transaction, and
+ * to be passed to the callback.
+ * @param cb Optional callback to be called when the transaction has
+ * received a final response. The callback will be called with
+ * the previously registered token and the event that triggers
+ * the completion of the transaction.
+ *
+ * @return PJ_SUCCESS, or the appropriate error code.
+ */
+PJ_DECL(pj_status_t) pjsip_endpt_send_request( pjsip_endpoint *endpt,
+ pjsip_tx_data *tdata,
+ pj_int32_t timeout,
+ void *token,
+ pjsip_endpt_send_callback cb);
+
+/**
+ * @}
+ */
+
+/**
+ * @defgroup PJSIP_PROXY_CORE Core Proxy Layer
+ * @brief Core proxy operations
+ * @{
+ */
+
+/**
+ * Create new request message to be forwarded upstream to new destination URI
+ * in uri. The new request is a full/deep clone of the request received in
+ * rdata, unless if other copy mechanism is specified in the options.
+ * The branch parameter, if not NULL, will be used as the branch-param in
+ * the Via header. If it is NULL, then a unique branch parameter will be used.
+ *
+ * Note: this function DOES NOT perform Route information preprocessing as
+ * described in RFC 3261 Section 16.4. Application must take care of
+ * removing/updating the Route headers according of the rules as
+ * described in that section.
+ *
+ * @param endpt The endpoint instance.
+ * @param rdata The incoming request message.
+ * @param uri The URI where the request will be forwarded to.
+ * @param branch Optional branch parameter. Application may specify its
+ * own branch, for example if it wishes to perform loop
+ * detection. If the branch parameter is not specified,
+ * this function will generate its own by calling
+ * #pjsip_calculate_branch_id() function.
+ * @param options Optional option flags when duplicating the message.
+ * @param tdata The result.
+ *
+ * @return PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjsip_endpt_create_request_fwd(pjsip_endpoint *endpt,
+ pjsip_rx_data *rdata,
+ const pjsip_uri *uri,
+ const pj_str_t *branch,
+ unsigned options,
+ pjsip_tx_data **tdata);
+
+
+
+/**
+ * Create new response message to be forwarded downstream by the proxy from
+ * the response message found in rdata. Note that this function practically
+ * will clone the response as is, i.e. without checking the validity of the
+ * response or removing top most Via header. This function will perform
+ * full/deep clone of the response, unless other copy mechanism is used in
+ * the options.
+ *
+ * @param endpt The endpoint instance.
+ * @param rdata The incoming response message.
+ * @param options Optional option flags when duplicate the message.
+ * @param tdata The result
+ *
+ * @return PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjsip_endpt_create_response_fwd( pjsip_endpoint *endpt,
+ pjsip_rx_data *rdata,
+ unsigned options,
+ pjsip_tx_data **tdata);
+
+
+
+/**
+ * Create a globally unique branch parameter based on the information in
+ * the incoming request message, for the purpose of creating a new request
+ * for forwarding. This is the default implementation used by
+ * #pjsip_endpt_create_request_fwd() function if the branch parameter is
+ * not specified.
+ *
+ * The default implementation here will just create an MD5 hash of the
+ * top-most Via.
+ *
+ * Note that the returned string was allocated from rdata's pool.
+ *
+ * @param rdata The incoming request message.
+ *
+ * @return Unique branch-ID string.
+ */
+PJ_DECL(pj_str_t) pjsip_calculate_branch_id( pjsip_rx_data *rdata );
+
+
+/**
+ * @}
+ */
+
+PJ_END_DECL
+
+#endif /* __PJSIP_SIP_MISC_H__ */
+
diff --git a/pjsip/include/pjsip_auth.h b/pjsip/include/pjsip_auth.h
new file mode 100644
index 0000000..3ab2c5e
--- /dev/null
+++ b/pjsip/include/pjsip_auth.h
@@ -0,0 +1,38 @@
+/* $Id: pjsip_auth.h 3553 2011-05-05 06:14:19Z nanang $ */
+/*
+ * 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_AUTH_H__
+#define __PJSIP_AUTH_H__
+
+/**
+ * @defgroup PJSIP_AUTH SIP Authorization module
+ */
+
+/**
+ * @file pjsip_auth.h
+ * @brief SIP Authorization Module.
+ */
+
+
+#include <pjsip_auth/sip_auth.h>
+#include <pjsip_auth/sip_auth_msg.h>
+#include <pjsip_auth/sip_auth_parser.h>
+
+#endif /* __PJSIP_AUTH_H__ */
+
diff --git a/pjsip/include/pjsip_simple.h b/pjsip/include/pjsip_simple.h
new file mode 100644
index 0000000..af5acda
--- /dev/null
+++ b/pjsip/include/pjsip_simple.h
@@ -0,0 +1,46 @@
+/* $Id: pjsip_simple.h 3553 2011-05-05 06:14:19Z nanang $ */
+/*
+ * 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
+ */
+
+/**
+ * @defgroup PJSIP_SIMPLE Event and Presence Framework
+ */
+
+/**
+ * @file pjsip_simple.h
+ * @brief SIP SIMPLE Extension
+ */
+
+/*
+ * Include this header file to get all functionalities for SIMPLE extension
+ * (SIP for Instant Messaging and Presence Leveraging Extension).
+ */
+#ifndef __PJSIP_SIMPLE_H__
+#define __PJSIP_SIMPLE_H__
+
+#include <pjsip-simple/evsub.h>
+#include <pjsip-simple/evsub_msg.h>
+#include <pjsip-simple/iscomposing.h>
+#include <pjsip-simple/mwi.h>
+#include <pjsip-simple/presence.h>
+#include <pjsip-simple/pidf.h>
+#include <pjsip-simple/publish.h>
+#include <pjsip-simple/xpidf.h>
+
+#endif /* __PJSIP_SIMPLE_H__ */
diff --git a/pjsip/include/pjsip_ua.h b/pjsip/include/pjsip_ua.h
new file mode 100644
index 0000000..59d5358
--- /dev/null
+++ b/pjsip/include/pjsip_ua.h
@@ -0,0 +1,32 @@
+/* $Id: pjsip_ua.h 3553 2011-05-05 06:14:19Z nanang $ */
+/*
+ * 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_UA_H__
+#define __PJSIP_UA_H__
+
+#include <pjsip-ua/sip_inv.h>
+#include <pjsip-ua/sip_regc.h>
+#include <pjsip-ua/sip_replaces.h>
+#include <pjsip-ua/sip_xfer.h>
+#include <pjsip-ua/sip_100rel.h>
+#include <pjsip-ua/sip_timer.h>
+
+
+#endif /* __PJSIP_UA_H__ */
+
diff --git a/pjsip/include/pjsua-lib/pjsua.h b/pjsip/include/pjsua-lib/pjsua.h
new file mode 100644
index 0000000..856d853
--- /dev/null
+++ b/pjsip/include/pjsua-lib/pjsua.h
@@ -0,0 +1,6346 @@
+/* $Id: pjsua.h 4180 2012-06-26 09:37:41Z 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 __PJSUA_H__
+#define __PJSUA_H__
+
+/**
+ * @file pjsua.h
+ * @brief PJSUA API.
+ */
+
+
+/* Include all PJSIP core headers. */
+#include <pjsip.h>
+
+/* Include all PJMEDIA headers. */
+#include <pjmedia.h>
+
+/* Include all PJMEDIA-CODEC headers. */
+#include <pjmedia-codec.h>
+
+/* Videodev too */
+#include <pjmedia_videodev.h>
+
+/* Include all PJSIP-UA headers */
+#include <pjsip_ua.h>
+
+/* Include all PJSIP-SIMPLE headers */
+#include <pjsip_simple.h>
+
+/* Include all PJNATH headers */
+#include <pjnath.h>
+
+/* Include all PJLIB-UTIL headers. */
+#include <pjlib-util.h>
+
+/* Include all PJLIB headers. */
+#include <pjlib.h>
+
+
+PJ_BEGIN_DECL
+
+
+/**
+ * @defgroup PJSUA_LIB PJSUA API - High Level Softphone API
+ * @brief Very high level API for constructing SIP UA applications.
+ * @{
+ *
+ * @section pjsua_api_intro A SIP User Agent API for C/C++
+ *
+ * PJSUA API is very high level API for constructing SIP multimedia user agent
+ * applications. It wraps together the signaling and media functionalities
+ * into an easy to use call API, provides account management, buddy
+ * management, presence, instant messaging, along with multimedia
+ * features such as conferencing, file streaming, local playback,
+ * voice recording, and so on.
+ *
+ * @subsection pjsua_for_c_cpp C/C++ Binding
+ * Application must link with <b>pjsua-lib</b> to use this API. In addition,
+ * this library depends on the following libraries:
+ * - <b>pjsip-ua</b>,
+ * - <b>pjsip-simple</b>,
+ * - <b>pjsip-core</b>,
+ * - <b>pjmedia</b>,
+ * - <b>pjmedia-codec</b>,
+ * - <b>pjlib-util</b>, and
+ * - <b>pjlib</b>,
+ *
+ * so application must also link with these libraries as well. For more
+ * information, please refer to
+ * <A HREF="http://www.pjsip.org/using.htm">Getting Started with PJSIP</A>
+ * page.
+ *
+ * @section pjsua_samples
+ *
+ * Few samples are provided:
+ *
+ - @ref page_pjsip_sample_simple_pjsuaua_c\n
+ Very simple SIP User Agent with registration, call, and media, using
+ PJSUA-API, all in under 200 lines of code.
+
+ - @ref page_pjsip_samples_pjsua\n
+ This is the reference implementation for PJSIP and PJMEDIA.
+ PJSUA is a console based application, designed to be simple enough
+ to be readble, but powerful enough to demonstrate all features
+ available in PJSIP and PJMEDIA.\n
+
+ * @section root_using_pjsua_lib Using PJSUA API
+ *
+ * Please refer to @ref PJSUA_LIB_BASE on how to create and initialize the API.
+ * And then see the Modules on the bottom of this page for more information
+ * about specific subject.
+ */
+
+
+
+/*****************************************************************************
+ * BASE API
+ */
+
+/**
+ * @defgroup PJSUA_LIB_BASE PJSUA-API Basic API
+ * @ingroup PJSUA_LIB
+ * @brief Basic application creation/initialization, logging configuration, etc.
+ * @{
+ *
+ * The base PJSUA API controls PJSUA creation, initialization, and startup, and
+ * also provides various auxiliary functions.
+ *
+ * @section using_pjsua_lib Using PJSUA Library
+ *
+ * @subsection creating_pjsua_lib Creating PJSUA
+ *
+ * Before anything else, application must create PJSUA by calling
+ * #pjsua_create().
+ * This, among other things, will initialize PJLIB, which is crucial before
+ * any PJLIB functions can be called, PJLIB-UTIL, and create a SIP endpoint.
+ *
+ * After this function is called, application can create a memory pool (with
+ * #pjsua_pool_create()) and read configurations from command line or file to
+ * build the settings to initialize PJSUA below.
+ *
+ * @subsection init_pjsua_lib Initializing PJSUA
+ *
+ * After PJSUA is created, application can initialize PJSUA by calling
+ * #pjsua_init(). This function takes several optional configuration settings
+ * in the argument, if application wants to set them.
+ *
+ * @subsubsection init_pjsua_lib_c_cpp PJSUA-LIB Initialization (in C)
+ * Sample code to initialize PJSUA in C code:
+ \code
+
+ #include <pjsua-lib/pjsua.h>
+
+ #define THIS_FILE __FILE__
+
+ static pj_status_t app_init(void)
+ {
+ pjsua_config ua_cfg;
+ pjsua_logging_config log_cfg;
+ pjsua_media_config media_cfg;
+ pj_status_t status;
+
+ // Must create pjsua before anything else!
+ status = pjsua_create();
+ if (status != PJ_SUCCESS) {
+ pjsua_perror(THIS_FILE, "Error initializing pjsua", status);
+ return status;
+ }
+
+ // Initialize configs with default settings.
+ pjsua_config_default(&ua_cfg);
+ pjsua_logging_config_default(&log_cfg);
+ pjsua_media_config_default(&media_cfg);
+
+ // At the very least, application would want to override
+ // the call callbacks in pjsua_config:
+ ua_cfg.cb.on_incoming_call = ...
+ ua_cfg.cb.on_call_state = ..
+ ...
+
+ // Customize other settings (or initialize them from application specific
+ // configuration file):
+ ...
+
+ // Initialize pjsua
+ status = pjsua_init(&ua_cfg, &log_cfg, &media_cfg);
+ if (status != PJ_SUCCESS) {
+ pjsua_perror(THIS_FILE, "Error initializing pjsua", status);
+ return status;
+ }
+ .
+ ...
+ }
+ \endcode
+ *
+ *
+
+
+ * @subsection other_init_pjsua_lib Other Initialization
+ *
+ * After PJSUA is initialized with #pjsua_init(), application will normally
+ * need/want to perform the following tasks:
+ *
+ * - create SIP transport with #pjsua_transport_create(). Application would
+ * to call #pjsua_transport_create() for each transport types that it
+ * wants to support (for example, UDP, TCP, and TLS). Please see
+ * @ref PJSUA_LIB_TRANSPORT section for more info.
+ * - create one or more SIP accounts with #pjsua_acc_add() or
+ * #pjsua_acc_add_local(). The SIP account is used for registering with
+ * the SIP server, if any. Please see @ref PJSUA_LIB_ACC for more info.
+ * - add one or more buddies with #pjsua_buddy_add(). Please see
+ * @ref PJSUA_LIB_BUDDY section for more info.
+ * - optionally configure the sound device, codec settings, and other
+ * media settings. Please see @ref PJSUA_LIB_MEDIA for more info.
+ *
+ *
+ * @subsection starting_pjsua_lib Starting PJSUA
+ *
+ * After all initializations have been done, application must call
+ * #pjsua_start() to start PJSUA. This function will check that all settings
+ * have been properly configured, and apply default settings when they haven't,
+ * or report error status when it is unable to recover from missing settings.
+ *
+ * Most settings can be changed during run-time. For example, application
+ * may add, modify, or delete accounts, buddies, or change media settings
+ * during run-time.
+ *
+ * @subsubsection starting_pjsua_lib_c C Example for Starting PJSUA
+ * Sample code:
+ \code
+ static pj_status_t app_run(void)
+ {
+ pj_status_t status;
+
+ // Start pjsua
+ status = pjsua_start();
+ if (status != PJ_SUCCESS) {
+ pjsua_destroy();
+ pjsua_perror(THIS_FILE, "Error starting pjsua", status);
+ return status;
+ }
+
+ // Run application loop
+ while (1) {
+ char choice[10];
+
+ printf("Select menu: ");
+ fgets(choice, sizeof(choice), stdin);
+ ...
+ }
+ }
+ \endcode
+
+ */
+
+/** Constant to identify invalid ID for all sorts of IDs. */
+#define PJSUA_INVALID_ID (-1)
+
+/** Disabled features temporarily for media reorganization */
+#define DISABLED_FOR_TICKET_1185 0
+
+/** Call identification */
+typedef int pjsua_call_id;
+
+/** Account identification */
+typedef int pjsua_acc_id;
+
+/** Buddy identification */
+typedef int pjsua_buddy_id;
+
+/** File player identification */
+typedef int pjsua_player_id;
+
+/** File recorder identification */
+typedef int pjsua_recorder_id;
+
+/** Conference port identification */
+typedef int pjsua_conf_port_id;
+
+/** Opaque declaration for server side presence subscription */
+typedef struct pjsua_srv_pres pjsua_srv_pres;
+
+/** Forward declaration for pjsua_msg_data */
+typedef struct pjsua_msg_data pjsua_msg_data;
+
+
+/**
+ * Maximum proxies in account.
+ */
+#ifndef PJSUA_ACC_MAX_PROXIES
+# define PJSUA_ACC_MAX_PROXIES 8
+#endif
+
+/**
+ * Default value of SRTP mode usage. Valid values are PJMEDIA_SRTP_DISABLED,
+ * PJMEDIA_SRTP_OPTIONAL, and PJMEDIA_SRTP_MANDATORY.
+ */
+#ifndef PJSUA_DEFAULT_USE_SRTP
+ #define PJSUA_DEFAULT_USE_SRTP PJMEDIA_SRTP_DISABLED
+#endif
+
+/**
+ * Default value of secure signaling requirement for SRTP.
+ * Valid values are:
+ * 0: SRTP does not require secure signaling
+ * 1: SRTP requires secure transport such as TLS
+ * 2: SRTP requires secure end-to-end transport (SIPS)
+ */
+#ifndef PJSUA_DEFAULT_SRTP_SECURE_SIGNALING
+ #define PJSUA_DEFAULT_SRTP_SECURE_SIGNALING 1
+#endif
+
+/**
+ * Controls whether PJSUA-LIB should add ICE media feature tag
+ * parameter (the ";+sip.ice" parameter) to Contact header if ICE
+ * is enabled in the config.
+ *
+ * Default: 1
+ */
+#ifndef PJSUA_ADD_ICE_TAGS
+# define PJSUA_ADD_ICE_TAGS 1
+#endif
+
+/**
+ * Timeout value used to acquire mutex lock on a particular call.
+ *
+ * Default: 2000 ms
+ */
+#ifndef PJSUA_ACQUIRE_CALL_TIMEOUT
+# define PJSUA_ACQUIRE_CALL_TIMEOUT 2000
+#endif
+
+/**
+ * Is video enabled.
+ */
+#ifndef PJSUA_HAS_VIDEO
+# define PJSUA_HAS_VIDEO PJMEDIA_HAS_VIDEO
+#endif
+
+
+/**
+ * Interval between two keyframe requests, in milliseconds.
+ *
+ * Default: 3000 ms
+ */
+#ifndef PJSUA_VID_REQ_KEYFRAME_INTERVAL
+# define PJSUA_VID_REQ_KEYFRAME_INTERVAL 3000
+#endif
+
+
+/**
+ * This enumeration represents pjsua state.
+ */
+typedef enum pjsua_state
+{
+ /**
+ * The library has not been initialized.
+ */
+ PJSUA_STATE_NULL,
+
+ /**
+ * After pjsua_create() is called but before pjsua_init() is called.
+ */
+ PJSUA_STATE_CREATED,
+
+ /**
+ * After pjsua_init() is called but before pjsua_start() is called.
+ */
+ PJSUA_STATE_INIT,
+
+ /**
+ * After pjsua_start() is called but before everything is running.
+ */
+ PJSUA_STATE_STARTING,
+
+ /**
+ * After pjsua_start() is called and before pjsua_destroy() is called.
+ */
+ PJSUA_STATE_RUNNING,
+
+ /**
+ * After pjsua_destroy() is called but before the function returns.
+ */
+ PJSUA_STATE_CLOSING
+
+} pjsua_state;
+
+
+/**
+ * Logging configuration, which can be (optionally) specified when calling
+ * #pjsua_init(). Application must call #pjsua_logging_config_default() to
+ * initialize this structure with the default values.
+ */
+typedef struct pjsua_logging_config
+{
+ /**
+ * Log incoming and outgoing SIP message? Yes!
+ */
+ pj_bool_t msg_logging;
+
+ /**
+ * Input verbosity level. Value 5 is reasonable.
+ */
+ unsigned level;
+
+ /**
+ * Verbosity level for console. Value 4 is reasonable.
+ */
+ unsigned console_level;
+
+ /**
+ * Log decoration.
+ */
+ unsigned decor;
+
+ /**
+ * Optional log filename.
+ */
+ pj_str_t log_filename;
+
+ /**
+ * Additional flags to be given to #pj_file_open() when opening
+ * the log file. By default, the flag is PJ_O_WRONLY. Application
+ * may set PJ_O_APPEND here so that logs are appended to existing
+ * file instead of overwriting it.
+ *
+ * Default is 0.
+ */
+ unsigned log_file_flags;
+
+ /**
+ * Optional callback function to be called to write log to
+ * application specific device. This function will be called for
+ * log messages on input verbosity level.
+ */
+ void (*cb)(int level, const char *data, int len);
+
+
+} pjsua_logging_config;
+
+
+/**
+ * Use this function to initialize logging config.
+ *
+ * @param cfg The logging config to be initialized.
+ */
+PJ_DECL(void) pjsua_logging_config_default(pjsua_logging_config *cfg);
+
+
+/**
+ * Use this function to duplicate logging config.
+ *
+ * @param pool Pool to use.
+ * @param dst Destination config.
+ * @param src Source config.
+ */
+PJ_DECL(void) pjsua_logging_config_dup(pj_pool_t *pool,
+ pjsua_logging_config *dst,
+ const pjsua_logging_config *src);
+
+
+/**
+ * Structure to be passed on MWI callback.
+ */
+typedef struct pjsua_mwi_info
+{
+ pjsip_evsub *evsub; /**< Event subscription session, for
+ reference. */
+ pjsip_rx_data *rdata; /**< The received NOTIFY request. */
+} pjsua_mwi_info;
+
+
+/**
+ * Structure to be passed on registration callback.
+ */
+typedef struct pjsua_reg_info
+{
+ struct pjsip_regc_cbparam *cbparam; /**< Parameters returned by
+ registration callback. */
+} pjsua_reg_info;
+
+
+/**
+ * Enumeration of media transport state types.
+ */
+typedef enum pjsua_med_tp_st
+{
+ /** Null, this is the state before media transport is created. */
+ PJSUA_MED_TP_NULL,
+
+ /**
+ * Just before media transport is created, which can finish
+ * asynchronously later.
+ */
+ PJSUA_MED_TP_CREATING,
+
+ /** Media transport creation is completed, but not initialized yet. */
+ PJSUA_MED_TP_IDLE,
+
+ /** Initialized (media_create() has been called). */
+ PJSUA_MED_TP_INIT,
+
+ /** Running (media_start() has been called). */
+ PJSUA_MED_TP_RUNNING,
+
+ /** Disabled (transport is initialized, but media is being disabled). */
+ PJSUA_MED_TP_DISABLED
+
+} pjsua_med_tp_st;
+
+
+/**
+ * Structure to be passed on media transport state callback.
+ */
+typedef struct pjsua_med_tp_state_info
+{
+ /**
+ * The media index.
+ */
+ unsigned med_idx;
+
+ /**
+ * The media transport state
+ */
+ pjsua_med_tp_st state;
+
+ /**
+ * The last error code related to the media transport state.
+ */
+ pj_status_t status;
+
+ /**
+ * Optional SIP error code.
+ */
+ int sip_err_code;
+
+ /**
+ * Optional extended info, the content is specific for each transport type.
+ */
+ void *ext_info;
+
+} pjsua_med_tp_state_info;
+
+
+/**
+ * Type of callback to be called when media transport state is changed.
+ *
+ * @param call_id The call ID.
+ * @param info The media transport state info.
+ *
+ * @return The callback must return PJ_SUCCESS at the moment.
+ */
+typedef pj_status_t
+(*pjsua_med_tp_state_cb)(pjsua_call_id call_id,
+ const pjsua_med_tp_state_info *info);
+
+
+/**
+ * This enumeration specifies the options for custom media transport creation.
+ */
+typedef enum pjsua_create_media_transport_flag
+{
+ /**
+ * This flag indicates that the media transport must also close its
+ * "member" or "child" transport when pjmedia_transport_close() is
+ * called. If this flag is not specified, then the media transport
+ * must not call pjmedia_transport_close() of its member transport.
+ */
+ PJSUA_MED_TP_CLOSE_MEMBER = 1
+
+} pjsua_create_media_transport_flag;
+
+
+/**
+ * Call settings.
+ */
+typedef struct pjsua_call_setting
+{
+ /**
+ * Bitmask of #pjsua_call_flag constants.
+ *
+ * Default: 0
+ */
+ unsigned flag;
+
+ /**
+ * This flag controls what methods to request keyframe are allowed on
+ * the call. Value is bitmask of #pjsua_vid_req_keyframe_method.
+ */
+ unsigned req_keyframe_method;
+
+ /**
+ * Number of simultaneous active audio streams for this call. Setting
+ * this to zero will disable audio in this call.
+ *
+ * Default: 1
+ */
+ unsigned aud_cnt;
+
+ /**
+ * Number of simultaneous active video streams for this call. Setting
+ * this to zero will disable video in this call.
+ *
+ * Default: 1 (if video feature is enabled, otherwise it is zero)
+ */
+ unsigned vid_cnt;
+
+} pjsua_call_setting;
+
+
+/**
+ * This structure describes application callback to receive various event
+ * notification from PJSUA-API. All of these callbacks are OPTIONAL,
+ * although definitely application would want to implement some of
+ * the important callbacks (such as \a on_incoming_call).
+ */
+typedef struct pjsua_callback
+{
+ /**
+ * Notify application when call state has changed.
+ * Application may then query the call info to get the
+ * detail call states by calling pjsua_call_get_info() function.
+ *
+ * @param call_id The call index.
+ * @param e Event which causes the call state to change.
+ */
+ void (*on_call_state)(pjsua_call_id call_id, pjsip_event *e);
+
+ /**
+ * Notify application on incoming call.
+ *
+ * @param acc_id The account which match the incoming call.
+ * @param call_id The call id that has just been created for
+ * the call.
+ * @param rdata The incoming INVITE request.
+ */
+ void (*on_incoming_call)(pjsua_acc_id acc_id, pjsua_call_id call_id,
+ pjsip_rx_data *rdata);
+
+ /**
+ * This is a general notification callback which is called whenever
+ * a transaction within the call has changed state. Application can
+ * implement this callback for example to monitor the state of
+ * outgoing requests, or to answer unhandled incoming requests
+ * (such as INFO) with a final response.
+ *
+ * @param call_id Call identification.
+ * @param tsx The transaction which has changed state.
+ * @param e Transaction event that caused the state change.
+ */
+ void (*on_call_tsx_state)(pjsua_call_id call_id,
+ pjsip_transaction *tsx,
+ pjsip_event *e);
+
+ /**
+ * Notify application when media state in the call has changed.
+ * Normal application would need to implement this callback, e.g.
+ * to connect the call's media to sound device. When ICE is used,
+ * this callback will also be called to report ICE negotiation
+ * failure.
+ *
+ * @param call_id The call index.
+ */
+ void (*on_call_media_state)(pjsua_call_id call_id);
+
+
+ /**
+ * Notify application when a call has just created a local SDP (for
+ * initial or subsequent SDP offer/answer). Application can implement
+ * this callback to modify the SDP, before it is being sent and/or
+ * negotiated with remote SDP, for example to apply per account/call
+ * basis codecs priority or to add custom/proprietary SDP attributes.
+ *
+ * @param call_id The call index.
+ * @param sdp The SDP has just been created.
+ * @param pool The pool instance, application should use this pool
+ * to modify the SDP.
+ * @param rem_sdp The remote SDP, will be NULL if local is SDP offerer.
+ */
+ void (*on_call_sdp_created)(pjsua_call_id call_id,
+ pjmedia_sdp_session *sdp,
+ pj_pool_t *pool,
+ const pjmedia_sdp_session *rem_sdp);
+
+
+ /**
+ * Notify application when media session is created and before it is
+ * registered to the conference bridge. Application may return different
+ * media port if it has added media processing port to the stream. This
+ * media port then will be added to the conference bridge instead.
+ *
+ * @param call_id Call identification.
+ * @param strm Media stream.
+ * @param stream_idx Stream index in the media session.
+ * @param p_port On input, it specifies the media port of the
+ * stream. Application may modify this pointer to
+ * point to different media port to be registered
+ * to the conference bridge.
+ */
+ void (*on_stream_created)(pjsua_call_id call_id,
+ pjmedia_stream *strm,
+ unsigned stream_idx,
+ pjmedia_port **p_port);
+
+ /**
+ * Notify application when media session has been unregistered from the
+ * conference bridge and about to be destroyed.
+ *
+ * @param call_id Call identification.
+ * @param strm Media stream.
+ * @param stream_idx Stream index in the media session.
+ */
+ void (*on_stream_destroyed)(pjsua_call_id call_id,
+ pjmedia_stream *strm,
+ unsigned stream_idx);
+
+ /**
+ * Notify application upon incoming DTMF digits.
+ *
+ * @param call_id The call index.
+ * @param digit DTMF ASCII digit.
+ */
+ void (*on_dtmf_digit)(pjsua_call_id call_id, int digit);
+
+ /**
+ * Notify application on call being transfered (i.e. REFER is received).
+ * Application can decide to accept/reject transfer request
+ * by setting the code (default is 202). When this callback
+ * is not defined, the default behavior is to accept the
+ * transfer. See also on_call_transfer_request2() callback for
+ * the version with \a pjsua_call_setting in the argument list.
+ *
+ * @param call_id The call index.
+ * @param dst The destination where the call will be
+ * transfered to.
+ * @param code Status code to be returned for the call transfer
+ * request. On input, it contains status code 200.
+ */
+ void (*on_call_transfer_request)(pjsua_call_id call_id,
+ const pj_str_t *dst,
+ pjsip_status_code *code);
+
+ /**
+ * Notify application on call being transfered (i.e. REFER is received).
+ * Application can decide to accept/reject transfer request
+ * by setting the code (default is 202). When this callback
+ * is not defined, the default behavior is to accept the
+ * transfer.
+ *
+ * @param call_id The call index.
+ * @param dst The destination where the call will be
+ * transfered to.
+ * @param code Status code to be returned for the call transfer
+ * request. On input, it contains status code 200.
+ * @param opt The current call setting, application can update
+ * this setting for the call being transfered.
+ */
+ void (*on_call_transfer_request2)(pjsua_call_id call_id,
+ const pj_str_t *dst,
+ pjsip_status_code *code,
+ pjsua_call_setting *opt);
+
+ /**
+ * Notify application of the status of previously sent call
+ * transfer request. Application can monitor the status of the
+ * call transfer request, for example to decide whether to
+ * terminate existing call.
+ *
+ * @param call_id Call ID.
+ * @param st_code Status progress of the transfer request.
+ * @param st_text Status progress text.
+ * @param final If non-zero, no further notification will
+ * be reported. The st_code specified in
+ * this callback is the final status.
+ * @param p_cont Initially will be set to non-zero, application
+ * can set this to FALSE if it no longer wants
+ * to receie further notification (for example,
+ * after it hangs up the call).
+ */
+ void (*on_call_transfer_status)(pjsua_call_id call_id,
+ int st_code,
+ const pj_str_t *st_text,
+ pj_bool_t final,
+ pj_bool_t *p_cont);
+
+ /**
+ * Notify application about incoming INVITE with Replaces header.
+ * Application may reject the request by setting non-2xx code.
+ * See also on_call_replace_request2() callback for the version
+ * with \a pjsua_call_setting in the argument list.
+ *
+ * @param call_id The call ID to be replaced.
+ * @param rdata The incoming INVITE request to replace the call.
+ * @param st_code Status code to be set by application. Application
+ * should only return a final status (200-699).
+ * @param st_text Optional status text to be set by application.
+ */
+ void (*on_call_replace_request)(pjsua_call_id call_id,
+ pjsip_rx_data *rdata,
+ int *st_code,
+ pj_str_t *st_text);
+
+ /**
+ * Notify application about incoming INVITE with Replaces header.
+ * Application may reject the request by setting non-2xx code.
+ *
+ * @param call_id The call ID to be replaced.
+ * @param rdata The incoming INVITE request to replace the call.
+ * @param st_code Status code to be set by application. Application
+ * should only return a final status (200-699).
+ * @param st_text Optional status text to be set by application.
+ * @param opt The current call setting, application can update
+ * this setting for the call being replaced.
+ */
+ void (*on_call_replace_request2)(pjsua_call_id call_id,
+ pjsip_rx_data *rdata,
+ int *st_code,
+ pj_str_t *st_text,
+ pjsua_call_setting *opt);
+
+ /**
+ * Notify application that an existing call has been replaced with
+ * a new call. This happens when PJSUA-API receives incoming INVITE
+ * request with Replaces header.
+ *
+ * After this callback is called, normally PJSUA-API will disconnect
+ * \a old_call_id and establish \a new_call_id.
+ *
+ * @param old_call_id Existing call which to be replaced with the
+ * new call.
+ * @param new_call_id The new call.
+ * @param rdata The incoming INVITE with Replaces request.
+ */
+ void (*on_call_replaced)(pjsua_call_id old_call_id,
+ pjsua_call_id new_call_id);
+
+
+ /**
+ * Notify application when call has received new offer from remote
+ * (i.e. re-INVITE/UPDATE with SDP is received). Application can
+ * decide to accept/reject the offer by setting the code (default
+ * is 200). If the offer is accepted, application can update the
+ * call setting to be applied in the answer. When this callback is
+ * not defined, the default behavior is to accept the offer using
+ * current call setting.
+ *
+ * @param call_id The call index.
+ * @param offer The new offer received.
+ * @param reserved Reserved param, currently not used.
+ * @param code Status code to be returned for answering the
+ * offer. On input, it contains status code 200.
+ * Currently, valid values are only 200 and 488.
+ * @param opt The current call setting, application can update
+ * this setting for answering the offer.
+ */
+ void (*on_call_rx_offer)(pjsua_call_id call_id,
+ const pjmedia_sdp_session *offer,
+ void *reserved,
+ pjsip_status_code *code,
+ pjsua_call_setting *opt);
+
+ /**
+ * Notify application when registration or unregistration has been
+ * initiated. Note that this only notifies the initial registration
+ * and unregistration. Once registration session is active, subsequent
+ * refresh will not cause this callback to be called.
+ *
+ * @param acc_id The account ID.
+ * @param renew Non-zero for registration and zero for
+ * unregistration.
+ */
+ void (*on_reg_started)(pjsua_acc_id acc_id, pj_bool_t renew);
+
+ /**
+ * Notify application when registration status has changed.
+ * Application may then query the account info to get the
+ * registration details.
+ *
+ * @param acc_id The account ID.
+ */
+ void (*on_reg_state)(pjsua_acc_id acc_id);
+
+ /**
+ * Notify application when registration status has changed.
+ * Application may inspect the registration info to get the
+ * registration status details.
+ *
+ * @param acc_id The account ID.
+ * @param info The registration info.
+ */
+ void (*on_reg_state2)(pjsua_acc_id acc_id, pjsua_reg_info *info);
+
+ /**
+ * Notification when incoming SUBSCRIBE request is received. Application
+ * may use this callback to authorize the incoming subscribe request
+ * (e.g. ask user permission if the request should be granted).
+ *
+ * If this callback is not implemented, all incoming presence subscription
+ * requests will be accepted.
+ *
+ * If this callback is implemented, application has several choices on
+ * what to do with the incoming request:
+ * - it may reject the request immediately by specifying non-200 class
+ * final response in the \a code argument.
+ * - it may immediately accept the request by specifying 200 as the
+ * \a code argument. This is the default value if application doesn't
+ * set any value to the \a code argument. In this case, the library
+ * will automatically send NOTIFY request upon returning from this
+ * callback.
+ * - it may delay the processing of the request, for example to request
+ * user permission whether to accept or reject the request. In this
+ * case, the application MUST set the \a code argument to 202, and
+ * later calls #pjsua_pres_notify() to accept or reject the
+ * subscription request.
+ *
+ * Any \a code other than 200 and 202 will be treated as 200.
+ *
+ * Application MUST return from this callback immediately (e.g. it must
+ * not block in this callback while waiting for user confirmation).
+ *
+ * @param srv_pres Server presence subscription instance. If
+ * application delays the acceptance of the request,
+ * it will need to specify this object when calling
+ * #pjsua_pres_notify().
+ * @param acc_id Account ID most appropriate for this request.
+ * @param buddy_id ID of the buddy matching the sender of the
+ * request, if any, or PJSUA_INVALID_ID if no
+ * matching buddy is found.
+ * @param from The From URI of the request.
+ * @param rdata The incoming request.
+ * @param code The status code to respond to the request. The
+ * default value is 200. Application may set this
+ * to other final status code to accept or reject
+ * the request.
+ * @param reason The reason phrase to respond to the request.
+ * @param msg_data If the application wants to send additional
+ * headers in the response, it can put it in this
+ * parameter.
+ */
+ void (*on_incoming_subscribe)(pjsua_acc_id acc_id,
+ pjsua_srv_pres *srv_pres,
+ pjsua_buddy_id buddy_id,
+ const pj_str_t *from,
+ pjsip_rx_data *rdata,
+ pjsip_status_code *code,
+ pj_str_t *reason,
+ pjsua_msg_data *msg_data);
+
+ /**
+ * Notification when server side subscription state has changed.
+ * This callback is optional as application normally does not need
+ * to do anything to maintain server side presence subscription.
+ *
+ * @param acc_id The account ID.
+ * @param srv_pres Server presence subscription object.
+ * @param remote_uri Remote URI string.
+ * @param state New subscription state.
+ * @param event PJSIP event that triggers the state change.
+ */
+ void (*on_srv_subscribe_state)(pjsua_acc_id acc_id,
+ pjsua_srv_pres *srv_pres,
+ const pj_str_t *remote_uri,
+ pjsip_evsub_state state,
+ pjsip_event *event);
+
+ /**
+ * Notify application when the buddy state has changed.
+ * Application may then query the buddy into to get the details.
+ *
+ * @param buddy_id The buddy id.
+ */
+ void (*on_buddy_state)(pjsua_buddy_id buddy_id);
+
+
+ /**
+ * Notify application when the state of client subscription session
+ * associated with a buddy has changed. Application may use this
+ * callback to retrieve more detailed information about the state
+ * changed event.
+ *
+ * @param buddy_id The buddy id.
+ * @param sub Event subscription session.
+ * @param event The event which triggers state change event.
+ */
+ void (*on_buddy_evsub_state)(pjsua_buddy_id buddy_id,
+ pjsip_evsub *sub,
+ pjsip_event *event);
+
+ /**
+ * Notify application on incoming pager (i.e. MESSAGE request).
+ * Argument call_id will be -1 if MESSAGE request is not related to an
+ * existing call.
+ *
+ * See also \a on_pager2() callback for the version with \a pjsip_rx_data
+ * passed as one of the argument.
+ *
+ * @param call_id Containts the ID of the call where the IM was
+ * sent, or PJSUA_INVALID_ID if the IM was sent
+ * outside call context.
+ * @param from URI of the sender.
+ * @param to URI of the destination message.
+ * @param contact The Contact URI of the sender, if present.
+ * @param mime_type MIME type of the message.
+ * @param body The message content.
+ */
+ void (*on_pager)(pjsua_call_id call_id, const pj_str_t *from,
+ const pj_str_t *to, const pj_str_t *contact,
+ const pj_str_t *mime_type, const pj_str_t *body);
+
+ /**
+ * This is the alternative version of the \a on_pager() callback with
+ * \a pjsip_rx_data argument.
+ *
+ * @param call_id Containts the ID of the call where the IM was
+ * sent, or PJSUA_INVALID_ID if the IM was sent
+ * outside call context.
+ * @param from URI of the sender.
+ * @param to URI of the destination message.
+ * @param contact The Contact URI of the sender, if present.
+ * @param mime_type MIME type of the message.
+ * @param body The message content.
+ * @param rdata The incoming MESSAGE request.
+ * @param acc_id Account ID most suitable for this message.
+ */
+ void (*on_pager2)(pjsua_call_id call_id, const pj_str_t *from,
+ const pj_str_t *to, const pj_str_t *contact,
+ const pj_str_t *mime_type, const pj_str_t *body,
+ pjsip_rx_data *rdata, pjsua_acc_id acc_id);
+
+ /**
+ * Notify application about the delivery status of outgoing pager
+ * request. See also on_pager_status2() callback for the version with
+ * \a pjsip_rx_data in the argument list.
+ *
+ * @param call_id Containts the ID of the call where the IM was
+ * sent, or PJSUA_INVALID_ID if the IM was sent
+ * outside call context.
+ * @param to Destination URI.
+ * @param body Message body.
+ * @param user_data Arbitrary data that was specified when sending
+ * IM message.
+ * @param status Delivery status.
+ * @param reason Delivery status reason.
+ */
+ void (*on_pager_status)(pjsua_call_id call_id,
+ const pj_str_t *to,
+ const pj_str_t *body,
+ void *user_data,
+ pjsip_status_code status,
+ const pj_str_t *reason);
+
+ /**
+ * Notify application about the delivery status of outgoing pager
+ * request.
+ *
+ * @param call_id Containts the ID of the call where the IM was
+ * sent, or PJSUA_INVALID_ID if the IM was sent
+ * outside call context.
+ * @param to Destination URI.
+ * @param body Message body.
+ * @param user_data Arbitrary data that was specified when sending
+ * IM message.
+ * @param status Delivery status.
+ * @param reason Delivery status reason.
+ * @param tdata The original MESSAGE request.
+ * @param rdata The incoming MESSAGE response, or NULL if the
+ * message transaction fails because of time out
+ * or transport error.
+ * @param acc_id Account ID from this the instant message was
+ * send.
+ */
+ void (*on_pager_status2)(pjsua_call_id call_id,
+ const pj_str_t *to,
+ const pj_str_t *body,
+ void *user_data,
+ pjsip_status_code status,
+ const pj_str_t *reason,
+ pjsip_tx_data *tdata,
+ pjsip_rx_data *rdata,
+ pjsua_acc_id acc_id);
+
+ /**
+ * Notify application about typing indication.
+ *
+ * @param call_id Containts the ID of the call where the IM was
+ * sent, or PJSUA_INVALID_ID if the IM was sent
+ * outside call context.
+ * @param from URI of the sender.
+ * @param to URI of the destination message.
+ * @param contact The Contact URI of the sender, if present.
+ * @param is_typing Non-zero if peer is typing, or zero if peer
+ * has stopped typing a message.
+ */
+ void (*on_typing)(pjsua_call_id call_id, const pj_str_t *from,
+ const pj_str_t *to, const pj_str_t *contact,
+ pj_bool_t is_typing);
+
+ /**
+ * Notify application about typing indication.
+ *
+ * @param call_id Containts the ID of the call where the IM was
+ * sent, or PJSUA_INVALID_ID if the IM was sent
+ * outside call context.
+ * @param from URI of the sender.
+ * @param to URI of the destination message.
+ * @param contact The Contact URI of the sender, if present.
+ * @param is_typing Non-zero if peer is typing, or zero if peer
+ * has stopped typing a message.
+ * @param rdata The received request.
+ * @param acc_id Account ID most suitable for this message.
+ */
+ void (*on_typing2)(pjsua_call_id call_id, const pj_str_t *from,
+ const pj_str_t *to, const pj_str_t *contact,
+ pj_bool_t is_typing, pjsip_rx_data *rdata,
+ pjsua_acc_id acc_id);
+
+ /**
+ * Callback when the library has finished performing NAT type
+ * detection.
+ *
+ * @param res NAT detection result.
+ */
+ void (*on_nat_detect)(const pj_stun_nat_detect_result *res);
+
+ /**
+ * This callback is called when the call is about to resend the
+ * INVITE request to the specified target, following the previously
+ * received redirection response.
+ *
+ * Application may accept the redirection to the specified target
+ * (the default behavior if this callback is implemented), reject
+ * this target only and make the session continue to try the next
+ * target in the list if such target exists, stop the whole
+ * redirection process altogether and cause the session to be
+ * disconnected, or defer the decision to ask for user confirmation.
+ *
+ * This callback is optional. If this callback is not implemented,
+ * the default behavior is to NOT follow the redirection response.
+ *
+ * @param call_id The call ID.
+ * @param target The current target to be tried.
+ * @param e The event that caused this callback to be called.
+ * This could be the receipt of 3xx response, or
+ * 4xx/5xx response received for the INVITE sent to
+ * subsequent targets, or NULL if this callback is
+ * called from within #pjsua_call_process_redirect()
+ * context.
+ *
+ * @return Action to be performed for the target. Set this
+ * parameter to one of the value below:
+ * - PJSIP_REDIRECT_ACCEPT: immediately accept the
+ * redirection (default value). When set, the
+ * call will immediately resend INVITE request
+ * to the target.
+ * - PJSIP_REDIRECT_REJECT: immediately reject this
+ * target. The call will continue retrying with
+ * next target if present, or disconnect the call
+ * if there is no more target to try.
+ * - PJSIP_REDIRECT_STOP: stop the whole redirection
+ * process and immediately disconnect the call. The
+ * on_call_state() callback will be called with
+ * PJSIP_INV_STATE_DISCONNECTED state immediately
+ * after this callback returns.
+ * - PJSIP_REDIRECT_PENDING: set to this value if
+ * no decision can be made immediately (for example
+ * to request confirmation from user). Application
+ * then MUST call #pjsua_call_process_redirect()
+ * to either accept or reject the redirection upon
+ * getting user decision.
+ */
+ pjsip_redirect_op (*on_call_redirected)(pjsua_call_id call_id,
+ const pjsip_uri *target,
+ const pjsip_event *e);
+
+ /**
+ * This callback is called when message waiting indication subscription
+ * state has changed. Application can then query the subscription state
+ * by calling #pjsip_evsub_get_state().
+ *
+ * @param acc_id The account ID.
+ * @param evsub The subscription instance.
+ */
+ void (*on_mwi_state)(pjsua_acc_id acc_id, pjsip_evsub *evsub);
+
+ /**
+ * This callback is called when a NOTIFY request for message summary /
+ * message waiting indication is received.
+ *
+ * @param acc_id The account ID.
+ * @param mwi_info Structure containing details of the event,
+ * including the received NOTIFY request in the
+ * \a rdata field.
+ */
+ void (*on_mwi_info)(pjsua_acc_id acc_id, pjsua_mwi_info *mwi_info);
+
+ /**
+ * This callback is called when transport state is changed. See also
+ * #pjsip_tp_state_callback.
+ */
+ pjsip_tp_state_callback on_transport_state;
+
+ /**
+ * This callback is called when media transport state is changed. See
+ * also #pjsua_med_tp_state_cb.
+ */
+ pjsua_med_tp_state_cb on_call_media_transport_state;
+
+ /**
+ * This callback is called to report error in ICE media transport.
+ * Currently it is used to report TURN Refresh error.
+ *
+ * @param index Transport index.
+ * @param op Operation which trigger the failure.
+ * @param status Error status.
+ * @param param Additional info about the event. Currently this will
+ * always be set to NULL.
+ */
+ void (*on_ice_transport_error)(int index, pj_ice_strans_op op,
+ pj_status_t status, void *param);
+
+ /**
+ * Callback when the sound device is about to be opened or closed.
+ * This callback will be called even when null sound device or no
+ * sound device is configured by the application (i.e. the
+ * #pjsua_set_null_snd_dev() and #pjsua_set_no_snd_dev() APIs).
+ * This API is mostly useful when the application wants to manage
+ * the sound device by itself (i.e. with #pjsua_set_no_snd_dev()),
+ * to get notified when it should open or close the sound device.
+ *
+ * @param operation The value will be set to 0 to signal that sound
+ * device is about to be closed, and 1 to be opened.
+ *
+ * @return The callback must return PJ_SUCCESS at the moment.
+ */
+ pj_status_t (*on_snd_dev_operation)(int operation);
+
+ /**
+ * Notification about media events such as video notifications. This
+ * callback will most likely be called from media threads, thus
+ * application must not perform heavy processing in this callback.
+ * Especially, application must not destroy the call or media in this
+ * callback. If application needs to perform more complex tasks to
+ * handle the event, it should post the task to another thread.
+ *
+ * @param call_id The call id.
+ * @param med_idx The media stream index.
+ * @param event The media event.
+ */
+ void (*on_call_media_event)(pjsua_call_id call_id,
+ unsigned med_idx,
+ pjmedia_event *event);
+
+ /**
+ * This callback can be used by application to implement custom media
+ * transport adapter for the call, or to replace the media transport
+ * with something completely new altogether.
+ *
+ * This callback is called when a new call is created. The library has
+ * created a media transport for the call, and it is provided as the
+ * \a base_tp argument of this callback. Upon returning, the callback
+ * must return an instance of media transport to be used by the call.
+ *
+ * @param call_id Call ID
+ * @param media_idx The media index in the SDP for which this media
+ * transport will be used.
+ * @param base_tp The media transport which otherwise will be
+ * used by the call has this callback not been
+ * implemented.
+ * @param flags Bitmask from pjsua_create_media_transport_flag.
+ *
+ * @return The callback must return an instance of media
+ * transport to be used by the call.
+ */
+ pjmedia_transport* (*on_create_media_transport)(pjsua_call_id call_id,
+ unsigned media_idx,
+ pjmedia_transport *base_tp,
+ unsigned flags);
+
+} pjsua_callback;
+
+
+/**
+ * This enumeration specifies the usage of SIP Session Timers extension.
+ */
+typedef enum pjsua_sip_timer_use
+{
+ /**
+ * When this flag is specified, Session Timers will not be used in any
+ * session, except it is explicitly required in the remote request.
+ */
+ PJSUA_SIP_TIMER_INACTIVE,
+
+ /**
+ * When this flag is specified, Session Timers will be used in all
+ * sessions whenever remote supports and uses it.
+ */
+ PJSUA_SIP_TIMER_OPTIONAL,
+
+ /**
+ * When this flag is specified, Session Timers support will be
+ * a requirement for the remote to be able to establish a session.
+ */
+ PJSUA_SIP_TIMER_REQUIRED,
+
+ /**
+ * When this flag is specified, Session Timers will always be used
+ * in all sessions, regardless whether remote supports/uses it or not.
+ */
+ PJSUA_SIP_TIMER_ALWAYS
+
+} pjsua_sip_timer_use;
+
+
+/**
+ * This constants controls the use of 100rel extension.
+ */
+typedef enum pjsua_100rel_use
+{
+ /**
+ * Not used. For UAC, support for 100rel will be indicated in Supported
+ * header so that peer can opt to use it if it wants to. As UAS, this
+ * option will NOT cause 100rel to be used even if UAC indicates that
+ * it supports this feature.
+ */
+ PJSUA_100REL_NOT_USED,
+
+ /**
+ * Mandatory. UAC will place 100rel in Require header, and UAS will
+ * reject incoming calls unless it has 100rel in Supported header.
+ */
+ PJSUA_100REL_MANDATORY,
+
+ /**
+ * Optional. Similar to PJSUA_100REL_NOT_USED, except that as UAS, this
+ * option will cause 100rel to be used if UAC indicates that it supports it.
+ */
+ PJSUA_100REL_OPTIONAL
+
+} pjsua_100rel_use;
+
+
+/**
+ * This structure describes the settings to control the API and
+ * user agent behavior, and can be specified when calling #pjsua_init().
+ * Before setting the values, application must call #pjsua_config_default()
+ * to initialize this structure with the default values.
+ */
+typedef struct pjsua_config
+{
+
+ /**
+ * Maximum calls to support (default: 4). The value specified here
+ * must be smaller than the compile time maximum settings
+ * PJSUA_MAX_CALLS, which by default is 32. To increase this
+ * limit, the library must be recompiled with new PJSUA_MAX_CALLS
+ * value.
+ */
+ unsigned max_calls;
+
+ /**
+ * Number of worker threads. Normally application will want to have at
+ * least one worker thread, unless when it wants to poll the library
+ * periodically, which in this case the worker thread can be set to
+ * zero.
+ */
+ unsigned thread_cnt;
+
+ /**
+ * Number of nameservers. If no name server is configured, the SIP SRV
+ * resolution would be disabled, and domain will be resolved with
+ * standard pj_gethostbyname() function.
+ */
+ unsigned nameserver_count;
+
+ /**
+ * Array of nameservers to be used by the SIP resolver subsystem.
+ * The order of the name server specifies the priority (first name
+ * server will be used first, unless it is not reachable).
+ */
+ pj_str_t nameserver[4];
+
+ /**
+ * Force loose-route to be used in all route/proxy URIs (outbound_proxy
+ * and account's proxy settings). When this setting is enabled, the
+ * library will check all the route/proxy URIs specified in the settings
+ * and append ";lr" parameter to the URI if the parameter is not present.
+ *
+ * Default: 1
+ */
+ pj_bool_t force_lr;
+
+ /**
+ * Number of outbound proxies in the \a outbound_proxy array.
+ */
+ unsigned outbound_proxy_cnt;
+
+ /**
+ * Specify the URL of outbound proxies to visit for all outgoing requests.
+ * The outbound proxies will be used for all accounts, and it will
+ * be used to build the route set for outgoing requests. The final
+ * route set for outgoing requests will consists of the outbound proxies
+ * and the proxy configured in the account.
+ */
+ pj_str_t outbound_proxy[4];
+
+ /**
+ * Warning: deprecated, please use \a stun_srv field instead. To maintain
+ * backward compatibility, if \a stun_srv_cnt is zero then the value of
+ * this field will be copied to \a stun_srv field, if present.
+ *
+ * Specify domain name to be resolved with DNS SRV resolution to get the
+ * address of the STUN server. Alternatively application may specify
+ * \a stun_host instead.
+ *
+ * If DNS SRV resolution failed for this domain, then DNS A resolution
+ * will be performed only if \a stun_host is specified.
+ */
+ pj_str_t stun_domain;
+
+ /**
+ * Warning: deprecated, please use \a stun_srv field instead. To maintain
+ * backward compatibility, if \a stun_srv_cnt is zero then the value of
+ * this field will be copied to \a stun_srv field, if present.
+ *
+ * Specify STUN server to be used, in "HOST[:PORT]" format. If port is
+ * not specified, default port 3478 will be used.
+ */
+ pj_str_t stun_host;
+
+ /**
+ * Number of STUN server entries in \a stun_srv array.
+ */
+ unsigned stun_srv_cnt;
+
+ /**
+ * Array of STUN servers to try. The library will try to resolve and
+ * contact each of the STUN server entry until it finds one that is
+ * usable. Each entry may be a domain name, host name, IP address, and
+ * it may contain an optional port number. For example:
+ * - "pjsip.org" (domain name)
+ * - "sip.pjsip.org" (host name)
+ * - "pjsip.org:33478" (domain name and a non-standard port number)
+ * - "10.0.0.1:3478" (IP address and port number)
+ *
+ * When nameserver is configured in the \a pjsua_config.nameserver field,
+ * if entry is not an IP address, it will be resolved with DNS SRV
+ * resolution first, and it will fallback to use DNS A resolution if this
+ * fails. Port number may be specified even if the entry is a domain name,
+ * in case the DNS SRV resolution should fallback to a non-standard port.
+ *
+ * When nameserver is not configured, entries will be resolved with
+ * #pj_gethostbyname() if it's not an IP address. Port number may be
+ * specified if the server is not listening in standard STUN port.
+ */
+ pj_str_t stun_srv[8];
+
+ /**
+ * This specifies if the library startup should ignore failure with the
+ * STUN servers. If this is set to PJ_FALSE, the library will refuse to
+ * start if it fails to resolve or contact any of the STUN servers.
+ *
+ * Default: PJ_TRUE
+ */
+ pj_bool_t stun_ignore_failure;
+
+ /**
+ * Support for adding and parsing NAT type in the SDP to assist
+ * troubleshooting. The valid values are:
+ * - 0: no information will be added in SDP, and parsing is disabled.
+ * - 1: only the NAT type number is added.
+ * - 2: add both NAT type number and name.
+ *
+ * Default: 1
+ */
+ int nat_type_in_sdp;
+
+ /**
+ * Specify how the support for reliable provisional response (100rel/
+ * PRACK) should be used by default. Note that this setting can be
+ * further customized in account configuration (#pjsua_acc_config).
+ *
+ * Default: PJSUA_100REL_NOT_USED
+ */
+ pjsua_100rel_use require_100rel;
+
+ /**
+ * Specify the usage of Session Timers for all sessions. See the
+ * #pjsua_sip_timer_use for possible values. Note that this setting can be
+ * further customized in account configuration (#pjsua_acc_config).
+ *
+ * Default: PJSUA_SIP_TIMER_OPTIONAL
+ */
+ pjsua_sip_timer_use use_timer;
+
+ /**
+ * Handle unsolicited NOTIFY requests containing message waiting
+ * indication (MWI) info. Unsolicited MWI is incoming NOTIFY requests
+ * which are not requested by client with SUBSCRIBE request.
+ *
+ * If this is enabled, the library will respond 200/OK to the NOTIFY
+ * request and forward the request to \a on_mwi_info() callback.
+ *
+ * See also \a mwi_enabled field #on pjsua_acc_config.
+ *
+ * Default: PJ_TRUE
+ *
+ */
+ pj_bool_t enable_unsolicited_mwi;
+
+ /**
+ * Specify Session Timer settings, see #pjsip_timer_setting.
+ * Note that this setting can be further customized in account
+ * configuration (#pjsua_acc_config).
+ */
+ pjsip_timer_setting timer_setting;
+
+ /**
+ * Number of credentials in the credential array.
+ */
+ unsigned cred_count;
+
+ /**
+ * Array of credentials. These credentials will be used by all accounts,
+ * and can be used to authenticate against outbound proxies. If the
+ * credential is specific to the account, then application should set
+ * the credential in the pjsua_acc_config rather than the credential
+ * here.
+ */
+ pjsip_cred_info cred_info[PJSUA_ACC_MAX_PROXIES];
+
+ /**
+ * Application callback to receive various event notifications from
+ * the library.
+ */
+ pjsua_callback cb;
+
+ /**
+ * Optional user agent string (default empty). If it's empty, no
+ * User-Agent header will be sent with outgoing requests.
+ */
+ pj_str_t user_agent;
+
+ /**
+ * Specify default value of secure media transport usage.
+ * Valid values are PJMEDIA_SRTP_DISABLED, PJMEDIA_SRTP_OPTIONAL, and
+ * PJMEDIA_SRTP_MANDATORY.
+ *
+ * Note that this setting can be further customized in account
+ * configuration (#pjsua_acc_config).
+ *
+ * Default: #PJSUA_DEFAULT_USE_SRTP
+ */
+ pjmedia_srtp_use use_srtp;
+
+ /**
+ * Specify whether SRTP requires secure signaling to be used. This option
+ * is only used when \a use_srtp option above is non-zero.
+ *
+ * Valid values are:
+ * 0: SRTP does not require secure signaling
+ * 1: SRTP requires secure transport such as TLS
+ * 2: SRTP requires secure end-to-end transport (SIPS)
+ *
+ * Note that this setting can be further customized in account
+ * configuration (#pjsua_acc_config).
+ *
+ * Default: #PJSUA_DEFAULT_SRTP_SECURE_SIGNALING
+ */
+ int srtp_secure_signaling;
+
+ /**
+ * This setting has been deprecated and will be ignored.
+ */
+ pj_bool_t srtp_optional_dup_offer;
+
+ /**
+ * Disconnect other call legs when more than one 2xx responses for
+ * outgoing INVITE are received due to forking. Currently the library
+ * is not able to handle simultaneous forked media, so disconnecting
+ * the other call legs is necessary.
+ *
+ * With this setting enabled, the library will handle only one of the
+ * connected call leg, and the other connected call legs will be
+ * disconnected.
+ *
+ * Default: PJ_TRUE (only disable this setting for testing purposes).
+ */
+ pj_bool_t hangup_forked_call;
+
+} pjsua_config;
+
+
+/**
+ * Flags to be given to pjsua_destroy2()
+ */
+typedef enum pjsua_destroy_flag
+{
+ /**
+ * Allow sending outgoing messages (such as unregistration, event
+ * unpublication, BYEs, unsubscription, etc.), but do not wait for
+ * responses. This is useful to perform "best effort" clean up
+ * without delaying the shutdown process waiting for responses.
+ */
+ PJSUA_DESTROY_NO_RX_MSG = 1,
+
+ /**
+ * If this flag is set, do not send any outgoing messages at all.
+ * This flag is useful if application knows that the network which
+ * the messages are to be sent on is currently down.
+ */
+ PJSUA_DESTROY_NO_TX_MSG = 2,
+
+ /**
+ * Do not send or receive messages during destroy. This flag is
+ * shorthand for PJSUA_DESTROY_NO_RX_MSG + PJSUA_DESTROY_NO_TX_MSG.
+ */
+ PJSUA_DESTROY_NO_NETWORK = PJSUA_DESTROY_NO_RX_MSG |
+ PJSUA_DESTROY_NO_TX_MSG
+
+} pjsua_destroy_flag;
+
+/**
+ * Use this function to initialize pjsua config.
+ *
+ * @param cfg pjsua config to be initialized.
+ */
+PJ_DECL(void) pjsua_config_default(pjsua_config *cfg);
+
+
+/** The implementation has been moved to sip_auth.h */
+#define pjsip_cred_dup pjsip_cred_info_dup
+
+
+/**
+ * Duplicate pjsua_config.
+ *
+ * @param pool The pool to get memory from.
+ * @param dst Destination config.
+ * @param src Source config.
+ */
+PJ_DECL(void) pjsua_config_dup(pj_pool_t *pool,
+ pjsua_config *dst,
+ const pjsua_config *src);
+
+
+/**
+ * This structure describes additional information to be sent with
+ * outgoing SIP message. It can (optionally) be specified for example
+ * with #pjsua_call_make_call(), #pjsua_call_answer(), #pjsua_call_hangup(),
+ * #pjsua_call_set_hold(), #pjsua_call_send_im(), and many more.
+ *
+ * Application MUST call #pjsua_msg_data_init() to initialize this
+ * structure before setting its values.
+ */
+struct pjsua_msg_data
+{
+ /**
+ * Additional message headers as linked list. Application can add
+ * headers to the list by creating the header, either from the heap/pool
+ * or from temporary local variable, and add the header using
+ * linked list operation. See pjsua_app.c for some sample codes.
+ */
+ pjsip_hdr hdr_list;
+
+ /**
+ * MIME type of optional message body.
+ */
+ pj_str_t content_type;
+
+ /**
+ * Optional message body to be added to the message, only when the
+ * message doesn't have a body.
+ */
+ pj_str_t msg_body;
+
+ /**
+ * Content type of the multipart body. If application wants to send
+ * multipart message bodies, it puts the parts in \a parts and set
+ * the content type in \a multipart_ctype. If the message already
+ * contains a body, the body will be added to the multipart bodies.
+ */
+ pjsip_media_type multipart_ctype;
+
+ /**
+ * List of multipart parts. If application wants to send multipart
+ * message bodies, it puts the parts in \a parts and set the content
+ * type in \a multipart_ctype. If the message already contains a body,
+ * the body will be added to the multipart bodies.
+ */
+ pjsip_multipart_part multipart_parts;
+};
+
+
+/**
+ * Initialize message data.
+ *
+ * @param msg_data Message data to be initialized.
+ */
+PJ_DECL(void) pjsua_msg_data_init(pjsua_msg_data *msg_data);
+
+
+/**
+ * Clone message data.
+ *
+ * @param pool Pool to allocate memory for the new message data.
+ * @param rhs Message data to be cloned.
+ *
+ * @return The new message data.
+ */
+PJ_DECL(pjsua_msg_data*) pjsua_msg_data_clone(pj_pool_t *pool,
+ const pjsua_msg_data *rhs);
+
+
+/**
+ * Instantiate pjsua application. Application must call this function before
+ * calling any other functions, to make sure that the underlying libraries
+ * are properly initialized. Once this function has returned success,
+ * application must call pjsua_destroy() before quitting.
+ *
+ * @return PJ_SUCCESS on success, or the appropriate error code.
+ */
+PJ_DECL(pj_status_t) pjsua_create(void);
+
+
+/** Forward declaration */
+typedef struct pjsua_media_config pjsua_media_config;
+
+
+/**
+ * Initialize pjsua with the specified settings. All the settings are
+ * optional, and the default values will be used when the config is not
+ * specified.
+ *
+ * Note that #pjsua_create() MUST be called before calling this function.
+ *
+ * @param ua_cfg User agent configuration.
+ * @param log_cfg Optional logging configuration.
+ * @param media_cfg Optional media configuration.
+ *
+ * @return PJ_SUCCESS on success, or the appropriate error code.
+ */
+PJ_DECL(pj_status_t) pjsua_init(const pjsua_config *ua_cfg,
+ const pjsua_logging_config *log_cfg,
+ const pjsua_media_config *media_cfg);
+
+
+/**
+ * Application is recommended to call this function after all initialization
+ * is done, so that the library can do additional checking set up
+ * additional
+ *
+ * Application may call this function anytime after #pjsua_init().
+ *
+ * @return PJ_SUCCESS on success, or the appropriate error code.
+ */
+PJ_DECL(pj_status_t) pjsua_start(void);
+
+
+/**
+ * Destroy pjsua. Application is recommended to perform graceful shutdown
+ * before calling this function (such as unregister the account from the SIP
+ * server, terminate presense subscription, and hangup active calls), however,
+ * this function will do all of these if it finds there are active sessions
+ * that need to be terminated. This function will approximately block for
+ * one second to wait for replies from remote.
+ *
+ * Application.may safely call this function more than once if it doesn't
+ * keep track of it's state.
+ *
+ * @see pjsua_destroy2()
+ *
+ * @return PJ_SUCCESS on success, or the appropriate error code.
+ */
+PJ_DECL(pj_status_t) pjsua_destroy(void);
+
+
+/**
+ * Retrieve pjsua state.
+ *
+ * @return pjsua state.
+ */
+PJ_DECL(pjsua_state) pjsua_get_state(void);
+
+
+/**
+ * Variant of destroy with additional flags.
+ *
+ * @param flags Combination of pjsua_destroy_flag enumeration.
+ *
+ * @return PJ_SUCCESS on success, or the appropriate error code.
+ */
+PJ_DECL(pj_status_t) pjsua_destroy2(unsigned flags);
+
+
+/**
+ * Poll pjsua for events, and if necessary block the caller thread for
+ * the specified maximum interval (in miliseconds).
+ *
+ * Application doesn't normally need to call this function if it has
+ * configured worker thread (\a thread_cnt field) in pjsua_config structure,
+ * because polling then will be done by these worker threads instead.
+ *
+ * @param msec_timeout Maximum time to wait, in miliseconds.
+ *
+ * @return The number of events that have been handled during the
+ * poll. Negative value indicates error, and application
+ * can retrieve the error as (status = -return_value).
+ */
+PJ_DECL(int) pjsua_handle_events(unsigned msec_timeout);
+
+
+/**
+ * Create memory pool to be used by the application. Once application
+ * finished using the pool, it must be released with pj_pool_release().
+ *
+ * @param name Optional pool name.
+ * @param init_size Initial size of the pool.
+ * @param increment Increment size.
+ *
+ * @return The pool, or NULL when there's no memory.
+ */
+PJ_DECL(pj_pool_t*) pjsua_pool_create(const char *name, pj_size_t init_size,
+ pj_size_t increment);
+
+
+/**
+ * Application can call this function at any time (after pjsua_create(), of
+ * course) to change logging settings.
+ *
+ * @param c Logging configuration.
+ *
+ * @return PJ_SUCCESS on success, or the appropriate error code.
+ */
+PJ_DECL(pj_status_t) pjsua_reconfigure_logging(const pjsua_logging_config *c);
+
+
+/**
+ * Internal function to get SIP endpoint instance of pjsua, which is
+ * needed for example to register module, create transports, etc.
+ * Only valid after #pjsua_init() is called.
+ *
+ * @return SIP endpoint instance.
+ */
+PJ_DECL(pjsip_endpoint*) pjsua_get_pjsip_endpt(void);
+
+/**
+ * Internal function to get media endpoint instance.
+ * Only valid after #pjsua_init() is called.
+ *
+ * @return Media endpoint instance.
+ */
+PJ_DECL(pjmedia_endpt*) pjsua_get_pjmedia_endpt(void);
+
+/**
+ * Internal function to get PJSUA pool factory.
+ * Only valid after #pjsua_create() is called.
+ *
+ * @return Pool factory currently used by PJSUA.
+ */
+PJ_DECL(pj_pool_factory*) pjsua_get_pool_factory(void);
+
+
+
+/*****************************************************************************
+ * Utilities.
+ *
+ */
+
+/**
+ * This structure is used to represent the result of the STUN server
+ * resolution and testing, the #pjsua_resolve_stun_servers() function.
+ * This structure will be passed in #pj_stun_resolve_cb callback.
+ */
+typedef struct pj_stun_resolve_result
+{
+ /**
+ * Arbitrary data that was passed to #pjsua_resolve_stun_servers()
+ * function.
+ */
+ void *token;
+
+ /**
+ * This will contain PJ_SUCCESS if at least one usable STUN server
+ * is found, otherwise it will contain the last error code during
+ * the operation.
+ */
+ pj_status_t status;
+
+ /**
+ * The server name that yields successful result. This will only
+ * contain value if status is successful.
+ */
+ pj_str_t name;
+
+ /**
+ * The server IP address. This will only contain value if status
+ * is successful.
+ */
+ pj_sockaddr addr;
+
+} pj_stun_resolve_result;
+
+
+/**
+ * Typedef of callback to be registered to #pjsua_resolve_stun_servers().
+ */
+typedef void (*pj_stun_resolve_cb)(const pj_stun_resolve_result *result);
+
+/**
+ * This is a utility function to detect NAT type in front of this
+ * endpoint. Once invoked successfully, this function will complete
+ * asynchronously and report the result in \a on_nat_detect() callback
+ * of pjsua_callback.
+ *
+ * After NAT has been detected and the callback is called, application can
+ * get the detected NAT type by calling #pjsua_get_nat_type(). Application
+ * can also perform NAT detection by calling #pjsua_detect_nat_type()
+ * again at later time.
+ *
+ * Note that STUN must be enabled to run this function successfully.
+ *
+ * @return PJ_SUCCESS on success, or the appropriate error code.
+ */
+PJ_DECL(pj_status_t) pjsua_detect_nat_type(void);
+
+
+/**
+ * Get the NAT type as detected by #pjsua_detect_nat_type() function.
+ * This function will only return useful NAT type after #pjsua_detect_nat_type()
+ * has completed successfully and \a on_nat_detect() callback has been called.
+ *
+ * @param type NAT type.
+ *
+ * @return When detection is in progress, this function will
+ * return PJ_EPENDING and \a type will be set to
+ * PJ_STUN_NAT_TYPE_UNKNOWN. After NAT type has been
+ * detected successfully, this function will return
+ * PJ_SUCCESS and \a type will be set to the correct
+ * value. Other return values indicate error and
+ * \a type will be set to PJ_STUN_NAT_TYPE_ERR_UNKNOWN.
+ *
+ * @see pjsua_call_get_rem_nat_type()
+ */
+PJ_DECL(pj_status_t) pjsua_get_nat_type(pj_stun_nat_type *type);
+
+
+/**
+ * Auxiliary function to resolve and contact each of the STUN server
+ * entries (sequentially) to find which is usable. The #pjsua_init() must
+ * have been called before calling this function.
+ *
+ * @param count Number of STUN server entries to try.
+ * @param srv Array of STUN server entries to try. Please see
+ * the \a stun_srv field in the #pjsua_config
+ * documentation about the format of this entry.
+ * @param wait Specify non-zero to make the function block until
+ * it gets the result. In this case, the function
+ * will block while the resolution is being done,
+ * and the callback will be called before this function
+ * returns.
+ * @param token Arbitrary token to be passed back to application
+ * in the callback.
+ * @param cb Callback to be called to notify the result of
+ * the function.
+ *
+ * @return If \a wait parameter is non-zero, this will return
+ * PJ_SUCCESS if one usable STUN server is found.
+ * Otherwise it will always return PJ_SUCCESS, and
+ * application will be notified about the result in
+ * the callback.
+ */
+PJ_DECL(pj_status_t) pjsua_resolve_stun_servers(unsigned count,
+ pj_str_t srv[],
+ pj_bool_t wait,
+ void *token,
+ pj_stun_resolve_cb cb);
+
+/**
+ * Cancel pending STUN resolution which match the specified token.
+ *
+ * @param token The token to match. This token was given to
+ * #pjsua_resolve_stun_servers()
+ * @param notify_cb Boolean to control whether the callback should
+ * be called for cancelled resolutions. When the
+ * callback is called, the status in the result
+ * will be set as PJ_ECANCELLED.
+ *
+ * @return PJ_SUCCESS if there is at least one pending STUN
+ * resolution cancelled, or PJ_ENOTFOUND if there is
+ * no matching one, or other error.
+ */
+PJ_DECL(pj_status_t) pjsua_cancel_stun_resolution(void *token,
+ pj_bool_t notify_cb);
+
+
+/**
+ * This is a utility function to verify that valid SIP url is given. If the
+ * URL is a valid SIP/SIPS scheme, PJ_SUCCESS will be returned.
+ *
+ * @param url The URL, as NULL terminated string.
+ *
+ * @return PJ_SUCCESS on success, or the appropriate error code.
+ *
+ * @see pjsua_verify_url()
+ */
+PJ_DECL(pj_status_t) pjsua_verify_sip_url(const char *url);
+
+
+/**
+ * This is a utility function to verify that valid URI is given. Unlike
+ * pjsua_verify_sip_url(), this function will return PJ_SUCCESS if tel: URI
+ * is given.
+ *
+ * @param url The URL, as NULL terminated string.
+ *
+ * @return PJ_SUCCESS on success, or the appropriate error code.
+ *
+ * @see pjsua_verify_sip_url()
+ */
+PJ_DECL(pj_status_t) pjsua_verify_url(const char *url);
+
+
+/**
+ * Schedule a timer entry. Note that the timer callback may be executed
+ * by different thread, depending on whether worker thread is enabled or
+ * not.
+ *
+ * @param entry Timer heap entry.
+ * @param delay The interval to expire.
+ *
+ * @return PJ_SUCCESS on success, or the appropriate error code.
+ *
+ * @see pjsip_endpt_schedule_timer()
+ */
+#if PJ_TIMER_DEBUG
+#define pjsua_schedule_timer(e,d) pjsua_schedule_timer_dbg(e,d,\
+ __FILE__,__LINE__)
+
+PJ_DECL(pj_status_t) pjsua_schedule_timer_dbg(pj_timer_entry *entry,
+ const pj_time_val *delay,
+ const char *src_file,
+ int src_line);
+#else
+PJ_DECL(pj_status_t) pjsua_schedule_timer(pj_timer_entry *entry,
+ const pj_time_val *delay);
+#endif
+
+/**
+ * Schedule a callback function to be called after a specified time interval.
+ * Note that the callback may be executed by different thread, depending on
+ * whether worker thread is enabled or not.
+ *
+ * @param cb The callback function.
+ * @param user_data The user data.
+ * @param msec_delay The time interval in msec.
+ *
+ * @return PJ_SUCCESS on success, or the appropriate error code.
+ */
+#if PJ_TIMER_DEBUG
+#define pjsua_schedule_timer2(cb,u,d) \
+ pjsua_schedule_timer2_dbg(cb,u,d,__FILE__,__LINE__)
+
+PJ_DECL(pj_status_t) pjsua_schedule_timer2_dbg(void (*cb)(void *user_data),
+ void *user_data,
+ unsigned msec_delay,
+ const char *src_file,
+ int src_line);
+#else
+PJ_DECL(pj_status_t) pjsua_schedule_timer2(void (*cb)(void *user_data),
+ void *user_data,
+ unsigned msec_delay);
+#endif
+
+/**
+ * Cancel the previously scheduled timer.
+ *
+ * @param entry Timer heap entry.
+ *
+ * @see pjsip_endpt_cancel_timer()
+ */
+PJ_DECL(void) pjsua_cancel_timer(pj_timer_entry *entry);
+
+
+/**
+ * This is a utility function to display error message for the specified
+ * error code. The error message will be sent to the log.
+ *
+ * @param sender The log sender field.
+ * @param title Message title for the error.
+ * @param status Status code.
+ */
+PJ_DECL(void) pjsua_perror(const char *sender, const char *title,
+ pj_status_t status);
+
+
+/**
+ * This is a utility function to dump the stack states to log, using
+ * verbosity level 3.
+ *
+ * @param detail Will print detailed output (such as list of
+ * SIP transactions) when non-zero.
+ */
+PJ_DECL(void) pjsua_dump(pj_bool_t detail);
+
+/**
+ * @}
+ */
+
+
+
+/*****************************************************************************
+ * TRANSPORT API
+ */
+
+/**
+ * @defgroup PJSUA_LIB_TRANSPORT PJSUA-API Signaling Transport
+ * @ingroup PJSUA_LIB
+ * @brief API for managing SIP transports
+ * @{
+ *
+ * PJSUA-API supports creating multiple transport instances, for example UDP,
+ * TCP, and TLS transport. SIP transport must be created before adding an
+ * account.
+ */
+
+
+/** SIP transport identification.
+ */
+typedef int pjsua_transport_id;
+
+
+/**
+ * Transport configuration for creating transports for both SIP
+ * and media. Before setting some values to this structure, application
+ * MUST call #pjsua_transport_config_default() to initialize its
+ * values with default settings.
+ */
+typedef struct pjsua_transport_config
+{
+ /**
+ * UDP port number to bind locally. This setting MUST be specified
+ * even when default port is desired. If the value is zero, the
+ * transport will be bound to any available port, and application
+ * can query the port by querying the transport info.
+ */
+ unsigned port;
+
+ /**
+ * Optional address to advertise as the address of this transport.
+ * Application can specify any address or hostname for this field,
+ * for example it can point to one of the interface address in the
+ * system, or it can point to the public address of a NAT router
+ * where port mappings have been configured for the application.
+ *
+ * Note: this option can be used for both UDP and TCP as well!
+ */
+ pj_str_t public_addr;
+
+ /**
+ * Optional address where the socket should be bound to. This option
+ * SHOULD only be used to selectively bind the socket to particular
+ * interface (instead of 0.0.0.0), and SHOULD NOT be used to set the
+ * published address of a transport (the public_addr field should be
+ * used for that purpose).
+ *
+ * Note that unlike public_addr field, the address (or hostname) here
+ * MUST correspond to the actual interface address in the host, since
+ * this address will be specified as bind() argument.
+ */
+ pj_str_t bound_addr;
+
+ /**
+ * This specifies TLS settings for TLS transport. It is only be used
+ * when this transport config is being used to create a SIP TLS
+ * transport.
+ */
+ pjsip_tls_setting tls_setting;
+
+ /**
+ * QoS traffic type to be set on this transport. When application wants
+ * to apply QoS tagging to the transport, it's preferable to set this
+ * field rather than \a qos_param fields since this is more portable.
+ *
+ * Default is QoS not set.
+ */
+ pj_qos_type qos_type;
+
+ /**
+ * Set the low level QoS parameters to the transport. This is a lower
+ * level operation than setting the \a qos_type field and may not be
+ * supported on all platforms.
+ *
+ * Default is QoS not set.
+ */
+ pj_qos_params qos_params;
+
+} pjsua_transport_config;
+
+
+/**
+ * Call this function to initialize UDP config with default values.
+ *
+ * @param cfg The UDP config to be initialized.
+ */
+PJ_DECL(void) pjsua_transport_config_default(pjsua_transport_config *cfg);
+
+
+/**
+ * Duplicate transport config.
+ *
+ * @param pool The pool.
+ * @param dst The destination config.
+ * @param src The source config.
+ */
+PJ_DECL(void) pjsua_transport_config_dup(pj_pool_t *pool,
+ pjsua_transport_config *dst,
+ const pjsua_transport_config *src);
+
+
+/**
+ * This structure describes transport information returned by
+ * #pjsua_transport_get_info() function.
+ */
+typedef struct pjsua_transport_info
+{
+ /**
+ * PJSUA transport identification.
+ */
+ pjsua_transport_id id;
+
+ /**
+ * Transport type.
+ */
+ pjsip_transport_type_e type;
+
+ /**
+ * Transport type name.
+ */
+ pj_str_t type_name;
+
+ /**
+ * Transport string info/description.
+ */
+ pj_str_t info;
+
+ /**
+ * Transport flag (see ##pjsip_transport_flags_e).
+ */
+ unsigned flag;
+
+ /**
+ * Local address length.
+ */
+ unsigned addr_len;
+
+ /**
+ * Local/bound address.
+ */
+ pj_sockaddr local_addr;
+
+ /**
+ * Published address (or transport address name).
+ */
+ pjsip_host_port local_name;
+
+ /**
+ * Current number of objects currently referencing this transport.
+ */
+ unsigned usage_count;
+
+
+} pjsua_transport_info;
+
+
+/**
+ * Create and start a new SIP transport according to the specified
+ * settings.
+ *
+ * @param type Transport type.
+ * @param cfg Transport configuration.
+ * @param p_id Optional pointer to receive transport ID.
+ *
+ * @return PJ_SUCCESS on success, or the appropriate error code.
+ */
+PJ_DECL(pj_status_t) pjsua_transport_create(pjsip_transport_type_e type,
+ const pjsua_transport_config *cfg,
+ pjsua_transport_id *p_id);
+
+/**
+ * Register transport that has been created by application. This function
+ * is useful if application wants to implement custom SIP transport and use
+ * it with pjsua.
+ *
+ * @param tp Transport instance.
+ * @param p_id Optional pointer to receive transport ID.
+ *
+ * @return PJ_SUCCESS on success, or the appropriate error code.
+ */
+PJ_DECL(pj_status_t) pjsua_transport_register(pjsip_transport *tp,
+ pjsua_transport_id *p_id);
+
+
+/**
+ * Enumerate all transports currently created in the system. This function
+ * will return all transport IDs, and application may then call
+ * #pjsua_transport_get_info() function to retrieve detailed information
+ * about the transport.
+ *
+ * @param id Array to receive transport ids.
+ * @param count In input, specifies the maximum number of elements.
+ * On return, it contains the actual number of elements.
+ *
+ * @return PJ_SUCCESS on success, or the appropriate error code.
+ */
+PJ_DECL(pj_status_t) pjsua_enum_transports( pjsua_transport_id id[],
+ unsigned *count );
+
+
+/**
+ * Get information about transports.
+ *
+ * @param id Transport ID.
+ * @param info Pointer to receive transport info.
+ *
+ * @return PJ_SUCCESS on success, or the appropriate error code.
+ */
+PJ_DECL(pj_status_t) pjsua_transport_get_info(pjsua_transport_id id,
+ pjsua_transport_info *info);
+
+
+/**
+ * Disable a transport or re-enable it. By default transport is always
+ * enabled after it is created. Disabling a transport does not necessarily
+ * close the socket, it will only discard incoming messages and prevent
+ * the transport from being used to send outgoing messages.
+ *
+ * @param id Transport ID.
+ * @param enabled Non-zero to enable, zero to disable.
+ *
+ * @return PJ_SUCCESS on success, or the appropriate error code.
+ */
+PJ_DECL(pj_status_t) pjsua_transport_set_enable(pjsua_transport_id id,
+ pj_bool_t enabled);
+
+
+/**
+ * Close the transport. If transport is forcefully closed, it will be
+ * immediately closed, and any pending transactions that are using the
+ * transport may not terminate properly (it may even crash). Otherwise,
+ * the system will wait until all transactions are closed while preventing
+ * new users from using the transport, and will close the transport when
+ * it is safe to do so.
+ *
+ * @param id Transport ID.
+ * @param force Non-zero to immediately close the transport. This
+ * is not recommended!
+ *
+ * @return PJ_SUCCESS on success, or the appropriate error code.
+ */
+PJ_DECL(pj_status_t) pjsua_transport_close( pjsua_transport_id id,
+ pj_bool_t force );
+
+/**
+ * @}
+ */
+
+
+
+
+/*****************************************************************************
+ * ACCOUNT API
+ */
+
+
+/**
+ * @defgroup PJSUA_LIB_ACC PJSUA-API Accounts Management
+ * @ingroup PJSUA_LIB
+ * @brief PJSUA Accounts management
+ * @{
+ *
+ * PJSUA accounts provide identity (or identities) of the user who is currently
+ * using the application. In SIP terms, the identity is used as the <b>From</b>
+ * header in outgoing requests.
+ *
+ * PJSUA-API supports creating and managing multiple accounts. The maximum
+ * number of accounts is limited by a compile time constant
+ * <tt>PJSUA_MAX_ACC</tt>.
+ *
+ * Account may or may not have client registration associated with it.
+ * An account is also associated with <b>route set</b> and some <b>authentication
+ * credentials</b>, which are used when sending SIP request messages using the
+ * account. An account also has presence's <b>online status</b>, which
+ * will be reported to remote peer when they subscribe to the account's
+ * presence, or which is published to a presence server if presence
+ * publication is enabled for the account.
+ *
+ * At least one account MUST be created in the application. If no user
+ * association is required, application can create a userless account by
+ * calling #pjsua_acc_add_local(). A userless account identifies local endpoint
+ * instead of a particular user, and it correspond with a particular
+ * transport instance.
+ *
+ * Also one account must be set as the <b>default account</b>, which is used as
+ * the account to use when PJSUA fails to match a request with any other
+ * accounts.
+ *
+ * When sending outgoing SIP requests (such as making calls or sending
+ * instant messages), normally PJSUA requires the application to specify
+ * which account to use for the request. If no account is specified,
+ * PJSUA may be able to select the account by matching the destination
+ * domain name, and fall back to default account when no match is found.
+ */
+
+/**
+ * Maximum accounts.
+ */
+#ifndef PJSUA_MAX_ACC
+# define PJSUA_MAX_ACC 8
+#endif
+
+
+/**
+ * Default registration interval.
+ */
+#ifndef PJSUA_REG_INTERVAL
+# define PJSUA_REG_INTERVAL 300
+#endif
+
+
+/**
+ * Default maximum time to wait for account unregistration transactions to
+ * complete during library shutdown sequence.
+ *
+ * Default: 4000 (4 seconds)
+ */
+#ifndef PJSUA_UNREG_TIMEOUT
+# define PJSUA_UNREG_TIMEOUT 4000
+#endif
+
+
+/**
+ * Default PUBLISH expiration
+ */
+#ifndef PJSUA_PUBLISH_EXPIRATION
+# define PJSUA_PUBLISH_EXPIRATION PJSIP_PUBC_EXPIRATION_NOT_SPECIFIED
+#endif
+
+
+/**
+ * Default account priority.
+ */
+#ifndef PJSUA_DEFAULT_ACC_PRIORITY
+# define PJSUA_DEFAULT_ACC_PRIORITY 0
+#endif
+
+
+/**
+ * This macro specifies the URI scheme to use in Contact header
+ * when secure transport such as TLS is used. Application can specify
+ * either "sip" or "sips".
+ */
+#ifndef PJSUA_SECURE_SCHEME
+# define PJSUA_SECURE_SCHEME "sip"
+#endif
+
+
+/**
+ * Maximum time to wait for unpublication transaction(s) to complete
+ * during shutdown process, before sending unregistration. The library
+ * tries to wait for the unpublication (un-PUBLISH) to complete before
+ * sending REGISTER request to unregister the account, during library
+ * shutdown process. If the value is set too short, it is possible that
+ * the unregistration is sent before unpublication completes, causing
+ * unpublication request to fail.
+ *
+ * Default: 2000 (2 seconds)
+ */
+#ifndef PJSUA_UNPUBLISH_MAX_WAIT_TIME_MSEC
+# define PJSUA_UNPUBLISH_MAX_WAIT_TIME_MSEC 2000
+#endif
+
+
+/**
+ * Default auto retry re-registration interval, in seconds. Set to 0
+ * to disable this. Application can set the timer on per account basis
+ * by setting the pjsua_acc_config.reg_retry_interval field instead.
+ *
+ * Default: 300 (5 minutes)
+ */
+#ifndef PJSUA_REG_RETRY_INTERVAL
+# define PJSUA_REG_RETRY_INTERVAL 300
+#endif
+
+
+/**
+ * This macro specifies the default value for \a contact_rewrite_method
+ * field in pjsua_acc_config. I specifies how Contact update will be
+ * done with the registration, if \a allow_contact_rewrite is enabled in
+ * the account config.
+ *
+ * If set to 1, the Contact update will be done by sending unregistration
+ * to the currently registered Contact, while simultaneously sending new
+ * registration (with different Call-ID) for the updated Contact.
+ *
+ * If set to 2, the Contact update will be done in a single, current
+ * registration session, by removing the current binding (by setting its
+ * Contact's expires parameter to zero) and adding a new Contact binding,
+ * all done in a single request.
+ *
+ * Value 1 is the legacy behavior.
+ *
+ * Default value: 2
+ */
+#ifndef PJSUA_CONTACT_REWRITE_METHOD
+# define PJSUA_CONTACT_REWRITE_METHOD 2
+#endif
+
+
+/**
+ * Bit value used in pjsua_acc_config.reg_use_proxy field to indicate that
+ * the global outbound proxy list should be added to the REGISTER request.
+ */
+#define PJSUA_REG_USE_OUTBOUND_PROXY 1
+
+
+/**
+ * Bit value used in pjsua_acc_config.reg_use_proxy field to indicate that
+ * the account proxy list should be added to the REGISTER request.
+ */
+#define PJSUA_REG_USE_ACC_PROXY 2
+
+
+/**
+ * This enumeration specifies how we should offer call hold request to
+ * remote peer. The default value is set by compile time constant
+ * PJSUA_CALL_HOLD_TYPE_DEFAULT, and application may control the setting
+ * on per-account basis by manipulating \a call_hold_type field in
+ * #pjsua_acc_config.
+ */
+typedef enum pjsua_call_hold_type
+{
+ /**
+ * This will follow RFC 3264 recommendation to use a=sendonly,
+ * a=recvonly, and a=inactive attribute as means to signal call
+ * hold status. This is the correct value to use.
+ */
+ PJSUA_CALL_HOLD_TYPE_RFC3264,
+
+ /**
+ * This will use the old and deprecated method as specified in RFC 2543,
+ * and will offer c=0.0.0.0 in the SDP instead. Using this has many
+ * drawbacks such as inability to keep the media transport alive while
+ * the call is being put on hold, and should only be used if remote
+ * does not understand RFC 3264 style call hold offer.
+ */
+ PJSUA_CALL_HOLD_TYPE_RFC2543
+
+} pjsua_call_hold_type;
+
+
+/**
+ * Specify the default call hold type to be used in #pjsua_acc_config.
+ *
+ * Default is PJSUA_CALL_HOLD_TYPE_RFC3264, and there's no reason to change
+ * this except if you're communicating with an old/non-standard peer.
+ */
+#ifndef PJSUA_CALL_HOLD_TYPE_DEFAULT
+# define PJSUA_CALL_HOLD_TYPE_DEFAULT PJSUA_CALL_HOLD_TYPE_RFC3264
+#endif
+
+/**
+ * This structure describes account configuration to be specified when
+ * adding a new account with #pjsua_acc_add(). Application MUST initialize
+ * this structure first by calling #pjsua_acc_config_default().
+ */
+typedef struct pjsua_acc_config
+{
+ /**
+ * Arbitrary user data to be associated with the newly created account.
+ * Application may set this later with #pjsua_acc_set_user_data() and
+ * retrieve it with #pjsua_acc_get_user_data().
+ */
+ void *user_data;
+
+ /**
+ * Account priority, which is used to control the order of matching
+ * incoming/outgoing requests. The higher the number means the higher
+ * the priority is, and the account will be matched first.
+ */
+ int priority;
+
+ /**
+ * The full SIP URL for the account. The value can take name address or
+ * URL format, and will look something like "sip:account@serviceprovider".
+ *
+ * This field is mandatory.
+ */
+ pj_str_t id;
+
+ /**
+ * This is the URL to be put in the request URI for the registration,
+ * and will look something like "sip:serviceprovider".
+ *
+ * This field should be specified if registration is desired. If the
+ * value is empty, no account registration will be performed.
+ */
+ pj_str_t reg_uri;
+
+ /**
+ * The optional custom SIP headers to be put in the registration
+ * request.
+ */
+ pjsip_hdr reg_hdr_list;
+
+ /**
+ * The optional custom SIP headers to be put in the presence
+ * subscription request.
+ */
+ pjsip_hdr sub_hdr_list;
+
+ /**
+ * Subscribe to message waiting indication events (RFC 3842).
+ *
+ * See also \a enable_unsolicited_mwi field on #pjsua_config.
+ *
+ * Default: no
+ */
+ pj_bool_t mwi_enabled;
+
+ /**
+ * Specify the default expiration time for Message Waiting Indication
+ * (RFC 3842) event subscription. This must not be zero.
+ *
+ * Default: PJSIP_MWI_DEFAULT_EXPIRES
+ */
+ unsigned mwi_expires;
+
+ /**
+ * If this flag is set, the presence information of this account will
+ * be PUBLISH-ed to the server where the account belongs.
+ *
+ * Default: PJ_FALSE
+ */
+ pj_bool_t publish_enabled;
+
+ /**
+ * Event publication options.
+ */
+ pjsip_publishc_opt publish_opt;
+
+ /**
+ * Maximum time to wait for unpublication transaction(s) to complete
+ * during shutdown process, before sending unregistration. The library
+ * tries to wait for the unpublication (un-PUBLISH) to complete before
+ * sending REGISTER request to unregister the account, during library
+ * shutdown process. If the value is set too short, it is possible that
+ * the unregistration is sent before unpublication completes, causing
+ * unpublication request to fail.
+ *
+ * Default: PJSUA_UNPUBLISH_MAX_WAIT_TIME_MSEC
+ */
+ unsigned unpublish_max_wait_time_msec;
+
+ /**
+ * Authentication preference.
+ */
+ pjsip_auth_clt_pref auth_pref;
+
+ /**
+ * Optional PIDF tuple ID for outgoing PUBLISH and NOTIFY. If this value
+ * is not specified, a random string will be used.
+ */
+ pj_str_t pidf_tuple_id;
+
+ /**
+ * Optional URI to be put as Contact for this account. It is recommended
+ * that this field is left empty, so that the value will be calculated
+ * automatically based on the transport address.
+ */
+ pj_str_t force_contact;
+
+ /**
+ * Additional parameters that will be appended in the Contact header
+ * for this account. This will affect the Contact header in all SIP
+ * messages sent on behalf of this account, including but not limited to
+ * REGISTER, INVITE, and SUBCRIBE requests or responses.
+ *
+ * The parameters should be preceeded by semicolon, and all strings must
+ * be properly escaped. Example:
+ * ";my-param=X;another-param=Hi%20there"
+ */
+ pj_str_t contact_params;
+
+ /**
+ * Additional URI parameters that will be appended in the Contact URI
+ * for this account. This will affect the Contact URI in all SIP
+ * messages sent on behalf of this account, including but not limited to
+ * REGISTER, INVITE, and SUBCRIBE requests or responses.
+ *
+ * The parameters should be preceeded by semicolon, and all strings must
+ * be properly escaped. Example:
+ * ";my-param=X;another-param=Hi%20there"
+ */
+ pj_str_t contact_uri_params;
+
+ /**
+ * Specify how support for reliable provisional response (100rel/
+ * PRACK) should be used for all sessions in this account. See the
+ * documentation of pjsua_100rel_use enumeration for more info.
+ *
+ * Default: The default value is taken from the value of
+ * require_100rel in pjsua_config.
+ */
+ pjsua_100rel_use require_100rel;
+
+ /**
+ * Specify the usage of Session Timers for all sessions. See the
+ * #pjsua_sip_timer_use for possible values.
+ *
+ * Default: PJSUA_SIP_TIMER_OPTIONAL
+ */
+ pjsua_sip_timer_use use_timer;
+
+ /**
+ * Specify Session Timer settings, see #pjsip_timer_setting.
+ */
+ pjsip_timer_setting timer_setting;
+
+ /**
+ * Number of proxies in the proxy array below.
+ */
+ unsigned proxy_cnt;
+
+ /**
+ * Optional URI of the proxies to be visited for all outgoing requests
+ * that are using this account (REGISTER, INVITE, etc). Application need
+ * to specify these proxies if the service provider requires that requests
+ * destined towards its network should go through certain proxies first
+ * (for example, border controllers).
+ *
+ * These proxies will be put in the route set for this account, with
+ * maintaining the orders (the first proxy in the array will be visited
+ * first). If global outbound proxies are configured in pjsua_config,
+ * then these account proxies will be placed after the global outbound
+ * proxies in the routeset.
+ */
+ pj_str_t proxy[PJSUA_ACC_MAX_PROXIES];
+
+ /**
+ * Optional interval for registration, in seconds. If the value is zero,
+ * default interval will be used (PJSUA_REG_INTERVAL, 300 seconds).
+ */
+ unsigned reg_timeout;
+
+ /**
+ * Specify the number of seconds to refresh the client registration
+ * before the registration expires.
+ *
+ * Default: PJSIP_REGISTER_CLIENT_DELAY_BEFORE_REFRESH, 5 seconds
+ */
+ unsigned reg_delay_before_refresh;
+
+ /**
+ * Specify the maximum time to wait for unregistration requests to
+ * complete during library shutdown sequence.
+ *
+ * Default: PJSUA_UNREG_TIMEOUT
+ */
+ unsigned unreg_timeout;
+
+ /**
+ * Number of credentials in the credential array.
+ */
+ unsigned cred_count;
+
+ /**
+ * Array of credentials. If registration is desired, normally there should
+ * be at least one credential specified, to successfully authenticate
+ * against the service provider. More credentials can be specified, for
+ * example when the requests are expected to be challenged by the
+ * proxies in the route set.
+ */
+ pjsip_cred_info cred_info[PJSUA_ACC_MAX_PROXIES];
+
+ /**
+ * Optionally bind this account to specific transport. This normally is
+ * not a good idea, as account should be able to send requests using
+ * any available transports according to the destination. But some
+ * application may want to have explicit control over the transport to
+ * use, so in that case it can set this field.
+ *
+ * Default: -1 (PJSUA_INVALID_ID)
+ *
+ * @see pjsua_acc_set_transport()
+ */
+ pjsua_transport_id transport_id;
+
+ /**
+ * This option is used to update the transport address and the Contact
+ * header of REGISTER request. When this option is enabled, the library
+ * will keep track of the public IP address from the response of REGISTER
+ * request. Once it detects that the address has changed, it will
+ * unregister current Contact, update the Contact with transport address
+ * learned from Via header, and register a new Contact to the registrar.
+ * This will also update the public name of UDP transport if STUN is
+ * configured.
+ *
+ * See also contact_rewrite_method field.
+ *
+ * Default: 1 (yes)
+ */
+ pj_bool_t allow_contact_rewrite;
+
+ /**
+ * Specify how Contact update will be done with the registration, if
+ * \a allow_contact_rewrite is enabled.
+ *
+ * If set to 1, the Contact update will be done by sending unregistration
+ * to the currently registered Contact, while simultaneously sending new
+ * registration (with different Call-ID) for the updated Contact.
+ *
+ * If set to 2, the Contact update will be done in a single, current
+ * registration session, by removing the current binding (by setting its
+ * Contact's expires parameter to zero) and adding a new Contact binding,
+ * all done in a single request.
+ *
+ * Value 1 is the legacy behavior.
+ *
+ * Default value: PJSUA_CONTACT_REWRITE_METHOD (2)
+ */
+ int contact_rewrite_method;
+
+ /**
+ * This option is used to overwrite the "sent-by" field of the Via header
+ * for outgoing messages with the same interface address as the one in
+ * the REGISTER request, as long as the request uses the same transport
+ * instance as the previous REGISTER request.
+ *
+ * Default: 1 (yes)
+ */
+ pj_bool_t allow_via_rewrite;
+
+ /**
+ * Control the use of SIP outbound feature. SIP outbound is described in
+ * RFC 5626 to enable proxies or registrar to send inbound requests back
+ * to UA using the same connection initiated by the UA for its
+ * registration. This feature is highly useful in NAT-ed deployemtns,
+ * hence it is enabled by default.
+ *
+ * Note: currently SIP outbound can only be used with TCP and TLS
+ * transports. If UDP is used for the registration, the SIP outbound
+ * feature will be silently ignored for the account.
+ *
+ * Default: PJ_TRUE
+ */
+ unsigned use_rfc5626;
+
+ /**
+ * Specify SIP outbound (RFC 5626) instance ID to be used by this
+ * application. If empty, an instance ID will be generated based on
+ * the hostname of this agent. If application specifies this parameter, the
+ * value will look like "<urn:uuid:00000000-0000-1000-8000-AABBCCDDEEFF>"
+ * without the doublequote.
+ *
+ * Default: empty
+ */
+ pj_str_t rfc5626_instance_id;
+
+ /**
+ * Specify SIP outbound (RFC 5626) registration ID. The default value
+ * is empty, which would cause the library to automatically generate
+ * a suitable value.
+ *
+ * Default: empty
+ */
+ pj_str_t rfc5626_reg_id;
+
+ /**
+ * Set the interval for periodic keep-alive transmission for this account.
+ * If this value is zero, keep-alive will be disabled for this account.
+ * The keep-alive transmission will be sent to the registrar's address,
+ * after successful registration.
+ *
+ * Default: 15 (seconds)
+ */
+ unsigned ka_interval;
+
+ /**
+ * Specify the data to be transmitted as keep-alive packets.
+ *
+ * Default: CR-LF
+ */
+ pj_str_t ka_data;
+
+ /**
+ * Specify whether incoming video should be shown to screen by default.
+ * This applies to incoming call (INVITE), incoming re-INVITE, and
+ * incoming UPDATE requests.
+ *
+ * Regardless of this setting, application can detect incoming video
+ * by implementing \a on_call_media_state() callback and enumerating
+ * the media stream(s) with #pjsua_call_get_info(). Once incoming
+ * video is recognised, application may retrieve the window associated
+ * with the incoming video and show or hide it with
+ * #pjsua_vid_win_set_show().
+ *
+ * Default: PJ_FALSE
+ */
+ pj_bool_t vid_in_auto_show;
+
+ /**
+ * Specify whether outgoing video should be activated by default when
+ * making outgoing calls and/or when incoming video is detected. This
+ * applies to incoming and outgoing calls, incoming re-INVITE, and
+ * incoming UPDATE. If the setting is non-zero, outgoing video
+ * transmission will be started as soon as response to these requests
+ * is sent (or received).
+ *
+ * Regardless of the value of this setting, application can start and
+ * stop outgoing video transmission with #pjsua_call_set_vid_strm().
+ *
+ * Default: PJ_FALSE
+ */
+ pj_bool_t vid_out_auto_transmit;
+
+ /**
+ * Specify video window's flags. The value is a bitmask combination of
+ * #pjmedia_vid_dev_wnd_flag.
+ *
+ * Default: 0
+ */
+ unsigned vid_wnd_flags;
+
+ /**
+ * Specify the default capture device to be used by this account. If
+ * \a vid_out_auto_transmit is enabled, this device will be used for
+ * capturing video.
+ *
+ * Default: PJMEDIA_VID_DEFAULT_CAPTURE_DEV
+ */
+ pjmedia_vid_dev_index vid_cap_dev;
+
+ /**
+ * Specify the default rendering device to be used by this account.
+ *
+ * Default: PJMEDIA_VID_DEFAULT_RENDER_DEV
+ */
+ pjmedia_vid_dev_index vid_rend_dev;
+
+ /**
+ * Specify the send rate control for video stream.
+ *
+ * Default: see #pjmedia_vid_stream_rc_config
+ */
+ pjmedia_vid_stream_rc_config vid_stream_rc_cfg;
+
+ /**
+ * Media transport config.
+ */
+ pjsua_transport_config rtp_cfg;
+
+ /**
+ * Specify whether secure media transport should be used for this account.
+ * Valid values are PJMEDIA_SRTP_DISABLED, PJMEDIA_SRTP_OPTIONAL, and
+ * PJMEDIA_SRTP_MANDATORY.
+ *
+ * Default: #PJSUA_DEFAULT_USE_SRTP
+ */
+ pjmedia_srtp_use use_srtp;
+
+ /**
+ * Specify whether SRTP requires secure signaling to be used. This option
+ * is only used when \a use_srtp option above is non-zero.
+ *
+ * Valid values are:
+ * 0: SRTP does not require secure signaling
+ * 1: SRTP requires secure transport such as TLS
+ * 2: SRTP requires secure end-to-end transport (SIPS)
+ *
+ * Default: #PJSUA_DEFAULT_SRTP_SECURE_SIGNALING
+ */
+ int srtp_secure_signaling;
+
+ /**
+ * This setting has been deprecated and will be ignored.
+ */
+ pj_bool_t srtp_optional_dup_offer;
+
+ /**
+ * Specify interval of auto registration retry upon registration failure
+ * (including caused by transport problem), in second. Set to 0 to
+ * disable auto re-registration. Note that if the registration retry
+ * occurs because of transport failure, the first retry will be done
+ * after \a reg_first_retry_interval seconds instead. Also note that
+ * the interval will be randomized slightly by approximately +/- ten
+ * seconds to avoid all clients re-registering at the same time.
+ *
+ * See also \a reg_first_retry_interval setting.
+ *
+ * Default: #PJSUA_REG_RETRY_INTERVAL
+ */
+ unsigned reg_retry_interval;
+
+ /**
+ * This specifies the interval for the first registration retry. The
+ * registration retry is explained in \a reg_retry_interval. Note that
+ * the value here will also be randomized by +/- ten seconds.
+ *
+ * Default: 0
+ */
+ unsigned reg_first_retry_interval;
+
+ /**
+ * Specify whether calls of the configured account should be dropped
+ * after registration failure and an attempt of re-registration has
+ * also failed.
+ *
+ * Default: PJ_FALSE (disabled)
+ */
+ pj_bool_t drop_calls_on_reg_fail;
+
+ /**
+ * Specify how the registration uses the outbound and account proxy
+ * settings. This controls if and what Route headers will appear in
+ * the REGISTER request of this account. The value is bitmask combination
+ * of PJSUA_REG_USE_OUTBOUND_PROXY and PJSUA_REG_USE_ACC_PROXY bits.
+ * If the value is set to 0, the REGISTER request will not use any proxy
+ * (i.e. it will not have any Route headers).
+ *
+ * Default: 3 (PJSUA_REG_USE_OUTBOUND_PROXY | PJSUA_REG_USE_ACC_PROXY)
+ */
+ unsigned reg_use_proxy;
+
+#if defined(PJMEDIA_STREAM_ENABLE_KA) && (PJMEDIA_STREAM_ENABLE_KA != 0)
+ /**
+ * Specify whether stream keep-alive and NAT hole punching with
+ * non-codec-VAD mechanism (see @ref PJMEDIA_STREAM_ENABLE_KA) is enabled
+ * for this account.
+ *
+ * Default: PJ_FALSE (disabled)
+ */
+ pj_bool_t use_stream_ka;
+#endif
+
+ /**
+ * Specify how to offer call hold to remote peer. Please see the
+ * documentation on #pjsua_call_hold_type for more info.
+ *
+ * Default: PJSUA_CALL_HOLD_TYPE_DEFAULT
+ */
+ pjsua_call_hold_type call_hold_type;
+
+
+ /**
+ * Specify whether the account should register as soon as it is
+ * added to the UA. Application can set this to PJ_FALSE and control
+ * the registration manually with pjsua_acc_set_registration().
+ *
+ * Default: PJ_TRUE
+ */
+ pj_bool_t register_on_acc_add;
+
+} pjsua_acc_config;
+
+
+/**
+ * Call this function to initialize account config with default values.
+ *
+ * @param cfg The account config to be initialized.
+ */
+PJ_DECL(void) pjsua_acc_config_default(pjsua_acc_config *cfg);
+
+
+/**
+ * Duplicate account config.
+ *
+ * @param pool Pool to be used for duplicating the config.
+ * @param dst Destination configuration.
+ * @param src Source configuration.
+ */
+PJ_DECL(void) pjsua_acc_config_dup(pj_pool_t *pool,
+ pjsua_acc_config *dst,
+ const pjsua_acc_config *src);
+
+
+/**
+ * Account info. Application can query account info by calling
+ * #pjsua_acc_get_info().
+ */
+typedef struct pjsua_acc_info
+{
+ /**
+ * The account ID.
+ */
+ pjsua_acc_id id;
+
+ /**
+ * Flag to indicate whether this is the default account.
+ */
+ pj_bool_t is_default;
+
+ /**
+ * Account URI
+ */
+ pj_str_t acc_uri;
+
+ /**
+ * Flag to tell whether this account has registration setting
+ * (reg_uri is not empty).
+ */
+ pj_bool_t has_registration;
+
+ /**
+ * An up to date expiration interval for account registration session.
+ */
+ int expires;
+
+ /**
+ * Last registration status code. If status code is zero, the account
+ * is currently not registered. Any other value indicates the SIP
+ * status code of the registration.
+ */
+ pjsip_status_code status;
+
+ /**
+ * Last registration error code. When the status field contains a SIP
+ * status code that indicates a registration failure, last registration
+ * error code contains the error code that causes the failure. In any
+ * other case, its value is zero.
+ */
+ pj_status_t reg_last_err;
+
+ /**
+ * String describing the registration status.
+ */
+ pj_str_t status_text;
+
+ /**
+ * Presence online status for this account.
+ */
+ pj_bool_t online_status;
+
+ /**
+ * Presence online status text.
+ */
+ pj_str_t online_status_text;
+
+ /**
+ * Extended RPID online status information.
+ */
+ pjrpid_element rpid;
+
+ /**
+ * Buffer that is used internally to store the status text.
+ */
+ char buf_[PJ_ERR_MSG_SIZE];
+
+} pjsua_acc_info;
+
+
+
+/**
+ * Get number of current accounts.
+ *
+ * @return Current number of accounts.
+ */
+PJ_DECL(unsigned) pjsua_acc_get_count(void);
+
+
+/**
+ * Check if the specified account ID is valid.
+ *
+ * @param acc_id Account ID to check.
+ *
+ * @return Non-zero if account ID is valid.
+ */
+PJ_DECL(pj_bool_t) pjsua_acc_is_valid(pjsua_acc_id acc_id);
+
+
+/**
+ * Set default account to be used when incoming and outgoing
+ * requests doesn't match any accounts.
+ *
+ * @param acc_id The account ID to be used as default.
+ *
+ * @return PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjsua_acc_set_default(pjsua_acc_id acc_id);
+
+
+/**
+ * Get default account to be used when receiving incoming requests (calls),
+ * when the destination of the incoming call doesn't match any other
+ * accounts.
+ *
+ * @return The default account ID, or PJSUA_INVALID_ID if no
+ * default account is configured.
+ */
+PJ_DECL(pjsua_acc_id) pjsua_acc_get_default(void);
+
+
+/**
+ * Add a new account to pjsua. PJSUA must have been initialized (with
+ * #pjsua_init()) before calling this function. If registration is configured
+ * for this account, this function would also start the SIP registration
+ * session with the SIP registrar server. This SIP registration session
+ * will be maintained internally by the library, and application doesn't
+ * need to do anything to maintain the registration session.
+ *
+ *
+ * @param acc_cfg Account configuration.
+ * @param is_default If non-zero, this account will be set as the default
+ * account. The default account will be used when sending
+ * outgoing requests (e.g. making call) when no account is
+ * specified, and when receiving incoming requests when the
+ * request does not match any accounts. It is recommended
+ * that default account is set to local/LAN account.
+ * @param p_acc_id Pointer to receive account ID of the new account.
+ *
+ * @return PJ_SUCCESS on success, or the appropriate error code.
+ */
+PJ_DECL(pj_status_t) pjsua_acc_add(const pjsua_acc_config *acc_cfg,
+ pj_bool_t is_default,
+ pjsua_acc_id *p_acc_id);
+
+
+/**
+ * Add a local account. A local account is used to identify local endpoint
+ * instead of a specific user, and for this reason, a transport ID is needed
+ * to obtain the local address information.
+ *
+ * @param tid Transport ID to generate account address.
+ * @param is_default If non-zero, this account will be set as the default
+ * account. The default account will be used when sending
+ * outgoing requests (e.g. making call) when no account is
+ * specified, and when receiving incoming requests when the
+ * request does not match any accounts. It is recommended
+ * that default account is set to local/LAN account.
+ * @param p_acc_id Pointer to receive account ID of the new account.
+ *
+ * @return PJ_SUCCESS on success, or the appropriate error code.
+ */
+PJ_DECL(pj_status_t) pjsua_acc_add_local(pjsua_transport_id tid,
+ pj_bool_t is_default,
+ pjsua_acc_id *p_acc_id);
+
+/**
+ * Set arbitrary data to be associated with the account.
+ *
+ * @param acc_id The account ID.
+ * @param user_data User/application data.
+ *
+ * @return PJ_SUCCESS on success, or the appropriate error code.
+ */
+PJ_DECL(pj_status_t) pjsua_acc_set_user_data(pjsua_acc_id acc_id,
+ void *user_data);
+
+
+/**
+ * Retrieve arbitrary data associated with the account.
+ *
+ * @param acc_id The account ID.
+ *
+ * @return The user data. In the case where the account ID is
+ * not valid, NULL is returned.
+ */
+PJ_DECL(void*) pjsua_acc_get_user_data(pjsua_acc_id acc_id);
+
+
+/**
+ * Delete an account. This will unregister the account from the SIP server,
+ * if necessary, and terminate server side presence subscriptions associated
+ * with this account.
+ *
+ * @param acc_id Id of the account to be deleted.
+ *
+ * @return PJ_SUCCESS on success, or the appropriate error code.
+ */
+PJ_DECL(pj_status_t) pjsua_acc_del(pjsua_acc_id acc_id);
+
+
+/**
+ * Get current config for the account. This will copy current account setting
+ * to the specified parameter. Note that all pointers in the settings will
+ * point to the original settings in the account and application must not
+ * modify the values in any way. Application must also take care that these
+ * data is only valid until the account is destroyed.
+ *
+ * @param acc_id The account ID.
+ * @param acc_cfg Structure to receive the settings.
+ *
+ * @return PJ_SUCCESS on success, or the appropriate error code.
+ */
+PJ_DECL(pj_status_t) pjsua_acc_get_config(pjsua_acc_id acc_id,
+ pjsua_acc_config *acc_cfg);
+
+
+/**
+ * Modify account information.
+ *
+ * @param acc_id Id of the account to be modified.
+ * @param acc_cfg New account configuration.
+ *
+ * @return PJ_SUCCESS on success, or the appropriate error code.
+ */
+PJ_DECL(pj_status_t) pjsua_acc_modify(pjsua_acc_id acc_id,
+ const pjsua_acc_config *acc_cfg);
+
+
+/**
+ * Modify account's presence status to be advertised to remote/presence
+ * subscribers. This would trigger the sending of outgoing NOTIFY request
+ * if there are server side presence subscription for this account, and/or
+ * outgoing PUBLISH if presence publication is enabled for this account.
+ *
+ * @see pjsua_acc_set_online_status2()
+ *
+ * @param acc_id The account ID.
+ * @param is_online True of false.
+ *
+ * @return PJ_SUCCESS on success, or the appropriate error code.
+ */
+PJ_DECL(pj_status_t) pjsua_acc_set_online_status(pjsua_acc_id acc_id,
+ pj_bool_t is_online);
+
+/**
+ * Modify account's presence status to be advertised to remote/presence
+ * subscribers. This would trigger the sending of outgoing NOTIFY request
+ * if there are server side presence subscription for this account, and/or
+ * outgoing PUBLISH if presence publication is enabled for this account.
+ *
+ * @see pjsua_acc_set_online_status()
+ *
+ * @param acc_id The account ID.
+ * @param is_online True of false.
+ * @param pr Extended information in subset of RPID format
+ * which allows setting custom presence text.
+ *
+ * @return PJ_SUCCESS on success, or the appropriate error code.
+ */
+PJ_DECL(pj_status_t) pjsua_acc_set_online_status2(pjsua_acc_id acc_id,
+ pj_bool_t is_online,
+ const pjrpid_element *pr);
+
+/**
+ * Update registration or perform unregistration. If registration is
+ * configured for this account, then initial SIP REGISTER will be sent
+ * when the account is added with #pjsua_acc_add(). Application normally
+ * only need to call this function if it wants to manually update the
+ * registration or to unregister from the server.
+ *
+ * @param acc_id The account ID.
+ * @param renew If renew argument is zero, this will start
+ * unregistration process.
+ *
+ * @return PJ_SUCCESS on success, or the appropriate error code.
+ */
+PJ_DECL(pj_status_t) pjsua_acc_set_registration(pjsua_acc_id acc_id,
+ pj_bool_t renew);
+
+/**
+ * Get information about the specified account.
+ *
+ * @param acc_id Account identification.
+ * @param info Pointer to receive account information.
+ *
+ * @return PJ_SUCCESS on success, or the appropriate error code.
+ */
+PJ_DECL(pj_status_t) pjsua_acc_get_info(pjsua_acc_id acc_id,
+ pjsua_acc_info *info);
+
+
+/**
+ * Enumerate all account currently active in the library. This will fill
+ * the array with the account Ids, and application can then query the
+ * account information for each id with #pjsua_acc_get_info().
+ *
+ * @see pjsua_acc_enum_info().
+ *
+ * @param ids Array of account IDs to be initialized.
+ * @param count In input, specifies the maximum number of elements.
+ * On return, it contains the actual number of elements.
+ *
+ * @return PJ_SUCCESS on success, or the appropriate error code.
+ */
+PJ_DECL(pj_status_t) pjsua_enum_accs(pjsua_acc_id ids[],
+ unsigned *count );
+
+
+/**
+ * Enumerate account informations.
+ *
+ * @param info Array of account infos to be initialized.
+ * @param count In input, specifies the maximum number of elements.
+ * On return, it contains the actual number of elements.
+ *
+ * @return PJ_SUCCESS on success, or the appropriate error code.
+ */
+PJ_DECL(pj_status_t) pjsua_acc_enum_info( pjsua_acc_info info[],
+ unsigned *count );
+
+
+/**
+ * This is an internal function to find the most appropriate account to
+ * used to reach to the specified URL.
+ *
+ * @param url The remote URL to reach.
+ *
+ * @return Account id.
+ */
+PJ_DECL(pjsua_acc_id) pjsua_acc_find_for_outgoing(const pj_str_t *url);
+
+
+/**
+ * This is an internal function to find the most appropriate account to be
+ * used to handle incoming calls.
+ *
+ * @param rdata The incoming request message.
+ *
+ * @return Account id.
+ */
+PJ_DECL(pjsua_acc_id) pjsua_acc_find_for_incoming(pjsip_rx_data *rdata);
+
+
+/**
+ * Create arbitrary requests using the account. Application should only use
+ * this function to create auxiliary requests outside dialog, such as
+ * OPTIONS, and use the call or presence API to create dialog related
+ * requests.
+ *
+ * @param acc_id The account ID.
+ * @param method The SIP method of the request.
+ * @param target Target URI.
+ * @param p_tdata Pointer to receive the request.
+ *
+ * @return PJ_SUCCESS or the error code.
+ */
+PJ_DECL(pj_status_t) pjsua_acc_create_request(pjsua_acc_id acc_id,
+ const pjsip_method *method,
+ const pj_str_t *target,
+ pjsip_tx_data **p_tdata);
+
+
+/**
+ * Create a suitable Contact header value, based on the specified target URI
+ * for the specified account.
+ *
+ * @param pool Pool to allocate memory for the string.
+ * @param contact The string where the Contact will be stored.
+ * @param acc_id Account ID.
+ * @param uri Destination URI of the request.
+ *
+ * @return PJ_SUCCESS on success, other on error.
+ */
+PJ_DECL(pj_status_t) pjsua_acc_create_uac_contact( pj_pool_t *pool,
+ pj_str_t *contact,
+ pjsua_acc_id acc_id,
+ const pj_str_t *uri);
+
+
+
+/**
+ * Create a suitable Contact header value, based on the information in the
+ * incoming request.
+ *
+ * @param pool Pool to allocate memory for the string.
+ * @param contact The string where the Contact will be stored.
+ * @param acc_id Account ID.
+ * @param rdata Incoming request.
+ *
+ * @return PJ_SUCCESS on success, other on error.
+ */
+PJ_DECL(pj_status_t) pjsua_acc_create_uas_contact( pj_pool_t *pool,
+ pj_str_t *contact,
+ pjsua_acc_id acc_id,
+ pjsip_rx_data *rdata );
+
+
+/**
+ * Lock/bind this account to a specific transport/listener. Normally
+ * application shouldn't need to do this, as transports will be selected
+ * automatically by the stack according to the destination.
+ *
+ * When account is locked/bound to a specific transport, all outgoing
+ * requests from this account will use the specified transport (this
+ * includes SIP registration, dialog (call and event subscription), and
+ * out-of-dialog requests such as MESSAGE).
+ *
+ * Note that transport_id may be specified in pjsua_acc_config too.
+ *
+ * @param acc_id The account ID.
+ * @param tp_id The transport ID.
+ *
+ * @return PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjsua_acc_set_transport(pjsua_acc_id acc_id,
+ pjsua_transport_id tp_id);
+
+
+/**
+ * @}
+ */
+
+
+/*****************************************************************************
+ * CALLS API
+ */
+
+
+/**
+ * @defgroup PJSUA_LIB_CALL PJSUA-API Calls Management
+ * @ingroup PJSUA_LIB
+ * @brief Call manipulation.
+ * @{
+ */
+
+/**
+ * Maximum simultaneous calls.
+ */
+#ifndef PJSUA_MAX_CALLS
+# define PJSUA_MAX_CALLS 32
+#endif
+
+/**
+ * Maximum active video windows
+ */
+#ifndef PJSUA_MAX_VID_WINS
+# define PJSUA_MAX_VID_WINS 16
+#endif
+
+/**
+ * Video window ID.
+ */
+typedef int pjsua_vid_win_id;
+
+
+/**
+ * This enumeration specifies the media status of a call, and it's part
+ * of pjsua_call_info structure.
+ */
+typedef enum pjsua_call_media_status
+{
+ /**
+ * Call currently has no media, or the media is not used.
+ */
+ PJSUA_CALL_MEDIA_NONE,
+
+ /**
+ * The media is active
+ */
+ PJSUA_CALL_MEDIA_ACTIVE,
+
+ /**
+ * The media is currently put on hold by local endpoint
+ */
+ PJSUA_CALL_MEDIA_LOCAL_HOLD,
+
+ /**
+ * The media is currently put on hold by remote endpoint
+ */
+ PJSUA_CALL_MEDIA_REMOTE_HOLD,
+
+ /**
+ * The media has reported error (e.g. ICE negotiation)
+ */
+ PJSUA_CALL_MEDIA_ERROR
+
+} pjsua_call_media_status;
+
+
+/**
+ * Enumeration of video keyframe request methods. Keyframe request is
+ * triggered by decoder, usually when the incoming video stream cannot
+ * be decoded properly due to missing video keyframe.
+ */
+typedef enum pjsua_vid_req_keyframe_method
+{
+ /**
+ * Requesting keyframe via SIP INFO message. Note that incoming keyframe
+ * request via SIP INFO will always be handled even if this flag is unset.
+ */
+ PJSUA_VID_REQ_KEYFRAME_SIP_INFO = 1,
+
+ /**
+ * Requesting keyframe via Picture Loss Indication of RTCP feedback.
+ * This is currently not supported.
+ */
+ PJSUA_VID_REQ_KEYFRAME_RTCP_PLI = 2
+
+} pjsua_vid_req_keyframe_method;
+
+
+/**
+ * Call media information.
+ */
+typedef struct pjsua_call_media_info
+{
+ /** Media index in SDP. */
+ unsigned index;
+
+ /** Media type. */
+ pjmedia_type type;
+
+ /** Media direction. */
+ pjmedia_dir dir;
+
+ /** Call media status. */
+ pjsua_call_media_status status;
+
+ /** The specific media stream info. */
+ union {
+ /** Audio stream */
+ struct {
+ /** The conference port number for the call. */
+ pjsua_conf_port_id conf_slot;
+ } aud;
+
+ /** Video stream */
+ struct {
+ /**
+ * The window id for incoming video, if any, or
+ * PJSUA_INVALID_ID.
+ */
+ pjsua_vid_win_id win_in;
+
+ /** The video capture device for outgoing transmission,
+ * if any, or PJMEDIA_VID_INVALID_DEV
+ */
+ pjmedia_vid_dev_index cap_dev;
+
+ } vid;
+ } stream;
+
+} pjsua_call_media_info;
+
+
+/**
+ * This structure describes the information and current status of a call.
+ */
+typedef struct pjsua_call_info
+{
+ /** Call identification. */
+ pjsua_call_id id;
+
+ /** Initial call role (UAC == caller) */
+ pjsip_role_e role;
+
+ /** The account ID where this call belongs. */
+ pjsua_acc_id acc_id;
+
+ /** Local URI */
+ pj_str_t local_info;
+
+ /** Local Contact */
+ pj_str_t local_contact;
+
+ /** Remote URI */
+ pj_str_t remote_info;
+
+ /** Remote contact */
+ pj_str_t remote_contact;
+
+ /** Dialog Call-ID string. */
+ pj_str_t call_id;
+
+ /** Call setting */
+ pjsua_call_setting setting;
+
+ /** Call state */
+ pjsip_inv_state state;
+
+ /** Text describing the state */
+ pj_str_t state_text;
+
+ /** Last status code heard, which can be used as cause code */
+ pjsip_status_code last_status;
+
+ /** The reason phrase describing the status. */
+ pj_str_t last_status_text;
+
+ /** Media status of the first audio stream. */
+ pjsua_call_media_status media_status;
+
+ /** Media direction of the first audio stream. */
+ pjmedia_dir media_dir;
+
+ /** The conference port number for the first audio stream. */
+ pjsua_conf_port_id conf_slot;
+
+ /** Number of active media info in this call. */
+ unsigned media_cnt;
+
+ /** Array of active media information. */
+ pjsua_call_media_info media[PJMEDIA_MAX_SDP_MEDIA];
+
+ /** Number of provisional media info in this call. */
+ unsigned prov_media_cnt;
+
+ /** Array of provisional media information. This contains the media info
+ * in the provisioning state, that is when the media session is being
+ * created/updated (SDP offer/answer is on progress).
+ */
+ pjsua_call_media_info prov_media[PJMEDIA_MAX_SDP_MEDIA];
+
+ /** Up-to-date call connected duration (zero when call is not
+ * established)
+ */
+ pj_time_val connect_duration;
+
+ /** Total call duration, including set-up time */
+ pj_time_val total_duration;
+
+ /** Flag if remote was SDP offerer */
+ pj_bool_t rem_offerer;
+
+ /** Number of audio streams offered by remote */
+ unsigned rem_aud_cnt;
+
+ /** Number of video streams offered by remote */
+ unsigned rem_vid_cnt;
+
+ /** Internal */
+ struct {
+ char local_info[128];
+ char local_contact[128];
+ char remote_info[128];
+ char remote_contact[128];
+ char call_id[128];
+ char last_status_text[128];
+ } buf_;
+
+} pjsua_call_info;
+
+/**
+ * Flags to be given to various call APIs. More than one flags may be
+ * specified by bitmasking them.
+ */
+typedef enum pjsua_call_flag
+{
+ /**
+ * When the call is being put on hold, specify this flag to unhold it.
+ * This flag is only valid for #pjsua_call_reinvite(). Note: for
+ * compatibility reason, this flag must have value of 1 because
+ * previously the unhold option is specified as boolean value.
+ */
+ PJSUA_CALL_UNHOLD = 1,
+
+ /**
+ * Update the local invite session's contact with the contact URI from
+ * the account. This flag is only valid for #pjsua_call_reinvite() and
+ * #pjsua_call_update(). This flag is useful in IP address change
+ * situation, after the local account's Contact has been updated
+ * (typically with re-registration) use this flag to update the invite
+ * session with the new Contact and to inform this new Contact to the
+ * remote peer with the outgoing re-INVITE or UPDATE
+ */
+ PJSUA_CALL_UPDATE_CONTACT = 2,
+
+ /**
+ * Include SDP "m=" line with port set to zero for each disabled media
+ * (i.e when aud_cnt or vid_cnt is set to zero). This flag is only valid
+ * for #pjsua_call_make_call().
+ */
+ PJSUA_CALL_INCLUDE_DISABLED_MEDIA = 4
+
+} pjsua_call_flag;
+
+
+/**
+ * Media stream info.
+ */
+typedef struct pjsua_stream_info
+{
+ /** Media type of this stream. */
+ pjmedia_type type;
+
+ /** Stream info (union). */
+ union {
+ /** Audio stream info */
+ pjmedia_stream_info aud;
+
+ /** Video stream info */
+ pjmedia_vid_stream_info vid;
+ } info;
+
+} pjsua_stream_info;
+
+
+/**
+ * Media stream statistic.
+ */
+typedef struct pjsua_stream_stat
+{
+ /** RTCP statistic. */
+ pjmedia_rtcp_stat rtcp;
+
+ /** Jitter buffer statistic. */
+ pjmedia_jb_state jbuf;
+
+} pjsua_stream_stat;
+
+/**
+ * This enumeration represents video stream operation on a call.
+ * See also #pjsua_call_vid_strm_op_param for further info.
+ */
+typedef enum pjsua_call_vid_strm_op
+{
+ /**
+ * No operation
+ */
+ PJSUA_CALL_VID_STRM_NO_OP,
+
+ /**
+ * Add a new video stream. This will add a new m=video line to
+ * the media, regardless of whether existing video is/are present
+ * or not. This will cause re-INVITE or UPDATE to be sent to remote
+ * party.
+ */
+ PJSUA_CALL_VID_STRM_ADD,
+
+ /**
+ * Remove/disable an existing video stream. This will
+ * cause re-INVITE or UPDATE to be sent to remote party.
+ */
+ PJSUA_CALL_VID_STRM_REMOVE,
+
+ /**
+ * Change direction of a video stream. This operation can be used
+ * to activate or deactivate an existing video media. This will
+ * cause re-INVITE or UPDATE to be sent to remote party.
+ */
+ PJSUA_CALL_VID_STRM_CHANGE_DIR,
+
+ /**
+ * Change capture device of a video stream. This will not send
+ * re-INVITE or UPDATE to remote party.
+ */
+ PJSUA_CALL_VID_STRM_CHANGE_CAP_DEV,
+
+ /**
+ * Start transmitting video stream. This will cause previously
+ * stopped stream to start transmitting again. Note that no
+ * re-INVITE/UPDATE is to be transmitted to remote since this
+ * operation only operates on local stream.
+ */
+ PJSUA_CALL_VID_STRM_START_TRANSMIT,
+
+ /**
+ * Stop transmitting video stream. This will cause the stream to
+ * be paused in TX direction, causing it to stop sending any video
+ * packets. No re-INVITE/UPDATE is to be transmitted to remote
+ * with this operation.
+ */
+ PJSUA_CALL_VID_STRM_STOP_TRANSMIT,
+
+ /**
+ * Send keyframe in the video stream. This will force the stream to
+ * generate and send video keyframe as soon as possible. No
+ * re-INVITE/UPDATE is to be transmitted to remote with this operation.
+ */
+ PJSUA_CALL_VID_STRM_SEND_KEYFRAME
+
+} pjsua_call_vid_strm_op;
+
+
+/**
+ * Parameters for video stream operation on a call. Application should
+ * use #pjsua_call_vid_strm_op_param_default() to initialize this structure
+ * with its default values.
+ */
+typedef struct pjsua_call_vid_strm_op_param
+{
+ /**
+ * Specify the media stream index. This can be set to -1 to denote
+ * the default video stream in the call, which is the first active
+ * video stream or any first video stream if none is active.
+ *
+ * This field is valid for all video stream operations, except
+ * PJSUA_CALL_VID_STRM_ADD.
+ *
+ * Default: -1 (first active video stream, or any first video stream
+ * if none is active)
+ */
+ int med_idx;
+
+ /**
+ * Specify the media stream direction.
+ *
+ * This field is valid for the following video stream operations:
+ * PJSUA_CALL_VID_STRM_ADD and PJSUA_CALL_VID_STRM_CHANGE_DIR.
+ *
+ * Default: PJMEDIA_DIR_ENCODING_DECODING
+ */
+ pjmedia_dir dir;
+
+ /**
+ * Specify the video capture device ID. This can be set to
+ * PJMEDIA_VID_DEFAULT_CAPTURE_DEV to specify the default capture
+ * device as configured in the account.
+ *
+ * This field is valid for the following video stream operations:
+ * PJSUA_CALL_VID_STRM_ADD and PJSUA_CALL_VID_STRM_CHANGE_CAP_DEV.
+ *
+ * Default: PJMEDIA_VID_DEFAULT_CAPTURE_DEV.
+ */
+ pjmedia_vid_dev_index cap_dev;
+
+} pjsua_call_vid_strm_op_param;
+
+
+/**
+ * Initialize call settings.
+ *
+ * @param opt The call setting to be initialized.
+ */
+PJ_DECL(void) pjsua_call_setting_default(pjsua_call_setting *opt);
+
+
+/**
+ * Initialize video stream operation param with default values.
+ *
+ * @param param The video stream operation param to be initialized.
+ */
+PJ_DECL(void)
+pjsua_call_vid_strm_op_param_default(pjsua_call_vid_strm_op_param *param);
+
+
+/**
+ * Get maximum number of calls configured in pjsua.
+ *
+ * @return Maximum number of calls configured.
+ */
+PJ_DECL(unsigned) pjsua_call_get_max_count(void);
+
+/**
+ * Get number of currently active calls.
+ *
+ * @return Number of currently active calls.
+ */
+PJ_DECL(unsigned) pjsua_call_get_count(void);
+
+/**
+ * Enumerate all active calls. Application may then query the information and
+ * state of each call by calling #pjsua_call_get_info().
+ *
+ * @param ids Array of account IDs to be initialized.
+ * @param count In input, specifies the maximum number of elements.
+ * On return, it contains the actual number of elements.
+ *
+ * @return PJ_SUCCESS on success, or the appropriate error code.
+ */
+PJ_DECL(pj_status_t) pjsua_enum_calls(pjsua_call_id ids[],
+ unsigned *count);
+
+
+/**
+ * Make outgoing call to the specified URI using the specified account.
+ *
+ * @param acc_id The account to be used.
+ * @param dst_uri URI to be put in the To header (normally is the same
+ * as the target URI).
+ * @param opt Optional call setting. This should be initialized
+ * using #pjsua_call_setting_default().
+ * @param user_data Arbitrary user data to be attached to the call, and
+ * can be retrieved later.
+ * @param msg_data Optional headers etc to be added to outgoing INVITE
+ * request, or NULL if no custom header is desired.
+ * @param p_call_id Pointer to receive call identification.
+ *
+ * @return PJ_SUCCESS on success, or the appropriate error code.
+ */
+PJ_DECL(pj_status_t) pjsua_call_make_call(pjsua_acc_id acc_id,
+ const pj_str_t *dst_uri,
+ const pjsua_call_setting *opt,
+ void *user_data,
+ const pjsua_msg_data *msg_data,
+ pjsua_call_id *p_call_id);
+
+
+/**
+ * Check if the specified call has active INVITE session and the INVITE
+ * session has not been disconnected.
+ *
+ * @param call_id Call identification.
+ *
+ * @return Non-zero if call is active.
+ */
+PJ_DECL(pj_bool_t) pjsua_call_is_active(pjsua_call_id call_id);
+
+
+/**
+ * Check if call has an active media session.
+ *
+ * @param call_id Call identification.
+ *
+ * @return Non-zero if yes.
+ */
+PJ_DECL(pj_bool_t) pjsua_call_has_media(pjsua_call_id call_id);
+
+
+/**
+ * Get the conference port identification associated with the call.
+ *
+ * @param call_id Call identification.
+ *
+ * @return Conference port ID, or PJSUA_INVALID_ID when the
+ * media has not been established or is not active.
+ */
+PJ_DECL(pjsua_conf_port_id) pjsua_call_get_conf_port(pjsua_call_id call_id);
+
+/**
+ * Obtain detail information about the specified call.
+ *
+ * @param call_id Call identification.
+ * @param info Call info to be initialized.
+ *
+ * @return PJ_SUCCESS on success, or the appropriate error code.
+ */
+PJ_DECL(pj_status_t) pjsua_call_get_info(pjsua_call_id call_id,
+ pjsua_call_info *info);
+
+/**
+ * Check if remote peer support the specified capability.
+ *
+ * @param call_id Call identification.
+ * @param htype The header type to be checked, which value may be:
+ * - PJSIP_H_ACCEPT
+ * - PJSIP_H_ALLOW
+ * - PJSIP_H_SUPPORTED
+ * @param hname If htype specifies PJSIP_H_OTHER, then the header
+ * name must be supplied in this argument. Otherwise the
+ * value must be set to NULL.
+ * @param token The capability token to check. For example, if \a
+ * htype is PJSIP_H_ALLOW, then \a token specifies the
+ * method names; if \a htype is PJSIP_H_SUPPORTED, then
+ * \a token specifies the extension names such as
+ * "100rel".
+ *
+ * @return PJSIP_DIALOG_CAP_SUPPORTED if the specified capability
+ * is explicitly supported, see @pjsip_dialog_cap_status
+ * for more info.
+ */
+PJ_DECL(pjsip_dialog_cap_status) pjsua_call_remote_has_cap(
+ pjsua_call_id call_id,
+ int htype,
+ const pj_str_t *hname,
+ const pj_str_t *token);
+
+/**
+ * Attach application specific data to the call. Application can then
+ * inspect this data by calling #pjsua_call_get_user_data().
+ *
+ * @param call_id Call identification.
+ * @param user_data Arbitrary data to be attached to the call.
+ *
+ * @return The user data.
+ */
+PJ_DECL(pj_status_t) pjsua_call_set_user_data(pjsua_call_id call_id,
+ void *user_data);
+
+
+/**
+ * Get user data attached to the call, which has been previously set with
+ * #pjsua_call_set_user_data().
+ *
+ * @param call_id Call identification.
+ *
+ * @return The user data.
+ */
+PJ_DECL(void*) pjsua_call_get_user_data(pjsua_call_id call_id);
+
+
+/**
+ * Get the NAT type of remote's endpoint. This is a proprietary feature
+ * of PJSUA-LIB which sends its NAT type in the SDP when \a nat_type_in_sdp
+ * is set in #pjsua_config.
+ *
+ * This function can only be called after SDP has been received from remote,
+ * which means for incoming call, this function can be called as soon as
+ * call is received as long as incoming call contains SDP, and for outgoing
+ * call, this function can be called only after SDP is received (normally in
+ * 200/OK response to INVITE). As a general case, application should call
+ * this function after or in \a on_call_media_state() callback.
+ *
+ * @param call_id Call identification.
+ * @param p_type Pointer to store the NAT type. Application can then
+ * retrieve the string description of the NAT type
+ * by calling pj_stun_get_nat_name().
+ *
+ * @return PJ_SUCCESS on success.
+ *
+ * @see pjsua_get_nat_type(), nat_type_in_sdp
+ */
+PJ_DECL(pj_status_t) pjsua_call_get_rem_nat_type(pjsua_call_id call_id,
+ pj_stun_nat_type *p_type);
+
+/**
+ * Send response to incoming INVITE request. Depending on the status
+ * code specified as parameter, this function may send provisional
+ * response, establish the call, or terminate the call. See also
+ * #pjsua_call_answer2().
+ *
+ * @param call_id Incoming call identification.
+ * @param code Status code, (100-699).
+ * @param reason Optional reason phrase. If NULL, default text
+ * will be used.
+ * @param msg_data Optional list of headers etc to be added to outgoing
+ * response message.
+ *
+ * @return PJ_SUCCESS on success, or the appropriate error code.
+ */
+PJ_DECL(pj_status_t) pjsua_call_answer(pjsua_call_id call_id,
+ unsigned code,
+ const pj_str_t *reason,
+ const pjsua_msg_data *msg_data);
+
+
+/**
+ * Send response to incoming INVITE request with call setting param.
+ * Depending on the status code specified as parameter, this function may
+ * send provisional response, establish the call, or terminate the call.
+ * Notes about call setting:
+ * - if call setting is changed in the subsequent call to this function,
+ * only the first call setting supplied will applied. So normally
+ * application will not supply call setting before getting confirmation
+ * from the user.
+ * - if no call setting is supplied when SDP has to be sent, i.e: answer
+ * with status code 183 or 2xx, the default call setting will be used,
+ * check #pjsua_call_setting for its default values.
+ *
+ * @param call_id Incoming call identification.
+ * @param opt Optional call setting.
+ * @param code Status code, (100-699).
+ * @param reason Optional reason phrase. If NULL, default text
+ * will be used.
+ * @param msg_data Optional list of headers etc to be added to outgoing
+ * response message.
+ *
+ * @return PJ_SUCCESS on success, or the appropriate error code.
+ */
+PJ_DECL(pj_status_t) pjsua_call_answer2(pjsua_call_id call_id,
+ const pjsua_call_setting *opt,
+ unsigned code,
+ const pj_str_t *reason,
+ const pjsua_msg_data *msg_data);
+
+
+/**
+ * Hangup call by using method that is appropriate according to the
+ * call state. This function is different than answering the call with
+ * 3xx-6xx response (with #pjsua_call_answer()), in that this function
+ * will hangup the call regardless of the state and role of the call,
+ * while #pjsua_call_answer() only works with incoming calls on EARLY
+ * state.
+ *
+ * @param call_id Call identification.
+ * @param code Optional status code to be sent when we're rejecting
+ * incoming call. If the value is zero, "603/Decline"
+ * will be sent.
+ * @param reason Optional reason phrase to be sent when we're rejecting
+ * incoming call. If NULL, default text will be used.
+ * @param msg_data Optional list of headers etc to be added to outgoing
+ * request/response message.
+ *
+ * @return PJ_SUCCESS on success, or the appropriate error code.
+ */
+PJ_DECL(pj_status_t) pjsua_call_hangup(pjsua_call_id call_id,
+ unsigned code,
+ const pj_str_t *reason,
+ const pjsua_msg_data *msg_data);
+
+/**
+ * Accept or reject redirection response. Application MUST call this function
+ * after it signaled PJSIP_REDIRECT_PENDING in the \a on_call_redirected()
+ * callback, to notify the call whether to accept or reject the redirection
+ * to the current target. Application can use the combination of
+ * PJSIP_REDIRECT_PENDING command in \a on_call_redirected() callback and
+ * this function to ask for user permission before redirecting the call.
+ *
+ * Note that if the application chooses to reject or stop redirection (by
+ * using PJSIP_REDIRECT_REJECT or PJSIP_REDIRECT_STOP respectively), the
+ * call disconnection callback will be called before this function returns.
+ * And if the application rejects the target, the \a on_call_redirected()
+ * callback may also be called before this function returns if there is
+ * another target to try.
+ *
+ * @param call_id The call ID.
+ * @param cmd Redirection operation to be applied to the current
+ * target. The semantic of this argument is similar
+ * to the description in the \a on_call_redirected()
+ * callback, except that the PJSIP_REDIRECT_PENDING is
+ * not accepted here.
+ *
+ * @return PJ_SUCCESS on successful operation.
+ */
+PJ_DECL(pj_status_t) pjsua_call_process_redirect(pjsua_call_id call_id,
+ pjsip_redirect_op cmd);
+
+/**
+ * Put the specified call on hold. This will send re-INVITE with the
+ * appropriate SDP to inform remote that the call is being put on hold.
+ * The final status of the request itself will be reported on the
+ * \a on_call_media_state() callback, which inform the application that
+ * the media state of the call has changed.
+ *
+ * @param call_id Call identification.
+ * @param msg_data Optional message components to be sent with
+ * the request.
+ *
+ * @return PJ_SUCCESS on success, or the appropriate error code.
+ */
+PJ_DECL(pj_status_t) pjsua_call_set_hold(pjsua_call_id call_id,
+ const pjsua_msg_data *msg_data);
+
+
+/**
+ * Send re-INVITE to release hold.
+ * The final status of the request itself will be reported on the
+ * \a on_call_media_state() callback, which inform the application that
+ * the media state of the call has changed.
+ *
+ * @param call_id Call identification.
+ * @param options Bitmask of pjsua_call_flag constants. Note that
+ * for compatibility, specifying PJ_TRUE here is
+ * equal to specifying PJSUA_CALL_UNHOLD flag.
+ * @param msg_data Optional message components to be sent with
+ * the request.
+ *
+ * @return PJ_SUCCESS on success, or the appropriate error code.
+ */
+PJ_DECL(pj_status_t) pjsua_call_reinvite(pjsua_call_id call_id,
+ unsigned options,
+ const pjsua_msg_data *msg_data);
+
+
+/**
+ * Send re-INVITE to release hold.
+ * The final status of the request itself will be reported on the
+ * \a on_call_media_state() callback, which inform the application that
+ * the media state of the call has changed.
+ *
+ * @param call_id Call identification.
+ * @param opt Optional call setting, if NULL, the current call
+ * setting will remain unchanged.
+ * @param msg_data Optional message components to be sent with
+ * the request.
+ *
+ * @return PJ_SUCCESS on success, or the appropriate error code.
+ */
+PJ_DECL(pj_status_t) pjsua_call_reinvite2(pjsua_call_id call_id,
+ const pjsua_call_setting *opt,
+ const pjsua_msg_data *msg_data);
+
+
+/**
+ * Send UPDATE request.
+ *
+ * @param call_id Call identification.
+ * @param options Bitmask of pjsua_call_flag constants.
+ * @param msg_data Optional message components to be sent with
+ * the request.
+ *
+ * @return PJ_SUCCESS on success, or the appropriate error code.
+ */
+PJ_DECL(pj_status_t) pjsua_call_update(pjsua_call_id call_id,
+ unsigned options,
+ const pjsua_msg_data *msg_data);
+
+
+/**
+ * Send UPDATE request.
+ *
+ * @param call_id Call identification.
+ * @param opt Optional call setting, if NULL, the current call
+ * setting will remain unchanged.
+ * @param msg_data Optional message components to be sent with
+ * the request.
+ *
+ * @return PJ_SUCCESS on success, or the appropriate error code.
+ */
+PJ_DECL(pj_status_t) pjsua_call_update2(pjsua_call_id call_id,
+ const pjsua_call_setting *opt,
+ const pjsua_msg_data *msg_data);
+
+
+/**
+ * Initiate call transfer to the specified address. This function will send
+ * REFER request to instruct remote call party to initiate a new INVITE
+ * session to the specified destination/target.
+ *
+ * If application is interested to monitor the successfulness and
+ * the progress of the transfer request, it can implement
+ * \a on_call_transfer_status() callback which will report the progress
+ * of the call transfer request.
+ *
+ * @param call_id The call id to be transfered.
+ * @param dest Address of new target to be contacted.
+ * @param msg_data Optional message components to be sent with
+ * the request.
+ *
+ * @return PJ_SUCCESS on success, or the appropriate error code.
+ */
+PJ_DECL(pj_status_t) pjsua_call_xfer(pjsua_call_id call_id,
+ const pj_str_t *dest,
+ const pjsua_msg_data *msg_data);
+
+/**
+ * Flag to indicate that "Require: replaces" should not be put in the
+ * outgoing INVITE request caused by REFER request created by
+ * #pjsua_call_xfer_replaces().
+ */
+#define PJSUA_XFER_NO_REQUIRE_REPLACES 1
+
+/**
+ * Initiate attended call transfer. This function will send REFER request
+ * to instruct remote call party to initiate new INVITE session to the URL
+ * of \a dest_call_id. The party at \a dest_call_id then should "replace"
+ * the call with us with the new call from the REFER recipient.
+ *
+ * @param call_id The call id to be transfered.
+ * @param dest_call_id The call id to be replaced.
+ * @param options Application may specify PJSUA_XFER_NO_REQUIRE_REPLACES
+ * to suppress the inclusion of "Require: replaces" in
+ * the outgoing INVITE request created by the REFER
+ * request.
+ * @param msg_data Optional message components to be sent with
+ * the request.
+ *
+ * @return PJ_SUCCESS on success, or the appropriate error code.
+ */
+PJ_DECL(pj_status_t) pjsua_call_xfer_replaces(pjsua_call_id call_id,
+ pjsua_call_id dest_call_id,
+ unsigned options,
+ const pjsua_msg_data *msg_data);
+
+/**
+ * Send DTMF digits to remote using RFC 2833 payload formats.
+ *
+ * @param call_id Call identification.
+ * @param digits DTMF string digits to be sent.
+ *
+ * @return PJ_SUCCESS on success, or the appropriate error code.
+ */
+PJ_DECL(pj_status_t) pjsua_call_dial_dtmf(pjsua_call_id call_id,
+ const pj_str_t *digits);
+
+/**
+ * Send instant messaging inside INVITE session.
+ *
+ * @param call_id Call identification.
+ * @param mime_type Optional MIME type. If NULL, then "text/plain" is
+ * assumed.
+ * @param content The message content.
+ * @param msg_data Optional list of headers etc to be included in outgoing
+ * request. The body descriptor in the msg_data is
+ * ignored.
+ * @param user_data Optional user data, which will be given back when
+ * the IM callback is called.
+ *
+ * @return PJ_SUCCESS on success, or the appropriate error code.
+ */
+PJ_DECL(pj_status_t) pjsua_call_send_im( pjsua_call_id call_id,
+ const pj_str_t *mime_type,
+ const pj_str_t *content,
+ const pjsua_msg_data *msg_data,
+ void *user_data);
+
+
+/**
+ * Send IM typing indication inside INVITE session.
+ *
+ * @param call_id Call identification.
+ * @param is_typing Non-zero to indicate to remote that local person is
+ * currently typing an IM.
+ * @param msg_data Optional list of headers etc to be included in outgoing
+ * request.
+ *
+ * @return PJ_SUCCESS on success, or the appropriate error code.
+ */
+PJ_DECL(pj_status_t) pjsua_call_send_typing_ind(pjsua_call_id call_id,
+ pj_bool_t is_typing,
+ const pjsua_msg_data*msg_data);
+
+/**
+ * Send arbitrary request with the call. This is useful for example to send
+ * INFO request. Note that application should not use this function to send
+ * requests which would change the invite session's state, such as re-INVITE,
+ * UPDATE, PRACK, and BYE.
+ *
+ * @param call_id Call identification.
+ * @param method SIP method of the request.
+ * @param msg_data Optional message body and/or list of headers to be
+ * included in outgoing request.
+ *
+ * @return PJ_SUCCESS on success, or the appropriate error code.
+ */
+PJ_DECL(pj_status_t) pjsua_call_send_request(pjsua_call_id call_id,
+ const pj_str_t *method,
+ const pjsua_msg_data *msg_data);
+
+
+/**
+ * Terminate all calls. This will initiate #pjsua_call_hangup() for all
+ * currently active calls.
+ */
+PJ_DECL(void) pjsua_call_hangup_all(void);
+
+
+/**
+ * Dump call and media statistics to string.
+ *
+ * @param call_id Call identification.
+ * @param with_media Non-zero to include media information too.
+ * @param buffer Buffer where the statistics are to be written to.
+ * @param maxlen Maximum length of buffer.
+ * @param indent Spaces for left indentation.
+ *
+ * @return PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjsua_call_dump(pjsua_call_id call_id,
+ pj_bool_t with_media,
+ char *buffer,
+ unsigned maxlen,
+ const char *indent);
+
+/**
+ * Get the media stream index of the default video stream in the call.
+ * Typically this will just retrieve the stream index of the first
+ * activated video stream in the call. If none is active, it will return
+ * the first inactive video stream.
+ *
+ * @param call_id Call identification.
+ *
+ * @return The media stream index or -1 if no video stream
+ * is present in the call.
+ */
+PJ_DECL(int) pjsua_call_get_vid_stream_idx(pjsua_call_id call_id);
+
+
+/**
+ * Determine if video stream for the specified call is currently running
+ * (i.e. has been created, started, and not being paused) for the specified
+ * direction.
+ *
+ * @param call_id Call identification.
+ * @param med_idx Media stream index, or -1 to specify default video
+ * media.
+ * @param dir The direction to be checked.
+ *
+ * @return PJ_TRUE if stream is currently running for the
+ * specified direction.
+ */
+PJ_DECL(pj_bool_t) pjsua_call_vid_stream_is_running(pjsua_call_id call_id,
+ int med_idx,
+ pjmedia_dir dir);
+
+/**
+ * Add, remove, modify, and/or manipulate video media stream for the
+ * specified call. This may trigger a re-INVITE or UPDATE to be sent
+ * for the call.
+ *
+ * @param call_id Call identification.
+ * @param op The video stream operation to be performed,
+ * possible values are #pjsua_call_vid_strm_op.
+ * @param param The parameters for the video stream operation,
+ * or NULL for the default parameter values
+ * (see #pjsua_call_vid_strm_op_param).
+ *
+ * @return PJ_SUCCESS on success or the appropriate error.
+ */
+PJ_DECL(pj_status_t) pjsua_call_set_vid_strm (
+ pjsua_call_id call_id,
+ pjsua_call_vid_strm_op op,
+ const pjsua_call_vid_strm_op_param *param);
+
+
+/**
+ * Get media stream info for the specified media index.
+ *
+ * @param call_id The call identification.
+ * @param med_idx Media stream index.
+ * @param psi To be filled with the stream info.
+ *
+ * @return PJ_SUCCESS on success or the appropriate error.
+ */
+PJ_DECL(pj_status_t) pjsua_call_get_stream_info(pjsua_call_id call_id,
+ unsigned med_idx,
+ pjsua_stream_info *psi);
+
+/**
+ * Get media stream statistic for the specified media index.
+ *
+ * @param call_id The call identification.
+ * @param med_idx Media stream index.
+ * @param psi To be filled with the stream statistic.
+ *
+ * @return PJ_SUCCESS on success or the appropriate error.
+ */
+PJ_DECL(pj_status_t) pjsua_call_get_stream_stat(pjsua_call_id call_id,
+ unsigned med_idx,
+ pjsua_stream_stat *stat);
+
+/**
+ * Get media transport info for the specified media index.
+ *
+ * @param call_id The call identification.
+ * @param med_idx Media stream index.
+ * @param t To be filled with the transport info.
+ *
+ * @return PJ_SUCCESS on success or the appropriate error.
+ */
+PJ_DECL(pj_status_t)
+pjsua_call_get_med_transport_info(pjsua_call_id call_id,
+ unsigned med_idx,
+ pjmedia_transport_info *t);
+
+
+
+/**
+ * @}
+ */
+
+
+/*****************************************************************************
+ * BUDDY API
+ */
+
+
+/**
+ * @defgroup PJSUA_LIB_BUDDY PJSUA-API Buddy, Presence, and Instant Messaging
+ * @ingroup PJSUA_LIB
+ * @brief Buddy management, buddy's presence, and instant messaging.
+ * @{
+ *
+ * This section describes PJSUA-APIs related to buddies management,
+ * presence management, and instant messaging.
+ */
+
+/**
+ * Max buddies in buddy list.
+ */
+#ifndef PJSUA_MAX_BUDDIES
+# define PJSUA_MAX_BUDDIES 256
+#endif
+
+
+/**
+ * This specifies how long the library should wait before retrying failed
+ * SUBSCRIBE request, and there is no rule to automatically resubscribe
+ * (for example, no "retry-after" parameter in Subscription-State header).
+ *
+ * This also controls the duration before failed PUBLISH request will be
+ * retried.
+ *
+ * Default: 300 seconds
+ */
+#ifndef PJSUA_PRES_TIMER
+# define PJSUA_PRES_TIMER 300
+#endif
+
+
+/**
+ * This structure describes buddy configuration when adding a buddy to
+ * the buddy list with #pjsua_buddy_add(). Application MUST initialize
+ * the structure with #pjsua_buddy_config_default() to initialize this
+ * structure with default configuration.
+ */
+typedef struct pjsua_buddy_config
+{
+ /**
+ * Buddy URL or name address.
+ */
+ pj_str_t uri;
+
+ /**
+ * Specify whether presence subscription should start immediately.
+ */
+ pj_bool_t subscribe;
+
+ /**
+ * Specify arbitrary application data to be associated with with
+ * the buddy object.
+ */
+ void *user_data;
+
+} pjsua_buddy_config;
+
+
+/**
+ * This enumeration describes basic buddy's online status.
+ */
+typedef enum pjsua_buddy_status
+{
+ /**
+ * Online status is unknown (possibly because no presence subscription
+ * has been established).
+ */
+ PJSUA_BUDDY_STATUS_UNKNOWN,
+
+ /**
+ * Buddy is known to be online.
+ */
+ PJSUA_BUDDY_STATUS_ONLINE,
+
+ /**
+ * Buddy is offline.
+ */
+ PJSUA_BUDDY_STATUS_OFFLINE,
+
+} pjsua_buddy_status;
+
+
+
+/**
+ * This structure describes buddy info, which can be retrieved by calling
+ * #pjsua_buddy_get_info().
+ */
+typedef struct pjsua_buddy_info
+{
+ /**
+ * The buddy ID.
+ */
+ pjsua_buddy_id id;
+
+ /**
+ * The full URI of the buddy, as specified in the configuration.
+ */
+ pj_str_t uri;
+
+ /**
+ * Buddy's Contact, only available when presence subscription has
+ * been established to the buddy.
+ */
+ pj_str_t contact;
+
+ /**
+ * Buddy's online status.
+ */
+ pjsua_buddy_status status;
+
+ /**
+ * Text to describe buddy's online status.
+ */
+ pj_str_t status_text;
+
+ /**
+ * Flag to indicate that we should monitor the presence information for
+ * this buddy (normally yes, unless explicitly disabled).
+ */
+ pj_bool_t monitor_pres;
+
+ /**
+ * If \a monitor_pres is enabled, this specifies the last state of the
+ * presence subscription. If presence subscription session is currently
+ * active, the value will be PJSIP_EVSUB_STATE_ACTIVE. If presence
+ * subscription request has been rejected, the value will be
+ * PJSIP_EVSUB_STATE_TERMINATED, and the termination reason will be
+ * specified in \a sub_term_reason.
+ */
+ pjsip_evsub_state sub_state;
+
+ /**
+ * String representation of subscription state.
+ */
+ const char *sub_state_name;
+
+ /**
+ * Specifies the last presence subscription termination code. This would
+ * return the last status of the SUBSCRIBE request. If the subscription
+ * is terminated with NOTIFY by the server, this value will be set to
+ * 200, and subscription termination reason will be given in the
+ * \a sub_term_reason field.
+ */
+ unsigned sub_term_code;
+
+ /**
+ * Specifies the last presence subscription termination reason. If
+ * presence subscription is currently active, the value will be empty.
+ */
+ pj_str_t sub_term_reason;
+
+ /**
+ * Extended RPID information about the person.
+ */
+ pjrpid_element rpid;
+
+ /**
+ * Extended presence info.
+ */
+ pjsip_pres_status pres_status;
+
+ /**
+ * Internal buffer.
+ */
+ char buf_[512];
+
+} pjsua_buddy_info;
+
+
+/**
+ * Set default values to the buddy config.
+ */
+PJ_DECL(void) pjsua_buddy_config_default(pjsua_buddy_config *cfg);
+
+
+/**
+ * Get total number of buddies.
+ *
+ * @return Number of buddies.
+ */
+PJ_DECL(unsigned) pjsua_get_buddy_count(void);
+
+
+/**
+ * Check if buddy ID is valid.
+ *
+ * @param buddy_id Buddy ID to check.
+ *
+ * @return Non-zero if buddy ID is valid.
+ */
+PJ_DECL(pj_bool_t) pjsua_buddy_is_valid(pjsua_buddy_id buddy_id);
+
+
+/**
+ * Enumerate all buddy IDs in the buddy list. Application then can use
+ * #pjsua_buddy_get_info() to get the detail information for each buddy
+ * id.
+ *
+ * @param ids Array of ids to be initialized.
+ * @param count On input, specifies max elements in the array.
+ * On return, it contains actual number of elements
+ * that have been initialized.
+ *
+ * @return PJ_SUCCESS on success, or the appropriate error code.
+ */
+PJ_DECL(pj_status_t) pjsua_enum_buddies(pjsua_buddy_id ids[],
+ unsigned *count);
+
+/**
+ * Find the buddy ID with the specified URI.
+ *
+ * @param uri The buddy URI.
+ *
+ * @return The buddy ID, or PJSUA_INVALID_ID if not found.
+ */
+PJ_DECL(pjsua_buddy_id) pjsua_buddy_find(const pj_str_t *uri);
+
+
+/**
+ * Get detailed buddy info.
+ *
+ * @param buddy_id The buddy identification.
+ * @param info Pointer to receive information about buddy.
+ *
+ * @return PJ_SUCCESS on success, or the appropriate error code.
+ */
+PJ_DECL(pj_status_t) pjsua_buddy_get_info(pjsua_buddy_id buddy_id,
+ pjsua_buddy_info *info);
+
+/**
+ * Set the user data associated with the buddy object.
+ *
+ * @param buddy_id The buddy identification.
+ * @param user_data Arbitrary application data to be associated with
+ * the buddy object.
+ *
+ * @return PJ_SUCCESS on success, or the appropriate error code.
+ */
+PJ_DECL(pj_status_t) pjsua_buddy_set_user_data(pjsua_buddy_id buddy_id,
+ void *user_data);
+
+
+/**
+ * Get the user data associated with the budy object.
+ *
+ * @param buddy_id The buddy identification.
+ *
+ * @return The application data.
+ */
+PJ_DECL(void*) pjsua_buddy_get_user_data(pjsua_buddy_id buddy_id);
+
+
+/**
+ * Add new buddy to the buddy list. If presence subscription is enabled
+ * for this buddy, this function will also start the presence subscription
+ * session immediately.
+ *
+ * @param buddy_cfg Buddy configuration.
+ * @param p_buddy_id Pointer to receive buddy ID.
+ *
+ * @return PJ_SUCCESS on success, or the appropriate error code.
+ */
+PJ_DECL(pj_status_t) pjsua_buddy_add(const pjsua_buddy_config *buddy_cfg,
+ pjsua_buddy_id *p_buddy_id);
+
+
+/**
+ * Delete the specified buddy from the buddy list. Any presence subscription
+ * to this buddy will be terminated.
+ *
+ * @param buddy_id Buddy identification.
+ *
+ * @return PJ_SUCCESS on success, or the appropriate error code.
+ */
+PJ_DECL(pj_status_t) pjsua_buddy_del(pjsua_buddy_id buddy_id);
+
+
+/**
+ * Enable/disable buddy's presence monitoring. Once buddy's presence is
+ * subscribed, application will be informed about buddy's presence status
+ * changed via \a on_buddy_state() callback.
+ *
+ * @param buddy_id Buddy identification.
+ * @param subscribe Specify non-zero to activate presence subscription to
+ * the specified buddy.
+ *
+ * @return PJ_SUCCESS on success, or the appropriate error code.
+ */
+PJ_DECL(pj_status_t) pjsua_buddy_subscribe_pres(pjsua_buddy_id buddy_id,
+ pj_bool_t subscribe);
+
+
+/**
+ * Update the presence information for the buddy. Although the library
+ * periodically refreshes the presence subscription for all buddies, some
+ * application may want to refresh the buddy's presence subscription
+ * immediately, and in this case it can use this function to accomplish
+ * this.
+ *
+ * Note that the buddy's presence subscription will only be initiated
+ * if presence monitoring is enabled for the buddy. See
+ * #pjsua_buddy_subscribe_pres() for more info. Also if presence subscription
+ * for the buddy is already active, this function will not do anything.
+ *
+ * Once the presence subscription is activated successfully for the buddy,
+ * application will be notified about the buddy's presence status in the
+ * on_buddy_state() callback.
+ *
+ * @param buddy_id Buddy identification.
+ *
+ * @return PJ_SUCCESS on success, or the appropriate error code.
+ */
+PJ_DECL(pj_status_t) pjsua_buddy_update_pres(pjsua_buddy_id buddy_id);
+
+
+/**
+ * Send NOTIFY to inform account presence status or to terminate server
+ * side presence subscription. If application wants to reject the incoming
+ * request, it should set the \a state to PJSIP_EVSUB_STATE_TERMINATED.
+ *
+ * @param acc_id Account ID.
+ * @param srv_pres Server presence subscription instance.
+ * @param state New state to set.
+ * @param state_str Optionally specify the state string name, if state
+ * is not "active", "pending", or "terminated".
+ * @param reason If the new state is PJSIP_EVSUB_STATE_TERMINATED,
+ * optionally specify the termination reason.
+ * @param with_body If the new state is PJSIP_EVSUB_STATE_TERMINATED,
+ * this specifies whether the NOTIFY request should
+ * contain message body containing account's presence
+ * information.
+ * @param msg_data Optional list of headers to be sent with the NOTIFY
+ * request.
+ *
+ * @return PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjsua_pres_notify(pjsua_acc_id acc_id,
+ pjsua_srv_pres *srv_pres,
+ pjsip_evsub_state state,
+ const pj_str_t *state_str,
+ const pj_str_t *reason,
+ pj_bool_t with_body,
+ const pjsua_msg_data *msg_data);
+
+/**
+ * Dump presence subscriptions to log.
+ *
+ * @param verbose Yes or no.
+ */
+PJ_DECL(void) pjsua_pres_dump(pj_bool_t verbose);
+
+
+/**
+ * The MESSAGE method (defined in pjsua_im.c)
+ */
+extern const pjsip_method pjsip_message_method;
+
+
+/**
+ * The INFO method (defined in pjsua_call.c)
+ */
+extern const pjsip_method pjsip_info_method;
+
+
+/**
+ * Send instant messaging outside dialog, using the specified account for
+ * route set and authentication.
+ *
+ * @param acc_id Account ID to be used to send the request.
+ * @param to Remote URI.
+ * @param mime_type Optional MIME type. If NULL, then "text/plain" is
+ * assumed.
+ * @param content The message content.
+ * @param msg_data Optional list of headers etc to be included in outgoing
+ * request. The body descriptor in the msg_data is
+ * ignored.
+ * @param user_data Optional user data, which will be given back when
+ * the IM callback is called.
+ *
+ * @return PJ_SUCCESS on success, or the appropriate error code.
+ */
+PJ_DECL(pj_status_t) pjsua_im_send(pjsua_acc_id acc_id,
+ const pj_str_t *to,
+ const pj_str_t *mime_type,
+ const pj_str_t *content,
+ const pjsua_msg_data *msg_data,
+ void *user_data);
+
+
+/**
+ * Send typing indication outside dialog.
+ *
+ * @param acc_id Account ID to be used to send the request.
+ * @param to Remote URI.
+ * @param is_typing If non-zero, it tells remote person that local person
+ * is currently composing an IM.
+ * @param msg_data Optional list of headers etc to be added to outgoing
+ * request.
+ *
+ * @return PJ_SUCCESS on success, or the appropriate error code.
+ */
+PJ_DECL(pj_status_t) pjsua_im_typing(pjsua_acc_id acc_id,
+ const pj_str_t *to,
+ pj_bool_t is_typing,
+ const pjsua_msg_data *msg_data);
+
+
+
+/**
+ * @}
+ */
+
+
+/*****************************************************************************
+ * MEDIA API
+ */
+
+
+/**
+ * @defgroup PJSUA_LIB_MEDIA PJSUA-API Media Manipulation
+ * @ingroup PJSUA_LIB
+ * @brief Media manipulation.
+ * @{
+ *
+ * PJSUA has rather powerful media features, which are built around the
+ * PJMEDIA conference bridge. Basically, all media "ports" (such as calls, WAV
+ * players, WAV playlist, file recorders, sound device, tone generators, etc)
+ * are terminated in the conference bridge, and application can manipulate
+ * the interconnection between these terminations freely.
+ *
+ * The conference bridge provides powerful switching and mixing functionality
+ * for application. With the conference bridge, each conference slot (e.g.
+ * a call) can transmit to multiple destinations, and one destination can
+ * receive from multiple sources. If more than one media terminations are
+ * terminated in the same slot, the conference bridge will mix the signal
+ * automatically.
+ *
+ * Application connects one media termination/slot to another by calling
+ * #pjsua_conf_connect() function. This will establish <b>unidirectional</b>
+ * media flow from the source termination to the sink termination. To
+ * establish bidirectional media flow, application wound need to make another
+ * call to #pjsua_conf_connect(), this time inverting the source and
+ * destination slots in the parameter.
+ *
+ * For example, to stream a WAV file to remote call, application may use
+ * the following steps:
+ *
+ \code
+
+ pj_status_t stream_to_call( pjsua_call_id call_id )
+ {
+ pjsua_player_id player_id;
+
+ status = pjsua_player_create("mysong.wav", 0, &player_id);
+ if (status != PJ_SUCCESS)
+ return status;
+
+ status = pjsua_conf_connect( pjsua_player_get_conf_port(),
+ pjsua_call_get_conf_port() );
+ }
+ \endcode
+ *
+ *
+ * Other features of PJSUA media:
+ * - efficient N to M interconnections between media terminations.
+ * - media termination can be connected to itself to create loopback
+ * media.
+ * - the media termination may have different clock rates, and resampling
+ * will be done automatically by conference bridge.
+ * - media terminations may also have different frame time; the
+ * conference bridge will perform the necessary bufferring to adjust
+ * the difference between terminations.
+ * - interconnections are removed automatically when media termination
+ * is removed from the bridge.
+ * - sound device may be changed even when there are active media
+ * interconnections.
+ * - correctly report call's media quality (in #pjsua_call_dump()) from
+ * RTCP packet exchange.
+ */
+
+/**
+ * Use PJMEDIA for media? Set this to zero when using third party media
+ * stack.
+ */
+#ifndef PJSUA_MEDIA_HAS_PJMEDIA
+# define PJSUA_MEDIA_HAS_PJMEDIA 1
+#endif /* PJSUA_MEDIA_HAS_PJMEDIA */
+
+
+/**
+ * Max ports in the conference bridge. This setting is the default value
+ * for pjsua_media_config.max_media_ports.
+ */
+#ifndef PJSUA_MAX_CONF_PORTS
+# define PJSUA_MAX_CONF_PORTS 254
+#endif
+
+/**
+ * The default clock rate to be used by the conference bridge. This setting
+ * is the default value for pjsua_media_config.clock_rate.
+ */
+#ifndef PJSUA_DEFAULT_CLOCK_RATE
+# define PJSUA_DEFAULT_CLOCK_RATE 16000
+#endif
+
+/**
+ * Default frame length in the conference bridge. This setting
+ * is the default value for pjsua_media_config.audio_frame_ptime.
+ */
+#ifndef PJSUA_DEFAULT_AUDIO_FRAME_PTIME
+# define PJSUA_DEFAULT_AUDIO_FRAME_PTIME 20
+#endif
+
+
+/**
+ * Default codec quality settings. This setting is the default value
+ * for pjsua_media_config.quality.
+ */
+#ifndef PJSUA_DEFAULT_CODEC_QUALITY
+# define PJSUA_DEFAULT_CODEC_QUALITY 8
+#endif
+
+/**
+ * Default iLBC mode. This setting is the default value for
+ * pjsua_media_config.ilbc_mode.
+ */
+#ifndef PJSUA_DEFAULT_ILBC_MODE
+# define PJSUA_DEFAULT_ILBC_MODE 30
+#endif
+
+/**
+ * The default echo canceller tail length. This setting
+ * is the default value for pjsua_media_config.ec_tail_len.
+ */
+#ifndef PJSUA_DEFAULT_EC_TAIL_LEN
+# define PJSUA_DEFAULT_EC_TAIL_LEN 200
+#endif
+
+
+/**
+ * The maximum file player.
+ */
+#ifndef PJSUA_MAX_PLAYERS
+# define PJSUA_MAX_PLAYERS 32
+#endif
+
+
+/**
+ * The maximum file player.
+ */
+#ifndef PJSUA_MAX_RECORDERS
+# define PJSUA_MAX_RECORDERS 32
+#endif
+
+
+/**
+ * This structure describes media configuration, which will be specified
+ * when calling #pjsua_init(). Application MUST initialize this structure
+ * by calling #pjsua_media_config_default().
+ */
+struct pjsua_media_config
+{
+ /**
+ * Clock rate to be applied to the conference bridge.
+ * If value is zero, default clock rate will be used
+ * (PJSUA_DEFAULT_CLOCK_RATE, which by default is 16KHz).
+ */
+ unsigned clock_rate;
+
+ /**
+ * Clock rate to be applied when opening the sound device.
+ * If value is zero, conference bridge clock rate will be used.
+ */
+ unsigned snd_clock_rate;
+
+ /**
+ * Channel count be applied when opening the sound device and
+ * conference bridge.
+ */
+ unsigned channel_count;
+
+ /**
+ * Specify audio frame ptime. The value here will affect the
+ * samples per frame of both the sound device and the conference
+ * bridge. Specifying lower ptime will normally reduce the
+ * latency.
+ *
+ * Default value: PJSUA_DEFAULT_AUDIO_FRAME_PTIME
+ */
+ unsigned audio_frame_ptime;
+
+ /**
+ * Specify maximum number of media ports to be created in the
+ * conference bridge. Since all media terminate in the bridge
+ * (calls, file player, file recorder, etc), the value must be
+ * large enough to support all of them. However, the larger
+ * the value, the more computations are performed.
+ *
+ * Default value: PJSUA_MAX_CONF_PORTS
+ */
+ unsigned max_media_ports;
+
+ /**
+ * Specify whether the media manager should manage its own
+ * ioqueue for the RTP/RTCP sockets. If yes, ioqueue will be created
+ * and at least one worker thread will be created too. If no,
+ * the RTP/RTCP sockets will share the same ioqueue as SIP sockets,
+ * and no worker thread is needed.
+ *
+ * Normally application would say yes here, unless it wants to
+ * run everything from a single thread.
+ */
+ pj_bool_t has_ioqueue;
+
+ /**
+ * Specify the number of worker threads to handle incoming RTP
+ * packets. A value of one is recommended for most applications.
+ */
+ unsigned thread_cnt;
+
+ /**
+ * Media quality, 0-10, according to this table:
+ * 5-10: resampling use large filter,
+ * 3-4: resampling use small filter,
+ * 1-2: resampling use linear.
+ * The media quality also sets speex codec quality/complexity to the
+ * number.
+ *
+ * Default: 5 (PJSUA_DEFAULT_CODEC_QUALITY).
+ */
+ unsigned quality;
+
+ /**
+ * Specify default codec ptime.
+ *
+ * Default: 0 (codec specific)
+ */
+ unsigned ptime;
+
+ /**
+ * Disable VAD?
+ *
+ * Default: 0 (no (meaning VAD is enabled))
+ */
+ pj_bool_t no_vad;
+
+ /**
+ * iLBC mode (20 or 30).
+ *
+ * Default: 30 (PJSUA_DEFAULT_ILBC_MODE)
+ */
+ unsigned ilbc_mode;
+
+ /**
+ * Percentage of RTP packet to drop in TX direction
+ * (to simulate packet lost).
+ *
+ * Default: 0
+ */
+ unsigned tx_drop_pct;
+
+ /**
+ * Percentage of RTP packet to drop in RX direction
+ * (to simulate packet lost).
+ *
+ * Default: 0
+ */
+ unsigned rx_drop_pct;
+
+ /**
+ * Echo canceller options (see #pjmedia_echo_create())
+ *
+ * Default: 0.
+ */
+ unsigned ec_options;
+
+ /**
+ * Echo canceller tail length, in miliseconds.
+ *
+ * Default: PJSUA_DEFAULT_EC_TAIL_LEN
+ */
+ unsigned ec_tail_len;
+
+ /**
+ * Audio capture buffer length, in milliseconds.
+ *
+ * Default: PJMEDIA_SND_DEFAULT_REC_LATENCY
+ */
+ unsigned snd_rec_latency;
+
+ /**
+ * Audio playback buffer length, in milliseconds.
+ *
+ * Default: PJMEDIA_SND_DEFAULT_PLAY_LATENCY
+ */
+ unsigned snd_play_latency;
+
+ /**
+ * Jitter buffer initial prefetch delay in msec. The value must be
+ * between jb_min_pre and jb_max_pre below.
+ *
+ * Default: -1 (to use default stream settings, currently 150 msec)
+ */
+ int jb_init;
+
+ /**
+ * Jitter buffer minimum prefetch delay in msec.
+ *
+ * Default: -1 (to use default stream settings, currently 60 msec)
+ */
+ int jb_min_pre;
+
+ /**
+ * Jitter buffer maximum prefetch delay in msec.
+ *
+ * Default: -1 (to use default stream settings, currently 240 msec)
+ */
+ int jb_max_pre;
+
+ /**
+ * Set maximum delay that can be accomodated by the jitter buffer msec.
+ *
+ * Default: -1 (to use default stream settings, currently 360 msec)
+ */
+ int jb_max;
+
+ /**
+ * Enable ICE
+ */
+ pj_bool_t enable_ice;
+
+ /**
+ * Set the maximum number of host candidates.
+ *
+ * Default: -1 (maximum not set)
+ */
+ int ice_max_host_cands;
+
+ /**
+ * ICE session options.
+ */
+ pj_ice_sess_options ice_opt;
+
+ /**
+ * Disable RTCP component.
+ *
+ * Default: no
+ */
+ pj_bool_t ice_no_rtcp;
+
+ /**
+ * Enable TURN relay candidate in ICE.
+ */
+ pj_bool_t enable_turn;
+
+ /**
+ * Specify TURN domain name or host name, in in "DOMAIN:PORT" or
+ * "HOST:PORT" format.
+ */
+ pj_str_t turn_server;
+
+ /**
+ * Specify the connection type to be used to the TURN server. Valid
+ * values are PJ_TURN_TP_UDP or PJ_TURN_TP_TCP.
+ *
+ * Default: PJ_TURN_TP_UDP
+ */
+ pj_turn_tp_type turn_conn_type;
+
+ /**
+ * Specify the credential to authenticate with the TURN server.
+ */
+ pj_stun_auth_cred turn_auth_cred;
+
+ /**
+ * Specify idle time of sound device before it is automatically closed,
+ * in seconds. Use value -1 to disable the auto-close feature of sound
+ * device
+ *
+ * Default : 1
+ */
+ int snd_auto_close_time;
+
+ /**
+ * Specify whether built-in/native preview should be used if available.
+ * In some systems, video input devices have built-in capability to show
+ * preview window of the device. Using this built-in preview is preferable
+ * as it consumes less CPU power. If built-in preview is not available,
+ * the library will perform software rendering of the input. If this
+ * field is set to PJ_FALSE, software preview will always be used.
+ *
+ * Default: PJ_TRUE
+ */
+ pj_bool_t vid_preview_enable_native;
+};
+
+
+/**
+ * Use this function to initialize media config.
+ *
+ * @param cfg The media config to be initialized.
+ */
+PJ_DECL(void) pjsua_media_config_default(pjsua_media_config *cfg);
+
+
+/**
+ * This structure describes codec information, which can be retrieved by
+ * calling #pjsua_enum_codecs().
+ */
+typedef struct pjsua_codec_info
+{
+ /**
+ * Codec unique identification.
+ */
+ pj_str_t codec_id;
+
+ /**
+ * Codec priority (integer 0-255).
+ */
+ pj_uint8_t priority;
+
+ /**
+ * Codec description.
+ */
+ pj_str_t desc;
+
+ /**
+ * Internal buffer.
+ */
+ char buf_[64];
+
+} pjsua_codec_info;
+
+
+/**
+ * This structure descibes information about a particular media port that
+ * has been registered into the conference bridge. Application can query
+ * this info by calling #pjsua_conf_get_port_info().
+ */
+typedef struct pjsua_conf_port_info
+{
+ /** Conference port number. */
+ pjsua_conf_port_id slot_id;
+
+ /** Port name. */
+ pj_str_t name;
+
+ /** Clock rate. */
+ unsigned clock_rate;
+
+ /** Number of channels. */
+ unsigned channel_count;
+
+ /** Samples per frame */
+ unsigned samples_per_frame;
+
+ /** Bits per sample */
+ unsigned bits_per_sample;
+
+ /** Number of listeners in the array. */
+ unsigned listener_cnt;
+
+ /** Array of listeners (in other words, ports where this port is
+ * transmitting to.
+ */
+ pjsua_conf_port_id listeners[PJSUA_MAX_CONF_PORTS];
+
+} pjsua_conf_port_info;
+
+
+/**
+ * This structure holds information about custom media transport to
+ * be registered to pjsua.
+ */
+typedef struct pjsua_media_transport
+{
+ /**
+ * Media socket information containing the address information
+ * of the RTP and RTCP socket.
+ */
+ pjmedia_sock_info skinfo;
+
+ /**
+ * The media transport instance.
+ */
+ pjmedia_transport *transport;
+
+} pjsua_media_transport;
+
+
+/**
+ * Get maxinum number of conference ports.
+ *
+ * @return Maximum number of ports in the conference bridge.
+ */
+PJ_DECL(unsigned) pjsua_conf_get_max_ports(void);
+
+
+/**
+ * Get current number of active ports in the bridge.
+ *
+ * @return The number.
+ */
+PJ_DECL(unsigned) pjsua_conf_get_active_ports(void);
+
+
+/**
+ * Enumerate all conference ports.
+ *
+ * @param id Array of conference port ID to be initialized.
+ * @param count On input, specifies max elements in the array.
+ * On return, it contains actual number of elements
+ * that have been initialized.
+ *
+ * @return PJ_SUCCESS on success, or the appropriate error code.
+ */
+PJ_DECL(pj_status_t) pjsua_enum_conf_ports(pjsua_conf_port_id id[],
+ unsigned *count);
+
+
+/**
+ * Get information about the specified conference port
+ *
+ * @param port_id Port identification.
+ * @param info Pointer to store the port info.
+ *
+ * @return PJ_SUCCESS on success, or the appropriate error code.
+ */
+PJ_DECL(pj_status_t) pjsua_conf_get_port_info( pjsua_conf_port_id port_id,
+ pjsua_conf_port_info *info);
+
+
+/**
+ * Add arbitrary media port to PJSUA's conference bridge. Application
+ * can use this function to add the media port that it creates. For
+ * media ports that are created by PJSUA-LIB (such as calls, file player,
+ * or file recorder), PJSUA-LIB will automatically add the port to
+ * the bridge.
+ *
+ * @param pool Pool to use.
+ * @param port Media port to be added to the bridge.
+ * @param p_id Optional pointer to receive the conference
+ * slot id.
+ *
+ * @return PJ_SUCCESS on success, or the appropriate error code.
+ */
+PJ_DECL(pj_status_t) pjsua_conf_add_port(pj_pool_t *pool,
+ pjmedia_port *port,
+ pjsua_conf_port_id *p_id);
+
+
+/**
+ * Remove arbitrary slot from the conference bridge. Application should only
+ * call this function if it registered the port manually with previous call
+ * to #pjsua_conf_add_port().
+ *
+ * @param port_id The slot id of the port to be removed.
+ *
+ * @return PJ_SUCCESS on success, or the appropriate error code.
+ */
+PJ_DECL(pj_status_t) pjsua_conf_remove_port(pjsua_conf_port_id port_id);
+
+
+/**
+ * Establish unidirectional media flow from souce to sink. One source
+ * may transmit to multiple destinations/sink. And if multiple
+ * sources are transmitting to the same sink, the media will be mixed
+ * together. Source and sink may refer to the same ID, effectively
+ * looping the media.
+ *
+ * If bidirectional media flow is desired, application needs to call
+ * this function twice, with the second one having the arguments
+ * reversed.
+ *
+ * @param source Port ID of the source media/transmitter.
+ * @param sink Port ID of the destination media/received.
+ *
+ * @return PJ_SUCCESS on success, or the appropriate error code.
+ */
+PJ_DECL(pj_status_t) pjsua_conf_connect(pjsua_conf_port_id source,
+ pjsua_conf_port_id sink);
+
+
+/**
+ * Disconnect media flow from the source to destination port.
+ *
+ * @param source Port ID of the source media/transmitter.
+ * @param sink Port ID of the destination media/received.
+ *
+ * @return PJ_SUCCESS on success, or the appropriate error code.
+ */
+PJ_DECL(pj_status_t) pjsua_conf_disconnect(pjsua_conf_port_id source,
+ pjsua_conf_port_id sink);
+
+
+/**
+ * Adjust the signal level to be transmitted from the bridge to the
+ * specified port by making it louder or quieter.
+ *
+ * @param slot The conference bridge slot number.
+ * @param level Signal level adjustment. Value 1.0 means no level
+ * adjustment, while value 0 means to mute the port.
+ *
+ * @return PJ_SUCCESS on success, or the appropriate error code.
+ */
+PJ_DECL(pj_status_t) pjsua_conf_adjust_tx_level(pjsua_conf_port_id slot,
+ float level);
+
+/**
+ * Adjust the signal level to be received from the specified port (to
+ * the bridge) by making it louder or quieter.
+ *
+ * @param slot The conference bridge slot number.
+ * @param level Signal level adjustment. Value 1.0 means no level
+ * adjustment, while value 0 means to mute the port.
+ *
+ * @return PJ_SUCCESS on success, or the appropriate error code.
+ */
+PJ_DECL(pj_status_t) pjsua_conf_adjust_rx_level(pjsua_conf_port_id slot,
+ float level);
+
+/**
+ * Get last signal level transmitted to or received from the specified port.
+ * The signal level is an integer value in zero to 255, with zero indicates
+ * no signal, and 255 indicates the loudest signal level.
+ *
+ * @param slot The conference bridge slot number.
+ * @param tx_level Optional argument to receive the level of signal
+ * transmitted to the specified port (i.e. the direction
+ * is from the bridge to the port).
+ * @param rx_level Optional argument to receive the level of signal
+ * received from the port (i.e. the direction is from the
+ * port to the bridge).
+ *
+ * @return PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjsua_conf_get_signal_level(pjsua_conf_port_id slot,
+ unsigned *tx_level,
+ unsigned *rx_level);
+
+
+/*****************************************************************************
+ * File player and playlist.
+ */
+
+/**
+ * Create a file player, and automatically add this player to
+ * the conference bridge.
+ *
+ * @param filename The filename to be played. Currently only
+ * WAV files are supported, and the WAV file MUST be
+ * formatted as 16bit PCM mono/single channel (any
+ * clock rate is supported).
+ * @param options Optional option flag. Application may specify
+ * PJMEDIA_FILE_NO_LOOP to prevent playback loop.
+ * @param p_id Pointer to receive player ID.
+ *
+ * @return PJ_SUCCESS on success, or the appropriate error code.
+ */
+PJ_DECL(pj_status_t) pjsua_player_create(const pj_str_t *filename,
+ unsigned options,
+ pjsua_player_id *p_id);
+
+
+/**
+ * Create a file playlist media port, and automatically add the port
+ * to the conference bridge.
+ *
+ * @param file_names Array of file names to be added to the play list.
+ * Note that the files must have the same clock rate,
+ * number of channels, and number of bits per sample.
+ * @param file_count Number of files in the array.
+ * @param label Optional label to be set for the media port.
+ * @param options Optional option flag. Application may specify
+ * PJMEDIA_FILE_NO_LOOP to prevent looping.
+ * @param p_id Optional pointer to receive player ID.
+ *
+ * @return PJ_SUCCESS on success, or the appropriate error code.
+ */
+PJ_DECL(pj_status_t) pjsua_playlist_create(const pj_str_t file_names[],
+ unsigned file_count,
+ const pj_str_t *label,
+ unsigned options,
+ pjsua_player_id *p_id);
+
+/**
+ * Get conference port ID associated with player or playlist.
+ *
+ * @param id The file player ID.
+ *
+ * @return Conference port ID associated with this player.
+ */
+PJ_DECL(pjsua_conf_port_id) pjsua_player_get_conf_port(pjsua_player_id id);
+
+
+/**
+ * Get the media port for the player or playlist.
+ *
+ * @param id The player ID.
+ * @param p_port The media port associated with the player.
+ *
+ * @return PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjsua_player_get_port(pjsua_player_id id,
+ pjmedia_port **p_port);
+
+/**
+ * Set playback position. This operation is not valid for playlist.
+ *
+ * @param id The file player ID.
+ * @param samples The playback position, in samples. Application can
+ * specify zero to re-start the playback.
+ *
+ * @return PJ_SUCCESS on success, or the appropriate error code.
+ */
+PJ_DECL(pj_status_t) pjsua_player_set_pos(pjsua_player_id id,
+ pj_uint32_t samples);
+
+
+/**
+ * Close the file of playlist, remove the player from the bridge, and free
+ * resources associated with the file player or playlist.
+ *
+ * @param id The file player ID.
+ *
+ * @return PJ_SUCCESS on success, or the appropriate error code.
+ */
+PJ_DECL(pj_status_t) pjsua_player_destroy(pjsua_player_id id);
+
+
+/*****************************************************************************
+ * File recorder.
+ */
+
+/**
+ * Create a file recorder, and automatically connect this recorder to
+ * the conference bridge. The recorder currently supports recording WAV file.
+ * The type of the recorder to use is determined by the extension of the file
+ * (e.g. ".wav").
+ *
+ * @param filename Output file name. The function will determine the
+ * default format to be used based on the file extension.
+ * Currently ".wav" is supported on all platforms.
+ * @param enc_type Optionally specify the type of encoder to be used to
+ * compress the media, if the file can support different
+ * encodings. This value must be zero for now.
+ * @param enc_param Optionally specify codec specific parameter to be
+ * passed to the file writer.
+ * For .WAV recorder, this value must be NULL.
+ * @param max_size Maximum file size. Specify zero or -1 to remove size
+ * limitation. This value must be zero or -1 for now.
+ * @param options Optional options.
+ * @param p_id Pointer to receive the recorder instance.
+ *
+ * @return PJ_SUCCESS on success, or the appropriate error code.
+ */
+PJ_DECL(pj_status_t) pjsua_recorder_create(const pj_str_t *filename,
+ unsigned enc_type,
+ void *enc_param,
+ pj_ssize_t max_size,
+ unsigned options,
+ pjsua_recorder_id *p_id);
+
+
+/**
+ * Get conference port associated with recorder.
+ *
+ * @param id The recorder ID.
+ *
+ * @return Conference port ID associated with this recorder.
+ */
+PJ_DECL(pjsua_conf_port_id) pjsua_recorder_get_conf_port(pjsua_recorder_id id);
+
+
+/**
+ * Get the media port for the recorder.
+ *
+ * @param id The recorder ID.
+ * @param p_port The media port associated with the recorder.
+ *
+ * @return PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjsua_recorder_get_port(pjsua_recorder_id id,
+ pjmedia_port **p_port);
+
+
+/**
+ * Destroy recorder (this will complete recording).
+ *
+ * @param id The recorder ID.
+ *
+ * @return PJ_SUCCESS on success, or the appropriate error code.
+ */
+PJ_DECL(pj_status_t) pjsua_recorder_destroy(pjsua_recorder_id id);
+
+
+/*****************************************************************************
+ * Sound devices.
+ */
+
+/**
+ * Enum all audio devices installed in the system.
+ *
+ * @param info Array of info to be initialized.
+ * @param count On input, specifies max elements in the array.
+ * On return, it contains actual number of elements
+ * that have been initialized.
+ *
+ * @return PJ_SUCCESS on success, or the appropriate error code.
+ */
+PJ_DECL(pj_status_t) pjsua_enum_aud_devs(pjmedia_aud_dev_info info[],
+ unsigned *count);
+
+/**
+ * Enum all sound devices installed in the system (old API).
+ *
+ * @param info Array of info to be initialized.
+ * @param count On input, specifies max elements in the array.
+ * On return, it contains actual number of elements
+ * that have been initialized.
+ *
+ * @return PJ_SUCCESS on success, or the appropriate error code.
+ */
+PJ_DECL(pj_status_t) pjsua_enum_snd_devs(pjmedia_snd_dev_info info[],
+ unsigned *count);
+
+/**
+ * Get currently active sound devices. If sound devices has not been created
+ * (for example when pjsua_start() is not called), it is possible that
+ * the function returns PJ_SUCCESS with -1 as device IDs.
+ *
+ * @param capture_dev On return it will be filled with device ID of the
+ * capture device.
+ * @param playback_dev On return it will be filled with device ID of the
+ * device ID of the playback device.
+ *
+ * @return PJ_SUCCESS on success, or the appropriate error code.
+ */
+PJ_DECL(pj_status_t) pjsua_get_snd_dev(int *capture_dev,
+ int *playback_dev);
+
+
+/**
+ * Select or change sound device. Application may call this function at
+ * any time to replace current sound device.
+ *
+ * @param capture_dev Device ID of the capture device.
+ * @param playback_dev Device ID of the playback device.
+ *
+ * @return PJ_SUCCESS on success, or the appropriate error code.
+ */
+PJ_DECL(pj_status_t) pjsua_set_snd_dev(int capture_dev,
+ int playback_dev);
+
+
+/**
+ * Set pjsua to use null sound device. The null sound device only provides
+ * the timing needed by the conference bridge, and will not interract with
+ * any hardware.
+ *
+ * @return PJ_SUCCESS on success, or the appropriate error code.
+ */
+PJ_DECL(pj_status_t) pjsua_set_null_snd_dev(void);
+
+
+/**
+ * Disconnect the main conference bridge from any sound devices, and let
+ * application connect the bridge to it's own sound device/master port.
+ *
+ * @return The port interface of the conference bridge,
+ * so that application can connect this to it's own
+ * sound device or master port.
+ */
+PJ_DECL(pjmedia_port*) pjsua_set_no_snd_dev(void);
+
+
+/**
+ * Change the echo cancellation settings.
+ *
+ * The behavior of this function depends on whether the sound device is
+ * currently active, and if it is, whether device or software AEC is
+ * being used.
+ *
+ * If the sound device is currently active, and if the device supports AEC,
+ * this function will forward the change request to the device and it will
+ * be up to the device on whether support the request. If software AEC is
+ * being used (the software EC will be used if the device does not support
+ * AEC), this function will change the software EC settings. In all cases,
+ * the setting will be saved for future opening of the sound device.
+ *
+ * If the sound device is not currently active, this will only change the
+ * default AEC settings and the setting will be applied next time the
+ * sound device is opened.
+ *
+ * @param tail_ms The tail length, in miliseconds. Set to zero to
+ * disable AEC.
+ * @param options Options to be passed to pjmedia_echo_create().
+ * Normally the value should be zero.
+ *
+ * @return PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjsua_set_ec(unsigned tail_ms, unsigned options);
+
+
+/**
+ * Get current echo canceller tail length.
+ *
+ * @param p_tail_ms Pointer to receive the tail length, in miliseconds.
+ * If AEC is disabled, the value will be zero.
+ *
+ * @return PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjsua_get_ec_tail(unsigned *p_tail_ms);
+
+
+/**
+ * Check whether the sound device is currently active. The sound device
+ * may be inactive if the application has set the auto close feature to
+ * non-zero (the snd_auto_close_time setting in #pjsua_media_config), or
+ * if null sound device or no sound device has been configured via the
+ * #pjsua_set_no_snd_dev() function.
+ */
+PJ_DECL(pj_bool_t) pjsua_snd_is_active(void);
+
+
+/**
+ * Configure sound device setting to the sound device being used. If sound
+ * device is currently active, the function will forward the setting to the
+ * sound device instance to be applied immediately, if it supports it.
+ *
+ * The setting will be saved for future opening of the sound device, if the
+ * "keep" argument is set to non-zero. If the sound device is currently
+ * inactive, and the "keep" argument is false, this function will return
+ * error.
+ *
+ * Note that in case the setting is kept for future use, it will be applied
+ * to any devices, even when application has changed the sound device to be
+ * used.
+ *
+ * Note also that the echo cancellation setting should be set with
+ * #pjsua_set_ec() API instead.
+ *
+ * See also #pjmedia_aud_stream_set_cap() for more information about setting
+ * an audio device capability.
+ *
+ * @param cap The sound device setting to change.
+ * @param pval Pointer to value. Please see #pjmedia_aud_dev_cap
+ * documentation about the type of value to be
+ * supplied for each setting.
+ * @param keep Specify whether the setting is to be kept for future
+ * use.
+ *
+ * @return PJ_SUCCESS on success or the appropriate error code.
+ */
+PJ_DECL(pj_status_t) pjsua_snd_set_setting(pjmedia_aud_dev_cap cap,
+ const void *pval,
+ pj_bool_t keep);
+
+/**
+ * Retrieve a sound device setting. If sound device is currently active,
+ * the function will forward the request to the sound device. If sound device
+ * is currently inactive, and if application had previously set the setting
+ * and mark the setting as kept, then that setting will be returned.
+ * Otherwise, this function will return error.
+ *
+ * Note that echo cancellation settings should be retrieved with
+ * #pjsua_get_ec_tail() API instead.
+ *
+ * @param cap The sound device setting to retrieve.
+ * @param pval Pointer to receive the value.
+ * Please see #pjmedia_aud_dev_cap documentation about
+ * the type of value to be supplied for each setting.
+ *
+ * @return PJ_SUCCESS on success or the appropriate error code.
+ */
+PJ_DECL(pj_status_t) pjsua_snd_get_setting(pjmedia_aud_dev_cap cap,
+ void *pval);
+
+
+/*****************************************************************************
+ * Codecs.
+ */
+
+/**
+ * Enum all supported codecs in the system.
+ *
+ * @param id Array of ID to be initialized.
+ * @param count On input, specifies max elements in the array.
+ * On return, it contains actual number of elements
+ * that have been initialized.
+ *
+ * @return PJ_SUCCESS on success, or the appropriate error code.
+ */
+PJ_DECL(pj_status_t) pjsua_enum_codecs( pjsua_codec_info id[],
+ unsigned *count );
+
+
+/**
+ * Change codec priority.
+ *
+ * @param codec_id Codec ID, which is a string that uniquely identify
+ * the codec (such as "speex/8000"). Please see pjsua
+ * manual or pjmedia codec reference for details.
+ * @param priority Codec priority, 0-255, where zero means to disable
+ * the codec.
+ *
+ * @return PJ_SUCCESS on success, or the appropriate error code.
+ */
+PJ_DECL(pj_status_t) pjsua_codec_set_priority( const pj_str_t *codec_id,
+ pj_uint8_t priority );
+
+
+/**
+ * Get codec parameters.
+ *
+ * @param codec_id Codec ID.
+ * @param param Structure to receive codec parameters.
+ *
+ * @return PJ_SUCCESS on success, or the appropriate error code.
+ */
+PJ_DECL(pj_status_t) pjsua_codec_get_param( const pj_str_t *codec_id,
+ pjmedia_codec_param *param );
+
+
+/**
+ * Set codec parameters.
+ *
+ * @param codec_id Codec ID.
+ * @param param Codec parameter to set. Set to NULL to reset
+ * codec parameter to library default settings.
+ *
+ * @return PJ_SUCCESS on success, or the appropriate error code.
+ */
+PJ_DECL(pj_status_t) pjsua_codec_set_param( const pj_str_t *codec_id,
+ const pjmedia_codec_param *param);
+
+
+#if DISABLED_FOR_TICKET_1185
+/**
+ * Create UDP media transports for all the calls. This function creates
+ * one UDP media transport for each call.
+ *
+ * @param cfg Media transport configuration. The "port" field in the
+ * configuration is used as the start port to bind the
+ * sockets.
+ *
+ * @return PJ_SUCCESS on success, or the appropriate error code.
+ */
+PJ_DECL(pj_status_t)
+pjsua_media_transports_create(const pjsua_transport_config *cfg);
+
+
+/**
+ * Register custom media transports to be used by calls. There must
+ * enough media transports for all calls.
+ *
+ * @param tp The media transport array.
+ * @param count Number of elements in the array. This number MUST
+ * match the number of maximum calls configured when
+ * pjsua is created.
+ * @param auto_delete Flag to indicate whether the transports should be
+ * destroyed when pjsua is shutdown.
+ *
+ * @return PJ_SUCCESS on success, or the appropriate error code.
+ */
+PJ_DECL(pj_status_t)
+pjsua_media_transports_attach( pjsua_media_transport tp[],
+ unsigned count,
+ pj_bool_t auto_delete);
+#endif
+
+
+/* end of MEDIA API */
+/**
+ * @}
+ */
+
+
+/*****************************************************************************
+ * VIDEO API
+ */
+
+
+/**
+ * @defgroup PJSUA_LIB_VIDEO PJSUA-API Video
+ * @ingroup PJSUA_LIB
+ * @brief Video support
+ * @{
+ */
+
+/*
+ * Video devices API
+ */
+
+/**
+ * Get the number of video devices installed in the system.
+ *
+ * @return The number of devices.
+ */
+PJ_DECL(unsigned) pjsua_vid_dev_count(void);
+
+/**
+ * Retrieve the video device info for the specified device index.
+ *
+ * @param id The device index.
+ * @param vdi Device info to be initialized.
+ *
+ * @return PJ_SUCCESS on success, or the appropriate error code.
+ */
+PJ_DECL(pj_status_t) pjsua_vid_dev_get_info(pjmedia_vid_dev_index id,
+ pjmedia_vid_dev_info *vdi);
+
+/**
+ * Enum all video devices installed in the system.
+ *
+ * @param info Array of info to be initialized.
+ * @param count On input, specifies max elements in the array.
+ * On return, it contains actual number of elements
+ * that have been initialized.
+ *
+ * @return PJ_SUCCESS on success, or the appropriate error code.
+ */
+PJ_DECL(pj_status_t) pjsua_vid_enum_devs(pjmedia_vid_dev_info info[],
+ unsigned *count);
+
+
+/*
+ * Video preview API
+ */
+
+/**
+ * Parameters for starting video preview with pjsua_vid_preview_start().
+ * Application should initialize this structure with
+ * pjsua_vid_preview_param_default().
+ */
+typedef struct pjsua_vid_preview_param
+{
+ /**
+ * Device ID for the video renderer to be used for rendering the
+ * capture stream for preview. This parameter is ignored if native
+ * preview is being used.
+ *
+ * Default: PJMEDIA_VID_DEFAULT_RENDER_DEV
+ */
+ pjmedia_vid_dev_index rend_id;
+
+ /**
+ * Show window initially.
+ *
+ * Default: PJ_TRUE.
+ */
+ pj_bool_t show;
+
+ /**
+ * Window flags. The value is a bitmask combination of
+ * #pjmedia_vid_dev_wnd_flag.
+ *
+ * Default: 0.
+ */
+ unsigned wnd_flags;
+
+} pjsua_vid_preview_param;
+
+
+/**
+ * Initialize pjsua_vid_preview_param
+ *
+ * @param p The parameter to be initialized.
+ */
+PJ_DECL(void) pjsua_vid_preview_param_default(pjsua_vid_preview_param *p);
+
+/**
+ * Determine if the specified video input device has built-in native
+ * preview capability. This is a convenience function that is equal to
+ * querying device's capability for PJMEDIA_VID_DEV_CAP_INPUT_PREVIEW
+ * capability.
+ *
+ * @param id The capture device ID.
+ *
+ * @return PJ_TRUE if it has.
+ */
+PJ_DECL(pj_bool_t) pjsua_vid_preview_has_native(pjmedia_vid_dev_index id);
+
+/**
+ * Start video preview window for the specified capture device.
+ *
+ * @param id The capture device ID where its preview will be
+ * started.
+ * @param p Optional video preview parameters. Specify NULL
+ * to use default values.
+ *
+ * @return PJ_SUCCESS on success, or the appropriate error code.
+ */
+PJ_DECL(pj_status_t) pjsua_vid_preview_start(pjmedia_vid_dev_index id,
+ const pjsua_vid_preview_param *p);
+
+/**
+ * Get the preview window handle associated with the capture device, if any.
+ *
+ * @param id The capture device ID.
+ *
+ * @return The window ID of the preview window for the
+ * specified capture device ID, or PJSUA_INVALID_ID if
+ * preview has not been started for the device.
+ */
+PJ_DECL(pjsua_vid_win_id) pjsua_vid_preview_get_win(pjmedia_vid_dev_index id);
+
+/**
+ * Stop video preview.
+ *
+ * @param id The capture device ID.
+ *
+ * @return PJ_SUCCESS on success, or the appropriate error code.
+ */
+PJ_DECL(pj_status_t) pjsua_vid_preview_stop(pjmedia_vid_dev_index id);
+
+
+/*
+ * Video window manipulation API.
+ */
+
+/**
+ * This structure describes video window info.
+ */
+typedef struct pjsua_vid_win_info
+{
+ /**
+ * Flag to indicate whether this window is a native window,
+ * such as created by built-in preview device. If this field is
+ * PJ_TRUE, only the native window handle field of this
+ * structure is valid.
+ */
+ pj_bool_t is_native;
+
+ /**
+ * Native window handle.
+ */
+ pjmedia_vid_dev_hwnd hwnd;
+
+ /**
+ * Renderer device ID.
+ */
+ pjmedia_vid_dev_index rdr_dev;
+
+ /**
+ * Window show status. The window is hidden if false.
+ */
+ pj_bool_t show;
+
+ /**
+ * Window position.
+ */
+ pjmedia_coord pos;
+
+ /**
+ * Window size.
+ */
+ pjmedia_rect_size size;
+
+} pjsua_vid_win_info;
+
+
+/**
+ * Enumerates all video windows.
+ *
+ * @param id Array of window ID to be initialized.
+ * @param count On input, specifies max elements in the array.
+ * On return, it contains actual number of elements
+ * that have been initialized.
+ *
+ * @return PJ_SUCCESS on success, or the appropriate error code.
+ */
+PJ_DECL(pj_status_t) pjsua_vid_enum_wins(pjsua_vid_win_id wids[],
+ unsigned *count);
+
+
+/**
+ * Get window info.
+ *
+ * @param wid The video window ID.
+ * @param wi The video window info to be initialized.
+ *
+ * @return PJ_SUCCESS on success, or the appropriate error code.
+ */
+PJ_DECL(pj_status_t) pjsua_vid_win_get_info(pjsua_vid_win_id wid,
+ pjsua_vid_win_info *wi);
+
+/**
+ * Show or hide window. This operation is not valid for native windows
+ * (pjsua_vid_win_info.is_native=PJ_TRUE), on which native windowing API
+ * must be used instead.
+ *
+ * @param wid The video window ID.
+ * @param show Set to PJ_TRUE to show the window, PJ_FALSE to
+ * hide the window.
+ *
+ * @return PJ_SUCCESS on success, or the appropriate error code.
+ */
+PJ_DECL(pj_status_t) pjsua_vid_win_set_show(pjsua_vid_win_id wid,
+ pj_bool_t show);
+
+/**
+ * Set video window position. This operation is not valid for native windows
+ * (pjsua_vid_win_info.is_native=PJ_TRUE), on which native windowing API
+ * must be used instead.
+ *
+ * @param wid The video window ID.
+ * @param pos The window position.
+ *
+ * @return PJ_SUCCESS on success, or the appropriate error code.
+ */
+PJ_DECL(pj_status_t) pjsua_vid_win_set_pos(pjsua_vid_win_id wid,
+ const pjmedia_coord *pos);
+
+/**
+ * Resize window. This operation is not valid for native windows
+ * (pjsua_vid_win_info.is_native=PJ_TRUE), on which native windowing API
+ * must be used instead.
+ *
+ * @param wid The video window ID.
+ * @param size The new window size.
+ *
+ * @return PJ_SUCCESS on success, or the appropriate error code.
+ */
+PJ_DECL(pj_status_t) pjsua_vid_win_set_size(pjsua_vid_win_id wid,
+ const pjmedia_rect_size *size);
+
+/**
+ * Rotate the video window. This function will change the video orientation
+ * and also possibly the video window size (width and height get swapped).
+ * This operation is not valid for native windows (pjsua_vid_win_info.is_native
+ * =PJ_TRUE), on which native windowing API must be used instead.
+ *
+ * @param wid The video window ID.
+ * @param angle The rotation angle in degrees, must be multiple of 90.
+ * Specify positive value for clockwise rotation or
+ * negative value for counter-clockwise rotation.
+ *
+ * @return PJ_SUCCESS on success, or the appropriate error code.
+ */
+PJ_DECL(pj_status_t) pjsua_vid_win_rotate(pjsua_vid_win_id wid,
+ int angle);
+
+
+/*
+ * Video codecs API
+ */
+
+/**
+ * Enum all supported video codecs in the system.
+ *
+ * @param id Array of ID to be initialized.
+ * @param count On input, specifies max elements in the array.
+ * On return, it contains actual number of elements
+ * that have been initialized.
+ *
+ * @return PJ_SUCCESS on success, or the appropriate error code.
+ */
+PJ_DECL(pj_status_t) pjsua_vid_enum_codecs( pjsua_codec_info id[],
+ unsigned *count );
+
+
+/**
+ * Change video codec priority.
+ *
+ * @param codec_id Codec ID, which is a string that uniquely identify
+ * the codec (such as "H263/90000"). Please see pjsua
+ * manual or pjmedia codec reference for details.
+ * @param priority Codec priority, 0-255, where zero means to disable
+ * the codec.
+ *
+ * @return PJ_SUCCESS on success, or the appropriate error code.
+ */
+PJ_DECL(pj_status_t) pjsua_vid_codec_set_priority( const pj_str_t *codec_id,
+ pj_uint8_t priority );
+
+
+/**
+ * Get video codec parameters.
+ *
+ * @param codec_id Codec ID.
+ * @param param Structure to receive video codec parameters.
+ *
+ * @return PJ_SUCCESS on success, or the appropriate error code.
+ */
+PJ_DECL(pj_status_t) pjsua_vid_codec_get_param(
+ const pj_str_t *codec_id,
+ pjmedia_vid_codec_param *param);
+
+
+/**
+ * Set video codec parameters.
+ *
+ * @param codec_id Codec ID.
+ * @param param Codec parameter to set. Set to NULL to reset
+ * codec parameter to library default settings.
+ *
+ * @return PJ_SUCCESS on success, or the appropriate error code.
+ */
+PJ_DECL(pj_status_t) pjsua_vid_codec_set_param(
+ const pj_str_t *codec_id,
+ const pjmedia_vid_codec_param *param);
+
+
+
+/* end of VIDEO API */
+/**
+ * @}
+ */
+
+
+/**
+ * @}
+ */
+
+PJ_END_DECL
+
+
+#endif /* __PJSUA_H__ */
diff --git a/pjsip/include/pjsua-lib/pjsua_internal.h b/pjsip/include/pjsua-lib/pjsua_internal.h
new file mode 100644
index 0000000..c228513
--- /dev/null
+++ b/pjsip/include/pjsua-lib/pjsua_internal.h
@@ -0,0 +1,805 @@
+/* $Id: pjsua_internal.h 4175 2012-06-22 08:53:11Z nanang $ */
+/*
+ * 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 __PJSUA_INTERNAL_H__
+#define __PJSUA_INTERNAL_H__
+
+/**
+ * This is the private header used by pjsua library implementation.
+ * Applications should not include this file.
+ */
+
+PJ_BEGIN_DECL
+
+/** Forward decl of pjsua call */
+typedef struct pjsua_call pjsua_call;
+
+/** Forward decl of pjsua call media */
+typedef struct pjsua_call_media pjsua_call_media;
+
+
+/**
+ * Call's media stream.
+ */
+struct pjsua_call_media
+{
+ pjsua_call *call; /**< Parent call. */
+ pjmedia_type type; /**< Media type. */
+ unsigned idx; /**< This media index in parent call. */
+ pjsua_call_media_status state; /**< Media state. */
+ pjsua_call_media_status prev_state;/**< Previous media state. */
+ pjmedia_dir dir; /**< Media direction. */
+
+ /** The stream */
+ struct {
+ /** Audio stream */
+ struct {
+ pjmedia_stream *stream; /**< The audio stream. */
+ int conf_slot; /**< Slot # in conference bridge. */
+ } a;
+
+ /** Video stream */
+ struct {
+ pjmedia_vid_stream *stream; /**< The video stream. */
+ pjsua_vid_win_id cap_win_id;/**< The video capture window */
+ pjsua_vid_win_id rdr_win_id;/**< The video render window */
+ pjmedia_vid_dev_index cap_dev; /**< The video capture device */
+ pjmedia_vid_dev_index rdr_dev; /**< The video-in render device */
+ } v;
+
+ } strm;
+
+ pj_uint32_t ssrc; /**< RTP SSRC */
+ pj_uint32_t rtp_tx_ts; /**< Initial RTP timestamp for sender. */
+ pj_uint16_t rtp_tx_seq;/**< Initial RTP sequence for sender. */
+ pj_uint8_t rtp_tx_seq_ts_set;
+ /**< Bitmask flags if initial RTP sequence
+ and/or timestamp for sender are set.
+ bit 0/LSB : sequence flag
+ bit 1 : timestamp flag */
+
+ pjmedia_transport *tp; /**< Current media transport (can be 0) */
+ pj_status_t tp_ready; /**< Media transport status. */
+ pj_status_t tp_result; /**< Media transport creation result. */
+ pjmedia_transport *tp_orig; /**< Original media transport */
+ pj_bool_t tp_auto_del; /**< May delete media transport */
+ pjsua_med_tp_st tp_st; /**< Media transport state */
+ pj_bool_t use_custom_med_tp;/**< Use custom media transport? */
+ pj_sockaddr rtp_addr; /**< Current RTP source address
+ (used to update ICE default
+ address) */
+ pjmedia_srtp_use rem_srtp_use; /**< Remote's SRTP usage policy. */
+ pj_timestamp last_req_keyframe;/**< Last TX keyframe request. */
+
+ pjsua_med_tp_state_cb med_init_cb;/**< Media transport
+ initialization callback. */
+
+ /** Media transport creation callback. */
+ pj_status_t (*med_create_cb)(pjsua_call_media *call_med,
+ pj_status_t status, int security_level,
+ int *sip_err_code);
+};
+
+/**
+ * Maximum number of SDP "m=" lines to be supported.
+ */
+#define PJSUA_MAX_CALL_MEDIA PJMEDIA_MAX_SDP_MEDIA
+
+/* Call answer's list. */
+typedef struct call_answer
+{
+ PJ_DECL_LIST_MEMBER(struct call_answer);
+ pjsua_msg_data *msg_data; /**< Answer's headers list. */
+ pj_str_t *reason; /**< Answer's reason phrase. */
+ unsigned code; /**< Answer's status code. */
+ pjsua_call_setting *opt; /**< Answer's call setting. */
+} call_answer;
+
+
+/**
+ * Structure to be attached to invite dialog.
+ * Given a dialog "dlg", application can retrieve this structure
+ * by accessing dlg->mod_data[pjsua.mod.id].
+ */
+struct pjsua_call
+{
+ unsigned index; /**< Index in pjsua array. */
+ pjsua_call_setting opt; /**< Call setting. */
+ pj_bool_t opt_inited;/**< Initial call setting has been set,
+ to avoid different opt in answer. */
+ pjsip_inv_session *inv; /**< The invite session. */
+ void *user_data; /**< User/application data. */
+ pjsip_status_code last_code; /**< Last status code seen. */
+ pj_str_t last_text; /**< Last status text seen. */
+ pj_time_val start_time;/**< First INVITE sent/received. */
+ pj_time_val res_time; /**< First response sent/received. */
+ pj_time_val conn_time; /**< Connected/confirmed time. */
+ pj_time_val dis_time; /**< Disconnect time. */
+ pjsua_acc_id acc_id; /**< Account index being used. */
+ int secure_level;/**< Signaling security level. */
+ pjsua_call_hold_type call_hold_type; /**< How to do call hold. */
+ pj_bool_t local_hold;/**< Flag for call-hold by local. */
+ void *hold_msg; /**< Outgoing hold tx_data. */
+
+ unsigned med_cnt; /**< Number of media in SDP. */
+ pjsua_call_media media[PJSUA_MAX_CALL_MEDIA]; /**< Array of media */
+ unsigned med_prov_cnt;/**< Number of provisional media. */
+ pjsua_call_media media_prov[PJSUA_MAX_CALL_MEDIA];
+ /**< Array of provisional media. */
+
+ int audio_idx; /**< First active audio media. */
+ pj_mutex_t *med_ch_mutex;/**< Media channel callback's mutex. */
+ pjsua_med_tp_state_cb med_ch_cb;/**< Media channel callback. */
+ pjsua_med_tp_state_info med_ch_info;/**< Media channel info. */
+
+ pjsip_evsub *xfer_sub; /**< Xfer server subscription, if this
+ call was triggered by xfer. */
+ pj_stun_nat_type rem_nat_type; /**< NAT type of remote endpoint. */
+
+ char last_text_buf_[128]; /**< Buffer for last_text. */
+
+ struct {
+ pj_timer_entry reinv_timer;/**< Reinvite retry timer. */
+ pj_uint32_t sdp_ver; /**< SDP version of the bad answer */
+ int retry_cnt; /**< Retry count. */
+ pj_bool_t pending; /**< Pending until CONFIRMED state */
+ } lock_codec; /**< Data for codec locking when answer
+ contains multiple codecs. */
+
+ struct {
+ pjsip_dialog *dlg; /**< Call dialog. */
+ pjmedia_sdp_session *rem_sdp;/**< Remote SDP. */
+ pj_pool_t *pool_prov;/**< Provisional pool. */
+ pj_bool_t med_ch_deinit;/**< Media channel de-init-ed? */
+ union {
+ struct {
+ pjsua_msg_data *msg_data;/**< Headers for outgoing INVITE. */
+ } out_call;
+ struct {
+ call_answer answers;/**< A list of call answers. */
+ pjsip_dialog *replaced_dlg; /**< Replaced dialog. */
+ } inc_call;
+ } call_var;
+ } async_call; /**< Temporary storage for async
+ outgoing/incoming call. */
+
+ pj_bool_t rem_offerer; /**< Was remote SDP offerer? */
+ unsigned rem_aud_cnt; /**< No of active audio in last remote
+ offer. */
+ unsigned rem_vid_cnt; /**< No of active video in last remote
+ offer. */
+};
+
+
+/**
+ * Server presence subscription list head.
+ */
+struct pjsua_srv_pres
+{
+ PJ_DECL_LIST_MEMBER(struct pjsua_srv_pres);
+ pjsip_evsub *sub; /**< The evsub. */
+ char *remote; /**< Remote URI. */
+ int acc_id; /**< Account ID. */
+ pjsip_dialog *dlg; /**< Dialog. */
+ int expires; /**< "expires" value in the request. */
+};
+
+/**
+ * Account
+ */
+typedef struct pjsua_acc
+{
+ pj_pool_t *pool; /**< Pool for this account. */
+ pjsua_acc_config cfg; /**< Account configuration. */
+ pj_bool_t valid; /**< Is this account valid? */
+
+ int index; /**< Index in accounts array. */
+ pj_str_t display; /**< Display name, if any. */
+ pj_str_t user_part; /**< User part of local URI. */
+ pj_str_t contact; /**< Our Contact header. */
+ pj_str_t reg_contact; /**< Contact header for REGISTER.
+ It may be different than acc
+ contact if outbound is used */
+ pjsip_host_port via_addr; /**< Address for Via header */
+ pjsip_transport *via_tp; /**< Transport associated with
+ the Via address */
+
+ pj_str_t srv_domain; /**< Host part of reg server. */
+ int srv_port; /**< Port number of reg server. */
+
+ pjsip_regc *regc; /**< Client registration session. */
+ pj_status_t reg_last_err; /**< Last registration error. */
+ int reg_last_code; /**< Last status last register. */
+
+ struct {
+ pj_bool_t active; /**< Flag of reregister status. */
+ pj_timer_entry timer; /**< Timer for reregistration. */
+ void *reg_tp; /**< Transport for registration. */
+ unsigned attempt_cnt; /**< Attempt counter. */
+ } auto_rereg; /**< Reregister/reconnect data. */
+
+ pj_timer_entry ka_timer; /**< Keep-alive timer for UDP. */
+ pjsip_transport *ka_transport; /**< Transport for keep-alive. */
+ pj_sockaddr ka_target; /**< Destination address for K-A */
+ unsigned ka_target_len; /**< Length of ka_target. */
+
+ pjsip_route_hdr route_set; /**< Complete route set inc. outbnd.*/
+ pj_uint32_t global_route_crc; /** CRC of global route setting. */
+ pj_uint32_t local_route_crc; /** CRC of account route setting.*/
+
+ unsigned rfc5626_status;/**< SIP outbound status:
+ 0: not used
+ 1: requested
+ 2: acknowledged by servers */
+ pj_str_t rfc5626_instprm;/**< SIP outbound instance param. */
+ pj_str_t rfc5626_regprm;/**< SIP outbound reg param. */
+
+ unsigned cred_cnt; /**< Number of credentials. */
+ pjsip_cred_info cred[PJSUA_ACC_MAX_PROXIES]; /**< Complete creds. */
+
+ pj_bool_t online_status; /**< Our online status. */
+ pjrpid_element rpid; /**< RPID element information. */
+ pjsua_srv_pres pres_srv_list; /**< Server subscription list. */
+ pjsip_publishc *publish_sess; /**< Client publication session. */
+ pj_bool_t publish_state; /**< Last published online status */
+
+ pjsip_evsub *mwi_sub; /**< MWI client subscription */
+ pjsip_dialog *mwi_dlg; /**< Dialog for MWI sub. */
+} pjsua_acc;
+
+
+/**
+ *Transport.
+ */
+typedef struct pjsua_transport_data
+{
+ int index;
+ pjsip_transport_type_e type;
+ pjsip_host_port local_name;
+
+ union {
+ pjsip_transport *tp;
+ pjsip_tpfactory *factory;
+ void *ptr;
+ } data;
+
+} pjsua_transport_data;
+
+
+/** Maximum length of subscription termination reason. */
+#define PJSUA_BUDDY_SUB_TERM_REASON_LEN 32
+
+/**
+ * Buddy data.
+ */
+typedef struct pjsua_buddy
+{
+ pj_pool_t *pool; /**< Pool for this buddy. */
+ unsigned index; /**< Buddy index. */
+ void *user_data; /**< Application data. */
+ pj_str_t uri; /**< Buddy URI. */
+ pj_str_t contact; /**< Contact learned from subscrp. */
+ pj_str_t name; /**< Buddy name. */
+ pj_str_t display; /**< Buddy display name. */
+ pj_str_t host; /**< Buddy host. */
+ unsigned port; /**< Buddy port. */
+ pj_bool_t monitor; /**< Should we monitor? */
+ pjsip_dialog *dlg; /**< The underlying dialog. */
+ pjsip_evsub *sub; /**< Buddy presence subscription */
+ unsigned term_code; /**< Subscription termination code */
+ pj_str_t term_reason;/**< Subscription termination reason */
+ pjsip_pres_status status; /**< Buddy presence status. */
+ pj_timer_entry timer; /**< Resubscription timer */
+} pjsua_buddy;
+
+
+/**
+ * File player/recorder data.
+ */
+typedef struct pjsua_file_data
+{
+ pj_bool_t type; /* 0=player, 1=playlist */
+ pjmedia_port *port;
+ pj_pool_t *pool;
+ unsigned slot;
+} pjsua_file_data;
+
+
+/**
+ * Additional parameters for conference bridge.
+ */
+typedef struct pjsua_conf_setting
+{
+ unsigned channel_count;
+ unsigned samples_per_frame;
+ unsigned bits_per_sample;
+} pjsua_conf_setting;
+
+typedef struct pjsua_stun_resolve
+{
+ PJ_DECL_LIST_MEMBER(struct pjsua_stun_resolve);
+
+ pj_pool_t *pool; /**< Pool */
+ unsigned count; /**< # of entries */
+ pj_str_t *srv; /**< Array of entries */
+ unsigned idx; /**< Current index */
+ void *token; /**< App token */
+ pj_stun_resolve_cb cb; /**< App callback */
+ pj_bool_t blocking; /**< Blocking? */
+ pj_status_t status; /**< Session status */
+ pj_sockaddr addr; /**< Result */
+ pj_stun_sock *stun_sock; /**< Testing STUN sock */
+} pjsua_stun_resolve;
+
+/* See also pjsua_vid_win_type_name() */
+typedef enum pjsua_vid_win_type
+{
+ PJSUA_WND_TYPE_NONE,
+ PJSUA_WND_TYPE_PREVIEW,
+ PJSUA_WND_TYPE_STREAM
+} pjsua_vid_win_type;
+
+typedef struct pjsua_vid_win
+{
+ pjsua_vid_win_type type; /**< Type. */
+ pj_pool_t *pool; /**< Own pool. */
+ unsigned ref_cnt; /**< Reference counter. */
+ pjmedia_vid_port *vp_cap; /**< Capture vidport. */
+ pjmedia_vid_port *vp_rend; /**< Renderer vidport */
+ pjmedia_port *tee; /**< Video tee */
+ pjmedia_vid_dev_index preview_cap_id;/**< Capture dev id */
+ pj_bool_t preview_running;/**< Preview is started*/
+ pj_bool_t is_native; /**< Preview is by dev */
+} pjsua_vid_win;
+
+
+typedef struct pjsua_timer_list
+{
+ PJ_DECL_LIST_MEMBER(struct pjsua_timer_list);
+ pj_timer_entry entry;
+ void (*cb)(void *user_data);
+ void *user_data;
+} pjsua_timer_list;
+
+
+/**
+ * Global pjsua application data.
+ */
+struct pjsua_data
+{
+
+ /* Control: */
+ pj_caching_pool cp; /**< Global pool factory. */
+ pj_pool_t *pool; /**< pjsua's private pool. */
+ pj_mutex_t *mutex; /**< Mutex protection for this data */
+ unsigned mutex_nesting_level; /**< Mutex nesting level. */
+ pj_thread_t *mutex_owner; /**< Mutex owner. */
+ pjsua_state state; /**< Library state. */
+
+ /* Logging: */
+ pjsua_logging_config log_cfg; /**< Current logging config. */
+ pj_oshandle_t log_file; /**<Output log file handle */
+
+ /* SIP: */
+ pjsip_endpoint *endpt; /**< Global endpoint. */
+ pjsip_module mod; /**< pjsua's PJSIP module. */
+ pjsua_transport_data tpdata[8]; /**< Array of transports. */
+ pjsip_tp_state_callback old_tp_cb; /**< Old transport callback. */
+
+ /* Threading: */
+ pj_bool_t thread_quit_flag; /**< Thread quit flag. */
+ pj_thread_t *thread[4]; /**< Array of threads. */
+
+ /* STUN and resolver */
+ pj_stun_config stun_cfg; /**< Global STUN settings. */
+ pj_sockaddr stun_srv; /**< Resolved STUN server address */
+ pj_status_t stun_status; /**< STUN server status. */
+ pjsua_stun_resolve stun_res; /**< List of pending STUN resolution*/
+ pj_dns_resolver *resolver; /**< DNS resolver. */
+
+ /* Detected NAT type */
+ pj_stun_nat_type nat_type; /**< NAT type. */
+ pj_status_t nat_status; /**< Detection status. */
+ pj_bool_t nat_in_progress; /**< Detection in progress */
+
+ /* List of outbound proxies: */
+ pjsip_route_hdr outbound_proxy;
+
+ /* Account: */
+ unsigned acc_cnt; /**< Number of accounts. */
+ pjsua_acc_id default_acc; /**< Default account ID */
+ pjsua_acc acc[PJSUA_MAX_ACC]; /**< Account array. */
+ pjsua_acc_id acc_ids[PJSUA_MAX_ACC]; /**< Acc sorted by prio*/
+
+ /* Calls: */
+ pjsua_config ua_cfg; /**< UA config. */
+ unsigned call_cnt; /**< Call counter. */
+ pjsua_call calls[PJSUA_MAX_CALLS];/**< Calls array. */
+ pjsua_call_id next_call_id; /**< Next call id to use*/
+
+ /* Buddy; */
+ unsigned buddy_cnt; /**< Buddy count. */
+ pjsua_buddy buddy[PJSUA_MAX_BUDDIES]; /**< Buddy array. */
+
+ /* Presence: */
+ pj_timer_entry pres_timer;/**< Presence refresh timer. */
+
+ /* Media: */
+ pjsua_media_config media_cfg; /**< Media config. */
+ pjmedia_endpt *med_endpt; /**< Media endpoint. */
+ pjsua_conf_setting mconf_cfg; /**< Additionan conf. bridge. param */
+ pjmedia_conf *mconf; /**< Conference bridge. */
+ pj_bool_t is_mswitch;/**< Are we using audio switchboard
+ (a.k.a APS-Direct) */
+
+ /* Sound device */
+ pjmedia_aud_dev_index cap_dev; /**< Capture device ID. */
+ pjmedia_aud_dev_index play_dev; /**< Playback device ID. */
+ pj_uint32_t aud_svmask;/**< Which settings to save */
+ pjmedia_aud_param aud_param; /**< User settings to sound dev */
+ pj_bool_t aud_open_cnt;/**< How many # device is opened */
+ pj_bool_t no_snd; /**< No sound (app will manage it) */
+ pj_pool_t *snd_pool; /**< Sound's private pool. */
+ pjmedia_snd_port *snd_port; /**< Sound port. */
+ pj_timer_entry snd_idle_timer;/**< Sound device idle timer. */
+ pjmedia_master_port *null_snd; /**< Master port for null sound. */
+ pjmedia_port *null_port; /**< Null port. */
+ pj_bool_t snd_is_on; /**< Media flow is currently active */
+
+ /* Video device */
+ pjmedia_vid_dev_index vcap_dev; /**< Capture device ID. */
+ pjmedia_vid_dev_index vrdr_dev; /**< Playback device ID. */
+
+ /* File players: */
+ unsigned player_cnt;/**< Number of file players. */
+ pjsua_file_data player[PJSUA_MAX_PLAYERS];/**< Array of players.*/
+
+ /* File recorders: */
+ unsigned rec_cnt; /**< Number of file recorders. */
+ pjsua_file_data recorder[PJSUA_MAX_RECORDERS];/**< Array of recs.*/
+
+ /* Video windows */
+#if PJSUA_HAS_VIDEO
+ pjsua_vid_win win[PJSUA_MAX_VID_WINS]; /**< Array of windows */
+#endif
+
+ /* Timer entry list */
+ pjsua_timer_list timer_list;
+ pj_mutex_t *timer_mutex;
+};
+
+
+extern struct pjsua_data pjsua_var;
+
+/**
+ * Get the instance of pjsua
+ */
+PJ_DECL(struct pjsua_data*) pjsua_get_var(void);
+
+
+
+/**
+ * IM callback data.
+ */
+typedef struct pjsua_im_data
+{
+ pjsua_acc_id acc_id;
+ pjsua_call_id call_id;
+ pj_str_t to;
+ pj_str_t body;
+ void *user_data;
+} pjsua_im_data;
+
+pj_status_t pjsua_media_apply_xml_control(pjsua_call_id call_id,
+ const pj_str_t *xml_st);
+
+
+/**
+ * Duplicate IM data.
+ */
+PJ_INLINE(pjsua_im_data*) pjsua_im_data_dup(pj_pool_t *pool,
+ const pjsua_im_data *src)
+{
+ pjsua_im_data *dst;
+
+ dst = (pjsua_im_data*) pj_pool_alloc(pool, sizeof(*dst));
+ dst->acc_id = src->acc_id;
+ dst->call_id = src->call_id;
+ pj_strdup_with_null(pool, &dst->to, &src->to);
+ dst->user_data = src->user_data;
+ pj_strdup_with_null(pool, &dst->body, &src->body);
+
+ return dst;
+}
+
+
+#if 1
+
+PJ_INLINE(void) PJSUA_LOCK()
+{
+ pj_mutex_lock(pjsua_var.mutex);
+ pjsua_var.mutex_owner = pj_thread_this();
+ ++pjsua_var.mutex_nesting_level;
+}
+
+PJ_INLINE(void) PJSUA_UNLOCK()
+{
+ if (--pjsua_var.mutex_nesting_level == 0)
+ pjsua_var.mutex_owner = NULL;
+ pj_mutex_unlock(pjsua_var.mutex);
+}
+
+PJ_INLINE(pj_status_t) PJSUA_TRY_LOCK()
+{
+ pj_status_t status;
+ status = pj_mutex_trylock(pjsua_var.mutex);
+ if (status == PJ_SUCCESS) {
+ pjsua_var.mutex_owner = pj_thread_this();
+ ++pjsua_var.mutex_nesting_level;
+ }
+ return status;
+}
+
+PJ_INLINE(pj_bool_t) PJSUA_LOCK_IS_LOCKED()
+{
+ return pjsua_var.mutex_owner == pj_thread_this();
+}
+
+#else
+#define PJSUA_LOCK()
+#define PJSUA_TRY_LOCK() PJ_SUCCESS
+#define PJSUA_UNLOCK()
+#define PJSUA_LOCK_IS_LOCKED() PJ_TRUE
+#endif
+
+/* Core */
+void pjsua_set_state(pjsua_state new_state);
+
+/******
+ * STUN resolution
+ */
+/* Resolve the STUN server */
+pj_status_t resolve_stun_server(pj_bool_t wait);
+
+/**
+ * Normalize route URI (check for ";lr" and append one if it doesn't
+ * exist and pjsua_config.force_lr is set.
+ */
+pj_status_t normalize_route_uri(pj_pool_t *pool, pj_str_t *uri);
+
+/**
+ * Handle incoming invite request.
+ */
+pj_bool_t pjsua_call_on_incoming(pjsip_rx_data *rdata);
+
+/*
+ * Media channel.
+ */
+pj_status_t pjsua_media_channel_init(pjsua_call_id call_id,
+ pjsip_role_e role,
+ int security_level,
+ pj_pool_t *tmp_pool,
+ const pjmedia_sdp_session *rem_sdp,
+ int *sip_err_code,
+ pj_bool_t async,
+ pjsua_med_tp_state_cb cb);
+pj_status_t pjsua_media_channel_create_sdp(pjsua_call_id call_id,
+ pj_pool_t *pool,
+ const pjmedia_sdp_session *rem_sdp,
+ pjmedia_sdp_session **p_sdp,
+ int *sip_err_code);
+pj_status_t pjsua_media_channel_update(pjsua_call_id call_id,
+ const pjmedia_sdp_session *local_sdp,
+ const pjmedia_sdp_session *remote_sdp);
+pj_status_t pjsua_media_channel_deinit(pjsua_call_id call_id);
+
+pj_status_t pjsua_call_media_init(pjsua_call_media *call_med,
+ pjmedia_type type,
+ const pjsua_transport_config *tcfg,
+ int security_level,
+ int *sip_err_code,
+ pj_bool_t async,
+ pjsua_med_tp_state_cb cb);
+void pjsua_set_media_tp_state(pjsua_call_media *call_med, pjsua_med_tp_st tp_st);
+
+void pjsua_media_prov_clean_up(pjsua_call_id call_id);
+
+/* Callback to receive media events */
+pj_status_t call_media_on_event(pjmedia_event *event,
+ void *user_data);
+
+/**
+ * Init presence.
+ */
+pj_status_t pjsua_pres_init();
+
+/*
+ * Start presence subsystem.
+ */
+pj_status_t pjsua_pres_start(void);
+
+/**
+ * Refresh presence subscriptions
+ */
+void pjsua_pres_refresh(void);
+
+/*
+ * Update server subscription (e.g. when our online status has changed)
+ */
+void pjsua_pres_update_acc(int acc_id, pj_bool_t force);
+
+/*
+ * Shutdown presence.
+ */
+void pjsua_pres_shutdown(unsigned flags);
+
+/**
+ * Init presence for aoocunt.
+ */
+pj_status_t pjsua_pres_init_acc(int acc_id);
+
+/**
+ * Send PUBLISH
+ */
+pj_status_t pjsua_pres_init_publish_acc(int acc_id);
+
+/**
+ * Send un-PUBLISH
+ */
+void pjsua_pres_unpublish(pjsua_acc *acc, unsigned flags);
+
+/**
+ * Terminate server subscription for the account
+ */
+void pjsua_pres_delete_acc(int acc_id, unsigned flags);
+
+/**
+ * Init IM module handler to handle incoming MESSAGE outside dialog.
+ */
+pj_status_t pjsua_im_init(void);
+
+/**
+ * Start MWI subscription
+ */
+pj_status_t pjsua_start_mwi(pjsua_acc_id acc_id, pj_bool_t force_renew);
+
+/**
+ * Init call subsystem.
+ */
+pj_status_t pjsua_call_subsys_init(const pjsua_config *cfg);
+
+/**
+ * Start call subsystem.
+ */
+pj_status_t pjsua_call_subsys_start(void);
+
+/**
+ * Init media subsystems.
+ */
+pj_status_t pjsua_media_subsys_init(const pjsua_media_config *cfg);
+
+/**
+ * Start pjsua media subsystem.
+ */
+pj_status_t pjsua_media_subsys_start(void);
+
+/**
+ * Destroy pjsua media subsystem.
+ */
+pj_status_t pjsua_media_subsys_destroy(unsigned flags);
+
+/**
+ * Private: check if we can accept the message.
+ * If not, then p_accept header will be filled with a valid
+ * Accept header.
+ */
+pj_bool_t pjsua_im_accept_pager(pjsip_rx_data *rdata,
+ pjsip_accept_hdr **p_accept_hdr);
+
+/**
+ * Private: process pager message.
+ * This may trigger pjsua_ui_on_pager() or pjsua_ui_on_typing().
+ */
+void pjsua_im_process_pager(int call_id, const pj_str_t *from,
+ const pj_str_t *to, pjsip_rx_data *rdata);
+
+
+/**
+ * Create Accept header for MESSAGE.
+ */
+pjsip_accept_hdr* pjsua_im_create_accept(pj_pool_t *pool);
+
+/*
+ * Add additional headers etc in msg_data specified by application
+ * when sending requests.
+ */
+void pjsua_process_msg_data(pjsip_tx_data *tdata,
+ const pjsua_msg_data *msg_data);
+
+
+/*
+ * Add route_set to outgoing requests
+ */
+void pjsua_set_msg_route_set( pjsip_tx_data *tdata,
+ const pjsip_route_hdr *route_set );
+
+
+/*
+ * Simple version of MIME type parsing (it doesn't support parameters)
+ */
+void pjsua_parse_media_type( pj_pool_t *pool,
+ const pj_str_t *mime,
+ pjsip_media_type *media_type);
+
+
+/*
+ * Internal function to init transport selector from transport id.
+ */
+void pjsua_init_tpselector(pjsua_transport_id tp_id,
+ pjsip_tpselector *sel);
+
+pjsip_dialog* on_dlg_forked(pjsip_dialog *first_set, pjsip_rx_data *res);
+pj_status_t acquire_call(const char *title,
+ pjsua_call_id call_id,
+ pjsua_call **p_call,
+ pjsip_dialog **p_dlg);
+const char *good_number(char *buf, pj_int32_t val);
+void print_call(const char *title,
+ int call_id,
+ char *buf, pj_size_t size);
+
+/*
+ * Audio
+ */
+pj_status_t pjsua_aud_subsys_init(void);
+pj_status_t pjsua_aud_subsys_start(void);
+pj_status_t pjsua_aud_subsys_destroy(void);
+void pjsua_aud_stop_stream(pjsua_call_media *call_med);
+pj_status_t pjsua_aud_channel_update(pjsua_call_media *call_med,
+ pj_pool_t *tmp_pool,
+ pjmedia_stream_info *si,
+ const pjmedia_sdp_session *local_sdp,
+ const pjmedia_sdp_session *remote_sdp);
+void pjsua_check_snd_dev_idle();
+
+/*
+ * Video
+ */
+pj_status_t pjsua_vid_subsys_init(void);
+pj_status_t pjsua_vid_subsys_start(void);
+pj_status_t pjsua_vid_subsys_destroy(void);
+void pjsua_vid_stop_stream(pjsua_call_media *call_med);
+pj_status_t pjsua_vid_channel_init(pjsua_call_media *call_med);
+pj_status_t pjsua_vid_channel_update(pjsua_call_media *call_med,
+ pj_pool_t *tmp_pool,
+ pjmedia_vid_stream_info *si,
+ const pjmedia_sdp_session *local_sdp,
+ const pjmedia_sdp_session *remote_sdp);
+
+#if PJSUA_HAS_VIDEO
+PJ_DECL(void) pjsua_vid_win_reset(pjsua_vid_win_id wid);
+#else
+# define pjsua_vid_win_reset(wid)
+#endif
+
+
+PJ_END_DECL
+
+#endif /* __PJSUA_INTERNAL_H__ */
+
diff --git a/pjsip/include/pjsua.h b/pjsip/include/pjsua.h
new file mode 100644
index 0000000..9614367
--- /dev/null
+++ b/pjsip/include/pjsua.h
@@ -0,0 +1 @@
+#include <pjsua-lib/pjsua.h>