[asterisk-commits] kharwell: branch kharwell/pimp_sip_qualify r391316 - in /team/kharwell/pimp_s...
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Mon Jun 10 18:06:35 CDT 2013
Author: kharwell
Date: Mon Jun 10 18:06:34 2013
New Revision: 391316
URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=391316
Log:
updates per review
Modified:
team/kharwell/pimp_sip_qualify/include/asterisk/res_sip.h
team/kharwell/pimp_sip_qualify/res/res_sip.c
team/kharwell/pimp_sip_qualify/res/res_sip/location.c
team/kharwell/pimp_sip_qualify/res/res_sip/sip_options.c
team/kharwell/pimp_sip_qualify/res/res_sip_registrar.c
Modified: team/kharwell/pimp_sip_qualify/include/asterisk/res_sip.h
URL: http://svnview.digium.com/svn/asterisk/team/kharwell/pimp_sip_qualify/include/asterisk/res_sip.h?view=diff&rev=391316&r1=391315&r2=391316
==============================================================================
--- team/kharwell/pimp_sip_qualify/include/asterisk/res_sip.h (original)
+++ team/kharwell/pimp_sip_qualify/include/asterisk/res_sip.h Mon Jun 10 18:06:34 2013
@@ -139,6 +139,32 @@
struct timeval expiration_time;
/*! Frequency to send OPTIONS requests to contact. 0 is disabled. */
unsigned int qualify_frequency;
+ /*! If true authenticate the qualify if needed */
+ int authenticate_qualify;
+};
+
+/*!
+ * \brief Status type for a contact.
+ */
+enum ast_sip_contact_status_type {
+ UNAVAILABLE,
+ AVAILABLE
+};
+
+/*!
+ * \brief A contact's status.
+ *
+ * \detail Maintains a contact's current status and round trip time
+ * if available.
+ */
+struct ast_sip_contact_status {
+ SORCERY_OBJECT(details);
+ /*! Current status for a contact (default - unavailable) */
+ enum ast_sip_contact_status_type status;
+ /*! The round trip start time set before sending a qualify request */
+ struct timeval rtt_start;
+ /*! The round trip time in microseconds */
+ int64_t rtt;
};
/*!
@@ -170,6 +196,8 @@
unsigned int default_expiration;
/*! Frequency to send OPTIONS requests to AOR contacts. 0 is disabled. */
unsigned int qualify_frequency;
+ /*! If true authenticate the qualify if needed */
+ int authenticate_qualify;
/*! Maximum number of external contacts, 0 to disable */
unsigned int max_contacts;
/*! Whether to remove any existing contacts not related to an incoming REGISTER when it comes in */
Modified: team/kharwell/pimp_sip_qualify/res/res_sip.c
URL: http://svnview.digium.com/svn/asterisk/team/kharwell/pimp_sip_qualify/res/res_sip.c?view=diff&rev=391316&r1=391315&r2=391316
==============================================================================
--- team/kharwell/pimp_sip_qualify/res/res_sip.c (original)
+++ team/kharwell/pimp_sip_qualify/res/res_sip.c Mon Jun 10 18:06:34 2013
@@ -603,6 +603,13 @@
If <literal>0</literal> never qualify. Time in seconds.
</para></description>
</configOption>
+ <configOption name="authenticate_qualify" default="no">
+ <synopsis>Authenticates if a qualify request if needed</synopsis>
+ <description><para>
+ If true and a qualify request receives a challenge or authenticate response
+ authentication is attempted before declaring the contact available.
+ </para></description>
+ </configOption>
</configObject>
</configFile>
</configInfo>
Modified: team/kharwell/pimp_sip_qualify/res/res_sip/location.c
URL: http://svnview.digium.com/svn/asterisk/team/kharwell/pimp_sip_qualify/res/res_sip/location.c?view=diff&rev=391316&r1=391315&r2=391316
==============================================================================
--- team/kharwell/pimp_sip_qualify/res/res_sip/location.c (original)
+++ team/kharwell/pimp_sip_qualify/res/res_sip/location.c Mon Jun 10 18:06:34 2013
@@ -236,6 +236,7 @@
ast_string_field_set(contact, uri, uri);
contact->expiration_time = expiration_time;
contact->qualify_frequency = aor->qualify_frequency;
+ contact->authenticate_qualify = aor->authenticate_qualify;
return ast_sorcery_create(ast_sip_get_sorcery(), contact);
}
@@ -303,6 +304,7 @@
ast_sorcery_object_field_register(sorcery, "aor", "maximum_expiration", "7200", OPT_UINT_T, 0, FLDSET(struct ast_sip_aor, maximum_expiration));
ast_sorcery_object_field_register(sorcery, "aor", "default_expiration", "3600", OPT_UINT_T, 0, FLDSET(struct ast_sip_aor, default_expiration));
ast_sorcery_object_field_register(sorcery, "aor", "qualify_frequency", 0, OPT_UINT_T, PARSE_IN_RANGE, FLDSET(struct ast_sip_aor, qualify_frequency), 0, 86400);
+ ast_sorcery_object_field_register(sorcery, "contact", "authenticate_qualify", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_aor, authenticate_qualify));
ast_sorcery_object_field_register(sorcery, "aor", "max_contacts", "0", OPT_UINT_T, 0, FLDSET(struct ast_sip_aor, max_contacts));
ast_sorcery_object_field_register(sorcery, "aor", "remove_existing", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_aor, remove_existing));
ast_sorcery_object_field_register_custom(sorcery, "aor", "contact", "", permanent_uri_handler, NULL, 0, 0);
Modified: team/kharwell/pimp_sip_qualify/res/res_sip/sip_options.c
URL: http://svnview.digium.com/svn/asterisk/team/kharwell/pimp_sip_qualify/res/res_sip/sip_options.c?view=diff&rev=391316&r1=391315&r2=391316
==============================================================================
--- team/kharwell/pimp_sip_qualify/res/res_sip/sip_options.c (original)
+++ team/kharwell/pimp_sip_qualify/res/res_sip/sip_options.c Mon Jun 10 18:06:34 2013
@@ -37,53 +37,33 @@
static int qualify_contact(struct ast_sip_contact *contact);
-enum contact_status_type {
- UNAVAILABLE,
- AVAILABLE
-};
-
-/*!
- * \internal
- * \brief A contact's status.
- *
- * \detail Maintains a contact's current status and round trip time
- * if available.
- */
-struct contact_status {
- SORCERY_OBJECT(details);
- /*! 0 = unavailable, 1 = available (default) */
- enum contact_status_type status;
- /*! The round trip start time set before sending a qualify request */
- struct timeval rtt_start;
- /*! The round trip time in microseconds */
- int64_t rtt;
-};
-
-/*!
- * \internal
- * \brief Create a contact_status object.
+/*!
+ * \internal
+ * \brief Create a ast_sip_contact_status object.
*/
static void *contact_status_alloc(const char *name)
{
- struct contact_status *status = ao2_alloc_options(
+ struct ast_sip_contact_status *status = ao2_alloc_options(
sizeof(*status), NULL, AO2_ALLOC_OPT_LOCK_NOLOCK);
if (!status) {
- ast_log(LOG_ERROR, "Unable to allocate contact_status\n");
+ ast_log(LOG_ERROR, "Unable to allocate ast_sip_contact_status\n");
return NULL;
}
+ status->status = UNAVAILABLE;
+
return status;
}
/*!
* \internal
- * \brief Retrieve a contact_status object from sorcery creating
+ * \brief Retrieve a ast_sip_contact_status object from sorcery creating
* one if not found.
*/
-static struct contact_status *get_contact_status(const struct ast_sip_contact *contact)
-{
- struct contact_status *status = ast_sorcery_retrieve_by_id(
+static struct ast_sip_contact_status *find_or_create_contact_status(const struct ast_sip_contact *contact)
+{
+ struct ast_sip_contact_status *status = ast_sorcery_retrieve_by_id(
ast_sip_get_sorcery(), CONTACT_STATUS,
ast_sorcery_object_get_id(contact));
@@ -95,13 +75,13 @@
ast_sip_get_sorcery(), CONTACT_STATUS,
ast_sorcery_object_get_id(contact)))) {
- ast_log(LOG_ERROR, "Unable to create contact_status for contact %s\n",
+ ast_log(LOG_ERROR, "Unable to create ast_sip_contact_status for contact %s\n",
contact->uri);
return NULL;
}
if (ast_sorcery_create(ast_sip_get_sorcery(), status)) {
- ast_log(LOG_ERROR, "Unable to persist contact_status for contact %s\n",
+ ast_log(LOG_ERROR, "Unable to persist ast_sip_contact_status for contact %s\n",
contact->uri);
return NULL;
}
@@ -111,38 +91,39 @@
/*!
* \internal
- * \brief Set a contact_status's status to the given value.
+ * \brief Update an ast_sip_contact_status's elements.
*/
static void update_contact_status(const struct ast_sip_contact *contact,
- enum contact_status_type value)
-{
- RAII_VAR(struct contact_status *, status,
- get_contact_status(contact), ao2_cleanup);
-
- RAII_VAR(struct contact_status *, copy, ast_sorcery_copy(
- ast_sip_get_sorcery(), status), ao2_cleanup);
-
- if (!copy) {
- ast_log(LOG_ERROR, "Unable to copy contact_status for contact %s\n",
+ enum ast_sip_contact_status_type value)
+{
+ RAII_VAR(struct ast_sip_contact_status *, status,
+ find_or_create_contact_status(contact), ao2_cleanup);
+
+ RAII_VAR(struct ast_sip_contact_status *, update, ast_sorcery_alloc(
+ ast_sip_get_sorcery(), CONTACT_STATUS,
+ ast_sorcery_object_get_id(status)), ao2_cleanup);
+
+ if (!update) {
+ ast_log(LOG_ERROR, "Unable to create update ast_sip_contact_status for contact %s\n",
contact->uri);
return;
}
- copy->status = value;
+ update->status = value;
/* status is set to unavailable just before sending, so intialize the rrt
start time to "now", so when we receive a response (status = available)
we can calculate the rtt */
- if (copy->status) {
- copy->rtt = ast_tvdiff_us(ast_tvnow(), status->rtt_start);
- copy->rtt_start = ast_tv(0, 0);
+ if (update->status) {
+ update->rtt = ast_tvdiff_us(ast_tvnow(), status->rtt_start);
+ update->rtt_start = ast_tv(0, 0);
} else {
- copy->rtt_start = ast_tvnow();
- copy->rtt = 0;
- }
-
- if (ast_sorcery_update(ast_sip_get_sorcery(), copy)) {
- ast_log(LOG_ERROR, "Unable to update contact_status for contact %s\n",
+ update->rtt_start = ast_tvnow();
+ update->rtt = 0;
+ }
+
+ if (ast_sorcery_update(ast_sip_get_sorcery(), update)) {
+ ast_log(LOG_ERROR, "Unable to update ast_sip_contact_status for contact %s\n",
contact->uri);
}
}
@@ -159,10 +140,7 @@
/*!
* \internal
- * \brief For an endpoint iterate over aors/contacts
- *
- * \detail For the given endpoint either match on a contact (if one
- * is given) or qualify all contacts found.
+ * \brief For an endpoint try to match on a given contact.
*/
static int on_endpoint(void *obj, void *arg, int flags)
{
@@ -186,8 +164,6 @@
if (arg && ao2_find(contacts, arg, OBJ_NODATA | OBJ_POINTER)) {
return CMP_MATCH;
- } else {
- ao2_callback(contacts, OBJ_NODATA, on_contact, NULL);
}
}
@@ -220,7 +196,17 @@
pjsip_rx_data *challenge = e->body.tsx_state.src.rdata;
pjsip_tx_data *tdata;
- if (tsx->status_code != 401 && tsx->status_code != 407) {
+ switch(e->body.tsx_state.type) {
+ case PJSIP_EVENT_TRANSPORT_ERROR:
+ case PJSIP_EVENT_TIMER:
+ update_contact_status(contact, UNAVAILABLE);
+ return;
+ default:
+ break;
+ }
+
+ if (!contact->authenticate_qualify || (tsx->status_code != 401 &&
+ tsx->status_code != 407)) {
update_contact_status(contact, AVAILABLE);
return;
}
@@ -254,9 +240,6 @@
static int qualify_contact(struct ast_sip_contact *contact)
{
pjsip_tx_data *tdata;
- /* assume we can't connect so if no reply comes back the contact is
- considered unavailable */
- update_contact_status(contact, UNAVAILABLE);
if (ast_sip_create_request("OPTIONS", NULL, NULL, contact->uri, &tdata)) {
ast_log(LOG_ERROR, "Unable to create request to qualify contact %s\n",
@@ -307,14 +290,7 @@
static void sched_data_destructor(void *obj)
{
struct sched_data *data = obj;
-
- if (!AST_SCHED_DEL(sched, data->id)) {
- /* If we successfully deleted the qualify, we got it before it
- fired. We can safely unref the data that was passed to it.
- Otherwise, we're getting deleted while this is firing, so
- don't unref! */
- ao2_ref(data->contact, -1);
- }
+ ao2_cleanup(data->contact);
}
/*!
* \internal
@@ -351,22 +327,18 @@
*/
static int qualify_contact_sched(const void *obj)
{
- RAII_VAR(struct sched_data *, data, (struct sched_data *)obj, ao2_cleanup);
-
- if (!data) {
- return 0;
- }
-
- ao2_ref(data, +1);
+ struct sched_data *data = (struct sched_data *)obj;
if (!data->contact) {
/* contact is gone - so remove from scheduler */
+ ao2_cleanup(data);
return 0;
}
ao2_ref(data->contact, +1);
if (ast_sip_push_task(NULL, qualify_contact_task, data->contact)) {
ao2_ref(data->contact, -1);
+ ao2_cleanup(data);
return 0;
}
@@ -385,10 +357,12 @@
return;
}
- data->id = ast_sched_add_variable(
- sched, contact->qualify_frequency * 1000, qualify_contact_sched, data, 1);
-
- if (data->id < 0) {
+ ao2_ref(data, +1);
+ if ((data->id = ast_sched_add_variable(
+ sched, contact->qualify_frequency * 1000,
+ qualify_contact_sched, data, 1)) < 0) {
+
+ ao2_ref(data, -1);
ast_log(LOG_ERROR, "Unable to schedule qualify for contact %s\n",
contact->uri);
return;
@@ -403,7 +377,14 @@
*/
static void unschedule_qualify(struct ast_sip_contact *contact)
{
- ao2_find(sched_qualifies, contact, OBJ_UNLINK | OBJ_NODATA);
+ RAII_VAR(struct sched_data *, data, ao2_find(
+ sched_qualifies, contact, OBJ_UNLINK | OBJ_NODATA), ao2_cleanup);
+
+ if (!data) {
+ return;
+ }
+
+ AST_SCHED_DEL_UNREF(sched, data->id, ao2_cleanup(data));
}
/*!
@@ -438,7 +419,7 @@
static void contact_deleted(const void *obj)
{
struct ast_sip_contact *contact = (struct ast_sip_contact *)obj;
- RAII_VAR(struct contact_status *, status, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_sip_contact_status *, status, NULL, ao2_cleanup);
unschedule_qualify(contact);
@@ -449,7 +430,7 @@
}
if (ast_sorcery_delete(ast_sip_get_sorcery(), status)) {
- ast_log(LOG_ERROR, "Unable to delete contact_status for contact %s\n",
+ ast_log(LOG_ERROR, "Unable to delete ast_sip_contact_status for contact %s\n",
contact->uri);
}
}
@@ -585,6 +566,33 @@
.stop = options_stop,
.on_rx_request = options_on_rx_request,
};
+
+/*!
+ * \internal
+ * \brief For an endpoint iterate over and qualify all aors/contacts
+ */
+static void cli_qualify_contacts(struct ast_sip_endpoint *endpoint)
+{
+ char *aor_name, *aors;
+
+ if (ast_strlen_zero(endpoint->aors)) {
+ return;
+ }
+
+ aors = ast_strdupa(endpoint->aors);
+
+ while ((aor_name = strsep(&aors, ","))) {
+ RAII_VAR(struct ast_sip_aor *, aor,
+ ast_sip_location_retrieve_aor(aor_name), ao2_cleanup);
+ RAII_VAR(struct ao2_container *, contacts, NULL, ao2_cleanup);
+
+ if (!aor || !(contacts = ast_sip_location_retrieve_aor_contacts(aor))) {
+ continue;
+ }
+
+ ao2_callback(contacts, OBJ_NODATA, on_contact, NULL);
+ }
+}
static char *cli_qualify(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
{
@@ -615,7 +623,7 @@
}
/* send a qualify for all contacts registered with the endpoint */
- on_endpoint(endpoint, NULL, 0);
+ cli_qualify_contacts(endpoint);
return CLI_SUCCESS;
}
@@ -624,8 +632,8 @@
{
struct ast_sip_contact *contact = obj;
struct ast_cli_args *a = arg;
- RAII_VAR(struct contact_status *, status,
- get_contact_status(contact), ao2_cleanup);
+ RAII_VAR(struct ast_sip_contact_status *, status,
+ find_or_create_contact_status(contact), ao2_cleanup);
ast_cli(a->fd, "\tContact %s:\n", contact->uri);
@@ -724,17 +732,19 @@
int ast_sip_initialize_sorcery_qualify(struct ast_sorcery *sorcery)
{
- /* initialize sorcery contact_status resource */
+ /* initialize sorcery ast_sip_contact_status resource */
ast_sorcery_apply_default(sorcery, CONTACT_STATUS, "memory", NULL);
if (ast_sorcery_object_register(sorcery, CONTACT_STATUS,
contact_status_alloc, NULL, NULL)) {
- ast_log(LOG_ERROR, "Unable to register contact_status in sorcery\n");
+ ast_log(LOG_ERROR, "Unable to register ast_sip_contact_status in sorcery\n");
return -1;
}
ast_sorcery_object_field_register(sorcery, CONTACT_STATUS, "rtt", "0", OPT_UINT_T,
- 1, FLDSET(struct contact_status, rtt));
+ 1, FLDSET(struct ast_sip_contact_status, status));
+ ast_sorcery_object_field_register(sorcery, CONTACT_STATUS, "rtt", "0", OPT_UINT_T,
+ 1, FLDSET(struct ast_sip_contact_status, rtt));
if (ast_sorcery_observer_add(sorcery, "contact", &contact_observer)) {
ast_log(LOG_WARNING, "Unable to add contact observer\n");
Modified: team/kharwell/pimp_sip_qualify/res/res_sip_registrar.c
URL: http://svnview.digium.com/svn/asterisk/team/kharwell/pimp_sip_qualify/res/res_sip_registrar.c?view=diff&rev=391316&r1=391315&r2=391316
==============================================================================
--- team/kharwell/pimp_sip_qualify/res/res_sip_registrar.c (original)
+++ team/kharwell/pimp_sip_qualify/res/res_sip_registrar.c Mon Jun 10 18:06:34 2013
@@ -311,6 +311,7 @@
RAII_VAR(struct ast_sip_contact *, updated, ast_sorcery_copy(ast_sip_get_sorcery(), contact), ao2_cleanup);
updated->expiration_time = ast_tvadd(ast_tvnow(), ast_samp2tv(expiration, 1));
updated->qualify_frequency = aor->qualify_frequency;
+ updated->authenticate_qualify = aor->authenticate_qualify;
ast_sip_location_update_contact(updated);
ast_debug(3, "Refreshed contact '%s' on AOR '%s' with new expiration of %d seconds\n",
More information about the asterisk-commits
mailing list