From 7124f61d570b669452d55f7b2159f87810c9f6c9 Mon Sep 17 00:00:00 2001 From: Carolyn Beeton Date: Wed, 6 Oct 2010 15:42:00 -0400 Subject: [PATCH] Improve support of Dialog events. Adds local-tag and remote-tag and populates all fields of dialog element as per RFC4235. --- src/mod/endpoints/mod_sofia/sofia.c | 33 ++++++-- src/mod/endpoints/mod_sofia/sofia_glue.c | 2 + src/mod/endpoints/mod_sofia/sofia_presence.c | 121 ++++++++++++++++++++++--- 3 files changed, 135 insertions(+), 21 deletions(-) diff --git a/src/mod/endpoints/mod_sofia/sofia.c b/src/mod/endpoints/mod_sofia/sofia.c index 0d69bdb..5d470ed 100644 --- a/src/mod/endpoints/mod_sofia/sofia.c +++ b/src/mod/endpoints/mod_sofia/sofia.c @@ -4338,6 +4338,8 @@ static void sofia_handle_sip_r_invite(switch_core_session_t *session, int status !switch_channel_test_flag(channel, CF_RING_READY)) { const char *from_user = "", *from_host = "", *to_user = "", *to_host = "", *contact_user = "", *contact_host = ""; const char *user_agent = "", *call_id = ""; + const char *to_tag = ""; + const char *from_tag = ""; char *sql = NULL; if (sip->sip_user_agent) { @@ -4350,12 +4352,14 @@ static void sofia_handle_sip_r_invite(switch_core_session_t *session, int status if (to) { from_user = switch_str_nil(to->url_user); + from_tag = switch_str_nil(sip->sip_to->a_tag); } if (from) { from_host = switch_str_nil(from->url_host); to_user = switch_str_nil(from->url_user); to_host = switch_str_nil(from->url_host); + to_tag = switch_str_nil(sip->sip_from->a_tag); } if (contact) { @@ -4377,12 +4381,12 @@ static void sofia_handle_sip_r_invite(switch_core_session_t *session, int status p++; } sql = switch_mprintf("insert into sip_dialogs " - "(call_id,uuid,sip_to_user,sip_to_host,sip_from_user,sip_from_host,contact_user," + "(call_id,uuid,sip_to_user,sip_to_host,sip_to_tag,sip_from_user,sip_from_host,sip_from_tag,contact_user," "contact_host,state,direction,user_agent,profile_name,hostname,contact,presence_id,presence_data,call_info) " - "values('%q','%q','%q','%q','%q','%q','%q','%q','%q','%q','%q','%q','%q','%q','%q','%q','%q')", + "values('%q','%q','%q','%q','%q','%q','%q','%q','%q','%q','%q','%q','%q','%q','%q','%q','%q','%q','%q')", call_id, switch_core_session_get_uuid(session), - to_user, to_host, from_user, from_host, contact_user, + to_user, to_host, to_tag, from_user, from_host, from_tag, contact_user, contact_host, astate, "outbound", user_agent, profile->name, mod_sofia_globals.hostname, switch_str_nil(full_contact), switch_str_nil(presence_id), switch_str_nil(presence_data), switch_str_nil(p)); @@ -4601,6 +4605,19 @@ static void sofia_handle_sip_i_state(switch_core_session_t *session, int status, } } + if (profile->pres_type && ss_state == nua_callstate_ready && status == 200) { + const char* to_tag = ""; + char *sql = NULL; + to_tag = switch_str_nil(switch_channel_get_variable(channel, "sip_to_tag")); + sql = switch_mprintf("update sip_dialogs set sip_to_tag='%q' " + "where uuid='%q'", to_tag, switch_core_session_get_uuid(session)); + + if (mod_sofia_globals.debug_presence > 1) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "QUERY SQL %s\n", sql); + } + + sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE); + } state_process: @@ -7034,6 +7051,8 @@ void sofia_handle_sip_i_invite(nua_t *nua, sofia_profile_t *profile, nua_handle_ const char *user_agent = "", *call_id = ""; url_t *from = NULL, *to = NULL, *contact = NULL; char *sql = NULL; + const char *to_tag = ""; + const char *from_tag = ""; if (sip->sip_to) { to = sip->sip_to->a_url; @@ -7056,11 +7075,13 @@ void sofia_handle_sip_i_invite(nua_t *nua, sofia_profile_t *profile, nua_handle_ if (to) { to_user = switch_str_nil(to->url_user); to_host = switch_str_nil(to->url_host); + to_tag = switch_str_nil(sip->sip_to->a_tag); } if (from) { dialog_from_user = switch_str_nil(from->url_user); dialog_from_host = switch_str_nil(from->url_host); + from_tag = switch_str_nil(sip->sip_from->a_tag); } if (contact) { @@ -7089,12 +7110,12 @@ void sofia_handle_sip_i_invite(nua_t *nua, sofia_profile_t *profile, nua_handle_ sql = switch_mprintf("insert into sip_dialogs " - "(call_id,uuid,sip_to_user,sip_to_host,sip_from_user,sip_from_host,contact_user," + "(call_id,uuid,sip_to_user,sip_to_host,sip_to_tag,sip_from_user,sip_from_host,sip_from_tag,contact_user," "contact_host,state,direction,user_agent,profile_name,hostname,contact,presence_id,presence_data,call_info) " - "values('%q','%q','%q','%q','%q','%q','%q','%q','%q','%q','%q','%q','%q','%q','%q','%q','%q')", + "values('%q','%q','%q','%q','%q','%q','%q','%q','%q','%q','%q','%q','%q','%q','%q','%q','%q','%q','%q')", call_id, tech_pvt->sofia_private->uuid, - to_user, to_host, dialog_from_user, dialog_from_host, + to_user, to_host, to_tag, dialog_from_user, dialog_from_host, from_tag, contact_user, contact_host, "confirmed", "inbound", user_agent, profile->name, mod_sofia_globals.hostname, switch_str_nil(full_contact), switch_str_nil(presence_id), switch_str_nil(presence_data), switch_str_nil(p)); diff --git a/src/mod/endpoints/mod_sofia/sofia_glue.c b/src/mod/endpoints/mod_sofia/sofia_glue.c index cb8b257..773b283 100644 --- a/src/mod/endpoints/mod_sofia/sofia_glue.c +++ b/src/mod/endpoints/mod_sofia/sofia_glue.c @@ -5229,8 +5229,10 @@ int sofia_glue_init_sql(sofia_profile_t *profile) " uuid VARCHAR(255),\n" " sip_to_user VARCHAR(255),\n" " sip_to_host VARCHAR(255),\n" + " sip_to_tag VARCHAR(255),\n" " sip_from_user VARCHAR(255),\n" " sip_from_host VARCHAR(255),\n" + " sip_from_tag VARCHAR(255),\n" " contact_user VARCHAR(255),\n" " contact_host VARCHAR(255),\n" " state VARCHAR(255),\n" diff --git a/src/mod/endpoints/mod_sofia/sofia_presence.c b/src/mod/endpoints/mod_sofia/sofia_presence.c index 55b0c5c..bec59a4 100644 --- a/src/mod/endpoints/mod_sofia/sofia_presence.c +++ b/src/mod/endpoints/mod_sofia/sofia_presence.c @@ -570,25 +570,25 @@ static void actual_sofia_presence_event_handler(switch_event_t *event) sofia_glue_execute_sql_callback(profile, profile->ireg_mutex, sql, sofia_presence_dialog_callback, &dh); switch_safe_free(sql); - - sql = switch_mprintf("select sip_registrations.sip_user, sip_registrations.sip_host, sip_registrations.status, " + sql = switch_mprintf("select '%q','%q', sip_registrations.status, " "sip_registrations.rpid,'', sip_dialogs.uuid, sip_dialogs.state, sip_dialogs.direction, " "sip_dialogs.sip_to_user, sip_dialogs.sip_to_host, sip_presence.status,sip_presence.rpid,sip_presence.open_closed," - "'%q','%q' " - - "from sip_registrations left join sip_dialogs on " + "'%q','%q', " + "sip_dialogs.contact, sip_dialogs.sip_to_tag, sip_dialogs.sip_from_tag, " + "sip_dialogs.call_id " + "from sip_dialogs left join sip_registrations on " "(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) ) " - "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_dialogs.sip_from_user=sip_presence.sip_user and sip_dialogs.sip_from_host=sip_presence.sip_host and " "sip_registrations.profile_name=sip_presence.profile_name) " - "where sip_registrations.sip_user='%q' and " - "(sip_registrations.orig_server_host='%q' or sip_registrations.sip_host='%q' " + "where (sip_dialogs.sip_from_user='%q' and " + "(sip_dialogs.sip_from_host='%q' or sip_registrations.sip_host='%q' ) or " + "(sip_dialogs.sip_to_user='%q' and sip_dialogs.sip_to_host='%q') " "or sip_registrations.presence_hosts like '%%%q%%')", - dh.status, dh.rpid, probe_euser, probe_host, probe_host, probe_host); + probe_euser, probe_host, dh.status, dh.rpid, probe_euser, probe_host, probe_host, probe_euser, probe_host); switch_assert(sql); if (mod_sofia_globals.debug_presence > 0) { @@ -948,6 +948,52 @@ static int sofia_presence_sub_reg_callback(void *pArg, int argc, char **argv, ch return 0; } +char *get_display_name_from_contact(const char *in, char* dst) +{ + // name-addr = [ display-name ] LAQUOT addr-spec RAQUOT + // display-name = *(token LWS)/ quoted-string + // return whatever comes before the left angle bracket, stripped of whitespace and quotes + char *e; + char *p; + char buf[1024]; + + strcpy(dst,""); + if ((e = strchr(in, '<')) && (strchr(in, '>'))) { + strncpy(buf, in, e-in+1); + e = strchr(buf, '<'); + *e = '\0'; + p = switch_strip_whitespace(buf); + if (p) { + if (*p == '"') { + if (end_of(p+1) == '"') { + char *q = strdup(p+1); + end_of(q) = '\0'; + strcpy(dst, q); + switch_safe_free(q); + } + } + else { + strcpy(dst, p); + } + switch_safe_free(p); + } + } + return dst; +} + +char *get_user_from_url(const char *in, char* dst) +{ + // userinfo = ( user / telephone-subscriber ) [ ":" password ] "@" + char *e; + strcpy(dst,""); + if ((e = strchr(in, '@'))) { + strncpy(dst, in, e-in+1); + e = strchr(dst, '@'); + *e = '\0'; + } + return dst; +} + static int sofia_presence_resub_callback(void *pArg, int argc, char **argv, char **columnNames) { struct resub_helper *h = (struct resub_helper *) pArg; @@ -962,6 +1008,13 @@ static int sofia_presence_resub_callback(void *pArg, int argc, char **argv, char char *uuid = NULL; char *state = NULL; char *direction = NULL; + char *contact = NULL; + char *to_tag = NULL; + char *from_tag = NULL; + char *ref_call_id = NULL; + char contact_buf[128]; + char remote_user[128]; + char remote_display[128]; switch_event_t *event; char to_buf[128] = ""; switch_event_header_t *hp; @@ -980,6 +1033,17 @@ static int sofia_presence_resub_callback(void *pArg, int argc, char **argv, char rpid = argv[11]; } } + if (argc > 15 && !zstr(argv[15])) { + switch_set_string(contact_buf, argv[15]); + get_display_name_from_contact(contact_buf, remote_display); + contact = sofia_glue_strip_uri(argv[15]); + get_user_from_url(sofia_glue_strip_proto(contact), remote_user); + } + if (argc > 18) { + to_tag = switch_str_nil(argv[16]); + from_tag = switch_str_nil(argv[17]); + ref_call_id = switch_str_nil(argv[18]); + } if (zstr(proto)) { proto = NULL; @@ -1014,6 +1078,12 @@ static int sofia_presence_resub_callback(void *pArg, int argc, char **argv, char switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "answer-state", state); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "astate", state); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "presence-call-direction", direction); + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "remote-display", remote_display); + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "remote-contact", contact); + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "to_tag", to_tag); + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "from_tag", from_tag); + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "variable_sip_from_user", remote_user); + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "ref_call_id", ref_call_id); } if (h->event) { @@ -1294,6 +1364,10 @@ static int sofia_presence_sub_callback(void *pArg, int argc, char **argv, char * if (helper->event) { switch_stream_handle_t stream = { 0 }; const char *direction = switch_str_nil(switch_event_get_header(helper->event, "presence-call-direction")); + const char *remote_contact = switch_str_nil(switch_event_get_header(helper->event, "remote-contact")); + const char *remote_display = switch_str_nil(switch_event_get_header(helper->event, "remote-display")); + const char *to_tag = switch_str_nil(switch_event_get_header(helper->event, "to_tag")); + const char *from_tag = switch_str_nil(switch_event_get_header(helper->event, "from_tag")); const char *uuid = switch_str_nil(switch_event_get_header(helper->event, "unique-id")); const char *event_status = switch_str_nil(switch_event_get_header(helper->event, "status")); const char *astate = switch_str_nil(switch_event_get_header(helper->event, "astate")); @@ -1302,9 +1376,12 @@ static int sofia_presence_sub_callback(void *pArg, int argc, char **argv, char * const char *from_id = switch_str_nil(switch_event_get_header(helper->event, "Other-Leg-Caller-ID-Number")); const char *to_user = switch_str_nil(switch_event_get_header(helper->event, "variable_sip_to_user")); const char *from_user = switch_str_nil(switch_event_get_header(helper->event, "variable_sip_from_user")); + const char *ref_call_id = switch_str_nil(switch_event_get_header(helper->event, "ref_call_id")); char *clean_to_user = NULL; char *clean_from_user = NULL; int force_status = 0; + const char* local_tag = ""; + const char* remote_tag = ""; #if 0 char *buf; switch_event_serialize(helper->event, &buf, SWITCH_FALSE); @@ -1320,9 +1397,13 @@ static int sofia_presence_sub_callback(void *pArg, int argc, char **argv, char * if (!strcasecmp(direction, "outbound")) { direction = "recipient"; dft_state = "early"; + local_tag = from_tag; + remote_tag = to_tag; } else { direction = "initiator"; dft_state = "confirmed"; + local_tag = to_tag; + remote_tag = from_tag; } if (is_dialog) { @@ -1373,7 +1454,14 @@ static int sofia_presence_sub_callback(void *pArg, int argc, char **argv, char * } } - stream.write_function(&stream, "\n", uuid, direction); + stream.write_function(&stream, "\n", + direction); stream.write_function(&stream, "%s\n", astate); } else { if (!strcasecmp(astate, "ringing")) { @@ -1384,7 +1472,10 @@ static int sofia_presence_sub_callback(void *pArg, int argc, char **argv, char * if (!strcasecmp(astate, "early") || !strcasecmp(astate, "confirmed")) { clean_to_user = switch_mprintf("%s", sub_to_user ? sub_to_user : to_user); - clean_from_user = switch_mprintf("%s", from_id ? from_id : from_user); + clean_from_user = switch_mprintf("%s", !zstr(from_id) ? from_id : from_user); + if (zstr(remote_display)) { + remote_display = clean_from_user; + } if (is_dialog) { if (!zstr(clean_to_user) && !zstr(clean_from_user)) { @@ -1393,9 +1484,9 @@ static int sofia_presence_sub_callback(void *pArg, int argc, char **argv, char * stream.write_function(&stream, "\n", !strcasecmp(event_status, "hold") ? "no" : "yes"); stream.write_function(&stream, "\n\n"); - stream.write_function(&stream, "\nsip:%s@%s\n", clean_from_user, clean_from_user, - host); - stream.write_function(&stream, "\n", clean_to_user, host); + stream.write_function(&stream, "\nsip:%s@%s\n", remote_display, clean_from_user, + host); + stream.write_function(&stream, "\n", remote_contact); stream.write_function(&stream, "\n"); } else if (!strcasecmp(proto, "park")) { stream.write_function(&stream, "\nsip:parking@%s;fifo=%s\n", -- 1.6.0.6