if (for_everyone) {
sql = switch_mprintf("select proto,sip_user,sip_host,sub_to_user,sub_to_host,event,contact,call_id,full_from,"
"full_via,expires,user_agent,accept,profile_name,network_ip"
- ",'%q','%q' from sip_subscriptions where version > -1 and expires > -1 and event='message-summary' "
- "and sub_to_user='%q' and (sub_to_host='%q' or presence_hosts like '%%%q%%')", stream.data, host, user, host, host);
+ ",'%q',full_to,network_ip,network_port from sip_subscriptions where version > -1 and expires > -1 and event='message-summary' "
+ "and sub_to_user='%q' and (sub_to_host='%q' or presence_hosts like '%%%q%%')", stream.data, user, host, host);
} else if (sub_call_id) {
sql = switch_mprintf("select proto,sip_user,sip_host,sub_to_user,sub_to_host,event,contact,call_id,full_from,"
"full_via,expires,user_agent,accept,profile_name,network_ip"
- ",'%q','%q' from sip_subscriptions where version > -1 and expires > -1 and event='message-summary' "
+ ",'%q',full_to,network_ip,network_port from sip_subscriptions where version > -1 and expires > -1 and event='message-summary' "
"and sub_to_user='%q' and (sub_to_host='%q' or presence_hosts like '%%%q%%' and call_id='%q')",
- stream.data, host, user, host, host, sub_call_id);
+ stream.data, user, host, host, sub_call_id);
}
// The dialog_probe_callback has built up the dialogs to be included in the NOTIFY.
// Now send the "full" dialog event to the triggering subscription.
sql = switch_mprintf("select call_id,expires,sub_to_user,sub_to_host,event,version, "
- "'full' "
+ "'full',full_to,full_from,contact,expires,event,network_ip,network_port "
"from sip_subscriptions "
"where expires > -1 and hostname='%q' "
"and sub_to_user='%q' and sub_to_host='%q' " "and (event='dialog') and "
"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,sip_subscriptions.network_ip"
- ",1,'%q','%q',sip_presence.status,sip_presence.rpid,sip_presence.open_closed "
+ ",1,'%q','%q',sip_presence.status,sip_presence.rpid,sip_presence.open_closed,'','','','','sip',"
+ " 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) "
"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,sip_subscriptions.network_ip"
- ",1,'%q','%q',sip_presence.status,sip_presence.rpid,sip_presence.open_closed "
+ ",1,'%q','%q',sip_presence.status,sip_presence.rpid,sip_presence.open_closed,'','','','','sip',"
+ "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) "
call_info, call_info_state, mod_sofia_globals.hostname, euser, host, euser, host, call_info);
}
- //printf("WTF %s\n", sql);
if (mod_sofia_globals.debug_sla > 1) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "STATE SQL %s\n", sql);
"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.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 "
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
+ )
+{
+ 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);
+
+ if (expires) {
+ long ltmp = atol(expires);
+
+ if (ltmp > 0) {
+ exptime = (ltmp - now);
+ } else {
+ exptime = 0;
+ }
+ }
+
+
+ switch_mutex_lock(profile->ireg_mutex);
+ if (!profile->cseq_base) {
+ profile->cseq_base = (now - 1312693200) * 10;
+ }
+ callsequence = ++profile->cseq_base;
+ switch_mutex_unlock(profile->ireg_mutex);
+
+
+ nh = nua_handle(profile->nua, NULL, 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), "active;expires=%u", (unsigned) exptime);
+ } else {
+ switch_snprintf(sstr, sizeof(sstr), "terminated;reason=noresource");
+ }
+
+
+ tmp = (char *)contact;
+ contact = sofia_glue_get_url_from_contact(tmp, 0);
+
+ if (remote_ip && remote_port) {
+ route = switch_mprintf("sip:%s:%s", remote_ip, remote_port);
+ }
+
+ 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,
+ profile->url,
+ 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),
+ SIPTAG_FROM_STR(full_to),
+ SIPTAG_TO_STR(full_from),
+ SIPTAG_CONTACT_STR(profile->url),
+ SIPTAG_CALL_ID_STR(call_id),
+ TAG_IF(*expires_str, SIPTAG_EXPIRES_STR(expires_str)),
+ SIPTAG_SUBSCRIPTION_STATE_STR(sstr),
+ SIPTAG_EVENT_STR(event),
+ TAG_IF(!zstr(ct), SIPTAG_CONTENT_TYPE_STR(ct)),
+ TAG_IF(!zstr(pl), SIPTAG_PAYLOAD_STR(pl)),
+ TAG_IF(!zstr(call_info), SIPTAG_CALL_INFO_STR(call_info)),
+ TAG_IF(!exptime, SIPTAG_EXPIRES_STR("0")),
+ SIPTAG_CSEQ(cseq),
+ TAG_END());
+
+ switch_safe_free(route);
+
+
+}
+
+
static int sofia_dialog_probe_notify_callback(void *pArg, int argc, char **argv, char **columnNames)
{
struct rfc4235_helper *sh = (struct rfc4235_helper *) pArg;
char *event = argv[4];
char *version = argv[5];
char *notify_state = argv[6];
-
+ char *full_to = argv[7];
+ char *full_from = argv[8];
+ char *contact = argv[9];
+ char *remote_ip = argv[10];
+ char *remote_port = argv[11];
+
switch_stream_handle_t stream = { 0 };
- nua_handle_t *nh;
- time_t exptime = switch_epoch_time_now(NULL) + 3600;
- char sstr[128] = "";
- char expires_str[10] = "";
char *to;
const char *pl = NULL;
const char *ct = "application/dialog-info+xml";
- if (!(nh = nua_handle_by_call_id(sh->profile->nua, call_id))) {
- switch_log_printf(SWITCH_CHANNEL_LOG,SWITCH_LOG_DEBUG, "sofia_dialog_probe_notify_callback: could not find nua handle (old subscription)\n");
- return 0;
- }
-
+
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",
pl = stream.data;
ct = "application/dialog-info+xml";
- nua_handle_bind(nh, &mod_sofia_globals.keep_private);
-
- if (expires) {
- long tmp = atol(expires);
- exptime = tmp - switch_epoch_time_now(NULL);
- }
- if (exptime > 0) {
- switch_snprintf(sstr, sizeof(sstr), "active;expires=%u", (unsigned) exptime);
- } else {
- switch_snprintf(sstr, sizeof(sstr), "terminated;reason=timeout");
- }
-
if (mod_sofia_globals.debug_presence > 0 && pl) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "send payload:\n%s\n", pl);
}
- nua_notify(nh,
- TAG_IF(*expires_str, SIPTAG_EXPIRES_STR(expires_str)),
- SIPTAG_SUBSCRIPTION_STATE_STR(sstr), SIPTAG_EVENT_STR(event), SIPTAG_CONTENT_TYPE_STR(ct), SIPTAG_PAYLOAD_STR(pl), TAG_END());
+
+ send_presence_notify(sh->profile,
+ full_to,
+ full_from,
+ contact,
+ expires,
+ call_id,
+ event,
+ remote_ip,
+ remote_port,
+ ct,
+ pl,
+ NULL
+ );
+
switch_safe_free(to);
switch_safe_free(stream.data);
struct presence_helper *helper = (struct presence_helper *) pArg;
char *pl = NULL;
char *clean_id = NULL, *id = NULL;
+
char *proto = argv[0];
char *user = argv[1];
char *host = argv[2];
char *sub_to_user = argv[3];
char *event = argv[5];
+ char *contact = argv[6];
char *call_id = argv[7];
+ char *full_from = argv[8];
+ //char *full_via = argv[9];
+
char *expires = argv[10];
char *user_agent = argv[11];
char *profile_name = argv[13];
char *dialog_rpid = NULL;
const char *ct = "no/idea";
- nua_handle_t *nh;
+
char *to = NULL;
char *open;
char *prpid;
- time_t exptime = switch_epoch_time_now(NULL) + 3600;
+
int is_dialog = 0;
sofia_profile_t *ext_profile = NULL, *profile = helper->profile;
- char sstr[128] = "";
- int kill_handle = 0;
- char expires_str[10] = "";
+
char status_line[256] = "";
char *version = "0";
char *presence_id = NULL;
int holding = 0;
char *orig_proto = NULL;
int skip_proto = 0;
+ char *full_to = NULL;
+ char *ip = NULL;
+ char *port = 0;
-
- //int i;
-
- //for(i = 0; i < argc; i++) {
- //printf("arg %d[%s] = [%s]\n", i, columnNames[i], argv[i]);
- //}
- //DUMP_EVENT(helper->event);
+ 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]);
+ }
+ DUMP_EVENT(helper->event);
+ }
if (argc > 18) {
if (!zstr(argv[17])) {
version = argv[22];
presence_id = argv[23];
orig_proto = argv[24];
+ full_to = argv[25];
+ ip = argv[26];
+ port = argv[27];
}
if (!zstr(presence_id) && strchr(presence_id, '@')) {
}
}
- if (!(nh = nua_handle_by_call_id(profile->nua, call_id))) {
- if (mod_sofia_globals.debug_presence > 0) {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to find handle for call id %s\n", call_id);
- }
-
- goto end;
+ if (!strcasecmp(proto, SOFIA_CHAT_PROTO) || skip_proto) {
+ clean_id = switch_mprintf("sip:%s@%s", sub_to_user, sub_to_host);
+ } else {
+ clean_id = switch_mprintf("sip:%s+%s@%s", proto, sub_to_user, sub_to_host);
}
- if (expires) {
- long tmp = atol(expires);
- if (tmp > 0) {
- exptime = tmp - switch_epoch_time_now(NULL); // - SUB_OVERLAP;
- } else {
- exptime = tmp;
- }
- }
+
if (!rpid) {
rpid = "unknown";
}
- if (!strcasecmp(proto, SOFIA_CHAT_PROTO) || skip_proto) {
- clean_id = switch_mprintf("sip:%s@%s", sub_to_user, sub_to_host);
- } else {
- clean_id = switch_mprintf("sip:%s+%s@%s", proto, sub_to_user, sub_to_host);
- }
+ // if (!strcasecmp(proto, SOFIA_CHAT_PROTO) || skip_proto) {
+ // clean_id = switch_mprintf("sip:%s@%s", sub_to_user, sub_to_host);
+ //} else {
+ // clean_id = switch_mprintf("sip:%s+%s@%s", proto, sub_to_user, sub_to_host);
+ //}
if (mod_sofia_globals.debug_presence > 0) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE,
if (!zstr(astate) && !zstr(uuid) &&
helper && helper->stream.data && strcmp(helper->last_uuid, uuid) && strcasecmp(astate, "terminated") && strchr(uuid, '-')) {
helper->stream.write_function(&helper->stream, "update sip_dialogs set state='%s' where uuid='%s';", astate, uuid);
- //printf("WTF update sip_dialogs set state='%s' where uuid='%s';\n", astate, uuid);
switch_copy_string(helper->last_uuid, uuid, sizeof(helper->last_uuid));
}
if (!zstr(uuid) && strchr(uuid, '-') && !zstr(status_line) && !zstr(rpid) && (zstr(register_source) || strcasecmp(register_source, "register"))) {
char *sql = switch_mprintf("update sip_dialogs set rpid='%q',status='%q' where uuid='%q'", rpid, status_line, uuid);
- //printf("WTF %s\n", sql);
sofia_glue_execute_sql(profile, &sql, SWITCH_TRUE);
}
}
-
- nua_handle_bind(nh, &mod_sofia_globals.keep_private);
-
- if (helper->event && helper->event->event_id == SWITCH_EVENT_PRESENCE_OUT) {
- switch_set_string(sstr, "terminated;reason=noresource");
- switch_set_string(expires_str, "0");
- kill_handle = 1;
- } else if (exptime > 0) {
- switch_snprintf(sstr, sizeof(sstr), "active;expires=%u", (unsigned) exptime);
- } else {
- unsigned delta = (unsigned) (exptime * -1);
- switch_snprintf(sstr, sizeof(sstr), "active;expires=%u", delta);
- switch_snprintf(expires_str, sizeof(expires_str), "%u", delta);
- if (nh && nh->nh_ds && nh->nh_ds->ds_usage) {
- nua_dialog_usage_set_refresh_range(nh->nh_ds->ds_usage, delta, delta);
- }
- }
-
- if (mod_sofia_globals.debug_presence > 0 && pl) {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "send payload:\n%s\n", pl);
- }
-
- nua_notify(nh,
- TAG_IF(*expires_str, SIPTAG_EXPIRES_STR(expires_str)),
- SIPTAG_SUBSCRIPTION_STATE_STR(sstr), SIPTAG_EVENT_STR(event), SIPTAG_CONTENT_TYPE_STR(ct), SIPTAG_PAYLOAD_STR(pl), TAG_END());
-
- nua_handle_unref(nh);
-
- end:
+ send_presence_notify(profile, full_to, full_from, contact, expires, call_id, event, ip, port, ct, pl, NULL);
switch_safe_free(free_me);
switch_safe_free(pl);
switch_safe_free(to);
- if (nh && kill_handle) {
- nua_handle_destroy(nh);
- }
-
return 0;
}
static int sofia_presence_mwi_callback(void *pArg, int argc, char **argv, char **columnNames)
{
- char *sub_to_user = argv[3];
- char *sub_to_host = argv[15];
+ //char *sub_to_user = argv[3];
+ //char *sub_to_host = argv[4];
char *event = argv[5];
+ char *contact = argv[6];
char *call_id = argv[7];
+ char *full_from = argv[8];
char *expires = argv[10];
char *profile_name = argv[13];
char *body = argv[15];
- char *id = NULL;
- nua_handle_t *nh;
- int expire_sec = atoi(expires);
+ char *full_to = argv[16];
+ char *remote_ip = argv[17];
+ char *remote_port = argv[18];
+
struct mwi_helper *h = (struct mwi_helper *) pArg;
sofia_profile_t *ext_profile = NULL, *profile = h->profile;
}
}
- if (!(nh = nua_handle_by_call_id(h->profile->nua, call_id))) {
- if (profile->debug) {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Cannot find handle for %s\n", call_id);
- }
- goto end;
- }
-
- id = switch_mprintf("sip:%s@%s", sub_to_user, sub_to_host);
- expire_sec = (int) (expire_sec - switch_epoch_time_now(NULL));
- if (expire_sec < 0) {
- expire_sec = 3600;
- }
-
- nua_handle_bind(nh, &mod_sofia_globals.keep_private);
- nua_notify(nh, SIPTAG_SUBSCRIPTION_STATE_STR("active"),
- SIPTAG_EVENT_STR(event), SIPTAG_CONTENT_TYPE_STR("application/simple-message-summary"), SIPTAG_PAYLOAD_STR(body), TAG_END());
+ send_presence_notify(profile,
+ full_to,
+ full_from,
+ contact,
+ expires,
+ call_id,
+ event,
+ remote_ip,
+ remote_port,
+ "application/simple-message-summary",
+ body,
+ NULL
+ );
- nua_handle_unref(nh);
-
- switch_safe_free(id);
h->total++;
- end:
-
if (ext_profile) {
sofia_glue_release_profile(ext_profile);
}
char key[256] = "";
char *data = NULL, *tmp;
char *call_id = argv[0];
- char *expires = argv[1];
+ //char *expires = argv[1];
char *user = argv[2];
char *host = argv[3];
char *event = argv[4];
int i;
- char sstr[128] = "", expires_str[128] = "";
- time_t exptime = 3600;
- nua_handle_t *nh;
if (mod_sofia_globals.debug_sla > 1) {
for (i = 0; i < argc; i++) {
switch_snprintf(key, sizeof(key), "%s%s", user, host);
data = switch_core_hash_find(sh->hash, key);
-
- if (expires) {
- long tmp = atol(expires);
- exptime = tmp - switch_epoch_time_now(NULL);
- }
-
- if (exptime > 0) {
- switch_snprintf(sstr, sizeof(sstr), "active;expires=%u", (unsigned) exptime);
- } else {
- switch_snprintf(sstr, sizeof(sstr), "terminated;reason=noresource");
- }
-
- switch_snprintf(expires_str, sizeof(expires_str), "%u", (unsigned) exptime);
+
data = switch_core_hash_find(sh->hash, key);
tmp = switch_core_sprintf(sh->pool, "<sip:%s>;appearance-index=*;appearance-state=idle", host);
}
- if (!strcasecmp(event, "line-seize") && (nh = nua_handle_by_call_id(sh->profile->nua, call_id))) {
+
+ if (!strcasecmp(event, "line-seize")) {
char *hack;
if ((hack = (char *) switch_stristr("=seized", tmp))) {
switch_snprintf(hack, 7, "=idle ");
}
- nua_notify(nh,
- SIPTAG_EXPIRES_STR("0"),
- SIPTAG_SUBSCRIPTION_STATE_STR("terminated;reason=noresource"), SIPTAG_EVENT_STR("line-seize"), SIPTAG_CALL_INFO_STR(tmp), TAG_END());
- nua_handle_unref(nh);
- return 0;
}
- if (!strcasecmp(event, "call-info") && (nh = nua_handle_by_call_id(sh->profile->nua, call_id))) {
- nua_notify(nh,
- TAG_IF(*expires_str, SIPTAG_EXPIRES_STR(expires_str)),
- SIPTAG_SUBSCRIPTION_STATE_STR(sstr), SIPTAG_EVENT_STR("call-info"), SIPTAG_CALL_INFO_STR(tmp), TAG_END());
- nua_handle_unref(nh);
+ if (mod_sofia_globals.debug_sla > 1) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "DB PRES NOTIFY: [%s]\n[%s]\n[%s]\n[%s]\n[%s]\n[%s]\n[%s]\n[%s]\n[%s]\n",
+ argv[5], argv[6], argv[7], argv[8], call_id, event, argv[9], argv[10], tmp);
+
}
-
+
+ send_presence_notify(sh->profile, argv[5], argv[6], argv[7], argv[8], call_id, event, argv[9], argv[10], NULL, NULL, tmp);
+
return 0;
}
if (unseize) {
- sql = switch_mprintf("select call_id,expires,sub_to_user,sub_to_host,event "
+ 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 "
+ 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);
tagi_t tags[])
{
- long exp_delta;
+ long exp_delta = 0;
char exp_delta_str[30] = "";
sip_to_t const *to;
const char *from_user = NULL, *from_host = NULL;
const char *call_id = NULL;
char *to_str = NULL;
char *full_from = NULL;
+ char *full_to = NULL;
char *full_via = NULL;
char *full_agent = NULL;
char *sstr;
const char *contact_user;
sofia_nat_parse_t np = { { 0 } };
int found_proto = 0;
+ char to_tag[13] = "";
if (!sip) {
return;
return;
}
+ switch_stun_random_string(to_tag, 12, NULL);
+
//contact_host = sip->sip_contact->m_url->url_host;
contact_user = sip->sip_contact->m_url->url_user;
event = sip_header_as_string(nh->nh_home, (void *) sip->sip_event);
-
- /* the following could be refactored back to the calling event handler in sofia.c XXX MTK */
- if (sofia_test_pflag(profile, PFLAG_MANAGE_SHARED_APPEARANCE)) {
- if (sip->sip_request->rq_url->url_user && !strncmp(sip->sip_request->rq_url->url_user, "sla-agent", sizeof("sla-agent"))) {
- /* only fire this on <200 to try to avoid resubscribes. probably better ways to do this? */
- if (status < 200) {
- sofia_sla_handle_sip_i_subscribe(nua, contact_str, profile, nh, sip, de, tags);
- }
- switch_safe_free(contact_str);
- return;
- }
- }
-
if (to) {
to_str = switch_mprintf("sip:%s@%s", to->a_url->url_user, to->a_url->url_host);
}
call_id = sip->sip_call_id->i_id;
full_from = sip_header_as_string(nh->nh_home, (void *) sip->sip_from);
+ full_to = sip_header_as_string(nh->nh_home, (void *) sip->sip_to);
full_via = sip_header_as_string(nh->nh_home, (void *) sip->sip_via);
+
if (sip->sip_expires && sip->sip_expires->ex_delta > 31536000) {
sip->sip_expires->ex_delta = 31536000;
}
} else {
sip_accept_t *ap = sip->sip_accept;
char accept[256] = "";
+
full_agent = sip_header_as_string(nh->nh_home, (void *) sip->sip_user_agent);
while (ap) {
switch_snprintf(accept + strlen(accept), sizeof(accept) - strlen(accept), "%s%s ", ap->ac_type, ap->ac_next ? "," : "");
sql = switch_mprintf("insert into sip_subscriptions "
"(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) "
- "values ('%q','%q','%q','%q','%q','%q','%q','%q','%q','%q','%q',%ld,'%q','%q','%q','%q','%d','%q','%q')",
+ "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,
event, contact_str, call_id, full_from, full_via,
- //sofia_test_pflag(profile, PFLAG_MULTIREG) ? switch_epoch_time_now(NULL) + exp_delta : exp_delta * -1,
(long) switch_epoch_time_now(NULL) + exp_delta,
- full_agent, accept, profile->name, mod_sofia_globals.hostname, np.network_port, np.network_ip, orig_proto);
+ full_agent, accept, profile->name, mod_sofia_globals.hostname,
+ np.network_port, np.network_ip, orig_proto, full_to, to_tag);
switch_assert(sql != NULL);
sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE);
sstr = switch_mprintf("active;expires=%ld", exp_delta);
- }
-
- switch_mutex_unlock(profile->ireg_mutex);
+ }
+
+ switch_mutex_unlock(profile->ireg_mutex);
}
if (status < 200) {
char *sticky = NULL;
char *contactstr = profile->url, *cs = NULL;
char *p = NULL, *new_contactstr = NULL;
+
if (np.is_nat) {
char params[128] = "";
new_contactstr = switch_mprintf("<sip:%s%s>", to_user, p);
}
}
-
+
+ sip_to_tag(nh->nh_home, sip->sip_to, to_tag);
+
nua_respond(nh, SIP_202_ACCEPTED,
+ SIPTAG_TO(sip->sip_to),
TAG_IF(new_contactstr, SIPTAG_CONTACT_STR(new_contactstr)),
NUTAG_WITH_THIS_MSG(de->data->e_msg),
SIPTAG_SUBSCRIPTION_STATE_STR(sstr), SIPTAG_EXPIRES_STR(exp_delta_str), TAG_IF(sticky, NUTAG_PROXY(sticky)), TAG_END());
if (full_from) {
su_free(nh->nh_home, full_from);
}
+ if (full_to) {
+ su_free(nh->nh_home, full_to);
+ }
+
if (full_via) {
su_free(nh->nh_home, full_via);
}
if (!sent_reply) {
nua_respond(nh, 481, "INVALID SUBSCRIPTION", TAG_END());
}
-
+
+ nua_handle_destroy(nh);
+
}
return;
}
- /* the following could possibly be refactored back towards the calling event handler in sofia.c XXX MTK */
- if (sofia_test_pflag(profile, PFLAG_MANAGE_SHARED_APPEARANCE)) {
- if (!strcasecmp(o->o_type, "dialog") && msg_params_find(o->o_params, "sla")) {
- sofia_sla_handle_sip_r_subscribe(status, phrase, nua, profile, nh, sofia_private, sip, de, tags);
- return;
- }
- }
-
if (!sofia_private || !sofia_private->gateway) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Gateway information missing\n");
return;
}
}
-struct cpc {
- sofia_profile_t *profile;
- sofia_dispatch_event_t *de;
-};
-static int sofia_counterpath_crutch(void *pArg, int argc, char **argv, char **columnNames)
+static int sofia_presence_send_sql(void *pArg, int argc, char **argv, char **columnNames)
{
- nua_handle_t *nh;
- struct cpc *crutch = (struct cpc *) pArg;
- char *call_id = argv[0];
- char *pl = argv[1];
- char *event_type = argv[2];
- long exp_delta = atol(argv[3]);
-
- if ((nh = nua_handle_by_call_id(crutch->profile->nua, call_id))) {
- char sstr[128] = "", expstr[128] = "";
- switch_snprintf(expstr, sizeof(expstr), "%d", exp_delta);
- switch_snprintf(sstr, sizeof(sstr), "active;expires=%u", exp_delta);
- nua_notify(nh,
- NUTAG_WITH_THIS_MSG(crutch->de->data->e_msg),
- SIPTAG_EXPIRES_STR(expstr),
- SIPTAG_SUBSCRIPTION_STATE_STR(sstr), SIPTAG_EVENT_STR(event_type),
- SIPTAG_CONTENT_TYPE_STR("application/pidf+xml"), SIPTAG_PAYLOAD_STR(pl), TAG_END());
- nua_handle_unref(nh);
- }
+ sofia_profile_t *profile = (sofia_profile_t *) pArg;
+ send_presence_notify(profile, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8], argv[9], NULL);
+
return 0;
}
from = sip->sip_from;
payload = sip->sip_payload;
- /* the following could instead be refactored back to the calling event handler in sofia.c XXX MTK */
- if (sofia_test_pflag(profile, PFLAG_MANAGE_SHARED_APPEARANCE)) {
- /* also it probably is unsafe to dereference so many things in a row without testing XXX MTK */
- if (sip->sip_request->rq_url->url_user && !strncmp(sip->sip_request->rq_url->url_user, "sla-agent", sizeof("sla-agent"))) {
- sofia_sla_handle_sip_i_publish(nua, profile, nh, sip, de, tags);
- return;
- }
- }
-
contact_str = sofia_glue_gen_contact_str(profile, sip, de, NULL);
if (from) {
}
} else if (contact_str) {
- struct cpc crutch;
-
- crutch.profile = profile;
- crutch.de = de;
- sql = switch_mprintf("select call_id,'%q','%q','%ld' from sip_subscriptions where sub_to_user='%q' and sub_to_host='%q' "
- "and contact = '%q' ", payload->pl_data ? payload->pl_data : "", event_type, exp_delta,
- from_user, from_host, contact_str);
- sofia_glue_execute_sql_callback(profile, profile->ireg_mutex, sql, sofia_counterpath_crutch, &crutch);
+ sql = switch_mprintf("select full_to, full_from, contact, expires, call_id, event, network_ip, network_port, "
+ "'application/pidf+xml' as ct,'%q' as pt "
+ " from sip_subscriptions where sub_to_user='%q' and sub_to_host='%q' and event='%q'"
+ "and contact = '%q' ", switch_str_nil(payload->pl_data), from_user, from_host, event_type);
+
+ sofia_glue_execute_sql_callback(profile, profile->ireg_mutex, sql, sofia_presence_send_sql, profile);
switch_safe_free(sql);
}
switch_mutex_unlock(tech_pvt->profile->flag_mutex);
}
+
+void sofia_presence_check_subscriptions(sofia_profile_t *profile, time_t now)
+{
+ char *sql;
+
+ if (now) {
+ sql = switch_mprintf("select full_to, full_from, contact, expires, call_id, event, network_ip, network_port, "
+ "NULL as ct, NULL as pt "
+ " from sip_subscriptions where (expires = -1 or (expires > 0 and expires <= %ld)) and hostname='%q'",
+ (long) now, mod_sofia_globals.hostname);
+
+ sofia_glue_execute_sql_callback(profile, profile->ireg_mutex, sql, sofia_presence_send_sql, profile);
+ switch_safe_free(sql);
+
+ sql = switch_mprintf("delete from sip_subscriptions where (expires = -1 or (expires > 0 and expires <= %ld)) and hostname='%q'",
+ (long) now, mod_sofia_globals.hostname);
+ sofia_glue_actually_execute_sql(profile, sql, NULL);
+ }
+
+
+
+}
+
+
/* For Emacs:
* Local Variables:
* mode:c
+++ /dev/null
-/*
- * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
- * Copyright (C) 2005-2011, Anthony Minessale II <anthm@freeswitch.org>
- *
- * Version: MPL 1.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
- *
- * The Initial Developer of the Original Code is
- * Anthony Minessale II <anthm@freeswitch.org>
- * Portions created by the Initial Developer are Copyright (C)
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *
- * Anthony Minessale II <anthm@freeswitch.org>
- * Ken Rice, Asteria Solutions Group, Inc <ken@asteriasgi.com>
- * Paul D. Tinsley <pdt at jackhammer.org>
- * Bret McDanel <trixter AT 0xdecafbad.com>
- * Brian West <brian@freeswitch.org>
- *
- * sofia_sla.c -- SOFIA SIP Endpoint (support for shared line appearance)
- * This file (and calls into it) developed by Matthew T Kaufman <matthew@matthew.at>
- *
- */
-#include "mod_sofia.h"
-
-static int sofia_sla_sub_callback(void *pArg, int argc, char **argv, char **columnNames);
-
-struct sla_helper {
- char call_id[1024];
-};
-
-static int get_call_id_callback(void *pArg, int argc, char **argv, char **columnNames)
-{
- struct sla_helper *sh = (struct sla_helper *) pArg;
-
- switch_set_string(sh->call_id, argv[0]);
- 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,
- sofia_dispatch_event_t *de, long exptime, const char *full_contact)
-{
- nua_handle_t *nh = NULL;
- char exp_str[256] = "";
- char my_contact[256] = "";
- char *sql;
- struct sla_helper sh = { {0} };
- char *contact_str = sofia_glue_strip_uri(full_contact);
- 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] = "";
- nua_handle_t *fnh = NULL;
-
- sofia_glue_get_addr(de->data->e_msg, 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, profile->ireg_mutex, sql, get_call_id_callback, &sh);
-
- free(sql);
-
- if (*sh.call_id) {
- if ((nh = nua_handle_by_call_id(profile->nua, sh.call_id))) {
- fnh = nh;
- } else {
- if ((sql = switch_mprintf("delete 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(profile, &sql, SWITCH_TRUE);
- }
- }
- }
-
- if (!nh) {
- nh = nua_handle(nua, NULL, NUTAG_URL(sip->sip_contact->m_url), TAG_NULL());
- }
-
- 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), "<sip:%s@%s%s;transport=%s>;expires=%s", profile->sla_contact,
- profile->extsipip, port_str, sofia_glue_transport2str(transport), exp_str);
- } else {
- switch_snprintf(my_contact, sizeof(my_contact), "<sip:%s@%s%s;transport=%s>;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;include-session-description"), SIPTAG_ACCEPT_STR("application/dialog-info+xml"), TAG_NULL());
-
-
- if (fnh) {
- nua_handle_unref(fnh);
- }
-
- sofia_glue_free_destination(dst);
-
- free(contact_str);
-}
-
-void sofia_sla_handle_sip_i_publish(nua_t *nua, sofia_profile_t *profile, nua_handle_t *nh, sip_t const *sip,
- sofia_dispatch_event_t *de, tagi_t tags[])
-{
- /* at present there's no SLA versions that we deal with that do publish. to be safe, we say "OK" */
- nua_respond(nh, SIP_200_OK, NUTAG_WITH_THIS_MSG(de->data->e_msg), TAG_END());
-}
-
-void sofia_sla_handle_sip_i_subscribe(nua_t *nua, const char *contact_str, sofia_profile_t *profile, nua_handle_t *nh, sip_t const *sip,
- sofia_dispatch_event_t *de, tagi_t tags[])
-{
- char *aor = NULL;
- char *subscriber = NULL;
- char *sql = NULL;
- char *route_uri = NULL;
- char *sla_contact = NULL;
- char network_ip[80];
- int network_port = 0;
- char port_str[25] = "";
-
- sofia_transport_t transport = sofia_glue_url2transport(sip->sip_contact->m_url);
-
- sofia_glue_get_addr(de->data->e_msg, network_ip, sizeof(network_ip), &network_port);
- /*
- * XXX MTK FIXME - we don't look at the tag to see if NUTAG_SUBSTATE(nua_substate_terminated) or
- * a Subscription-State header with state "terminated" and/or expiration of 0. So we never forget
- * about them here.
- * likewise, we also don't have a hook against nua_r_notify events, so we can't see nua_substate_terminated there.
- */
-
- /*
- * extracting AOR is weird...
- * the From is the main extension, not the third-party one...
- * and the contact has the phone's own network address, not the AOR address
- * so we do what openser's pua_bla does and...
- */
-
- /* We always store the AOR as the sipip and not the request so SLA works with NAT inside out */
- aor = switch_mprintf("sip:%s@%s", sip->sip_contact->m_url->url_user, profile->sipip);
-
- /*
- * ok, and now that we HAVE the AOR, we REALLY should go check in the XML config and see if this particular
- * extension is set up to have shared appearances managed. right now it is all-or-nothing on the profile,
- * which won't be sufficient for real life. FIXME XXX MTK
- */
-
- /* then the subscriber is the user at their network location... this is arguably the wrong way, but works so far... */
-
- subscriber = switch_mprintf("sip:%s@%s;transport=%s", sip->sip_from->a_url->url_user,
- sip->sip_contact->m_url->url_host, sofia_glue_transport2str(transport));
-
- if ((sql =
- switch_mprintf("delete from sip_shared_appearance_subscriptions where subscriber='%q' and profile_name='%q' and hostname='%q'",
- subscriber, profile->name, mod_sofia_globals.hostname))) {
- sofia_glue_execute_sql(profile, &sql, SWITCH_TRUE);
- }
-
- if ((sql =
- switch_mprintf("insert into sip_shared_appearance_subscriptions (subscriber, call_id, aor, profile_name, hostname, contact_str, network_ip) "
- "values ('%q','%q','%q','%q','%q','%q','%q')",
- subscriber, sip->sip_call_id->i_id, aor, profile->name, mod_sofia_globals.hostname, contact_str, network_ip))) {
- sofia_glue_execute_sql(profile, &sql, SWITCH_TRUE);
- }
-
- if (strstr(contact_str, ";fs_nat")) {
- char *p;
- route_uri = sofia_glue_get_url_from_contact((char *) contact_str, 1);
- if ((p = strstr(contact_str, ";fs_"))) {
- *p = '\0';
- }
- }
-
- if (route_uri) {
- char *p;
-
- while (route_uri && *route_uri && (*route_uri == '<' || *route_uri == ' ')) {
- route_uri++;
- }
- if ((p = strchr(route_uri, '>'))) {
- *p++ = '\0';
- }
- }
-
- 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)) {
- sla_contact = switch_mprintf("<sip:%s@%s%s;transport=%s>", profile->sla_contact, profile->extsipip, port_str, sofia_glue_transport2str(transport));
- } else {
- sla_contact = switch_mprintf("<sip:%s@%s%s;transport=%s>", profile->sla_contact, profile->sipip, port_str, sofia_glue_transport2str(transport));
- }
-
- nua_respond(nh, SIP_202_ACCEPTED, SIPTAG_CONTACT_STR(sla_contact), NUTAG_WITH_THIS_MSG(de->data->e_msg), TAG_IF(route_uri, NUTAG_PROXY(route_uri)), SIPTAG_SUBSCRIPTION_STATE_STR("active;expires=300"), /* you thought the OTHER time was fake... need delta here FIXME XXX MTK */
- SIPTAG_EXPIRES_STR("300"), /* likewise, totally fake - FIXME XXX MTK */
- /* sofia_presence says something about needing TAG_IF(sticky, NUTAG_PROXY(sticky)) for NAT stuff? */
- TAG_END());
-
- switch_safe_free(aor);
- switch_safe_free(subscriber);
- switch_safe_free(route_uri);
- switch_safe_free(sla_contact);
- switch_safe_free(sql);
-}
-
-struct sla_notify_helper {
- sofia_profile_t *profile;
- char *payload;
-};
-
-void sofia_sla_handle_sip_r_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,
- tagi_t tags[])
-{
- if (status >= 300) {
- nua_handle_destroy(nh);
- sofia_private_free(sofia_private);
- } else {
- char *full_contact = sip_header_as_string(nua_handle_home(nh), (void *) sip->sip_contact);
- time_t expires = switch_epoch_time_now(NULL);
- char *sql;
- char *contact_str = sofia_glue_strip_uri(full_contact);
-
- if (sip && sip->sip_expires) {
- expires += sip->sip_expires->ex_delta + 30;
- }
-
- if ((sql = switch_mprintf("insert into sip_shared_appearance_dialogs (profile_name, hostname, contact_str, call_id, expires) "
- "values ('%q','%q','%q','%q','%ld')",
- profile->name, mod_sofia_globals.hostname, contact_str, sip->sip_call_id->i_id, (long) expires))) {
- sofia_glue_execute_sql(profile, &sql, SWITCH_TRUE);
- }
-
- free(contact_str);
- }
-}
-
-void sofia_sla_handle_sip_i_notify(nua_t *nua, sofia_profile_t *profile, nua_handle_t *nh, sip_t const *sip,
- sofia_dispatch_event_t *de, tagi_t tags[])
-{
- char *sql = NULL;
- struct sla_notify_helper helper;
- char *aor = NULL;
- char *contact = NULL;
- sofia_transport_t transport = sofia_glue_url2transport(sip->sip_contact->m_url);
-
- /*
- * things we know we don't do:
- * draft-anil-sipping-bla says we should look and see if the specific appearance is in use and if it is
- * return an error for the i_notify, to handle the initial line-seize for dialing out case.
- * to do that we would need to really track all the appearances *and* override sofia's autoresponder for i_notify
- * because at this point, it already sent the 200 for us.
- * and we simply don't track all the appearance status by decoding the XML payload out and recording that in
- * an SQL line appearance database yet. we'll need to do that in order to do the above, and in order to make
- * interoperation possible between devices that disagree on the dialog xml payload OR don't even do it that
- * way and instead use things like call-info/line-seize events like the old Broadsoft spec.
- * instead we cheat and just reflect the entire payload back to the subscribers (who, because we don't
- * yet check each AOR as it comes in to see if it is to be managed, is more subscribers than we probably
- * should have). for the current prototype stage, this works ok anyway.
- * and because we don't parse the XML, we even reflect it right back to the notifier/sender (which is called
- * "target" in the payload XML, of course).
- * also because we don't track on a per-appearance basis, there IS NOT a hook back from sofia_glue to add
- * an appearance index to the outbound invite for the "next free appearance". this can lead to race
- * conditions where a call shows up on slightly different line key numbers at different phones, making
- * "pick up on line X" meaningless if such a race occurs. again, it is a prototype. we can fix it later.
- */
-
-
- /* the dispatcher calls us just because it is aimed at us, so check to see if it is dialog;sla at the very least... */
-
- if ((!sip->sip_event)
- || (strcasecmp(sip->sip_event->o_type, "dialog"))
- || !msg_params_find(sip->sip_event->o_params, "sla")) {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "sent to sla-agent but not dialog;sla\n");
- return;
- }
-
- /* calculate the AOR we're trying to tell people about. should probably double-check before derferencing XXX MTK */
- /* We always store the AOR as the sipip and not the request so SLA works with NAT inside out */
- aor = switch_mprintf("sip:%s@%s", sip->sip_to->a_url->url_user, profile->sipip);
-
- /* this isn't sufficient because on things like the polycom, the subscriber is the 'main' ext number, but the
- * 'main' ext number isn't in ANY of the headers they send us in the notify. of course.
- * as a side effect, the subscriber<>'%q' below isn't sufficient to prevent reflecting the event back
- * at a phone that has the ext # != third-party#. see above, can only fix by parsing the XML for the 'target'
- * so we don't reflect it back at anyone who is the "boss" config, but we do reflect it back at the "secretary"
- * config. if that breaks the phone, just set them all up as the "boss" config where ext#==third-party#
- */
- contact = switch_mprintf("sip:%s@%s;transport=%s", sip->sip_contact->m_url->url_user,
- sip->sip_contact->m_url->url_host, sofia_glue_transport2str(transport));
-
- if (sip->sip_payload && sip->sip_payload->pl_data) {
- sql = switch_mprintf("select subscriber,call_id,aor,profile_name,hostname,contact_str,network_ip from sip_shared_appearance_subscriptions where "
- "aor='%q' and profile_name='%q' and hostname='%q'", aor, profile->name, mod_sofia_globals.hostname);
-
- helper.profile = profile;
- 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, profile->ireg_mutex, sql, sofia_sla_sub_callback, &helper);
-
- switch_safe_free(sql);
- switch_safe_free(aor);
- switch_safe_free(contact);
- }
-}
-
-static int sofia_sla_sub_callback(void *pArg, int argc, char **argv, char **columnNames)
-{
- struct sla_notify_helper *helper = pArg;
- /* char *subscriber = argv[0]; */
- char *call_id = argv[1];
- /* char *aor = argv[2]; */
- /* char *profile_name = argv[3]; */
- /* char *hostname = argv[4]; */
- char *contact_str = argv[5];
- char *network_ip = argv[6];
- nua_handle_t *nh;
- char *route_uri = NULL;
- char *xml_fixup = NULL;
- char *fixup = NULL;
- nh = nua_handle_by_call_id(helper->profile->nua, call_id); /* that's all you need to find the subscription's nh */
-
- if (nh) {
-
- if (strstr(contact_str, ";fs_nat")) {
- char *p;
- route_uri = sofia_glue_get_url_from_contact(contact_str, 1);
- if ((p = strstr(contact_str, ";fs_"))) {
- *p = '\0';
- }
- }
-
- if (route_uri) {
- char *p;
-
- while (route_uri && *route_uri && (*route_uri == '<' || *route_uri == ' ')) {
- route_uri++;
- }
- if ((p = strchr(route_uri, '>'))) {
- *p++ = '\0';
- }
- }
-
- if (helper->profile->extsipip) {
- if (sofia_glue_check_nat(helper->profile, network_ip)) {
- fixup = switch_string_replace(helper->payload, helper->profile->sipip, helper->profile->extsipip);
- } else {
- fixup = switch_string_replace(helper->payload, helper->profile->extsipip, helper->profile->sipip);
- }
- xml_fixup = fixup;
- } else {
- xml_fixup = helper->payload;
- }
-
- 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(xml_fixup), TAG_END());
- switch_safe_free(route_uri);
- if (fixup && fixup != helper->payload) {
- free(fixup);
- }
- nua_handle_unref(nh);
- }
- return 0;
-}