[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