diff --git a/src/mod/endpoints/mod_sofia/mod_sofia.c b/src/mod/endpoints/mod_sofia/mod_sofia.c index 75d77308e0..58869d49d5 100644 --- a/src/mod/endpoints/mod_sofia/mod_sofia.c +++ b/src/mod/endpoints/mod_sofia/mod_sofia.c @@ -4175,7 +4175,7 @@ SWITCH_STANDARD_API(sofia_function) } if (strstr(argv[2], "sla")) { - mod_sofia_globals.debug_sla = 1; + mod_sofia_globals.debug_sla = 10; stream->write_function(stream, "+OK Debugging sla\n"); } diff --git a/src/mod/endpoints/mod_sofia/mod_sofia.h b/src/mod/endpoints/mod_sofia/mod_sofia.h index ec036e0aea..12e9a8f277 100644 --- a/src/mod/endpoints/mod_sofia/mod_sofia.h +++ b/src/mod/endpoints/mod_sofia/mod_sofia.h @@ -828,6 +828,7 @@ typedef struct { int network_port; const char *is_nat; int is_auto_nat; + int fs_path; } sofia_nat_parse_t; @@ -1140,7 +1141,7 @@ switch_status_t sofia_glue_sdp_map(const char *r_sdp, switch_event_t **fmtp, swi void sofia_glue_build_vid_refresh_message(switch_core_session_t *session, const char *pl); void sofia_glue_check_dtmf_type(private_object_t *tech_pvt); void sofia_glue_parse_rtp_bugs(switch_rtp_bug_flag_t *flag_pole, const char *str); -char *sofia_glue_gen_contact_str(sofia_profile_t *profile, sip_t const *sip, sofia_dispatch_event_t *de, sofia_nat_parse_t *np); +char *sofia_glue_gen_contact_str(sofia_profile_t *profile, sip_t const *sip, nua_handle_t *nh, sofia_dispatch_event_t *de, sofia_nat_parse_t *np); void sofia_glue_pause_jitterbuffer(switch_core_session_t *session, switch_bool_t on); void sofia_process_dispatch_event(sofia_dispatch_event_t **dep); char *sofia_glue_get_host(const char *str, switch_memory_pool_t *pool); diff --git a/src/mod/endpoints/mod_sofia/sofia.c b/src/mod/endpoints/mod_sofia/sofia.c index 3e287248d5..1235ff3132 100644 --- a/src/mod/endpoints/mod_sofia/sofia.c +++ b/src/mod/endpoints/mod_sofia/sofia.c @@ -91,7 +91,7 @@ void sofia_handle_sip_r_notify(switch_core_session_t *session, int status, if (status >= 300 && sip && sip->sip_call_id && (!sofia_private || !sofia_private->is_call)) { char *sql; - sql = switch_mprintf("update sip_subscriptions set expires=%ld where call_id='%q'", (long) switch_epoch_time_now(NULL), sip->sip_call_id->i_id); + sql = switch_mprintf("delete from sip_subscriptions where call_id='%q'", sip->sip_call_id->i_id); switch_assert(sql != NULL); sofia_glue_execute_sql(profile, &sql, SWITCH_TRUE); nua_handle_destroy(nh); @@ -3686,7 +3686,7 @@ switch_status_t config_sofia(int reload, char *profile_name) 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_PRESENCE_ON_FIRST_REGISTER); + //sofia_set_pflag(profile, PFLAG_PRESENCE_ON_FIRST_REGISTER); sofia_set_pflag(profile, PFLAG_SQL_IN_TRANS); profile->shutdown_type = "false"; diff --git a/src/mod/endpoints/mod_sofia/sofia_glue.c b/src/mod/endpoints/mod_sofia/sofia_glue.c index 947eeb1e9f..9a052d8cee 100644 --- a/src/mod/endpoints/mod_sofia/sofia_glue.c +++ b/src/mod/endpoints/mod_sofia/sofia_glue.c @@ -5139,6 +5139,14 @@ char *sofia_glue_get_url_from_contact(char *buf, uint8_t to_dup) { char *url = NULL, *e; + while((e = strchr(buf, '"'))) { + buf = e+1; + } + + while(*buf == ' ') { + buf++; + } + if ((url = strchr(buf, '<')) && (e = strchr(url, '>'))) { url++; if (to_dup) { @@ -6504,9 +6512,14 @@ switch_status_t sofia_glue_send_notify(sofia_profile_t *profile, const char *use nua_handle_t *nh; sofia_destination_t *dst = NULL; char *contact_str, *contact, *user_via = NULL; - char *route_uri = NULL; + char *route_uri = NULL, *p; contact = sofia_glue_get_url_from_contact((char *) o_contact, 1); + + if ((p = strstr(contact, ";fs_"))) { + *p = '\0'; + } + if (!zstr(network_ip) && sofia_glue_check_nat(profile, network_ip)) { char *ptr = NULL; //const char *transport_str = NULL; @@ -6744,7 +6757,7 @@ void sofia_glue_parse_rtp_bugs(switch_rtp_bug_flag_t *flag_pole, const char *str } } -char *sofia_glue_gen_contact_str(sofia_profile_t *profile, sip_t const *sip, sofia_dispatch_event_t *de, sofia_nat_parse_t *np) +char *sofia_glue_gen_contact_str(sofia_profile_t *profile, sip_t const *sip, nua_handle_t *nh, sofia_dispatch_event_t *de, sofia_nat_parse_t *np) { char *contact_str = NULL; const char *contact_host;//, *contact_user; @@ -6841,7 +6854,8 @@ char *sofia_glue_gen_contact_str(sofia_profile_t *profile, sip_t const *sip, sof np->is_nat = "No contact host"; } - if (np->is_nat) { + + if (np->is_nat && !np->fs_path) { contact_host = np->network_ip; switch_snprintf(new_port, sizeof(new_port), ":%d", np->network_port); port = NULL; @@ -6853,17 +6867,50 @@ char *sofia_glue_gen_contact_str(sofia_profile_t *profile, sip_t const *sip, sof } ipv6 = strchr(contact_host, ':'); - if (contact->m_url->url_params) { - contact_str = switch_mprintf("%s %s", - display, contact->m_url->url_user, - ipv6 ? "[" : "", - contact_host, ipv6 ? "]" : "", new_port, contact->m_url->url_params, np->is_nat ? ";fs_nat=yes" : ""); - } else { - contact_str = switch_mprintf("%s %s", - display, - contact->m_url->url_user, ipv6 ? "[" : "", contact_host, ipv6 ? "]" : "", new_port, np->is_nat ? ";fs_nat=yes" : ""); - } + if (np->is_nat && np->fs_path) { + char *full_contact = sip_header_as_string(nh->nh_home, (void *) contact); + char *full_contact_dup; + char *path_encoded; + int path_encoded_len; + char *path_val; + const char *tp; + + full_contact_dup = sofia_glue_get_url_from_contact(full_contact, 1); + + if ((tp = switch_stristr("transport=", full_contact_dup))) { + tp += 10; + } + + if (zstr(tp)) { + tp = "udp"; + } + + path_val = switch_mprintf("sip:%s:%d;transport=%s", np->network_ip, np->network_port, tp); + path_encoded_len = (int)(strlen(path_val) * 3) + 1; + + switch_zmalloc(path_encoded, path_encoded_len); + switch_copy_string(path_encoded, ";fs_path=", 10); + switch_url_encode(path_val, path_encoded + 9, path_encoded_len - 9); + + contact_str = switch_mprintf("%s <%s;fs_nat=yes%s>", display, full_contact_dup, path_encoded); + + free(full_contact_dup); + free(path_encoded); + free(path_val); + + } else { + if (contact->m_url->url_params) { + contact_str = switch_mprintf("%s %s", + display, contact->m_url->url_user, + ipv6 ? "[" : "", + contact_host, ipv6 ? "]" : "", new_port, contact->m_url->url_params, np->is_nat ? ";fs_nat=yes" : ""); + } else { + contact_str = switch_mprintf("%s %s", + display, + contact->m_url->url_user, ipv6 ? "[" : "", contact_host, ipv6 ? "]" : "", new_port, np->is_nat ? ";fs_nat=yes" : ""); + } + } return contact_str; } diff --git a/src/mod/endpoints/mod_sofia/sofia_presence.c b/src/mod/endpoints/mod_sofia/sofia_presence.c index 9389c3209f..ebead19d39 100644 --- a/src/mod/endpoints/mod_sofia/sofia_presence.c +++ b/src/mod/endpoints/mod_sofia/sofia_presence.c @@ -40,6 +40,7 @@ struct state_helper { switch_hash_t *hash; sofia_profile_t *profile; switch_memory_pool_t *pool; + int total; }; @@ -50,7 +51,7 @@ static int sofia_presence_resub_callback(void *pArg, int argc, char **argv, char static int sofia_presence_sub_callback(void *pArg, int argc, char **argv, char **columnNames); static int broadsoft_sla_gather_state_callback(void *pArg, int argc, char **argv, char **columnNames); static int broadsoft_sla_notify_callback(void *pArg, int argc, char **argv, char **columnNames); -static void sync_sla(sofia_profile_t *profile, const char *to_user, const char *to_host, switch_bool_t clear, switch_bool_t unseize); +static int sync_sla(sofia_profile_t *profile, const char *to_user, const char *to_host, switch_bool_t clear, switch_bool_t unseize, const char *call_id); static int sofia_dialog_probe_callback(void *pArg, int argc, char **argv, char **columnNames); static int sofia_dialog_probe_notify_callback(void *pArg, int argc, char **argv, char **columnNames); @@ -574,7 +575,7 @@ static int sofia_presence_dialog_callback(void *pArg, int argc, char **argv, cha } -static void do_normal_probe(sofia_profile_t *profile, switch_event_t *event) +static void do_normal_probe(switch_event_t *event) { char *sql; struct resub_helper h = { 0 }; @@ -582,6 +583,8 @@ static void do_normal_probe(sofia_profile_t *profile, switch_event_t *event) char *proto = switch_event_get_header(event, "proto"); char *probe_user = NULL, *probe_euser, *probe_host, *p; struct dialog_helper dh = { { 0 } }; + char *sub_call_id = switch_event_get_header(event, "sub-call-id"); + sofia_profile_t *profile; //DUMP_EVENT(event); @@ -605,6 +608,8 @@ static void do_normal_probe(sofia_profile_t *profile, switch_event_t *event) 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') order by rcd desc", probe_euser, probe_host, probe_euser, probe_host); + + sofia_glue_execute_sql_callback(profile, profile->ireg_mutex, sql, sofia_presence_dialog_callback, &dh); h.profile = profile; @@ -626,7 +631,7 @@ static void do_normal_probe(sofia_profile_t *profile, switch_event_t *event) "sip_presence.rpid," "sip_dialogs.presence_id, " "sip_presence.open_closed," - "'%q','%q' " + "'%q','%q','%q' " "from sip_registrations " "left join sip_dialogs on " @@ -637,12 +642,17 @@ static void do_normal_probe(sofia_profile_t *profile, switch_event_t *event) "left join sip_presence on " "(sip_registrations.sip_user=sip_presence.sip_user and sip_registrations.orig_server_host=sip_presence.sip_host and " "sip_registrations.profile_name=sip_presence.profile_name) " - "where sip_dialogs.presence_id='%q@%q' or (sip_registrations.sip_user='%q' and " + "where sip_dialogs.call_info_state != 'seized' and " + "(sip_registrations.profile_name='%q' or sip_registrations.presence_hosts like '%%%q%%') " + "and sip_dialogs.presence_id='%q@%q' or (sip_registrations.sip_user='%q' and " "(sip_registrations.orig_server_host='%q' or sip_registrations.sub_host='%q' " - "or sip_registrations.presence_hosts like '%%%q%%'))", - dh.status, dh.rpid, + "))", + dh.status, dh.rpid, switch_str_nil(sub_call_id), switch_sql_concat(), switch_sql_concat(), - probe_euser, probe_host, probe_euser, probe_host, probe_host, probe_host); + profile->name, probe_host, probe_euser, probe_host, probe_euser, probe_host, probe_host); + + + switch_assert(sql); if (mod_sofia_globals.debug_presence > 0) { @@ -654,11 +664,12 @@ static void do_normal_probe(sofia_profile_t *profile, switch_event_t *event) } sofia_glue_execute_sql_callback(profile, profile->ireg_mutex, sql, sofia_presence_resub_callback, &h); - + if (!h.rowcount) { h.noreg++; switch_safe_free(sql); + /* find ones with presence_id defined that are not registred */ sql = switch_mprintf("select sip_from_user, sip_from_host, 'Registered', '', '', " "uuid, state, direction, " @@ -707,13 +718,14 @@ static void do_normal_probe(sofia_profile_t *profile, switch_event_t *event) switch_safe_free(probe_user); } -static void do_dialog_probe(sofia_profile_t *profile, switch_event_t *event) +static void do_dialog_probe(switch_event_t *event) { // Received SUBSCRIBE for "dialog" events. // Return a complete list of dialogs for the monitored entity. char *sql; char *to = switch_event_get_header(event, "to"); char *probe_user = NULL, *probe_euser, *probe_host, *p; + sofia_profile_t *profile; if (!to || !(probe_user = strdup(to))) { return; @@ -748,7 +760,7 @@ static void do_dialog_probe(sofia_profile_t *profile, switch_event_t *event) "(sip_dialogs.sip_from_user = sip_registrations.sip_user " "and (sip_dialogs.sip_from_host = sip_registrations.orig_server_host or " "sip_dialogs.sip_from_host = sip_registrations.sip_host) ) " - "where sip_dialogs.presence_id='%q@%q' or (sip_registrations.sip_user='%q' and " + "where sip_dialogs.call_info_state != 'seized' and sip_dialogs.presence_id='%q@%q' or (sip_registrations.sip_user='%q' and " "(sip_registrations.orig_server_host='%q' or sip_registrations.sub_host='%q' " "or sip_registrations.presence_hosts like '%%%q%%'))", probe_euser, probe_host, @@ -827,9 +839,11 @@ static void actual_sofia_presence_event_handler(switch_event_t *event) char *sql = NULL; char *euser = NULL, *user = NULL, *host = NULL; char *call_info = switch_event_get_header(event, "presence-call-info"); + char *call_id = switch_event_get_header(event, "call-id"); char *presence_source = switch_event_get_header(event, "presence-source"); char *call_info_state = switch_event_get_header(event, "presence-call-info-state"); switch_console_callback_match_t *matches; + struct presence_helper helper = { 0 }; if (!mod_sofia_globals.running) { return; @@ -961,10 +975,10 @@ static void actual_sofia_presence_event_handler(switch_event_t *event) if (!probe_type || strcasecmp(probe_type, "dialog")) { /* NORMAL PROBE */ - do_normal_probe(profile, event); + do_normal_probe(event); } else { /* DIALOG PROBE */ - do_dialog_probe(profile, event); + do_dialog_probe(event); } } goto done; @@ -1025,7 +1039,7 @@ static void actual_sofia_presence_event_handler(switch_event_t *event) switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "PROCESS PRESENCE EVENT\n"); } - sync_sla(profile, euser, host, SWITCH_TRUE, SWITCH_TRUE); + sync_sla(profile, euser, host, SWITCH_TRUE, SWITCH_TRUE, call_id); } if (!strcmp(proto, "dp")) { @@ -1041,125 +1055,147 @@ static void actual_sofia_presence_event_handler(switch_event_t *event) switch_safe_free(sql); - if (dh.hits && presence_source && (!strcasecmp(presence_source, "register") || switch_stristr("register", status))) { + if (zstr(call_id) && (dh.hits && presence_source && (!strcasecmp(presence_source, "register") || switch_stristr("register", status)))) { goto done; } + if (zstr(call_id)) { - 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',sip_subscriptions.orig_proto,sip_subscriptions.full_to," - "sip_subscriptions.network_ip, sip_subscriptions.network_port " - "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) " + 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',sip_subscriptions.orig_proto,sip_subscriptions.full_to," + "sip_subscriptions.network_ip, sip_subscriptions.network_port " + "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 " - "sip_subscriptions.proto='%q' 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) ", + "where sip_subscriptions.version > -1 and sip_subscriptions.expires > -1 and " + "sip_subscriptions.proto='%q' and " + "(event='%q' or event='%q') and sub_to_user='%q' " + "and (sub_to_host='%q' or sub_to_host='%q' or sub_to_host='%q' or presence_hosts like '%%%q%%') " + "and (sip_subscriptions.profile_name = '%q' or presence_hosts like '%%%q%%') ", - switch_str_nil(status), switch_str_nil(rpid), host, - dh.status,dh.rpid,dh.presence_id, proto, - event_type, alt_event_type, euser, host, host, profile->name))) { - - struct presence_helper helper = { 0 }; + switch_str_nil(status), switch_str_nil(rpid), host, + dh.status,dh.rpid,dh.presence_id, proto, + event_type, alt_event_type, euser, host, profile->sipip, + profile->extsipip ? profile->extsipip : "N/A", host, profile->name, host); + } else { + 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',sip_subscriptions.orig_proto,sip_subscriptions.full_to," + "sip_subscriptions.network_ip, sip_subscriptions.network_port " + "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.event != 'line-seize' and " + "sip_subscriptions.profile_name = '%q' and sip_subscriptions.call_id='%q'", + + switch_str_nil(status), switch_str_nil(rpid), host, + dh.status,dh.rpid,dh.presence_id, profile->name, call_id); - 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); - } + } + - 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); - } + 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); + } - sofia_glue_execute_sql_callback(profile, profile->ireg_mutex, 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 (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); + } -#if 1 - if (event) { - const char *refresh = switch_event_get_header(event, "refresh"); - if (switch_true(refresh)) { - switch_event_t *s_event; + sofia_glue_execute_sql_callback(profile, profile->ireg_mutex, 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 0 + if (event) { + const char *refresh = switch_event_get_header(event, "refresh"); + if (switch_true(refresh)) { + switch_event_t *s_event; - if (switch_event_create(&s_event, SWITCH_EVENT_PRESENCE_PROBE) == SWITCH_STATUS_SUCCESS) { - switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "proto", SOFIA_CHAT_PROTO); - switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "login", profile->name); - switch_event_add_header(s_event, SWITCH_STACK_BOTTOM, "from", "%s@%s", euser, host); - switch_event_add_header(s_event, SWITCH_STACK_BOTTOM, "to", "%s@%s", euser, host); - switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "event_type", "presence"); - switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "alt_event_type", "dialog"); - switch_event_fire(&s_event); - } - } + if (switch_event_create(&s_event, SWITCH_EVENT_PRESENCE_PROBE) == SWITCH_STATUS_SUCCESS) { + switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "proto", SOFIA_CHAT_PROTO); + switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "login", profile->name); + switch_event_add_header(s_event, SWITCH_STACK_BOTTOM, "from", "%s@%s", euser, host); + switch_event_add_header(s_event, SWITCH_STACK_BOTTOM, "to", "%s@%s", euser, host); + switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "event_type", "presence"); + switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "alt_event_type", "dialog"); + switch_event_fire(&s_event); } + } + } #endif - if (!zstr((char *) helper.stream.data)) { - char *this_sql = (char *) helper.stream.data; - char *next = NULL; - char *last = NULL; + 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); + do { + if ((next = strchr(this_sql, ';'))) { + *next++ = '\0'; + while (*next == '\n' || *next == ' ' || *next == '\r') { + *next++ = '\0'; + } } - switch_safe_free(helper.stream.data); - helper.stream.data = NULL; - } - sofia_glue_release_profile(profile); + + 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); } + switch_safe_free(helper.stream.data); + helper.stream.data = NULL; + + sofia_glue_release_profile(profile); } - switch_console_free_matches(&matches); } + switch_console_free_matches(&matches); +} - done: - switch_safe_free(sql); - switch_safe_free(user); +done: +switch_safe_free(sql); +switch_safe_free(user); } static int EVENT_THREAD_RUNNING = 0; @@ -1331,7 +1367,7 @@ static int sofia_presence_resub_callback(void *pArg, int argc, char **argv, char char *status = argv[2]; char *rpid = argv[3]; char *proto = argv[4]; - + char *call_id = NULL; char *presence_id = NULL; char *to_user = NULL; char *uuid = NULL; @@ -1341,7 +1377,14 @@ static int sofia_presence_resub_callback(void *pArg, int argc, char **argv, char char to_buf[128] = ""; switch_event_header_t *hp; char *free_me = NULL; - int do_event = 1; + int do_event = 1, i; + + + if (mod_sofia_globals.debug_presence > 1) { + for (i = 0; i < argc; i++) { + switch_log_printf(SWITCH_CHANNEL_LOG,SWITCH_LOG_WARNING, "sofia_presence_resub_callback: %d [%s]=[%s]\n", i, columnNames[i], argv[i]); + } + } if (argc > 5) { uuid = argv[5]; @@ -1365,6 +1408,11 @@ static int sofia_presence_resub_callback(void *pArg, int argc, char **argv, char if ((p = strchr(free_me, '@'))) *p = '\0'; user = free_me; } + + if (argc > 16) { + call_id = argv[16]; + } + } if (!zstr(uuid) && !switch_ivr_uuid_exists(uuid)) { @@ -1392,6 +1440,10 @@ static int sofia_presence_resub_callback(void *pArg, int argc, char **argv, char switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Force-Direction", "inbound"); } + if (!zstr(call_id)) { + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "call-id", call_id); + } + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "resub", "true"); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "status", status); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "rpid", rpid); @@ -1512,12 +1564,12 @@ static int sofia_dialog_probe_callback(void *pArg, int argc, char **argv, char * if (mod_sofia_globals.debug_presence > 1) { for (i = 0; i < argc; i++) { - switch_log_printf(SWITCH_CHANNEL_LOG,SWITCH_LOG_DEBUG, "sofia_dialog_probe_callback: %d [%s]=[%s]\n", i, columnNames[i], argv[i]); + switch_log_printf(SWITCH_CHANNEL_LOG,SWITCH_LOG_WARNING, "sofia_dialog_probe_callback: %d [%s]=[%s]\n", i, columnNames[i], argv[i]); } } if (zstr(to_user) || zstr(contact_user)) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "sofia_dialog_probe_callback: not enough info to generate a dialog entry\n"); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "sofia_dialog_probe_callback: not enough info to generate a dialog entry\n"); return 0; } @@ -1606,28 +1658,28 @@ static int sofia_dialog_probe_callback(void *pArg, int argc, char **argv, char * data = ""; } tmp = switch_core_sprintf(h->pool, "%s" - "\n" - " %s\n" - " \n" - " sip:%s@%s%s\n" - " \n" - " \n" - " \n" - " \n" - " \n" - " sip:%s@%s\n" - " \n" - " \n" - "\n", - data, - uuid, call_id, to_tag, from_tag, direction, - state, - local_user, local_user, local_host, local_user_param, - local_user, local_host, - !strcasecmp(event_status, "hold") ? "no" : "yes", - remote_display_buf, remote_user, remote_host, - remote_uri - ); + "\n" + " %s\n" + " \n" + " sip:%s@%s%s\n" + " \n" + " \n" + " \n" + " \n" + " \n" + " sip:%s@%s\n" + " \n" + " \n" + "\n", + data, + uuid, call_id, to_tag, from_tag, direction, + state, + local_user, local_user, local_host, local_user_param, + local_user, local_host, + !strcasecmp(event_status, "hold") ? "no" : "yes", + remote_display_buf, remote_user, remote_host, + remote_uri + ); switch_core_hash_insert(h->hash, key, tmp); switch_safe_free(buf_to_free); @@ -1636,34 +1688,99 @@ static int sofia_dialog_probe_callback(void *pArg, int argc, char **argv, char * return 0; } -static void send_presence_notify(sofia_profile_t *profile, - const char *full_to, - const char *full_from, - const char *contact, - const char *expires, - const char *call_id, - const char *event, - const char *remote_ip, - const char *remote_port, - const char *ct, - const char *pl, - const char *call_info +#define send_presence_notify(_a,_b,_c,_d,_e,_f,_g,_h,_i,_j,_k,_l) \ +_send_presence_notify(_a,_b,_c,_d,_e,_f,_g,_h,_i,_j,_k,_l,__FILE__, __SWITCH_FUNC__, __LINE__) + +static void _send_presence_notify(sofia_profile_t *profile, + const char *full_to, + const char *full_from, + const char *o_contact, + const char *expires, + const char *call_id, + const char *event, + const char *remote_ip, + const char *remote_port, + const char *ct, + const char *pl, + const char *call_info, + const char *file, const char *func, int line ) { char sstr[128] = ""; nua_handle_t *nh; int exptime = 0; char expires_str[10] = ""; - char *tmp, *route = NULL; sip_cseq_t *cseq = NULL; uint32_t callsequence; uint32_t now = (uint32_t) switch_epoch_time_now(NULL); - const char *tp; char *our_contact = profile->url, *our_contact_dup = NULL; + sofia_destination_t *dst = NULL; + char *contact_str, *contact, *user_via = NULL; + char *route_uri = NULL, *o_contact_dup = NULL, *tmp; + const char *tp; + + tmp = (char *)o_contact; + o_contact_dup = sofia_glue_get_url_from_contact(tmp, 1); + + + if ((tp = switch_stristr("transport=", o_contact_dup))) { + tp += 10; + } + + if (zstr(tp)) { + tp = "udp"; + } + + if (!switch_stristr("transport=", our_contact)) { + our_contact_dup = switch_mprintf("<%s;transport=%s>", our_contact, tp); + our_contact = our_contact_dup; + } + + + if (!zstr(remote_ip) && sofia_glue_check_nat(profile, remote_ip)) { + char *ptr = NULL; + + if ((ptr = sofia_glue_find_parameter(o_contact, "transport="))) { + sofia_transport_t transport = sofia_glue_str2transport(ptr); + + switch (transport) { + case SOFIA_TRANSPORT_TCP: + contact_str = profile->tcp_public_contact; + break; + case SOFIA_TRANSPORT_TCP_TLS: + contact_str = profile->tls_public_contact; + break; + default: + contact_str = profile->public_url; + break; + } + user_via = sofia_glue_create_external_via(NULL, profile, transport); + } else { + user_via = sofia_glue_create_external_via(NULL, profile, SOFIA_TRANSPORT_UDP); + contact_str = profile->public_url; + } + + } else { + contact_str = our_contact; + } + + dst = sofia_glue_get_destination((char *) o_contact); + switch_assert(dst); + + contact = sofia_glue_get_url_from_contact(dst->contact, 1); + + if (dst->route_uri) { + route_uri = sofia_glue_strip_uri(dst->route_uri); + } else { + if (remote_ip && remote_port) { + route_uri = switch_mprintf("sip:%s:%s;transport=%s", remote_ip, remote_port, tp); + } + } + if (expires) { long ltmp = atol(expires); - + if (ltmp > 0) { exptime = (ltmp - now); } else { @@ -1672,6 +1789,39 @@ static void send_presence_notify(sofia_profile_t *profile, } + + if (exptime <= 0) { + switch_snprintf(sstr, sizeof(sstr), "terminated;reason=noresource"); + } else { + switch_snprintf(sstr, sizeof(sstr), "active;expires=%u", (unsigned) exptime); + } + + if (mod_sofia_globals.debug_presence > 1) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "SEND PRES NOTIFY:\n" + "file[%s]\nfunc[%s]\nline[%d]\n" + "profile[%s]\nvia[%s]\nip[%s]\nport[%s]\nroute[%s]\ncontact[%s]\nto[%s]\nfrom[%s]\nurl[%s]\ncall_id[%s]\nexpires_str[%s]\n" + "event[%s]\nct[%s]\npl[%s]\ncall_info[%s]\nexptime[%ld]\n", + file, func, line, + profile->name, + switch_str_nil(user_via), + remote_ip, + remote_port, + route_uri, + o_contact, + full_to, + full_from, + contact, + call_id, + expires_str, + event, + switch_str_nil(ct), + switch_str_nil(pl), + switch_str_nil(call_info), + (long)exptime + ); + } + + switch_mutex_lock(profile->ireg_mutex); if (!profile->cseq_base) { profile->cseq_base = (now - 1312693200) * 10; @@ -1680,64 +1830,20 @@ static void send_presence_notify(sofia_profile_t *profile, switch_mutex_unlock(profile->ireg_mutex); - nh = nua_handle(profile->nua, NULL, TAG_END()); + nh = nua_handle(profile->nua, NULL, NUTAG_URL(contact), SIPTAG_CONTACT_STR(contact_str), TAG_END()); cseq = sip_cseq_create(nh->nh_home, callsequence, SIP_METHOD_NOTIFY); nua_handle_bind(nh, &mod_sofia_globals.destroy_private); - - if (exptime <= 0) { - switch_snprintf(sstr, sizeof(sstr), "terminated;reason=noresource"); - } else { - switch_snprintf(sstr, sizeof(sstr), "active;expires=%u", (unsigned) exptime); - } - tmp = (char *)contact; - contact = sofia_glue_get_url_from_contact(tmp, 0); - - if ((tp = switch_stristr("transport=", contact))) { - tp += 10; - } - - if (zstr(tp)) { - tp = "udp"; - } - - if (remote_ip && remote_port) { - route = switch_mprintf("sip:%s:%s;transport=%s", remote_ip, remote_port, tp); - } - - if (!switch_stristr("transport=", our_contact)) { - our_contact_dup = switch_mprintf("<%s;transport=%s>", our_contact, tp); - our_contact = our_contact_dup; - } - - if (mod_sofia_globals.debug_presence > 1) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "SEND PRES NOTIFY:\n" - "route[%s]\ncontact[%s]\nto[%s]\nfrom[%s]\nurl[%s]\ncall_id[%s]\nexpires_str[%s]\n" - "event[%s]\nct[%s]\npl[%s]\ncall_info[%s]\nexptime[%ld]\n", - route, - contact, - full_to, - full_from, - our_contact, - call_id, - expires_str, - event, - switch_str_nil(ct), - switch_str_nil(pl), - switch_str_nil(call_info), - (long)exptime - ); - - - } nua_notify(nh, NUTAG_NEWSUB(1), - TAG_IF(route, NUTAG_PROXY(route)), - NUTAG_URL(contact), + TAG_IF(dst->route_uri, NUTAG_PROXY(route_uri)), TAG_IF(dst->route, SIPTAG_ROUTE_STR(dst->route)), + TAG_IF(user_via, SIPTAG_VIA_STR(user_via)), + + SIPTAG_FROM_STR(full_to), SIPTAG_TO_STR(full_from), - SIPTAG_CONTACT_STR(our_contact), + SIPTAG_CALL_ID_STR(call_id), TAG_IF(*expires_str, SIPTAG_EXPIRES_STR(expires_str)), SIPTAG_SUBSCRIPTION_STATE_STR(sstr), @@ -1749,9 +1855,15 @@ static void send_presence_notify(sofia_profile_t *profile, SIPTAG_CSEQ(cseq), TAG_END()); - switch_safe_free(route); - switch_safe_free(our_contact_dup); + + switch_safe_free(route_uri); + switch_safe_free(contact); + + sofia_glue_free_destination(dst); + switch_safe_free(user_via); + switch_safe_free(o_contact_dup); + } @@ -1779,11 +1891,18 @@ static int sofia_dialog_probe_notify_callback(void *pArg, int argc, char **argv, const char *pl = NULL; const char *ct = "application/dialog-info+xml"; + if (mod_sofia_globals.debug_presence > 0) { + int i; + for(i = 0; i < argc; i++) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "arg %d[%s] = [%s]\n", i, columnNames[i], argv[i]); + } + } + if (mod_sofia_globals.debug_presence > 0) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, - "SEND DIALOG\nTo: \t%s@%s\nFrom: \t%s@%s\nCall-ID: \t%s\n", - user, host, user, host, call_id); + "SEND DIALOG\nTo: \t%s@%s\nFrom: \t%s@%s\nCall-ID: \t%s\n", + user, host, user, host, call_id); } to = switch_mprintf("sip:%s@%s", user, host); @@ -1870,7 +1989,7 @@ static char *translate_rpid(char *in) r = "busy"; } - end: + end: return r; } @@ -2510,6 +2629,14 @@ static int sofia_presence_mwi_callback(void *pArg, int argc, char **argv, char * struct mwi_helper *h = (struct mwi_helper *) pArg; sofia_profile_t *ext_profile = NULL, *profile = h->profile; + + if (mod_sofia_globals.debug_presence > 0) { + int i; + for(i = 0; i < argc; i++) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "arg %d[%s] = [%s]\n", i, columnNames[i], argv[i]); + } + } + if (profile_name && strcasecmp(profile_name, h->profile->name)) { if ((ext_profile = sofia_glue_find_profile(profile_name))) { profile = ext_profile; @@ -2581,6 +2708,7 @@ static int broadsoft_sla_notify_callback(void *pArg, int argc, char **argv, char char *event = argv[4]; int i; + if (mod_sofia_globals.debug_sla > 1) { for (i = 0; i < argc; i++) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "SLA3: %d [%s]=[%s]\n", i, columnNames[i], argv[i]); @@ -2615,6 +2743,8 @@ static int broadsoft_sla_notify_callback(void *pArg, int argc, char **argv, char } send_presence_notify(sh->profile, argv[5], argv[6], argv[7], argv[8], call_id, event, argv[9], argv[10], NULL, NULL, tmp); + + sh->total++; return 0; } @@ -2712,11 +2842,12 @@ static int broadsoft_sla_gather_state_callback(void *pArg, int argc, char **argv return 0; } -static void sync_sla(sofia_profile_t *profile, const char *to_user, const char *to_host, switch_bool_t clear, switch_bool_t unseize) +static int sync_sla(sofia_profile_t *profile, const char *to_user, const char *to_host, switch_bool_t clear, switch_bool_t unseize, const char *call_id) { struct state_helper *sh; switch_memory_pool_t *pool; char *sql; + int total = 0; switch_core_new_memory_pool(&pool); sh = switch_core_alloc(pool, sizeof(*sh)); @@ -2724,8 +2855,9 @@ static void sync_sla(sofia_profile_t *profile, const char *to_user, const char * switch_core_hash_init(&sh->hash, sh->pool); sql = switch_mprintf("select sip_from_user,sip_from_host,call_info,call_info_state,uuid from sip_dialogs " - "where call_info_state is not null and hostname='%q' and ((sip_from_user='%q' and sip_from_host='%q') or presence_id='%q@%q')", - mod_sofia_globals.hostname, to_user, to_host, to_user, to_host); + "where call_info_state is not null and hostname='%q' and ((sip_from_user='%q' and sip_from_host='%q') or presence_id='%q@%q') " + "and profile_name='%q'", + mod_sofia_globals.hostname, to_user, to_host, to_user, to_host, profile->name); if (mod_sofia_globals.debug_sla > 1) { @@ -2735,26 +2867,44 @@ static void sync_sla(sofia_profile_t *profile, const char *to_user, const char * switch_safe_free(sql); - if (unseize) { - sql = switch_mprintf("select call_id,expires,sub_to_user,sub_to_host,event,full_to,full_from,contact,expires,network_ip,network_port " - "from sip_subscriptions " - "where version > -1 and expires > -1 and hostname='%q' " - "and sub_to_user='%q' and sub_to_host='%q' " - "and (event='call-info' or event='line-seize')", mod_sofia_globals.hostname, to_user, to_host); - } else { - sql = switch_mprintf("select call_id,expires,sub_to_user,sub_to_host,event,full_to,full_from,contact,expires,network_ip,network_port " - "from sip_subscriptions " - "where version > -1 and expires > -1 and hostname='%q' " - "and sub_to_user='%q' and sub_to_host='%q' " "and (event='call-info')", mod_sofia_globals.hostname, to_user, to_host); - } + if (!zstr(call_id)) { + if (unseize) { + sql = switch_mprintf("select call_id,expires,sub_to_user,sub_to_host,event,full_to,full_from,contact,expires,network_ip,network_port " + "from sip_subscriptions where call_id='%q' and profile_name='%q')", call_id, profile->name); + + } else { + sql = switch_mprintf("select call_id,expires,sub_to_user,sub_to_host,event,full_to,full_from,contact,expires,network_ip,network_port " + "from sip_subscriptions where call_id='%q' and profile_name='%q'", call_id, profile->name); + } + + } else { + + if (unseize) { + sql = switch_mprintf("select call_id,expires,sub_to_user,sub_to_host,event,full_to,full_from,contact,expires,network_ip,network_port " + "from sip_subscriptions " + "where version > -1 and expires > -1 and hostname='%q' " + "and sub_to_user='%q' and sub_to_host='%q' " + "and (event='call-info' or event='line-seize') and (profile_name='%q' or presence_hosts like '%%%q%%')", + mod_sofia_globals.hostname, to_user, to_host, profile->name, to_host); + } else { + sql = switch_mprintf("select call_id,expires,sub_to_user,sub_to_host,event,full_to,full_from,contact,expires,network_ip,network_port " + "from sip_subscriptions " + "where version > -1 and expires > -1 and hostname='%q' " + "and sub_to_user='%q' and sub_to_host='%q' " "and (event='call-info') and " + "(profile_name='%q' or presence_hosts like '%%%q%%')", + mod_sofia_globals.hostname, to_user, to_host, profile->name, to_host); + } + } if (mod_sofia_globals.debug_sla > 1) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "PRES SQL %s\n", sql); } + sh->profile = profile; sofia_glue_execute_sql_callback(profile, profile->ireg_mutex, sql, broadsoft_sla_notify_callback, sh); switch_safe_free(sql); + total = sh->total; sh = NULL; switch_core_destroy_memory_pool(&pool); @@ -2771,12 +2921,14 @@ static void sync_sla(sofia_profile_t *profile, const char *to_user, const char * sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE); } + return total; + } void sofia_presence_handle_sip_i_subscribe(int status, char const *phrase, nua_t *nua, sofia_profile_t *profile, nua_handle_t *nh, sofia_private_t *sofia_private, sip_t const *sip, - sofia_dispatch_event_t *de, + sofia_dispatch_event_t *de, tagi_t tags[]) { @@ -2818,7 +2970,8 @@ void sofia_presence_handle_sip_i_subscribe(int status, to = sip->sip_to; contact = sip->sip_contact; - if (!(contact_str = sofia_glue_gen_contact_str(profile, sip, de, &np))) { + np.fs_path = 1; + if (!(contact_str = sofia_glue_gen_contact_str(profile, sip, nh, de, &np))) { nua_respond(nh, 481, "INVALID SUBSCRIPTION", TAG_END()); return; } @@ -2937,9 +3090,9 @@ void sofia_presence_handle_sip_i_subscribe(int status, sstr = switch_mprintf("active;expires=%ld", exp_delta); sql = switch_mprintf("update sip_subscriptions " - "set expires=%ld,version=0 " + "set version=0,expires=%ld,contact='%q' " "where call_id='%q'", - (long) switch_epoch_time_now(NULL) + exp_delta, + (long) switch_epoch_time_now(NULL) + exp_delta, contact_str, call_id); if (mod_sofia_globals.debug_presence > 0 || mod_sofia_globals.debug_sla > 0) { @@ -2950,20 +3103,20 @@ void sofia_presence_handle_sip_i_subscribe(int status, sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE); } else { - sql = switch_mprintf("delete from sip_subscriptions where call_id='%q'", call_id, mod_sofia_globals.hostname); - - if (mod_sofia_globals.debug_presence > 0 || mod_sofia_globals.debug_sla > 0) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, - "sub del sql: %s\n", sql); - } - - switch_mutex_lock(profile->ireg_mutex); - switch_assert(sql != NULL); - sofia_glue_actually_execute_sql(profile, sql, NULL); - switch_safe_free(sql); - if (sub_state == nua_substate_terminated) { - sstr = switch_mprintf("terminated"); + sql = switch_mprintf("delete from sip_subscriptions where call_id='%q'", call_id, mod_sofia_globals.hostname); + + if (mod_sofia_globals.debug_presence > 0 || mod_sofia_globals.debug_sla > 0) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, + "sub del sql: %s\n", sql); + } + + switch_mutex_lock(profile->ireg_mutex); + switch_assert(sql != NULL); + sofia_glue_actually_execute_sql(profile, sql, NULL); + switch_safe_free(sql); + + sstr = switch_mprintf("terminated;reason=noresource"); } else { sip_accept_t *ap = sip->sip_accept; char accept[256] = ""; @@ -2980,7 +3133,7 @@ void sofia_presence_handle_sip_i_subscribe(int status, "(proto,sip_user,sip_host,sub_to_user,sub_to_host,presence_hosts,event,contact,call_id,full_from," "full_via,expires,user_agent,accept,profile_name,hostname,network_port,network_ip, orig_proto, full_to) " "values ('%q','%q','%q','%q','%q','%q','%q','%q','%q','%q','%q',%ld,'%q','%q','%q','%q','%d','%q','%q','%q;tag=%q')", - proto, from_user, from_host, to_user, to_host, profile->presence_hosts ? profile->presence_hosts : to_host, + proto, from_user, from_host, to_user, to_host, profile->presence_hosts ? profile->presence_hosts : "", event, contact_str, call_id, full_from, full_via, (long) switch_epoch_time_now(NULL) + exp_delta, full_agent, accept, profile->name, mod_sofia_globals.hostname, @@ -3078,10 +3231,11 @@ void sofia_presence_handle_sip_i_subscribe(int status, p++; } +#if 0 nua_notify(nh, SIPTAG_EXPIRES_STR("0"), SIPTAG_SUBSCRIPTION_STATE_STR(sstr), TAG_IF(full_call_info, SIPTAG_CALL_INFO_STR(full_call_info)), TAG_END()); - +#endif if (!strcasecmp(event, "line-seize")) { if (mod_sofia_globals.debug_sla > 1) { @@ -3098,7 +3252,7 @@ void sofia_presence_handle_sip_i_subscribe(int status, } sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE); - sync_sla(profile, to_user, to_host, SWITCH_FALSE, SWITCH_FALSE); + sync_sla(profile, to_user, to_host, SWITCH_FALSE, SWITCH_FALSE, NULL); } su_free(nh->nh_home, full_call_info); @@ -3125,8 +3279,8 @@ void sofia_presence_handle_sip_i_subscribe(int status, sql = switch_mprintf("delete from sip_dialogs where ((sip_from_user='%q' and sip_from_host='%q') or presence_id='%q@%q') " - "and call_info_state='seized'", - to_user, to_host, to_user, to_host); + "and call_info_state='seized' and profile_name='%q'", + to_user, to_host, to_user, to_host, profile->name); if (mod_sofia_globals.debug_sla > 1) { @@ -3135,20 +3289,21 @@ void sofia_presence_handle_sip_i_subscribe(int status, sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE); now = switch_epoch_time_now(NULL); - sql = switch_mprintf("insert into sip_dialogs (sip_from_user,sip_from_host,call_info,call_info_state,hostname,expires,rcd) " - "values ('%q','%q','%q','seized','%q',%ld,%ld)", - to_user, to_host, switch_str_nil(p), mod_sofia_globals.hostname, switch_epoch_time_now(NULL) + exp_delta, (long)now); + sql = switch_mprintf("insert into sip_dialogs (sip_from_user,sip_from_host,call_info,call_info_state,hostname,expires,rcd,profile_name) " + "values ('%q','%q','%q','seized','%q',%ld,%ld,'%q')", + to_user, to_host, switch_str_nil(p), mod_sofia_globals.hostname, + switch_epoch_time_now(NULL) + exp_delta, (long)now, profile->name); if (mod_sofia_globals.debug_sla > 1) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "SEIZE SQL %s\n", sql); } sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE); - sync_sla(profile, to_user, to_host, SWITCH_FALSE, SWITCH_FALSE); + sync_sla(profile, to_user, to_host, SWITCH_FALSE, SWITCH_FALSE, NULL); su_free(nh->nh_home, full_call_info); } } else if (!strcasecmp(event, "call-info")) { - sync_sla(profile, to_user, to_host, SWITCH_FALSE, SWITCH_FALSE); + sync_sla(profile, to_user, to_host, SWITCH_FALSE, SWITCH_FALSE, call_id); } } @@ -3170,66 +3325,78 @@ void sofia_presence_handle_sip_i_subscribe(int status, end: - if (to_user && (strstr(to_user, "ext+") || strstr(to_user, "user+"))) { - char protocol[80]; - char *p; + if (strcasecmp(event, "call-info") && strcasecmp(event, "line-seize")) { - switch_copy_string(protocol, to_user, sizeof(protocol)); - if ((p = strchr(protocol, '+'))) { - *p = '\0'; - } + if (to_user && (strstr(to_user, "ext+") || strstr(to_user, "user+"))) { + char protocol[80]; + char *p; - if (switch_event_create(&sevent, SWITCH_EVENT_PRESENCE_IN) == SWITCH_STATUS_SUCCESS) { - switch_event_add_header_string(sevent, SWITCH_STACK_BOTTOM, "proto", protocol); - if (!zstr(orig_proto)) { - switch_event_add_header_string(sevent, SWITCH_STACK_BOTTOM, "orig_proto", orig_proto); + switch_copy_string(protocol, to_user, sizeof(protocol)); + if ((p = strchr(protocol, '+'))) { + *p = '\0'; } - switch_event_add_header_string(sevent, SWITCH_STACK_BOTTOM, "login", profile->name); - switch_event_add_header(sevent, SWITCH_STACK_BOTTOM, "from", "%s@%s", to_user, to_host); - switch_event_add_header_string(sevent, SWITCH_STACK_BOTTOM, "rpid", "active"); - switch_event_add_header_string(sevent, SWITCH_STACK_BOTTOM, "status", "Click To Call"); - switch_event_fire(&sevent); - } - } else if (to_user && (strcasecmp(proto, SOFIA_CHAT_PROTO) != 0)) { - if (switch_event_create(&sevent, SWITCH_EVENT_PRESENCE_PROBE) == SWITCH_STATUS_SUCCESS) { - switch_event_add_header_string(sevent, SWITCH_STACK_BOTTOM, "proto", proto); - if (!zstr(orig_proto)) { - switch_event_add_header_string(sevent, SWITCH_STACK_BOTTOM, "orig_proto", orig_proto); + if (switch_event_create(&sevent, SWITCH_EVENT_PRESENCE_IN) == SWITCH_STATUS_SUCCESS) { + switch_event_add_header_string(sevent, SWITCH_STACK_BOTTOM, "proto", protocol); + if (!zstr(orig_proto)) { + switch_event_add_header_string(sevent, SWITCH_STACK_BOTTOM, "orig_proto", orig_proto); + } + switch_event_add_header_string(sevent, SWITCH_STACK_BOTTOM, "login", profile->name); + switch_event_add_header(sevent, SWITCH_STACK_BOTTOM, "from", "%s@%s", to_user, to_host); + switch_event_add_header_string(sevent, SWITCH_STACK_BOTTOM, "rpid", "active"); + switch_event_add_header_string(sevent, SWITCH_STACK_BOTTOM, "status", "Click To Call"); + switch_event_fire(&sevent); } - switch_event_add_header_string(sevent, SWITCH_STACK_BOTTOM, "login", profile->name); - switch_event_add_header(sevent, SWITCH_STACK_BOTTOM, "from", "%s@%s", from_user, from_host); - switch_event_add_header(sevent, SWITCH_STACK_BOTTOM, "to", "%s%s%s@%s", proto, "+", to_user, to_host); - switch_event_add_header_string(sevent, SWITCH_STACK_BOTTOM, "proto-specific-event-name", event); - switch_event_add_header_string(sevent, SWITCH_STACK_BOTTOM, "expires", exp_delta_str); - switch_event_add_header_string(sevent, SWITCH_STACK_BOTTOM, "event_type", "presence"); - switch_event_add_header_string(sevent, SWITCH_STACK_BOTTOM, "alt_event_type", "dialog"); - switch_event_add_header_string(sevent, SWITCH_STACK_BOTTOM, "expires", exp_delta_str); - switch_event_fire(&sevent); + + } else if (to_user && (strcasecmp(proto, SOFIA_CHAT_PROTO) != 0)) { + if (switch_event_create(&sevent, SWITCH_EVENT_PRESENCE_PROBE) == SWITCH_STATUS_SUCCESS) { + switch_event_add_header_string(sevent, SWITCH_STACK_BOTTOM, "proto", proto); + if (!zstr(orig_proto)) { + switch_event_add_header_string(sevent, SWITCH_STACK_BOTTOM, "orig_proto", orig_proto); + } + switch_event_add_header_string(sevent, SWITCH_STACK_BOTTOM, "login", profile->name); + switch_event_add_header(sevent, SWITCH_STACK_BOTTOM, "from", "%s@%s", from_user, from_host); + switch_event_add_header(sevent, SWITCH_STACK_BOTTOM, "to", "%s%s%s@%s", proto, "+", to_user, to_host); + switch_event_add_header_string(sevent, SWITCH_STACK_BOTTOM, "proto-specific-event-name", event); + switch_event_add_header_string(sevent, SWITCH_STACK_BOTTOM, "expires", exp_delta_str); + switch_event_add_header_string(sevent, SWITCH_STACK_BOTTOM, "event_type", "presence"); + switch_event_add_header_string(sevent, SWITCH_STACK_BOTTOM, "alt_event_type", "dialog"); + switch_event_add_header_string(sevent, SWITCH_STACK_BOTTOM, "expires", exp_delta_str); + switch_event_fire(&sevent); - } - } else { - if (switch_event_create(&sevent, SWITCH_EVENT_PRESENCE_PROBE) == SWITCH_STATUS_SUCCESS) { - if (!strcasecmp(event, "dialog")) { - switch_event_add_header_string(sevent, SWITCH_STACK_BOTTOM, "probe-type", "dialog"); } + } else { - switch_event_add_header_string(sevent, SWITCH_STACK_BOTTOM, "proto", SOFIA_CHAT_PROTO); - switch_event_add_header_string(sevent, SWITCH_STACK_BOTTOM, "login", profile->name); - switch_event_add_header(sevent, SWITCH_STACK_BOTTOM, "from", "%s@%s", from_user, from_host); - switch_event_add_header(sevent, SWITCH_STACK_BOTTOM, "to", "%s@%s", to_user, to_host); - switch_event_add_header_string(sevent, SWITCH_STACK_BOTTOM, "proto-specific-event-name", event); - switch_event_add_header_string(sevent, SWITCH_STACK_BOTTOM, "expires", exp_delta_str); - switch_event_add_header_string(sevent, SWITCH_STACK_BOTTOM, "event_type", "presence"); - switch_event_add_header_string(sevent, SWITCH_STACK_BOTTOM, "alt_event_type", "dialog"); - switch_event_add_header_string(sevent, SWITCH_STACK_BOTTOM, "expires", exp_delta_str); - switch_event_add_header_string(sevent, SWITCH_STACK_BOTTOM, "sub-call-id", call_id); - switch_event_fire(&sevent); + if (!strcasecmp(event, "dialog")) { + if (switch_event_create(&sevent, SWITCH_EVENT_PRESENCE_PROBE) == SWITCH_STATUS_SUCCESS) { + switch_event_add_header_string(sevent, SWITCH_STACK_BOTTOM, "probe-type", "dialog"); + switch_event_add_header_string(sevent, SWITCH_STACK_BOTTOM, "proto", SOFIA_CHAT_PROTO); + switch_event_add_header_string(sevent, SWITCH_STACK_BOTTOM, "login", profile->name); + switch_event_add_header(sevent, SWITCH_STACK_BOTTOM, "from", "%s@%s", from_user, from_host); + switch_event_add_header(sevent, SWITCH_STACK_BOTTOM, "to", "%s@%s", to_user, to_host); + switch_event_add_header_string(sevent, SWITCH_STACK_BOTTOM, "proto-specific-event-name", event); + switch_event_add_header_string(sevent, SWITCH_STACK_BOTTOM, "expires", exp_delta_str); + switch_event_add_header_string(sevent, SWITCH_STACK_BOTTOM, "event_type", "presence"); + switch_event_add_header_string(sevent, SWITCH_STACK_BOTTOM, "alt_event_type", "dialog"); + switch_event_add_header_string(sevent, SWITCH_STACK_BOTTOM, "expires", exp_delta_str); + switch_event_add_header_string(sevent, SWITCH_STACK_BOTTOM, "sub-call-id", call_id); + switch_event_fire(&sevent); + } + } else { + if (switch_event_create(&sevent, SWITCH_EVENT_PRESENCE_IN) == SWITCH_STATUS_SUCCESS) { + switch_event_add_header_string(sevent, SWITCH_STACK_BOTTOM, "proto", SOFIA_CHAT_PROTO); + switch_event_add_header_string(sevent, SWITCH_STACK_BOTTOM, "login", profile->name); + switch_event_add_header_string(sevent, SWITCH_STACK_BOTTOM, "presence-source", "subscribe"); + switch_event_add_header(sevent, SWITCH_STACK_BOTTOM, "from", "%s@%s", from_user, from_host); + switch_event_add_header_string(sevent, SWITCH_STACK_BOTTOM, "rpid", "unknown"); + switch_event_add_header_string(sevent, SWITCH_STACK_BOTTOM, "status", "Registered"); + switch_event_add_header_string(sevent, SWITCH_STACK_BOTTOM, "call-id", call_id); + switch_event_fire(&sevent); + } + } } } - - if (event) { su_free(nh->nh_home, event); } @@ -3347,6 +3514,14 @@ static int sofia_presence_send_sql(void *pArg, int argc, char **argv, char **col { struct pres_sql_cb *cb = (struct pres_sql_cb *) pArg; + + if (mod_sofia_globals.debug_presence > 0) { + int i; + for(i = 0; i < argc; i++) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "arg %d[%s] = [%s]\n", i, columnNames[i], argv[i]); + } + } + send_presence_notify(cb->profile, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8], argv[9], NULL); cb->ttl++; @@ -3367,7 +3542,7 @@ uint32_t sofia_presence_contact_count(sofia_profile_t *profile, const char *cont } void sofia_presence_handle_sip_i_publish(nua_t *nua, sofia_profile_t *profile, nua_handle_t *nh, sofia_private_t *sofia_private, sip_t const *sip, - sofia_dispatch_event_t *de, + sofia_dispatch_event_t *de, tagi_t tags[]) { @@ -3392,7 +3567,7 @@ void sofia_presence_handle_sip_i_publish(nua_t *nua, sofia_profile_t *profile, n from = sip->sip_from; payload = sip->sip_payload; - contact_str = sofia_glue_gen_contact_str(profile, sip, de, NULL); + contact_str = sofia_glue_gen_contact_str(profile, sip, nh, de, NULL); if (from) { from_user = (char *) from->a_url->url_user; @@ -3542,7 +3717,7 @@ void sofia_presence_set_hash_key(char *hash_key, int32_t len, sip_t const *sip) void sofia_presence_handle_sip_i_message(int status, char const *phrase, nua_t *nua, sofia_profile_t *profile, nua_handle_t *nh, sofia_private_t *sofia_private, sip_t const *sip, - sofia_dispatch_event_t *de, + sofia_dispatch_event_t *de, tagi_t tags[]) { if (sip) { diff --git a/src/mod/endpoints/mod_sofia/sofia_reg.c b/src/mod/endpoints/mod_sofia/sofia_reg.c index ba159c7f7f..14fbfcad7b 100644 --- a/src/mod/endpoints/mod_sofia/sofia_reg.c +++ b/src/mod/endpoints/mod_sofia/sofia_reg.c @@ -1521,7 +1521,7 @@ uint8_t sofia_reg_handle_register(nua_t *nua, sofia_profile_t *profile, nua_hand "user_agent,server_user,server_host,profile_name,hostname,network_ip,network_port,sip_username,sip_realm," "mwi_user,mwi_host, orig_server_host, orig_hostname, sub_host) " "values ('%q','%q', '%q','%q','%q','%q', '%q', %ld, '%q', '%q', '%q', '%q', '%q', '%q', '%q','%q','%q','%q','%q','%q','%q','%q')", - call_id, to_user, reg_host, profile->presence_hosts ? profile->presence_hosts : reg_host, + call_id, to_user, reg_host, profile->presence_hosts ? profile->presence_hosts : "", contact_str, reg_desc, rpid, (long) switch_epoch_time_now(NULL) + (long) exptime + 60, agent, from_user, guess_ip4, profile->name, mod_sofia_globals.hostname, network_ip, network_port_c, username, realm, mwi_user, mwi_host, guess_ip4, mod_sofia_globals.hostname, sub_host); @@ -1553,7 +1553,7 @@ uint8_t sofia_reg_handle_register(nua_t *nua, sofia_profile_t *profile, nua_hand switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "profile-name", profile->name); switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "from-user", to_user); switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "from-host", reg_host); - switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "presence-hosts", profile->presence_hosts ? profile->presence_hosts : reg_host); + switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "presence-hosts", profile->presence_hosts ? profile->presence_hosts : "n/a"); switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "contact", contact_str); switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "call-id", call_id); switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "rpid", rpid); @@ -1576,38 +1576,6 @@ uint8_t sofia_reg_handle_register(nua_t *nua, sofia_profile_t *profile, nua_hand "Register:\nFrom: [%s@%s]\nContact: [%s]\nExpires: [%ld]\n", to_user, reg_host, contact_str, (long) exptime); } -#if 0 - if (switch_event_create(&event, SWITCH_EVENT_PRESENCE_IN) == SWITCH_STATUS_SUCCESS) { - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "proto", SOFIA_CHAT_PROTO); - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "rpid", rpid); - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "login", profile->url); - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "user-agent", - (sip && sip->sip_user_agent) ? sip->sip_user_agent->g_string : "unknown"); - switch_event_add_header(event, SWITCH_STACK_BOTTOM, "from", "%s@%s", to_user, sub_host); - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "status", "Registered"); - 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, sub_host); - switch_event_add_header(event, SWITCH_STACK_BOTTOM, "to", "%s@%s", to_user, sub_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 - - } else { int send = 1; @@ -1629,18 +1597,7 @@ uint8_t sofia_reg_handle_register(nua_t *nua, sofia_profile_t *profile, nua_hand switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "event_type", "presence"); switch_event_fire(&event); } -#if 0 - if (switch_event_create(&event, SWITCH_EVENT_PRESENCE_OUT) == 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(event, SWITCH_STACK_BOTTOM, "from", "%s+%s@%s", SOFIA_CHAT_PROTO, to_user, sub_host); - - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "status", "unavailable"); - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "rpid", rpid); - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "event_type", "presence"); - switch_event_fire(&event); - } -#endif + if (multi_reg) { char *icontact, *p;