res_pjsip: improve realtime performance
authorAlexei Gradinari <alex2grad@gmail.com>
Fri, 15 Apr 2016 14:32:12 +0000 (10:32 -0400)
committerJoshua Colp <jcolp@digium.com>
Thu, 5 May 2016 15:45:49 +0000 (10:45 -0500)
This patch modified pjsip_options to retrieve only
permament contacts for aor if the qualify_frequency is > 0
and persisted contacts if the qualify_frequency is > 0.

This patch also fixed a bug in res_sorcery_astdb.
res_sorcery_astdb doesn't save object data retrived from astdb.

ASTERISK-25826

Change-Id: I1831fa46c4578eae5a3e574ee3362fddf08a1f05

contrib/ast-db-manage/config/versions/837aa67461fb_ps_contacts_add_authenticate_qualify.py [new file with mode: 0644]
res/res_pjsip.c
res/res_pjsip/location.c
res/res_pjsip/pjsip_options.c
res/res_sorcery_astdb.c

diff --git a/contrib/ast-db-manage/config/versions/837aa67461fb_ps_contacts_add_authenticate_qualify.py b/contrib/ast-db-manage/config/versions/837aa67461fb_ps_contacts_add_authenticate_qualify.py
new file mode 100644 (file)
index 0000000..76faf39
--- /dev/null
@@ -0,0 +1,32 @@
+"""ps_contacts add authenticate_qualify
+
+Revision ID: 6be31516058d
+Revises: 81b01a191a46
+Create Date: 2016-05-03 14:57:12.538179
+
+"""
+
+# revision identifiers, used by Alembic.
+revision = '6be31516058d'
+down_revision = '81b01a191a46'
+
+from alembic import op
+import sqlalchemy as sa
+from sqlalchemy.dialects.postgresql import ENUM
+
+YESNO_NAME = 'yesno_values'
+YESNO_VALUES = ['yes', 'no']
+
+def upgrade():
+    ############################# Enums ##############################
+
+    # yesno_values have already been created, so use postgres enum object
+    # type to get around "already created" issue - works okay with mysql
+    yesno_values = ENUM(*YESNO_VALUES, name=YESNO_NAME, create_type=False)
+
+    op.add_column('ps_contacts', sa.Column('authenticate_qualify', yesno_values))
+
+
+def downgrade():
+    op.drop_column('ps_contacts', 'authenticate_qualify')
+
index db3395f..a3b2d08 100644 (file)
                                                If <literal>0</literal> no timeout. Time in fractional seconds.
                                        </para></description>
                                </configOption>
+                               <configOption name="authenticate_qualify" default="no">
+                                       <synopsis>Authenticates 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>
                                <configOption name="outbound_proxy">
                                        <synopsis>Outbound proxy used when sending OPTIONS request</synopsis>
                                        <description><para>
index 2779fe3..fd6db6e 100644 (file)
@@ -1116,6 +1116,7 @@ int ast_sip_initialize_sorcery_location(void)
        ast_sorcery_object_field_register(sorcery, "contact", "qualify_frequency", 0, OPT_UINT_T,
                PARSE_IN_RANGE, FLDSET(struct ast_sip_contact, qualify_frequency), 0, 86400);
        ast_sorcery_object_field_register(sorcery, "contact", "qualify_timeout", "3.0", OPT_DOUBLE_T, 0, FLDSET(struct ast_sip_contact, qualify_timeout));
+       ast_sorcery_object_field_register(sorcery, "contact", "authenticate_qualify", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_contact, authenticate_qualify));
        ast_sorcery_object_field_register(sorcery, "contact", "outbound_proxy", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_contact, outbound_proxy));
        ast_sorcery_object_field_register(sorcery, "contact", "user_agent", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_contact, user_agent));
        ast_sorcery_object_field_register(sorcery, "contact", "reg_server", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_contact, reg_server));
index c0d41c3..62640fe 100644 (file)
@@ -1025,17 +1025,11 @@ int ast_sip_initialize_sorcery_qualify(void)
        return 0;
 }
 
-static int qualify_and_schedule_cb(void *obj, void *arg, int flags)
+static void qualify_and_schedule_contact(struct ast_sip_contact *contact)
 {
-       struct ast_sip_contact *contact = obj;
-       struct ast_sip_aor *aor = arg;
        int initial_interval;
        int max_time = ast_sip_get_max_initial_qualify_time();
 
-       contact->qualify_frequency = aor->qualify_frequency;
-       contact->qualify_timeout = aor->qualify_timeout;
-       contact->authenticate_qualify = aor->authenticate_qualify;
-
        /* Delay initial qualification by a random fraction of the specified interval */
        if (max_time && max_time < contact->qualify_frequency) {
                initial_interval = max_time;
@@ -1051,26 +1045,47 @@ static int qualify_and_schedule_cb(void *obj, void *arg, int flags)
        } else {
                update_contact_status(contact, UNKNOWN);
        }
+}
+
+static int qualify_and_schedule_cb_with_aor(void *obj, void *arg, int flags)
+{
+       struct ast_sip_contact *contact = obj;
+       struct ast_sip_aor *aor = arg;
+
+       contact->qualify_frequency = aor->qualify_frequency;
+       contact->qualify_timeout = aor->qualify_timeout;
+       contact->authenticate_qualify = aor->authenticate_qualify;
+
+       qualify_and_schedule_contact(contact);
+
+       return 0;
+}
+
+static int qualify_and_schedule_cb_without_aor(void *obj, void *arg, int flags)
+{
+       qualify_and_schedule_contact((struct ast_sip_contact *) obj);
 
        return 0;
 }
 
 /*!
  * \internal
- * \brief Qualify and schedule an endpoint's contacts
+ * \brief Qualify and schedule an aor's contacts
  *
- * \details For the given endpoint retrieve its list of aors, qualify all
- *         contacts, and schedule for checks if configured.
+ * \details For the given aor check if it has permanent contacts,
+ *         qualify all contacts and schedule for checks if configured.
  */
 static int qualify_and_schedule_all_cb(void *obj, void *arg, int flags)
 {
        struct ast_sip_aor *aor = obj;
        struct ao2_container *contacts;
 
-       contacts = ast_sip_location_retrieve_aor_contacts(aor);
-       if (contacts) {
-               ao2_callback(contacts, OBJ_NODATA, qualify_and_schedule_cb, aor);
-               ao2_ref(contacts, -1);
+       if (aor->permanent_contacts) {
+               contacts = ast_sip_location_retrieve_aor_contacts(aor);
+               if (contacts) {
+                       ao2_callback(contacts, OBJ_NODATA, qualify_and_schedule_cb_with_aor, aor);
+                       ao2_ref(contacts, -1);
+               }
        }
 
        return 0;
@@ -1093,6 +1108,7 @@ static void qualify_and_schedule_all(void)
 {
        struct ast_variable *var = ast_variable_new("qualify_frequency >", "0", "");
        struct ao2_container *aors;
+       struct ao2_container *contacts;
 
        if (!var) {
                return;
@@ -1100,16 +1116,22 @@ static void qualify_and_schedule_all(void)
        aors = ast_sorcery_retrieve_by_fields(ast_sip_get_sorcery(),
                "aor", AST_RETRIEVE_FLAG_MULTIPLE, var);
 
-       ast_variables_destroy(var);
-
        ao2_callback(sched_qualifies, OBJ_NODATA | OBJ_MULTIPLE | OBJ_UNLINK, unschedule_all_cb, NULL);
 
-       if (!aors) {
-               return;
+       if (aors) {
+               ao2_callback(aors, OBJ_NODATA, qualify_and_schedule_all_cb, NULL);
+               ao2_ref(aors, -1);
        }
 
-       ao2_callback(aors, OBJ_NODATA, qualify_and_schedule_all_cb, NULL);
-       ao2_ref(aors, -1);
+       contacts = ast_sorcery_retrieve_by_fields(ast_sip_get_sorcery(),
+               "contact", AST_RETRIEVE_FLAG_MULTIPLE, var);
+       if (contacts) {
+               ao2_callback(contacts, OBJ_NODATA, qualify_and_schedule_cb_without_aor, NULL);
+               ao2_ref(contacts, -1);
+       }
+
+       ast_variables_destroy(var);
+
 }
 
 static int format_contact_status(void *obj, void *arg, int flags)
@@ -1175,7 +1197,7 @@ static void aor_observer_modified(const void *obj)
 
        contacts = ast_sip_location_retrieve_aor_contacts(aor);
        if (contacts) {
-               ao2_callback(contacts, OBJ_NODATA, qualify_and_schedule_cb, aor);
+               ao2_callback(contacts, OBJ_NODATA, qualify_and_schedule_cb_with_aor, aor);
                ao2_ref(contacts, -1);
        }
 }
index b3642d8..dcfaba5 100644 (file)
@@ -97,7 +97,6 @@ static void *sorcery_astdb_retrieve_fields_common(const struct ast_sorcery *sorc
                const char *key = entry->key + strlen(family) + 2;
                RAII_VAR(struct ast_json *, json, NULL, ast_json_unref);
                struct ast_json_error error;
-               RAII_VAR(struct ast_variable *, objset, NULL, ast_variables_destroy);
                RAII_VAR(struct ast_variable *, existing, NULL, ast_variables_destroy);
                void *object = NULL;
 
@@ -113,7 +112,7 @@ static void *sorcery_astdb_retrieve_fields_common(const struct ast_sorcery *sorc
                }
 
                if (!(object = ast_sorcery_alloc(sorcery, type, key)) ||
-                       ast_sorcery_objectset_apply(sorcery, object, objset)) {
+                       ast_sorcery_objectset_apply(sorcery, object, existing)) {
                        ao2_cleanup(object);
                        return NULL;
                }