initial commit

This commit is contained in:
Dan Bastone committed 2021-10-29 14:41:03 -04:00
commit 636959b37b
2474 files changed
+1343178

No files matched your search

@@ -0,0 +1,245 @@
/* $Id$ */
/*
* 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__ */
File diff suppressed because it is too large. Load diff
@@ -0,0 +1,491 @@
/* $Id$ */
/*
* 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 PJSIP_EXPIRES_NOT_SPECIFIED
/** 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. */
unsigned expiration;/**< Next expiration interval,
PJSIP_REGC_EXPIRATION_NOT_SPECIFIED
if not specified. */
int contact_cnt;/**<Number of contacts in response. */
pjsip_contact_hdr *contact[PJSIP_REGC_MAX_CONTACT]; /**< Contacts. */
pj_bool_t is_unreg; /**< Expire header, if any, set to zero?*/
};
/** Type declaration for callback to receive registration result. */
typedef void pjsip_regc_cb(struct pjsip_regc_cbparam *param);
/**
* Structure to hold parameters when calling application's callback
* specified in #pjsip_regc_set_reg_tsx_cb().
* To update contact address, application can set the field contact_cnt
* and contact inside the callback.
*/
struct pjsip_regc_tsx_cb_param
{
struct pjsip_regc_cbparam cbparam;
int contact_cnt;
pj_str_t contact[PJSIP_REGC_MAX_CONTACT];
};
/** Type declaration for callback set in #pjsip_regc_set_reg_tsx_cb(). */
typedef void pjsip_regc_tsx_cb(struct pjsip_regc_tsx_cb_param *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? */
unsigned interval; /**< Registration interval (seconds). */
unsigned 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);
/**
* Destroy client registration structure. If a registration transaction is
* in progress:
* - if force is PJ_TRUE, then the structure will be deleted only after
* a final response has been received, and in this case, the callback
* won't be called (this behavior is the same as calling
* pjsip_regc_destroye()).
* - if force is PJ_FALSE, the function will return PJ_EBUSY
*
* @param regc The client registration structure.
* @param force Specify if the function must destroy the structure.
*
* @return PJ_SUCCESS on success, or PJ_EBUSY.
*/
PJ_DECL(pj_status_t) pjsip_regc_destroy2(pjsip_regc *regc, pj_bool_t force);
/**
* 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);
/**
* Increment busy counter temporarily, to prevent client registration
* structure from being destroyed.
*
* @param regc The client registration structure.
*/
PJ_DECL(void) pjsip_regc_add_ref( pjsip_regc *regc );
/**
* Decrement temporary busy counter. After this function
* is called, client registration structure may have been destroyed
* if there's a pending destroy.
*
* @param regc The client registration structure.
*
* @return PJ_SUCCESS on success. PJ_EGONE if the registration
* structure has been destroyed inside the function.
*/
PJ_DECL(pj_status_t) pjsip_regc_dec_ref( pjsip_regc *regc );
/**
* Set callback to be called when the registration received a final response.
* This callback is different with the one specified during creation via
* #pjsip_regc_create(). This callback will be called for any final response
* (including 401/407/423) and before any subsequent requests are sent.
* In case of unregistration, this callback will not be called.
*
* @param regc The client registration structure.
* @param tsx_cb Pointer to callback function to receive registration status.
*
* @return PJ_SUCCESS on success.
*/
PJ_DECL(pj_status_t) pjsip_regc_set_reg_tsx_cb(pjsip_regc *regc,
pjsip_regc_tsx_cb *tsx_cb);
/**
* 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__ */
@@ -0,0 +1,301 @@
/* $Id$ */
/*
* 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_and_inc_lock(.., 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__ */
@@ -0,0 +1,275 @@
/* $Id$ */
/*
* 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 refresh error, this function will process
* error from refresh request. The error will be handle according the
* error code, i.e : BYE will be sent after error 503 (Transport Error).
*
* @param inv The invite session.
* @param event The event that trigger the error.
*
* @return PJ_SUCCESS on successful.
*/
PJ_DECL(pj_status_t) pjsip_timer_handle_refresh_error(
pjsip_inv_session *inv,
pjsip_event *event);
/**
* 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__ */
@@ -0,0 +1,208 @@
/* $Id$ */
/*
* 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__ */