From 17cb6a22b31d96a3ef2246aaaa73eaeb0f1bbc29 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Fri, 2 Mar 2012 16:42:05 -0600 Subject: [PATCH] add some defensive code to allow support for yealink in SCA mode even when its broken --- src/mod/endpoints/mod_sofia/sofia.c | 74 +++++++++++- src/mod/endpoints/mod_sofia/sofia_glue.c | 4 +- src/mod/endpoints/mod_sofia/sofia_presence.c | 117 +++++++++++++++---- 3 files changed, 164 insertions(+), 31 deletions(-) diff --git a/src/mod/endpoints/mod_sofia/sofia.c b/src/mod/endpoints/mod_sofia/sofia.c index b84cc00f4a..1ebddbc87d 100644 --- a/src/mod/endpoints/mod_sofia/sofia.c +++ b/src/mod/endpoints/mod_sofia/sofia.c @@ -4806,6 +4806,7 @@ static void sofia_handle_sip_r_invite(switch_core_session_t *session, int status if (channel && sip->sip_call_info) { char *p; call_info = sip_header_as_string(nua_handle_home(nh), (void *) sip->sip_call_info); + if (switch_stristr("appearance", call_info)) { switch_channel_set_variable(channel, "presence_call_info_full", call_info); if ((p = strchr(call_info, ';'))) { @@ -4842,10 +4843,15 @@ static void sofia_handle_sip_r_invite(switch_core_session_t *session, int status if (mod_sofia_globals.debug_sla > 1) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "QUERY SQL %s\n", sql); } - + sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE); + + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Auto-Fixing Broken SLA [;%s]\n", + sip->sip_from->a_url->url_host, buf); + switch_channel_set_variable_printf(channel, "presence_call_info_full", ";%s", sip->sip_from->a_url->url_host, buf); + switch_channel_set_variable(channel, "presence_call_info", buf); } - } + } } } @@ -8021,12 +8027,67 @@ void sofia_handle_sip_i_invite(nua_t *nua, sofia_profile_t *profile, nua_handle_ if ((call_info = sip_call_info(sip))) { call_info_str = sip_header_as_string(nh->nh_home, (void *) call_info); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "WTF %s\n", call_info_str); + + if (sofia_test_pflag(profile, PFLAG_MANAGE_SHARED_APPEARANCE) && switch_stristr("appearance", call_info_str)) { + char *p; + + switch_channel_set_variable(channel, "presence_call_info_full", call_info_str); + if ((p = strchr(call_info_str, ';'))) { + p++; + switch_channel_set_variable(channel, "presence_call_info", p); + } + } + if (call_info->ci_params && (msg_params_find(call_info->ci_params, "answer-after=0"))) { switch_channel_set_variable(channel, "sip_auto_answer_detected", "true"); } switch_channel_set_variable(channel, "sip_call_info", call_info_str); + } else if (sofia_test_pflag(profile, PFLAG_MANAGE_SHARED_APPEARANCE)) { + char buf[128] = ""; + char *sql; + char *state = "progressing"; + + if (sip && + sip->sip_from && sip->sip_from->a_url && sip->sip_from->a_url->url_user && sip->sip_from->a_url->url_host && + sip->sip_to && sip->sip_to->a_url && sip->sip_to->a_url->url_user && sip->sip_to->a_url->url_host) { + sql = + switch_mprintf("select 'appearance-index=1' from sip_subscriptions where expires > -1 and hostname='%q' and event='call-info' and " + "sub_to_user='%q' and sub_to_host='%q'", mod_sofia_globals.hostname, sip->sip_to->a_url->url_user, + sip->sip_from->a_url->url_host); + sofia_glue_execute_sql2str(profile, profile->ireg_mutex, sql, buf, sizeof(buf)); + + if (mod_sofia_globals.debug_sla > 1) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "QUERY SQL %s [%s]\n", sql, buf); + } + free(sql); + + if (!zstr(buf)) { + sql = switch_mprintf("update sip_dialogs set call_info='%q',call_info_state='%q' " + "where uuid='%q'", buf, state, switch_core_session_get_uuid(session)); + + if (mod_sofia_globals.debug_sla > 1) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "QUERY SQL %s\n", sql); + } + + sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE); + + + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Auto-Fixing Broken SLA [;%s]\n", + sip->sip_from->a_url->url_host, buf); + + switch_channel_set_variable_printf(channel, "presence_call_info_full", ";%s", sip->sip_from->a_url->url_host, buf); + switch_channel_set_variable(channel, "presence_call_info", buf); + call_info_str = switch_core_session_sprintf(session, ";%s", sip->sip_from->a_url->url_host, buf); + } + } else { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "WTF FAIL IF\n"); + + + } } + if (profile->pres_type) { const char *presence_id = switch_channel_get_variable(channel, "presence_id"); if (zstr(presence_id)) { @@ -8145,7 +8206,8 @@ void sofia_handle_sip_i_invite(nua_t *nua, sofia_profile_t *profile, nua_handle_ free(sql); } - } + } + check_decode(displayname, session); tech_pvt->caller_profile = switch_caller_profile_new(switch_core_session_get_pool(session), @@ -8197,7 +8259,7 @@ void sofia_handle_sip_i_invite(nua_t *nua, sofia_profile_t *profile, nua_handle_ if (app && data && !strcasecmp(app, "conference")) { - tech_pvt->caller_profile->destination_number = switch_core_sprintf(tech_pvt->caller_profile->pool, "answer,conference:%s", data); + tech_pvt->caller_profile->destination_number = switch_core_sprintf(tech_pvt->caller_profile->pool, "answer,conference:%s+flags{dist-dtmf}", data); tech_pvt->caller_profile->dialplan = "inline"; } else { if (switch_core_session_check_interface(b_session, sofia_endpoint_interface)) { @@ -8233,7 +8295,7 @@ void sofia_handle_sip_i_invite(nua_t *nua, sofia_profile_t *profile, nua_handle_ if (!one_leg && (!b_tech_pvt || !sofia_test_flag(b_tech_pvt, TFLAG_SIP_HOLD)) && (!c_tech_pvt || !sofia_test_flag(c_tech_pvt, TFLAG_SIP_HOLD))) { - char *ext = switch_core_session_sprintf(session, "answer,conference:%s@sla+flags{mintwo}", uuid); + char *ext = switch_core_session_sprintf(session, "answer,conference:%s@sla+flags{mintwo|dist-dtmf}", uuid); switch_channel_set_flag(c_channel, CF_REDIRECT); switch_ivr_session_transfer(b_session, ext, "inline", NULL); @@ -8246,7 +8308,7 @@ void sofia_handle_sip_i_invite(nua_t *nua, sofia_profile_t *profile, nua_handle_ if (do_conf) { tech_pvt->caller_profile->destination_number = switch_core_sprintf(tech_pvt->caller_profile->pool, - "answer,conference:%s@sla+flags{mintwo}", uuid); + "answer,conference:%s@sla+flags{mintwo|dist-dtmf}", uuid); } else { if (one_leg && c_app) { if (c_data) { diff --git a/src/mod/endpoints/mod_sofia/sofia_glue.c b/src/mod/endpoints/mod_sofia/sofia_glue.c index 4b31e760e1..ad0f25300b 100644 --- a/src/mod/endpoints/mod_sofia/sofia_glue.c +++ b/src/mod/endpoints/mod_sofia/sofia_glue.c @@ -2362,7 +2362,7 @@ switch_status_t sofia_glue_do_invite(switch_core_session_t *session) switch_channel_set_variable(channel, "presence_id", from); } - + if (!(tech_pvt->nh = nua_handle(tech_pvt->profile->nua, NULL, NUTAG_URL(url_str), TAG_IF(call_id, SIPTAG_CALL_ID_STR(call_id)), @@ -2575,7 +2575,7 @@ switch_status_t sofia_glue_do_invite(switch_core_session_t *session) } else { tech_pvt->session_refresher = nua_no_refresher; } - + if (sofia_use_soa(tech_pvt)) { nua_invite(tech_pvt->nh, NUTAG_AUTOANSWER(0), diff --git a/src/mod/endpoints/mod_sofia/sofia_presence.c b/src/mod/endpoints/mod_sofia/sofia_presence.c index 7700674243..1dfa7188cd 100644 --- a/src/mod/endpoints/mod_sofia/sofia_presence.c +++ b/src/mod/endpoints/mod_sofia/sofia_presence.c @@ -55,6 +55,13 @@ static int sync_sla(sofia_profile_t *profile, const char *to_user, const char *t 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); +struct pres_sql_cb { + sofia_profile_t *profile; + int ttl; +}; + +static int sofia_presence_send_sql(void *pArg, int argc, char **argv, char **columnNames); + struct dialog_helper { char state[128]; char status[512]; @@ -627,7 +634,7 @@ static void do_normal_probe(switch_event_t *event) if (probe_euser && probe_host && (profile = sofia_glue_find_profile(probe_host))) { sql = switch_mprintf("select state,status,rpid,presence_id from sip_dialogs " - "where hostname='%q' and profile_name='%q' and " + "where hostname='%q' and profile_name='%q' and call_info_state != 'seized' and " "((sip_from_user='%q' and sip_from_host='%q') or presence_id='%q@%q') order by rcd desc", mod_sofia_globals.hostname, profile->name, probe_euser, probe_host, probe_euser, probe_host); @@ -701,7 +708,7 @@ static void do_normal_probe(switch_event_t *event) "from sip_dialogs " - "where hostname='%q' and profile_name='%q' and (presence_id='%q@%q' or " + "where call_info_state != 'seized' and hostname='%q' and profile_name='%q' and (presence_id='%q@%q' or " "(sip_from_user='%q' and (sip_from_host='%q' or sip_to_host='%q')))", mod_sofia_globals.hostname, profile->name, dh.status, dh.rpid, probe_euser, probe_host, probe_euser, probe_host, probe_host); @@ -1938,15 +1945,13 @@ 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) { + if (mod_sofia_globals.debug_presence > 1 || mod_sofia_globals.debug_sla > 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" @@ -2007,7 +2012,6 @@ static void _send_presence_notify(sofia_profile_t *profile, TAG_END()); - switch_safe_free(route_uri); switch_safe_free(dcs); switch_safe_free(contact); @@ -3018,6 +3022,85 @@ static int sync_sla(sofia_profile_t *profile, const char *to_user, const char *t char *sql; int total = 0; + + if (clear) { + struct pres_sql_cb cb = {profile, 0}; + + + if (call_id) { + + sql = switch_mprintf("update sip_subscriptions set version=version+1,expires=%ld where " + "call_id='%q' " + "and event='line-seize'", (long) switch_epoch_time_now(NULL), + call_id); + + sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE); + + if (mod_sofia_globals.debug_sla > 1) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "CLEAR SQL %s\n", sql); + } + switch_safe_free(sql); + + sql = switch_mprintf("select full_to, full_from, contact, -1, call_id, event, network_ip, network_port, " + "NULL as ct, NULL as pt " + " from sip_subscriptions where call_id='%q' " + + "and event='line-seize'", call_id); + + sofia_glue_execute_sql_callback(profile, profile->ireg_mutex, sql, sofia_presence_send_sql, &cb); + if (mod_sofia_globals.debug_sla > 1) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "CLEAR SQL %s\n", sql); + } + switch_safe_free(sql); + } else { + + sql = switch_mprintf("update sip_subscriptions set version=version+1,expires=%ld where " + "hostname='%q' and profile_name='%q' " + "and sub_to_user='%q' and sub_to_host='%q' " + + "and event='line-seize'", (long) switch_epoch_time_now(NULL), + mod_sofia_globals.hostname, profile->name, to_user, to_host + ); + + if (mod_sofia_globals.debug_sla > 1) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "CLEAR SQL %s\n", sql); + } + + sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE); + + + sql = switch_mprintf("select full_to, full_from, contact, -1, call_id, event, network_ip, network_port, " + "NULL as ct, NULL as pt " + " from sip_subscriptions where " + "hostname='%q' and profile_name='%q' " + "and sub_to_user='%q' and sub_to_host='%q' " + "and event='line-seized'", + mod_sofia_globals.hostname, profile->name, to_user, to_host + ); + + sofia_glue_execute_sql_callback(profile, profile->ireg_mutex, sql, sofia_presence_send_sql, &cb); + + if (mod_sofia_globals.debug_sla > 1) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "CLEAR SQL %s\n", sql); + } + + switch_safe_free(sql); + } + + + sql = switch_mprintf("delete from sip_dialogs where hostname='%q' and profile_name='%q' and " + "((sip_from_user='%q' and sip_from_host='%q') or presence_id='%q@%q') " + "and call_info_state='seized'", mod_sofia_globals.hostname, profile->name, to_user, to_host, to_user, to_host); + + + if (mod_sofia_globals.debug_sla > 1) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "CLEAR SQL %s\n", sql); + } + sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE); + switch_safe_free(sql); + } + + switch_core_new_memory_pool(&pool); sh = switch_core_alloc(pool, sizeof(*sh)); sh->pool = pool; @@ -3041,12 +3124,13 @@ static int sync_sla(sofia_profile_t *profile, const char *to_user, const char *t 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 hostname='%q' and profile_name='%q')", + "from sip_subscriptions where call_id='%q' and hostname='%q' and profile_name='%q' " + "and (event='call-info' or event='line-seize')", call_id, mod_sofia_globals.hostname, 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 hostname='%q' and profile_name='%q'", + "from sip_subscriptions where call_id='%q' and hostname='%q' and profile_name='%q' and event='call-info'", call_id, mod_sofia_globals.hostname, profile->name); } @@ -3082,17 +3166,7 @@ static int sync_sla(sofia_profile_t *profile, const char *to_user, const char *t - if (clear) { - sql = switch_mprintf("delete from sip_dialogs where hostname='%q' and profile_name='%q' and " - "((sip_from_user='%q' and sip_from_host='%q') or presence_id='%q@%q') " - "and call_info_state='seized'", mod_sofia_globals.hostname, profile->name, to_user, to_host, to_user, to_host); - - - if (mod_sofia_globals.debug_sla > 1) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "CLEAR SQL %s\n", sql); - } - sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE); - } + return total; @@ -3452,6 +3526,7 @@ void sofia_presence_handle_sip_i_subscribe(int status, SIPTAG_SUBSCRIPTION_STATE_STR(sstr), SIPTAG_EVENT_STR("line-seize"), TAG_IF(full_call_info, SIPTAG_CALL_INFO_STR(full_call_info)), TAG_END()); + sql = switch_mprintf("delete from sip_dialogs where hostname='%q' and profile_name='%q' and " @@ -3687,10 +3762,6 @@ void sofia_presence_handle_sip_r_subscribe(int status, } } -struct pres_sql_cb { - sofia_profile_t *profile; - int ttl; -}; static int sofia_presence_send_sql(void *pArg, int argc, char **argv, char **columnNames) {