mirror of
https://github.com/asterisk/asterisk.git
synced 2025-10-04 12:12:48 +00:00
Merge "res_pjsip: Add support for returning only reachable contacts and use it." into 13
This commit is contained in:
6
CHANGES
6
CHANGES
@@ -19,6 +19,12 @@ res_agi
|
|||||||
EAGI provides. If not specified, it will continue to use the default signed
|
EAGI provides. If not specified, it will continue to use the default signed
|
||||||
linear (slin).
|
linear (slin).
|
||||||
|
|
||||||
|
chan_pjsip
|
||||||
|
------------------
|
||||||
|
* When dialing an endpoint directly or using the PJSIP_DIAL_CONTACTS dialplan
|
||||||
|
function any contact which is considered unreachable due to qualify being
|
||||||
|
enabled will no longer be called.
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
------------------------------------------------------------------------------
|
||||||
--- Functionality changes from Asterisk 13.15.0 to Asterisk 13.16.0 ----------
|
--- Functionality changes from Asterisk 13.15.0 to Asterisk 13.16.0 ----------
|
||||||
------------------------------------------------------------------------------
|
------------------------------------------------------------------------------
|
||||||
|
@@ -898,7 +898,7 @@ int pjsip_acf_dial_contacts_read(struct ast_channel *chan, const char *cmd, char
|
|||||||
if (!aor) {
|
if (!aor) {
|
||||||
/* If the AOR provided is not found skip it, there may be more */
|
/* If the AOR provided is not found skip it, there may be more */
|
||||||
continue;
|
continue;
|
||||||
} else if (!(contacts = ast_sip_location_retrieve_aor_contacts(aor))) {
|
} else if (!(contacts = ast_sip_location_retrieve_aor_contacts_filtered(aor, AST_SIP_CONTACT_FILTER_REACHABLE))) {
|
||||||
/* No contacts are available, skip it as well */
|
/* No contacts are available, skip it as well */
|
||||||
continue;
|
continue;
|
||||||
} else if (!ao2_container_count(contacts)) {
|
} else if (!ao2_container_count(contacts)) {
|
||||||
|
@@ -870,6 +870,17 @@ struct ast_sip_endpoint_identifier {
|
|||||||
struct ast_sip_endpoint *(*identify_endpoint)(pjsip_rx_data *rdata);
|
struct ast_sip_endpoint *(*identify_endpoint)(pjsip_rx_data *rdata);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Contact retrieval filtering flags
|
||||||
|
*/
|
||||||
|
enum ast_sip_contact_filter {
|
||||||
|
/*! \brief Default filter flags */
|
||||||
|
AST_SIP_CONTACT_FILTER_DEFAULT = 0,
|
||||||
|
|
||||||
|
/*! \brief Return only reachable or unknown contacts */
|
||||||
|
AST_SIP_CONTACT_FILTER_REACHABLE = (1 << 0),
|
||||||
|
};
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief Register a SIP service in Asterisk.
|
* \brief Register a SIP service in Asterisk.
|
||||||
*
|
*
|
||||||
@@ -1055,6 +1066,18 @@ struct ast_sip_aor *ast_sip_location_retrieve_aor(const char *aor_name);
|
|||||||
*/
|
*/
|
||||||
struct ast_sip_contact *ast_sip_location_retrieve_first_aor_contact(const struct ast_sip_aor *aor);
|
struct ast_sip_contact *ast_sip_location_retrieve_first_aor_contact(const struct ast_sip_aor *aor);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Retrieve the first bound contact for an AOR and filter based on flags
|
||||||
|
* \since 13.16.0
|
||||||
|
*
|
||||||
|
* \param aor Pointer to the AOR
|
||||||
|
* \param flags Filtering flags
|
||||||
|
* \retval NULL if no contacts available
|
||||||
|
* \retval non-NULL if contacts available
|
||||||
|
*/
|
||||||
|
struct ast_sip_contact *ast_sip_location_retrieve_first_aor_contact_filtered(const struct ast_sip_aor *aor,
|
||||||
|
unsigned int flags);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief Retrieve all contacts currently available for an AOR
|
* \brief Retrieve all contacts currently available for an AOR
|
||||||
*
|
*
|
||||||
@@ -1069,6 +1092,23 @@ struct ast_sip_contact *ast_sip_location_retrieve_first_aor_contact(const struct
|
|||||||
*/
|
*/
|
||||||
struct ao2_container *ast_sip_location_retrieve_aor_contacts(const struct ast_sip_aor *aor);
|
struct ao2_container *ast_sip_location_retrieve_aor_contacts(const struct ast_sip_aor *aor);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Retrieve all contacts currently available for an AOR and filter based on flags
|
||||||
|
* \since 13.16.0
|
||||||
|
*
|
||||||
|
* \param aor Pointer to the AOR
|
||||||
|
* \param flags Filtering flags
|
||||||
|
*
|
||||||
|
* \retval NULL if no contacts available
|
||||||
|
* \retval non-NULL if contacts available
|
||||||
|
*
|
||||||
|
* \warning
|
||||||
|
* Since this function prunes expired contacts before returning, it holds a named write
|
||||||
|
* lock on the aor. If you already hold the lock, call ast_sip_location_retrieve_aor_contacts_nolock instead.
|
||||||
|
*/
|
||||||
|
struct ao2_container *ast_sip_location_retrieve_aor_contacts_filtered(const struct ast_sip_aor *aor,
|
||||||
|
unsigned int flags);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief Retrieve all contacts currently available for an AOR without locking the AOR
|
* \brief Retrieve all contacts currently available for an AOR without locking the AOR
|
||||||
* \since 13.9.0
|
* \since 13.9.0
|
||||||
@@ -1083,6 +1123,22 @@ struct ao2_container *ast_sip_location_retrieve_aor_contacts(const struct ast_si
|
|||||||
*/
|
*/
|
||||||
struct ao2_container *ast_sip_location_retrieve_aor_contacts_nolock(const struct ast_sip_aor *aor);
|
struct ao2_container *ast_sip_location_retrieve_aor_contacts_nolock(const struct ast_sip_aor *aor);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Retrieve all contacts currently available for an AOR without locking the AOR and filter based on flags
|
||||||
|
* \since 13.16.0
|
||||||
|
*
|
||||||
|
* \param aor Pointer to the AOR
|
||||||
|
* \param flags Filtering flags
|
||||||
|
*
|
||||||
|
* \retval NULL if no contacts available
|
||||||
|
* \retval non-NULL if contacts available
|
||||||
|
*
|
||||||
|
* \warning
|
||||||
|
* This function should only be called if you already hold a named write lock on the aor.
|
||||||
|
*/
|
||||||
|
struct ao2_container *ast_sip_location_retrieve_aor_contacts_nolock_filtered(const struct ast_sip_aor *aor,
|
||||||
|
unsigned int flags);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief Retrieve the first bound contact from a list of AORs
|
* \brief Retrieve the first bound contact from a list of AORs
|
||||||
*
|
*
|
||||||
@@ -1111,6 +1167,18 @@ struct ao2_container *ast_sip_location_retrieve_contacts_from_aor_list(const cha
|
|||||||
void ast_sip_location_retrieve_contact_and_aor_from_list(const char *aor_list, struct ast_sip_aor **aor,
|
void ast_sip_location_retrieve_contact_and_aor_from_list(const char *aor_list, struct ast_sip_aor **aor,
|
||||||
struct ast_sip_contact **contact);
|
struct ast_sip_contact **contact);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Retrieve the first bound contact AND the AOR chosen from a list of AORs and filter based on flags
|
||||||
|
* \since 13.16.0
|
||||||
|
*
|
||||||
|
* \param aor_list A comma-separated list of AOR names
|
||||||
|
* \param flags Filtering flags
|
||||||
|
* \param aor The chosen AOR
|
||||||
|
* \param contact The chosen contact
|
||||||
|
*/
|
||||||
|
void ast_sip_location_retrieve_contact_and_aor_from_list_filtered(const char *aor_list, unsigned int flags,
|
||||||
|
struct ast_sip_aor **aor, struct ast_sip_contact **contact);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief Retrieve a named contact
|
* \brief Retrieve a named contact
|
||||||
*
|
*
|
||||||
|
@@ -3038,7 +3038,7 @@ pjsip_dialog *ast_sip_create_dialog_uac(const struct ast_sip_endpoint *endpoint,
|
|||||||
if (res != PJ_SUCCESS) {
|
if (res != PJ_SUCCESS) {
|
||||||
if (res == PJSIP_EINVALIDURI) {
|
if (res == PJSIP_EINVALIDURI) {
|
||||||
ast_log(LOG_ERROR,
|
ast_log(LOG_ERROR,
|
||||||
"Endpoint '%s': Could not create dialog to invalid URI '%s'. Is endpoint registered?\n",
|
"Endpoint '%s': Could not create dialog to invalid URI '%s'. Is endpoint registered and reachable?\n",
|
||||||
ast_sorcery_object_get_id(endpoint), uri);
|
ast_sorcery_object_get_id(endpoint), uri);
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@@ -171,12 +171,36 @@ static int contact_link_static(void *obj, void *arg, int flags)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*! \brief Internal callback function which removes any contact which is unreachable */
|
||||||
|
static int contact_remove_unreachable(void *obj, void *arg, int flags)
|
||||||
|
{
|
||||||
|
struct ast_sip_contact *contact = obj;
|
||||||
|
struct ast_sip_contact_status *status;
|
||||||
|
int unreachable;
|
||||||
|
|
||||||
|
status = ast_res_pjsip_find_or_create_contact_status(contact);
|
||||||
|
if (!status) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
unreachable = (status->status == UNAVAILABLE);
|
||||||
|
ao2_ref(status, -1);
|
||||||
|
|
||||||
|
return unreachable ? CMP_MATCH : 0;
|
||||||
|
}
|
||||||
|
|
||||||
struct ast_sip_contact *ast_sip_location_retrieve_first_aor_contact(const struct ast_sip_aor *aor)
|
struct ast_sip_contact *ast_sip_location_retrieve_first_aor_contact(const struct ast_sip_aor *aor)
|
||||||
|
{
|
||||||
|
return ast_sip_location_retrieve_first_aor_contact_filtered(aor, AST_SIP_CONTACT_FILTER_DEFAULT);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ast_sip_contact *ast_sip_location_retrieve_first_aor_contact_filtered(const struct ast_sip_aor *aor,
|
||||||
|
unsigned int flags)
|
||||||
{
|
{
|
||||||
struct ao2_container *contacts;
|
struct ao2_container *contacts;
|
||||||
struct ast_sip_contact *contact = NULL;
|
struct ast_sip_contact *contact = NULL;
|
||||||
|
|
||||||
contacts = ast_sip_location_retrieve_aor_contacts(aor);
|
contacts = ast_sip_location_retrieve_aor_contacts_filtered(aor, flags);
|
||||||
if (contacts && ao2_container_count(contacts)) {
|
if (contacts && ao2_container_count(contacts)) {
|
||||||
/* Get the first AOR contact in the container. */
|
/* Get the first AOR contact in the container. */
|
||||||
contact = ao2_callback(contacts, 0, NULL, NULL);
|
contact = ao2_callback(contacts, 0, NULL, NULL);
|
||||||
@@ -186,6 +210,12 @@ struct ast_sip_contact *ast_sip_location_retrieve_first_aor_contact(const struct
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct ao2_container *ast_sip_location_retrieve_aor_contacts_nolock(const struct ast_sip_aor *aor)
|
struct ao2_container *ast_sip_location_retrieve_aor_contacts_nolock(const struct ast_sip_aor *aor)
|
||||||
|
{
|
||||||
|
return ast_sip_location_retrieve_aor_contacts_nolock_filtered(aor, AST_SIP_CONTACT_FILTER_DEFAULT);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ao2_container *ast_sip_location_retrieve_aor_contacts_nolock_filtered(const struct ast_sip_aor *aor,
|
||||||
|
unsigned int flags)
|
||||||
{
|
{
|
||||||
/* Give enough space for ^ at the beginning and ;@ at the end, since that is our object naming scheme */
|
/* Give enough space for ^ at the beginning and ;@ at the end, since that is our object naming scheme */
|
||||||
char regex[strlen(ast_sorcery_object_get_id(aor)) + 4];
|
char regex[strlen(ast_sorcery_object_get_id(aor)) + 4];
|
||||||
@@ -205,10 +235,20 @@ struct ao2_container *ast_sip_location_retrieve_aor_contacts_nolock(const struct
|
|||||||
ao2_callback(aor->permanent_contacts, OBJ_NODATA, contact_link_static, contacts);
|
ao2_callback(aor->permanent_contacts, OBJ_NODATA, contact_link_static, contacts);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (flags & AST_SIP_CONTACT_FILTER_REACHABLE) {
|
||||||
|
ao2_callback(contacts, OBJ_NODATA | OBJ_MULTIPLE | OBJ_UNLINK, contact_remove_unreachable, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
return contacts;
|
return contacts;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ao2_container *ast_sip_location_retrieve_aor_contacts(const struct ast_sip_aor *aor)
|
struct ao2_container *ast_sip_location_retrieve_aor_contacts(const struct ast_sip_aor *aor)
|
||||||
|
{
|
||||||
|
return ast_sip_location_retrieve_aor_contacts_filtered(aor, AST_SIP_CONTACT_FILTER_DEFAULT);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ao2_container *ast_sip_location_retrieve_aor_contacts_filtered(const struct ast_sip_aor *aor,
|
||||||
|
unsigned int flags)
|
||||||
{
|
{
|
||||||
struct ao2_container *contacts;
|
struct ao2_container *contacts;
|
||||||
struct ast_named_lock *lock;
|
struct ast_named_lock *lock;
|
||||||
@@ -219,15 +259,22 @@ struct ao2_container *ast_sip_location_retrieve_aor_contacts(const struct ast_si
|
|||||||
}
|
}
|
||||||
|
|
||||||
ao2_lock(lock);
|
ao2_lock(lock);
|
||||||
contacts = ast_sip_location_retrieve_aor_contacts_nolock(aor);
|
contacts = ast_sip_location_retrieve_aor_contacts_nolock_filtered(aor, flags);
|
||||||
ao2_unlock(lock);
|
ao2_unlock(lock);
|
||||||
ast_named_lock_put(lock);
|
ast_named_lock_put(lock);
|
||||||
|
|
||||||
return contacts;
|
return contacts;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void ast_sip_location_retrieve_contact_and_aor_from_list(const char *aor_list, struct ast_sip_aor **aor,
|
void ast_sip_location_retrieve_contact_and_aor_from_list(const char *aor_list, struct ast_sip_aor **aor,
|
||||||
struct ast_sip_contact **contact)
|
struct ast_sip_contact **contact)
|
||||||
|
{
|
||||||
|
ast_sip_location_retrieve_contact_and_aor_from_list_filtered(aor_list, AST_SIP_CONTACT_FILTER_DEFAULT, aor, contact);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ast_sip_location_retrieve_contact_and_aor_from_list_filtered(const char *aor_list, unsigned int flags,
|
||||||
|
struct ast_sip_aor **aor, struct ast_sip_contact **contact)
|
||||||
{
|
{
|
||||||
char *aor_name;
|
char *aor_name;
|
||||||
char *rest;
|
char *rest;
|
||||||
@@ -247,7 +294,7 @@ void ast_sip_location_retrieve_contact_and_aor_from_list(const char *aor_list, s
|
|||||||
if (!(*aor)) {
|
if (!(*aor)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
*contact = ast_sip_location_retrieve_first_aor_contact(*aor);
|
*contact = ast_sip_location_retrieve_first_aor_contact_filtered(*aor, flags);
|
||||||
/* If a valid contact is available use its URI for dialing */
|
/* If a valid contact is available use its URI for dialing */
|
||||||
if (*contact) {
|
if (*contact) {
|
||||||
break;
|
break;
|
||||||
|
@@ -1717,7 +1717,8 @@ struct ast_sip_session *ast_sip_session_create_outgoing(struct ast_sip_endpoint
|
|||||||
if (location || !contact) {
|
if (location || !contact) {
|
||||||
location = S_OR(location, endpoint->aors);
|
location = S_OR(location, endpoint->aors);
|
||||||
|
|
||||||
ast_sip_location_retrieve_contact_and_aor_from_list(location, &found_aor, &found_contact);
|
ast_sip_location_retrieve_contact_and_aor_from_list_filtered(location, AST_SIP_CONTACT_FILTER_REACHABLE,
|
||||||
|
&found_aor, &found_contact);
|
||||||
if (!found_contact || ast_strlen_zero(found_contact->uri)) {
|
if (!found_contact || ast_strlen_zero(found_contact->uri)) {
|
||||||
uri = location;
|
uri = location;
|
||||||
} else {
|
} else {
|
||||||
|
Reference in New Issue
Block a user