Merge remote branch 'fsorig/master'

Conflicts:
	libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_rcv.c
	libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_support.c
This commit is contained in:
Moises Silva committed 2011-12-17 17:21:14 -05:00
commit 7e31b9cc28
300 files changed
+15500 -6153

No files matched your search

+1 -1
View File
@@ -9,7 +9,7 @@ SOFIAUA_BUILDDIR=$(SOFIA_BUILDDIR)/libsofia-sip-ua
SOFIALA=$(SOFIAUA_BUILDDIR)/libsofia-sip-ua.la
mod_LTLIBRARIES = mod_sofia.la
mod_sofia_la_SOURCES = mod_sofia.c sofia.c sofia_glue.c sofia_presence.c sofia_reg.c sofia_sla.c sip-dig.c mod_sofia.h
mod_sofia_la_SOURCES = mod_sofia.c sofia.c sofia_glue.c sofia_presence.c sofia_reg.c sip-dig.c mod_sofia.h
mod_sofia_la_CFLAGS = $(AM_CFLAGS) -I. $(SOFIA_CMD_LINE_CFLAGS)
mod_sofia_la_CFLAGS += -I$(SOFIAUA_DIR)/bnf -I$(SOFIAUA_BUILDDIR)/bnf
mod_sofia_la_CFLAGS += -I$(SOFIAUA_DIR)/http -I$(SOFIAUA_BUILDDIR)/http
@@ -321,10 +321,6 @@
RelativePath=".\sofia_reg.c"
>
</File>
<File
RelativePath=".\sofia_sla.c"
>
</File>
</Files>
<Globals>
</Globals>
@@ -143,7 +143,6 @@
<ClCompile Include="sofia_glue.c" />
<ClCompile Include="sofia_presence.c" />
<ClCompile Include="sofia_reg.c" />
<ClCompile Include="sofia_sla.c" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="mod_sofia.h" />
+211 -59
View File
@@ -250,6 +250,11 @@ char *generate_pai_str(private_object_t *tech_pvt)
const char *callee_name = NULL, *callee_number = NULL;
const char *var, *header, *ua = switch_channel_get_variable(tech_pvt->channel, "sip_user_agent");
char *pai = NULL;
const char *host = switch_channel_get_variable(tech_pvt->channel, "sip_to_host");
if (zstr(host)) {
host = tech_pvt->profile->sipip;
}
if (!sofia_test_pflag(tech_pvt->profile, PFLAG_PASS_CALLEE_ID) || !sofia_test_pflag(tech_pvt->profile, PFLAG_CID_IN_1XX) ||
((var = switch_channel_get_variable(tech_pvt->channel, "sip_cid_in_1xx")) && switch_false(var))) {
@@ -276,7 +281,7 @@ char *generate_pai_str(private_object_t *tech_pvt)
callee_name = switch_sanitize_number(switch_core_session_strdup(session, callee_name));
if (!zstr(callee_number) && (zstr(ua) || !switch_stristr("polycom", ua))) {
callee_number = switch_core_session_sprintf(session, "sip:%s@%s", callee_number, tech_pvt->profile->sipip);
callee_number = switch_core_session_sprintf(session, "sip:%s@%s", callee_number, host);
}
header = (tech_pvt->cid_type == CID_TYPE_RPID && !switch_stristr("aastra", ua)) ? "Remote-Party-ID" : "P-Asserted-Identity";
@@ -321,8 +326,11 @@ static int hangup_cause_to_sip(switch_call_cause_t cause)
case SWITCH_CAUSE_REDIRECTION_TO_NEW_DESTINATION:
return 410;
case SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER:
case SWITCH_CAUSE_INVALID_PROFILE:
return 502;
case SWITCH_CAUSE_INVALID_NUMBER_FORMAT:
case SWITCH_CAUSE_INVALID_URL:
case SWITCH_CAUSE_INVALID_GATEWAY:
return 484;
case SWITCH_CAUSE_FACILITY_REJECTED:
return 501;
@@ -333,6 +341,7 @@ static int hangup_cause_to_sip(switch_call_cause_t cause)
case SWITCH_CAUSE_NETWORK_OUT_OF_ORDER:
case SWITCH_CAUSE_NORMAL_TEMPORARY_FAILURE:
case SWITCH_CAUSE_SWITCH_CONGESTION:
case SWITCH_CAUSE_GATEWAY_DOWN:
return 503;
case SWITCH_CAUSE_OUTGOING_CALL_BARRED:
case SWITCH_CAUSE_INCOMING_CALL_BARRED:
@@ -484,11 +493,12 @@ switch_status_t sofia_on_hangup(switch_core_session_t *session)
const char *val = NULL;
val = switch_channel_get_variable(tech_pvt->channel, "disable_q850_reason");
if (!val || switch_true(val)) {
if (cause > 0 && cause < 128) {
switch_snprintf(reason, sizeof(reason), "Q.850;cause=%d;text=\"%s\"", cause, switch_channel_cause2str(cause));
} else if (cause == SWITCH_CAUSE_PICKED_OFF || cause == SWITCH_CAUSE_LOSE_RACE) {
if (switch_false(val)) {
if (switch_channel_test_flag(channel, CF_INTERCEPT) || cause == SWITCH_CAUSE_PICKED_OFF || cause == SWITCH_CAUSE_LOSE_RACE) {
switch_snprintf(reason, sizeof(reason), "SIP;cause=200;text=\"Call completed elsewhere\"");
} else if (cause > 0 && cause < 128) {
switch_snprintf(reason, sizeof(reason), "Q.850;cause=%d;text=\"%s\"", cause, switch_channel_cause2str(cause));
} else {
switch_snprintf(reason, sizeof(reason), "%s;cause=%d;text=\"%s\"", tech_pvt->profile->username, cause, switch_channel_cause2str(cause));
}
@@ -952,7 +962,6 @@ static switch_status_t sofia_read_frame(switch_core_session_t *session, switch_f
while (!(tech_pvt->read_codec.implementation && switch_rtp_ready(tech_pvt->rtp_session) && !switch_channel_test_flag(channel, CF_REQ_MEDIA))) {
switch_ivr_parse_all_messages(tech_pvt->session);
if (--sanity && switch_channel_up(channel)) {
switch_yield(10000);
} else {
@@ -1009,39 +1018,66 @@ static switch_status_t sofia_read_frame(switch_core_session_t *session, switch_f
switch_event_t *event;
if (switch_event_create(&event, SWITCH_EVENT_RECV_RTCP_MESSAGE) == SWITCH_STATUS_SUCCESS) {
char buf[30];
char value[30];
char header[50];
int i;
char *uuid = switch_core_session_get_uuid(session);
if (uuid) {
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Unique-ID", switch_core_session_get_uuid(session));
}
snprintf(buf, sizeof(buf), "%.8x", rtcp_frame.ssrc);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "SSRC", buf);
snprintf(value, sizeof(value), "%.8x", rtcp_frame.ssrc);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "SSRC", value);
snprintf(buf, sizeof(buf), "%u", rtcp_frame.ntp_msw);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "NTP-Most-Significant-Word", buf);
snprintf(value, sizeof(value), "%u", rtcp_frame.ntp_msw);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "NTP-Most-Significant-Word", value);
snprintf(buf, sizeof(buf), "%u", rtcp_frame.ntp_lsw);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "NTP-Least-Significant-Word", buf);
snprintf(value, sizeof(value), "%u", rtcp_frame.ntp_lsw);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "NTP-Least-Significant-Word", value);
snprintf(buf, sizeof(buf), "%u", rtcp_frame.timestamp);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "RTP-Timestamp", buf);
snprintf(value, sizeof(value), "%u", rtcp_frame.timestamp);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "RTP-Timestamp", value);
snprintf(buf, sizeof(buf), "%u", rtcp_frame.packet_count);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Sender-Packet-Count", buf);
snprintf(value, sizeof(value), "%u", rtcp_frame.packet_count);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Sender-Packet-Count", value);
snprintf(buf, sizeof(buf), "%u", rtcp_frame.octect_count);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Octect-Packet-Count", buf);
snprintf(value, sizeof(value), "%u", rtcp_frame.octect_count);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Octect-Packet-Count", value);
snprintf(buf, sizeof(buf), "%" SWITCH_SIZE_T_FMT, tech_pvt->read_frame.timestamp);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Last-RTP-Timestamp", buf);
snprintf(value, sizeof(value), "%" SWITCH_SIZE_T_FMT, tech_pvt->read_frame.timestamp);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Last-RTP-Timestamp", value);
snprintf(buf, sizeof(buf), "%u", tech_pvt->read_frame.rate);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "RTP-Rate", buf);
snprintf(value, sizeof(value), "%u", tech_pvt->read_frame.rate);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "RTP-Rate", value);
snprintf(buf, sizeof(buf), "%" SWITCH_TIME_T_FMT, switch_time_now());
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Capture-Time", buf);
snprintf(value, sizeof(value), "%" SWITCH_TIME_T_FMT, switch_time_now());
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Capture-Time", value);
// Add sources info
for (i = 0; i < rtcp_frame.report_count; i++) {
snprintf(header, sizeof(header), "Source%u-SSRC", i);
snprintf(value, sizeof(value), "%.8x", rtcp_frame.reports[i].ssrc);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, header, value);
snprintf(header, sizeof(header), "Source%u-Fraction", i);
snprintf(value, sizeof(value), "%u", rtcp_frame.reports[i].fraction);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, header, value);
snprintf(header, sizeof(header), "Source%u-Lost", i);
snprintf(value, sizeof(value), "%u", rtcp_frame.reports[i].lost);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, header, value);
snprintf(header, sizeof(header), "Source%u-Highest-Sequence-Number-Received", i);
snprintf(value, sizeof(value), "%u", rtcp_frame.reports[i].highest_sequence_number_received);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, header, value);
snprintf(header, sizeof(header), "Source%u-Jitter", i);
snprintf(value, sizeof(value), "%u", rtcp_frame.reports[i].jitter);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, header, value);
snprintf(header, sizeof(header), "Source%u-LSR", i);
snprintf(value, sizeof(value), "%u", rtcp_frame.reports[i].lsr);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, header, value);
snprintf(header, sizeof(header), "Source%u-DLSR", i);
snprintf(value, sizeof(value), "%u", rtcp_frame.reports[i].dlsr);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, header, value);
}
switch_event_fire(&event);
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG10, "Dispatched RTCP event\n");
@@ -1504,6 +1540,9 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi
SWITCH_LOG_DEBUG, "Setting Jitterbuffer to %dms (%d frames) (%d max frames) (%d max drift)\n",
len, qlen, maxqlen, max_drift);
switch_channel_set_flag(tech_pvt->channel, CF_JITTERBUFFER);
if (!switch_false(switch_channel_get_variable(tech_pvt->channel, "sip_jitter_buffer_plc"))) {
switch_channel_set_flag(tech_pvt->channel, CF_JITTERBUFFER_PLC);
}
} else {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session),
SWITCH_LOG_WARNING, "Error Setting Jitterbuffer to %dms (%d frames)\n", len, qlen);
@@ -1782,6 +1821,28 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi
}
break;
case SWITCH_MESSAGE_INDICATE_AUDIO_DATA:
{
if (switch_rtp_ready(tech_pvt->rtp_session)) {
if (msg->numeric_arg) {
if (switch_channel_test_flag(tech_pvt->channel, CF_JITTERBUFFER)) {
switch_rtp_pause_jitter_buffer(tech_pvt->rtp_session, SWITCH_TRUE);
sofia_set_flag(tech_pvt, TFLAG_JB_PAUSED);
}
rtp_flush_read_buffer(tech_pvt->rtp_session, SWITCH_RTP_FLUSH_UNSTICK);
} else {
if (sofia_test_flag(tech_pvt, TFLAG_JB_PAUSED)) {
sofia_clear_flag(tech_pvt, TFLAG_JB_PAUSED);
if (switch_channel_test_flag(tech_pvt->channel, CF_JITTERBUFFER)) {
switch_rtp_pause_jitter_buffer(tech_pvt->rtp_session, SWITCH_FALSE);
}
}
}
}
}
break;
case SWITCH_MESSAGE_INDICATE_MEDIA_REDIRECT:
{
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s Sending media re-direct:\n%s\n",
@@ -1793,7 +1854,10 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi
}
sofia_set_flag_locked(tech_pvt, TFLAG_SENT_UPDATE);
switch_channel_set_flag(channel, CF_REQ_MEDIA);
if (!switch_channel_test_flag(channel, CF_PROXY_MEDIA)) {
switch_channel_set_flag(channel, CF_REQ_MEDIA);
}
sofia_glue_do_invite(session);
}
break;
@@ -1854,7 +1918,9 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi
sofia_glue_set_image_sdp(tech_pvt, t38_options, msg->numeric_arg);
switch_channel_set_flag(channel, CF_REQ_MEDIA);
if (!switch_channel_test_flag(channel, CF_PROXY_MEDIA)) {
switch_channel_set_flag(channel, CF_REQ_MEDIA);
}
sofia_set_flag_locked(tech_pvt, TFLAG_SENT_UPDATE);
sofia_glue_do_invite(session);
}
@@ -1892,7 +1958,9 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi
sofia_glue_set_local_sdp(tech_pvt, NULL, 0, NULL, 1);
if (send_invite) {
switch_channel_set_flag(channel, CF_REQ_MEDIA);
if (!switch_channel_test_flag(channel, CF_PROXY_MEDIA)) {
switch_channel_set_flag(channel, CF_REQ_MEDIA);
}
sofia_glue_do_invite(session);
} else {
status = SWITCH_STATUS_FALSE;
@@ -1918,6 +1986,43 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi
} else {
nua_notify(tech_pvt->nh, NUTAG_NEWSUB(1), NUTAG_SUBSTATE(nua_substate_active), SIPTAG_EVENT_STR(event), TAG_END());
}
}
case SWITCH_MESSAGE_INDICATE_INFO:
{
char *ct = "freeswitch/data";
int ok = 0;
if (!zstr(msg->string_array_arg[0]) && !zstr(msg->string_array_arg[1])) {
ct = switch_core_session_sprintf(session, "%s/%s", msg->string_array_arg[0], msg->string_array_arg[1]);
ok = 1;
}
if (switch_stristr("send_info", tech_pvt->x_freeswitch_support_remote)) {
ok = 1;
}
if (switch_true(switch_channel_get_variable(channel, "fs_send_unspported_info"))) {
ok = 1;
}
if (ok) {
char *headers = sofia_glue_get_extra_headers(channel, SOFIA_SIP_INFO_HEADER_PREFIX);
const char *pl = NULL;
if (!zstr(msg->string_array_arg[2])) {
pl = msg->string_array_arg[2];
}
nua_info(tech_pvt->nh,
SIPTAG_CONTENT_TYPE_STR(ct),
TAG_IF(!zstr(headers), SIPTAG_HEADER_STR(headers)),
TAG_IF(!zstr(tech_pvt->user_via), SIPTAG_VIA_STR(tech_pvt->user_via)),
TAG_IF(pl, SIPTAG_PAYLOAD_STR(pl)),
TAG_END());
} else {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s send_info is not supported.\n", switch_channel_get_name(channel));
}
}
break;
case SWITCH_MESSAGE_INDICATE_SIMPLIFY:
@@ -1989,6 +2094,9 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi
const char *ua = switch_channel_get_variable(tech_pvt->channel, "sip_user_agent");
switch_event_t *event;
check_decode(name, tech_pvt->session);
if (zstr(number)) {
number = tech_pvt->caller_profile->destination_number;
}
@@ -2306,7 +2414,7 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi
if (switch_channel_test_flag(channel, CF_PROXY_MEDIA)) {
sofia_glue_tech_patch_sdp(tech_pvt);
sofia_glue_tech_proxy_remote_addr(tech_pvt);
sofia_glue_tech_proxy_remote_addr(tech_pvt, NULL);
}
if (sofia_use_soa(tech_pvt)) {
nua_respond(tech_pvt->nh, code, su_strdup(nua_handle_home(tech_pvt->nh), reason), SIPTAG_CONTACT_STR(tech_pvt->reply_contact),
@@ -2569,7 +2677,7 @@ static switch_status_t sofia_receive_event(switch_core_session_t *session, switc
switch_mutex_lock(tech_pvt->sofia_mutex);
msg_nh = nua_handle(tech_pvt->profile->nua, NULL,
SIPTAG_FROM_STR(tech_pvt->chat_from),
NUTAG_URL(tech_pvt->chat_to), SIPTAG_TO_STR(tech_pvt->chat_to), SIPTAG_CONTACT_STR(tech_pvt->profile->url), TAG_END());
NUTAG_URL(tech_pvt->chat_to), SIPTAG_TO_STR(tech_pvt->chat_to), TAG_END());
nua_handle_bind(msg_nh, &mod_sofia_globals.destroy_private);
nua_message(msg_nh, SIPTAG_CONTENT_TYPE_STR("text/html"), SIPTAG_PAYLOAD_STR(body), TAG_END());
switch_mutex_unlock(tech_pvt->sofia_mutex);
@@ -2867,7 +2975,6 @@ static switch_status_t cmd_status(char **argv, int argc, switch_stream_handle_t
stream->write_function(stream, "CALLS-OUT \t%u\n", profile->ob_calls);
stream->write_function(stream, "FAILED-CALLS-OUT \t%u\n", profile->ob_failed_calls);
}
stream->write_function(stream, "\nRegistrations:\n%s\n", line);
cb.profile = profile;
cb.stream = stream;
@@ -2884,6 +2991,12 @@ static switch_status_t cmd_status(char **argv, int argc, switch_stream_handle_t
"network_ip,network_port,sip_username,sip_realm,mwi_user,mwi_host"
" from sip_registrations where profile_name='%q' and contact like '%%%q%%'", profile->name, argv[3]);
}
if (!sql && argv[2] && !strcasecmp(argv[2], "reg")) {
sql = switch_mprintf("select call_id,sip_user,sip_host,contact,status,"
"rpid,expires,user_agent,server_user,server_host,profile_name,hostname,"
"network_ip,network_port,sip_username,sip_realm,mwi_user,mwi_host"
" from sip_registrations where profile_name='%q'", profile->name);
}
if (!sql && argv[2] && !strcasecmp(argv[2], "user") && argv[3]) {
char *dup = strdup(argv[3]);
char *host = NULL, *user = NULL;
@@ -2914,20 +3027,18 @@ static switch_status_t cmd_status(char **argv, int argc, switch_stream_handle_t
switch_safe_free(sqlextra);
}
if (!sql) {
sql = switch_mprintf("select call_id,sip_user,sip_host,contact,status,"
"rpid,expires,user_agent,server_user,server_host,profile_name,hostname,"
"network_ip,network_port,sip_username,sip_realm,mwi_user,mwi_host"
" from sip_registrations where profile_name='%q'", profile->name);
if (sql) {
stream->write_function(stream, "\nRegistrations:\n%s\n", line);
sofia_glue_execute_sql_callback(profile, profile->ireg_mutex, sql, show_reg_callback, &cb);
switch_safe_free(sql);
stream->write_function(stream, "Total items returned: %d\n", cb.row_process);
stream->write_function(stream, "%s\n", line);
}
sofia_glue_execute_sql_callback(profile, profile->ireg_mutex, sql, show_reg_callback, &cb);
switch_safe_free(sql);
stream->write_function(stream, "Total items returned: %d\n", cb.row_process);
stream->write_function(stream, "%s\n", line);
sofia_glue_release_profile(profile);
} else {
stream->write_function(stream, "Invalid Profile!\n");
}
@@ -3973,7 +4084,7 @@ SWITCH_STANDARD_API(sofia_function)
" siptrace <on|off>\n"
" capture <on|off>\n"
" watchdog <on|off>\n\n"
"sofia <status|xmlstatus> profile <name> [reg <contact str>] | [pres <pres str>] | [user <user@domain>]\n"
"sofia <status|xmlstatus> profile <name> [reg [<contact str>]] | [pres <pres str>] | [user <user@domain>]\n"
"sofia <status|xmlstatus> gateway <name>\n\n"
"sofia loglevel <all|default|tport|iptsec|nea|nta|nth_client|nth_server|nua|soa|sresolv|stun> [0-9]\n"
"sofia tracelevel <console|alert|crit|err|warning|notice|info|debug>\n\n"
@@ -4033,6 +4144,7 @@ SWITCH_STANDARD_API(sofia_function)
int ston = -1;
int cton = -1;
int wdon = -1;
int stbyon = -1;
if (argc > 1) {
if (!strcasecmp(argv[1], "debug")) {
@@ -4068,6 +4180,12 @@ SWITCH_STANDARD_API(sofia_function)
}
}
if (!strcasecmp(argv[1], "standby")) {
if (argc > 2) {
stbyon = switch_true(argv[2]);
}
}
if (!strcasecmp(argv[1], "capture")) {
if (argc > 2) {
cton = switch_true(argv[2]);
@@ -4085,11 +4203,14 @@ SWITCH_STANDARD_API(sofia_function)
sofia_glue_global_siptrace(ston);
stream->write_function(stream, "+OK Global siptrace %s", ston ? "on" : "off");
} else if (cton != -1) {
sofia_glue_global_capture(cton);
stream->write_function(stream, "+OK Global capture %s", cton ? "on" : "off");
sofia_glue_global_capture(cton);
stream->write_function(stream, "+OK Global capture %s", cton ? "on" : "off");
} else if (wdon != -1) {
sofia_glue_global_watchdog(wdon);
stream->write_function(stream, "+OK Global watchdog %s", wdon ? "on" : "off");
} else if (stbyon != -1) {
sofia_glue_global_standby(stbyon);
stream->write_function(stream, "+OK Global standby %s", stbyon ? "on" : "off");
} else {
stream->write_function(stream, "-ERR Usage: siptrace <on|off>|capture <on|off>|watchdog <on|off>|debug <sla|presence|none");
}
@@ -4102,10 +4223,23 @@ SWITCH_STANDARD_API(sofia_function)
stream->write_function(stream, "Flushing recovery database.\n");
} else {
int x = sofia_glue_recover(SWITCH_FALSE);
switch_event_t *event = NULL;
if (x) {
if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM,
MY_EVENT_RECOVERY_RECOVERED) == SWITCH_STATUS_SUCCESS) {
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "recovered_calls", "%d", x);
switch_event_fire(&event);
}
stream->write_function(stream, "Recovered %d call(s)\n", x);
} else {
if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM,
MY_EVENT_RECOVERY_RECOVERED) == SWITCH_STATUS_SUCCESS) {
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "recovered_calls", "0");
switch_event_fire(&event);
}
stream->write_function(stream, "No calls to recover.\n");
}
}
@@ -4178,7 +4312,7 @@ static switch_call_cause_t sofia_outgoing_channel(switch_core_session_t *session
*new_session = NULL;
if (!outbound_profile || zstr(outbound_profile->destination_number)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Invalid Destination\n");
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Invalid Empty Destination\n");
goto error;
}
@@ -4215,30 +4349,30 @@ static switch_call_cause_t sofia_outgoing_channel(switch_core_session_t *session
char *gw, *params;
if (!(gw = strchr(profile_name, '/'))) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Invalid URL\n");
cause = SWITCH_CAUSE_INVALID_NUMBER_FORMAT;
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Invalid URL \'%s\'\n", profile_name);
cause = SWITCH_CAUSE_INVALID_URL;
goto error;
}
*gw++ = '\0';
if (!(dest = strchr(gw, '/'))) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Invalid URL\n");
cause = SWITCH_CAUSE_INVALID_NUMBER_FORMAT;
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Invalid URL \'%s\'\n", gw);
cause = SWITCH_CAUSE_INVALID_URL;
goto error;
}
*dest++ = '\0';
if (!(gateway_ptr = sofia_reg_find_gateway(gw))) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Invalid Gateway\n");
cause = SWITCH_CAUSE_INVALID_NUMBER_FORMAT;
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Invalid Gateway \'%s\'\n", gw);
cause = SWITCH_CAUSE_INVALID_GATEWAY;
goto error;
}
if (gateway_ptr->status != SOFIA_GATEWAY_UP) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Gateway is down!\n");
cause = SWITCH_CAUSE_NETWORK_OUT_OF_ORDER;
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Gateway \'%s\' is down!\n", gw);
cause = SWITCH_CAUSE_GATEWAY_DOWN;
gateway_ptr->ob_failed_calls++;
goto error;
}
@@ -4278,6 +4412,13 @@ static switch_call_cause_t sofia_outgoing_channel(switch_core_session_t *session
}
profile = gateway_ptr->profile;
if (profile && sofia_test_pflag(profile, PFLAG_STANDBY)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "System Paused\n");
cause = SWITCH_CAUSE_SYSTEM_SHUTDOWN;
goto error;
}
tech_pvt->gateway_name = switch_core_session_strdup(nsession, gateway_ptr->name);
switch_channel_set_variable(nchannel, "sip_gateway_name", gateway_ptr->name);
@@ -4345,14 +4486,20 @@ static switch_call_cause_t sofia_outgoing_channel(switch_core_session_t *session
} else {
if (!(dest = strchr(profile_name, '/'))) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Invalid URL\n");
cause = SWITCH_CAUSE_INVALID_NUMBER_FORMAT;
cause = SWITCH_CAUSE_INVALID_URL;
goto error;
}
*dest++ = '\0';
if (!(profile = sofia_glue_find_profile(profile_name))) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Invalid Profile\n");
cause = SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER;
cause = SWITCH_CAUSE_INVALID_PROFILE;
goto error;
}
if (profile && sofia_test_pflag(profile, PFLAG_STANDBY)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "System Paused\n");
cause = SWITCH_CAUSE_SYSTEM_SHUTDOWN;
goto error;
}
@@ -4465,6 +4612,8 @@ static switch_call_cause_t sofia_outgoing_channel(switch_core_session_t *session
if (profile->pres_type) {
char *sql;
time_t now;
const char *presence_id = switch_channel_get_variable(nchannel, "presence_id");
const char *presence_data = switch_channel_get_variable(nchannel, "presence_data");
@@ -4476,9 +4625,10 @@ static switch_call_cause_t sofia_outgoing_channel(switch_core_session_t *session
presence_data = switch_event_get_header(var_event, "presence_data");
}
sql = switch_mprintf("insert into sip_dialogs (uuid,presence_id,presence_data,profile_name,hostname) "
"values ('%q', '%q', '%q', '%q', '%q')", switch_core_session_get_uuid(nsession),
switch_str_nil(presence_id), switch_str_nil(presence_data), profile->name, mod_sofia_globals.hostname);
now = switch_epoch_time_now(NULL);
sql = switch_mprintf("insert into sip_dialogs (uuid,presence_id,presence_data,profile_name,hostname,rcd) "
"values ('%q', '%q', '%q', '%q', '%q', %ld)", switch_core_session_get_uuid(nsession),
switch_str_nil(presence_id), switch_str_nil(presence_data), profile->name, mod_sofia_globals.hostname, (long) now);
sofia_glue_actually_execute_sql(profile, sql, profile->ireg_mutex);
switch_safe_free(sql);
}
@@ -5284,6 +5434,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_sofia_load)
switch_console_set_complete("add sofia tracelevel ::[console:alert:crit:err:warning:notice:info:debug");
switch_console_set_complete("add sofia global siptrace ::[on:off");
switch_console_set_complete("add sofia global standby ::[on:off");
switch_console_set_complete("add sofia global capture ::[on:off");
switch_console_set_complete("add sofia global watchdog ::[on:off");
@@ -5398,3 +5549,4 @@ SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_sofia_shutdown)
* For VIM:
* vim:set softtabstop=4 shiftwidth=4 tabstop=4:
*/
+23 -23
View File
@@ -87,6 +87,7 @@ typedef struct private_object private_object_t;
#define MY_EVENT_GATEWAY_DEL "sofia::gateway_delete"
#define MY_EVENT_RECOVERY "sofia::recovery_recv"
#define MY_EVENT_RECOVERY_SEND "sofia::recovery_send"
#define MY_EVENT_RECOVERY_RECOVERED "sofia::recovery_recovered"
#define MULTICAST_EVENT "multicast::event"
#define SOFIA_REPLACES_HEADER "_sofia_replaces_"
@@ -95,6 +96,8 @@ typedef struct private_object private_object_t;
#define SOFIA_MULTIPART_PREFIX "sip_mp_"
#define SOFIA_MULTIPART_PREFIX_T "~sip_mp_"
#define SOFIA_SIP_HEADER_PREFIX "sip_h_"
#define SOFIA_SIP_INFO_HEADER_PREFIX "sip_info_h_"
#define SOFIA_SIP_INFO_HEADER_PREFIX_T "~sip_info_h_"
#define SOFIA_SIP_RESPONSE_HEADER_PREFIX "sip_rh_"
#define SOFIA_SIP_RESPONSE_HEADER_PREFIX_T "~sip_rh_"
#define SOFIA_SIP_BYE_HEADER_PREFIX "sip_bye_h_"
@@ -109,7 +112,7 @@ typedef struct private_object private_object_t;
#define SOFIA_SECURE_MEDIA_CONFIRMED_VARIABLE "sip_secure_media_confirmed"
#define SOFIA_HAS_CRYPTO_VARIABLE "sip_has_crypto"
#define SOFIA_CRYPTO_MANDATORY_VARIABLE "sip_crypto_mandatory"
#define FREESWITCH_SUPPORT "update_display"
#define FREESWITCH_SUPPORT "update_display,send_info"
#include <switch_stun.h>
#include <sofia-sip/nua.h>
@@ -128,6 +131,9 @@ typedef struct private_object private_object_t;
#include "sofia-sip/sip_parser.h"
#include "sofia-sip/tport_tag.h"
#include <sofia-sip/msg.h>
#ifndef WIN32
#include <sofia-sip/uniqueid.h>
#endif
typedef enum {
DTMF_2833,
@@ -200,6 +206,7 @@ typedef enum {
PFLAG_WORKER_RUNNING,
PFLAG_UNREG_OPTIONS_FAIL,
PFLAG_DISABLE_TIMER,
PFLAG_ENABLE_RFC5626,
PFLAG_DISABLE_100REL,
PFLAG_AGGRESSIVE_NAT_DETECTION,
PFLAG_RECIEVED_IN_NAT_REG_CONTACT,
@@ -214,7 +221,7 @@ typedef enum {
PFLAG_UUID_AS_CALLID,
PFLAG_SCROOGE,
PFLAG_MANAGE_SHARED_APPEARANCE,
PFLAG_MANAGE_SHARED_APPEARANCE_SYLANTRO,
PFLAG_STANDBY,
PFLAG_DISABLE_SRV,
PFLAG_DISABLE_SRV503,
PFLAG_DISABLE_NAPTR,
@@ -230,6 +237,7 @@ typedef enum {
PFLAG_AUTO_NAT,
PFLAG_SIPCOMPACT,
PFLAG_SQL_IN_TRANS,
PFLAG_PRESENCE_PRIVACY,
PFLAG_PASS_CALLEE_ID,
PFLAG_LOG_AUTH_FAIL,
PFLAG_FORWARD_MWI_NOTIFY,
@@ -253,6 +261,8 @@ typedef enum {
PFLAG_AUTO_ASSIGN_PORT,
PFLAG_AUTO_ASSIGN_TLS_PORT,
PFLAG_SHUTDOWN,
PFLAG_PRESENCE_MAP,
PFLAG_OPTIONS_RESPOND_503_ON_BUSY,
/* No new flags below this line */
PFLAG_MAX
} PFLAGS;
@@ -472,6 +482,7 @@ struct sofia_gateway {
int32_t retry_seconds;
int32_t reg_timeout_seconds;
int32_t failure_status;
sub_state_t sub_state;
reg_state_t state;
switch_memory_pool_t *pool;
int deleted;
@@ -543,6 +554,7 @@ struct sofia_profile {
char *record_template;
char *record_path;
char *presence_hosts;
char *presence_privacy;
char *challenge_realm;
char *rtcp_audio_interval_msec;
char *rtcp_video_interval_msec;
@@ -625,6 +637,8 @@ struct sofia_profile {
uint32_t event_timeout;
int watchdog_enabled;
switch_mutex_t *gw_mutex;
uint32_t queued_events;
uint32_t cseq_base;
};
struct private_object {
@@ -790,6 +804,7 @@ typedef enum {
AUTH_OK,
AUTH_FORBIDDEN,
AUTH_STALE,
AUTH_RENEWED,
} auth_res_t;
typedef struct {
@@ -830,6 +845,8 @@ switch_mutex_unlock(obj->flag_mutex);
/* Function Prototypes */
/*************************************************************************************************************************************************************/
void sofia_glue_global_standby(switch_bool_t on);
switch_status_t sofia_glue_activate_rtp(private_object_t *tech_pvt, switch_rtp_flag_t myflags);
void sofia_glue_deactivate_rtp(private_object_t *tech_pvt);
@@ -1033,7 +1050,7 @@ int sofia_glue_transport_has_tls(const sofia_transport_t tp);
const char *sofia_glue_get_unknown_header(sip_t const *sip, const char *name);
switch_status_t sofia_glue_build_crypto(private_object_t *tech_pvt, int index, switch_rtp_crypto_key_type_t type, switch_rtp_crypto_direction_t direction);
void sofia_glue_tech_patch_sdp(private_object_t *tech_pvt);
switch_status_t sofia_glue_tech_proxy_remote_addr(private_object_t *tech_pvt);
switch_status_t sofia_glue_tech_proxy_remote_addr(private_object_t *tech_pvt, const char *sdp_str);
void sofia_presence_event_thread_start(void);
void sofia_reg_expire_call_id(sofia_profile_t *profile, const char *call_id, int reboot);
void sofia_reg_check_call_id(sofia_profile_t *profile, const char *call_id);
@@ -1055,24 +1072,6 @@ switch_status_t sofia_glue_tech_set_codec(private_object_t *tech_pvt, int force)
void sofia_wait_for_reply(struct private_object *tech_pvt, nua_event_t event, uint32_t timeout);
void sofia_glue_set_image_sdp(private_object_t *tech_pvt, switch_t38_options_t *t38_options, int insist);
/*
* SLA (shared line appearance) entrypoints
*/
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);
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[]);
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[]);
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[]);
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[]);
/*
* Logging control functions
*/
@@ -1104,7 +1103,7 @@ void sofia_glue_free_destination(sofia_destination_t *dst);
switch_status_t sofia_glue_send_notify(sofia_profile_t *profile, const char *user, const char *host, const char *event, const char *contenttype,
const char *body, const char *o_contact, const char *network_ip);
char *sofia_glue_get_extra_headers(switch_channel_t *channel, const char *prefix);
void sofia_glue_set_extra_headers(switch_channel_t *channel, sip_t const *sip, const char *prefix);
void sofia_glue_set_extra_headers(switch_core_session_t *session, sip_t const *sip, const char *prefix);
void sofia_info_send_sipfrag(switch_core_session_t *aleg, switch_core_session_t *bleg);
void sofia_update_callee_id(switch_core_session_t *session, sofia_profile_t *profile, sip_t const *sip, switch_bool_t send);
void sofia_send_callee_id(switch_core_session_t *session, const char *name, const char *number);
@@ -1135,4 +1134,5 @@ 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);
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);
void sofia_presence_check_subscriptions(sofia_profile_t *profile, time_t now);
+421 -91
View File
@@ -31,6 +31,7 @@
* Norman Brandinger
* Raymond Chandler <intralanman@gmail.com>
* Nathan Patrick <npatrick at corp.sonic.net>
* Joseph Sullivan <jossulli@amazon.com>
*
*
* sofia.c -- SOFIA SIP Endpoint (sofia code)
@@ -89,7 +90,8 @@ 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("delete from sip_subscriptions where call_id='%q'", sip->sip_call_id->i_id);
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);
switch_assert(sql != NULL);
sofia_glue_execute_sql(profile, &sql, SWITCH_TRUE);
nua_handle_destroy(nh);
@@ -182,15 +184,78 @@ static void extract_header_vars(sofia_profile_t *profile, sip_t const *sip,
su_free(nh->nh_home, full);
}
}
if (sip->sip_via) {
if ((full = sip_header_as_string(nh->nh_home, (void *) sip->sip_via))) {
const char *v = switch_channel_get_variable(channel, "sip_full_via");
if (!v) {
switch_channel_set_variable(channel, "sip_full_via", full);
}
su_free(nh->nh_home, full);
if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) {
if (sip->sip_contact) {
char *c = sip_header_as_string(nh->nh_home, (void *) sip->sip_contact);
switch_channel_set_variable(channel, "sip_recover_contact", c);
su_free(nh->nh_home, c);
}
}
if (sip->sip_record_route) {
sip_record_route_t *rrp;
switch_stream_handle_t stream = { 0 };
int x = 0;
SWITCH_STANDARD_STREAM(stream);
if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) {
char *tmp[128] = { 0 };
int y = 0;
for(rrp = sip->sip_record_route; rrp; rrp = rrp->r_next) {
char *rr = sip_header_as_string(nh->nh_home, (void *) rrp);
tmp[y++] = rr;
if (y == 127) break;
}
y--;
while(y >= 0) {
stream.write_function(&stream, x == 0 ? "%s" : ",%s", tmp[y]);
su_free(nh->nh_home, tmp[y]);
y--;
x++;
}
} else {
for(rrp = sip->sip_record_route; rrp; rrp = rrp->r_next) {
char *rr = sip_header_as_string(nh->nh_home, (void *) rrp);
stream.write_function(&stream, x == 0 ? "%s" : ",%s", rr);
su_free(nh->nh_home, rr);
x++;
}
}
switch_channel_set_variable(channel, "sip_invite_record_route", (char *)stream.data);
free(stream.data);
}
if (sip->sip_via) {
sip_via_t *vp;
switch_stream_handle_t stream = { 0 };
int x = 0;
if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) {
SWITCH_STANDARD_STREAM(stream);
for(vp = sip->sip_via; vp; vp = vp->v_next) {
char *v = sip_header_as_string(nh->nh_home, (void *) vp);
stream.write_function(&stream, x == 0 ? "%s" : ",%s", v);
su_free(nh->nh_home, v);
x++;
}
switch_channel_set_variable(channel, "sip_recover_via", (char *)stream.data);
free(stream.data);
}
}
if (sip->sip_from) {
char *p = strip_quotes(sip->sip_from->a_display);
@@ -203,6 +268,7 @@ static void extract_header_vars(sofia_profile_t *profile, sip_t const *sip,
su_free(nh->nh_home, full);
}
}
if (sip->sip_to) {
char *p = strip_quotes(sip->sip_to->a_display);
@@ -274,21 +340,6 @@ void sofia_handle_sip_i_notify(switch_core_session_t *session, int status,
goto error;
}
/* the following could be refactored back to the calling event handler here in sofia.c XXX MTK */
/* potentially interesting note: for Linksys shared appearance, we'll probably have to set up to get bare notifies
* and pass them inward to the sla handler. we'll have to set NUTAG_APPL_METHOD("NOTIFY") when creating
* nua, and also pick them off special elsewhere here in sofia.c - MTK
* *and* for Linksys, I believe they use "sa" as their magic appearance agent name for those blind notifies, so
* we'll probably have to change to match
*/
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"))) {
sofia_sla_handle_sip_i_notify(nua, profile, nh, sip, de, tags);
goto end;
}
}
/* Automatically return a 200 OK for Event: keep-alive */
if (!strcasecmp(sip->sip_event->o_type, "keep-alive")) {
/* XXX MTK - is this right? in this case isn't sofia is already sending a 200 itself also? */
@@ -413,7 +464,7 @@ void sofia_handle_sip_i_notify(switch_core_session_t *session, int status,
/* dispatch freeswitch event */
if (switch_event_create(&s_event, SWITCH_EVENT_NOTIFY_IN) == SWITCH_STATUS_SUCCESS) {
switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "event", sip->sip_event->o_type);
switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "pl_data", sip->sip_payload->pl_data);
switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "pl_data", sip->sip_payload ? sip->sip_payload->pl_data : "");
switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "sip_content_type", sip->sip_content_type->c_type);
switch_event_add_header(s_event, SWITCH_STACK_BOTTOM, "port", "%d", sofia_private->gateway->profile->sip_port);
switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "module_name", "mod_sofia");
@@ -545,7 +596,6 @@ void sofia_handle_sip_i_bye(switch_core_session_t *session, int status,
switch_snprintf(st, sizeof(st), "%d", status);
switch_channel_set_variable(channel, "sip_term_status", st);
switch_snprintf(st, sizeof(st), "sip:%d", status);
switch_channel_set_variable_partner(channel, SWITCH_PROTO_SPECIFIC_HANGUP_CAUSE_VARIABLE, st);
switch_channel_set_variable(channel, SWITCH_PROTO_SPECIFIC_HANGUP_CAUSE_VARIABLE, st);
if (phrase) {
@@ -556,7 +606,7 @@ void sofia_handle_sip_i_bye(switch_core_session_t *session, int status,
switch_channel_set_variable(channel, "sip_term_cause", st);
extra_headers = sofia_glue_get_extra_headers(channel, SOFIA_SIP_BYE_HEADER_PREFIX);
sofia_glue_set_extra_headers(channel, sip, SOFIA_SIP_BYE_HEADER_PREFIX);
sofia_glue_set_extra_headers(session, sip, SOFIA_SIP_BYE_HEADER_PREFIX);
if (!(vval = switch_channel_get_variable(channel, "sip_copy_custom_headers")) || switch_true(vval)) {
switch_core_session_t *nsession = NULL;
@@ -695,6 +745,7 @@ void sofia_update_callee_id(switch_core_session_t *session, sofia_profile_t *pro
if ((val = sofia_glue_get_unknown_header(sip, "X-FS-Display-Name"))) {
name = (char *) val;
check_decode(name, session);
fs++;
}
@@ -806,8 +857,7 @@ static void our_sofia_event_callback(nua_event_t event,
int locked = 0;
int check_destroy = 1;
if (sofia_private && sofia_private->de) {
if (sofia_private && sofia_private->is_call && sofia_private->de) {
sofia_dispatch_event_t *qde = sofia_private->de;
sofia_private->de = NULL;
sofia_process_dispatch_event(&qde);
@@ -874,7 +924,7 @@ static void our_sofia_event_callback(nua_event_t event,
uint32_t sess_count = switch_core_session_count();
uint32_t sess_max = switch_core_session_limit(0);
if (sess_count >= sess_max || !sofia_test_pflag(profile, PFLAG_RUNNING) || !switch_core_ready()) {
if (sess_count >= sess_max || !sofia_test_pflag(profile, PFLAG_RUNNING) || !switch_core_ready_inbound()) {
nua_respond(nh, 503, "Maximum Calls In Progress", SIPTAG_RETRY_AFTER_STR("300"), TAG_END());
//switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "No more sessions allowed at this time.\n");
@@ -883,7 +933,8 @@ static void our_sofia_event_callback(nua_event_t event,
}
}
if (sofia_test_pflag(profile, PFLAG_AUTH_ALL) && tech_pvt && tech_pvt->key && sip) {
if (sofia_test_pflag(profile, PFLAG_AUTH_ALL) && tech_pvt && tech_pvt->key && sip && (event < nua_r_set_params || event > nua_r_authenticate)) {
sip_authorization_t const *authorization = NULL;
if (sip->sip_authorization) {
@@ -900,7 +951,7 @@ static void our_sofia_event_callback(nua_event_t event,
REG_INVITE, NULL, NULL, NULL);
}
if (auth_res != AUTH_OK) {
if ((auth_res != AUTH_OK && auth_res != AUTH_RENEWED)) {
//switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
nua_respond(nh, SIP_401_UNAUTHORIZED, TAG_END());
goto done;
@@ -1136,7 +1187,8 @@ void sofia_process_dispatch_event(sofia_dispatch_event_t **dep)
sofia_dispatch_event_t *de = *dep;
nua_handle_t *nh = de->nh;
nua_t *nua = de->nua;
sofia_profile_t *profile = de->profile;
*dep = NULL;
our_sofia_event_callback(de->data->e_event, de->data->e_status, de->data->e_phrase, de->nua, de->profile,
@@ -1144,6 +1196,10 @@ void sofia_process_dispatch_event(sofia_dispatch_event_t **dep)
nua_destroy_event(de->event);
su_free(nh->nh_home, de);
switch_mutex_lock(profile->flag_mutex);
profile->queued_events--;
switch_mutex_unlock(profile->flag_mutex);
nua_handle_unref(nh);
nua_stack_unref(nua);
@@ -1244,6 +1300,19 @@ void sofia_event_callback(nua_event_t event,
{
sofia_dispatch_event_t *de;
if (sofia_test_pflag(profile, PFLAG_STANDBY)) {
if (event < nua_r_set_params || event > nua_r_authenticate) {
nua_respond(nh, 503, "System Paused", TAG_END());
}
return;
}
switch_mutex_lock(profile->flag_mutex);
profile->queued_events++;
switch_mutex_unlock(profile->flag_mutex);
de = su_alloc(nh->nh_home, sizeof(*de));
memset(de, 0, sizeof(*de));
nua_save_event(nua, de->event);
@@ -1524,6 +1593,12 @@ void *SWITCH_THREAD_FUNC sofia_profile_worker_thread_run(switch_thread_t *thread
/* While we're running, or there is a pending sql statment that we haven't appended to sqlbuf yet, because of a lack of buffer space */
while ((mod_sofia_globals.running == 1 && sofia_test_pflag(profile, PFLAG_RUNNING)) || sql) {
if (sofia_test_pflag(profile, PFLAG_STANDBY)) {
switch_yield(1000000);
continue;
}
if (sofia_test_pflag(profile, PFLAG_SQL_IN_TRANS)) {
/* Do we have enough statements or is the timeout expired */
while (sql || (sofia_test_pflag(profile, PFLAG_RUNNING) && mod_sofia_globals.running == 1 &&
@@ -1745,6 +1820,7 @@ void *SWITCH_THREAD_FUNC sofia_profile_thread_run(switch_thread_t *thread, void
switch_event_t *s_event;
int use_100rel = !sofia_test_pflag(profile, PFLAG_DISABLE_100REL);
int use_timer = !sofia_test_pflag(profile, PFLAG_DISABLE_TIMER);
int use_rfc_5626 = sofia_test_pflag(profile, PFLAG_ENABLE_RFC5626);
const char *supported = NULL;
int sanity;
switch_thread_t *worker_thread;
@@ -1766,7 +1842,7 @@ void *SWITCH_THREAD_FUNC sofia_profile_thread_run(switch_thread_t *thread, void
goto end;
}
supported = switch_core_sprintf(profile->pool, "%s%sprecondition, path, replaces", use_100rel ? "100rel, " : "", use_timer ? "timer, " : "");
supported = switch_core_sprintf(profile->pool, "%s%s%sprecondition, path, replaces", use_100rel ? "100rel, " : "", use_timer ? "timer, " : "", use_rfc_5626 ? "outbound, " : "");
if (sofia_test_pflag(profile, PFLAG_AUTO_NAT) && switch_nat_get_type()) {
if (switch_nat_add_mapping(profile->sip_port, SWITCH_NAT_UDP, NULL, SWITCH_FALSE) == SWITCH_STATUS_SUCCESS) {
@@ -1971,7 +2047,7 @@ void *SWITCH_THREAD_FUNC sofia_profile_thread_run(switch_thread_t *thread, void
nua_shutdown(profile->nua);
sanity = 10;
while (!sofia_test_pflag(profile, PFLAG_SHUTDOWN)) {
while (!sofia_test_pflag(profile, PFLAG_SHUTDOWN) || profile->queued_events > 0) {
su_root_step(profile->s_root, 1000);
if (!--sanity) {
break;
@@ -2231,7 +2307,7 @@ static void parse_gateways(sofia_profile_t *profile, switch_xml_t gateways_tag)
if ((gateway = switch_core_alloc(profile->pool, sizeof(*gateway)))) {
const char *sipip, *format;
switch_uuid_t uuid;
uint32_t ping_freq = 0, extension_in_contact = 0, distinct_to = 0;
uint32_t ping_freq = 0, extension_in_contact = 0, distinct_to = 0, rfc_5626 = 0;
int ping_max = 1, ping_min = -1;
char *register_str = "true", *scheme = "Digest",
*realm = NULL,
@@ -2246,7 +2322,8 @@ static void parse_gateways(sofia_profile_t *profile, switch_xml_t gateways_tag)
*retry_seconds = "30",
*timeout_seconds = "60",
*from_user = "", *from_domain = NULL, *outbound_proxy = NULL, *register_proxy = NULL, *contact_host = NULL,
*contact_params = NULL, *params = NULL, *register_transport = NULL;
*contact_params = NULL, *params = NULL, *register_transport = NULL,
*reg_id = NULL, *str_rfc_5626 = NULL;
if (!context) {
context = "default";
@@ -2369,6 +2446,10 @@ static void parse_gateways(sofia_profile_t *profile, switch_xml_t gateways_tag)
outbound_proxy = val;
} else if (!strcmp(var, "distinct-to")) {
distinct_to = switch_true(val);
} else if (!strcmp(var, "rfc-5626")) {
rfc_5626 = switch_true(val);
} else if (!strcmp(var, "reg-id")) {
reg_id = val;
} else if (!strcmp(var, "contact-params")) {
contact_params = val;
} else if (!strcmp(var, "register-transport")) {
@@ -2382,6 +2463,17 @@ static void parse_gateways(sofia_profile_t *profile, switch_xml_t gateways_tag)
gateway->register_transport = transport;
}
}
#ifndef WIN32
/* Windows todo figure this out! */
/* RFC 5626 enable in the GW profile and the UA profile */
if (rfc_5626 && sofia_test_pflag(profile, PFLAG_ENABLE_RFC5626)) {
char str_guid[su_guid_strlen + 1];
su_guid_t guid[1];
su_guid_generate(guid);
su_guid_sprintf(str_guid, su_guid_strlen + 1, guid);
str_rfc_5626 = switch_core_sprintf(gateway->pool, ";reg-id=%s;+sip.instance=\"<urn:uuid:%s>\"",reg_id,str_guid);
}
#endif
if (ping_freq) {
if (ping_freq >= 5) {
@@ -2406,14 +2498,16 @@ static void parse_gateways(sofia_profile_t *profile, switch_xml_t gateways_tag)
}
}
if (zstr(username)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "ERROR: username param is REQUIRED!\n");
goto skip;
}
if (switch_true(register_str)) {
if (zstr(username)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "ERROR: username param is REQUIRED!\n");
goto skip;
}
if (zstr(password)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "ERROR: password param is REQUIRED!\n");
goto skip;
if (zstr(password)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "ERROR: password param is REQUIRED!\n");
goto skip;
}
}
if (zstr(from_user)) {
@@ -2546,17 +2640,36 @@ static void parse_gateways(sofia_profile_t *profile, switch_xml_t gateways_tag)
}
if (extension_in_contact) {
format = strchr(sipip, ':') ? "<sip:%s@[%s]:%d%s>" : "<sip:%s@%s:%d%s>";
gateway->register_contact = switch_core_sprintf(gateway->pool, format, extension,
sipip,
sofia_glue_transport_has_tls(gateway->register_transport) ?
profile->tls_sip_port : profile->sip_port, params);
if (rfc_5626) {
format = strchr(sipip, ':') ? "<sip:%s@[%s]:%d>%s" : "<sip:%s@%s:%d%s>%s";
gateway->register_contact = switch_core_sprintf(gateway->pool, format, extension,
sipip,
sofia_glue_transport_has_tls(gateway->register_transport) ?
profile->tls_sip_port : profile->sip_port, params, str_rfc_5626);
} else {
format = strchr(sipip, ':') ? "<sip:%s@[%s]:%d%s>" : "<sip:%s@%s:%d%s%s>";
gateway->register_contact = switch_core_sprintf(gateway->pool, format, extension,
sipip,
sofia_glue_transport_has_tls(gateway->register_transport) ?
profile->tls_sip_port : profile->sip_port, params,contact_params);
}
} else {
format = strchr(sipip, ':') ? "<sip:gw+%s@[%s]:%d%s>" : "<sip:gw+%s@%s:%d%s>";
gateway->register_contact = switch_core_sprintf(gateway->pool, format, gateway->name,
sipip,
sofia_glue_transport_has_tls(gateway->register_transport) ?
profile->tls_sip_port : profile->sip_port, params);
if (rfc_5626) {
format = strchr(sipip, ':') ? "<sip:gw+%s@[%s]:%d%s>%s" : "<sip:gw+%s@%s:%d%s>%s";
gateway->register_contact = switch_core_sprintf(gateway->pool, format, gateway->name,
sipip,
sofia_glue_transport_has_tls(gateway->register_transport) ?
profile->tls_sip_port : profile->sip_port, params, str_rfc_5626);
} else {
format = strchr(sipip, ':') ? "<sip:gw+%s@[%s]:%d%s>" : "<sip:gw+%s@%s:%d%s>";
gateway->register_contact = switch_core_sprintf(gateway->pool, format, gateway->name,
sipip,
sofia_glue_transport_has_tls(gateway->register_transport) ?
profile->tls_sip_port : profile->sip_port, params);
}
}
gateway->expires_str = switch_core_strdup(gateway->pool, expire_seconds);
@@ -2766,6 +2879,7 @@ switch_status_t reconfig_sofia(sofia_profile_t *profile)
/* you could change profile->foo here if it was a minor change like context or dialplan ... */
profile->acl_count = 0;
profile->nat_acl_count = 0;
profile->reg_acl_count = 0;
profile->proxy_acl_count = 0;
sofia_set_pflag(profile, PFLAG_STUN_ENABLED);
@@ -2861,6 +2975,18 @@ switch_status_t reconfig_sofia(sofia_profile_t *profile)
} else {
sofia_clear_pflag(profile, PFLAG_LOG_AUTH_FAIL);
}
} else if (!strcasecmp(var, "presence-proto-lookup")) {
if (switch_true(val)) {
sofia_set_pflag(profile, PFLAG_PRESENCE_MAP);
} else {
sofia_clear_pflag(profile, PFLAG_PRESENCE_MAP);
}
} else if (!strcasecmp(var, "profile-standby")) {
if (switch_true(val)) {
sofia_set_pflag(profile, PFLAG_STANDBY);
} else {
sofia_clear_pflag(profile, PFLAG_STANDBY);
}
} else if (!strcasecmp(var, "liberal-dtmf")) {
if (switch_true(val)) {
sofia_set_pflag(profile, PFLAG_LIBERAL_DTMF);
@@ -3079,6 +3205,8 @@ switch_status_t reconfig_sofia(sofia_profile_t *profile)
profile->user_agent_filter = switch_core_strdup(profile->pool, val);
} else if (!strcasecmp(var, "max-registrations-per-extension")) {
profile->max_registrations_perext = atoi(val);
} else if (!strcasecmp(var,"presence-privacy")) {
profile->presence_privacy = switch_core_strdup(profile->pool, val);
} else if (!strcasecmp(var, "rfc2833-pt")) {
profile->te = (switch_payload_t) atoi(val);
} else if (!strcasecmp(var, "cng-pt") && !(sofia_test_pflag(profile, PFLAG_SUPPRESS_CNG))) {
@@ -3292,6 +3420,12 @@ switch_status_t reconfig_sofia(sofia_profile_t *profile)
profile->timer_t4 = 4000;
}
nua_set_params(profile->nua, NTATAG_SIP_T4(profile->timer_t4), TAG_END());
} else if (!strcasecmp(var, "sip-options-respond-503-on-busy")) {
if (switch_true(val)) {
sofia_set_pflag(profile, PFLAG_OPTIONS_RESPOND_503_ON_BUSY);
} else {
sofia_clear_pflag(profile, PFLAG_OPTIONS_RESPOND_503_ON_BUSY);
}
}
}
}
@@ -3524,8 +3658,9 @@ 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_SQL_IN_TRANS);
sofia_set_pflag(profile, PFLAG_PRESENCE_ON_REGISTER);
profile->shutdown_type = "false";
profile->local_network = "localnet.auto";
sofia_set_flag(profile, TFLAG_ENABLE_SOA);
@@ -3576,6 +3711,18 @@ switch_status_t config_sofia(int reload, char *profile_name)
} else {
sofia_clear_pflag(profile, PFLAG_LOG_AUTH_FAIL);
}
} else if (!strcasecmp(var, "presence-proto-lookup")) {
if (switch_true(val)) {
sofia_set_pflag(profile, PFLAG_PRESENCE_MAP);
} else {
sofia_clear_pflag(profile, PFLAG_PRESENCE_MAP);
}
} else if (!strcasecmp(var, "profile-standby")) {
if (switch_true(val)) {
sofia_set_pflag(profile, PFLAG_STANDBY);
} else {
sofia_clear_pflag(profile, PFLAG_STANDBY);
}
} else if (!strcasecmp(var, "liberal-dtmf")) {
if (switch_true(val)) {
sofia_set_pflag(profile, PFLAG_LIBERAL_DTMF);
@@ -3632,7 +3779,7 @@ switch_status_t config_sofia(int reload, char *profile_name)
sofia_clear_pflag(profile, PFLAG_PRESENCE_PROBE_ON_REGISTER);
}
} else if (!strcasecmp(var, "send-presence-on-register")) {
if (switch_true(val)) {
if (switch_true(val) || !strcasecmp(val, "all")) {
sofia_set_pflag(profile, PFLAG_PRESENCE_ON_REGISTER);
} else if (!strcasecmp(val, "first-only")) {
sofia_clear_pflag(profile, PFLAG_PRESENCE_ON_REGISTER);
@@ -3968,6 +4115,10 @@ switch_status_t config_sofia(int reload, char *profile_name)
} else if (switch_true(val)) {
profile->pres_type = PRES_TYPE_FULL;
}
} else if (!strcasecmp(var, "presence-privacy")) {
if (switch_true(val)) {
sofia_set_pflag(profile, PFLAG_PRESENCE_PRIVACY);
}
} else if (!strcasecmp(var, "manage-shared-appearance")) {
if (switch_true(val)) {
sofia_set_pflag(profile, PFLAG_MANAGE_SHARED_APPEARANCE);
@@ -3975,8 +4126,9 @@ switch_status_t config_sofia(int reload, char *profile_name)
sofia_set_pflag(profile, PFLAG_MULTIREG);
} else if (!strcasecmp(val, "sylantro")) {
profile->sla_contact = switch_core_sprintf(profile->pool, "sla-agent");
sofia_set_pflag(profile, PFLAG_MANAGE_SHARED_APPEARANCE_SYLANTRO);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR,
"Sylantro support has been removed.\n"
"It was incomplete anyway, and we fully support the broadsoft SCA shared line spec.");
}
} else if (!strcasecmp(var, "disable-srv")) {
if (switch_true(val)) {
@@ -4125,6 +4277,10 @@ switch_status_t config_sofia(int reload, char *profile_name)
if (!switch_true(val)) {
sofia_set_pflag(profile, PFLAG_DISABLE_TIMER);
}
} else if (!strcasecmp(var, "enable-rfc-5626")) {
if (switch_true(val)) {
sofia_set_pflag(profile, PFLAG_ENABLE_RFC5626);
}
} else if (!strcasecmp(var, "minimum-session-expires")) {
profile->minimum_session_expires = atoi(val);
/* per RFC 4028: minimum_session_expires must be > 90 */
@@ -4288,6 +4444,12 @@ switch_status_t config_sofia(int reload, char *profile_name)
} else {
profile->timer_t4 = 4000;
}
} else if (!strcasecmp(var, "sip-options-respond-503-on-busy")) {
if (switch_true(val)) {
sofia_set_pflag(profile, PFLAG_OPTIONS_RESPOND_503_ON_BUSY);
} else {
sofia_clear_pflag(profile, PFLAG_OPTIONS_RESPOND_503_ON_BUSY);
}
} else if (!strcasecmp(var, "reuse-connections")) {
switch_bool_t value = switch_true(val);
if (!value) {
@@ -4510,6 +4672,14 @@ static void sofia_handle_sip_r_invite(switch_core_session_t *session, int status
switch_caller_profile_t *caller_profile = NULL;
int has_t38 = 0;
switch_channel_clear_flag(channel, CF_REQ_MEDIA);
if (status >= 900) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "%s status %d received.\n",
switch_channel_get_name(channel), status);
return;
}
sofia_glue_get_addr(de->data->e_msg, network_ip, sizeof(network_ip), &network_port);
switch_channel_set_variable_printf(channel, "sip_local_network_addr", "%s", profile->extsipip ? profile->extsipip : profile->sipip);
@@ -4523,8 +4693,6 @@ static void sofia_handle_sip_r_invite(switch_core_session_t *session, int status
caller_profile->network_addr = switch_core_strdup(caller_profile->pool, network_ip);
}
switch_channel_clear_flag(channel, CF_REQ_MEDIA);
tech_pvt->last_sdp_str = NULL;
if (!sofia_use_soa(tech_pvt) && sip->sip_payload && sip->sip_payload->pl_data) {
tech_pvt->last_sdp_str = switch_core_session_strdup(session, sip->sip_payload->pl_data);
@@ -4609,9 +4777,9 @@ static void sofia_handle_sip_r_invite(switch_core_session_t *session, int status
const char *vval;
if (status > 199) {
sofia_glue_set_extra_headers(channel, sip, SOFIA_SIP_RESPONSE_HEADER_PREFIX);
sofia_glue_set_extra_headers(session, sip, SOFIA_SIP_RESPONSE_HEADER_PREFIX);
} else {
sofia_glue_set_extra_headers(channel, sip, SOFIA_SIP_PROGRESS_HEADER_PREFIX);
sofia_glue_set_extra_headers(session, sip, SOFIA_SIP_PROGRESS_HEADER_PREFIX);
}
@@ -4814,10 +4982,15 @@ static void sofia_handle_sip_r_invite(switch_core_session_t *session, int status
}
if (sip->sip_payload && sip->sip_payload->pl_data && switch_stristr("m=image", sip->sip_payload->pl_data)) {
if (!switch_channel_test_flag(channel, CF_PROXY_MODE) &&
sip->sip_payload && sip->sip_payload->pl_data && switch_stristr("m=image", sip->sip_payload->pl_data)) {
has_t38 = 1;
}
if (switch_channel_test_flag(channel, CF_PROXY_MODE)) {
sofia_clear_flag(tech_pvt, TFLAG_T38_PASSTHRU);
}
if (switch_channel_test_flag(channel, CF_PROXY_MODE) ||
switch_channel_test_flag(channel, CF_PROXY_MEDIA) ||
(sofia_test_flag(tech_pvt, TFLAG_T38_PASSTHRU) && (has_t38 || status > 299))) {
@@ -4835,9 +5008,9 @@ static void sofia_handle_sip_r_invite(switch_core_session_t *session, int status
sip->sip_content_type && sip->sip_content_type->c_subtype && switch_stristr("sdp", sip->sip_content_type->c_subtype)) {
tech_pvt->remote_sdp_str = switch_core_session_strdup(tech_pvt->session, sip->sip_payload->pl_data);
r_sdp = tech_pvt->remote_sdp_str;
sofia_glue_tech_proxy_remote_addr(tech_pvt);
sofia_glue_tech_proxy_remote_addr(tech_pvt, NULL);
}
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Passing %d %s to other leg\n", status, phrase);
if (status > 299) {
@@ -4950,6 +5123,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) {
@@ -4962,12 +5137,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) {
@@ -4980,7 +5157,8 @@ static void sofia_handle_sip_r_invite(switch_core_session_t *session, int status
const char *presence_id = switch_channel_get_variable(channel, "presence_id");
char *full_contact = "";
char *p = NULL;
time_t now;
if (sip->sip_contact) {
full_contact = sip_header_as_string(nua_handle_home(tech_pvt->nh), (void *) sip->sip_contact);
}
@@ -4988,16 +5166,19 @@ static void sofia_handle_sip_r_invite(switch_core_session_t *session, int status
if (call_info && (p = strchr(call_info, ';'))) {
p++;
}
now = switch_epoch_time_now(NULL);
sql = switch_mprintf("insert into sip_dialogs "
"(call_id,uuid,sip_to_user,sip_to_host,sip_from_user,sip_from_host,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')",
"(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,rcd) "
"values('%q','%q','%q','%q','%q','%q','%q','%q','%q','%q','%q','%q','%q','%q','%q','%q','%q','%q','%q',%ld)",
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));
switch_str_nil(presence_id), switch_str_nil(presence_data), switch_str_nil(p), (long) now);
switch_assert(sql);
sofia_glue_actually_execute_sql(profile, sql, profile->ireg_mutex);
@@ -5080,6 +5261,83 @@ static void launch_media_on_hold(switch_core_session_t *session)
switch_thread_create(&thread, thd_attr, media_on_hold_thread_run, session, switch_core_session_get_pool(session));
}
static void mark_transfer_record(switch_core_session_t *session, const char *br_a, const char *br_b)
{
switch_core_session_t *br_b_session, *br_a_session;
switch_channel_t *channel;
const char *uvar1, *dvar1, *uvar2, *dvar2;
channel = switch_core_session_get_channel(session);
if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_INBOUND) {
uvar1 = "sip_from_user";
dvar1 = "sip_from_host";
} else {
uvar1 = "sip_to_user";
dvar1 = "sip_to_host";
}
if ((br_b_session = switch_core_session_locate(br_b)) ) {
switch_channel_t *br_b_channel = switch_core_session_get_channel(br_b_session);
switch_caller_profile_t *cp = switch_channel_get_caller_profile(br_b_channel);
if (switch_channel_direction(br_b_channel) == SWITCH_CALL_DIRECTION_INBOUND) {
uvar2 = "sip_from_user";
dvar2 = "sip_from_host";
} else {
uvar2 = "sip_to_user";
dvar2 = "sip_to_host";
}
cp->transfer_source = switch_core_sprintf(cp->pool,
"%ld:%s:att_xfer:%s@%s/%s@%s",
(long) switch_epoch_time_now(NULL),
cp->uuid_str,
switch_channel_get_variable(channel, uvar1),
switch_channel_get_variable(channel, dvar1),
switch_channel_get_variable(br_b_channel, uvar2),
switch_channel_get_variable(br_b_channel, dvar2));
switch_channel_add_variable_var_check(br_b_channel, SWITCH_TRANSFER_HISTORY_VARIABLE, cp->transfer_source, SWITCH_FALSE, SWITCH_STACK_PUSH);
switch_channel_set_variable(br_b_channel, SWITCH_TRANSFER_SOURCE_VARIABLE, cp->transfer_source);
switch_core_session_rwunlock(br_b_session);
}
if ((br_a_session = switch_core_session_locate(br_a)) ) {
switch_channel_t *br_a_channel = switch_core_session_get_channel(br_a_session);
switch_caller_profile_t *cp = switch_channel_get_caller_profile(br_a_channel);
if (switch_channel_direction(br_a_channel) == SWITCH_CALL_DIRECTION_INBOUND) {
uvar2 = "sip_from_user";
dvar2 = "sip_from_host";
} else {
uvar2 = "sip_to_user";
dvar2 = "sip_to_host";
}
cp->transfer_source = switch_core_sprintf(cp->pool,
"%ld:%s:att_xfer:%s@%s/%s@%s",
(long) switch_epoch_time_now(NULL),
cp->uuid_str,
switch_channel_get_variable(channel, uvar1),
switch_channel_get_variable(channel, dvar1),
switch_channel_get_variable(br_a_channel, uvar2),
switch_channel_get_variable(br_a_channel, dvar2));
switch_channel_add_variable_var_check(br_a_channel, SWITCH_TRANSFER_HISTORY_VARIABLE, cp->transfer_source, SWITCH_FALSE, SWITCH_STACK_PUSH);
switch_channel_set_variable(br_a_channel, SWITCH_TRANSFER_SOURCE_VARIABLE, cp->transfer_source);
switch_core_session_rwunlock(br_a_session);
}
}
static void sofia_handle_sip_i_state(switch_core_session_t *session, 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,
@@ -5212,6 +5470,19 @@ static void sofia_handle_sip_i_state(switch_core_session_t *session, int status,
status = 183;
}
if (channel && 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' and sip_to_tag = ''", 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);
}
if (channel && (status == 180 || status == 183) && switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) {
const char *val;
if ((val = switch_channel_get_variable(channel, "sip_auto_answer")) && switch_true(val)) {
@@ -5401,15 +5672,17 @@ static void sofia_handle_sip_i_state(switch_core_session_t *session, int status,
const char *br_b = switch_channel_get_variable(channel, SWITCH_SIGNAL_BOND_VARIABLE);
char *br_a = b_private->uuid;
if (br_b) {
switch_core_session_t *tmp;
if (switch_true(switch_channel_get_variable(channel, "recording_follow_transfer")) &&
switch_core_session_t *tmp;
if (switch_true(switch_channel_get_variable(channel, "recording_follow_transfer")) &&
(tmp = switch_core_session_locate(br_a))) {
switch_core_media_bug_transfer_recordings(session, tmp);
switch_core_session_rwunlock(tmp);
}
mark_transfer_record(session, br_a, br_b);
switch_ivr_uuid_bridge(br_a, br_b);
switch_channel_set_variable(channel, SWITCH_ENDPOINT_DISPOSITION_VARIABLE, "ATTENDED_TRANSFER");
sofia_clear_flag_locked(tech_pvt, TFLAG_SIP_HOLD);
@@ -5582,6 +5855,15 @@ static void sofia_handle_sip_i_state(switch_core_session_t *session, int status,
goto done;
}
if (switch_channel_test_flag(channel, CF_PROXY_MEDIA)) {
if (sofia_glue_tech_proxy_remote_addr(tech_pvt, r_sdp) == SWITCH_STATUS_SUCCESS) {
nua_respond(tech_pvt->nh, SIP_200_OK, TAG_END());
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Audio params changed, NOT proxying re-invite.\n");
switch_core_session_rwunlock(other_session);
goto done;
}
}
msg = switch_core_session_alloc(other_session, sizeof(*msg));
msg->message_id = SWITCH_MESSAGE_INDICATE_MEDIA_REDIRECT;
msg->from = __FILE__;
@@ -5902,12 +6184,11 @@ static void sofia_handle_sip_i_state(switch_core_session_t *session, int status,
switch_snprintf(st, sizeof(st), "%d", status);
switch_channel_set_variable(channel, "sip_term_status", st);
switch_snprintf(st, sizeof(st), "sip:%d", status);
switch_channel_set_variable_partner(channel, SWITCH_PROTO_SPECIFIC_HANGUP_CAUSE_VARIABLE, st);
switch_channel_set_variable(channel, SWITCH_PROTO_SPECIFIC_HANGUP_CAUSE_VARIABLE, st);
if (phrase) {
switch_channel_set_variable_partner(channel, "sip_hangup_phrase", phrase);
}
sofia_glue_set_extra_headers(channel, sip, SOFIA_SIP_BYE_HEADER_PREFIX);
sofia_glue_set_extra_headers(session, sip, SOFIA_SIP_BYE_HEADER_PREFIX);
}
switch_snprintf(st, sizeof(st), "%d", cause);
switch_channel_set_variable(channel, "sip_term_cause", st);
@@ -5973,12 +6254,13 @@ void *SWITCH_THREAD_FUNC nightmare_xfer_thread_run(switch_thread_t *thread, void
if ((status = switch_ivr_originate(NULL, &tsession, &cause, nhelper->exten_with_params, timeout, NULL, NULL, NULL,
switch_channel_get_caller_profile(channel_a), nhelper->vars, SOF_NONE, NULL)) == SWITCH_STATUS_SUCCESS) {
if (switch_channel_up(channel_a)) {
if (switch_true(switch_channel_get_variable(channel_a, "recording_follow_transfer"))) {
switch_core_media_bug_transfer_recordings(session, a_session);
}
tuuid_str = switch_core_session_get_uuid(tsession);
mark_transfer_record(session, nhelper->bridge_to_uuid, tuuid_str);
switch_ivr_uuid_bridge(nhelper->bridge_to_uuid, tuuid_str);
switch_channel_set_variable(channel_a, SWITCH_ENDPOINT_DISPOSITION_VARIABLE, "ATTENDED_TRANSFER");
sofia_set_flag_locked(tech_pvt, TFLAG_BYE);
@@ -6342,6 +6624,8 @@ void sofia_handle_sip_i_refer(nua_t *nua, sofia_profile_t *profile, nua_handle_t
switch_core_session_rwunlock(tmp);
}
mark_transfer_record(session, br_b, br_a);
switch_ivr_uuid_bridge(br_b, br_a);
switch_channel_set_variable(channel_b, SWITCH_ENDPOINT_DISPOSITION_VARIABLE, "ATTENDED_TRANSFER");
@@ -6739,9 +7023,44 @@ void sofia_handle_sip_i_info(nua_t *nua, sofia_profile_t *profile, nua_handle_t
if (session) {
/* Get the channel */
switch_channel_t *channel = switch_core_session_get_channel(session);
const char *vval;
/* Barf if we didn't get our private */
assert(switch_core_session_get_private(session));
sofia_glue_set_extra_headers(session, sip, SOFIA_SIP_INFO_HEADER_PREFIX);
if (sip && sip->sip_content_type && sip->sip_content_type->c_type && !strcasecmp(sip->sip_content_type->c_type, "freeswitch/data")) {
char *data = NULL;
if (sip->sip_payload && sip->sip_payload->pl_data) {
data = sip->sip_payload->pl_data;
}
if ((vval = switch_channel_get_variable(channel, "sip_copy_custom_headers")) && switch_true(vval)) {
switch_core_session_t *nsession = NULL;
switch_core_session_get_partner(session, &nsession);
if (nsession) {
switch_core_session_message_t *msg;
switch_ivr_transfer_variable(session, nsession, SOFIA_SIP_INFO_HEADER_PREFIX_T);
msg = switch_core_session_alloc(nsession, sizeof(*msg));
MESSAGE_STAMP_FFL(msg);
msg->message_id = SWITCH_MESSAGE_INDICATE_INFO;
msg->string_array_arg[2] = switch_core_session_strdup(nsession, data);
msg->from = __FILE__;
switch_core_session_queue_message(nsession, msg);
switch_core_session_rwunlock(nsession);
}
}
}
if (sip && sip->sip_content_type && sip->sip_content_type->c_subtype && sip->sip_content_type->c_type &&
!strncasecmp(sip->sip_content_type->c_type, "message", 7) &&
@@ -7229,7 +7548,7 @@ void sofia_handle_sip_i_invite(nua_t *nua, sofia_profile_t *profile, nua_handle_
transport = sofia_glue_url2transport(sip->sip_contact->m_url);
tech_pvt->record_route =
tech_pvt->record_route=
switch_core_session_sprintf(session,
"sip:%s@%s%s%s:%d;transport=%s",
sip->sip_contact->m_url->url_user,
@@ -7276,16 +7595,12 @@ void sofia_handle_sip_i_invite(nua_t *nua, sofia_profile_t *profile, nua_handle_
}
if (sip->sip_from && sip->sip_from->a_url) {
char *tmp;
from_user = sip->sip_from->a_url->url_user;
from_host = sip->sip_from->a_url->url_host;
channel_name = url_set_chanvars(session, sip->sip_from->a_url, sip_from);
if (sip->sip_from->a_url->url_params && (tmp = sofia_glue_find_parameter(sip->sip_from->a_url->url_params, "isup-oli="))) {
aniii = switch_core_session_strdup(session, tmp + 9);
if ((tmp = strchr(aniii, ';'))) {
tmp = '\0';
}
if (sip->sip_from->a_url->url_params) {
aniii = switch_find_parameter(sip->sip_from->a_url->url_params, "isup-oli", switch_core_session_get_pool(session));
}
if (!zstr(from_user)) {
@@ -7627,7 +7942,7 @@ void sofia_handle_sip_i_invite(nua_t *nua, sofia_profile_t *profile, nua_handle_
if (sip->sip_request->rq_url->url_params) {
gw_param_name = sofia_glue_find_parameter_value(session, sip->sip_request->rq_url->url_params, "gw=");
gw_param_name = switch_find_parameter(sip->sip_request->rq_url->url_params, "gw", switch_core_session_get_pool(session));
}
if (strstr(destination_number, "gw+")) {
@@ -7971,6 +8286,8 @@ void sofia_handle_sip_i_invite(nua_t *nua, sofia_profile_t *profile, nua_handle_
const char *dialog_from_user = "", *dialog_from_host = "", *to_user = "", *to_host = "", *contact_user = "", *contact_host = "";
const char *user_agent = "", *call_id = "";
url_t *from = NULL, *to = NULL, *contact = NULL;
const char *to_tag = "";
const char *from_tag = "";
char *sql = NULL;
if (sip->sip_to) {
@@ -7994,11 +8311,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) {
@@ -8011,7 +8330,7 @@ void sofia_handle_sip_i_invite(nua_t *nua, sofia_profile_t *profile, nua_handle_
const char *presence_id = switch_channel_get_variable(channel, "presence_id");
char *full_contact = "";
char *p = NULL;
time_t now;
if (sip->sip_contact) {
full_contact = sip_header_as_string(nua_handle_home(tech_pvt->nh), (void *) sip->sip_contact);
@@ -8025,17 +8344,18 @@ void sofia_handle_sip_i_invite(nua_t *nua, sofia_profile_t *profile, nua_handle_
}
}
now = switch_epoch_time_now(NULL);
sql = switch_mprintf("insert into sip_dialogs "
"(call_id,uuid,sip_to_user,sip_to_host,sip_from_user,sip_from_host,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')",
"(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,rcd) "
"values('%q','%q','%q','%q','%q','%q','%q','%q','%q','%q','%q','%q','%q','%q','%q','%q','%q','%q','%q',%ld)",
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));
switch_str_nil(presence_id), switch_str_nil(presence_data), switch_str_nil(p), now);
switch_assert(sql);
@@ -8088,7 +8408,16 @@ void sofia_handle_sip_i_options(int status,
sofia_dispatch_event_t *de,
tagi_t tags[])
{
nua_respond(nh, SIP_200_OK, NUTAG_WITH_THIS_MSG(de->data->e_msg), TAG_END());
uint32_t sess_count = switch_core_session_count();
uint32_t sess_max = switch_core_session_limit(0);
if (sofia_test_pflag(profile, PFLAG_OPTIONS_RESPOND_503_ON_BUSY) &&
(sess_count >= sess_max || !sofia_test_pflag(profile, PFLAG_RUNNING) || !switch_core_ready_inbound())) {
nua_respond(nh, 503, "Maximum Calls In Progress", NUTAG_WITH_THIS_MSG(de->data->e_msg), SIPTAG_RETRY_AFTER_STR("300"), TAG_END());
} else {
nua_respond(nh, SIP_200_OK, NUTAG_WITH_THIS_MSG(de->data->e_msg), TAG_END());
}
}
void sofia_info_send_sipfrag(switch_core_session_t *aleg, switch_core_session_t *bleg)
@@ -8119,6 +8448,7 @@ void sofia_info_send_sipfrag(switch_core_session_t *aleg, switch_core_session_t
if (zstr(acp->caller_id_name)) {
snprintf(message, sizeof(message), "P-Asserted-Identity: \"%s\" <%s>", acp->caller_id_number, acp->caller_id_number);
} else {
check_decode(acp->caller_id_name, aleg);
snprintf(message, sizeof(message), "P-Asserted-Identity: \"%s\" <%s>", acp->caller_id_name, acp->caller_id_number);
}
+199 -52
View File
@@ -1374,7 +1374,7 @@ char *sofia_overcome_sip_uri_weakness(switch_core_session_t *session, const char
}
#define RA_PTR_LEN 512
switch_status_t sofia_glue_tech_proxy_remote_addr(private_object_t *tech_pvt)
switch_status_t sofia_glue_tech_proxy_remote_addr(private_object_t *tech_pvt, const char *sdp_str)
{
const char *err;
char rip[RA_PTR_LEN] = "";
@@ -1383,29 +1383,34 @@ switch_status_t sofia_glue_tech_proxy_remote_addr(private_object_t *tech_pvt)
char *p, *ip_ptr = NULL, *port_ptr = NULL, *vid_port_ptr = NULL, *pe;
int x;
const char *val;
if (zstr(tech_pvt->remote_sdp_str)) {
return SWITCH_STATUS_FALSE;
switch_status_t status = SWITCH_STATUS_FALSE;
if (zstr(sdp_str)) {
sdp_str = tech_pvt->remote_sdp_str;
}
if ((p = (char *) switch_stristr("c=IN IP4 ", tech_pvt->remote_sdp_str)) || (p = (char *) switch_stristr("c=IN IP6 ", tech_pvt->remote_sdp_str))) {
if (zstr(sdp_str)) {
goto end;
}
if ((p = (char *) switch_stristr("c=IN IP4 ", sdp_str)) || (p = (char *) switch_stristr("c=IN IP6 ", sdp_str))) {
ip_ptr = p + 9;
}
if ((p = (char *) switch_stristr("m=audio ", tech_pvt->remote_sdp_str))) {
if ((p = (char *) switch_stristr("m=audio ", sdp_str))) {
port_ptr = p + 8;
}
if ((p = (char *) switch_stristr("m=image ", tech_pvt->remote_sdp_str))) {
if ((p = (char *) switch_stristr("m=image ", sdp_str))) {
port_ptr = p + 8;
}
if ((p = (char *) switch_stristr("m=video ", tech_pvt->remote_sdp_str))) {
if ((p = (char *) switch_stristr("m=video ", sdp_str))) {
vid_port_ptr = p + 8;
}
if (!(ip_ptr && port_ptr)) {
return SWITCH_STATUS_FALSE;
goto end;
}
p = ip_ptr;
@@ -1415,7 +1420,7 @@ switch_status_t sofia_glue_tech_proxy_remote_addr(private_object_t *tech_pvt)
rip[x++] = *p;
p++;
if (p >= pe) {
return SWITCH_STATUS_FALSE;
goto end;
}
}
@@ -1425,7 +1430,7 @@ switch_status_t sofia_glue_tech_proxy_remote_addr(private_object_t *tech_pvt)
rp[x++] = *p;
p++;
if (p >= pe) {
return SWITCH_STATUS_FALSE;
goto end;
}
}
@@ -1435,13 +1440,13 @@ switch_status_t sofia_glue_tech_proxy_remote_addr(private_object_t *tech_pvt)
rvp[x++] = *p;
p++;
if (p >= pe) {
return SWITCH_STATUS_FALSE;
goto end;
}
}
if (!(*rip && *rp)) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_ERROR, "invalid SDP\n");
return SWITCH_STATUS_FALSE;
goto end;
}
tech_pvt->remote_sdp_audio_ip = switch_core_session_strdup(tech_pvt->session, rip);
@@ -1496,7 +1501,7 @@ switch_status_t sofia_glue_tech_proxy_remote_addr(private_object_t *tech_pvt)
if (remote_host && remote_port && !strcmp(remote_host, tech_pvt->remote_sdp_audio_ip) && remote_port == tech_pvt->remote_sdp_audio_port) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG, "Remote address:port [%s:%d] has not changed.\n",
tech_pvt->remote_sdp_audio_ip, tech_pvt->remote_sdp_audio_port);
return SWITCH_STATUS_SUCCESS;
switch_goto_status(SWITCH_STATUS_BREAK, end);
}
if ((rport = switch_channel_get_variable(tech_pvt->channel, "sip_remote_audio_rtcp_port"))) {
@@ -1507,6 +1512,7 @@ switch_status_t sofia_glue_tech_proxy_remote_addr(private_object_t *tech_pvt)
if (switch_rtp_set_remote_address(tech_pvt->rtp_session, tech_pvt->remote_sdp_audio_ip,
tech_pvt->remote_sdp_audio_port, remote_rtcp_port, SWITCH_TRUE, &err) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_ERROR, "AUDIO RTP REPORTS ERROR: [%s]\n", err);
status = SWITCH_STATUS_GENERR;
} else {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG, "AUDIO RTP CHANGING DEST TO: [%s:%d]\n",
tech_pvt->remote_sdp_audio_ip, tech_pvt->remote_sdp_audio_port);
@@ -1518,10 +1524,13 @@ switch_status_t sofia_glue_tech_proxy_remote_addr(private_object_t *tech_pvt)
if (sofia_test_pflag(tech_pvt->profile, PFLAG_AUTOFIX_TIMING)) {
tech_pvt->check_frames = 0;
}
status = SWITCH_STATUS_SUCCESS;
}
}
return SWITCH_STATUS_SUCCESS;
end:
return status;
}
@@ -1899,11 +1908,14 @@ char *sofia_glue_get_extra_headers(switch_channel_t *channel, const char *prefix
return extra_headers;
}
void sofia_glue_set_extra_headers(switch_channel_t *channel, sip_t const *sip, const char *prefix)
void sofia_glue_set_extra_headers(switch_core_session_t *session, sip_t const *sip, const char *prefix)
{
sip_unknown_t *un;
char name[512] = "";
switch_channel_t *channel = switch_core_session_get_channel(session);
char *pstr;
if (!sip || !channel) {
return;
}
@@ -1916,6 +1928,13 @@ void sofia_glue_set_extra_headers(switch_channel_t *channel, sip_t const *sip, c
}
}
}
pstr = switch_core_session_sprintf(session, "execute_on_%sprefix", prefix);
switch_channel_execute_on(channel, pstr);
switch_channel_api_on(channel, pstr);
switch_channel_execute_on(channel, "execute_on_sip_extra_headers");
switch_channel_api_on(channel, "api_on_sip_extra_headers");
}
@@ -1941,7 +1960,7 @@ switch_status_t sofia_glue_do_invite(switch_core_session_t *session)
sofia_destination_t *dst = NULL;
sofia_cid_type_t cid_type = tech_pvt->profile->cid_type;
sip_cseq_t *cseq = NULL;
const char *invite_full_via = switch_channel_get_variable(tech_pvt->channel, "sip_invite_full_via");
const char *invite_record_route = switch_channel_get_variable(tech_pvt->channel, "sip_invite_record_route");
const char *invite_route_uri = switch_channel_get_variable(tech_pvt->channel, "sip_invite_route_uri");
const char *invite_full_from = switch_channel_get_variable(tech_pvt->channel, "sip_invite_full_from");
const char *invite_full_to = switch_channel_get_variable(tech_pvt->channel, "sip_invite_full_to");
@@ -1950,6 +1969,23 @@ switch_status_t sofia_glue_do_invite(switch_core_session_t *session)
const char *force_full_from = switch_channel_get_variable(tech_pvt->channel, "sip_force_full_from");
const char *force_full_to = switch_channel_get_variable(tech_pvt->channel, "sip_force_full_to");
char *mp = NULL, *mp_type = NULL;
char *record_route = NULL;
const char *recover_via = NULL;
if (sofia_test_flag(tech_pvt, TFLAG_RECOVERING)) {
const char *recover_contact = switch_channel_get_variable(tech_pvt->channel, "sip_recover_contact");
recover_via = switch_channel_get_variable(tech_pvt->channel, "sip_recover_via");
if (!zstr(invite_record_route)) {
record_route = switch_core_session_sprintf(session, "Record-Route: %s", invite_record_route);
}
if (recover_contact) {
char *tmp = switch_core_session_strdup(session, recover_contact);
tech_pvt->redirected = sofia_glue_get_url_from_contact(tmp, 0);
}
}
rep = switch_channel_get_variable(channel, SOFIA_REPLACES_HEADER);
@@ -1959,6 +1995,12 @@ switch_status_t sofia_glue_do_invite(switch_core_session_t *session)
caller_profile = switch_channel_get_caller_profile(channel);
if (!caller_profile) {
switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
return SWITCH_STATUS_FALSE;
}
cid_name = caller_profile->caller_id_name;
cid_num = caller_profile->caller_id_number;
sofia_glue_tech_prepare_codecs(tech_pvt);
@@ -2051,7 +2093,7 @@ switch_status_t sofia_glue_do_invite(switch_core_session_t *session)
if (!zstr(tech_pvt->gateway_from_str)) {
rpid_domain = switch_core_session_strdup(session, tech_pvt->gateway_from_str);
} else if (!zstr(tech_pvt->from_str)) {
rpid_domain = switch_core_session_strdup(session, tech_pvt->from_str);
rpid_domain = switch_core_session_strdup(session, use_from_str);
}
sofia_glue_get_url_from_contact(rpid_domain, 0);
@@ -2214,10 +2256,14 @@ switch_status_t sofia_glue_do_invite(switch_core_session_t *session)
}
switch_channel_set_variable(channel, "sip_req_uri", s);
}
switch_channel_set_variable(channel, "sip_to_host", sofia_glue_get_host(to_str, switch_core_session_get_pool(session)));
switch_channel_set_variable(channel, "sip_from_host", sofia_glue_get_host(from_str, switch_core_session_get_pool(session)));
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)),
TAG_IF(!zstr(record_route), SIPTAG_HEADER_STR(record_route)),
SIPTAG_TO_STR(to_str), SIPTAG_FROM_STR(from_str), SIPTAG_CONTACT_STR(invite_contact), TAG_END()))) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_CRIT,
@@ -2376,7 +2422,7 @@ switch_status_t sofia_glue_do_invite(switch_core_session_t *session)
if (switch_channel_test_flag(channel, CF_PROXY_MEDIA)) {
if (switch_rtp_ready(tech_pvt->rtp_session)) {
sofia_glue_tech_proxy_remote_addr(tech_pvt);
sofia_glue_tech_proxy_remote_addr(tech_pvt, NULL);
}
sofia_glue_tech_patch_sdp(tech_pvt);
}
@@ -2441,7 +2487,7 @@ switch_status_t sofia_glue_do_invite(switch_core_session_t *session)
TAG_IF(invite_full_to, SIPTAG_TO_STR(invite_full_to)),
TAG_IF(tech_pvt->redirected, NUTAG_URL(tech_pvt->redirected)),
TAG_IF(!zstr(tech_pvt->user_via), SIPTAG_VIA_STR(tech_pvt->user_via)),
TAG_IF(!zstr(invite_full_via), SIPTAG_VIA_STR(invite_full_via)),
TAG_IF(!zstr(recover_via), SIPTAG_VIA_STR(recover_via)),
TAG_IF(!zstr(tech_pvt->rpid), SIPTAG_REMOTE_PARTY_ID_STR(tech_pvt->rpid)),
TAG_IF(!zstr(tech_pvt->preferred_id), SIPTAG_P_PREFERRED_IDENTITY_STR(tech_pvt->preferred_id)),
TAG_IF(!zstr(tech_pvt->asserted_id), SIPTAG_P_ASSERTED_IDENTITY_STR(tech_pvt->asserted_id)),
@@ -2475,7 +2521,7 @@ switch_status_t sofia_glue_do_invite(switch_core_session_t *session)
TAG_IF(invite_full_to, SIPTAG_TO_STR(invite_full_to)),
TAG_IF(tech_pvt->redirected, NUTAG_URL(tech_pvt->redirected)),
TAG_IF(!zstr(tech_pvt->user_via), SIPTAG_VIA_STR(tech_pvt->user_via)),
TAG_IF(!zstr(invite_full_via), SIPTAG_VIA_STR(invite_full_via)),
TAG_IF(!zstr(recover_via), SIPTAG_VIA_STR(recover_via)),
TAG_IF(!zstr(tech_pvt->rpid), SIPTAG_REMOTE_PARTY_ID_STR(tech_pvt->rpid)),
TAG_IF(!zstr(tech_pvt->preferred_id), SIPTAG_P_PREFERRED_IDENTITY_STR(tech_pvt->preferred_id)),
TAG_IF(!zstr(tech_pvt->asserted_id), SIPTAG_P_ASSERTED_IDENTITY_STR(tech_pvt->asserted_id)),
@@ -3144,9 +3190,7 @@ switch_status_t sofia_glue_activate_rtp(private_object_t *tech_pvt, switch_rtp_f
}
if (switch_channel_test_flag(tech_pvt->channel, CF_PROXY_MEDIA)) {
if ((status = sofia_glue_tech_proxy_remote_addr(tech_pvt)) != SWITCH_STATUS_SUCCESS) {
goto end;
}
sofia_glue_tech_proxy_remote_addr(tech_pvt, NULL);
if (!sofia_test_pflag(tech_pvt->profile, PFLAG_DISABLE_RTP_AUTOADJ) &&
!((val = switch_channel_get_variable(tech_pvt->channel, "disable_rtp_auto_adjust")) && switch_true(val))) {
@@ -3247,7 +3291,7 @@ switch_status_t sofia_glue_activate_rtp(private_object_t *tech_pvt, switch_rtp_f
switch_rtp_intentional_bugs(tech_pvt->rtp_session, tech_pvt->rtp_bugs | tech_pvt->profile->manual_rtp_bugs);
if ((vad_in && inb) || (vad_out && !inb)) {
switch_rtp_enable_vad(tech_pvt->rtp_session, tech_pvt->session, &tech_pvt->read_codec, SWITCH_VAD_FLAG_TALKING);
switch_rtp_enable_vad(tech_pvt->rtp_session, tech_pvt->session, &tech_pvt->read_codec, SWITCH_VAD_FLAG_TALKING | SWITCH_VAD_FLAG_EVENTS_TALK | SWITCH_VAD_FLAG_EVENTS_NOTALK);
sofia_set_flag(tech_pvt, TFLAG_VAD);
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG, "AUDIO RTP Engage VAD for %s ( %s %s )\n",
switch_channel_get_name(switch_core_session_get_channel(tech_pvt->session)), vad_in ? "in" : "", vad_out ? "out" : "");
@@ -3318,6 +3362,9 @@ switch_status_t sofia_glue_activate_rtp(private_object_t *tech_pvt, switch_rtp_f
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session),
SWITCH_LOG_DEBUG, "Setting Jitterbuffer to %dms (%d frames)\n", jb_msec, qlen);
switch_channel_set_flag(tech_pvt->channel, CF_JITTERBUFFER);
if (!switch_false(switch_channel_get_variable(tech_pvt->channel, "sip_jitter_buffer_plc"))) {
switch_channel_set_flag(tech_pvt->channel, CF_JITTERBUFFER_PLC);
}
} else {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session),
SWITCH_LOG_WARNING, "Error Setting Jitterbuffer to %dms (%d frames)\n", jb_msec, qlen);
@@ -3464,9 +3511,7 @@ switch_status_t sofia_glue_activate_rtp(private_object_t *tech_pvt, switch_rtp_f
}
if (switch_channel_test_flag(tech_pvt->channel, CF_PROXY_MEDIA)) {
if ((status = sofia_glue_tech_proxy_remote_addr(tech_pvt)) != SWITCH_STATUS_SUCCESS) {
goto end;
}
sofia_glue_tech_proxy_remote_addr(tech_pvt, NULL);
if (!sofia_test_pflag(tech_pvt->profile, PFLAG_DISABLE_RTP_AUTOADJ) &&
!((val = switch_channel_get_variable(tech_pvt->channel, "disable_rtp_auto_adjust")) && switch_true(val))) {
@@ -4423,26 +4468,33 @@ uint8_t sofia_glue_negotiate_sdp(switch_core_session_t *session, const char *r_s
int pass = sofia_test_pflag(tech_pvt->profile, PFLAG_T38_PASSTHRU);
if (var) {
pass = switch_true(var);
if (!(pass = switch_true(var))) {
if (!strcasecmp(var, "once")) {
pass = 2;
}
}
}
/* can't remember if this is necessary but its causing a bug so i'll leave this comment here to remind me
if (sofia_test_flag(tech_pvt, TFLAG_T38_PASSTHRU)) {
pass = 0;
}
*/
if (switch_channel_test_flag(tech_pvt->channel, CF_PROXY_MODE) ||
switch_channel_test_flag(tech_pvt->channel, CF_PROXY_MEDIA) || !switch_rtp_ready(tech_pvt->rtp_session)) {
if ((pass == 2 && sofia_test_flag(tech_pvt, TFLAG_T38_PASSTHRU)) ||
!sofia_test_flag(tech_pvt, TFLAG_REINVITE) ||
switch_channel_test_flag(tech_pvt->channel, CF_PROXY_MODE) ||
switch_channel_test_flag(tech_pvt->channel, CF_PROXY_MEDIA) ||
!switch_rtp_ready(tech_pvt->rtp_session)) {
pass = 0;
}
if (pass && switch_core_session_get_partner(session, &other_session) == SWITCH_STATUS_SUCCESS) {
private_object_t *other_tech_pvt = switch_core_session_get_private(other_session);
switch_channel_t *other_channel = switch_core_session_get_channel(other_session);
switch_core_session_message_t *msg;
char *remote_host = switch_rtp_get_remote_host(tech_pvt->rtp_session);
switch_port_t remote_port = switch_rtp_get_remote_port(tech_pvt->rtp_session);
char tmp[32] = "";
if (switch_true(switch_channel_get_variable(tech_pvt->channel, "t38_broken_boolean")) &&
switch_true(switch_channel_get_variable(tech_pvt->channel, "t38_pass_broken_boolean"))) {
switch_channel_set_variable(other_channel, "t38_broken_boolean", "true");
}
tech_pvt->remote_sdp_audio_ip = switch_core_session_strdup(tech_pvt->session, t38_options->remote_ip);
tech_pvt->remote_sdp_audio_port = t38_options->remote_port;
@@ -4469,7 +4521,7 @@ uint8_t sofia_glue_negotiate_sdp(switch_core_session_t *session, const char *r_s
}
sofia_glue_copy_t38_options(t38_options, other_session);
@@ -5260,6 +5312,30 @@ void sofia_glue_global_siptrace(switch_bool_t on)
}
void sofia_glue_global_standby(switch_bool_t on)
{
switch_hash_index_t *hi;
const void *var;
void *val;
sofia_profile_t *pptr;
switch_mutex_lock(mod_sofia_globals.hash_mutex);
if (mod_sofia_globals.profile_hash) {
for (hi = switch_hash_first(NULL, mod_sofia_globals.profile_hash); hi; hi = switch_hash_next(hi)) {
switch_hash_this(hi, &var, NULL, &val);
if ((pptr = (sofia_profile_t *) val)) {
if (on) {
sofia_set_pflag_locked(pptr, PFLAG_STANDBY);
} else {
sofia_clear_pflag_locked(pptr, PFLAG_STANDBY);
}
}
}
}
switch_mutex_unlock(mod_sofia_globals.hash_mutex);
}
void sofia_glue_global_capture(switch_bool_t on)
{
switch_hash_index_t *hi;
@@ -5355,6 +5431,7 @@ static int recover_callback(void *pArg, int argc, char **argv, char **columnName
switch_channel_t *channel;
private_object_t *tech_pvt = NULL;
const char *tmp;
const char *rr;
xml = switch_xml_parse_str_dynamic(argv[3], SWITCH_TRUE);
@@ -5362,7 +5439,7 @@ static int recover_callback(void *pArg, int argc, char **argv, char **columnName
return 0;
if (!(session = switch_core_session_request_xml(sofia_endpoint_interface, NULL, xml))) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "skipping non-bridged entry\n");
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Invalid cdr data, call not recovered\n");
return 0;
}
@@ -5395,20 +5472,22 @@ static int recover_callback(void *pArg, int argc, char **argv, char **columnName
}
}
rr = switch_channel_get_variable(channel, "sip_invite_record_route");
if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) {
tech_pvt->dest = switch_core_session_sprintf(session, "sip:%s", switch_channel_get_variable(channel, "sip_req_uri"));
switch_channel_set_variable(channel, "sip_invite_full_via", switch_channel_get_variable(channel, "sip_full_via"));
switch_channel_set_variable(channel, "sip_handle_full_from", switch_channel_get_variable(channel, "sip_full_from"));
switch_channel_set_variable(channel, "sip_handle_full_to", switch_channel_get_variable(channel, "sip_full_to"));
} else {
tech_pvt->redirected = switch_core_session_sprintf(session, "sip:%s", switch_channel_get_variable(channel, "sip_contact_uri"));
switch_channel_set_variable_printf(channel, "sip_invite_route_uri", "<sip:%s@%s:%s;lr>",
switch_channel_get_variable(channel, "sip_from_user"),
switch_channel_get_variable(channel, "sip_network_ip"), switch_channel_get_variable(channel, "sip_network_port")
);
if (zstr(rr)) {
switch_channel_set_variable_printf(channel, "sip_invite_route_uri", "<sip:%s@%s:%s;lr>",
switch_channel_get_variable(channel, "sip_from_user"),
switch_channel_get_variable(channel, "sip_network_ip"), switch_channel_get_variable(channel, "sip_network_port")
);
}
tech_pvt->dest = switch_core_session_sprintf(session, "sip:%s", switch_channel_get_variable(channel, "sip_from_uri"));
@@ -5421,6 +5500,10 @@ static int recover_callback(void *pArg, int argc, char **argv, char **columnName
}
}
if (rr) {
switch_channel_set_variable(channel, "sip_invite_route_uri", rr);
}
tech_pvt->dest_to = tech_pvt->dest;
sofia_glue_attach_private(session, h->profile, tech_pvt, NULL);
@@ -5615,6 +5698,8 @@ int sofia_glue_recover(switch_bool_t flush)
h.profile = profile;
h.total = 0;
sofia_clear_pflag_locked(profile, PFLAG_STANDBY);
if (flush) {
sql = switch_mprintf("delete from sip_recovery where profile_name='%q'", profile->name);
sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE);
@@ -5818,7 +5903,10 @@ int sofia_glue_init_sql(sofia_profile_t *profile)
" call_info_state VARCHAR(255),\n"
" expires INTEGER default 0,\n"
" status VARCHAR(255),\n"
" rpid VARCHAR(255)\n"
" rpid VARCHAR(255),\n"
" sip_to_tag VARCHAR(255),\n"
" sip_from_tag VARCHAR(255),\n"
" rcd INTEGER not null default 0\n"
");\n";
char sub_sql[] =
@@ -5841,7 +5929,9 @@ int sofia_glue_init_sql(sofia_profile_t *profile)
" hostname VARCHAR(255),\n"
" network_port VARCHAR(6),\n"
" network_ip VARCHAR(255),\n"
" version INTEGER DEFAULT 0 NOT NULL\n"
" version INTEGER DEFAULT 0 NOT NULL,\n"
" orig_proto VARCHAR(255),\n"
" full_to VARCHAR(255)\n"
");\n";
char auth_sql[] =
@@ -5881,6 +5971,8 @@ int sofia_glue_init_sql(sofia_profile_t *profile)
"create index sr_call_id on sip_registrations (call_id)",
"create index sr_sip_user on sip_registrations (sip_user)",
"create index sr_sip_host on sip_registrations (sip_host)",
"create index sr_mwi_user on sip_registrations (mwi_user)",
"create index sr_mwi_host on sip_registrations (mwi_host)",
"create index sr_profile_name on sip_registrations (profile_name)",
"create index sr_presence_hosts on sip_registrations (presence_hosts)",
"create index sr_contact on sip_registrations (contact)",
@@ -5903,15 +5995,37 @@ int sofia_glue_init_sql(sofia_profile_t *profile)
"create index ss_proto on sip_subscriptions (proto)",
"create index ss_sub_to_user on sip_subscriptions (sub_to_user)",
"create index ss_sub_to_host on sip_subscriptions (sub_to_host)",
"create index ss_expires on sip_subscriptions (expires)",
"create index ss_orig_proto on sip_subscriptions (orig_proto)",
"create index ss_network_port on sip_subscriptions (network_port)",
"create index ss_profile_name on sip_subscriptions (profile_name)",
"create index ss_version on sip_subscriptions (version)",
"create index ss_full_from on sip_subscriptions (full_from)",
"create index ss_contact on sip_subscriptions (contact)",
"create index sd_uuid on sip_dialogs (uuid)",
"create index sd_hostname on sip_dialogs (hostname)",
"create index sd_presence_data on sip_dialogs (presence_data)",
"create index sd_call_info on sip_dialogs (call_info)",
"create index sd_call_info_state on sip_dialogs (call_info_state)",
"create index sd_expires on sip_dialogs (expires)",
"create index sd_rcd on sip_dialogs (rcd)",
"create index sd_sip_to_tag on sip_dialogs (sip_to_tag)",
"create index sd_sip_from_user on sip_dialogs (sip_from_user)",
"create index sd_sip_from_host on sip_dialogs (sip_from_host)",
"create index sd_sip_to_host on sip_dialogs (sip_to_host)",
"create index sd_presence_id on sip_dialogs (presence_id)",
"create index sd_call_id on sip_dialogs (call_id)",
"create index sd_sip_from_tag on sip_dialogs (sip_from_tag)",
"create index sp_hostname on sip_presence (hostname)",
"create index sp_open_closed on sip_presence (open_closed)",
"create index sp_sip_user on sip_presence (sip_user)",
"create index sp_sip_host on sip_presence (sip_host)",
"create index sp_profile_name on sip_presence (profile_name)",
"create index sp_expires on sip_presence (expires)",
"create index sa_nonce on sip_authentication (nonce)",
"create index sa_hostname on sip_authentication (hostname)",
"create index sa_expires on sip_authentication (expires)",
"create index sa_last_nc on sip_authentication (last_nc)",
"create index ssa_hostname on sip_shared_appearance_subscriptions (hostname)",
"create index ssa_network_ip on sip_shared_appearance_subscriptions (network_ip)",
"create index ssa_subscriber on sip_shared_appearance_subscriptions (subscriber)",
@@ -5960,13 +6074,13 @@ int sofia_glue_init_sql(sofia_profile_t *profile)
free(test_sql);
test_sql = switch_mprintf("delete from sip_subscriptions where hostname='%q' and version < 0 and network_ip like '%%' and network_port like '%%'",
mod_sofia_globals.hostname);
test_sql = switch_mprintf("delete from sip_subscriptions where hostname='%q' and full_to='XXX'", mod_sofia_globals.hostname);
switch_cache_db_test_reactive(dbh, test_sql, "DROP TABLE sip_subscriptions", sub_sql);
free(test_sql);
test_sql = switch_mprintf("delete from sip_dialogs where hostname='%q' and expires <> -9999 or rpid=''", mod_sofia_globals.hostname);
test_sql = switch_mprintf("delete from sip_dialogs where hostname='%q' and (expires <> -9999 or rpid='' or sip_from_tag='' or rcd > 0)",
mod_sofia_globals.hostname);
switch_cache_db_test_reactive(dbh, test_sql, "DROP TABLE sip_dialogs", dialog_sql);
@@ -6577,6 +6691,14 @@ void sofia_glue_parse_rtp_bugs(switch_rtp_bug_flag_t *flag_pole, const char *str
if (switch_stristr("~ACCEPT_ANY_PACKETS", str)) {
*flag_pole &= ~RTP_BUG_ACCEPT_ANY_PACKETS;
}
if (switch_stristr("GEN_ONE_GEN_ALL", str)) {
*flag_pole |= RTP_BUG_GEN_ONE_GEN_ALL;
}
if (switch_stristr("~GEN_ONE_GEN_ALL", str)) {
*flag_pole &= ~RTP_BUG_GEN_ONE_GEN_ALL;
}
}
char *sofia_glue_gen_contact_str(sofia_profile_t *profile, sip_t const *sip, sofia_dispatch_event_t *de, sofia_nat_parse_t *np)
@@ -6703,6 +6825,31 @@ char *sofia_glue_gen_contact_str(sofia_profile_t *profile, sip_t const *sip, sof
return contact_str;
}
char *sofia_glue_get_host(const char *str, switch_memory_pool_t *pool)
{
char *s, *p;
if ((p = strchr(str, '@'))) {
p++;
} else {
return NULL;
}
if (pool) {
s = switch_core_strdup(pool, p);
} else {
s = strdup(p);
}
for (p = s; p && *p; p++) {
if ((*p == ';') || (*p == '>')) {
*p = '\0';
break;
}
}
return s;
}
/* For Emacs:
File diff suppressed because it is too large. Load diff
+172 -124
View File
@@ -65,10 +65,73 @@ static void sofia_reg_new_handle(sofia_gateway_t *gateway_ptr, int attach)
}
}
static void sofia_reg_new_sub_handle(sofia_gateway_t *gateway_ptr, int attach)
{
char *user_via = NULL;
char *register_host = sofia_glue_get_register_host(gateway_ptr->register_proxy);
int ss_state = nua_callstate_authenticating;
/* check for NAT and place a Via header if necessary (hostname or non-local IP) */
if (register_host && sofia_glue_check_nat(gateway_ptr->profile, register_host)) {
user_via = sofia_glue_create_external_via(NULL, gateway_ptr->profile, gateway_ptr->register_transport);
}
if (gateway_ptr->sub_nh) {
nua_handle_bind(gateway_ptr->sub_nh, NULL);
nua_handle_destroy(gateway_ptr->sub_nh);
gateway_ptr->sub_nh = NULL;
sofia_private_free(gateway_ptr->sofia_private);
}
gateway_ptr->sub_nh = nua_handle(gateway_ptr->profile->nua, NULL,
NUTAG_URL(gateway_ptr->register_proxy),
TAG_IF(user_via, SIPTAG_VIA_STR(user_via)),
SIPTAG_TO_STR(gateway_ptr->register_to),
NUTAG_CALLSTATE_REF(ss_state), SIPTAG_FROM_STR(gateway_ptr->register_from), TAG_END());
if (attach) {
if (!gateway_ptr->sofia_private) {
gateway_ptr->sofia_private = malloc(sizeof(*gateway_ptr->sofia_private));
switch_assert(gateway_ptr->sofia_private);
}
memset(gateway_ptr->sofia_private, 0, sizeof(*gateway_ptr->sofia_private));
gateway_ptr->sofia_private->gateway = gateway_ptr;
nua_handle_bind(gateway_ptr->sub_nh, gateway_ptr->sofia_private);
}
switch_safe_free(register_host);
switch_safe_free(user_via);
}
static void sofia_reg_kill_sub(sofia_gateway_t *gateway_ptr)
{
if (gateway_ptr->sub_nh) {
nua_handle_bind(gateway_ptr->sub_nh, NULL);
}
if (gateway_ptr->sub_state != SUB_STATE_SUBED && gateway_ptr->sub_state != SUB_STATE_UNSUBSCRIBE) {
if (gateway_ptr->sub_nh) {
nua_handle_destroy(gateway_ptr->sub_nh);
gateway_ptr->sub_nh = NULL;
}
return;
}
if (gateway_ptr->sub_nh) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "UN-Subbing %s\n", gateway_ptr->name);
nua_unsubscribe(gateway_ptr->sub_nh, NUTAG_URL(gateway_ptr->register_url), TAG_END());
}
}
static void sofia_reg_kill_reg(sofia_gateway_t *gateway_ptr)
{
if (gateway_ptr->state != REG_STATE_REGED) {
if (gateway_ptr->nh) {
nua_handle_bind(gateway_ptr->nh, NULL);
}
if (gateway_ptr->state != REG_STATE_REGED && gateway_ptr->state != REG_STATE_UNREGISTER) {
if (gateway_ptr->nh) {
nua_handle_destroy(gateway_ptr->nh);
gateway_ptr->nh = NULL;
@@ -76,19 +139,10 @@ static void sofia_reg_kill_reg(sofia_gateway_t *gateway_ptr)
return;
}
/*
if (!gateway_ptr->nh) {
sofia_reg_new_handle(gateway_ptr, SWITCH_FALSE);
}
*/
if (gateway_ptr->nh) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "UN-Registering %s\n", gateway_ptr->name);
nua_unregister(gateway_ptr->nh, NUTAG_URL(gateway_ptr->register_url), NUTAG_REGISTRAR(gateway_ptr->register_proxy), TAG_END());
}
}
void sofia_reg_fire_custom_gateway_state_event(sofia_gateway_t *gateway, int status, const char *phrase)
@@ -111,9 +165,15 @@ void sofia_reg_fire_custom_gateway_state_event(sofia_gateway_t *gateway, int sta
void sofia_reg_unregister(sofia_profile_t *profile)
{
sofia_gateway_t *gateway_ptr;
sofia_gateway_subscription_t *gw_sub_ptr;
switch_mutex_lock(mod_sofia_globals.hash_mutex);
for (gateway_ptr = profile->gateways; gateway_ptr; gateway_ptr = gateway_ptr->next) {
if (gateway_ptr->nh) {
nua_handle_bind(gateway_ptr->nh, NULL);
}
if (gateway_ptr->sofia_private) {
sofia_private_free(gateway_ptr->sofia_private);
}
@@ -122,6 +182,12 @@ void sofia_reg_unregister(sofia_profile_t *profile)
sofia_reg_kill_reg(gateway_ptr);
}
for (gw_sub_ptr = gateway_ptr->subscriptions; gw_sub_ptr; gw_sub_ptr = gw_sub_ptr->next) {
if (gw_sub_ptr->state == SUB_STATE_SUBED) {
sofia_reg_kill_sub(gateway_ptr);
}
}
}
switch_mutex_unlock(mod_sofia_globals.hash_mutex);
}
@@ -140,24 +206,14 @@ void sofia_sub_check_gateway(sofia_profile_t *profile, time_t now)
sofia_gateway_subscription_t *gw_sub_ptr;
for (gw_sub_ptr = gateway_ptr->subscriptions; gw_sub_ptr; gw_sub_ptr = gw_sub_ptr->next) {
int ss_state = nua_callstate_authenticating;
sub_state_t ostate = gw_sub_ptr->state;
char *user_via = NULL;
char *register_host = NULL;
if (!now) {
gw_sub_ptr->state = ostate = SUB_STATE_UNSUBED;
gw_sub_ptr->expires_str = "0";
}
register_host = sofia_glue_get_register_host(gateway_ptr->register_proxy);
/* check for NAT and place a Via header if necessary (hostname or non-local IP) */
if (register_host && sofia_glue_check_nat(gateway_ptr->profile, register_host)) {
user_via = sofia_glue_create_external_via(NULL, gateway_ptr->profile, gateway_ptr->register_transport);
}
switch_safe_free(register_host);
gateway_ptr->sub_state = gw_sub_ptr->state;
switch (ostate) {
case SUB_STATE_NOSUB:
@@ -168,37 +224,17 @@ void sofia_sub_check_gateway(sofia_profile_t *profile, time_t now)
break;
case SUB_STATE_UNSUBSCRIBE:
gw_sub_ptr->state = SUB_STATE_NOSUB;
/* not tested .. */
nua_unsubscribe(gateway_ptr->nh,
NUTAG_URL(gateway_ptr->register_url),
TAG_IF(user_via, SIPTAG_VIA_STR(user_via)),
SIPTAG_EVENT_STR(gw_sub_ptr->event),
SIPTAG_ACCEPT_STR(gw_sub_ptr->content_type),
SIPTAG_TO_STR(gateway_ptr->register_from),
SIPTAG_FROM_STR(gateway_ptr->register_from), SIPTAG_CONTACT_STR(gateway_ptr->register_contact), TAG_NULL());
sofia_reg_kill_sub(gateway_ptr);
break;
case SUB_STATE_UNSUBED:
gateway_ptr->sub_nh = nua_handle(gateway_ptr->profile->nua, NULL,
NUTAG_URL(gateway_ptr->register_proxy),
TAG_IF(user_via, SIPTAG_VIA_STR(user_via)),
SIPTAG_TO_STR(gateway_ptr->register_to),
NUTAG_CALLSTATE_REF(ss_state), SIPTAG_FROM_STR(gateway_ptr->register_from), TAG_END());
sofia_reg_new_sub_handle(gateway_ptr, 1);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "subscribing to [%s] on gateway [%s]\n", gw_sub_ptr->event, gateway_ptr->name);
gateway_ptr->sofia_private = malloc(sizeof(*gateway_ptr->sofia_private));
switch_assert(gateway_ptr->sofia_private);
memset(gateway_ptr->sofia_private, 0, sizeof(*gateway_ptr->sofia_private));
gateway_ptr->sofia_private->gateway = gateway_ptr;
nua_handle_bind(gateway_ptr->nh, gateway_ptr->sofia_private);
if (now) {
nua_subscribe(gateway_ptr->sub_nh,
NUTAG_URL(gateway_ptr->register_url),
TAG_IF(user_via, SIPTAG_VIA_STR(user_via)),
SIPTAG_EVENT_STR(gw_sub_ptr->event),
SIPTAG_ACCEPT_STR(gw_sub_ptr->content_type),
SIPTAG_TO_STR(gateway_ptr->register_from),
@@ -210,7 +246,6 @@ void sofia_sub_check_gateway(sofia_profile_t *profile, time_t now)
} else {
nua_unsubscribe(gateway_ptr->sub_nh,
NUTAG_URL(gateway_ptr->register_url),
TAG_IF(user_via, SIPTAG_VIA_STR(user_via)),
SIPTAG_EVENT_STR(gw_sub_ptr->event),
SIPTAG_ACCEPT_STR(gw_sub_ptr->content_type),
SIPTAG_FROM_STR(gateway_ptr->register_from),
@@ -233,7 +268,7 @@ void sofia_sub_check_gateway(sofia_profile_t *profile, time_t now)
}
break;
}
switch_safe_free(user_via);
}
}
switch_mutex_unlock(profile->gw_mutex);
@@ -676,10 +711,10 @@ void sofia_reg_check_expire(sofia_profile_t *profile, time_t now, int reboot)
sofia_glue_execute_sql_callback(profile, NULL, sql, sofia_reg_del_callback, profile);
if (now) {
switch_snprintf(sql, sizeof(sql), "delete from sip_registrations where expires > 0 and expires <= %ld and hostname='%s'",
switch_snprintfv(sql, sizeof(sql), "delete from sip_registrations where expires > 0 and expires <= %ld and hostname='%q'",
(long) now, mod_sofia_globals.hostname);
} else {
switch_snprintf(sql, sizeof(sql), "delete from sip_registrations where expires > 0 and hostname='%s'", mod_sofia_globals.hostname);
switch_snprintfv(sql, sizeof(sql), "delete from sip_registrations where expires > 0 and hostname='%q'", mod_sofia_globals.hostname);
}
sofia_glue_actually_execute_sql(profile, sql, NULL);
@@ -687,11 +722,11 @@ void sofia_reg_check_expire(sofia_profile_t *profile, time_t now, int reboot)
if (now) {
switch_snprintf(sql, sizeof(sql), "select call_id from sip_shared_appearance_dialogs where hostname='%s' "
switch_snprintfv(sql, sizeof(sql), "select call_id from sip_shared_appearance_dialogs where hostname='%q' "
"and profile_name='%s' and expires <= %ld", mod_sofia_globals.hostname, profile->name, (long) now);
sofia_glue_execute_sql_callback(profile, NULL, sql, sofia_sla_dialog_del_callback, profile);
switch_snprintf(sql, sizeof(sql), "delete from sip_shared_appearance_dialogs where expires > 0 and hostname='%s' and expires <= %ld",
switch_snprintfv(sql, sizeof(sql), "delete from sip_shared_appearance_dialogs where expires > 0 and hostname='%q' and expires <= %ld",
mod_sofia_globals.hostname, (long) now);
@@ -700,19 +735,19 @@ void sofia_reg_check_expire(sofia_profile_t *profile, time_t now, int reboot)
if (now) {
switch_snprintf(sql, sizeof(sql), "delete from sip_presence where expires > 0 and expires <= %ld and hostname='%s'",
switch_snprintfv(sql, sizeof(sql), "delete from sip_presence where expires > 0 and expires <= %ld and hostname='%q'",
(long) now, mod_sofia_globals.hostname);
} else {
switch_snprintf(sql, sizeof(sql), "delete from sip_presence where expires > 0 and hostname='%s'", mod_sofia_globals.hostname);
switch_snprintfv(sql, sizeof(sql), "delete from sip_presence where expires > 0 and hostname='%q'", mod_sofia_globals.hostname);
}
sofia_glue_actually_execute_sql(profile, sql, NULL);
if (now) {
switch_snprintf(sql, sizeof(sql), "delete from sip_authentication where expires > 0 and expires <= %ld and hostname='%s'",
switch_snprintfv(sql, sizeof(sql), "delete from sip_authentication where expires > 0 and expires <= %ld and hostname='%q'",
(long) now, mod_sofia_globals.hostname);
} else {
switch_snprintf(sql, sizeof(sql), "delete from sip_authentication where expires > 0 and hostname='%s'", mod_sofia_globals.hostname);
switch_snprintfv(sql, sizeof(sql), "delete from sip_authentication where expires > 0 and hostname='%q'", mod_sofia_globals.hostname);
}
sofia_glue_actually_execute_sql(profile, sql, NULL);
@@ -722,27 +757,20 @@ void sofia_reg_check_expire(sofia_profile_t *profile, time_t now, int reboot)
"select call_id from sip_subscriptions where (expires = -1 or (expires > 0 and expires <= %ld)) and hostname='%s'", (long) now,
mod_sofia_globals.hostname);
} else {
switch_snprintf(sql, sizeof(sql), "select sub_to_user,sub_to_host,call_id from sip_subscriptions where expires >= -1 and hostname='%s'",
switch_snprintfv(sql, sizeof(sql), "select sub_to_user,sub_to_host,call_id from sip_subscriptions where expires >= -1 and hostname='%q'",
mod_sofia_globals.hostname);
}
sofia_glue_execute_sql_callback(profile, NULL, sql, sofia_sub_del_callback, profile);
if (now) {
switch_snprintf(sql, sizeof(sql), "delete from sip_subscriptions where (expires = -1 or (expires > 0 and expires <= %ld)) and hostname='%s'",
(long) now, mod_sofia_globals.hostname);
} else {
switch_snprintf(sql, sizeof(sql), "delete from sip_subscriptions where expires >= -1 and hostname='%s'", mod_sofia_globals.hostname);
}
sofia_glue_actually_execute_sql(profile, sql, NULL);
sofia_presence_check_subscriptions(profile, now);
if (now) {
switch_snprintf(sql, sizeof(sql), "delete from sip_dialogs where (expires = -1 or (expires > 0 and expires <= %ld)) and hostname='%s'",
switch_snprintfv(sql, sizeof(sql), "delete from sip_dialogs where (expires = -1 or (expires > 0 and expires <= %ld)) and hostname='%q'",
(long) now, mod_sofia_globals.hostname);
} else {
switch_snprintf(sql, sizeof(sql), "delete from sip_dialogs where expires >= -1 and hostname='%s'", mod_sofia_globals.hostname);
switch_snprintfv(sql, sizeof(sql), "delete from sip_dialogs where expires >= -1 and hostname='%q'", mod_sofia_globals.hostname);
}
sofia_glue_actually_execute_sql(profile, sql, NULL);
@@ -833,24 +861,24 @@ void sofia_reg_check_sync(sofia_profile_t *profile)
sofia_glue_execute_sql_callback(profile, NULL, sql, sofia_reg_del_callback, profile);
switch_snprintf(sql, sizeof(sql), "delete from sip_registrations where expires > 0 and hostname='%s'", mod_sofia_globals.hostname);
switch_snprintfv(sql, sizeof(sql), "delete from sip_registrations where expires > 0 and hostname='%q'", mod_sofia_globals.hostname);
sofia_glue_actually_execute_sql(profile, sql, NULL);
switch_snprintf(sql, sizeof(sql), "delete from sip_presence where expires > 0 and hostname='%s'", mod_sofia_globals.hostname);
switch_snprintfv(sql, sizeof(sql), "delete from sip_presence where expires > 0 and hostname='%q'", mod_sofia_globals.hostname);
sofia_glue_actually_execute_sql(profile, sql, NULL);
switch_snprintf(sql, sizeof(sql), "delete from sip_authentication where expires > 0 and hostname='%s'", mod_sofia_globals.hostname);
switch_snprintfv(sql, sizeof(sql), "delete from sip_authentication where expires > 0 and hostname='%q'", mod_sofia_globals.hostname);
sofia_glue_actually_execute_sql(profile, sql, NULL);
switch_snprintf(sql, sizeof(sql), "select sub_to_user,sub_to_host,call_id from sip_subscriptions where expires >= -1 and hostname='%s'",
switch_snprintfv(sql, sizeof(sql), "select sub_to_user,sub_to_host,call_id from sip_subscriptions where expires >= -1 and hostname='%q'",
mod_sofia_globals.hostname);
sofia_glue_execute_sql_callback(profile, NULL, sql, sofia_sub_del_callback, profile);
switch_snprintf(sql, sizeof(sql), "delete from sip_subscriptions where expires >= -1 and hostname='%s'", mod_sofia_globals.hostname);
switch_snprintfv(sql, sizeof(sql), "delete from sip_subscriptions where expires >= -1 and hostname='%q'", mod_sofia_globals.hostname);
sofia_glue_actually_execute_sql(profile, sql, NULL);
switch_snprintf(sql, sizeof(sql), "delete from sip_dialogs where expires >= -1 and hostname='%s'", mod_sofia_globals.hostname);
switch_snprintfv(sql, sizeof(sql), "delete from sip_dialogs where expires >= -1 and hostname='%q'", mod_sofia_globals.hostname);
sofia_glue_actually_execute_sql(profile, sql, NULL);
switch_mutex_unlock(profile->ireg_mutex);
@@ -871,10 +899,10 @@ char *sofia_reg_find_reg_url(sofia_profile_t *profile, const char *user, const c
cbt.len = len;
if (host) {
switch_snprintf(sql, sizeof(sql), "select contact from sip_registrations where sip_user='%s' and (sip_host='%s' or presence_hosts like '%%%s%%')",
switch_snprintfv(sql, sizeof(sql), "select contact from sip_registrations where sip_user='%q' and (sip_host='%q' or presence_hosts like '%%%q%%')",
user, host, host);
} else {
switch_snprintf(sql, sizeof(sql), "select contact from sip_registrations where sip_user='%s'", user);
switch_snprintfv(sql, sizeof(sql), "select contact from sip_registrations where sip_user='%q'", user);
}
@@ -900,10 +928,10 @@ switch_console_callback_match_t *sofia_reg_find_reg_url_multi(sofia_profile_t *p
}
if (host) {
switch_snprintf(sql, sizeof(sql), "select contact from sip_registrations where sip_user='%s' and (sip_host='%s' or presence_hosts like '%%%s%%')",
switch_snprintfv(sql, sizeof(sql), "select contact from sip_registrations where sip_user='%q' and (sip_host='%q' or presence_hosts like '%%%q%%')",
user, host, host);
} else {
switch_snprintf(sql, sizeof(sql), "select contact from sip_registrations where sip_user='%s'", user);
switch_snprintfv(sql, sizeof(sql), "select contact from sip_registrations where sip_user='%q'", user);
}
@@ -924,10 +952,10 @@ switch_console_callback_match_t *sofia_reg_find_reg_url_with_positive_expires_mu
}
if (host) {
switch_snprintf(sql, sizeof(sql), "select contact,expires from sip_registrations where sip_user='%s' and (sip_host='%s' or presence_hosts like '%%%s%%')",
switch_snprintfv(sql, sizeof(sql), "select contact,expires from sip_registrations where sip_user='%q' and (sip_host='%q' or presence_hosts like '%%%q%%')",
user, host, host);
} else {
switch_snprintf(sql, sizeof(sql), "select contact,expires from sip_registrations where sip_user='%s'", user);
switch_snprintfv(sql, sizeof(sql), "select contact,expires from sip_registrations where sip_user='%q'", user);
}
sofia_glue_execute_sql_callback(profile, profile->ireg_mutex, sql, sofia_reg_find_reg_with_positive_expires_callback, &cbt);
@@ -1011,7 +1039,7 @@ uint8_t sofia_reg_handle_register(nua_t *nua, sofia_profile_t *profile, nua_hand
char contact_str[1024] = "";
uint8_t multi_reg = 0, multi_reg_contact = 0, avoid_multi_reg = 0;
uint8_t stale = 0, forbidden = 0;
auth_res_t auth_res;
auth_res_t auth_res = AUTH_OK;
long exptime = 300;
switch_event_t *event;
const char *rpid = "unknown";
@@ -1343,7 +1371,7 @@ uint8_t sofia_reg_handle_register(nua_t *nua, sofia_profile_t *profile, nua_hand
}
}
if (auth_res != AUTH_OK && !stale) {
if (auth_res != AUTH_OK && auth_res != AUTH_RENEWED && !stale) {
if (auth_res == AUTH_FORBIDDEN) {
nua_respond(nh, SIP_403_FORBIDDEN, NUTAG_WITH_THIS_MSG(de->data->e_msg), TAG_END());
forbidden = 1;
@@ -1401,7 +1429,7 @@ uint8_t sofia_reg_handle_register(nua_t *nua, sofia_profile_t *profile, nua_hand
}
/* Log line added to support Fail2Ban */
if (sofia_test_pflag(profile, PFLAG_LOG_AUTH_FAIL)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG10, "SIP auth challenge (%s) on sofia profile '%s' "
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "SIP auth challenge (%s) on sofia profile '%s' "
"for [%s@%s] from ip %s\n", (regtype == REG_INVITE) ? "INVITE" : "REGISTER",
profile->name, to_user, to_host, network_ip);
}
@@ -1455,38 +1483,51 @@ uint8_t sofia_reg_handle_register(nua_t *nua, sofia_profile_t *profile, nua_hand
const char *realm = reg_host;
char *url = NULL;
char *contact = NULL;
switch_bool_t update_registration = SWITCH_FALSE;
if (auth_params) {
username = switch_event_get_header(auth_params, "sip_auth_username");
realm = switch_event_get_header(auth_params, "sip_auth_realm");
}
if (auth_res != AUTH_RENEWED) {
if (multi_reg) {
if (multi_reg) {
if (delete_subs) {
if (reg_count == 1) {
sql = switch_mprintf("update sip_subscriptions set expires=%ld where sip_user='%q' and sip_host='%q' and contact='%q'",
(long) switch_epoch_time_now(NULL), to_user, sub_host, contact_str);
sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE);
}
}
if (delete_subs) {
if (reg_count == 1) {
sql = switch_mprintf("delete from sip_subscriptions where sip_user='%q' and sip_host='%q' and contact='%q'",
to_user, sub_host, contact_str);
if (multi_reg_contact) {
sql =
switch_mprintf("delete from sip_registrations where sip_user='%q' and sip_host='%q' and contact='%q'", to_user, reg_host, contact_str);
} else {
sql = switch_mprintf("delete from sip_registrations where call_id='%q'", call_id);
}
} else {
if (delete_subs) {
sql = switch_mprintf("delete from sip_subscriptions where sip_user='%q' and sip_host='%q'", to_user, sub_host);
sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE);
}
sql = switch_mprintf("delete from sip_registrations where sip_user='%q' and sip_host='%q'", to_user, reg_host);
}
if (multi_reg_contact) {
sql =
switch_mprintf("delete from sip_registrations where sip_user='%q' and sip_host='%q' and contact='%q'", to_user, reg_host, contact_str);
} else {
sql = switch_mprintf("delete from sip_registrations where call_id='%q'", call_id);
}
switch_mutex_lock(profile->ireg_mutex);
sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE);
} else {
if (delete_subs) {
sql = switch_mprintf("delete from sip_subscriptions where sip_user='%q' and sip_host='%q'", to_user, sub_host);
sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE);
char buf[32] = "";
sql = switch_mprintf("select count(*) from sip_registrations where sip_user='%q' and sip_host='%q' and contact='%q'", to_user, reg_host, contact_str);
switch_mutex_lock(profile->ireg_mutex);
sofia_glue_execute_sql2str(profile, profile->ireg_mutex, sql, buf, sizeof(buf));
switch_safe_free(sql);
if (atoi(buf) > 0) {
update_registration = SWITCH_TRUE;
}
sql = switch_mprintf("delete from sip_registrations where sip_user='%q' and sip_host='%q'", to_user, reg_host);
}
switch_mutex_lock(profile->ireg_mutex);
sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE);
switch_find_local_ip(guess_ip4, sizeof(guess_ip4), NULL, AF_INET);
@@ -1499,21 +1540,25 @@ uint8_t sofia_reg_handle_register(nua_t *nua, sofia_profile_t *profile, nua_hand
switch_safe_free(url);
switch_safe_free(contact);
sql = switch_mprintf("insert into sip_registrations "
"(call_id,sip_user,sip_host,presence_hosts,contact,status,rpid,expires,"
"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) "
"values ('%q','%q', '%q','%q','%q','%q', '%q', %ld, '%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,
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);
if (!update_registration) {
sql = switch_mprintf("insert into sip_registrations "
"(call_id,sip_user,sip_host,presence_hosts,contact,status,rpid,expires,"
"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) "
"values ('%q','%q', '%q','%q','%q','%q', '%q', %ld, '%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,
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);
} else {
sql = switch_mprintf("update sip_registrations set expires = %ld where sip_user='%q' and sip_host='%q' and contact='%q'", (long) switch_epoch_time_now(NULL) + (long) exptime + 60, to_user, reg_host, contact_str);
}
if (sql) {
sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE);
}
if (sofia_reg_reg_count(profile, to_user, reg_host) == 1) {
if (!update_registration && sofia_reg_reg_count(profile, to_user, reg_host) == 1) {
sql = switch_mprintf("delete from sip_presence where sip_user='%q' and sip_host='%q' and profile_name='%q' and open_closed='closed'",
to_user, reg_host, profile->name);
if (mod_sofia_globals.debug_presence > 0) {
@@ -1563,7 +1608,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);
}
#else
if (sofia_test_pflag(profile, PFLAG_MESSAGE_QUERY_ON_REGISTER) ||
(reg_count == 1 && sofia_test_pflag(profile, PFLAG_MESSAGE_QUERY_ON_FIRST_REGISTER))) {
@@ -1600,6 +1645,7 @@ uint8_t sofia_reg_handle_register(nua_t *nua, sofia_profile_t *profile, nua_hand
(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", "Unregistered");
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "presence-source", "register");
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "event_type", "presence");
switch_event_fire(&event);
}
@@ -1628,9 +1674,10 @@ uint8_t sofia_reg_handle_register(nua_t *nua, sofia_profile_t *profile, nua_hand
if (delete_subs) {
if (multi_reg_contact) {
sql =
switch_mprintf("delete from sip_subscriptions where sip_user='%q' and sip_host='%q' and contact='%q'", to_user, sub_host, contact_str);
switch_mprintf("update sip_subscriptions set expires=%ld where sip_user='%q' and sip_host='%q' and contact='%q'",
(long) switch_epoch_time_now(NULL), to_user, sub_host, contact_str);
} else {
sql = switch_mprintf("delete from sip_subscriptions where call_id='%q'", call_id);
sql = switch_mprintf("update sip_subscriptions set expires=%ld where call_id='%q'", (long) switch_epoch_time_now(NULL), call_id);
}
sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE);
@@ -1648,7 +1695,8 @@ uint8_t sofia_reg_handle_register(nua_t *nua, sofia_profile_t *profile, nua_hand
switch_safe_free(icontact);
} else {
if (delete_subs) {
if ((sql = switch_mprintf("delete from sip_subscriptions where sip_user='%q' and sip_host='%q'", to_user, sub_host))) {
if ((sql = switch_mprintf("update sip_subscriptions set expires=%ld where sip_user='%q' and sip_host='%q'",
(long) switch_epoch_time_now(NULL), to_user, sub_host))) {
sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE);
}
}
@@ -1681,7 +1729,7 @@ uint8_t sofia_reg_handle_register(nua_t *nua, sofia_profile_t *profile, nua_hand
(reg_count == 1 && sofia_test_pflag(profile, PFLAG_MESSAGE_QUERY_ON_FIRST_REGISTER))) {
if (switch_event_create(&s_mwi_event, SWITCH_EVENT_MESSAGE_QUERY) == SWITCH_STATUS_SUCCESS) {
switch_event_add_header(s_mwi_event, SWITCH_STACK_BOTTOM, "Message-Account", "sip:%s@%s", mwi_user, mwi_host);
switch_event_add_header_string(s_mwi_event, SWITCH_STACK_BOTTOM, "VM-Sofia-Profile", profile->name);
switch_event_add_header_string(s_mwi_event, SWITCH_STACK_BOTTOM, "VM-Sofia-Pofile", profile->name);
switch_event_add_header_string(s_mwi_event, SWITCH_STACK_BOTTOM, "VM-Call-ID", call_id);
}
}
@@ -1697,6 +1745,7 @@ uint8_t sofia_reg_handle_register(nua_t *nua, sofia_profile_t *profile, nua_hand
switch_event_add_header(s_event, SWITCH_STACK_BOTTOM, "from", "%s@%s", to_user, sub_host);
switch_event_add_header(s_event, SWITCH_STACK_BOTTOM, "to", "%s@%s", to_user, sub_host);
switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "event_type", "presence");
switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "presence-source", "register");
switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "alt_event_type", "dialog");
switch_event_fire(&s_event);
}
@@ -1704,6 +1753,7 @@ uint8_t sofia_reg_handle_register(nua_t *nua, sofia_profile_t *profile, nua_hand
if (switch_event_create(&s_event, SWITCH_EVENT_PRESENCE_IN) == 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_string(s_event, SWITCH_STACK_BOTTOM, "presence-source", "register");
switch_event_add_header(s_event, SWITCH_STACK_BOTTOM, "from", "%s@%s", to_user, sub_host);
switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "rpid", "unknown");
switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "status", "Registered");
@@ -1774,10 +1824,6 @@ uint8_t sofia_reg_handle_register(nua_t *nua, sofia_profile_t *profile, nua_hand
switch_event_fire(&s_mwi_event);
}
if (contact && *contact_str && sofia_test_pflag(profile, PFLAG_MANAGE_SHARED_APPEARANCE_SYLANTRO)) {
sofia_sla_handle_register(nua, profile, sip, de, exptime, contact_str);
}
switch_goto_int(r, 1, end);
}
@@ -2098,7 +2144,7 @@ void sofia_reg_handle_sip_r_challenge(int status,
switch_event_create(&locate_params, SWITCH_EVENT_REQUEST_PARAMS);
switch_assert(locate_params);
switch_event_add_header_string(locate_params, SWITCH_STACK_BOTTOM, "Action", "reverse-auth-lookup");
switch_event_add_header_string(locate_params, SWITCH_STACK_BOTTOM, "action", "reverse-auth-lookup");
if (switch_xml_locate_user_merged("id", sip->sip_to->a_url->url_user, sip->sip_to->a_url->url_host, NULL,
&x_user, locate_params) == SWITCH_STATUS_SUCCESS) {
@@ -2626,8 +2672,7 @@ auth_res_t sofia_reg_parse_auth(sofia_profile_t *profile,
switch_safe_free(input2);
skip_auth:
if (first && ret == AUTH_OK) {
if (first && (ret == AUTH_OK || ret == AUTH_RENEWED)) {
if (v_event) {
switch_event_create_plain(v_event, SWITCH_EVENT_REQUEST_PARAMS);
}
@@ -2753,6 +2798,9 @@ auth_res_t sofia_reg_parse_auth(sofia_profile_t *profile,
switch_assert(sql != NULL);
sofia_glue_actually_execute_sql(profile, sql, profile->ireg_mutex);
switch_safe_free(sql);
if (ret == AUTH_OK)
ret = AUTH_RENEWED;
}
switch_event_destroy(&params);
@@ -2772,7 +2820,7 @@ auth_res_t sofia_reg_parse_auth(sofia_profile_t *profile,
switch_safe_free(response);
if (reg_count && !*reg_count) {
if (ret == AUTH_OK) {
if ((ret == AUTH_OK || ret == AUTH_RENEWED)) {
if (ncl) {
*reg_count = ncl;
} else {
-413
View File
@@ -1,413 +0,0 @@
/*
* 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;
}