diff --git a/src/mod/endpoints/mod_sofia/mod_sofia.c b/src/mod/endpoints/mod_sofia/mod_sofia.c index 770ae67ce5..6c9f2a4310 100644 --- a/src/mod/endpoints/mod_sofia/mod_sofia.c +++ b/src/mod/endpoints/mod_sofia/mod_sofia.c @@ -2042,7 +2042,7 @@ static switch_status_t cmd_status(char **argv, int argc, switch_stream_handle_t profile->name); } - sofia_glue_execute_sql_callback(profile, SWITCH_FALSE, profile->ireg_mutex, sql, show_reg_callback, &cb); + sofia_glue_execute_sql_callback(profile, profile->ireg_mutex, sql, show_reg_callback, &cb); switch_safe_free(sql); stream->write_function(stream, "%s\n", line); @@ -2263,7 +2263,7 @@ static switch_status_t cmd_xml_status(char **argv, int argc, switch_stream_handl profile->name); } - sofia_glue_execute_sql_callback(profile, SWITCH_FALSE, profile->ireg_mutex, sql, show_reg_callback_xml, &cb); + sofia_glue_execute_sql_callback(profile, profile->ireg_mutex, sql, show_reg_callback_xml, &cb); switch_safe_free(sql); stream->write_function(stream, " \n"); @@ -2653,7 +2653,7 @@ SWITCH_STANDARD_API(sofia_contact_function) } switch_assert(sql); - sofia_glue_execute_sql_callback(profile, SWITCH_FALSE, profile->ireg_mutex, sql, contact_callback, &cb); + sofia_glue_execute_sql_callback(profile, profile->ireg_mutex, sql, contact_callback, &cb); switch_safe_free(sql); reply = (char *) mystream.data; if (!zstr(reply) && end_of(reply) == ',') { @@ -3365,7 +3365,7 @@ static void general_event_handler(switch_event_t *event) switch_mutex_lock(profile->ireg_mutex); - sofia_glue_execute_sql_callback(profile, SWITCH_TRUE, NULL, sql, notify_callback, profile); + sofia_glue_execute_sql_callback(profile, NULL, sql, notify_callback, profile); switch_mutex_unlock(profile->ireg_mutex); sofia_glue_release_profile(profile); diff --git a/src/mod/endpoints/mod_sofia/mod_sofia.h b/src/mod/endpoints/mod_sofia/mod_sofia.h index 03132cceb6..e6c5e958f8 100644 --- a/src/mod/endpoints/mod_sofia/mod_sofia.h +++ b/src/mod/endpoints/mod_sofia/mod_sofia.h @@ -475,7 +475,8 @@ struct sofia_profile { sofia_gateway_t *gateways; su_home_t *home; switch_hash_t *chat_hash; - switch_core_db_t *master_db; + switch_hash_t *db_hash; + //switch_core_db_t *master_db; switch_thread_rwlock_t *rwlock; switch_mutex_t *flag_mutex; uint32_t inuse; @@ -670,6 +671,11 @@ typedef struct { char *route_uri; } sofia_destination_t; +typedef struct { + switch_core_db_t *db; + time_t last_used; +} sofia_cache_db_handle_t; + #define sofia_test_pflag(obj, flag) ((obj)->pflags[flag] ? 1 : 0) #define sofia_set_pflag(obj, flag) (obj)->pflags[flag] = 1 #define sofia_set_pflag_locked(obj, flag) assert(obj->flag_mutex != NULL);\ @@ -747,7 +753,7 @@ switch_status_t config_sofia(int reload, char *profile_name); void sofia_reg_auth_challenge(nua_t *nua, sofia_profile_t *profile, nua_handle_t *nh, sofia_regtype_t regtype, const char *realm, int stale); auth_res_t sofia_reg_parse_auth(sofia_profile_t *profile, sip_authorization_t const *authorization, sip_t const *sip, const char *regstr, char *np, size_t nplen, char *ip, switch_event_t **v_event, - long exptime, sofia_regtype_t regtype, const char *to_user, switch_event_t **auth_params); + long exptime, sofia_regtype_t regtype, const char *to_user, switch_event_t **auth_params, long *reg_count); void sofia_reg_handle_sip_r_challenge(int status, @@ -773,7 +779,7 @@ void sofia_presence_handle_sip_i_subscribe(int status, nua_t *nua, sofia_profile_t *profile, nua_handle_t *nh, sofia_private_t *sofia_private, sip_t const *sip, tagi_t tags[]); void sofia_glue_execute_sql(sofia_profile_t *profile, char **sqlp, switch_bool_t sql_already_dynamic); -void sofia_glue_actually_execute_sql(sofia_profile_t *profile, switch_bool_t master, char *sql, switch_mutex_t *mutex); +void sofia_glue_actually_execute_sql(sofia_profile_t *profile, char *sql, switch_mutex_t *mutex); void sofia_reg_check_expire(sofia_profile_t *profile, time_t now, int reboot); void sofia_reg_check_gateway(sofia_profile_t *profile, time_t now); void sofia_sub_check_gateway(sofia_profile_t *profile, time_t now); @@ -795,7 +801,6 @@ void sofia_glue_sql_close(sofia_profile_t *profile); int sofia_glue_init_sql(sofia_profile_t *profile); char *sofia_overcome_sip_uri_weakness(switch_core_session_t *session, const char *uri, const sofia_transport_t transport, switch_bool_t uri_only, const char *params); switch_bool_t sofia_glue_execute_sql_callback(sofia_profile_t *profile, - switch_bool_t master, switch_mutex_t *mutex, char *sql, switch_core_db_callback_func_t callback, @@ -925,3 +930,4 @@ void sofia_glue_set_extra_headers(switch_channel_t *channel, sip_t const *sip, c void sofia_info_send_sipfrag(switch_core_session_t *aleg, switch_core_session_t *bleg); void sofia_update_callee_id(switch_core_session_t *session, sofia_profile_t *profile, sip_t const *sip, switch_bool_t send); void sofia_send_callee_id(switch_core_session_t *session, const char *name, const char *number); +int sofia_sla_supported(sip_t const *sip); diff --git a/src/mod/endpoints/mod_sofia/sofia.c b/src/mod/endpoints/mod_sofia/sofia.c index 1645880e84..ba08175299 100644 --- a/src/mod/endpoints/mod_sofia/sofia.c +++ b/src/mod/endpoints/mod_sofia/sofia.c @@ -591,7 +591,7 @@ void sofia_event_callback(nua_event_t event, sofia_glue_get_addr(nua_current_request(nua), network_ip, sizeof(network_ip), NULL); auth_res = sofia_reg_parse_auth(profile, authorization, sip, (char *) sip->sip_request->rq_method_name, tech_pvt->key, strlen(tech_pvt->key), network_ip, NULL, 0, - REG_INVITE, NULL, NULL); + REG_INVITE, NULL, NULL, NULL); } if (auth_res != AUTH_OK) { @@ -943,7 +943,7 @@ void *SWITCH_THREAD_FUNC sofia_profile_worker_thread_run(switch_thread_t *thread sprintf(sqlbuf + len, "commit;\n"); //printf("TRANS:\n%s\n", sqlbuf); - sofia_glue_actually_execute_sql(profile, SWITCH_TRUE, sqlbuf, NULL); + sofia_glue_actually_execute_sql(profile, sqlbuf, NULL); switch_mutex_unlock(profile->ireg_mutex); loop_count = 0; } @@ -951,7 +951,7 @@ void *SWITCH_THREAD_FUNC sofia_profile_worker_thread_run(switch_thread_t *thread if (qsize) { switch_mutex_lock(profile->ireg_mutex); while (switch_queue_trypop(profile->sql_queue, &pop) == SWITCH_STATUS_SUCCESS && pop) { - sofia_glue_actually_execute_sql(profile, SWITCH_TRUE, (char *) pop, NULL); + sofia_glue_actually_execute_sql(profile, (char *) pop, NULL); free(pop); } switch_mutex_unlock(profile->ireg_mutex); @@ -978,7 +978,7 @@ void *SWITCH_THREAD_FUNC sofia_profile_worker_thread_run(switch_thread_t *thread switch_mutex_lock(profile->ireg_mutex); while (switch_queue_trypop(profile->sql_queue, &pop) == SWITCH_STATUS_SUCCESS && pop) { - sofia_glue_actually_execute_sql(profile, SWITCH_TRUE, (char *) pop, NULL); + sofia_glue_actually_execute_sql(profile, (char *) pop, NULL); free(pop); } switch_mutex_unlock(profile->ireg_mutex); @@ -1098,6 +1098,7 @@ void *SWITCH_THREAD_FUNC sofia_profile_thread_run(switch_thread_t *thread, void NUTAG_APPL_METHOD("NOTIFY"), NUTAG_APPL_METHOD("INFO"), NUTAG_APPL_METHOD("ACK"), + NUTAG_APPL_METHOD("SUBSCRIBE"), #ifdef MANUAL_BYE NUTAG_APPL_METHOD("BYE"), #endif @@ -1267,6 +1268,7 @@ void *SWITCH_THREAD_FUNC sofia_profile_thread_run(switch_thread_t *thread, void sofia_glue_del_profile(profile); switch_core_hash_destroy(&profile->chat_hash); + switch_core_hash_destroy(&profile->db_hash); switch_thread_rwlock_unlock(profile->rwlock); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Write unlock %s\n", profile->name); @@ -1864,6 +1866,7 @@ switch_status_t reconfig_sofia(sofia_profile_t *profile) if (switch_true(val)) { sofia_set_pflag(profile, PFLAG_MESSAGE_QUERY_ON_REGISTER); } else if (!strcasecmp(val, "first-only")) { + sofia_clear_pflag(profile, PFLAG_MESSAGE_QUERY_ON_REGISTER); sofia_set_pflag(profile, PFLAG_MESSAGE_QUERY_ON_FIRST_REGISTER); } else { sofia_clear_pflag(profile, PFLAG_MESSAGE_QUERY_ON_REGISTER); @@ -2387,6 +2390,7 @@ switch_status_t config_sofia(int reload, char *profile_name) profile->dbname = switch_core_strdup(profile->pool, url); switch_core_hash_init(&profile->chat_hash, profile->pool); + switch_core_hash_init(&profile->db_hash, profile->pool); switch_thread_rwlock_create(&profile->rwlock, profile->pool); switch_mutex_init(&profile->flag_mutex, SWITCH_MUTEX_NESTED, profile->pool); profile->dtmf_duration = 100; @@ -2397,10 +2401,11 @@ switch_status_t config_sofia(int reload, char *profile_name) sofia_set_pflag(profile, PFLAG_DISABLE_100REL); profile->auto_restart = 1; sofia_set_pflag(profile, PFLAG_AUTOFIX_TIMING); - sofia_set_pflag(profile, PFLAG_MESSAGE_QUERY_ON_REGISTER); sofia_set_pflag(profile, PFLAG_RTP_AUTOFLUSH_DURING_BRIDGE); profile->contact_user = SOFIA_DEFAULT_CONTACT_USER; sofia_set_pflag(profile, PFLAG_PASS_CALLEE_ID); + sofia_set_pflag(profile, PFLAG_MESSAGE_QUERY_ON_FIRST_REGISTER); + sofia_set_pflag(profile, PFLAG_SQL_IN_TRANS); for (param = switch_xml_child(settings, "param"); param; param = param->next) { char *var = (char *) switch_xml_attr_soft(param, "name"); @@ -2479,6 +2484,7 @@ switch_status_t config_sofia(int reload, char *profile_name) if (switch_true(val)) { sofia_set_pflag(profile, PFLAG_MESSAGE_QUERY_ON_REGISTER); } else if (!strcasecmp(val, "first-only")) { + sofia_clear_pflag(profile, PFLAG_MESSAGE_QUERY_ON_REGISTER); sofia_set_pflag(profile, PFLAG_MESSAGE_QUERY_ON_FIRST_REGISTER); } else { sofia_clear_pflag(profile, PFLAG_MESSAGE_QUERY_ON_REGISTER); @@ -2653,6 +2659,7 @@ switch_status_t config_sofia(int reload, char *profile_name) } else if (!strcasecmp(var, "manage-shared-appearance")) { if (switch_true(val)) { sofia_set_pflag(profile, PFLAG_MANAGE_SHARED_APPEARANCE); + profile->pres_type = PRES_TYPE_FULL; profile->sla_contact = switch_core_sprintf(profile->pool, "sla-agent"); } } else if (!strcasecmp(var, "disable-srv")) { diff --git a/src/mod/endpoints/mod_sofia/sofia_glue.c b/src/mod/endpoints/mod_sofia/sofia_glue.c index 7e64e91b53..d34272cdb3 100644 --- a/src/mod/endpoints/mod_sofia/sofia_glue.c +++ b/src/mod/endpoints/mod_sofia/sofia_glue.c @@ -3609,6 +3609,7 @@ void sofia_glue_del_profile(sofia_profile_t *profile) int sofia_glue_init_sql(sofia_profile_t *profile) { char *test_sql = NULL; + switch_core_db_t *db = NULL; char reg_sql[] = "CREATE TABLE sip_registrations (\n" @@ -3780,7 +3781,8 @@ int sofia_glue_init_sql(sofia_profile_t *profile) test_sql = switch_mprintf("delete from sip_registrations where (contact like '%%TCP%%' " "or status like '%%TCP%%' or status like '%%TLS%%') and hostname='%q' " - "and network_ip!='-1' and network_port!='-1' and sip_username != '-1' and mwi_user != '-1' and mwi_host != '-1'", + "and network_ip like '%%' and network_port like '%%' and sip_username " + "like '%%' and mwi_user like '%%' and mwi_host like '%%'", mod_sofia_globals.hostname); if (switch_odbc_handle_exec(profile->master_odbc, test_sql, NULL) != SWITCH_ODBC_SUCCESS) { @@ -3790,7 +3792,8 @@ int sofia_glue_init_sql(sofia_profile_t *profile) free(test_sql); - test_sql = switch_mprintf("delete from sip_subscriptions where hostname='%q' and network_ip!='-1' and network_port!='-1'", mod_sofia_globals.hostname); + test_sql = switch_mprintf("delete from sip_subscriptions where hostname='%q' and network_ip like '%%' and network_port like '%%'", + mod_sofia_globals.hostname); if (switch_odbc_handle_exec(profile->master_odbc, test_sql, NULL) != SWITCH_ODBC_SUCCESS) { switch_odbc_handle_exec(profile->master_odbc, "DROP TABLE sip_subscriptions", NULL); @@ -3813,7 +3816,7 @@ int sofia_glue_init_sql(sofia_profile_t *profile) } free(test_sql); - test_sql = switch_mprintf("delete from sip_authentication where hostname='%q' and last_nc >= 0", mod_sofia_globals.hostname); + test_sql = switch_mprintf("delete from sip_authentication where hostname='%q' or last_nc >= 0", mod_sofia_globals.hostname); if (switch_odbc_handle_exec(profile->master_odbc, test_sql, NULL) != SWITCH_ODBC_SUCCESS) { switch_odbc_handle_exec(profile->master_odbc, "DROP TABLE sip_authentication", NULL); @@ -3821,7 +3824,7 @@ int sofia_glue_init_sql(sofia_profile_t *profile) } free(test_sql); - test_sql = switch_mprintf("delete from sip_shared_appearance_subscriptions where contact_str='' or hostname='%q' and network_ip!='-1'", + test_sql = switch_mprintf("delete from sip_shared_appearance_subscriptions where contact_str='' or hostname='%q' and network_ip like '%%'", mod_sofia_globals.hostname); if (switch_odbc_handle_exec(profile->master_odbc, test_sql, NULL) != SWITCH_ODBC_SUCCESS) { switch_odbc_handle_exec(profile->master_odbc, "DROP TABLE sip_shared_appearance_subscriptions", NULL); @@ -3830,7 +3833,7 @@ int sofia_glue_init_sql(sofia_profile_t *profile) free(test_sql); - test_sql = switch_mprintf("delete from sip_shared_appearance_dialogs where contact_str='' or hostname='%q' and network_ip!='-1'", + test_sql = switch_mprintf("delete from sip_shared_appearance_dialogs where contact_str='' or hostname='%q' and network_ip like '%%'", mod_sofia_globals.hostname); if (switch_odbc_handle_exec(profile->master_odbc, test_sql, NULL) != SWITCH_ODBC_SUCCESS) { switch_odbc_handle_exec(profile->master_odbc, "DROP TABLE sip_shared_appearance_dialogs", NULL); @@ -3847,111 +3850,119 @@ int sofia_glue_init_sql(sofia_profile_t *profile) } else if (profile->odbc_dsn) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "ODBC IS NOT AVAILABLE!\n"); } else { - if (!(profile->master_db = switch_core_db_open_file(profile->dbname))) { + if (!(db = switch_core_db_open_file(profile->dbname))) { return 0; } test_sql = switch_mprintf("delete from sip_registrations where (contact like '%%TCP%%' " "or status like '%%TCP%%' or status like '%%TLS%%') and hostname='%q' " - "and network_ip!='-1' and network_port!='-1' and sip_username != '-1' and mwi_user != '-1' and mwi_host != '-1'", + "and network_ip like '%%' and network_port like '%%' and sip_username " + "like '%%' and mwi_user like '%%' and mwi_host like '%%'", mod_sofia_globals.hostname); - switch_core_db_test_reactive(profile->master_db, test_sql, "DROP TABLE sip_registrations", reg_sql); + switch_core_db_test_reactive(db, test_sql, "DROP TABLE sip_registrations", reg_sql); free(test_sql); - test_sql = switch_mprintf("delete from sip_subscriptions where hostname='%q' and network_ip!='-1' and network_port!='-1'", mod_sofia_globals.hostname); - switch_core_db_test_reactive(profile->master_db, test_sql, "DROP TABLE sip_subscriptions", sub_sql); + test_sql = switch_mprintf("delete from sip_subscriptions where hostname='%q' and network_ip like '%%' or network_port like '%%'", + mod_sofia_globals.hostname); + switch_core_db_test_reactive(db, test_sql, "DROP TABLE sip_subscriptions", sub_sql); free(test_sql); test_sql = switch_mprintf("delete from sip_dialogs where hostname='%q' and contact like '%%'", mod_sofia_globals.hostname); - switch_core_db_test_reactive(profile->master_db, test_sql, "DROP TABLE sip_dialogs", dialog_sql); + switch_core_db_test_reactive(db, test_sql, "DROP TABLE sip_dialogs", dialog_sql); free(test_sql); test_sql = switch_mprintf("delete from sip_presence where hostname='%q'", mod_sofia_globals.hostname); - switch_core_db_test_reactive(profile->master_db, test_sql, "DROP TABLE sip_presence", pres_sql); + switch_core_db_test_reactive(db, test_sql, "DROP TABLE sip_presence", pres_sql); free(test_sql); - test_sql = switch_mprintf("delete from sip_authentication where hostname='%q' and last_nc >= 0", mod_sofia_globals.hostname); - switch_core_db_test_reactive(profile->master_db, test_sql, "DROP TABLE sip_authentication", auth_sql); + test_sql = switch_mprintf("delete from sip_authentication where hostname='%q' or last_nc >= 0", mod_sofia_globals.hostname); + switch_core_db_test_reactive(db, test_sql, "DROP TABLE sip_authentication", auth_sql); free(test_sql); - test_sql = switch_mprintf("delete from sip_shared_appearance_subscriptions where contact_str = '' or hostname='%q' and network_ip!='-1'", + test_sql = switch_mprintf("delete from sip_shared_appearance_subscriptions where contact_str = '' or hostname='%q' and network_ip like '%%'", mod_sofia_globals.hostname); - switch_core_db_test_reactive(profile->master_db, test_sql, "DROP TABLE sip_shared_appearance_subscriptions", shared_appearance_sql); + switch_core_db_test_reactive(db, test_sql, "DROP TABLE sip_shared_appearance_subscriptions", shared_appearance_sql); free(test_sql); test_sql = switch_mprintf("delete from sip_shared_appearance_dialogs where contact_str = '' or hostname='%q'", mod_sofia_globals.hostname); - switch_core_db_test_reactive(profile->master_db, test_sql, "DROP TABLE sip_shared_appearance_dialogs", shared_appearance_dialogs_sql); + switch_core_db_test_reactive(db, test_sql, "DROP TABLE sip_shared_appearance_dialogs", shared_appearance_dialogs_sql); free(test_sql); - switch_core_db_exec(profile->master_db, "create index if not exists ssa_hostname on sip_shared_appearance_subscriptions (hostname)", + switch_core_db_exec(db, "create index if not exists ssa_hostname on sip_shared_appearance_subscriptions (hostname)", NULL, NULL, NULL); - switch_core_db_exec(profile->master_db, "create index if not exists ssa_subscriber on sip_shared_appearance_subscriptions (subscriber)", + switch_core_db_exec(db, "create index if not exists ssa_subscriber on sip_shared_appearance_subscriptions (subscriber)", NULL, NULL, NULL); - switch_core_db_exec(profile->master_db, "create index if not exists ssa_profile_name on sip_shared_appearance_subscriptions (profile_name)", + switch_core_db_exec(db, "create index if not exists ssa_profile_name on sip_shared_appearance_subscriptions (profile_name)", NULL, NULL, NULL); - switch_core_db_exec(profile->master_db, "create index if not exists ssa_aor on sip_shared_appearance_subscriptions (aor)", NULL, NULL, NULL); + switch_core_db_exec(db, "create index if not exists ssa_aor on sip_shared_appearance_subscriptions (aor)", NULL, NULL, NULL); - switch_core_db_exec(profile->master_db, "create index if not exists ssd_profile_name on sip_shared_appearance_dialogs (profile_name)", + switch_core_db_exec(db, "create index if not exists ssd_profile_name on sip_shared_appearance_dialogs (profile_name)", NULL, NULL, NULL); - switch_core_db_exec(profile->master_db, "create index if not exists ssd_hostname on sip_shared_appearance_dialogs (hostname)", + switch_core_db_exec(db, "create index if not exists ssd_hostname on sip_shared_appearance_dialogs (hostname)", NULL, NULL, NULL); - switch_core_db_exec(profile->master_db, "create index if not exists ssd_hostname on sip_shared_appearance_dialogs (network_ip)", + switch_core_db_exec(db, "create index if not exists ssd_hostname on sip_shared_appearance_dialogs (network_ip)", NULL, NULL, NULL); - switch_core_db_exec(profile->master_db, "create index if not exists ssd_contact_str on sip_shared_appearance_dialogs (contact_str)", + switch_core_db_exec(db, "create index if not exists ssd_contact_str on sip_shared_appearance_dialogs (contact_str)", NULL, NULL, NULL); - switch_core_db_exec(profile->master_db, "create index if not exists ssd_call_id on sip_shared_appearance_dialogs (call_id)", + switch_core_db_exec(db, "create index if not exists ssd_call_id on sip_shared_appearance_dialogs (call_id)", NULL, NULL, NULL); - switch_core_db_exec(profile->master_db, "create index if not exists ssd_expires on sip_shared_appearance_dialogs (expires)", + switch_core_db_exec(db, "create index if not exists ssd_expires on sip_shared_appearance_dialogs (expires)", NULL, NULL, NULL); - switch_core_db_exec(profile->master_db, "create index if not exists sr_call_id on sip_registrations (call_id)", NULL, NULL, NULL); - switch_core_db_exec(profile->master_db, "create index if not exists sr_sip_user on sip_registrations (sip_user)", NULL, NULL, NULL); - switch_core_db_exec(profile->master_db, "create index if not exists sr_sip_host on sip_registrations (sip_host)", NULL, NULL, NULL); - switch_core_db_exec(profile->master_db, "create index if not exists sr_profile_name on sip_registrations (profile_name)", NULL, NULL, NULL); - switch_core_db_exec(profile->master_db, "create index if not exists sr_presence_hosts on sip_registrations (presence_hosts)", NULL, NULL, NULL); - switch_core_db_exec(profile->master_db, "create index if not exists sr_contact on sip_registrations (contact)", NULL, NULL, NULL); - switch_core_db_exec(profile->master_db, "create index if not exists sr_expires on sip_registrations (expires)", NULL, NULL, NULL); - switch_core_db_exec(profile->master_db, "create index if not exists sr_hostname on sip_registrations (hostname)", NULL, NULL, NULL); - switch_core_db_exec(profile->master_db, "create index if not exists sr_status on sip_registrations (status)", NULL, NULL, NULL); - switch_core_db_exec(profile->master_db, "create index if not exists sr_network_ip on sip_registrations (network_ip)", NULL, NULL, NULL); - switch_core_db_exec(profile->master_db, "create index if not exists sr_network_port on sip_registrations (network_port)", NULL, NULL, NULL); - switch_core_db_exec(profile->master_db, "create index if not exists sr_sip_username on sip_registrations (sip_username)", NULL, NULL, NULL); - switch_core_db_exec(profile->master_db, "create index if not exists sr_sip_realm on sip_registrations (sip_realm)", NULL, NULL, NULL); + switch_core_db_exec(db, "create index if not exists sr_call_id on sip_registrations (call_id)", NULL, NULL, NULL); + switch_core_db_exec(db, "create index if not exists sr_sip_user on sip_registrations (sip_user)", NULL, NULL, NULL); + switch_core_db_exec(db, "create index if not exists sr_sip_host on sip_registrations (sip_host)", NULL, NULL, NULL); + switch_core_db_exec(db, "create index if not exists sr_profile_name on sip_registrations (profile_name)", NULL, NULL, NULL); + switch_core_db_exec(db, "create index if not exists sr_presence_hosts on sip_registrations (presence_hosts)", NULL, NULL, NULL); + switch_core_db_exec(db, "create index if not exists sr_contact on sip_registrations (contact)", NULL, NULL, NULL); + switch_core_db_exec(db, "create index if not exists sr_expires on sip_registrations (expires)", NULL, NULL, NULL); + switch_core_db_exec(db, "create index if not exists sr_hostname on sip_registrations (hostname)", NULL, NULL, NULL); + switch_core_db_exec(db, "create index if not exists sr_status on sip_registrations (status)", NULL, NULL, NULL); + switch_core_db_exec(db, "create index if not exists sr_network_ip on sip_registrations (network_ip)", NULL, NULL, NULL); + switch_core_db_exec(db, "create index if not exists sr_network_port on sip_registrations (network_port)", NULL, NULL, NULL); + switch_core_db_exec(db, "create index if not exists sr_sip_username on sip_registrations (sip_username)", NULL, NULL, NULL); + switch_core_db_exec(db, "create index if not exists sr_sip_realm on sip_registrations (sip_realm)", NULL, NULL, NULL); - switch_core_db_exec(profile->master_db, "create index if not exists ss_call_id on sip_subscriptions (call_id)", NULL, NULL, NULL); - switch_core_db_exec(profile->master_db, "create index if not exists ss_hostname on sip_subscriptions (hostname)", NULL, NULL, NULL); - switch_core_db_exec(profile->master_db, "create index if not exists ss_hostname on sip_subscriptions (network_ip)", NULL, NULL, NULL); - switch_core_db_exec(profile->master_db, "create index if not exists ss_sip_user on sip_subscriptions (sip_user)", NULL, NULL, NULL); - switch_core_db_exec(profile->master_db, "create index if not exists ss_sip_host on sip_subscriptions (sip_host)", NULL, NULL, NULL); - switch_core_db_exec(profile->master_db, "create index if not exists ss_presence_hosts on sip_subscriptions (presence_hosts)", NULL, NULL, NULL); - switch_core_db_exec(profile->master_db, "create index if not exists ss_event on sip_subscriptions (event)", NULL, NULL, NULL); - switch_core_db_exec(profile->master_db, "create index if not exists ss_proto on sip_subscriptions (proto)", NULL, NULL, NULL); - switch_core_db_exec(profile->master_db, "create index if not exists ss_sub_to_user on sip_subscriptions (sub_to_user)", NULL, NULL, NULL); - switch_core_db_exec(profile->master_db, "create index if not exists ss_sub_to_host on sip_subscriptions (sub_to_host)", NULL, NULL, NULL); + switch_core_db_exec(db, "create index if not exists ss_call_id on sip_subscriptions (call_id)", NULL, NULL, NULL); + switch_core_db_exec(db, "create index if not exists ss_hostname on sip_subscriptions (hostname)", NULL, NULL, NULL); + switch_core_db_exec(db, "create index if not exists ss_hostname on sip_subscriptions (network_ip)", NULL, NULL, NULL); + switch_core_db_exec(db, "create index if not exists ss_sip_user on sip_subscriptions (sip_user)", NULL, NULL, NULL); + switch_core_db_exec(db, "create index if not exists ss_sip_host on sip_subscriptions (sip_host)", NULL, NULL, NULL); + switch_core_db_exec(db, "create index if not exists ss_presence_hosts on sip_subscriptions (presence_hosts)", NULL, NULL, NULL); + switch_core_db_exec(db, "create index if not exists ss_event on sip_subscriptions (event)", NULL, NULL, NULL); + switch_core_db_exec(db, "create index if not exists ss_proto on sip_subscriptions (proto)", NULL, NULL, NULL); + switch_core_db_exec(db, "create index if not exists ss_sub_to_user on sip_subscriptions (sub_to_user)", NULL, NULL, NULL); + switch_core_db_exec(db, "create index if not exists ss_sub_to_host on sip_subscriptions (sub_to_host)", NULL, NULL, NULL); - switch_core_db_exec(profile->master_db, "create index if not exists sd_uuid on sip_dialogs (uuid)", NULL, NULL, NULL); - switch_core_db_exec(profile->master_db, "create index if not exists sd_hostname on sip_dialogs (hostname)", NULL, NULL, NULL); - switch_core_db_exec(profile->master_db, "create index if not exists sd_hostname on sip_dialogs (contact)", NULL, NULL, NULL); - switch_core_db_exec(profile->master_db, "create index if not exists sd_hostname on sip_dialogs (presence_id)", NULL, NULL, NULL); - switch_core_db_exec(profile->master_db, "create index if not exists sd_hostname on sip_dialogs (presence_data)", NULL, NULL, NULL); + switch_core_db_exec(db, "create index if not exists sd_uuid on sip_dialogs (uuid)", NULL, NULL, NULL); + switch_core_db_exec(db, "create index if not exists sd_hostname on sip_dialogs (hostname)", NULL, NULL, NULL); + switch_core_db_exec(db, "create index if not exists sd_hostname on sip_dialogs (contact)", NULL, NULL, NULL); + switch_core_db_exec(db, "create index if not exists sd_hostname on sip_dialogs (presence_id)", NULL, NULL, NULL); + switch_core_db_exec(db, "create index if not exists sd_hostname on sip_dialogs (presence_data)", NULL, NULL, NULL); - switch_core_db_exec(profile->master_db, "create index if not exists sp_hostname on sip_presence (hostname)", NULL, NULL, NULL); + switch_core_db_exec(db, "create index if not exists sp_hostname on sip_presence (hostname)", NULL, NULL, NULL); - switch_core_db_exec(profile->master_db, "create index if not exists sa_nonce on sip_authentication (nonce)", NULL, NULL, NULL); - switch_core_db_exec(profile->master_db, "create index if not exists sa_hostname on sip_authentication (hostname)", NULL, NULL, NULL); + switch_core_db_exec(db, "create index if not exists sa_nonce on sip_authentication (nonce)", NULL, NULL, NULL); + switch_core_db_exec(db, "create index if not exists sa_hostname on sip_authentication (hostname)", NULL, NULL, NULL); } if (switch_odbc_available() && profile->odbc_dsn) { return profile->master_odbc ? 1 : 0; } + + if (db) { + switch_core_db_close(db); + return 1; + } else { + return 0; + } - return profile->master_db ? 1 : 0; } void sofia_glue_sql_close(sofia_profile_t *profile) @@ -3959,8 +3970,25 @@ void sofia_glue_sql_close(sofia_profile_t *profile) if (switch_odbc_available() && profile->master_odbc) { switch_odbc_handle_destroy(&profile->master_odbc); } else { - switch_core_db_close(profile->master_db); - profile->master_db = NULL; + switch_hash_index_t *hi; + const void *var; + void *val; + sofia_cache_db_handle_t *dbh = NULL; + + switch_mutex_lock(profile->ireg_mutex); + top: + for (hi = switch_hash_first(NULL, profile->db_hash); hi; hi = switch_hash_next(hi)) { + switch_hash_this(hi, &var, NULL, &val); + if ((dbh = (sofia_cache_db_handle_t *) val)) { + switch_core_db_close(dbh->db); + dbh->db = NULL; + switch_core_hash_delete(profile->db_hash, (char *)var); + + goto top; + } + } + switch_mutex_unlock(profile->ireg_mutex); + } } @@ -3988,7 +4016,7 @@ void sofia_glue_execute_sql(sofia_profile_t *profile, char **sqlp, switch_bool_t } if (status != SWITCH_STATUS_SUCCESS) { - sofia_glue_actually_execute_sql(profile, SWITCH_FALSE, sql, profile->ireg_mutex); + sofia_glue_actually_execute_sql(profile, sql, profile->ireg_mutex); } switch_safe_free(d_sql); @@ -3998,7 +4026,33 @@ void sofia_glue_execute_sql(sofia_profile_t *profile, char **sqlp, switch_bool_t } } -void sofia_glue_actually_execute_sql(sofia_profile_t *profile, switch_bool_t master, char *sql, switch_mutex_t *mutex) +switch_core_db_t *sofia_glue_get_db_handle(sofia_profile_t *profile) +{ + switch_thread_id_t self = switch_thread_self(); + char thread_str[256] = ""; + switch_core_db_t *db = NULL; + sofia_cache_db_handle_t *dbh = NULL; + + snprintf(thread_str, sizeof(thread_str) - 1, "%lu", (unsigned long)(intptr_t)self); + + switch_mutex_lock(profile->ireg_mutex); + if ((dbh = switch_core_hash_find(profile->db_hash, thread_str))) { + db = dbh->db; + } else { + dbh = switch_core_alloc(profile->pool, sizeof(*dbh)); + dbh->db = switch_core_db_open_file(profile->dbname); + dbh->last_used = switch_epoch_time_now(NULL); + switch_core_hash_insert(profile->db_hash, thread_str, dbh); + db = dbh->db; + } + switch_mutex_unlock(profile->ireg_mutex); + + return db; +} + + + +void sofia_glue_actually_execute_sql(sofia_profile_t *profile, char *sql, switch_mutex_t *mutex) { switch_core_db_t *db; @@ -4022,24 +4076,18 @@ void sofia_glue_actually_execute_sql(sofia_profile_t *profile, switch_bool_t mas } else { char *errmsg; - if (master) { - db = profile->master_db; - } else { - if (!(db = switch_core_db_open_file(profile->dbname))) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error Opening DB %s\n", profile->dbname); - goto end; - } + + if (!(db = sofia_glue_get_db_handle(profile))) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error Opening DB %s\n", profile->dbname); + goto end; } switch_core_db_exec(db, sql, NULL, NULL, &errmsg); + if (errmsg) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "SQL ERR [%s]\n%s\n", errmsg, sql); switch_core_db_free(errmsg); } - - if (!master) { - switch_core_db_close(db); - } } end: @@ -4049,7 +4097,7 @@ void sofia_glue_actually_execute_sql(sofia_profile_t *profile, switch_bool_t mas } switch_bool_t sofia_glue_execute_sql_callback(sofia_profile_t *profile, - switch_bool_t master, switch_mutex_t *mutex, char *sql, switch_core_db_callback_func_t callback, void *pdata) + switch_mutex_t *mutex, char *sql, switch_core_db_callback_func_t callback, void *pdata) { switch_bool_t ret = SWITCH_FALSE; switch_core_db_t *db; @@ -4066,25 +4114,18 @@ switch_bool_t sofia_glue_execute_sql_callback(sofia_profile_t *profile, switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "ODBC IS NOT AVAILABLE!\n"); } else { - if (master) { - db = profile->master_db; - } else { - if (!(db = switch_core_db_open_file(profile->dbname))) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error Opening DB %s\n", profile->dbname); - goto end; - } + if (!(db = sofia_glue_get_db_handle(profile))) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error Opening DB %s\n", profile->dbname); + goto end; } + switch_core_db_exec(db, sql, callback, pdata, &errmsg); if (errmsg) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "SQL ERR: [%s] %s\n", sql, errmsg); free(errmsg); } - - if (!master && db) { - switch_core_db_close(db); - } } end: diff --git a/src/mod/endpoints/mod_sofia/sofia_presence.c b/src/mod/endpoints/mod_sofia/sofia_presence.c index 7502ad2768..3108930595 100644 --- a/src/mod/endpoints/mod_sofia/sofia_presence.c +++ b/src/mod/endpoints/mod_sofia/sofia_presence.c @@ -190,7 +190,7 @@ void sofia_presence_cancel(void) } helper.profile = profile; helper.event = NULL; - if (sofia_glue_execute_sql_callback(profile, SWITCH_FALSE, profile->ireg_mutex, sql, sofia_presence_sub_callback, &helper) != SWITCH_TRUE) { + if (sofia_glue_execute_sql_callback(profile, profile->ireg_mutex, sql, sofia_presence_sub_callback, &helper) != SWITCH_TRUE) { continue; } } @@ -202,13 +202,13 @@ void sofia_presence_cancel(void) void sofia_presence_establish_presence(sofia_profile_t *profile) { - if (sofia_glue_execute_sql_callback(profile, SWITCH_FALSE, profile->ireg_mutex, + if (sofia_glue_execute_sql_callback(profile, profile->ireg_mutex, "select sip_user,sip_host,'Registered','unknown','' from sip_registrations", sofia_presence_resub_callback, profile) != SWITCH_TRUE) { return; } - if (sofia_glue_execute_sql_callback(profile, SWITCH_FALSE, profile->ireg_mutex, + if (sofia_glue_execute_sql_callback(profile, profile->ireg_mutex, "select sub_to_user,sub_to_host,'Online','unknown',proto from sip_subscriptions " "where proto='ext' or proto='user' or proto='conf'", sofia_presence_resub_callback, profile) != SWITCH_TRUE) { return; @@ -337,7 +337,7 @@ static void actual_sofia_presence_mwi_event_handler(switch_event_t *event) if (sql) { - sofia_glue_execute_sql_callback(profile, SWITCH_FALSE, profile->ireg_mutex, sql, sofia_presence_mwi_callback, &h); + sofia_glue_execute_sql_callback(profile, profile->ireg_mutex, sql, sofia_presence_mwi_callback, &h); free(sql); sql = NULL; @@ -355,7 +355,7 @@ static void actual_sofia_presence_mwi_event_handler(switch_event_t *event) if (sql) { switch_assert(sql != NULL); - sofia_glue_execute_sql_callback(profile, SWITCH_FALSE, profile->ireg_mutex, sql, sofia_presence_mwi_callback2, &h); + sofia_glue_execute_sql_callback(profile, profile->ireg_mutex, sql, sofia_presence_mwi_callback2, &h); free(sql); sql = NULL; } @@ -456,7 +456,7 @@ static void actual_sofia_presence_event_handler(switch_event_t *event) } helper.profile = profile; helper.event = NULL; - sofia_glue_execute_sql_callback(profile, SWITCH_FALSE, profile->ireg_mutex, sql, sofia_presence_sub_callback, &helper); + sofia_glue_execute_sql_callback(profile, profile->ireg_mutex, sql, sofia_presence_sub_callback, &helper); } switch_mutex_unlock(mod_sofia_globals.hash_mutex); free(sql); @@ -534,7 +534,7 @@ static void actual_sofia_presence_event_handler(switch_event_t *event) switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "%s DUMP PRESENCE_PROBE_SQL:\n%s\n", profile->name, sql); } - sofia_glue_execute_sql_callback(profile, SWITCH_FALSE, profile->ireg_mutex, sql, sofia_presence_resub_callback, profile); + sofia_glue_execute_sql_callback(profile, profile->ireg_mutex, sql, sofia_presence_resub_callback, profile); if (mod_sofia_globals.debug_presence > 0) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "%s END_PRESENCE_PROBE_SQL\n\n", profile->name); } @@ -573,7 +573,6 @@ static void actual_sofia_presence_event_handler(switch_event_t *event) } continue; } - if ((sql = switch_mprintf( @@ -615,7 +614,7 @@ static void actual_sofia_presence_event_handler(switch_event_t *event) free(buf); } - sofia_glue_execute_sql_callback(profile, SWITCH_FALSE, + sofia_glue_execute_sql_callback(profile, NULL, sql, sofia_presence_sub_callback, &helper); if (mod_sofia_globals.debug_presence > 0) { @@ -1764,7 +1763,7 @@ void sofia_presence_handle_sip_i_subscribe(int status, "full_via,expires,user_agent,accept,profile_name,network_ip" " from sip_subscriptions where sip_user='%q' and (sip_host='%q' or presence_hosts like '%%%q%%')", to_host, to_user, to_host, to_host))) { - sofia_glue_execute_sql_callback(profile, SWITCH_FALSE, profile->ireg_mutex, sql, sofia_presence_sub_reg_callback, profile); + sofia_glue_execute_sql_callback(profile, profile->ireg_mutex, sql, sofia_presence_sub_reg_callback, profile); switch_safe_free(sql); } diff --git a/src/mod/endpoints/mod_sofia/sofia_reg.c b/src/mod/endpoints/mod_sofia/sofia_reg.c index 0c41a39192..4d5c65252a 100644 --- a/src/mod/endpoints/mod_sofia/sofia_reg.c +++ b/src/mod/endpoints/mod_sofia/sofia_reg.c @@ -521,7 +521,7 @@ void sofia_reg_expire_call_id(sofia_profile_t *profile, const char *call_id, int switch_safe_free(sqlextra); switch_mutex_lock(profile->ireg_mutex); - sofia_glue_execute_sql_callback(profile, SWITCH_TRUE, NULL, sql, sofia_reg_del_callback, profile); + sofia_glue_execute_sql_callback(profile, NULL, sql, sofia_reg_del_callback, profile); switch_mutex_unlock(profile->ireg_mutex); switch_safe_free(sql); @@ -543,11 +543,6 @@ void sofia_reg_check_expire(sofia_profile_t *profile, time_t now, int reboot) switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error Opening DB %s\n", profile->dbname); return; } - } else { - if (!profile->master_db) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error Opening DB %s\n", profile->dbname); - return; - } } switch_mutex_lock(profile->ireg_mutex); @@ -562,7 +557,7 @@ void sofia_reg_check_expire(sofia_profile_t *profile, time_t now, int reboot) ",%d from sip_registrations where expires > 0", reboot); } - sofia_glue_execute_sql_callback(profile, SWITCH_TRUE, NULL, sql, sofia_reg_del_callback, profile); + sofia_glue_execute_sql_callback(profile, NULL, sql, sofia_reg_del_callback, profile); if (now) { switch_snprintf(sql, sizeof(sql), "delete from sip_registrations where expires > 0 and expires <= %ld and hostname='%s'", (long) now, mod_sofia_globals.hostname); @@ -570,7 +565,7 @@ void sofia_reg_check_expire(sofia_profile_t *profile, time_t now, int reboot) switch_snprintf(sql, sizeof(sql), "delete from sip_registrations where expires > 0 and hostname='%s'", mod_sofia_globals.hostname); } - sofia_glue_actually_execute_sql(profile, SWITCH_FALSE, sql, NULL); + sofia_glue_actually_execute_sql(profile, sql, NULL); @@ -579,12 +574,12 @@ void sofia_reg_check_expire(sofia_profile_t *profile, time_t now, int reboot) "and profile_name='%s' and expires <= %ld", mod_sofia_globals.hostname, profile->name, (long) now); - sofia_glue_execute_sql_callback(profile, SWITCH_TRUE, NULL, sql, sofia_sla_dialog_del_callback, profile); + sofia_glue_execute_sql_callback(profile, NULL, sql, sofia_sla_dialog_del_callback, profile); switch_snprintf(sql, sizeof(sql), "delete from sip_registrations where expires > 0 and hostname='%s' and expires <= %ld", mod_sofia_globals.hostname, (long) now); - sofia_glue_actually_execute_sql(profile, SWITCH_FALSE, sql, NULL); + sofia_glue_actually_execute_sql(profile, sql, NULL); } @@ -595,7 +590,7 @@ void sofia_reg_check_expire(sofia_profile_t *profile, time_t now, int reboot) switch_snprintf(sql, sizeof(sql), "delete from sip_presence where expires > 0 and hostname='%s'", mod_sofia_globals.hostname); } - sofia_glue_actually_execute_sql(profile, SWITCH_FALSE, sql, NULL); + sofia_glue_actually_execute_sql(profile, sql, NULL); if (now) { switch_snprintf(sql, sizeof(sql), "delete from sip_authentication where expires > 0 and expires <= %ld and hostname='%s'", @@ -604,7 +599,7 @@ void sofia_reg_check_expire(sofia_profile_t *profile, time_t now, int reboot) switch_snprintf(sql, sizeof(sql), "delete from sip_authentication where expires > 0 and hostname='%s'", mod_sofia_globals.hostname); } - sofia_glue_actually_execute_sql(profile, SWITCH_FALSE, sql, NULL); + sofia_glue_actually_execute_sql(profile, sql, NULL); @@ -615,7 +610,7 @@ void sofia_reg_check_expire(sofia_profile_t *profile, time_t now, int reboot) switch_snprintf(sql, sizeof(sql), "select call_id from sip_subscriptions where expires > 0 and hostname='%s'", mod_sofia_globals.hostname); } - sofia_glue_execute_sql_callback(profile, SWITCH_TRUE, NULL, sql, sofia_sub_del_callback, profile); + sofia_glue_execute_sql_callback(profile, NULL, sql, sofia_sub_del_callback, profile); if (now) { switch_snprintf(sql, sizeof(sql), "delete from sip_subscriptions where expires > 0 and expires <= %ld and hostname='%s'", @@ -624,7 +619,7 @@ void sofia_reg_check_expire(sofia_profile_t *profile, time_t now, int reboot) switch_snprintf(sql, sizeof(sql), "delete from sip_subscriptions where expires > 0 and hostname='%s'", mod_sofia_globals.hostname); } - sofia_glue_actually_execute_sql(profile, SWITCH_FALSE, sql, NULL); + sofia_glue_actually_execute_sql(profile, sql, NULL); if (now && sofia_test_pflag(profile, PFLAG_NAT_OPTIONS_PING)) { @@ -633,7 +628,7 @@ void sofia_reg_check_expire(sofia_profile_t *profile, time_t now, int reboot) " from sip_registrations where (status like '%%AUTO-NAT%%' " "or status like '%%UDP-NAT%%') and hostname='%s'", mod_sofia_globals.hostname); - sofia_glue_execute_sql_callback(profile, SWITCH_TRUE, NULL, sql, sofia_reg_nat_callback, profile); + sofia_glue_execute_sql_callback(profile, NULL, sql, sofia_reg_nat_callback, profile); } switch_mutex_unlock(profile->ireg_mutex); @@ -661,7 +656,7 @@ char *sofia_reg_find_reg_url(sofia_profile_t *profile, const char *user, const c } - sofia_glue_execute_sql_callback(profile, SWITCH_FALSE, profile->ireg_mutex, sql, sofia_reg_find_callback, &cbt); + sofia_glue_execute_sql_callback(profile, profile->ireg_mutex, sql, sofia_reg_find_callback, &cbt); if (cbt.matches) { @@ -686,9 +681,10 @@ void sofia_reg_auth_challenge(nua_t *nua, sofia_profile_t *profile, nua_handle_t switch_epoch_time_now(NULL) + (profile->nonce_ttl ? profile->nonce_ttl : DEFAULT_NONCE_TTL), profile->name, mod_sofia_globals.hostname); switch_assert(sql != NULL); - sofia_glue_actually_execute_sql(profile, SWITCH_FALSE, sql, profile->ireg_mutex); + sofia_glue_actually_execute_sql(profile, sql, profile->ireg_mutex); switch_safe_free(sql); + //auth_str = switch_mprintf("Digest realm=\"%q\", nonce=\"%q\",%s algorithm=MD5, qop=\"auth\"", realm, uuid_str, stale ? " stale=true," : ""); auth_str = switch_mprintf("Digest realm=\"%q\", nonce=\"%q\",%s algorithm=MD5, qop=\"auth\"", realm, uuid_str, stale ? " stale=\"true\"," : ""); if (regtype == REG_REGISTER) { @@ -741,6 +737,7 @@ uint8_t sofia_reg_handle_register(nua_t *nua, sofia_profile_t *profile, nua_hand char *path_val = NULL; switch_event_t *auth_params = NULL; int r = 0; + long reg_count = 0; /* all callers must confirm that sip, sip->sip_request and sip->sip_contact are not NULL */ switch_assert(sip != NULL && sip->sip_contact != NULL && sip->sip_request != NULL); @@ -896,7 +893,7 @@ uint8_t sofia_reg_handle_register(nua_t *nua, sofia_profile_t *profile, nua_hand if (authorization) { char *v_contact_str; if ((auth_res = sofia_reg_parse_auth(profile, authorization, sip, sip->sip_request->rq_method_name, - key, keylen, network_ip, v_event, exptime, regtype, to_user, &auth_params)) == AUTH_STALE) { + key, keylen, network_ip, v_event, exptime, regtype, to_user, &auth_params, ®_count)) == AUTH_STALE) { stale = 1; } @@ -1131,16 +1128,21 @@ uint8_t sofia_reg_handle_register(nua_t *nua, sofia_profile_t *profile, nua_hand switch_event_fire(&event); } #else - if (switch_event_create(&event, SWITCH_EVENT_PRESENCE_PROBE) == SWITCH_STATUS_SUCCESS) { - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "proto", "sip"); - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "login", profile->url); - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "rpid", rpid); - switch_event_add_header(event, SWITCH_STACK_BOTTOM, "from", "%s@%s", to_user, reg_host); - switch_event_add_header(event, SWITCH_STACK_BOTTOM, "to", "%s@%s", to_user, reg_host); - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "status", "Registered"); - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "event_subtype", "probe"); - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "event_type", "presence"); - switch_event_fire(&event); + + if (sofia_test_pflag(profile, PFLAG_MESSAGE_QUERY_ON_REGISTER) || + (reg_count == 1 && sofia_test_pflag(profile, PFLAG_MESSAGE_QUERY_ON_FIRST_REGISTER))) { + + if (switch_event_create(&event, SWITCH_EVENT_PRESENCE_PROBE) == SWITCH_STATUS_SUCCESS) { + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "proto", "sip"); + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "login", profile->url); + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "rpid", rpid); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "from", "%s@%s", to_user, reg_host); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "to", "%s@%s", to_user, reg_host); + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "status", "Registered"); + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "event_subtype", "probe"); + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "event_type", "presence"); + switch_event_fire(&event); + } } #endif @@ -1213,28 +1215,15 @@ uint8_t sofia_reg_handle_register(nua_t *nua, sofia_profile_t *profile, nua_hand if (regtype == REG_REGISTER) { char exp_param[128] = ""; char date[80] = ""; - long nc_long = 0; - + s_event = NULL; if (exptime) { switch_snprintf(exp_param, sizeof(exp_param), "expires=%ld", exptime); sip_contact_add_param(nua_handle_home(nh), sip->sip_contact, exp_param); - if (auth_params && sofia_test_pflag(profile, PFLAG_MESSAGE_QUERY_ON_FIRST_REGISTER)) { - const char *nc = NULL; - - if ((nc = switch_event_get_header(auth_params, "sip_auth_nc"))) { - nc_long = strtoul(nc, 0, 16); - } else { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, - "No nonce count, cannot determine if this was the first register, sending notify implicitly.\n"); - nc_long = 1; - } - } - if (sofia_test_pflag(profile, PFLAG_MESSAGE_QUERY_ON_REGISTER) || - (nc_long == 1 && sofia_test_pflag(profile, PFLAG_MESSAGE_QUERY_ON_FIRST_REGISTER))) { + (reg_count == 1 && sofia_test_pflag(profile, PFLAG_MESSAGE_QUERY_ON_FIRST_REGISTER))) { if (switch_event_create(&s_event, SWITCH_EVENT_MESSAGE_QUERY) == SWITCH_STATUS_SUCCESS) { switch_event_add_header(s_event, SWITCH_STACK_BOTTOM, "Message-Account", "sip:%s@%s", mwi_user, mwi_host); switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "VM-Sofia-Profile", profile->name); @@ -1263,13 +1252,9 @@ uint8_t sofia_reg_handle_register(nua_t *nua, sofia_profile_t *profile, nua_hand if (s_event) { switch_event_fire(&s_event); } - - if (sofia_test_pflag(profile, PFLAG_MANAGE_SHARED_APPEARANCE)) { - char *full_contact = sip_header_as_string(nua_handle_home(nh), (void *) sip->sip_contact); - if (full_contact && switch_stristr("SUBSCRIBE", full_contact)) { - sofia_sla_handle_register(nua, profile, sip, exptime, full_contact); - su_free(nua_handle_home(nh), full_contact); - } + + if (contact_str && sofia_test_pflag(profile, PFLAG_MANAGE_SHARED_APPEARANCE) && sofia_sla_supported(sip)) { + sofia_sla_handle_register(nua, profile, sip, exptime, contact_str); } switch_goto_int(r, 1, end); @@ -1594,6 +1579,20 @@ void sofia_reg_handle_sip_r_challenge(int status, } +typedef struct { + char *nonce; + switch_size_t nplen; + int last_nc; +} nonce_cb_t; + +static int sofia_reg_nonce_callback(void *pArg, int argc, char **argv, char **columnNames) +{ + nonce_cb_t *cb = (nonce_cb_t *) pArg; + switch_copy_string(cb->nonce, argv[0], cb->nplen); + cb->last_nc = zstr(argv[1]) ? 0 : atoi(argv[1]); + return 0; +} + auth_res_t sofia_reg_parse_auth(sofia_profile_t *profile, sip_authorization_t const *authorization, sip_t const *sip, @@ -1606,7 +1605,8 @@ auth_res_t sofia_reg_parse_auth(sofia_profile_t *profile, sofia_regtype_t regtype, const char *to_user, - switch_event_t **auth_params) + switch_event_t **auth_params, + long *reg_count) { int indexnum; const char *cur; @@ -1626,6 +1626,7 @@ auth_res_t sofia_reg_parse_auth(sofia_profile_t *profile, char *domain_name = NULL; switch_event_t *params = NULL; const char *auth_acl = NULL; + long ncl = 0; username = realm = nonce = uri = qop = cnonce = nc = response = NULL; @@ -1684,20 +1685,35 @@ auth_res_t sofia_reg_parse_auth(sofia_profile_t *profile, } if (zstr(np)) { + nonce_cb_t cb = { 0 }; + long nc_long = 0; first = 1; + if (nc) { - sql = switch_mprintf("select nonce from sip_authentication where nonce='%q' and last_nc < %lu", nonce, strtoul(nc, 0, 16)); + nc_long = strtoul(nc, 0, 16); + sql = switch_mprintf("select nonce,last_nc from sip_authentication where nonce='%q' and last_nc < %lu", nonce, nc_long); } else { sql = switch_mprintf("select nonce from sip_authentication where nonce='%q'", nonce); } + cb.nonce = np; + cb.nplen = nplen; + switch_assert(sql != NULL); - if (!sofia_glue_execute_sql2str(profile, profile->ireg_mutex, sql, np, nplen)) { - free(sql); + sofia_glue_execute_sql_callback(profile, NULL, sql, sofia_reg_nonce_callback, &cb); + free(sql); + + //if (!sofia_glue_execute_sql2str(profile, profile->ireg_mutex, sql, np, nplen)) { + if (zstr(np)) { + sql = switch_mprintf("delete from sip_authentication where nonce='%q'", nonce); + sofia_glue_execute_sql(profile, &sql, SWITCH_TRUE); ret = AUTH_STALE; goto end; } - free(sql); + + if (reg_count) { + *reg_count = cb.last_nc + 1; + } } switch_event_create(¶ms, SWITCH_EVENT_REQUEST_PARAMS); @@ -2082,6 +2098,7 @@ auth_res_t sofia_reg_parse_auth(sofia_profile_t *profile, if (nc && cnonce && qop) { + ncl = strtoul(nc, 0, 16); #if defined(_WIN32) && !defined(_WIN64) #define LL_FMT "ll" @@ -2089,10 +2106,10 @@ auth_res_t sofia_reg_parse_auth(sofia_profile_t *profile, #define LL_FMT "l" #endif sql = switch_mprintf("update sip_authentication set expires='%"LL_FMT"u',last_nc=%lu where nonce='%s'", - switch_epoch_time_now(NULL) + (profile->nonce_ttl ? profile->nonce_ttl : exptime + 10), strtoul(nc, 0, 16), nonce); + switch_epoch_time_now(NULL) + (profile->nonce_ttl ? profile->nonce_ttl : exptime + 10), ncl, nonce); switch_assert(sql != NULL); - sofia_glue_actually_execute_sql(profile, SWITCH_FALSE, sql, profile->ireg_mutex); + sofia_glue_actually_execute_sql(profile, sql, profile->ireg_mutex); switch_safe_free(sql); } @@ -2112,6 +2129,18 @@ auth_res_t sofia_reg_parse_auth(sofia_profile_t *profile, switch_safe_free(nc); switch_safe_free(response); + if (reg_count && !*reg_count) { + if (ret == AUTH_OK) { + if (ncl) { + *reg_count = ncl; + } else { + *reg_count = 1; + } + } else { + *reg_count = 0; + } + } + return ret; } diff --git a/src/mod/endpoints/mod_sofia/sofia_sla.c b/src/mod/endpoints/mod_sofia/sofia_sla.c index 9ae56e10fc..afec5e5a12 100644 --- a/src/mod/endpoints/mod_sofia/sofia_sla.c +++ b/src/mod/endpoints/mod_sofia/sofia_sla.c @@ -49,6 +49,25 @@ static int get_call_id_callback(void *pArg, int argc, char **argv, char **column return 0; } +int sofia_sla_supported(sip_t const *sip) +{ + if (sip && sip->sip_user_agent && sip->sip_user_agent->g_string) { + const char *ua = sip->sip_user_agent->g_string; + + if (switch_stristr("polycom", ua)) { + return 1; + } + + if (switch_stristr("snom", ua)) { + return 1; + } + + } + + return 0; +} + + void sofia_sla_handle_register(nua_t *nua, sofia_profile_t *profile, sip_t const *sip, long exptime, const char *full_contact) { nua_handle_t *nh = NULL; @@ -60,12 +79,15 @@ void sofia_sla_handle_register(nua_t *nua, sofia_profile_t *profile, sip_t const sofia_transport_t transport = sofia_glue_url2transport(sip->sip_contact->m_url); char network_ip[80]; int network_port = 0; + sofia_destination_t *dst; + char *route_uri = NULL; + char port_str[25] = ""; sofia_glue_get_addr(nua_current_request(nua), network_ip, sizeof(network_ip), &network_port); sql = switch_mprintf("select call_id from sip_shared_appearance_dialogs where hostname='%q' and profile_name='%q' and contact_str='%q'", mod_sofia_globals.hostname, profile->name, contact_str); - sofia_glue_execute_sql_callback(profile, SWITCH_FALSE, profile->ireg_mutex, sql, get_call_id_callback, &sh); + sofia_glue_execute_sql_callback(profile, profile->ireg_mutex, sql, get_call_id_callback, &sh); free(sql); @@ -85,21 +107,35 @@ void sofia_sla_handle_register(nua_t *nua, sofia_profile_t *profile, sip_t const nua_handle_bind(nh, &mod_sofia_globals.keep_private); switch_snprintf(exp_str, sizeof(exp_str), "%ld", exptime + 30); + + switch_snprintf(port_str, sizeof(port_str), ":%ld", sofia_glue_transport_has_tls(transport) ? profile->tls_sip_port : profile->sip_port); + if (sofia_glue_check_nat(profile, network_ip)) { - switch_snprintf(my_contact, sizeof(my_contact), ";expires=%s", profile->sla_contact, - profile->extsipip, sofia_glue_transport2str(transport), exp_str); + switch_snprintf(my_contact, sizeof(my_contact), ";expires=%s", profile->sla_contact, + profile->extsipip, port_str, sofia_glue_transport2str(transport), exp_str); } else { - switch_snprintf(my_contact, sizeof(my_contact), ";expires=%s", profile->sla_contact, - profile->sipip, sofia_glue_transport2str(transport), exp_str); + switch_snprintf(my_contact, sizeof(my_contact), ";expires=%s", profile->sla_contact, + profile->sipip, port_str, sofia_glue_transport2str(transport), exp_str); } + + dst = sofia_glue_get_destination((char*) full_contact); + + if(dst->route_uri) { + route_uri = sofia_glue_strip_uri(dst->route_uri); + } + nua_subscribe(nh, + TAG_IF(dst->route_uri, NUTAG_PROXY(route_uri)), TAG_IF(dst->route, SIPTAG_ROUTE_STR(dst->route)), SIPTAG_TO(sip->sip_to), SIPTAG_FROM(sip->sip_to), SIPTAG_CONTACT_STR(my_contact), SIPTAG_EXPIRES_STR(exp_str), - SIPTAG_EVENT_STR("dialog;sla"), /* some phones want ;include-session-description too? */ + SIPTAG_EVENT_STR("dialog;sla;include-session-description"), + SIPTAG_ACCEPT_STR("application/dialog-info+xml"), TAG_NULL()); + sofia_glue_free_destination(dst); + free(contact_str); } @@ -119,6 +155,7 @@ void sofia_sla_handle_sip_i_subscribe(nua_t *nua, const char *contact_str, sofia char network_ip[80]; int network_port = 0; sofia_transport_t transport = sofia_glue_url2transport(sip->sip_contact->m_url); + char *pl; sofia_glue_get_addr(nua_current_request(nua), network_ip, sizeof(network_ip), &network_port); /* @@ -194,6 +231,21 @@ void sofia_sla_handle_sip_i_subscribe(nua_t *nua, const char *contact_str, sofia /* sofia_presence says something about needing TAG_IF(sticky, NUTAG_PROXY(sticky)) for NAT stuff? */ TAG_END()); + + + pl = switch_mprintf("\n" + "\n", aor); + + nua_notify(nh, + SIPTAG_SUBSCRIPTION_STATE_STR("active;expires=300"), /* XXX MTK FIXME - this is totally fake calculation */ + TAG_IF(route_uri, NUTAG_PROXY(route_uri)), + SIPTAG_CONTENT_TYPE_STR("application/dialog-info+xml"), /* could've just kept the type from the payload */ + SIPTAG_PAYLOAD_STR(pl), + TAG_END()); + + + switch_safe_free(aor); switch_safe_free(subscriber); switch_safe_free(route_uri); @@ -295,7 +347,7 @@ void sofia_sla_handle_sip_i_notify(nua_t *nua, sofia_profile_t *profile, nua_han helper.payload = sip->sip_payload->pl_data; /* could just send the WHOLE payload. you'd get the type that way. */ /* which mutex if any is correct to hold in this callback? XXX MTK FIXME */ - sofia_glue_execute_sql_callback(profile, SWITCH_FALSE, profile->ireg_mutex, sql, sofia_sla_sub_callback, &helper); + sofia_glue_execute_sql_callback(profile, profile->ireg_mutex, sql, sofia_sla_sub_callback, &helper); switch_safe_free(sql); switch_safe_free(aor);