mirror of
https://github.com/signalwire/freeswitch.git
synced 2026-10-18 01:04:13 +00:00
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:
commit
7e31b9cc28
300 files changed
+15500
-6153
No files matched your search
@@ -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" />
|
||||
|
||||
@@ -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:
|
||||
*/
|
||||
|
||||
@@ -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);
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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
@@ -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(¶ms);
|
||||
@@ -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 {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
Reference in new issue
Block a user