]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
add mutex around gateway access on per-profile basis and token based access to global...
authorAnthony Minessale <anthm@freeswitch.org>
Thu, 16 Jun 2011 19:32:08 +0000 (14:32 -0500)
committerAnthony Minessale <anthm@freeswitch.org>
Thu, 16 Jun 2011 19:32:14 +0000 (14:32 -0500)
src/mod/endpoints/mod_sofia/mod_sofia.c
src/mod/endpoints/mod_sofia/mod_sofia.h
src/mod/endpoints/mod_sofia/sofia.c
src/mod/endpoints/mod_sofia/sofia_glue.c
src/mod/endpoints/mod_sofia/sofia_presence.c
src/mod/endpoints/mod_sofia/sofia_reg.c

index b06eacb36d9fb1ed3c898501badf016f10266b28..a7e6d99dc2d7dcc321d07e50295b35668b91586d 100644 (file)
@@ -4940,7 +4940,7 @@ static void general_event_handler(switch_event_t *event)
        }
 }
 
-static switch_status_t list_profiles(const char *line, const char *cursor, switch_console_callback_match_t **matches)
+switch_status_t list_profiles(const char *line, const char *cursor, switch_console_callback_match_t **matches)
 {
        sofia_profile_t *profile = NULL;
        switch_hash_index_t *hi;
@@ -4983,9 +4983,11 @@ static switch_status_t list_gateways(const char *line, const char *cursor, switc
                profile = (sofia_profile_t *) val;
                if (sofia_test_pflag(profile, PFLAG_RUNNING)) {
                        sofia_gateway_t *gp;
+                       switch_mutex_lock(profile->gw_mutex);
                        for (gp = profile->gateways; gp; gp = gp->next) {
                                switch_console_push_match(&my_matches, gp->name);
                        }
+                       switch_mutex_unlock(profile->gw_mutex);
                }
        }
        switch_mutex_unlock(mod_sofia_globals.hash_mutex);
index b99616707478c1080d4f3ac85e76f7a4ff6a6fbb..db8a6ff9e3c75e48e442f02a5a0bf4758f71d944 100644 (file)
@@ -592,6 +592,7 @@ struct sofia_profile {
        uint32_t step_timeout;
        uint32_t event_timeout;
        int watchdog_enabled;
+       switch_mutex_t *gw_mutex;
 };
 
 struct private_object {
@@ -1034,6 +1035,7 @@ switch_status_t sofia_set_loglevel(const char *name, int level);
  * \note Valid components are "default" (sofia's default logger), "tport", "iptsec", "nea", "nta", "nth_client", "nth_server", "nua", "soa", "sresolv", "stun"
  * \return the component's loglevel, or -1 if the component isn't valid
  */
+switch_status_t list_profiles(const char *line, const char *cursor, switch_console_callback_match_t **matches);
 int sofia_get_loglevel(const char *name);
 sofia_cid_type_t sofia_cid_name2type(const char *name);
 void sofia_glue_tech_set_local_sdp(private_object_t *tech_pvt, const char *sdp_str, switch_bool_t dup);
index d9a2a3af0d2c4bb0344c0dccce6f87926b7381fc..bf9ff4e7c4c1bed1199b8ca1cff6823ff1d82389 100644 (file)
@@ -3055,6 +3055,9 @@ switch_status_t config_sofia(int reload, char *profile_name)
                                        goto done;
                                }
 
+
+                               switch_mutex_init(&profile->gw_mutex, SWITCH_MUTEX_NESTED, pool);
+
                                profile->trans_timeout = 100;
 
                                profile->auto_rtp_bugs = RTP_BUG_CISCO_SKIP_MARK_BIT_2833;// | RTP_BUG_SONUS_SEND_INVALID_TIMESTAMP_2833;
index 15abe43dc3605bb76cf7c717970b794e774b9372..6fcf2e30cd9c6754334d6979fca11e6c96299c68 100644 (file)
@@ -5518,27 +5518,21 @@ static int recover_callback(void *pArg, int argc, char **argv, char **columnName
 
 int sofia_glue_recover(switch_bool_t flush)
 {
-       switch_hash_index_t *hi;
-       const void *var;
-       void *val;
        sofia_profile_t *profile;
        char *sql;
        int r = 0;
+       switch_console_callback_match_t *matches;
 
-       switch_mutex_lock(mod_sofia_globals.hash_mutex);
-       if (mod_sofia_globals.profile_hash) {
-               for (hi = switch_hash_first(NULL, mod_sofia_globals.profile_hash); hi; hi = switch_hash_next(hi)) {
-                       switch_hash_this(hi, &var, NULL, &val);
 
-                       if ((profile = (sofia_profile_t *) val)) {
+       if (list_profiles(NULL, NULL, &matches) == SWITCH_STATUS_SUCCESS) {
+               switch_console_callback_match_node_t *m;
+               for (m = matches->head; m; m = m->next) {
+                       if ((profile = sofia_glue_find_profile(m->val))) {
+
                                struct recover_helper h = { 0 };
                                h.profile = profile;
                                h.total = 0;
 
-                               if (strcmp((char *) var, profile->name)) {
-                                       continue;
-                               }
-
                                if (flush) {
                                        sql = switch_mprintf("delete from sip_recovery where profile_name='%q'", profile->name);
                                        sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE);
@@ -5559,8 +5553,8 @@ int sofia_glue_recover(switch_bool_t flush)
                                }
                        }
                }
+               switch_console_free_matches(&matches);
        }
-       switch_mutex_unlock(mod_sofia_globals.hash_mutex);
 
        return r;
 }
index a7490f6a8b4ab6a8cca2ee50482d6a8ccbe030dc..2ca69c5f57ff283832a6d2cb6a91fc0027e59157 100644 (file)
@@ -275,33 +275,40 @@ void sofia_presence_cancel(void)
 {
        char *sql;
        sofia_profile_t *profile;
-       switch_hash_index_t *hi;
-       void *val;
        struct presence_helper helper = { 0 };
+       switch_console_callback_match_t *matches;
 
-       if (!mod_sofia_globals.profile_hash)
+       if (!mod_sofia_globals.profile_hash) {
                return;
+       }
+       
+       if (list_profiles(NULL, NULL, &matches) == SWITCH_STATUS_SUCCESS) {
+               switch_console_callback_match_node_t *m;
+               
+               sql = switch_mprintf("select proto,sip_user,sip_host,sub_to_user,sub_to_host,event,contact,call_id,full_from,"
+                                                        "full_via,expires,user_agent,accept,profile_name,network_ip"
+                                                        ",-1,'unavailable','unavailable' from sip_subscriptions where version > -1 and "
+                                                        "expires > -1 and event='presence' and hostname='%q'",
+                                                        mod_sofia_globals.hostname);
+       
 
-       if ((sql = switch_mprintf("select proto,sip_user,sip_host,sub_to_user,sub_to_host,event,contact,call_id,full_from,"
-                                                         "full_via,expires,user_agent,accept,profile_name,network_ip"
-                                                         ",-1,'unavailable','unavailable' from sip_subscriptions where version > -1 and "
-                                                         "expires > -1 and event='presence' and hostname='%q'",
-                                                         mod_sofia_globals.hostname))) {
-               switch_mutex_lock(mod_sofia_globals.hash_mutex);
-               for (hi = switch_hash_first(NULL, mod_sofia_globals.profile_hash); hi; hi = switch_hash_next(hi)) {
-                       switch_hash_this(hi, NULL, NULL, &val);
-                       profile = (sofia_profile_t *) val;
-                       if (profile->pres_type != PRES_TYPE_FULL) {
-                               continue;
-                       }
-                       helper.profile = profile;
-                       helper.event = NULL;
-                       if (sofia_glue_execute_sql_callback(profile, profile->ireg_mutex, sql, sofia_presence_sub_callback, &helper) != SWITCH_TRUE) {
-                               continue;
+               for (m = matches->head; m; m = m->next) {
+                       if ((profile = sofia_glue_find_profile(m->val))) {
+                               if (profile->pres_type == PRES_TYPE_FULL) {
+                                       helper.profile = profile;
+                                       helper.event = NULL;
+                                       if (sofia_glue_execute_sql_callback(profile, profile->ireg_mutex, sql, sofia_presence_sub_callback, &helper) != SWITCH_TRUE) {
+                                               sofia_glue_release_profile(profile);
+                                               continue;
+                                       }
+                               }
+                               sofia_glue_release_profile(profile);
                        }
                }
+
                switch_safe_free(sql);
-               switch_mutex_unlock(mod_sofia_globals.hash_mutex);
+               switch_console_free_matches(&matches);
+
        }
 }
 
@@ -397,23 +404,29 @@ static void actual_sofia_presence_mwi_event_handler(switch_event_t *event)
        if (!profile) {
                if (!host || !(profile = sofia_glue_find_profile(host))) {
                        char *sql;
-                       switch_hash_index_t *hi;
-                       void *val;
-                       const void *vvar;
                        char buf[512] = "";
+                       switch_console_callback_match_t *matches;
 
                        sql = switch_mprintf("select profile_name from sip_registrations where sip_host='%s' or mwi_host='%s'", host, host);
 
-                       switch_mutex_lock(mod_sofia_globals.hash_mutex);
-                       for (hi = switch_hash_first(NULL, mod_sofia_globals.profile_hash); hi; hi = switch_hash_next(hi)) {
-                               switch_hash_this(hi, &vvar, NULL, &val);
-                               profile = (sofia_profile_t *) val;
-                               sofia_glue_execute_sql2str(profile, profile->ireg_mutex, sql, buf, sizeof(buf));
-                               if (!zstr(buf)) {
-                                       break;
+                       if (list_profiles(NULL, NULL, &matches) == SWITCH_STATUS_SUCCESS) {
+                               switch_console_callback_match_node_t *m;
+
+                               for (m = matches->head; m; m = m->next) {
+                                       if ((profile = sofia_glue_find_profile(m->val))) {
+
+                                               sofia_glue_execute_sql2str(profile, profile->ireg_mutex, sql, buf, sizeof(buf));
+                                               if (!zstr(buf)) {
+                                                       break;
+                                               }
+                                               sofia_glue_release_profile(profile);
+                                       }
                                }
+
+                               switch_console_free_matches(&matches);
                        }
-                       switch_mutex_unlock(mod_sofia_globals.hash_mutex);
+
+                       
 
                        if (!(profile = sofia_glue_find_profile(buf))) {
                                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Cannot find profile %s\n", switch_str_nil(host));
@@ -509,9 +522,6 @@ static int sofia_presence_dialog_callback(void *pArg, int argc, char **argv, cha
 static void actual_sofia_presence_event_handler(switch_event_t *event)
 {
        sofia_profile_t *profile = NULL;
-       switch_hash_index_t *hi;
-       const void *var;
-       void *val;
        char *from = switch_event_get_header(event, "from");
        char *proto = switch_event_get_header(event, "proto");
        char *rpid = switch_event_get_header(event, "rpid");
@@ -524,7 +534,7 @@ static void actual_sofia_presence_event_handler(switch_event_t *event)
        char *call_info = switch_event_get_header(event, "presence-call-info");
        char *call_info_state = switch_event_get_header(event, "presence-call-info-state");
        struct resub_helper h = { 0 };
-
+       switch_console_callback_match_t *matches;
 
        if (!mod_sofia_globals.running) {
                return;
@@ -548,7 +558,7 @@ static void actual_sofia_presence_event_handler(switch_event_t *event)
 
        if (event->event_id == SWITCH_EVENT_ROSTER) {
                struct presence_helper helper = { 0 };
-
+               
                if (!mod_sofia_globals.profile_hash)
                        return;
 
@@ -581,28 +591,28 @@ static void actual_sofia_presence_event_handler(switch_event_t *event)
                }
 
                switch_assert(sql != NULL);
-               switch_mutex_lock(mod_sofia_globals.hash_mutex);
-               for (hi = switch_hash_first(NULL, mod_sofia_globals.profile_hash); hi; hi = switch_hash_next(hi)) {
-                       switch_hash_this(hi, &var, NULL, &val);
-                       profile = (sofia_profile_t *) val;
-
-                       if (strcmp((char *) var, profile->name)) {
-                               if (mod_sofia_globals.debug_presence > 0) {
-                                       switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "%s is an alias, skipping\n", (char *) var);
-                               }
-                               continue;
-                       }
-                       if (profile->pres_type != PRES_TYPE_FULL) {
-                               if (mod_sofia_globals.debug_presence > 0) {
-                                       switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "%s is passive, skipping\n", (char *) var);
+               
+               if (list_profiles(NULL, NULL, &matches) == SWITCH_STATUS_SUCCESS) {
+                       switch_console_callback_match_node_t *m;
+
+                       for (m = matches->head; m; m = m->next) {
+                               if ((profile = sofia_glue_find_profile(m->val))) {
+                                       if (profile->pres_type != PRES_TYPE_FULL) {
+                                               if (mod_sofia_globals.debug_presence > 0) {
+                                                       switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "%s is passive, skipping\n", (char *) profile->name);
+                                               }
+                                               sofia_glue_release_profile(profile);
+                                               continue;
+                                       }
+                                       helper.profile = profile;
+                                       helper.event = NULL;
+                                       sofia_glue_execute_sql_callback(profile, profile->ireg_mutex, sql, sofia_presence_sub_callback, &helper);
+                                       sofia_glue_release_profile(profile);
                                }
-                               continue;
                        }
-                       helper.profile = profile;
-                       helper.event = NULL;
-                       sofia_glue_execute_sql_callback(profile, profile->ireg_mutex, sql, sofia_presence_sub_callback, &helper);
+                       switch_console_free_matches(&matches);
                }
-               switch_mutex_unlock(mod_sofia_globals.hash_mutex);
+               
                free(sql);
                return;
        }
@@ -774,163 +784,161 @@ static void actual_sofia_presence_event_handler(switch_event_t *event)
 
 
 
-       if (!mod_sofia_globals.profile_hash)
+       if (!mod_sofia_globals.profile_hash) {
                goto done;
+       }
 
-       switch_mutex_lock(mod_sofia_globals.hash_mutex);
-       for (hi = switch_hash_first(NULL, mod_sofia_globals.profile_hash); hi; hi = switch_hash_next(hi)) {
-               struct dialog_helper dh = { { 0 } };
-
-               switch_hash_this(hi, &var, NULL, &val);
-               profile = (sofia_profile_t *) val;
-
-               if (strcmp((char *) var, profile->name)) {
-                       if (mod_sofia_globals.debug_presence > 0) {
-                               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "%s is an alias, skipping\n", (char *) var);
-                       }
-                       continue;
-               }
+       if (list_profiles(NULL, NULL, &matches) == SWITCH_STATUS_SUCCESS) {
+               switch_console_callback_match_node_t *m;
 
-               if (profile->pres_type != PRES_TYPE_FULL) {
-                       if (mod_sofia_globals.debug_presence > 0) {
-                               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "%s is passive, skipping\n", (char *) var);
-                       }
-                       continue;
-               }
+               for (m = matches->head; m; m = m->next) {
+                       struct dialog_helper dh = { { 0 } };
 
-               if (call_info) {
-                       const char *uuid = switch_event_get_header(event, "unique-id");
+                       if ((profile = sofia_glue_find_profile(m->val))) {
+                               if (profile->pres_type != PRES_TYPE_FULL) {
+                                       if (mod_sofia_globals.debug_presence > 0) {
+                                               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "%s is passive, skipping\n", (char *) profile->name);
+                                       }
+                                       sofia_glue_release_profile(profile);
+                                       continue;
+                               }
 
+                               if (call_info) {
+                                       const char *uuid = switch_event_get_header(event, "unique-id");
 
+                                       
 #if 0
-                       if (mod_sofia_globals.debug_sla > 1) {
-                               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "SLA EVENT:\n");
-                               DUMP_EVENT(event);
-                       }
+                                       if (mod_sofia_globals.debug_sla > 1) {
+                                               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "SLA EVENT:\n");
+                                               DUMP_EVENT(event);
+                                       }
 #endif
 
-                       if (uuid) {
-                               sql = switch_mprintf("update sip_dialogs set call_info='%q',call_info_state='%q' where hostname='%q' and uuid='%q'",
-                                                                        call_info, call_info_state, mod_sofia_globals.hostname, uuid);
-                       } else {
-                               sql = switch_mprintf("update sip_dialogs set call_info='%q', call_info_state='%q' where hostname='%q' and "
-                                                                        "((sip_dialogs.sip_from_user='%q' and sip_dialogs.sip_from_host='%q') or presence_id='%q@%q') and call_info='%q'",
-                                                                        
-                                                                        call_info, call_info_state, mod_sofia_globals.hostname, euser, host, euser, host, call_info);
-
-                       }
-
-                       if (mod_sofia_globals.debug_sla > 1) {
-                               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "STATE SQL %s\n", sql);
-                       }
-                       sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE);
-
-
-
-                       if (mod_sofia_globals.debug_sla > 1) {
-                               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "PROCESS PRESENCE EVENT\n");
-                       }
-
-                       sync_sla(profile, euser, host, SWITCH_TRUE, SWITCH_TRUE);
-               }
-               
-               if (!strcmp(proto, "dp")) {
-                       sql = switch_mprintf("update sip_presence set rpid='%q',status='%q' where sip_user='%q' and sip_host='%q'",
-                                                                rpid, status, euser, host);
-                       sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE);
-               }
-
-               sql = switch_mprintf("select status,rpid,presence_id from sip_dialogs where ((sip_from_user='%q' and sip_from_host='%q') or presence_id='%q@%q')", 
-                                                        euser, host, euser, host);
-               sofia_glue_execute_sql_callback(profile, profile->ireg_mutex, sql, sofia_presence_dialog_callback, &dh);
-               switch_safe_free(sql);
-               
-               if ((sql = switch_mprintf("select distinct sip_subscriptions.proto,sip_subscriptions.sip_user,sip_subscriptions.sip_host,"
-                                                                 "sip_subscriptions.sub_to_user,sip_subscriptions.sub_to_host,sip_subscriptions.event,"
-                                                                 "sip_subscriptions.contact,sip_subscriptions.call_id,sip_subscriptions.full_from,"
-                                                                 "sip_subscriptions.full_via,sip_subscriptions.expires,sip_subscriptions.user_agent,"
-                                                                 "sip_subscriptions.accept,sip_subscriptions.profile_name"
-                                                                 ",'%q','%q','%q',sip_presence.status,sip_presence.rpid,sip_presence.open_closed,'%q','%q',"
-                                                                 "sip_subscriptions.version, '%q' "
-                                                                 "from sip_subscriptions "
-                                                                 "left join sip_presence on "
-                                                                 "(sip_subscriptions.sub_to_user=sip_presence.sip_user and sip_subscriptions.sub_to_host=sip_presence.sip_host and "
-                                                                 "sip_subscriptions.profile_name=sip_presence.profile_name) "
-                                                                 
-                                                                 "where sip_subscriptions.version > -1 and sip_subscriptions.expires > -1 and "
-                                                                 "(event='%q' or event='%q') and sub_to_user='%q' "
-                                                                 "and (sub_to_host='%q' or presence_hosts like '%%%q%%') "
-                                                                 "and (sip_subscriptions.profile_name = '%q' or sip_subscriptions.presence_hosts != sip_subscriptions.sub_to_host) ",
-                                                                 
-                                                                 switch_str_nil(status), switch_str_nil(rpid), host,
-                                                                 dh.status,dh.rpid,dh.presence_id,
-                                                                 event_type, alt_event_type, euser, host, host, profile->name))) {
-                       
-                       struct presence_helper helper = { 0 };                  
-
-                       helper.profile = profile;
-                       helper.event = event;
-                       SWITCH_STANDARD_STREAM(helper.stream);
-                       switch_assert(helper.stream.data);
+                                       if (uuid) {
+                                               sql = switch_mprintf("update sip_dialogs set call_info='%q',call_info_state='%q' where hostname='%q' and uuid='%q'",
+                                                                                        call_info, call_info_state, mod_sofia_globals.hostname, uuid);
+                                       } else {
+                                               sql = switch_mprintf("update sip_dialogs set call_info='%q', call_info_state='%q' where hostname='%q' and "
+                                                                                        "((sip_dialogs.sip_from_user='%q' and sip_dialogs.sip_from_host='%q') or presence_id='%q@%q') and call_info='%q'",
+                                                                                        
+                                                                                        call_info, call_info_state, mod_sofia_globals.hostname, euser, host, euser, host, call_info);
+                                               
+                                       }
+                                       
+                                       if (mod_sofia_globals.debug_sla > 1) {
+                                               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "STATE SQL %s\n", sql);
+                                       }
+                                       sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE);
+                                       
 
-                       if (mod_sofia_globals.debug_presence > 0) {
-                               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "%s START_PRESENCE_SQL (%s)\n",
-                                                                 event->event_id == SWITCH_EVENT_PRESENCE_IN ? "IN" : "OUT", profile->name);
-                       }
 
-                       if (mod_sofia_globals.debug_presence) {
-                               char *buf;
-                               switch_event_serialize(event, &buf, SWITCH_FALSE);
-                               switch_assert(buf);
-                               if (mod_sofia_globals.debug_presence > 1) {
-                                       switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "DUMP PRESENCE SQL:\n%s\nEVENT DUMP:\n%s\n", sql, buf);
-                               } else {
-                                       switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "EVENT DUMP:\n%s\n", buf);
+                                       if (mod_sofia_globals.debug_sla > 1) {
+                                               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "PROCESS PRESENCE EVENT\n");
+                                       }
+                                       
+                                       sync_sla(profile, euser, host, SWITCH_TRUE, SWITCH_TRUE);
                                }
-                               free(buf);
-                       }
-
-                       sofia_glue_execute_sql_callback(profile, NULL, sql, sofia_presence_sub_callback, &helper);
-                       switch_safe_free(sql);
-                       
-                       sql = switch_mprintf("update sip_subscriptions set version=version+1 where event='dialog' and sub_to_user='%q' "
-                                                                "and (sub_to_host='%q' or presence_hosts like '%%%q%%') "
-                                                                "and (profile_name = '%q' or presence_hosts != sub_to_host)",
-                                                                euser, host, host, profile->name);
-
-                       sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE);
-
-
-                       if (mod_sofia_globals.debug_presence > 0) {
-                               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "%s END_PRESENCE_SQL (%s)\n",
-                                                                 event->event_id == SWITCH_EVENT_PRESENCE_IN ? "IN" : "OUT", profile->name);
-                       }
+                               
+                               if (!strcmp(proto, "dp")) {
+                                       sql = switch_mprintf("update sip_presence set rpid='%q',status='%q' where sip_user='%q' and sip_host='%q'",
+                                                                                rpid, status, euser, host);
+                                       sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE);
+                               }
+                               
+                               sql = switch_mprintf("select status,rpid,presence_id from sip_dialogs where ((sip_from_user='%q' and sip_from_host='%q') or presence_id='%q@%q')", 
+                                                                        euser, host, euser, host);
+                               sofia_glue_execute_sql_callback(profile, profile->ireg_mutex, sql, sofia_presence_dialog_callback, &dh);
+                               switch_safe_free(sql);
+                               
+                               if ((sql = switch_mprintf("select distinct sip_subscriptions.proto,sip_subscriptions.sip_user,sip_subscriptions.sip_host,"
+                                                                                 "sip_subscriptions.sub_to_user,sip_subscriptions.sub_to_host,sip_subscriptions.event,"
+                                                                                 "sip_subscriptions.contact,sip_subscriptions.call_id,sip_subscriptions.full_from,"
+                                                                                 "sip_subscriptions.full_via,sip_subscriptions.expires,sip_subscriptions.user_agent,"
+                                                                                 "sip_subscriptions.accept,sip_subscriptions.profile_name"
+                                                                                 ",'%q','%q','%q',sip_presence.status,sip_presence.rpid,sip_presence.open_closed,'%q','%q',"
+                                                                                 "sip_subscriptions.version, '%q' "
+                                                                                 "from sip_subscriptions "
+                                                                                 "left join sip_presence on "
+                                                                                 "(sip_subscriptions.sub_to_user=sip_presence.sip_user and sip_subscriptions.sub_to_host=sip_presence.sip_host and "
+                                                                                 "sip_subscriptions.profile_name=sip_presence.profile_name) "
+                                                                                 
+                                                                                 "where sip_subscriptions.version > -1 and sip_subscriptions.expires > -1 and "
+                                                                                 "(event='%q' or event='%q') and sub_to_user='%q' "
+                                                                                 "and (sub_to_host='%q' or presence_hosts like '%%%q%%') "
+                                                                                 "and (sip_subscriptions.profile_name = '%q' or sip_subscriptions.presence_hosts != sip_subscriptions.sub_to_host) ",
+                                                                                 
+                                                                                 switch_str_nil(status), switch_str_nil(rpid), host,
+                                                                                 dh.status,dh.rpid,dh.presence_id,
+                                                                                 event_type, alt_event_type, euser, host, host, profile->name))) {
+                                       
+                                       struct presence_helper helper = { 0 };                  
 
-                       if (!zstr((char *) helper.stream.data)) {
-                               char *this_sql = (char *) helper.stream.data;
-                               char *next = NULL;
-                               char *last = NULL;
+                                       helper.profile = profile;
+                                       helper.event = event;
+                                       SWITCH_STANDARD_STREAM(helper.stream);
+                                       switch_assert(helper.stream.data);
+                                       
+                                       if (mod_sofia_globals.debug_presence > 0) {
+                                               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "%s START_PRESENCE_SQL (%s)\n",
+                                                                                 event->event_id == SWITCH_EVENT_PRESENCE_IN ? "IN" : "OUT", profile->name);
+                                       }
 
-                               do {
-                                       if ((next = strchr(this_sql, ';'))) {
-                                               *next++ = '\0';
-                                               while (*next == '\n' || *next == ' ' || *next == '\r') {
-                                                       *next++ = '\0';
+                                       if (mod_sofia_globals.debug_presence) {
+                                               char *buf;
+                                               switch_event_serialize(event, &buf, SWITCH_FALSE);
+                                               switch_assert(buf);
+                                               if (mod_sofia_globals.debug_presence > 1) {
+                                                       switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "DUMP PRESENCE SQL:\n%s\nEVENT DUMP:\n%s\n", sql, buf);
+                                               } else {
+                                                       switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "EVENT DUMP:\n%s\n", buf);
                                                }
+                                               free(buf);
+                                       }
+
+                                       sofia_glue_execute_sql_callback(profile, NULL, sql, sofia_presence_sub_callback, &helper);
+                                       switch_safe_free(sql);
+                                       
+                                       sql = switch_mprintf("update sip_subscriptions set version=version+1 where event='dialog' and sub_to_user='%q' "
+                                                                                "and (sub_to_host='%q' or presence_hosts like '%%%q%%') "
+                                                                                "and (profile_name = '%q' or presence_hosts != sub_to_host)",
+                                                                                euser, host, host, profile->name);
+                                       
+                                       sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE);
+                                       
+                                       
+                                       if (mod_sofia_globals.debug_presence > 0) {
+                                               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "%s END_PRESENCE_SQL (%s)\n",
+                                                                                 event->event_id == SWITCH_EVENT_PRESENCE_IN ? "IN" : "OUT", profile->name);
                                        }
 
-                                       if (!zstr(this_sql) && (!last || strcmp(last, this_sql))) {
-                                               sofia_glue_execute_sql(profile, &this_sql, SWITCH_FALSE);
-                                               last = this_sql;
+                                       if (!zstr((char *) helper.stream.data)) {
+                                               char *this_sql = (char *) helper.stream.data;
+                                               char *next = NULL;
+                                               char *last = NULL;
+                                               
+                                               do {
+                                                       if ((next = strchr(this_sql, ';'))) {
+                                                               *next++ = '\0';
+                                                               while (*next == '\n' || *next == ' ' || *next == '\r') {
+                                                                       *next++ = '\0';
+                                                               }
+                                                       }
+                                                       
+                                                       if (!zstr(this_sql) && (!last || strcmp(last, this_sql))) {
+                                                               sofia_glue_execute_sql(profile, &this_sql, SWITCH_FALSE);
+                                                               last = this_sql;
+                                                       }
+                                                       this_sql = next;
+                                               } while (this_sql);
                                        }
-                                       this_sql = next;
-                               } while (this_sql);
+                                       switch_safe_free(helper.stream.data);
+                                       helper.stream.data = NULL;
+                               }
+                               sofia_glue_release_profile(profile);
                        }
-                       switch_safe_free(helper.stream.data);
-                       helper.stream.data = NULL;
                }
+               switch_console_free_matches(&matches);
        }
-       switch_mutex_unlock(mod_sofia_globals.hash_mutex);
 
   done:
        switch_safe_free(sql);
index df02436ecd7de509eea924f98657dd12b9c23a66..730576f9499b32970f0fb66e8ca4dc1b91e5970c 100644 (file)
@@ -134,7 +134,7 @@ void sofia_sub_check_gateway(sofia_profile_t *profile, time_t now)
         */
        sofia_gateway_t *gateway_ptr;
 
-       switch_mutex_lock(mod_sofia_globals.hash_mutex);
+       switch_mutex_lock(profile->gw_mutex);
        for (gateway_ptr = profile->gateways; gateway_ptr; gateway_ptr = gateway_ptr->next) {
                sofia_gateway_subscription_t *gw_sub_ptr;
 
@@ -235,7 +235,7 @@ void sofia_sub_check_gateway(sofia_profile_t *profile, time_t now)
                        switch_safe_free(user_via);
                }
        }
-       switch_mutex_unlock(mod_sofia_globals.hash_mutex);
+       switch_mutex_unlock(profile->gw_mutex);
 }
 
 void sofia_reg_check_gateway(sofia_profile_t *profile, time_t now)
@@ -244,7 +244,7 @@ void sofia_reg_check_gateway(sofia_profile_t *profile, time_t now)
        switch_event_t *event;
        char *pkey;
 
-       switch_mutex_lock(mod_sofia_globals.hash_mutex);
+       switch_mutex_lock(profile->gw_mutex);
        for (gateway_ptr = profile->gateways; gateway_ptr; gateway_ptr = gateway_ptr->next) {
                if (gateway_ptr->deleted && gateway_ptr->state == REG_STATE_NOREG) {
                        if (last) {
@@ -447,7 +447,7 @@ void sofia_reg_check_gateway(sofia_profile_t *profile, time_t now)
                        sofia_reg_fire_custom_gateway_state_event(gateway_ptr, 0, NULL);
                }
        }
-       switch_mutex_unlock(mod_sofia_globals.hash_mutex);
+       switch_mutex_unlock(profile->gw_mutex);
 }
 
 
@@ -2735,11 +2735,14 @@ switch_status_t sofia_reg_add_gateway(sofia_profile_t *profile, const char *key,
        switch_status_t status = SWITCH_STATUS_FALSE;
        char *pkey = switch_mprintf("%s::%s", profile->name, key);
 
-       switch_mutex_lock(mod_sofia_globals.hash_mutex);
+       switch_mutex_lock(profile->gw_mutex);
 
        gateway->next = profile->gateways;
        profile->gateways = gateway;
        
+       switch_mutex_unlock(profile->gw_mutex);
+
+       switch_mutex_lock(mod_sofia_globals.hash_mutex);
        if (!switch_core_hash_find(mod_sofia_globals.gateway_hash, key)) {
                status = switch_core_hash_insert(mod_sofia_globals.gateway_hash, key, gateway);
        }