res_pjsip: Allow configuration of endpoint identifier query order
[asterisk/asterisk.git] / include / asterisk / res_pjsip.h
index 9baceb9..a34c4b3 100644 (file)
 #include <pjlib.h>
 /* Needed for ast_rtp_dtls_cfg struct */
 #include "asterisk/rtp_engine.h"
+/* Needed for AST_VECTOR macro */
+#include "asterisk/vector.h"
+/* Needed for ast_sip_for_each_channel_snapshot struct */
+#include "asterisk/stasis_channels.h"
+#include "asterisk/stasis_endpoints.h"
 
 /* Forward declarations of PJSIP stuff */
 struct pjsip_rx_data;
@@ -86,6 +91,8 @@ struct ast_sip_transport {
        AST_DECLARE_STRING_FIELDS(
                /*! Certificate of authority list file */
                AST_STRING_FIELD(ca_list_file);
+               /*! Certificate of authority list path */
+               AST_STRING_FIELD(ca_list_path);
                /*! Public certificate file */
                AST_STRING_FIELD(cert_file);
                /*! Optional private key of the certificate file */
@@ -123,6 +130,8 @@ struct ast_sip_transport {
        unsigned int tos;
        /*! QOS COS value */
        unsigned int cos;
+       /*! Write timeout */
+       int write_timeout;
 };
 
 /*!
@@ -144,6 +153,12 @@ struct ast_sip_contact {
        AST_DECLARE_STRING_FIELDS(
                /*! Full URI of the contact */
                AST_STRING_FIELD(uri);
+               /*! Outbound proxy to use for qualify */
+               AST_STRING_FIELD(outbound_proxy);
+               /*! Path information to place in Route headers */
+               AST_STRING_FIELD(path);
+               /*! Content of the User-Agent header in REGISTER request */
+               AST_STRING_FIELD(user_agent);
        );
        /*! Absolute time that this contact is no longer valid after */
        struct timeval expiration_time;
@@ -180,17 +195,6 @@ struct ast_sip_contact_status {
 };
 
 /*!
- * \brief A transport to be used for messages to a contact
- */
-struct ast_sip_contact_transport {
-       AST_DECLARE_STRING_FIELDS(
-               /*! Full URI of the contact */
-               AST_STRING_FIELD(uri);
-       );
-       pjsip_transport *transport;
-};
-
-/*!
  * \brief A SIP address of record
  */
 struct ast_sip_aor {
@@ -199,6 +203,8 @@ struct ast_sip_aor {
        AST_DECLARE_STRING_FIELDS(
                /*! Voicemail boxes for this AOR */
                AST_STRING_FIELD(mailboxes);
+               /*! Outbound proxy for OPTIONS requests */
+               AST_STRING_FIELD(outbound_proxy);
        );
        /*! Minimum expiration time */
        unsigned int minimum_expiration;
@@ -216,6 +222,21 @@ struct ast_sip_aor {
        unsigned int remove_existing;
        /*! Any permanent configured contacts */
        struct ao2_container *permanent_contacts;
+       /*! Determines whether SIP Path headers are supported */
+       unsigned int support_path;
+};
+
+/*!
+ * \brief A wrapper for contact that adds the aor_id and
+ * a consistent contact id.  Used by ast_sip_for_each_contact.
+ */
+struct ast_sip_contact_wrapper {
+       /*! The id of the parent aor. */
+       char *aor_id;
+       /*! The id of contact in form of aor_id/contact_uri. */
+       char *contact_id;
+       /*! Pointer to the actual contact. */
+       struct ast_sip_contact *contact;
 };
 
 /*!
@@ -270,12 +291,7 @@ struct ast_sip_auth {
        enum ast_sip_auth_type type;
 };
 
-struct ast_sip_auth_array {
-       /*! Array of Sorcery IDs of auth sections */
-       const char **names;
-       /*! Number of credentials in the array */
-       unsigned int num;
-};
+AST_VECTOR(ast_sip_auth_vector, const char *);
 
 /*!
  * \brief Different methods by which incoming requests can be matched to endpoints
@@ -459,12 +475,18 @@ struct ast_sip_media_rtp_configuration {
        unsigned int use_ptime;
        /*! Do we use AVPF exclusively for this endpoint? */
        unsigned int use_avpf;
+       /*! Do we force AVP, AVPF, SAVP, or SAVPF even for DTLS media streams? */
+       unsigned int force_avp;
+       /*! Do we use the received media transport in our answer SDP */
+       unsigned int use_received_transport;
        /*! \brief DTLS-SRTP configuration information */
        struct ast_rtp_dtls_cfg dtls_cfg;
        /*! Should SRTP use a 32 byte tag instead of an 80 byte tag? */
        unsigned int srtp_tag_32;
        /*! Do we use media encryption? what type? */
        enum ast_sip_session_media_encryption encryption;
+       /*! Do we want to optimistically support encryption if possible? */
+       unsigned int encryption_optimistic;
 };
 
 /*!
@@ -512,8 +534,6 @@ struct ast_sip_endpoint_media_configuration {
        struct ast_sip_direct_media_configuration direct_media;
        /*! T.38 (FoIP) options */
        struct ast_sip_t38_configuration t38;
-       /*! Codec preferences */
-       struct ast_codec_pref prefs;
        /*! Configured codecs */
        struct ast_format_cap *codecs;
        /*! DSCP TOS bits for audio streams */
@@ -550,6 +570,10 @@ struct ast_sip_endpoint {
                AST_STRING_FIELD(fromuser);
                /*! Domain to place in From header */
                AST_STRING_FIELD(fromdomain);
+               /*! Context to route incoming MESSAGE requests to */
+               AST_STRING_FIELD(message_context);
+               /*! Accountcode to auto-set on channels */
+               AST_STRING_FIELD(accountcode);
        );
        /*! Configuration for extensions */
        struct ast_sip_endpoint_extensions extensions;
@@ -566,9 +590,9 @@ struct ast_sip_endpoint {
        /*! Call pickup configuration */
        struct ast_sip_endpoint_pickup_configuration pickup;
        /*! Inbound authentication credentials */
-       struct ast_sip_auth_array inbound_auths;
+       struct ast_sip_auth_vector inbound_auths;
        /*! Outbound authentication credentials */
-       struct ast_sip_auth_array outbound_auths;
+       struct ast_sip_auth_vector outbound_auths;
        /*! DTMF mode to use with this endpoint */
        enum ast_sip_dtmf_mode dtmf;
        /*! Method(s) by which the endpoint should be identified. */
@@ -585,24 +609,30 @@ struct ast_sip_endpoint {
        unsigned int allowtransfer;
        /*! Method used when handling redirects */
        enum ast_sip_session_redirect redirect_method;
+       /*! Variables set on channel creation */
+       struct ast_variable *channel_vars;
+       /*! Whether to place a 'user=phone' parameter into the request URI if user is a number */
+       unsigned int usereqphone;
+       /*! Whether to pass through hold and unhold using re-invites with recvonly and sendrecv */
+       unsigned int moh_passthrough;
 };
 
 /*!
- * \brief Initialize an auth array with the configured values.
+ * \brief Initialize an auth vector with the configured values.
  *
- * \param array Array to initialize
+ * \param vector Vector to initialize
  * \param auth_names Comma-separated list of names to set in the array
  * \retval 0 Success
  * \retval non-zero Failure
  */
-int ast_sip_auth_array_init(struct ast_sip_auth_array *array, const char *auth_names);
+int ast_sip_auth_vector_init(struct ast_sip_auth_vector *vector, const char *auth_names);
 
 /*!
- * \brief Free contents of an auth array.
+ * \brief Free contents of an auth vector.
  *
- * \param array Array whose contents are to be freed
+ * \param array Vector whose contents are to be freed
  */
-void ast_sip_auth_array_destroy(struct ast_sip_auth_array *array);
+void ast_sip_auth_vector_destroy(struct ast_sip_auth_vector *vector);
 
 /*!
  * \brief Possible returns from ast_sip_check_authentication
@@ -654,14 +684,14 @@ struct ast_sip_outbound_authenticator {
        /*!
         * \brief Create a new request with authentication credentials
         *
-        * \param auths An array of IDs of auth sorcery objects
+        * \param auths A vector of IDs of auth sorcery objects
         * \param challenge The SIP response with authentication challenge(s)
         * \param tsx The transaction in which the challenge was received
         * \param new_request The new SIP request with challenge response(s)
         * \retval 0 Successfully created new request
         * \retval -1 Failed to create a new request
         */
-       int (*create_request_with_auth)(const struct ast_sip_auth_array *auths, struct pjsip_rx_data *challenge,
+       int (*create_request_with_auth)(const struct ast_sip_auth_vector *auths, struct pjsip_rx_data *challenge,
                        struct pjsip_transaction *tsx, struct pjsip_tx_data **new_request);
 };
 
@@ -750,6 +780,23 @@ int ast_sip_register_outbound_authenticator(struct ast_sip_outbound_authenticato
 void ast_sip_unregister_outbound_authenticator(struct ast_sip_outbound_authenticator *auth);
 
 /*!
+ * \brief Register a SIP endpoint identifier with a name.
+ *
+ * An endpoint identifier's purpose is to determine which endpoint a given SIP
+ * message has come from.
+ *
+ * Multiple endpoint identifiers may be registered so that if an endpoint
+ * cannot be identified by one identifier, it may be identified by another.
+ *
+ * \param identifier The SIP endpoint identifier to register
+ * \param name The name of the endpoint identifier
+ * \retval 0 Success
+ * \retval -1 Failure
+ */
+int ast_sip_register_endpoint_identifier_by_name(struct ast_sip_endpoint_identifier *identifier,
+                                                const char *name);
+
+/*!
  * \brief Register a SIP endpoint identifier
  *
  * An endpoint identifier's purpose is to determine which endpoint a given SIP
@@ -812,36 +859,6 @@ pjsip_endpoint *ast_sip_get_pjsip_endpoint(void);
 struct ast_sorcery *ast_sip_get_sorcery(void);
 
 /*!
- * \brief Initialize transport support on a sorcery instance
- *
- * \param sorcery The sorcery instance
- *
- * \retval -1 failure
- * \retval 0 success
- */
-int ast_sip_initialize_sorcery_transport(struct ast_sorcery *sorcery);
-
-/*!
- * \brief Initialize qualify support on a sorcery instance
- *
- * \param sorcery The sorcery instance
- *
- * \retval -1 failure
- * \retval 0 success
- */
-int ast_sip_initialize_sorcery_qualify(struct ast_sorcery *sorcery);
-
-/*!
- * \brief Initialize location support on a sorcery instance
- *
- * \param sorcery The sorcery instance
- *
- * \retval -1 failure
- * \retval 0 success
- */
-int ast_sip_initialize_sorcery_location(struct ast_sorcery *sorcery);
-
-/*!
  * \brief Retrieve a named AOR
  *
  * \param aor_name Name of the AOR
@@ -880,45 +897,24 @@ struct ao2_container *ast_sip_location_retrieve_aor_contacts(const struct ast_si
 struct ast_sip_contact *ast_sip_location_retrieve_contact_from_aor_list(const char *aor_list);
 
 /*!
- * \brief Retrieve a named contact
+ * \brief Retrieve the first bound contact AND the AOR chosen from a list of AORs
  *
- * \param contact_name Name of the contact
- *
- * \retval NULL if not found
- * \retval non-NULL if found
- */
-struct ast_sip_contact *ast_sip_location_retrieve_contact(const char *contact_name);
-
-/*!
- * \brief Add a transport for a contact to use
- */
-
-void ast_sip_location_add_contact_transport(struct ast_sip_contact_transport *ct);
-
-/*!
- * \brief Delete a transport for a contact that went away
- */
-void ast_sip_location_delete_contact_transport(struct ast_sip_contact_transport *ct);
-
-/*!
- * \brief Retrieve a contact_transport, by URI
- *
- * \param contact_uri URI of the contact
- *
- * \retval NULL if not found
- * \retval non-NULL if found
+ * \param aor_list A comma-separated list of AOR names
+ * \param aor The chosen AOR
+ * \param contact The chosen contact
  */
-struct ast_sip_contact_transport *ast_sip_location_retrieve_contact_transport_by_uri(const char *contact_uri);
+ void ast_sip_location_retrieve_contact_and_aor_from_list(const char *aor_list, struct ast_sip_aor **aor,
+       struct ast_sip_contact **contact);
 
 /*!
- * \brief Retrieve a contact_transport, by transport
+ * \brief Retrieve a named contact
  *
- * \param transport transport the contact uses
+ * \param contact_name Name of the contact
  *
  * \retval NULL if not found
  * \retval non-NULL if found
  */
-struct ast_sip_contact_transport *ast_sip_location_retrieve_contact_transport_by_transport(pjsip_transport *transport);
+struct ast_sip_contact *ast_sip_location_retrieve_contact(const char *contact_name);
 
 /*!
  * \brief Add a new contact to an AOR
@@ -926,11 +922,14 @@ struct ast_sip_contact_transport *ast_sip_location_retrieve_contact_transport_by
  * \param aor Pointer to the AOR
  * \param uri Full contact URI
  * \param expiration_time Optional expiration time of the contact
+ * \param path_info Path information
+ * \param user_agent User-Agent header from REGISTER request
  *
  * \retval -1 failure
  * \retval 0 success
  */
-int ast_sip_location_add_contact(struct ast_sip_aor *aor, const char *uri, struct timeval expiration_time);
+int ast_sip_location_add_contact(struct ast_sip_aor *aor, const char *uri,
+       struct timeval expiration_time, const char *path_info, const char *user_agent);
 
 /*!
  * \brief Update a contact
@@ -953,26 +952,6 @@ int ast_sip_location_update_contact(struct ast_sip_contact *contact);
 int ast_sip_location_delete_contact(struct ast_sip_contact *contact);
 
 /*!
- * \brief Initialize domain aliases support on a sorcery instance
- *
- * \param sorcery The sorcery instance
- *
- * \retval -1 failure
- * \retval 0 success
- */
-int ast_sip_initialize_sorcery_domain_alias(struct ast_sorcery *sorcery);
-
-/*!
- * \brief Initialize authentication support on a sorcery instance
- *
- * \param sorcery The sorcery instance
- *
- * \retval -1 failure
- * \retval 0 success
- */
-int ast_sip_initialize_sorcery_auth(struct ast_sorcery *sorcery);
-
-/*!
  * \brief Callback called when an outbound request with authentication credentials is to be sent in dialog
  *
  * This callback will have the created request on it. The callback's purpose is to do any extra
@@ -1008,26 +987,6 @@ int ast_sip_dialog_setup_outbound_authentication(pjsip_dialog *dlg, const struct
                ast_sip_dialog_outbound_auth_cb cb, void *user_data);
 
 /*!
- * \brief Initialize the distributor module
- *
- * The distributor module is responsible for taking an incoming
- * SIP message and placing it into the threadpool. Once in the threadpool,
- * the distributor will perform endpoint lookups and authentication, and
- * then distribute the message up the stack to any further modules.
- *
- * \retval -1 Failure
- * \retval 0 Success
- */
-int ast_sip_initialize_distributor(void);
-
-/*!
- * \brief Destruct the distributor module.
- *
- * Unregisters pjsip modules and cleans up any allocated resources.
- */
-void ast_sip_destroy_distributor(void);
-
-/*!
  * \brief Retrieves a reference to the artificial auth.
  *
  * \retval The artificial auth
@@ -1215,8 +1174,26 @@ pjsip_dialog *ast_sip_create_dialog_uac(const struct ast_sip_endpoint *endpoint,
  *
  * \param endpoint A pointer to the endpoint
  * \param rdata The request that is starting the dialog
+ * \param[out] status On failure, the reason for failure in creating the dialog
+ */
+pjsip_dialog *ast_sip_create_dialog_uas(const struct ast_sip_endpoint *endpoint, pjsip_rx_data *rdata, pj_status_t *status);
+
+/*!
+ * \brief General purpose method for creating an rdata structure using specific information
+ *
+ * \param rdata[out] The rdata structure that will be populated
+ * \param packet A SIP message
+ * \param src_name The source IP address of the message
+ * \param src_port The source port of the message
+ * \param transport_type The type of transport the message was received on
+ * \param local_name The local IP address the message was received on
+ * \param local_port The local port the message was received on
+ *
+ * \retval 0 success
+ * \retval -1 failure
  */
-pjsip_dialog *ast_sip_create_dialog_uas(const struct ast_sip_endpoint *endpoint, pjsip_rx_data *rdata);
+int ast_sip_create_rdata(pjsip_rx_data *rdata, char *packet, const char *src_name, int src_port, char *transport_type,
+       const char *local_name, int local_port);
 
 /*!
  * \brief General purpose method for creating a SIP request
@@ -1234,18 +1211,22 @@ pjsip_dialog *ast_sip_create_dialog_uas(const struct ast_sip_endpoint *endpoint,
  *
  * \param method The method of the SIP request to send
  * \param dlg Optional. If specified, the dialog on which to request the message.
- * \param endpoint Optional. If specified, the request will be created out-of-dialog
- * to the endpoint.
+ * \param endpoint Optional. If specified, the request will be created out-of-dialog to the endpoint.
  * \param uri Optional. If specified, the request will be sent to this URI rather
- * this value.
  * than one configured for the endpoint.
+ * \param contact The contact with which this request is associated for out-of-dialog requests.
  * \param[out] tdata The newly-created request
+ *
+ * The provided contact is attached to tdata with its reference bumped, but will
+ * not survive for the entire lifetime of tdata since the contact is cleaned up
+ * when all supplements have completed execution.
+ *
  * \retval 0 Success
  * \retval -1 Failure
  */
 int ast_sip_create_request(const char *method, struct pjsip_dialog *dlg,
                struct ast_sip_endpoint *endpoint, const char *uri,
-               pjsip_tx_data **tdata);
+               struct ast_sip_contact *contact, pjsip_tx_data **tdata);
 
 /*!
  * \brief General purpose method for sending a SIP request
@@ -1258,12 +1239,50 @@ int ast_sip_create_request(const char *method, struct pjsip_dialog *dlg,
  * they arrive.
  *
  * \param tdata The request to send
- * \param dlg Optional. If specified, the dialog on which the request should be sent
- * \param endpoint Optional. If specified, the request is sent out-of-dialog to the endpoint.
+ * \param dlg Optional. The dialog in which the request is sent.  Otherwise it is out-of-dialog.
+ * \param endpoint Optional. If specified, the out-of-dialog request is sent to the endpoint.
+ * \param token Data to be passed to the callback upon receipt of out-of-dialog response.
+ * \param callback Callback to be called upon receipt of out-of-dialog response.
+ *
+ * \retval 0 Success
+ * \retval -1 Failure (out-of-dialog callback will not be called.)
+ */
+int ast_sip_send_request(pjsip_tx_data *tdata, struct pjsip_dialog *dlg,
+       struct ast_sip_endpoint *endpoint, void *token,
+       void (*callback)(void *token, pjsip_event *e));
+
+/*!
+ * \brief General purpose method for creating a SIP response
+ *
+ * Its typical use would be to create responses for out of dialog
+ * requests.
+ *
+ * \param rdata The rdata from the incoming request.
+ * \param st_code The response code to transmit.
+ * \param contact The contact with which this request is associated.
+ * \param[out] tdata The newly-created response
+ *
+ * The provided contact is attached to tdata with its reference bumped, but will
+ * not survive for the entire lifetime of tdata since the contact is cleaned up
+ * when all supplements have completed execution.
+ *
+ * \retval 0 Success
+ * \retval -1 Failure
+ */
+int ast_sip_create_response(const pjsip_rx_data *rdata, int st_code,
+       struct ast_sip_contact *contact, pjsip_tx_data **p_tdata);
+
+/*!
+ * \brief Send a response to an out of dialog request
+ *
+ * \param res_addr The response address for this response
+ * \param tdata The response to send
+ * \param endpoint The ast_sip_endpoint associated with this response
+ *
  * \retval 0 Success
  * \retval -1 Failure
  */
-int ast_sip_send_request(pjsip_tx_data *tdata, struct pjsip_dialog *dlg, struct ast_sip_endpoint *endpoint);
+int ast_sip_send_response(pjsip_response_addr *res_addr, pjsip_tx_data *tdata, struct ast_sip_endpoint *sip_endpoint);
 
 /*!
  * \brief Determine if an incoming request requires authentication
@@ -1305,7 +1324,7 @@ enum ast_sip_check_auth_result ast_sip_check_authentication(struct ast_sip_endpo
  * callback in the \ref ast_sip_outbound_authenticator structure for details about
  * the parameters and return values.
  */
-int ast_sip_create_request_with_auth(const struct ast_sip_auth_array *auths, pjsip_rx_data *challenge,
+int ast_sip_create_request_with_auth(const struct ast_sip_auth_vector *auths, pjsip_rx_data *challenge,
                pjsip_transaction *tsx, pjsip_tx_data **new_request);
 
 /*!
@@ -1323,6 +1342,16 @@ int ast_sip_create_request_with_auth(const struct ast_sip_auth_array *auths, pjs
 struct ast_sip_endpoint *ast_sip_identify_endpoint(pjsip_rx_data *rdata);
 
 /*!
+ * \brief Set the outbound proxy for an outbound SIP message
+ *
+ * \param tdata The message to set the outbound proxy on
+ * \param proxy SIP uri of the proxy
+ * \retval 0 Success
+ * \retval -1 Failure
+ */
+int ast_sip_set_outbound_proxy(pjsip_tx_data *tdata, const char *proxy);
+
+/*!
  * \brief Add a header to an outbound SIP message
  *
  * \param tdata The message to add the header to
@@ -1349,7 +1378,7 @@ int ast_sip_add_body(pjsip_tx_data *tdata, const struct ast_sip_body *body);
 /*!
  * \brief Add a multipart body to an outbound SIP message
  *
- * This will treat each part of the input array as part of a multipart body and
+ * This will treat each part of the input vector as part of a multipart body and
  * add each part to the SIP message.
  *
  * \param tdata The message to add the body to
@@ -1407,6 +1436,15 @@ void ast_copy_pj_str(char *dest, const pj_str_t *src, size_t size);
 struct ast_sip_endpoint *ast_pjsip_rdata_get_endpoint(pjsip_rx_data *rdata);
 
 /*!
+ * \brief Add 'user=phone' parameter to URI if enabled and user is a phone number.
+ *
+ * \param endpoint The endpoint to use for configuration
+ * \param pool The memory pool to allocate the parameter from
+ * \param uri The URI to check for user and to add parameter to
+ */
+void ast_sip_add_usereqphone(const struct ast_sip_endpoint *endpoint, pj_pool_t *pool, pjsip_uri *uri);
+
+/*!
  * \brief Retrieve any endpoints available to sorcery.
  *
  * \retval Endpoints available to sorcery, NULL if no endpoints found.
@@ -1414,12 +1452,19 @@ struct ast_sip_endpoint *ast_pjsip_rdata_get_endpoint(pjsip_rx_data *rdata);
 struct ao2_container *ast_sip_get_endpoints(void);
 
 /*!
+ * \brief Retrieve the default outbound endpoint.
+ *
+ * \retval The default outbound endpoint, NULL if not found.
+ */
+struct ast_sip_endpoint *ast_sip_default_outbound_endpoint(void);
+
+/*!
  * \brief Retrieve relevant SIP auth structures from sorcery
  *
- * \param auths Array of sorcery IDs of auth credentials to retrieve
+ * \param auths Vector of sorcery IDs of auth credentials to retrieve
  * \param[out] out The retrieved auths are stored here
  */
-int ast_sip_retrieve_auths(const struct ast_sip_auth_array *auths, struct ast_sip_auth **out);
+int ast_sip_retrieve_auths(const struct ast_sip_auth_vector *auths, struct ast_sip_auth **out);
 
 /*!
  * \brief Clean up retrieved auth structures from memory
@@ -1427,8 +1472,8 @@ int ast_sip_retrieve_auths(const struct ast_sip_auth_array *auths, struct ast_si
  * Call this function once you have completed operating on auths
  * retrieved from \ref ast_sip_retrieve_auths
  *
- * \param auths An array of auth structures to clean up
- * \param num_auths The number of auths in the array
+ * \param auths An vector of auth structures to clean up
+ * \param num_auths The number of auths in the vector
  */
 void ast_sip_cleanup_auths(struct ast_sip_auth *auths[], size_t num_auths);
 
@@ -1507,14 +1552,9 @@ void ast_sip_report_req_no_support(struct ast_sip_endpoint *endpoint, pjsip_rx_d
  */
 void ast_sip_report_mem_limit(struct ast_sip_endpoint *endpoint, pjsip_rx_data *rdata);
 
-void ast_sip_initialize_global_headers(void);
-void ast_sip_destroy_global_headers(void);
-
 int ast_sip_add_global_request_header(const char *name, const char *value, int replace);
 int ast_sip_add_global_response_header(const char *name, const char *value, int replace);
 
-int ast_sip_initialize_sorcery_global(struct ast_sorcery *sorcery);
-
 /*!
  * \brief Retrieves the value associated with the given key.
  *
@@ -1571,35 +1611,26 @@ void *ast_sip_dict_set(pj_pool_t* pool, void *ht,
        mod_data[id] = ast_sip_dict_set(pool, mod_data[id], key, val)
 
 /*!
- * \brief Function pointer for contact callbacks.
- */
-typedef int (*on_contact_t)(const struct ast_sip_aor *aor,
-                           const struct ast_sip_contact *contact,
-                           int last, void *arg);
-
-/*!
  * \brief For every contact on an AOR call the given 'on_contact' handler.
  *
  * \param aor the aor containing a list of contacts to iterate
- * \param on_contact callback on each contact on an AOR
+ * \param on_contact callback on each contact on an AOR.  The object
+ * received by the callback will be a ast_sip_contact_wrapper structure.
  * \param arg user data passed to handler
  * \retval 0 Success, non-zero on failure
  */
 int ast_sip_for_each_contact(const struct ast_sip_aor *aor,
-                            on_contact_t on_contact, void *arg);
+               ao2_callback_fn on_contact, void *arg);
 
 /*!
  * \brief Handler used to convert a contact to a string.
  *
- * \param aor the aor containing a list of contacts to iterate
- * \param contact the contact to convert
- * \param last is this the last contact
+ * \param object the ast_sip_aor_contact_pair containing a list of contacts to iterate and the contact
  * \param arg user data passed to handler
+ * \param flags
  * \retval 0 Success, non-zero on failure
  */
-int ast_sip_contact_to_str(const struct ast_sip_aor *aor,
-                          const struct ast_sip_contact *contact,
-                          int last, void *arg);
+int ast_sip_contact_to_str(void *object, void *arg, int flags);
 
 /*!
  * \brief For every aor in the comma separated aors string call the
@@ -1620,7 +1651,7 @@ int ast_sip_for_each_aor(const char *aors, ao2_callback_fn on_aor, void *arg);
  * \param arg user data passed to handler
  * \retval 0 Success, non-zero on failure
  */
-int ast_sip_for_each_auth(const struct ast_sip_auth_array *array,
+int ast_sip_for_each_auth(const struct ast_sip_auth_vector *array,
                          ao2_callback_fn on_auth, void *arg);
 
 /*!
@@ -1638,7 +1669,7 @@ const char *ast_sip_auth_type_to_str(enum ast_sip_auth_type type);
  * \param buf the string buffer to write the object data
  * \retval 0 Success, non-zero on failure
  */
-int ast_sip_auths_to_str(const struct ast_sip_auth_array *auths, char **buf);
+int ast_sip_auths_to_str(const struct ast_sip_auth_vector *auths, char **buf);
 
 /*
  * \brief AMI variable container
@@ -1648,8 +1679,12 @@ struct ast_sip_ami {
        struct mansession *s;
        /*! Manager message */
        const struct message *m;
+       /*! Manager Action ID */
+       const char *action_id;
        /*! user specified argument data */
        void *arg;
+       /*! count of objects */
+       int count;
 };
 
 /*!
@@ -1717,7 +1752,177 @@ int ast_sip_format_endpoint_ami(struct ast_sip_endpoint *endpoint,
  * \param ami ami variable container
  * \retval 0 Success, non-zero on failure
  */
-int ast_sip_format_auths_ami(const struct ast_sip_auth_array *auths,
+int ast_sip_format_auths_ami(const struct ast_sip_auth_vector *auths,
                             struct ast_sip_ami *ami);
 
+/*!
+ * \brief Retrieve the endpoint snapshot for an endpoint
+ *
+ * \param endpoint The endpoint whose snapshot is to be retreieved.
+ * \retval The endpoint snapshot
+ */
+struct ast_endpoint_snapshot *ast_sip_get_endpoint_snapshot(
+       const struct ast_sip_endpoint *endpoint);
+
+/*!
+ * \brief Retrieve the device state for an endpoint.
+ *
+ * \param endpoint The endpoint whose state is to be retrieved.
+ * \retval The device state.
+ */
+const char *ast_sip_get_device_state(const struct ast_sip_endpoint *endpoint);
+
+/*!
+ * \brief For every channel snapshot on an endpoint snapshot call the given
+ *        'on_channel_snapshot' handler.
+ *
+ * \param endpoint_snapshot snapshot of an endpoint
+ * \param on_channel_snapshot callback for each channel snapshot
+ * \param arg user data passed to handler
+ * \retval 0 Success, non-zero on failure
+ */
+int ast_sip_for_each_channel_snapshot(const struct ast_endpoint_snapshot *endpoint_snapshot,
+               ao2_callback_fn on_channel_snapshot,
+                                     void *arg);
+
+/*!
+ * \brief For every channel snapshot on an endpoint all the given
+ *        'on_channel_snapshot' handler.
+ *
+ * \param endpoint endpoint
+ * \param on_channel_snapshot callback for each channel snapshot
+ * \param arg user data passed to handler
+ * \retval 0 Success, non-zero on failure
+ */
+int ast_sip_for_each_channel(const struct ast_sip_endpoint *endpoint,
+               ao2_callback_fn on_channel_snapshot,
+                                     void *arg);
+
+enum ast_sip_supplement_priority {
+       /*! Top priority. Supplements with this priority are those that need to run before any others */
+       AST_SIP_SUPPLEMENT_PRIORITY_FIRST = 0,
+       /*! Channel creation priority.
+        * chan_pjsip creates a channel at this priority. If your supplement depends on being run before
+        * or after channel creation, then set your priority to be lower or higher than this value.
+        */
+       AST_SIP_SUPPLEMENT_PRIORITY_CHANNEL = 1000000,
+       /*! Lowest priority. Supplements with this priority should be run after all other supplements */
+       AST_SIP_SUPPLEMENT_PRIORITY_LAST = INT_MAX,
+};
+
+/*!
+ * \brief A supplement to SIP message processing
+ *
+ * These can be registered by any module in order to add
+ * processing to incoming and outgoing SIP out of dialog
+ * requests and responses
+ */
+struct ast_sip_supplement {
+       /*! Method on which to call the callbacks. If NULL, call on all methods */
+       const char *method;
+       /*! Priority for this supplement. Lower numbers are visited before higher numbers */
+       enum ast_sip_supplement_priority priority;
+       /*!
+        * \brief Called on incoming SIP request
+        * This method can indicate a failure in processing in its return. If there
+        * is a failure, it is required that this method sends a response to the request.
+        * This method is always called from a SIP servant thread.
+        *
+        * \note
+        * The following PJSIP methods will not work properly:
+        * pjsip_rdata_get_dlg()
+        * pjsip_rdata_get_tsx()
+        * The reason is that the rdata passed into this function is a cloned rdata structure,
+        * and its module data is not copied during the cloning operation.
+        * If you need to get the dialog, you can get it via session->inv_session->dlg.
+        *
+        * \note
+        * There is no guarantee that a channel will be present on the session when this is called.
+        */
+       int (*incoming_request)(struct ast_sip_endpoint *endpoint, struct pjsip_rx_data *rdata);
+       /*!
+        * \brief Called on an incoming SIP response
+        * This method is always called from a SIP servant thread.
+        *
+        * \note
+        * The following PJSIP methods will not work properly:
+        * pjsip_rdata_get_dlg()
+        * pjsip_rdata_get_tsx()
+        * The reason is that the rdata passed into this function is a cloned rdata structure,
+        * and its module data is not copied during the cloning operation.
+        * If you need to get the dialog, you can get it via session->inv_session->dlg.
+        *
+        * \note
+        * There is no guarantee that a channel will be present on the session when this is called.
+        */
+       void (*incoming_response)(struct ast_sip_endpoint *endpoint, struct pjsip_rx_data *rdata);
+       /*!
+        * \brief Called on an outgoing SIP request
+        * This method is always called from a SIP servant thread.
+        */
+       void (*outgoing_request)(struct ast_sip_endpoint *endpoint, struct ast_sip_contact *contact, struct pjsip_tx_data *tdata);
+       /*!
+        * \brief Called on an outgoing SIP response
+        * This method is always called from a SIP servant thread.
+        */
+       void (*outgoing_response)(struct ast_sip_endpoint *endpoint, struct ast_sip_contact *contact, struct pjsip_tx_data *tdata);
+       /*! Next item in the list */
+       AST_LIST_ENTRY(ast_sip_supplement) next;
+};
+
+/*!
+ * \brief Register a supplement to SIP out of dialog processing
+ *
+ * This allows for someone to insert themselves in the processing of out
+ * of dialog SIP requests and responses. This, for example could allow for
+ * a module to set channel data based on headers in an incoming message.
+ * Similarly, a module could reject an incoming request if desired.
+ *
+ * \param supplement The supplement to register
+ * \retval 0 Success
+ * \retval -1 Failure
+ */
+int ast_sip_register_supplement(struct ast_sip_supplement *supplement);
+
+/*!
+ * \brief Unregister a an supplement to SIP out of dialog processing
+ *
+ * \param supplement The supplement to unregister
+ */
+void ast_sip_unregister_supplement(struct ast_sip_supplement *supplement);
+
+/*!
+ * \brief Retrieve the system debug setting (yes|no|host).
+ *
+ * \note returned string needs to be de-allocated by caller.
+ *
+ * \retval the system debug setting.
+ */
+char *ast_sip_get_debug(void);
+
+/*!
+ * \brief Retrieve the global endpoint_identifier_order setting.
+ *
+ * Specifies the order by which endpoint identifiers should be regarded.
+ *
+ * \retval the global endpoint_identifier_order value
+ */
+char *ast_sip_get_endpoint_identifier_order(void);
+
+/*! \brief Determines whether the res_pjsip module is loaded */
+#define CHECK_PJSIP_MODULE_LOADED()                            \
+       do {                                                    \
+               if (!ast_module_check("res_pjsip.so")           \
+                       || !ast_sip_get_pjsip_endpoint()) {     \
+                       return AST_MODULE_LOAD_DECLINE;         \
+               }                                               \
+       } while(0)
+
+/*!
+ * \brief Retrieve the system keep alive interval setting.
+ *
+ * \retval the keep alive interval.
+ */
+unsigned int ast_sip_get_keep_alive_interval(void);
+
 #endif /* _RES_PJSIP_H */