mirror of
https://github.com/signalwire/freeswitch.git
synced 2026-07-24 05:02:10 +00:00
Merge branch 'fsorig'
Conflicts: libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_cfg.c libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_hndl.c
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
<configuration name="abstraction.conf" description="Abstraction">
|
||||
<apis>
|
||||
<api name="user_name" description="Return Name for extension" syntax="<exten>" parse="(.*)" destination="user_data" argument="$1@default var effective_caller_id_name"/>
|
||||
</apis>
|
||||
</configuration>
|
||||
@@ -0,0 +1,11 @@
|
||||
<configuration name="mod_blacklist.conf" description="Blacklist module">
|
||||
<lists>
|
||||
<!--
|
||||
Example blacklist, the referenced file contains blacklisted items, one entry per line
|
||||
|
||||
NOTE: make sure the file exists and is readable by FreeSWITCH.
|
||||
|
||||
<list name="example" filename="/usr/local/freeswitch/conf/blacklists/example.list"/>
|
||||
-->
|
||||
</lists>
|
||||
</configuration>
|
||||
@@ -0,0 +1,38 @@
|
||||
<configuration name="callcenter.conf" description="CallCenter">
|
||||
<settings>
|
||||
<!--<param name="odbc-dsn" value="dsn:user:pass"/>-->
|
||||
<!--<param name="dbname" value="/dev/shm/callcenter.db"/>-->
|
||||
</settings>
|
||||
|
||||
<queues>
|
||||
|
||||
<queue name="support@default">
|
||||
<param name="strategy" value="longest-idle-agent"/>
|
||||
<param name="moh-sound" value="$${hold_music}"/>
|
||||
<!--<param name="record-template" value="$${base_dir}/recordings/${strftime(%Y-%m-%d-%H-%M-%S)}.${destination_number}.${caller_id_number}.${uuid}.wav"/>-->
|
||||
<param name="time-base-score" value="system"/>
|
||||
<param name="max-wait-time" value="0"/>
|
||||
<param name="max-wait-time-with-no-agent" value="0"/>
|
||||
<param name="max-wait-time-with-no-agent-time-reached" value="5"/>
|
||||
<param name="tier-rules-apply" value="false"/>
|
||||
<param name="tier-rule-wait-second" value="300"/>
|
||||
<param name="tier-rule-wait-multiply-level" value="true"/>
|
||||
<param name="tier-rule-no-agent-no-wait" value="false"/>
|
||||
<param name="discard-abandoned-after" value="60"/>
|
||||
<param name="abandoned-resume-allowed" value="false"/>
|
||||
</queue>
|
||||
|
||||
</queues>
|
||||
|
||||
<!-- WARNING: Configuration of XML Agents will be updated into the DB upon restart. -->
|
||||
<!-- WARNING: Configuration of XML Tiers will reset the level and position if those were supplied. -->
|
||||
<!-- WARNING: Agents and Tiers XML config shouldn't be used in a multi FS shared DB setup (Not currently supported anyway) -->
|
||||
<agents>
|
||||
<!--<agent name="1000@default" type="callback" contact="[call_timeout=10]user/1000@default" status="Available" max-no-answer="3" wrap-up-time="10" reject-delay-time="10" busy-delay-time="60" />-->
|
||||
</agents>
|
||||
<tiers>
|
||||
<!-- If no level or position is provided, they will default to 1. You should do this to keep db value on restart. -->
|
||||
<!-- <tier agent="1000@default" queue="support@default" level="1" position="1"/> -->
|
||||
</tiers>
|
||||
|
||||
</configuration>
|
||||
@@ -1371,6 +1371,22 @@ end:
|
||||
return status;
|
||||
}
|
||||
|
||||
static void playback_array(switch_core_session_t *session, const char *str) {
|
||||
if (str && !strncmp(str, "ARRAY::", 7)) {
|
||||
char *i = (char*) str + 7, *j = i;
|
||||
while (1) {
|
||||
if ((j = strstr(i, "::"))) {
|
||||
*j = 0;
|
||||
}
|
||||
switch_ivr_play_file(session, NULL, i, NULL);
|
||||
if (!j) break;
|
||||
i = j + 2;
|
||||
}
|
||||
} else {
|
||||
switch_ivr_play_file(session, NULL, str, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
static void *SWITCH_THREAD_FUNC outbound_agent_thread_run(switch_thread_t *thread, void *obj)
|
||||
{
|
||||
struct call_helper *h = (struct call_helper *) obj;
|
||||
@@ -1429,6 +1445,14 @@ static void *SWITCH_THREAD_FUNC outbound_agent_thread_run(switch_thread_t *threa
|
||||
|
||||
/* CallBack Mode */
|
||||
if (!strcasecmp(h->agent_type, CC_AGENT_TYPE_CALLBACK)) {
|
||||
switch_channel_t *member_channel = switch_core_session_get_channel(member_session);
|
||||
char *cid_name = NULL;
|
||||
const char *cid_name_prefix = NULL;
|
||||
if ((cid_name_prefix = switch_channel_get_variable(member_channel, "cc_outbound_cid_name_prefix"))) {
|
||||
cid_name = switch_mprintf("%s%s", cid_name_prefix, h->member_cid_name);
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(member_session), SWITCH_LOG_DEBUG, "Setting outbound caller_id_name to: %s\n", cid_name);
|
||||
}
|
||||
|
||||
switch_event_create(&ovars, SWITCH_EVENT_REQUEST_PARAMS);
|
||||
switch_event_add_header(ovars, SWITCH_STACK_BOTTOM, "cc_queue", "%s", h->queue_name);
|
||||
switch_event_add_header(ovars, SWITCH_STACK_BOTTOM, "cc_member_uuid", "%s", h->member_uuid);
|
||||
@@ -1444,9 +1468,9 @@ static void *SWITCH_THREAD_FUNC outbound_agent_thread_run(switch_thread_t *threa
|
||||
|
||||
t_agent_called = local_epoch_time_now(NULL);
|
||||
dialstr = switch_mprintf("%s", h->originate_string);
|
||||
status = switch_ivr_originate(NULL, &agent_session, &cause, dialstr, 60, NULL, h->member_cid_name, h->member_cid_number, NULL, ovars, SOF_NONE, NULL);
|
||||
|
||||
status = switch_ivr_originate(NULL, &agent_session, &cause, dialstr, 60, NULL, cid_name ? cid_name : h->member_cid_name, h->member_cid_number, NULL, ovars, SOF_NONE, NULL);
|
||||
switch_safe_free(dialstr);
|
||||
switch_safe_free(cid_name);
|
||||
|
||||
switch_event_destroy(&ovars);
|
||||
/* UUID Standby Mode */
|
||||
@@ -1489,6 +1513,7 @@ static void *SWITCH_THREAD_FUNC outbound_agent_thread_run(switch_thread_t *threa
|
||||
switch_channel_t *member_channel = switch_core_session_get_channel(member_session);
|
||||
switch_channel_t *agent_channel = switch_core_session_get_channel(agent_session);
|
||||
const char *other_loopback_leg_uuid = switch_channel_get_variable(agent_channel, "other_loopback_leg_uuid");
|
||||
const char *o_announce = NULL;
|
||||
|
||||
switch_channel_set_variable(agent_channel, "cc_member_pre_answer_uuid", NULL);
|
||||
|
||||
@@ -1616,6 +1641,10 @@ static void *SWITCH_THREAD_FUNC outbound_agent_thread_run(switch_thread_t *threa
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(member_session), SWITCH_LOG_DEBUG, "Agent %s answered \"%s\" <%s> from queue %s%s\n",
|
||||
h->agent_name, h->member_cid_name, h->member_cid_number, h->queue_name, (h->record_template?" (Recorded)":""));
|
||||
|
||||
if ((o_announce = switch_channel_get_variable(member_channel, "cc_outbound_announce"))) {
|
||||
playback_array(agent_session, o_announce);
|
||||
}
|
||||
|
||||
switch_ivr_uuid_bridge(h->member_session_uuid, switch_core_session_get_uuid(agent_session));
|
||||
|
||||
switch_channel_set_variable(member_channel, "cc_agent_uuid", agent_uuid);
|
||||
@@ -2340,6 +2369,7 @@ void *SWITCH_THREAD_FUNC cc_member_thread_run(switch_thread_t *thread, void *obj
|
||||
|
||||
struct moh_dtmf_helper {
|
||||
const char *queue_name;
|
||||
const char *exit_keys;
|
||||
char dtmf;
|
||||
};
|
||||
|
||||
@@ -2348,10 +2378,9 @@ static switch_status_t moh_on_dtmf(switch_core_session_t *session, void *input,
|
||||
|
||||
switch (itype) {
|
||||
case SWITCH_INPUT_TYPE_DTMF:
|
||||
{
|
||||
/* Just laywork for people who want to get some DTMF actions */
|
||||
if (h->exit_keys && *(h->exit_keys)) {
|
||||
switch_dtmf_t *dtmf = (switch_dtmf_t *) input;
|
||||
if (strchr("#", dtmf->digit)) {
|
||||
if (strchr(h->exit_keys, dtmf->digit)) {
|
||||
h->dtmf = dtmf->digit;
|
||||
return SWITCH_STATUS_BREAK;
|
||||
}
|
||||
@@ -2552,6 +2581,7 @@ SWITCH_STANDARD_APP(callcenter_function)
|
||||
switch_input_args_t args = { 0 };
|
||||
struct moh_dtmf_helper ht;
|
||||
|
||||
ht.exit_keys = switch_channel_get_variable(member_channel, "cc_exit_keys");
|
||||
ht.dtmf = '\0';
|
||||
args.input_callback = moh_on_dtmf;
|
||||
args.buf = (void *) &ht;
|
||||
@@ -2575,17 +2605,21 @@ SWITCH_STANDARD_APP(callcenter_function)
|
||||
/* Sadly, there doesn't seem to be a return to switch_ivr_play_file that tell you the file wasn't found. FALSE also mean that the channel got switch to BRAKE state, so we check for read acceptable */
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(member_session), SWITCH_LOG_WARNING, "Couldn't play file '%s', continuing wait with no audio\n", cur_moh);
|
||||
moh_valid = SWITCH_FALSE;
|
||||
|
||||
} else if (status == SWITCH_STATUS_BREAK) {
|
||||
char buf[2] = { ht.dtmf, 0 };
|
||||
switch_channel_set_variable(member_channel, "cc_exit_key", buf);
|
||||
break;
|
||||
} else if (!SWITCH_READ_ACCEPTABLE(status)) {
|
||||
break;
|
||||
}
|
||||
|
||||
} else {
|
||||
switch_ivr_collect_digits_callback(session, &args, 0, 0);
|
||||
if ((switch_ivr_collect_digits_callback(member_session, &args, 0, 0)) == SWITCH_STATUS_BREAK) {
|
||||
char buf[2] = { ht.dtmf, 0 };
|
||||
switch_channel_set_variable(member_channel, "cc_exit_key", buf);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
switch_yield(1000);
|
||||
|
||||
}
|
||||
|
||||
/* Make sure an agent was found, as we might break above without setting it */
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
<configuration name="cidlookup.conf" description="cidlookup Configuration">
|
||||
<settings>
|
||||
<!-- comment out url to not setup a url based lookup -->
|
||||
<param name="url" value="http://query.voipcnam.com/query.php?api_key=MYAPIKEY&number=${caller_id_number}"/>
|
||||
|
||||
<!-- comment out whitepages-apikey to not use whitepages.com, you must
|
||||
get an API key from http://developer.whitepages.com/ -->
|
||||
<param name="whitepages-apikey" value="MYAPIKEY"/>
|
||||
|
||||
<!-- set to false to not cache (in memcache) results from the url query -->
|
||||
<param name="cache" value="true"/>
|
||||
<!-- expire is in seconds -->
|
||||
<param name="cache-expire" value="86400"/>
|
||||
|
||||
<param name="odbc-dsn" value="phone:phone:phone"/>
|
||||
|
||||
<!-- comment out sql to not setup a database (directory) lookup -->
|
||||
<param name="sql" value="
|
||||
SELECT name||' ('||type||')' AS name
|
||||
FROM phonebook p JOIN numbers n ON p.id = n.phonebook_id
|
||||
WHERE n.number='${caller_id_number}'
|
||||
LIMIT 1
|
||||
"/>
|
||||
<!-- comment out citystate-sql to not setup a database (city/state)
|
||||
lookup -->
|
||||
<param name="citystate-sql" value="
|
||||
SELECT ratecenter||' '||state as name
|
||||
FROM npa_nxx_company_ocn
|
||||
WHERE npa = ${caller_id_number:1:3} AND nxx = ${caller_id_number:4:3}
|
||||
LIMIT 1
|
||||
"/>
|
||||
</settings>
|
||||
</configuration>
|
||||
@@ -546,24 +546,19 @@ SWITCH_STANDARD_API(timer_test_function)
|
||||
goto end;
|
||||
}
|
||||
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Timer Test: samplecount after init: %d\n", timer.samplecount);
|
||||
switch_core_timer_next(&timer); /* Step timer once before testing results below, to get first timestamp as accurate as possible */
|
||||
|
||||
/* Step timer once before testing results below, to get first timestamp as accurate as possible */
|
||||
switch_core_timer_next(&timer);
|
||||
start = then = switch_time_ref();
|
||||
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Timer Test: samplecount after first step: %d\n", timer.samplecount);
|
||||
|
||||
start = switch_time_ref();
|
||||
for (x = 1; x <= max; x++) {
|
||||
then = switch_time_ref();
|
||||
switch_core_timer_next(&timer);
|
||||
now = switch_time_ref();
|
||||
diff = (int) (now - then);
|
||||
//stream->write_function(stream, "test %d sleep %ld %d\n", x, mss, diff);
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Timer Test: %d sleep %d %d\n", x, mss, diff);
|
||||
total += diff;
|
||||
then = now;
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Timer Test: %d sleep %d %d\n", x, mss, diff);
|
||||
}
|
||||
end = switch_time_ref();
|
||||
end = then;
|
||||
|
||||
switch_yield(250000);
|
||||
|
||||
@@ -1913,6 +1908,12 @@ SWITCH_STANDARD_API(ctl_function)
|
||||
}
|
||||
switch_core_session_ctl(command, &arg);
|
||||
stream->write_function(stream, "+OK\n");
|
||||
|
||||
} else if (!strcasecmp(argv[0], "debug_sql")) {
|
||||
int x = 0;
|
||||
switch_core_session_ctl(SCSC_DEBUG_SQL, &x);
|
||||
stream->write_function(stream, "+OK SQL DEBUG [%s]\n", x ? "on" : "off");
|
||||
|
||||
} else if (!strcasecmp(argv[0], "reclaim_mem")) {
|
||||
switch_core_session_ctl(SCSC_RECLAIM, &arg);
|
||||
stream->write_function(stream, "+OK\n");
|
||||
@@ -2379,7 +2380,7 @@ SWITCH_STANDARD_API(dual_transfer_function)
|
||||
}
|
||||
}
|
||||
|
||||
if ((dp2 = strstr(dest1, "/inline")) && *(dp2 + 7) == '\0') {
|
||||
if ((dp2 = strstr(dest2, "/inline")) && *(dp2 + 7) == '\0') {
|
||||
*dp2++ = '\0';
|
||||
} else {
|
||||
if ((dp2 = strchr(dest2, '/'))) {
|
||||
@@ -5312,6 +5313,27 @@ SWITCH_STANDARD_API(log_function)
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
SWITCH_STANDARD_API(file_exists_function)
|
||||
{
|
||||
if (!zstr(cmd)) {
|
||||
switch_memory_pool_t *pool;
|
||||
|
||||
switch_core_new_memory_pool(&pool);
|
||||
|
||||
if (switch_file_exists(cmd, pool) == SWITCH_STATUS_SUCCESS) {
|
||||
stream->write_function(stream, "true");
|
||||
} else {
|
||||
stream->write_function(stream, "false");
|
||||
}
|
||||
|
||||
switch_core_destroy_memory_pool(&pool);
|
||||
} else {
|
||||
stream->write_function(stream, "false");
|
||||
}
|
||||
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
SWITCH_MODULE_LOAD_FUNCTION(mod_commands_load)
|
||||
{
|
||||
switch_api_interface_t *commands_api_interface;
|
||||
@@ -5436,6 +5458,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_commands_load)
|
||||
SWITCH_ADD_API(commands_api_interface, "xml_flush_cache", "clear xml cache", xml_flush_function, "<id> <key> <val>");
|
||||
SWITCH_ADD_API(commands_api_interface, "xml_locate", "find some xml", xml_locate_function, "[root | <section> <tag> <tag_attr_name> <tag_attr_val>]");
|
||||
SWITCH_ADD_API(commands_api_interface, "xml_wrap", "Wrap another api command in xml", xml_wrap_api_function, "<command> <args>");
|
||||
SWITCH_ADD_API(commands_api_interface, "file_exists", "check if a file exists on server", file_exists_function, "<file>");
|
||||
|
||||
|
||||
switch_console_set_complete("add alias add");
|
||||
@@ -5444,6 +5467,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_commands_load)
|
||||
switch_console_set_complete("add complete del");
|
||||
switch_console_set_complete("add db_cache status");
|
||||
switch_console_set_complete("add fsctl debug_level");
|
||||
switch_console_set_complete("add fsctl debug_sql");
|
||||
switch_console_set_complete("add fsctl last_sps");
|
||||
switch_console_set_complete("add fsctl default_dtmf_duration");
|
||||
switch_console_set_complete("add fsctl hupall");
|
||||
@@ -5577,6 +5601,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_commands_load)
|
||||
switch_console_set_complete("add version");
|
||||
switch_console_set_complete("add uuid_warning ::console::list_uuid");
|
||||
switch_console_set_complete("add ...");
|
||||
switch_console_set_complete("add file_exists");
|
||||
|
||||
|
||||
/* indicate that the module should continue to be loaded */
|
||||
|
||||
@@ -0,0 +1,209 @@
|
||||
<!-- http://wiki.freeswitch.org/wiki/Mod_conference -->
|
||||
<!-- None of these paths are real if you want any of these options you need to really set them up -->
|
||||
<configuration name="conference.conf" description="Audio Conference">
|
||||
<!-- Advertise certain presence on startup . -->
|
||||
<advertise>
|
||||
<room name="3001@$${domain}" status="FreeSWITCH"/>
|
||||
</advertise>
|
||||
|
||||
<!-- These are the default keys that map when you do not specify a caller control group -->
|
||||
<!-- Note: none and default are reserved names for group names. Disabled if dist-dtmf member flag is set. -->
|
||||
<caller-controls>
|
||||
<group name="default">
|
||||
<control action="mute" digits="0"/>
|
||||
<control action="deaf mute" digits="*"/>
|
||||
<control action="energy up" digits="9"/>
|
||||
<control action="energy equ" digits="8"/>
|
||||
<control action="energy dn" digits="7"/>
|
||||
<control action="vol talk up" digits="3"/>
|
||||
<control action="vol talk zero" digits="2"/>
|
||||
<control action="vol talk dn" digits="1"/>
|
||||
<control action="vol listen up" digits="6"/>
|
||||
<control action="vol listen zero" digits="5"/>
|
||||
<control action="vol listen dn" digits="4"/>
|
||||
<control action="hangup" digits="#"/>
|
||||
</group>
|
||||
</caller-controls>
|
||||
|
||||
<!-- Profiles are collections of settings you can reference by name. -->
|
||||
<profiles>
|
||||
<!--If no profile is specified it will default to "default"-->
|
||||
<profile name="default">
|
||||
<!-- Directory to drop CDR's
|
||||
'auto' means $PREFIX/logs/conference_cdr/<confernece_uuid>.cdr.xml
|
||||
a non-absolute path means $PREFIX/logs/<value>/<confernece_uuid>.cdr.xml
|
||||
absolute path means <value>/<confernece_uuid>.cdr.xml
|
||||
-->
|
||||
<!-- <param name="cdr-log-dir" value="auto"/> -->
|
||||
|
||||
<!-- Domain (for presence) -->
|
||||
<param name="domain" value="$${domain}"/>
|
||||
<!-- Sample Rate-->
|
||||
<param name="rate" value="8000"/>
|
||||
<!-- Number of milliseconds per frame -->
|
||||
<param name="interval" value="20"/>
|
||||
<!-- Energy level required for audio to be sent to the other users -->
|
||||
<param name="energy-level" value="300"/>
|
||||
|
||||
<!--Can be | delim of waste|mute|deaf|dist-dtmf waste will always transmit data to each channel
|
||||
even during silence. dist-dtmf propagates dtmfs to all other members, but channel controls
|
||||
via dtmf will be disabled. -->
|
||||
<!--<param name="member-flags" value="waste"/>-->
|
||||
|
||||
<!-- Name of the caller control group to use for this profile -->
|
||||
<!-- <param name="caller-controls" value="some name"/> -->
|
||||
<!-- Name of the caller control group to use for the moderator in this profile -->
|
||||
<!-- <param name="moderator-controls" value="some name"/> -->
|
||||
<!-- TTS Engine to use -->
|
||||
<!--<param name="tts-engine" value="cepstral"/>-->
|
||||
<!-- TTS Voice to use -->
|
||||
<!--<param name="tts-voice" value="david"/>-->
|
||||
|
||||
<!-- If TTS is enabled all audio-file params beginning with -->
|
||||
<!-- 'say:' will be considered text to say with TTS -->
|
||||
<!-- Override the default path here, after which you use relative paths in the other sound params -->
|
||||
<!-- Note: The default path is the conference's first caller's sound_prefix -->
|
||||
<!--<param name="sound-prefix" value="$${sounds_dir}/en/us/callie"/>-->
|
||||
<!-- File to play to acknowledge succees -->
|
||||
<!--<param name="ack-sound" value="beep.wav"/>-->
|
||||
<!-- File to play to acknowledge failure -->
|
||||
<!--<param name="nack-sound" value="beeperr.wav"/>-->
|
||||
<!-- File to play to acknowledge muted -->
|
||||
<param name="muted-sound" value="conference/conf-muted.wav"/>
|
||||
<!-- File to play to acknowledge unmuted -->
|
||||
<param name="unmuted-sound" value="conference/conf-unmuted.wav"/>
|
||||
<!-- File to play if you are alone in the conference -->
|
||||
<param name="alone-sound" value="conference/conf-alone.wav"/>
|
||||
<!-- File to play endlessly (nobody will ever be able to talk) -->
|
||||
<!--<param name="perpetual-sound" value="perpetual.wav"/>-->
|
||||
<!-- File to play when you're alone (music on hold)-->
|
||||
<param name="moh-sound" value="$${hold_music}"/>
|
||||
<!-- File to play when you join the conference -->
|
||||
<param name="enter-sound" value="tone_stream://%(200,0,500,600,700)"/>
|
||||
<!-- File to play when you leave the conference -->
|
||||
<param name="exit-sound" value="tone_stream://%(500,0,300,200,100,50,25)"/>
|
||||
<!-- File to play when you ae ejected from the conference -->
|
||||
<param name="kicked-sound" value="conference/conf-kicked.wav"/>
|
||||
<!-- File to play when the conference is locked -->
|
||||
<param name="locked-sound" value="conference/conf-locked.wav"/>
|
||||
<!-- File to play when the conference is locked during the call-->
|
||||
<param name="is-locked-sound" value="conference/conf-is-locked.wav"/>
|
||||
<!-- File to play when the conference is unlocked during the call-->
|
||||
<param name="is-unlocked-sound" value="conference/conf-is-unlocked.wav"/>
|
||||
<!-- File to play to prompt for a pin -->
|
||||
<param name="pin-sound" value="conference/conf-pin.wav"/>
|
||||
<!-- File to play to when the pin is invalid -->
|
||||
<param name="bad-pin-sound" value="conference/conf-bad-pin.wav"/>
|
||||
<!-- Conference pin -->
|
||||
<!--<param name="pin" value="12345"/>-->
|
||||
<!--<param name="moderator-pin" value="54321"/>-->
|
||||
<!-- Max number of times the user can be prompted for PIN -->
|
||||
<!--<param name="pin-retries" value="3"/>-->
|
||||
<!-- Default Caller ID Name for outbound calls -->
|
||||
<param name="caller-id-name" value="$${outbound_caller_name}"/>
|
||||
<!-- Default Caller ID Number for outbound calls -->
|
||||
<param name="caller-id-number" value="$${outbound_caller_id}"/>
|
||||
<!-- Suppress start and stop talking events -->
|
||||
<!-- <param name="suppress-events" value="start-talking,stop-talking"/> -->
|
||||
<!-- enable comfort noise generation -->
|
||||
<param name="comfort-noise" value="true"/>
|
||||
<!-- Uncomment auto-record to toggle recording every conference call. -->
|
||||
<!-- Another valid value is shout://user:pass@server.com/live.mp3 -->
|
||||
<!--
|
||||
<param name="auto-record" value="$${recordings_dir}/${conference_name}_${strftime(%Y-%m-%d-%H-%M-%S)}.wav"/>
|
||||
-->
|
||||
|
||||
<!-- IVR digit machine timeouts -->
|
||||
<!-- How much to wait between DTMF digits to match caller-controls -->
|
||||
<!-- <param name="ivr-dtmf-timeout" value="500"/> -->
|
||||
<!-- How much to wait for the first DTMF, 0 forever -->
|
||||
<!-- <param name="ivr-input-timeout" value="0" /> -->
|
||||
<!-- Delay before a conference is asked to be terminated -->
|
||||
<!-- <param name="endconf-grace-time" value="120" /> -->
|
||||
</profile>
|
||||
|
||||
<profile name="wideband">
|
||||
<param name="domain" value="$${domain}"/>
|
||||
<param name="rate" value="16000"/>
|
||||
<param name="interval" value="20"/>
|
||||
<param name="energy-level" value="300"/>
|
||||
<!--<param name="sound-prefix" value="$${sounds_dir}/en/us/callie"/>-->
|
||||
<param name="muted-sound" value="conference/conf-muted.wav"/>
|
||||
<param name="unmuted-sound" value="conference/conf-unmuted.wav"/>
|
||||
<param name="alone-sound" value="conference/conf-alone.wav"/>
|
||||
<param name="moh-sound" value="$${hold_music}"/>
|
||||
<param name="enter-sound" value="tone_stream://%(200,0,500,600,700)"/>
|
||||
<param name="exit-sound" value="tone_stream://%(500,0,300,200,100,50,25)"/>
|
||||
<param name="kicked-sound" value="conference/conf-kicked.wav"/>
|
||||
<param name="locked-sound" value="conference/conf-locked.wav"/>
|
||||
<param name="is-locked-sound" value="conference/conf-is-locked.wav"/>
|
||||
<param name="is-unlocked-sound" value="conference/conf-is-unlocked.wav"/>
|
||||
<param name="pin-sound" value="conference/conf-pin.wav"/>
|
||||
<param name="bad-pin-sound" value="conference/conf-bad-pin.wav"/>
|
||||
<param name="caller-id-name" value="$${outbound_caller_name}"/>
|
||||
<param name="caller-id-number" value="$${outbound_caller_id}"/>
|
||||
<param name="comfort-noise" value="true"/>
|
||||
<!--<param name="tts-engine" value="flite"/>-->
|
||||
<!--<param name="tts-voice" value="kal16"/>-->
|
||||
</profile>
|
||||
|
||||
<profile name="ultrawideband">
|
||||
<param name="domain" value="$${domain}"/>
|
||||
<param name="rate" value="32000"/>
|
||||
<param name="interval" value="20"/>
|
||||
<param name="energy-level" value="300"/>
|
||||
<!--<param name="sound-prefix" value="$${sounds_dir}/en/us/callie"/>-->
|
||||
<param name="muted-sound" value="conference/conf-muted.wav"/>
|
||||
<param name="unmuted-sound" value="conference/conf-unmuted.wav"/>
|
||||
<param name="alone-sound" value="conference/conf-alone.wav"/>
|
||||
<param name="moh-sound" value="$${hold_music}"/>
|
||||
<param name="enter-sound" value="tone_stream://%(200,0,500,600,700)"/>
|
||||
<param name="exit-sound" value="tone_stream://%(500,0,300,200,100,50,25)"/>
|
||||
<param name="kicked-sound" value="conference/conf-kicked.wav"/>
|
||||
<param name="locked-sound" value="conference/conf-locked.wav"/>
|
||||
<param name="is-locked-sound" value="conference/conf-is-locked.wav"/>
|
||||
<param name="is-unlocked-sound" value="conference/conf-is-unlocked.wav"/>
|
||||
<param name="pin-sound" value="conference/conf-pin.wav"/>
|
||||
<param name="bad-pin-sound" value="conference/conf-bad-pin.wav"/>
|
||||
<param name="caller-id-name" value="$${outbound_caller_name}"/>
|
||||
<param name="caller-id-number" value="$${outbound_caller_id}"/>
|
||||
<param name="comfort-noise" value="true"/>
|
||||
<!--<param name="tts-engine" value="flite"/>-->
|
||||
<!--<param name="tts-voice" value="kal16"/>-->
|
||||
</profile>
|
||||
|
||||
<profile name="cdquality">
|
||||
<param name="domain" value="$${domain}"/>
|
||||
<param name="rate" value="48000"/>
|
||||
<param name="interval" value="10"/>
|
||||
<param name="energy-level" value="300"/>
|
||||
<!--<param name="sound-prefix" value="$${sounds_dir}/en/us/callie"/>-->
|
||||
<param name="muted-sound" value="conference/conf-muted.wav"/>
|
||||
<param name="unmuted-sound" value="conference/conf-unmuted.wav"/>
|
||||
<param name="alone-sound" value="conference/conf-alone.wav"/>
|
||||
<param name="moh-sound" value="$${hold_music}"/>
|
||||
<param name="enter-sound" value="tone_stream://%(200,0,500,600,700)"/>
|
||||
<param name="exit-sound" value="tone_stream://%(500,0,300,200,100,50,25)"/>
|
||||
<param name="kicked-sound" value="conference/conf-kicked.wav"/>
|
||||
<param name="locked-sound" value="conference/conf-locked.wav"/>
|
||||
<param name="is-locked-sound" value="conference/conf-is-locked.wav"/>
|
||||
<param name="is-unlocked-sound" value="conference/conf-is-unlocked.wav"/>
|
||||
<param name="pin-sound" value="conference/conf-pin.wav"/>
|
||||
<param name="bad-pin-sound" value="conference/conf-bad-pin.wav"/>
|
||||
<param name="caller-id-name" value="$${outbound_caller_name}"/>
|
||||
<param name="caller-id-number" value="$${outbound_caller_id}"/>
|
||||
<param name="comfort-noise" value="true"/>
|
||||
</profile>
|
||||
|
||||
<profile name="sla">
|
||||
<param name="domain" value="$${domain}"/>
|
||||
<param name="rate" value="16000"/>
|
||||
<param name="interval" value="20"/>
|
||||
<param name="caller-controls" value="none"/>
|
||||
<param name="energy-level" value="200"/>
|
||||
<param name="moh-sound" value="silence"/>
|
||||
<param name="comfort-noise" value="true"/>
|
||||
</profile>
|
||||
|
||||
</profiles>
|
||||
</configuration>
|
||||
@@ -0,0 +1,31 @@
|
||||
<!--
|
||||
start a dynamic conference with the settings of the "default" conference profile in conference.conf.xml
|
||||
-->
|
||||
<extension name="nb_conferences">
|
||||
<condition field="destination_number" expression="^(30\d{2})$">
|
||||
<action application="answer"/>
|
||||
<action application="conference" data="$1-${domain_name}@default"/>
|
||||
</condition>
|
||||
</extension>
|
||||
|
||||
<extension name="wb_conferences">
|
||||
<condition field="destination_number" expression="^(31\d{2})$">
|
||||
<action application="answer"/>
|
||||
<action application="conference" data="$1-${domain_name}@wideband"/>
|
||||
</condition>
|
||||
</extension>
|
||||
|
||||
<extension name="uwb_conferences">
|
||||
<condition field="destination_number" expression="^(32\d{2})$">
|
||||
<action application="answer"/>
|
||||
<action application="conference" data="$1-${domain_name}@ultrawideband"/>
|
||||
</condition>
|
||||
</extension>
|
||||
|
||||
<!-- MONO 48kHz conferences -->
|
||||
<extension name="cdquality_conferences">
|
||||
<condition field="destination_number" expression="^(33\d{2})$">
|
||||
<action application="answer"/>
|
||||
<action application="conference" data="$1-${domain_name}@cdquality"/>
|
||||
</condition>
|
||||
</extension>
|
||||
@@ -1104,6 +1104,7 @@ static switch_status_t conference_del_member(conference_obj_t *conference, confe
|
||||
|
||||
if (test_eflag(conference, EFLAG_FLOOR_CHANGE)) {
|
||||
switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, CONF_EVENT_MAINT);
|
||||
conference_add_event_data(conference, event);
|
||||
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Action", "floor-change");
|
||||
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Old-ID", "%d", member->id);
|
||||
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "New-ID", "none");
|
||||
@@ -1257,15 +1258,17 @@ static void *SWITCH_THREAD_FUNC conference_video_thread_run(switch_thread_t *thr
|
||||
}
|
||||
|
||||
session = conference->floor_holder->session;
|
||||
switch_core_session_read_lock(session);
|
||||
switch_mutex_unlock(conference->mutex);
|
||||
if (!switch_channel_ready(switch_core_session_get_channel(session))) {
|
||||
status = SWITCH_STATUS_FALSE;
|
||||
} else {
|
||||
status = switch_core_session_read_video_frame(session, &vid_frame, SWITCH_IO_FLAG_NONE, 0);
|
||||
|
||||
if ((status = switch_core_session_read_lock(session)) == SWITCH_STATUS_SUCCESS) {
|
||||
switch_mutex_unlock(conference->mutex);
|
||||
if (!switch_channel_ready(switch_core_session_get_channel(session))) {
|
||||
status = SWITCH_STATUS_FALSE;
|
||||
} else {
|
||||
status = switch_core_session_read_video_frame(session, &vid_frame, SWITCH_IO_FLAG_NONE, 0);
|
||||
}
|
||||
switch_mutex_lock(conference->mutex);
|
||||
switch_core_session_rwunlock(session);
|
||||
}
|
||||
switch_mutex_lock(conference->mutex);
|
||||
switch_core_session_rwunlock(session);
|
||||
|
||||
if (!SWITCH_READ_ACCEPTABLE(status)) {
|
||||
yield = 100000;
|
||||
@@ -6954,7 +6957,7 @@ static conference_obj_t *conference_new(char *name, conf_xml_cfg_t cfg, switch_c
|
||||
switch_uuid_t uuid;
|
||||
switch_codec_implementation_t read_impl = { 0 };
|
||||
switch_channel_t *channel = NULL;
|
||||
const char *force_rate = NULL, *force_interval = NULL;
|
||||
const char *force_rate = NULL, *force_interval = NULL, *presence_id = NULL;
|
||||
uint32_t force_rate_i = 0, force_interval_i = 0;
|
||||
|
||||
/* Validate the conference name */
|
||||
@@ -6969,6 +6972,8 @@ static conference_obj_t *conference_new(char *name, conf_xml_cfg_t cfg, switch_c
|
||||
switch_core_session_get_read_impl(session, &read_impl);
|
||||
channel = switch_core_session_get_channel(session);
|
||||
|
||||
presence_id = switch_channel_get_variable(channel, "presence_id");
|
||||
|
||||
if ((force_rate = switch_channel_get_variable(channel, "conference_force_rate"))) {
|
||||
if (!strcasecmp(force_rate, "auto")) {
|
||||
force_rate_i = read_impl.actual_samples_per_second;
|
||||
@@ -7362,7 +7367,11 @@ static conference_obj_t *conference_new(char *name, conf_xml_cfg_t cfg, switch_c
|
||||
|
||||
conference->name = switch_core_strdup(conference->pool, name);
|
||||
|
||||
if ((name_domain = strchr(conference->name, '@'))) {
|
||||
if (presence_id && (name_domain = strchr(presence_id, '@'))) {
|
||||
name_domain++;
|
||||
conference->domain = switch_core_strdup(conference->pool, name_domain);
|
||||
} else if ((name_domain = strchr(conference->name, '@'))) {
|
||||
name_domain++;
|
||||
conference->domain = switch_core_strdup(conference->pool, name_domain);
|
||||
} else if (domain) {
|
||||
conference->domain = switch_core_strdup(conference->pool, domain);
|
||||
|
||||
@@ -136,6 +136,12 @@
|
||||
<Project>{9778f1c0-09bc-4698-8ebc-bd982247209a}</Project>
|
||||
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\..\..\libs\win32\openssl\libeay32.2010.vcxproj">
|
||||
<Project>{d331904d-a00a-4694-a5a3-fcff64ab5dbe}</Project>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\..\..\libs\win32\openssl\ssleay32.2010.vcxproj">
|
||||
<Project>{b4b62169-5ad4-4559-8707-3d933ac5db39}</Project>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\..\..\w32\Library\FreeSwitchCore.2010.vcxproj">
|
||||
<Project>{202d7a4e-760d-4d0e-afa1-d7459ced30ff}</Project>
|
||||
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
<configuration name="db.conf" description="LIMIT DB Configuration">
|
||||
<settings>
|
||||
<!--<param name="odbc-dsn" value="dsn:user:pass"/>-->
|
||||
</settings>
|
||||
</configuration>
|
||||
@@ -0,0 +1,10 @@
|
||||
<configuration name="distributor.conf" description="Distributor Configuration">
|
||||
<lists>
|
||||
<!-- every 10 calls to test you will get foo1 once and foo2 9 times...yes NINE TIMES! -->
|
||||
<!-- this is not the same as 100 with 10 and 90 that would do foo1 10 times in a row then foo2 90 times in a row -->
|
||||
<list name="test" total-weight="10">
|
||||
<node name="foo1" weight="1"/>
|
||||
<node name="foo2" weight="9"/>
|
||||
</list>
|
||||
</lists>
|
||||
</configuration>
|
||||
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<include>
|
||||
<extension name="test gateway distro">
|
||||
<condition field="destination_number" expression="^(.*)$">
|
||||
<action application="bridge" data="sofia/gateway/${distributor(test)}/$1"/>
|
||||
</condition>
|
||||
</extension>
|
||||
</include>
|
||||
@@ -2902,6 +2902,12 @@ SWITCH_STANDARD_APP(audio_bridge_function)
|
||||
v_campon_fallback_exten,
|
||||
switch_channel_get_variable(caller_channel, "campon_fallback_dialplan"),
|
||||
switch_channel_get_variable(caller_channel, "campon_fallback_context"));
|
||||
|
||||
if (peer_session) {
|
||||
switch_channel_hangup(switch_core_session_get_channel(peer_session), SWITCH_CAUSE_ORIGINATOR_CANCEL);
|
||||
switch_core_session_rwunlock(peer_session);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -3038,6 +3044,11 @@ SWITCH_STANDARD_APP(audio_bridge_function)
|
||||
} else {
|
||||
|
||||
if (switch_channel_test_flag(caller_channel, CF_PROXY_MODE)) {
|
||||
switch_channel_t *peer_channel = switch_core_session_get_channel(peer_session);
|
||||
if (switch_true(switch_channel_get_variable(caller_channel, SWITCH_BYPASS_MEDIA_AFTER_BRIDGE_VARIABLE)) ||
|
||||
switch_true(switch_channel_get_variable(peer_channel, SWITCH_BYPASS_MEDIA_AFTER_BRIDGE_VARIABLE))) {
|
||||
switch_channel_set_flag(caller_channel, CF_BYPASS_MEDIA_AFTER_BRIDGE);
|
||||
}
|
||||
switch_ivr_signal_bridge(session, peer_session);
|
||||
} else {
|
||||
switch_channel_t *channel = switch_core_session_get_channel(session);
|
||||
@@ -3240,7 +3251,7 @@ static switch_call_cause_t user_outgoing_channel(switch_core_session_t *session,
|
||||
switch_call_cause_t *cancel_cause)
|
||||
{
|
||||
switch_xml_t x_user = NULL, x_param, x_params;
|
||||
char *user = NULL, *domain = NULL, *dup_domain = NULL;
|
||||
char *user = NULL, *domain = NULL, *dup_domain = NULL, *dialed_user = NULL;
|
||||
const char *dest = NULL;
|
||||
switch_call_cause_t cause = SWITCH_CAUSE_NONE;
|
||||
unsigned int timelimit = 60;
|
||||
@@ -3310,9 +3321,14 @@ static switch_call_cause_t user_outgoing_channel(switch_core_session_t *session,
|
||||
}
|
||||
}
|
||||
|
||||
dialed_user = (char *)switch_xml_attr(x_user, "id");
|
||||
|
||||
if (var_event) {
|
||||
switch_event_add_header_string(var_event, SWITCH_STACK_BOTTOM, "dialed_user", user);
|
||||
switch_event_add_header_string(var_event, SWITCH_STACK_BOTTOM, "dialed_user", dialed_user);
|
||||
switch_event_add_header_string(var_event, SWITCH_STACK_BOTTOM, "dialed_domain", domain);
|
||||
if (!zstr(dest) && !strstr(dest, "presence_id=")) {
|
||||
switch_event_add_header(var_event, SWITCH_STACK_BOTTOM, "presence_id", "%s@%s", dialed_user, domain);
|
||||
}
|
||||
}
|
||||
|
||||
if (!dest) {
|
||||
@@ -3338,7 +3354,7 @@ static switch_call_cause_t user_outgoing_channel(switch_core_session_t *session,
|
||||
timelimit = atoi(varval);
|
||||
}
|
||||
|
||||
switch_channel_set_variable(channel, "dialed_user", user);
|
||||
switch_channel_set_variable(channel, "dialed_user", dialed_user);
|
||||
switch_channel_set_variable(channel, "dialed_domain", domain);
|
||||
|
||||
d_dest = switch_channel_expand_variables(channel, dest);
|
||||
@@ -3359,7 +3375,7 @@ static switch_call_cause_t user_outgoing_channel(switch_core_session_t *session,
|
||||
switch_assert(event);
|
||||
}
|
||||
|
||||
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "dialed_user", user);
|
||||
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "dialed_user", dialed_user);
|
||||
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "dialed_domain", domain);
|
||||
d_dest = switch_event_expand_headers(event, dest);
|
||||
switch_event_destroy(&event);
|
||||
@@ -3374,7 +3390,7 @@ static switch_call_cause_t user_outgoing_channel(switch_core_session_t *session,
|
||||
}
|
||||
|
||||
|
||||
switch_snprintf(stupid, sizeof(stupid), "user/%s", user);
|
||||
switch_snprintf(stupid, sizeof(stupid), "user/%s", dialed_user);
|
||||
if (switch_stristr(stupid, d_dest)) {
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Waddya Daft? You almost called '%s' in an infinate loop!\n",
|
||||
stupid);
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
<configuration name="easyroute.conf" description="EasyRoute Module">
|
||||
<settings>
|
||||
<!-- These are kind Obvious -->
|
||||
<param name="db-username" value="root"/>
|
||||
<param name="db-password" value="password"/>
|
||||
<param name="db-dsn" value="easyroute"/>
|
||||
|
||||
<!-- Default Technology and profile -->
|
||||
<param name="default-techprofile" value="sofia/default"/>
|
||||
|
||||
<!-- IP or Hostname of Default Route -->
|
||||
<param name="default-gateway" value="192.168.66.6"/>
|
||||
|
||||
<!-- Number of times to retry ODBC connection on connection problems, default is 120 -->
|
||||
<param name="odbc-retries" value="120"/>
|
||||
|
||||
<!-- Customer Query. Use this with Care!!! We are not responsible if you mess
|
||||
This up!!! Query *MUST* return columns in the following order!
|
||||
gateway varchar(128) - contains destination gateway host:port pair (ex: 192.168.1.1:5060 )
|
||||
group varchar(128) - contains optional group name
|
||||
call_limit varchar(16) - contains optional call limit
|
||||
tech_prefix varchar(128) - tech prefix used to build dial string (ex: sofia/default )
|
||||
acctcode varchar(128) - used to set channel variable acctcode for logging into the CDRs
|
||||
destination_number varchar(16) - Number returning for the query for building the dial string. (ex: 18005551212)
|
||||
See Documentation on the Wiki for further information -->
|
||||
<!-- <param name="custom-query" value="call FS_GET_SIP_LOCATION(%s);"/> -->
|
||||
</settings>
|
||||
</configuration>
|
||||
@@ -0,0 +1,27 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<include>
|
||||
<!-- This example will test the limit value for the DID number being checked -->
|
||||
<!-- If over limit, send 503 -->
|
||||
<extension name="easyroute">
|
||||
<condition field="destination_number" expression="^1?(\d{10})$" break="on-true">
|
||||
<action application="easyroute" data="$1"/>
|
||||
<action application="limit" data="db easyroute ${easy_group} ${easy_limit} LE-$1"/>
|
||||
<action application="bridge" data="${easy_dialstring}"/>
|
||||
</condition>
|
||||
</extension>
|
||||
|
||||
<extension name="easyroute_limit_exceeded">
|
||||
<condition field="destination_number" expression="^LE-(\d{10})$" break="on-true">
|
||||
<action application="respond" data="503 Buzz Off You Ran Out of Channels"/>
|
||||
</condition>
|
||||
</extension>
|
||||
|
||||
<!-- Simple example - just grab the dialstring and send the call -->
|
||||
<extension name="easyroute">
|
||||
<condition field="destination_number" expression="^1?(\d{10})$" break="on-true">
|
||||
<action application="set" data="dialstring={easyroute($1 dialstring)"/>
|
||||
<action application="bridge" data="${easy_dialstring}"/>
|
||||
</condition>
|
||||
</extension>
|
||||
|
||||
<include>
|
||||
@@ -43,7 +43,7 @@ typedef struct easyroute_results {
|
||||
char dialstring[256];
|
||||
char group[16];
|
||||
char acctcode[17];
|
||||
char translated[17];
|
||||
char translated[61];
|
||||
} easyroute_results_t;
|
||||
|
||||
|
||||
@@ -53,7 +53,7 @@ typedef struct route_callback {
|
||||
char techprofile[129];
|
||||
char limit[129];
|
||||
char acctcode[129];
|
||||
char translated[17];
|
||||
char translated[61];
|
||||
} route_callback_t;
|
||||
|
||||
static struct {
|
||||
@@ -88,7 +88,7 @@ static int route_callback(void *pArg, int argc, char **argv, char **columnNames)
|
||||
switch_copy_string(cbt->limit, argv[2], 128);
|
||||
switch_copy_string(cbt->techprofile, argv[3], 128);
|
||||
switch_copy_string(cbt->acctcode, argv[4], 128);
|
||||
switch_copy_string(cbt->translated, argv[5], 16);
|
||||
switch_copy_string(cbt->translated, argv[5], 60);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
<configuration name="enum.conf" description="ENUM Module">
|
||||
<settings>
|
||||
<param name="default-root" value="e164.org"/>
|
||||
<param name="default-isn-root" value="freenum.org"/>
|
||||
<param name="query-timeout" value="10"/>
|
||||
<param name="auto-reload" value="true"/>
|
||||
</settings>
|
||||
|
||||
<routes>
|
||||
<route service="E2U+SIP" regex="sip:(.*)" replace="sofia/${use_profile}/$1"/>
|
||||
<!--<route service="E2U+XMPP" regex="XMPP:(.*)" replace="dingaling/$${xmpp_server_profile}/$1"/>-->
|
||||
</routes>
|
||||
</configuration>
|
||||
@@ -0,0 +1,8 @@
|
||||
<include>
|
||||
<extension name="enum">
|
||||
<condition field="${module_exists(mod_enum)}" expression="true"/>
|
||||
<condition field="destination_number" expression="^(.*)$">
|
||||
<action application="transfer" data="$1 enum"/>
|
||||
</condition>
|
||||
</extension>
|
||||
</include>
|
||||
@@ -0,0 +1,10 @@
|
||||
<configuration name="fifo.conf" description="FIFO Configuration">
|
||||
<settings>
|
||||
<param name="delete-all-outbound-member-on-startup" value="false"/>
|
||||
</settings>
|
||||
<fifos>
|
||||
<fifo name="cool_fifo@$${domain}" importance="0">
|
||||
<!--<member timeout="60" simo="1" lag="20">{member_wait=nowait}user/1005@$${domain}</member>-->
|
||||
</fifo>
|
||||
</fifos>
|
||||
</configuration>
|
||||
@@ -0,0 +1,19 @@
|
||||
<!--
|
||||
Parking extensions... transferring calls to 5900 will park them in a queue.
|
||||
-->
|
||||
<extension name="park">
|
||||
<condition field="destination_number" expression="^5900$">
|
||||
<action application="set" data="fifo_music=$${hold_music}"/>
|
||||
<action application="fifo" data="5900@${domain_name} in"/>
|
||||
</condition>
|
||||
</extension>
|
||||
|
||||
<!--
|
||||
Parking pickup extension. Calling 5901 will pickup the call.
|
||||
-->
|
||||
<extension name="unpark">
|
||||
<condition field="destination_number" expression="^5901$">
|
||||
<action application="answer"/>
|
||||
<action application="fifo" data="5900@${domain_name} out nowait"/>
|
||||
</condition>
|
||||
</extension>
|
||||
@@ -0,0 +1,6 @@
|
||||
<configuration name="hash.conf" description="Hash Configuration">
|
||||
<remotes>
|
||||
<!-- List of hosts from where to pull usage data -->
|
||||
<!-- <remote name="Test1" host="10.0.0.10" port="8021" password="ClueCon" interval="1000" /> -->
|
||||
</remotes>
|
||||
</configuration>
|
||||
@@ -0,0 +1,7 @@
|
||||
<extension name="hash_demo">
|
||||
<condition field="destination_number" expression="^hash_demo$">
|
||||
<action application="hash" data="insert/realm/key/value"/>
|
||||
<action application="hash" data="delete/realm/key"/>
|
||||
<action application="set" data="var=${hash(select/realm/key)}"/>
|
||||
</condition>
|
||||
</extension>
|
||||
+15
@@ -80,6 +80,21 @@ asr-engine : ASR engine to use
|
||||
asr-grammar : ASR grammar to use
|
||||
|
||||
|
||||
<vmname file name action digit-timeout input-timeout loops><bind action strip>*EXPR*</bind></playback>
|
||||
: Plays a vm name and optionally collects input.
|
||||
|
||||
ATTRS:
|
||||
file : The file
|
||||
name : Param name to save result.
|
||||
error-file : Error file to play on invalid input.
|
||||
action : Change the new target url.
|
||||
temp-action : Change url to submit to. just for the next loop.
|
||||
digit-timeout : Timeout waiting for digits after file plays (when input bindings are present)
|
||||
input-timeout : Timeout waiting for more digits in a multi-digit input.
|
||||
loops : max times to play the file when input bindings are present.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<record file name error-file action digit-timeout input-timeout><bind action strip>*EXPR*</bind></record>
|
||||
@@ -395,6 +395,7 @@ static switch_status_t parse_playback(const char *tag_name, client_t *client, sw
|
||||
const char *say_gender = NULL;
|
||||
const char *sp_engine = NULL;
|
||||
const char *sp_grammar = NULL;
|
||||
char *free_string = NULL;
|
||||
|
||||
if (!strcasecmp(tag_name, "say")) {
|
||||
say_lang = switch_xml_attr(tag, "language");
|
||||
@@ -431,6 +432,48 @@ static switch_status_t parse_playback(const char *tag_name, client_t *client, sw
|
||||
} else {
|
||||
play = 1;
|
||||
}
|
||||
} else if (!strcasecmp(tag_name, "vmname")) {
|
||||
const char *id = switch_xml_attr(tag, "id");
|
||||
char *cmd, *resp;
|
||||
switch_stream_handle_t stream = { 0 };
|
||||
char *p;
|
||||
|
||||
SWITCH_STANDARD_STREAM(stream);
|
||||
|
||||
cmd = switch_mprintf("%s|name_path", id);
|
||||
|
||||
switch_api_execute("vm_prefs", cmd, NULL, &stream);
|
||||
|
||||
resp = (char *) stream.data;
|
||||
|
||||
if (!zstr(resp)) {
|
||||
if (switch_stristr("://", resp) || switch_file_exists(resp, NULL) == SWITCH_STATUS_SUCCESS) {
|
||||
play = 1;
|
||||
file = free_string = resp;
|
||||
resp = NULL;
|
||||
} else {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid file! [%s]\n", resp);
|
||||
switch_safe_free(resp);
|
||||
return SWITCH_STATUS_FALSE;
|
||||
}
|
||||
} else {
|
||||
switch_safe_free(resp);
|
||||
say_lang = switch_xml_attr(tag, "language");
|
||||
say_gender = switch_xml_attr(tag, "gender");
|
||||
say_type = "name_spelled";
|
||||
say_method = "pronounced";
|
||||
free_string = strdup(id);
|
||||
if ((p = strchr(free_string, '@'))) {
|
||||
*p = '\0';
|
||||
}
|
||||
say = 1;
|
||||
|
||||
body = free_string;
|
||||
switch_ivr_play_file(client->session, NULL, "voicemail/vm-person.wav", &nullargs);
|
||||
|
||||
}
|
||||
|
||||
switch_safe_free(resp);
|
||||
}
|
||||
|
||||
|
||||
@@ -545,7 +588,7 @@ static switch_status_t parse_playback(const char *tag_name, client_t *client, sw
|
||||
|
||||
if (input_timeout && status == SWITCH_STATUS_SUCCESS) {
|
||||
if ((status = switch_ivr_sleep(client->session, input_timeout, SWITCH_TRUE, args)) == SWITCH_STATUS_SUCCESS) {
|
||||
status = SWITCH_STATUS_BREAK;
|
||||
status = (input || !pause) ? SWITCH_STATUS_BREAK : SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -618,11 +661,13 @@ static switch_status_t parse_playback(const char *tag_name, client_t *client, sw
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (dmachine) {
|
||||
switch_ivr_dmachine_destroy(&dmachine);
|
||||
}
|
||||
|
||||
switch_safe_free(free_string);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
@@ -2790,6 +2835,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_httapi_load)
|
||||
bind_parser("record", parse_record);
|
||||
bind_parser("recordCall", parse_record_call);
|
||||
bind_parser("playback", parse_playback);
|
||||
bind_parser("vmName", parse_playback);
|
||||
bind_parser("speak", parse_playback);
|
||||
bind_parser("say", parse_playback);
|
||||
bind_parser("conference", parse_conference);
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
<configuration name="http_cache.conf" description="HTTP GET cache">
|
||||
<settings>
|
||||
<param name="max-urls" value="10000"/>
|
||||
<param name="location" value="$${base_dir}/http_cache"/>
|
||||
<param name="default-max-age" value="86400"/>
|
||||
</settings>
|
||||
</configuration>
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
<include>
|
||||
<extension "http_cache_demo">
|
||||
<condition field="destination_number" expression="^(.*)$">
|
||||
<action application="playback" data="${http_get(http://myserver.yo/media/hello_world.wav)}"/>
|
||||
</condition>
|
||||
</extension>
|
||||
</include>
|
||||
@@ -0,0 +1,77 @@
|
||||
<include>
|
||||
|
||||
<X-PRE-PROCESS cmd="set" data="AT_EPENT1=0 0 0 -1 -1 0 -1 0 -1 -1 0 -1"/>
|
||||
<X-PRE-PROCESS cmd="set" data="AT_EPENT2=1 1 1 -1 -1 1 -1 1 -1 -1 1 -1"/>
|
||||
<X-PRE-PROCESS cmd="set" data="AT_CPENT1=0 -1 -1 0 -1 0 0 0 -1 -1 0 -1"/>
|
||||
<X-PRE-PROCESS cmd="set" data="AT_CPENT2=1 -1 -1 1 -1 1 1 1 -1 -1 1 -1"/>
|
||||
<X-PRE-PROCESS cmd="set" data="AT_CMAJ1=0 -1 0 0 -1 0 -1 0 0 -1 0 -1"/>
|
||||
<X-PRE-PROCESS cmd="set" data="AT_CMAJ2=1 -1 1 1 -1 1 -1 1 1 -1 1 -1"/>
|
||||
<X-PRE-PROCESS cmd="set" data="AT_BBLUES=1 -1 1 -1 -1 1 -1 1 1 1 -1 -1"/>
|
||||
<X-PRE-PROCESS cmd="set" data="ATGPENT2=-1 1 -1 1 -1 1 -1 -1 1 -1 1 -1"/>
|
||||
|
||||
<extension name="101">
|
||||
<condition field="destination_number" expression="^101$">
|
||||
<!-- AUTOTALENT DEFAULTS -->
|
||||
|
||||
<!--
|
||||
<action application="set" data="AT_TUNE=440"/>
|
||||
<action application="set" data="AT_FIXED=0"/>
|
||||
<action application="set" data="AT_PULL=0"/>
|
||||
<action application="set" data="AT_A=0"/>
|
||||
<action application="set" data="AT_Bb=-1"/>
|
||||
<action application="set" data="AT_B=0"/>
|
||||
<action application="set" data="AT_C=0"/>
|
||||
<action application="set" data="AT_Db=-1"/>
|
||||
<action application="set" data="AT_D=0"/>
|
||||
<action application="set" data="AT_Eb=-1"/>
|
||||
<action application="set" data="AT_E=0"/>
|
||||
<action application="set" data="AT_F=0"/>
|
||||
<action application="set" data="AT_Gb=-1"/>
|
||||
<action application="set" data="AT_G=0"/>
|
||||
<action application="set" data="AT_Ab=-1"/>
|
||||
<action application="set" data="AT_AMOUNT=1"/>
|
||||
<action application="set" data="AT_SMOOTH=0"/>
|
||||
<action application="set" data="AT_SHIFT=0"/>
|
||||
<action application="set" data="AT_OUTSCALE=0"/>
|
||||
<action application="set" data="AT_LFODEPTH=0"/>
|
||||
<action application="set" data="AT_LFORATE=5"/>
|
||||
<action application="set" data="AT_LFOSHAPE=0"/>
|
||||
<action application="set" data="AT_LFOSYMM=0"/>
|
||||
<action application="set" data="AT_LFOQUANT=0"/>
|
||||
<action application="set" data="AT_FCORR=0"/>
|
||||
<action application="set" data="AT_FWARP=0"/>
|
||||
<action application="set" data="AT_MIX=1"/>
|
||||
-->
|
||||
|
||||
|
||||
<action application="set" data="AT_TUNE=440"/>
|
||||
<action application="set" data="AT_FIXED=0"/>
|
||||
<action application="set" data="AT_PULL=0"/>
|
||||
|
||||
<action application="set" data="AT_AMOUNT=1"/>
|
||||
<action application="set" data="AT_SMOOTH=0"/>
|
||||
<action application="set" data="AT_SHIFT=1"/>
|
||||
<action application="set" data="AT_OUTSCALE=0"/>
|
||||
<action application="set" data="AT_LFODEPTH=0"/>
|
||||
<action application="set" data="AT_LFORATE=5"/>
|
||||
<action application="set" data="AT_LFOSHAPE=0"/>
|
||||
<action application="set" data="AT_LFOSYMM=0"/>
|
||||
<action application="set" data="AT_LFOQUANT=0"/>
|
||||
<action application="set" data="AT_FCORR=0"/>
|
||||
<action application="set" data="AT_FWARP=0"/>
|
||||
<action application="set" data="AT_MIX=1"/>
|
||||
|
||||
<!-- you have to download the ladspa package and the desired plugins from their desired site -->
|
||||
|
||||
|
||||
<action application="set"><![CDATA[ladspa_params=${AT_TUNE} ${AT_FIXED} ${AT_PULL} ${AT_EPENT2} ${AT_AMOUNT} ${AT_SMOOTH} ${AT_SHIFT} ${AT_OUTSCALE} ${AT_LFODEPTH} ${AT_LFORATE} ${AT_LFOSHAPE} ${AT_LFOSYMM} ${AT_LFOQUANT} ${AT_FCORR} ${AT_FWARP} ${AT_MIX}]]></action>
|
||||
|
||||
<action application="ladspa_run" data="r|autotalent||${ladspa_params}"/>
|
||||
<action application="ladspa_run" data="r|tap_chorusflanger||"/>
|
||||
<action application="ladspa_run" data="r|phasers_1217.so|autoPhaser|"/>
|
||||
<action application="bridge" data="sofia/internal/888@conference.freeswitch.org"/>
|
||||
|
||||
</condition>
|
||||
</extension>
|
||||
|
||||
</include>
|
||||
@@ -0,0 +1,4 @@
|
||||
mod_ladspa is a module that allow to use Linux Audio Developer's Simple Plugin API inside freeswitch in realtime.
|
||||
see http://wiki.freeswitch.org/wiki/Mod_ladspa for installation and configuration documentation.
|
||||
|
||||
Please Note Currently this module only works on Linux.
|
||||
@@ -0,0 +1,89 @@
|
||||
<configuration name="lcr.conf" description="LCR Configuration">
|
||||
<settings>
|
||||
<param name="odbc-dsn" value="freeswitch-mysql:freeswitch:Fr33Sw1tch"/>
|
||||
<!-- <param name="odbc-dsn" value="freeswitch-pgsql:freeswitch:Fr33Sw1tch"/> -->
|
||||
</settings>
|
||||
<profiles>
|
||||
<profile name="default">
|
||||
<param name="id" value="0"/>
|
||||
<param name="order_by" value="rate,quality,reliability"/>
|
||||
</profile>
|
||||
<profile name="qual_rel">
|
||||
<param name="id" value="1"/>
|
||||
<param name="order_by" value="quality,reliability"/>
|
||||
</profile>
|
||||
<profile name="rel_qual">
|
||||
<param name="id" value="2"/>
|
||||
<param name="order_by" value="reliability,quality"/>
|
||||
</profile>
|
||||
<!--
|
||||
Some samples of how to do custom SQL:
|
||||
|
||||
=============================================================
|
||||
PostgreSQL with contrib prefix module which supports fast
|
||||
prefix queries. Ideal option.
|
||||
=============================================================
|
||||
<profile name="pg_prefix">
|
||||
<param name="custom_sql" value="
|
||||
SELECT l.digits AS lcr_digits,
|
||||
c.carrier_name AS lcr_carrier_name,
|
||||
l.${lcr_rate_field} as lcr_rate_field,
|
||||
cg.prefix AS lcr_gw_prefix, cg.suffix AS lcr_gw_suffix,
|
||||
l.lead_strip AS lcr_lead_strip, l.trail_strip AS lcr_trail_strip,
|
||||
l.prefix AS lcr_prefix, l.suffix AS lcr_suffix
|
||||
FROM lcr l
|
||||
JOIN carriers c ON l.carrier_id=c.id
|
||||
JOIN carrier_gateway cg ON c.id=cg.carrier_id
|
||||
WHERE c.enabled = '1' AND cg.enabled = '1' AND l.enabled = '1'
|
||||
AND digits_prefix @> %q
|
||||
AND CURRENT_TIMESTAMP BETWEEN date_start AND date_end
|
||||
ORDER BY digits DESC, ${lcr_rate_field}, random();
|
||||
"/>
|
||||
</profile>
|
||||
|
||||
=============================================================
|
||||
PostgreSQL with contrib prefix module which supports fast
|
||||
prefix queries. Ideal option. Alternate syntax which requies
|
||||
a session but allows variable substitution.
|
||||
=============================================================
|
||||
<profile name="pg_prefix2">
|
||||
<param name="custom_sql" value="
|
||||
SELECT l.digits AS lcr_digits,
|
||||
c.carrier_name AS lcr_carrier_name,
|
||||
l.${lcr_rate_field} as lcr_rate_field,
|
||||
cg.prefix AS lcr_gw_prefix, cg.suffix AS lcr_gw_suffix,
|
||||
l.lead_strip AS lcr_lead_strip, l.trail_strip AS lcr_trail_strip,
|
||||
l.prefix AS lcr_prefix, l.suffix AS lcr_suffix
|
||||
FROM lcr l
|
||||
JOIN carriers c ON l.carrier_id=c.id
|
||||
JOIN carrier_gateway cg ON c.id=cg.carrier_id
|
||||
WHERE c.enabled = '1' AND cg.enabled = '1' AND l.enabled = '1'
|
||||
AND digits_prefix @> '${lcr_query_digits}'
|
||||
AND CURRENT_TIMESTAMP BETWEEN date_start AND date_end
|
||||
ORDER BY digits DESC, ${lcr_rate_field}, random();
|
||||
"/>
|
||||
</profile>
|
||||
|
||||
=============================================================
|
||||
Demonstrates use of computed inlist.
|
||||
=============================================================
|
||||
<profile name="inlist">
|
||||
<param name="custom_sql" value="
|
||||
SELECT l.digits AS lcr_digits,
|
||||
c.carrier_name AS lcr_carrier_name,
|
||||
l.${lcr_rate_field} as lcr_rate_field,
|
||||
cg.prefix AS lcr_gw_prefix, cg.suffix AS lcr_gw_suffix,
|
||||
l.lead_strip AS lcr_lead_strip, l.trail_strip AS lcr_trail_strip,
|
||||
l.prefix AS lcr_prefix, l.suffix AS lcr_suffix
|
||||
FROM lcr l
|
||||
JOIN carriers c ON l.carrier_id=c.id
|
||||
JOIN carrier_gateway cg ON c.id=cg.carrier_id
|
||||
WHERE c.enabled = '1' AND cg.enabled = '1' AND l.enabled = '1'
|
||||
AND digits IN (${lcr_query_expanded_digits})
|
||||
AND CURRENT_TIMESTAMP BETWEEN date_start AND date_end
|
||||
ORDER BY digits DESC, ${lcr_rate_field}, random();
|
||||
"/>
|
||||
</profile>
|
||||
-->
|
||||
</profiles>
|
||||
</configuration>
|
||||
@@ -0,0 +1,8 @@
|
||||
<include>
|
||||
<extension name="Outbound to PSTN 11 Digits">
|
||||
<condition field="destination_number" expression="^(1[2-9][0-9]{2}[2-9]{7})$">
|
||||
<action application="lcr" data="$1"/>
|
||||
<action application="bridge" data="${lcr_auto_route}"/>
|
||||
</condition>
|
||||
</extension>
|
||||
</include>
|
||||
@@ -0,0 +1,5 @@
|
||||
<configuration name="limit.conf" description="LIMIT Configuration">
|
||||
<settings>
|
||||
<!--<param name="odbc-dsn" value="dsn:user:pass"/>-->
|
||||
</settings>
|
||||
</configuration>
|
||||
@@ -0,0 +1,14 @@
|
||||
<include>
|
||||
<extension name="limit_exceeded">
|
||||
<condition field="destination_number" expression="^limit_exceeded$">
|
||||
<action application="playback" data="/sounds/overthelimit.wav"/>
|
||||
<action application="hangup"/>
|
||||
</condition>
|
||||
</extension>
|
||||
|
||||
<extension name="limit" continue="true">
|
||||
<condition>
|
||||
<action application="limit" data="db $${domain} ${sip_auth_username} ${max_calls}"/>
|
||||
</condition>
|
||||
</extension>
|
||||
</include>
|
||||
@@ -0,0 +1,6 @@
|
||||
<configuration name="memcache.conf" description="memcache Configuration">
|
||||
<settings>
|
||||
<!-- comma sep list of servers: eg: localhost,otherhost:port,anotherone -->
|
||||
<param name="memcache-servers" value="localhost"/>
|
||||
</settings>
|
||||
</configuration>
|
||||
@@ -0,0 +1,9 @@
|
||||
<include>
|
||||
<extension name="memcache_examples">
|
||||
<condition field="destination_number" expression="^memcache$">
|
||||
<action application="set" data="foo=${memcache(get key)}"/>
|
||||
<action application="set" data="ignore=${memcache(set key value)}"/>
|
||||
<action application="set" data="ignore=${memcache(set key ${channel_var})}"/>
|
||||
</condition>
|
||||
</extension>
|
||||
</include>
|
||||
@@ -0,0 +1,20 @@
|
||||
<configuration name="mongo.conf">
|
||||
<settings>
|
||||
<!--
|
||||
connection-string handles different ways to connect to mongo
|
||||
samples:
|
||||
server:port
|
||||
foo/server:port,server:port SET
|
||||
-->
|
||||
<param name="connection-string" value="127.0.0.1:27017"/>
|
||||
<param name="min-connections" value="10"/>
|
||||
<param name="max-connections" value="100"/>
|
||||
|
||||
<!--
|
||||
<param name="map" value="function() { emit(this.a, 1); }"/>
|
||||
<param name="reduce" value="function(key, values) { return Array.sum(values); }"/>
|
||||
<param name="finalize" value="function(key, value) { return value;}"/>
|
||||
-->
|
||||
|
||||
</settings>
|
||||
</configuration>
|
||||
@@ -0,0 +1,50 @@
|
||||
<configuration name="nibblebill.conf" description="Nibble Billing">
|
||||
<settings>
|
||||
<!-- See http://wiki.freeswitch.org/wiki/Mod_nibblebill for help with these options -->
|
||||
|
||||
<!-- Information for connecting to your database -->
|
||||
<param name="db_username" value="bandwidth.com"/>
|
||||
<param name="db_password" value="password"/>
|
||||
<param name="db_dsn" value="bandwidth.com"/>
|
||||
|
||||
<!-- The database table where your CASH column is located -->
|
||||
<param name="db_table" value="accounts"/>
|
||||
|
||||
<!-- The column name where we store the value of the account -->
|
||||
<param name="db_column_cash" value="cash"/>
|
||||
|
||||
<!-- The column name for the unique ID identifying the account -->
|
||||
<param name="db_column_account" value="id"/>
|
||||
|
||||
<!-- Custom SQL for loading current balance - overrides column names
|
||||
channel vars are interpreted.
|
||||
field nibble_balance is used for balance info
|
||||
|
||||
<param name="custom_sql_lookup" value="SELECT cash AS nibble_balance FROM accounts WHERE account_code='${nibble_account}'"/>
|
||||
-->
|
||||
|
||||
<!-- Custom SQL for loading current balance - overrides column names
|
||||
channel vars are interpreted.
|
||||
nibble_increment is the amount to update
|
||||
|
||||
<param name="custom_sql_save" value="UPDATE accounts SET cash=cash-${nibble_increment} WHERE account_code='${nibble_account}'"/>
|
||||
-->
|
||||
|
||||
|
||||
<!-- Default heartbeat interval. Set to 'off' for no heartbeat (i.e. bill only at end of call) -->
|
||||
<param name="global_heartbeat" value="60"/>
|
||||
|
||||
<!-- By default, warn a caller when their balance is at $5.00. You can set this to a negative number. -->
|
||||
<param name="lowbal_amt" value="5"/>
|
||||
<param name="lowbal_action" value="play ding"/>
|
||||
|
||||
<!-- By default, terminate a caller when their balance hits $0.00. You can set this to a negative number. -->
|
||||
<param name="nobal_amt" value="0"/>
|
||||
<param name="nobal_action" value="hangup"/>
|
||||
|
||||
<!-- If a call goes beyond a certain dollar amount, flag or terminate it -->
|
||||
<param name="percall_max_amt" value="100"/>
|
||||
<param name="percall_action" value="hangup"/>
|
||||
|
||||
</settings>
|
||||
</configuration>
|
||||
@@ -0,0 +1,27 @@
|
||||
<include>
|
||||
|
||||
<extension name="tollfree800">
|
||||
<condition field="destination_number" expression="^1{0,1}(800\d{7})$">
|
||||
<action application="set" data="nibble_account=${accountcode}"/>
|
||||
<action application="set" data="nibble_rate=0"/>
|
||||
<action application="bridge" data="sofia/gateway/bandwidth.com/$1"/>
|
||||
</condition>
|
||||
</extension>
|
||||
|
||||
<extension name="special919rate">
|
||||
<condition field="destination_number" expression="^1{0,1}(919\d{7})$">
|
||||
<action application="set" data="nibble_account=${accountcode}"/>
|
||||
<action application="set" data="nibble_rate=0.07"/>
|
||||
<action application="bridge" data="sofia/gateway/bandwidth.com/$1"/>
|
||||
</condition>
|
||||
</extension>
|
||||
|
||||
<extension name="domestic">
|
||||
<condition field="destination_number" expression="^(1{0,1}\d{10})$">
|
||||
<action application="set" data="nibble_account=${accountcode}"/>
|
||||
<action application="set" data="nibble_rate=0.05"/>
|
||||
<action application="bridge" data="sofia/gateway/bandwidth.com/$1"/>
|
||||
</condition>
|
||||
</extension>
|
||||
|
||||
</include>
|
||||
@@ -52,19 +52,20 @@
|
||||
|
||||
typedef struct {
|
||||
switch_time_t lastts; /* Last time we did any billing */
|
||||
float total; /* Total amount billed so far */
|
||||
double total; /* Total amount billed so far */
|
||||
|
||||
switch_time_t pausets; /* Timestamp of when a pause action started. 0 if not paused */
|
||||
float bill_adjustments; /* Adjustments to make to the next billing, based on pause/resume events */
|
||||
double bill_adjustments; /* Adjustments to make to the next billing, based on pause/resume events */
|
||||
|
||||
int lowbal_action_executed; /* Set to 1 once lowbal_action has been executed */
|
||||
} nibble_data_t;
|
||||
|
||||
|
||||
typedef struct nibblebill_results {
|
||||
float balance;
|
||||
double balance;
|
||||
|
||||
float percall_max; /* Overrides global on a per-user level */
|
||||
float lowbal_amt; /* ditto */
|
||||
double percall_max; /* Overrides global on a per-user level */
|
||||
double lowbal_amt; /* ditto */
|
||||
} nibblebill_results_t;
|
||||
|
||||
|
||||
@@ -80,11 +81,11 @@ static struct {
|
||||
switch_mutex_t *mutex;
|
||||
|
||||
/* Global billing config options */
|
||||
float percall_max_amt; /* Per-call billing limit (safety check, for fraud) */
|
||||
double percall_max_amt; /* Per-call billing limit (safety check, for fraud) */
|
||||
char *percall_action; /* Exceeded length of per-call action */
|
||||
float lowbal_amt; /* When we warn them they are near depletion */
|
||||
double lowbal_amt; /* When we warn them they are near depletion */
|
||||
char *lowbal_action; /* Low balance action */
|
||||
float nobal_amt; /* Minimum amount that must remain in the account */
|
||||
double nobal_amt; /* Minimum amount that must remain in the account */
|
||||
char *nobal_action; /* Drop action */
|
||||
|
||||
/* Other options */
|
||||
@@ -136,7 +137,7 @@ static int nibblebill_callback(void *pArg, int argc, char **argv, char **columnN
|
||||
|
||||
for (i = 0; i < argc; i++) {
|
||||
if (!strcasecmp(columnNames[i], "nibble_balance")) {
|
||||
cbt->balance = (float) atof(argv[0]);
|
||||
cbt->balance = atof(argv[0]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -179,15 +180,15 @@ static switch_status_t load_config(void)
|
||||
} else if (!strcasecmp(var, "percall_action")) {
|
||||
set_global_percall_action(val);
|
||||
} else if (!strcasecmp(var, "percall_max_amt")) {
|
||||
globals.percall_max_amt = (float) atof(val);
|
||||
globals.percall_max_amt = atof(val);
|
||||
} else if (!strcasecmp(var, "lowbal_action")) {
|
||||
set_global_lowbal_action(val);
|
||||
} else if (!strcasecmp(var, "lowbal_amt")) {
|
||||
globals.lowbal_amt = (float) atof(val);
|
||||
globals.lowbal_amt = atof(val);
|
||||
} else if (!strcasecmp(var, "nobal_action")) {
|
||||
set_global_nobal_action(val);
|
||||
} else if (!strcasecmp(var, "nobal_amt")) {
|
||||
globals.nobal_amt = (float) atof(val);
|
||||
globals.nobal_amt = atof(val);
|
||||
} else if (!strcasecmp(var, "global_heartbeat")) {
|
||||
globals.global_heartbeat = atoi(val);
|
||||
}
|
||||
@@ -252,6 +253,23 @@ void debug_event_handler(switch_event_t *event)
|
||||
}
|
||||
}
|
||||
|
||||
static switch_status_t exec_app(switch_core_session_t *session, const char *app_string)
|
||||
{
|
||||
switch_status_t status;
|
||||
char *strings[2] = { 0 };
|
||||
char *dup;
|
||||
|
||||
if (!app_string) {
|
||||
return SWITCH_STATUS_FALSE;
|
||||
}
|
||||
|
||||
dup = strdup(app_string);
|
||||
switch_assert(dup);
|
||||
switch_separate_string(dup, ' ', strings, sizeof(strings) / sizeof(strings[0]));
|
||||
status = switch_core_session_execute_application(session, strings[0], strings[1]);
|
||||
free(dup);
|
||||
return status;
|
||||
}
|
||||
|
||||
static void transfer_call(switch_core_session_t *session, char *destination)
|
||||
{
|
||||
@@ -292,9 +310,8 @@ static void transfer_call(switch_core_session_t *session, char *destination)
|
||||
free(mydup);
|
||||
}
|
||||
|
||||
|
||||
/* At this time, billing never succeeds if you don't have a database. */
|
||||
static switch_status_t bill_event(float billamount, const char *billaccount, switch_channel_t *channel)
|
||||
static switch_status_t bill_event(double billamount, const char *billaccount, switch_channel_t *channel)
|
||||
{
|
||||
char *sql = NULL, *dsql = NULL;
|
||||
switch_odbc_statement_handle_t stmt = NULL;
|
||||
@@ -306,7 +323,7 @@ static switch_status_t bill_event(float billamount, const char *billaccount, swi
|
||||
|
||||
if (globals.custom_sql_save) {
|
||||
if (switch_string_var_check_const(globals.custom_sql_save) || switch_string_has_escaped_data(globals.custom_sql_save)) {
|
||||
switch_channel_set_variable_printf(channel, "nibble_increment", "%f", billamount, SWITCH_FALSE);
|
||||
switch_channel_set_variable_printf(channel, "nibble_bill", "%f", billamount, SWITCH_FALSE);
|
||||
sql = switch_channel_expand_variables(channel, globals.custom_sql_save);
|
||||
if (sql != globals.custom_sql_save) dsql = sql;
|
||||
} else {
|
||||
@@ -339,14 +356,14 @@ static switch_status_t bill_event(float billamount, const char *billaccount, swi
|
||||
}
|
||||
|
||||
|
||||
static float get_balance(const char *billaccount, switch_channel_t *channel)
|
||||
static double get_balance(const char *billaccount, switch_channel_t *channel)
|
||||
{
|
||||
char *dsql = NULL, *sql = NULL;
|
||||
nibblebill_results_t pdata;
|
||||
float balance = 0.00f;
|
||||
double balance = 0.0;
|
||||
|
||||
if (!switch_odbc_available()) {
|
||||
return -1.00f;
|
||||
return -1.0;
|
||||
}
|
||||
|
||||
memset(&pdata, 0, sizeof(pdata));
|
||||
@@ -369,7 +386,7 @@ static float get_balance(const char *billaccount, switch_channel_t *channel)
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error running this query: [%s]\n", sql);
|
||||
/* Return -1 for safety */
|
||||
|
||||
balance = -1.00f;
|
||||
balance = -1.0;
|
||||
} else {
|
||||
/* Successfully retrieved! */
|
||||
balance = pdata.balance;
|
||||
@@ -391,7 +408,7 @@ static switch_status_t do_billing(switch_core_session_t *session)
|
||||
/* Local vars */
|
||||
nibble_data_t *nibble_data;
|
||||
switch_time_t ts = switch_micro_time_now();
|
||||
float billamount;
|
||||
double billamount;
|
||||
char date[80] = "";
|
||||
char *uuid;
|
||||
switch_size_t retsize;
|
||||
@@ -399,9 +416,9 @@ static switch_status_t do_billing(switch_core_session_t *session)
|
||||
const char *billrate;
|
||||
const char *billincrement;
|
||||
const char *billaccount;
|
||||
float nobal_amt = globals.nobal_amt;
|
||||
//float lowbal_amt = globals.lowbal_amt;
|
||||
float balance;
|
||||
double nobal_amt = globals.nobal_amt;
|
||||
double lowbal_amt = globals.lowbal_amt;
|
||||
double balance;
|
||||
|
||||
if (!session) {
|
||||
/* Why are we here? */
|
||||
@@ -421,13 +438,13 @@ static switch_status_t do_billing(switch_core_session_t *session)
|
||||
billaccount = switch_channel_get_variable(channel, "nibble_account");
|
||||
|
||||
if (!zstr(switch_channel_get_variable(channel, "nobal_amt"))) {
|
||||
nobal_amt = (float)atof(switch_channel_get_variable(channel, "nobal_amt"));
|
||||
nobal_amt = atof(switch_channel_get_variable(channel, "nobal_amt"));
|
||||
}
|
||||
/*
|
||||
|
||||
if (!zstr(switch_channel_get_variable(channel, "lowbal_amt"))) {
|
||||
lowbal_amt = (float)atof(switch_channel_get_variable(channel, "lowbal_amt"));
|
||||
lowbal_amt = atof(switch_channel_get_variable(channel, "lowbal_amt"));
|
||||
}
|
||||
*/
|
||||
|
||||
/* Return if there's no billing information on this session */
|
||||
if (!billrate || !billaccount) {
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
@@ -497,11 +514,15 @@ static switch_status_t do_billing(switch_core_session_t *session)
|
||||
if ((ts - nibble_data->lastts) >= 0) {
|
||||
/* If billincrement is set we bill by it and not by time elapsed */
|
||||
if (!(switch_strlen_zero(billincrement))) {
|
||||
float chargedunits = ((int)((ts - nibble_data->lastts) / 1000000) <= (int)atof(billincrement)) ? ((float)atof(billincrement) * 1000000) : ceil((ts - nibble_data->lastts) / ((float)atof(billincrement) * 1000000)) * ((float)atof(billincrement) * 1000000);
|
||||
billamount = ((float) atof(billrate) / 1000000 / 60) * chargedunits - nibble_data->bill_adjustments;
|
||||
switch_time_t chargedunits = (ts - nibble_data->lastts) / 1000000 <= atol(billincrement) ? atol(billincrement) * 1000000 : (switch_time_t)(ceil((ts - nibble_data->lastts) / (atol(billincrement) * 1000000.0))) * atol(billincrement) * 1000000;
|
||||
billamount = (atof(billrate) / 1000000 / 60) * chargedunits - nibble_data->bill_adjustments;
|
||||
/* Account for the prepaid amount */
|
||||
nibble_data->lastts += chargedunits;
|
||||
} else {
|
||||
/* Convert billrate into microseconds and multiply by # of microseconds that have passed since last *successful* bill */
|
||||
billamount = ((float) atof(billrate) / 1000000 / 60) * ((ts - nibble_data->lastts)) - nibble_data->bill_adjustments;
|
||||
billamount = (atof(billrate) / 1000000 / 60) * ((ts - nibble_data->lastts)) - nibble_data->bill_adjustments;
|
||||
/* Update the last time we billed */
|
||||
nibble_data->lastts = ts;
|
||||
}
|
||||
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Billing $%f to %s (Call: %s / %f so far)\n", billamount, billaccount,
|
||||
@@ -521,21 +542,31 @@ static switch_status_t do_billing(switch_core_session_t *session)
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_CRIT, "Failed to log to database!\n");
|
||||
}
|
||||
} else {
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Just tried to bill %s negative minutes! That should be impossible.\n",
|
||||
uuid);
|
||||
if (switch_strlen_zero(billincrement))
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Just tried to bill %s negative minutes! That should be impossible.\n", uuid);
|
||||
}
|
||||
|
||||
/* Update the last time we billed */
|
||||
nibble_data->lastts = ts;
|
||||
|
||||
/* Save this location */
|
||||
if (channel) {
|
||||
switch_channel_set_private(channel, "_nibble_data_", nibble_data);
|
||||
|
||||
/* don't verify balance and transfer to nobal if we're done with call */
|
||||
if (switch_channel_get_state(channel) != CS_REPORTING && switch_channel_get_state(channel) != CS_HANGUP) {
|
||||
/* See if this person has enough money left to continue the call */
|
||||
|
||||
balance = get_balance(billaccount, channel);
|
||||
|
||||
/* See if we've achieved low balance */
|
||||
if (!nibble_data->lowbal_action_executed && balance <= lowbal_amt) {
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Balance of %f fell below low balance amount of %f! (Account %s)\n",
|
||||
balance, lowbal_amt, billaccount);
|
||||
|
||||
if (exec_app(session, globals.lowbal_action) != SWITCH_STATUS_SUCCESS)
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Low balance action didn't execute\n");
|
||||
else
|
||||
nibble_data->lowbal_action_executed = 1;
|
||||
}
|
||||
|
||||
/* See if this person has enough money left to continue the call */
|
||||
if (balance <= nobal_amt) {
|
||||
/* Not enough money - reroute call to nobal location */
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_CRIT, "Balance of %f fell below allowed amount of %f! (Account %s)\n",
|
||||
@@ -665,7 +696,7 @@ static void nibblebill_resume(switch_core_session_t *session)
|
||||
billrate = switch_channel_get_variable(channel, "nibble_rate");
|
||||
|
||||
/* Calculate how much was "lost" to billings during pause - we do this here because you never know when the billrate may change during a call */
|
||||
nibble_data->bill_adjustments += ((float) atof(billrate) / 1000000 / 60) * ((ts - nibble_data->pausets));
|
||||
nibble_data->bill_adjustments += (atof(billrate) / 1000000 / 60) * ((ts - nibble_data->pausets));
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "Resumed billing! Subtracted %f from this billing cycle.\n",
|
||||
(atof(billrate) / 1000000 / 60) * ((ts - nibble_data->pausets)));
|
||||
|
||||
@@ -711,11 +742,11 @@ static void nibblebill_reset(switch_core_session_t *session)
|
||||
}
|
||||
}
|
||||
|
||||
static float nibblebill_check(switch_core_session_t *session)
|
||||
static double nibblebill_check(switch_core_session_t *session)
|
||||
{
|
||||
switch_channel_t *channel = switch_core_session_get_channel(session);
|
||||
nibble_data_t *nibble_data;
|
||||
float amount = 0;
|
||||
double amount = 0;
|
||||
|
||||
if (!channel) {
|
||||
return -99999;
|
||||
@@ -744,7 +775,7 @@ static float nibblebill_check(switch_core_session_t *session)
|
||||
return amount;
|
||||
}
|
||||
|
||||
static void nibblebill_adjust(switch_core_session_t *session, float amount)
|
||||
static void nibblebill_adjust(switch_core_session_t *session, double amount)
|
||||
{
|
||||
switch_channel_t *channel = switch_core_session_get_channel(session);
|
||||
const char *billaccount;
|
||||
@@ -780,7 +811,7 @@ SWITCH_STANDARD_APP(nibblebill_app_function)
|
||||
if (!zstr(data) && (lbuf = strdup(data))
|
||||
&& (argc = switch_separate_string(lbuf, ' ', argv, (sizeof(argv) / sizeof(argv[0]))))) {
|
||||
if (!strcasecmp(argv[0], "adjust") && argc == 2) {
|
||||
nibblebill_adjust(session, (float) atof(argv[1]));
|
||||
nibblebill_adjust(session, atof(argv[1]));
|
||||
} else if (!strcasecmp(argv[0], "flush")) {
|
||||
do_billing(session);
|
||||
} else if (!strcasecmp(argv[0], "pause")) {
|
||||
@@ -812,7 +843,7 @@ SWITCH_STANDARD_API(nibblebill_api_function)
|
||||
char *uuid = argv[0];
|
||||
if ((psession = switch_core_session_locate(uuid))) {
|
||||
if (!strcasecmp(argv[1], "adjust") && argc == 3) {
|
||||
nibblebill_adjust(psession, (float) atof(argv[2]));
|
||||
nibblebill_adjust(psession, atof(argv[2]));
|
||||
} else if (!strcasecmp(argv[1], "flush")) {
|
||||
do_billing(psession);
|
||||
} else if (!strcasecmp(argv[1], "pause")) {
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
<configuration name="osp.conf" description="OSP Module Configuration">
|
||||
<settings>
|
||||
<!-- Debug info flag -->
|
||||
<param name="debug-info" value="disabled"/>
|
||||
<!-- Log level for debug info -->
|
||||
<param name="log-level" value="info"/>
|
||||
<!-- Crypto hareware accelerate is disabled by default -->
|
||||
<param name="crypto-hardware" value="disabled"/>
|
||||
<!-- SIP settings -->
|
||||
<param name="sip" module="sofia" profile="external"/>
|
||||
<!-- H.323 settings -->
|
||||
<!-- <param name="h323" module="h323" profile="external"/> -->
|
||||
<!-- IAX settings -->
|
||||
<!-- <param name="iax" module="iax" profile="external"/> -->
|
||||
<!-- Skype settings -->
|
||||
<!-- <param name="skype" module="skypopen" profile="external"/> -->
|
||||
<!-- Default destination protocol -->
|
||||
<param name="default-protocol" value="sip"/>
|
||||
</settings>
|
||||
|
||||
<profiles>
|
||||
<!-- Default OSP profile -->
|
||||
<profile name="default">
|
||||
<!-- Service point URLs, up to 8 allowed -->
|
||||
<!-- <param name="service-point-url" value="http://osptestserver.transnexus.com:5045/osp"/> -->
|
||||
<!-- <param name="service-point-url" value="https://127.0.0.1:1443/osp"/> -->
|
||||
<param name="service-point-url" value="http://127.0.0.1:5045/osp"/>
|
||||
|
||||
<!-- FreeSWITCH IP address for OSP -->
|
||||
<param name="device-ip" value="127.0.0.1:5080"/>
|
||||
|
||||
<!-- SSL lifetime in seconds -->
|
||||
<param name="ssl-lifetime" value="300"/>
|
||||
<!-- HTTP max connections, 1~1000 -->
|
||||
<param name="http-max-connections" value="20"/>
|
||||
<!-- HTTP persistence in seconds -->
|
||||
<param name="http-persistence" value="60"/>
|
||||
<!-- HTTP retry delay in seconds, 0~10 -->
|
||||
<param name="http-retry-delay" value="0"/>
|
||||
<!-- HTTP retry limit, 0~100 -->
|
||||
<param name="http-retry-limit" value="2"/>
|
||||
<!-- HTTP timeout in milliseconds, 200~60000 -->
|
||||
<param name="http-timeout" value="10000"/>
|
||||
|
||||
<!-- OSP work mode, direct or indirect -->
|
||||
<param name="work-mode" value="direct"/>
|
||||
<!-- OSP service type, voice or npquery -->
|
||||
<param name="service-type" value="voice"/>
|
||||
<!-- Max number of destinations -->
|
||||
<param name="max-destinations" value="12"/>
|
||||
</profile>
|
||||
</profiles>
|
||||
</configuration>
|
||||
@@ -0,0 +1,7 @@
|
||||
<configuration name="redis.conf" description="mod_redis Configuration">
|
||||
<settings>
|
||||
<param name="host" value="localhost"/>
|
||||
<param name="port" value="6379"/>
|
||||
<param name="timeout" value="10000"/>
|
||||
</settings>
|
||||
</configuration>
|
||||
@@ -0,0 +1,7 @@
|
||||
<configuration name="rss.conf" description="RSS Parser">
|
||||
<feeds>
|
||||
<!-- Just download the files to wherever and refer to them here -->
|
||||
<!-- <feed name="Slash Dot">/home/rss/rss.rss</feed> -->
|
||||
<!-- <feed name="News Forge">/home/rss/newsforge.rss</feed> -->
|
||||
</feeds>
|
||||
</configuration>
|
||||
@@ -0,0 +1,7 @@
|
||||
<include>
|
||||
<extension name="rss">
|
||||
<condition field="destination_number" expression="^rss$">
|
||||
<action application="rss"/>
|
||||
</condition>
|
||||
</extension>
|
||||
</include>
|
||||
@@ -0,0 +1,12 @@
|
||||
if (session.ready()) {
|
||||
session.answer();
|
||||
session.speak("cepstral","David","Please wait while we refresh the RSS feeds.")
|
||||
|
||||
fetchURLFile("http://weather.yahooapis.com/forecastrss?p=60610","rss/weather.rss");
|
||||
fetchURLFile("http://rss.news.yahoo.com/rss/topstories","rss/yahootop.rss");
|
||||
fetchURLFile("http://rss.news.yahoo.com/rss/science","rss/yahoosci.rss");
|
||||
fetchURLFile("http://rss.news.yahoo.com/rss/business","rss/yahoobus.rss");
|
||||
fetchURLFile("http://rss.news.yahoo.com/rss/entertainment","rss/yahooent.rss");
|
||||
fetchURLFile("http://rss.slashdot.org/Slashdot/slashdot","rss/slashdot.rss");
|
||||
fetchURLFile("http://www.freeswitch.org/xml.php","rss/freeswitch.rss");
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
@@ -20,7 +20,7 @@
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectName>mod_sms</ProjectName>
|
||||
<ProjectGuid>{11C9BC3D-45E9-46E3-BE84-B8CEE4685E39}</ProjectGuid>
|
||||
<ProjectGuid>{2469B306-B027-4FF2-8815-C9C1EA2CAE79}</ProjectGuid>
|
||||
<RootNamespace>mod_sms</RootNamespace>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
</PropertyGroup>
|
||||
@@ -63,10 +63,6 @@
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup>
|
||||
<_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
|
||||
<OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(Platform)\$(Configuration)\</OutDir>
|
||||
<IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(Platform)\$(Configuration)\</IntDir>
|
||||
<OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(Platform)\$(Configuration)\</OutDir>
|
||||
<IntDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(Platform)\$(Configuration)\</IntDir>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
@@ -132,4 +128,4 @@
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
</Project>
|
||||
@@ -0,0 +1,16 @@
|
||||
<include>
|
||||
<extension name="snom-demo-1">
|
||||
<condition field="destination_number" expression="^9000$">
|
||||
<!-- <key> <light> <label> <user> <host> <profile> <action_name> <action> -->
|
||||
<action application="eval" data="${snom_bind_key(2 on DND ${sip_from_user} ${sip_from_host} ${sofia_profile_name} message api+uuid_transfer ${uuid} 9001)}"/>
|
||||
<action application="playback" data="$${hold_music}"/>
|
||||
</condition>
|
||||
</extension>
|
||||
|
||||
<extension name="snom-demo-2">
|
||||
<condition field="destination_number" expression="^9001$">
|
||||
<action application="eval" data="${snom_bind_key(2 off DND ${sip_from_user} ${sip_from_host} ${sofia_profile_name} message notused)}"/>
|
||||
<action application="transfer" data="3000"/>
|
||||
</condition>
|
||||
</extension>
|
||||
</include>
|
||||
@@ -0,0 +1,108 @@
|
||||
<configuration name="spandsp.conf" description="SpanDSP config">
|
||||
<modem-settings>
|
||||
<!--
|
||||
total-modems set to N will create that many soft-modems.
|
||||
If you use them with Hylafax you need the following for each one numbered 0..N:
|
||||
|
||||
1) A line like this in /etc/inittab:
|
||||
|
||||
f0:2345:respawn:/usr/lib/fax/faxgetty /dev/FS0
|
||||
|
||||
2) copy conf/config.FS0 to /var/spool/hylafax/etc (or wherver the appropriate dir is on your system)
|
||||
|
||||
Subsequent modem configs would incrment the 0 to 1 and so on.
|
||||
|
||||
-->
|
||||
<param name="total-modems" value="0"/>
|
||||
|
||||
<!-- Default context and dialplan to use on inbound calls from the modems -->
|
||||
<param name="context" value="default"/>
|
||||
<param name="dialplan" value="XML"/>
|
||||
|
||||
<!-- Extra tracing for debugging -->
|
||||
<param name="verbose" value="false"/>
|
||||
</modem-settings>
|
||||
|
||||
<fax-settings>
|
||||
<param name="use-ecm" value="true"/>
|
||||
<param name="verbose" value="false"/>
|
||||
<param name="disable-v17" value="false"/>
|
||||
<param name="ident" value="SpanDSP Fax Ident"/>
|
||||
<param name="header" value="SpanDSP Fax Header"/>
|
||||
|
||||
<param name="spool-dir" value="/tmp"/>
|
||||
<param name="file-prefix" value="faxrx"/>
|
||||
</fax-settings>
|
||||
|
||||
<descriptors>
|
||||
|
||||
<!-- These tones are defined in Annex to ITU Operational Bulletin No. 781 - 1.II.2003 -->
|
||||
<!-- Various Tones Used in National Networks (According to ITU-T Recommendation E.180)(03/1998) -->
|
||||
|
||||
<!-- North America -->
|
||||
<descriptor name="1">
|
||||
<tone name="CED_TONE">
|
||||
<element freq1="2100" freq2="0" min="500" max="0"/>
|
||||
</tone>
|
||||
<tone name="SIT">
|
||||
<element freq1="950" freq2="0" min="256" max="400"/>
|
||||
<element freq1="1400" freq2="0" min="256" max="400"/>
|
||||
<element freq1="1800" freq2="0" min="256" max="400"/>
|
||||
</tone>
|
||||
<tone name="REORDER_TONE">
|
||||
<element freq1="480" freq2="620" min="224" max="272"/>
|
||||
<element freq1="0" freq2="0" min="224" max="272"/>
|
||||
</tone>
|
||||
<tone name="BUSY_TONE">
|
||||
<element freq1="480" freq2="620" min="464" max="516"/>
|
||||
<element freq1="0" freq2="0" min="464" max="516"/>
|
||||
</tone>
|
||||
</descriptor>
|
||||
|
||||
<!-- United Kingdom -->
|
||||
<descriptor name="44">
|
||||
<tone name="CED_TONE">
|
||||
<element freq1="2100" freq2="0" min="500" max="0"/>
|
||||
</tone>
|
||||
<tone name="SIT">
|
||||
<element freq1="950" freq2="0" min="256" max="400"/>
|
||||
<element freq1="1400" freq2="0" min="256" max="400"/>
|
||||
<element freq1="1800" freq2="0" min="256" max="400"/>
|
||||
</tone>
|
||||
<tone name="REORDER_TONE">
|
||||
<element freq1="400" freq2="0" min="368" max="416"/>
|
||||
<element freq1="0" freq2="0" min="336" max="368"/>
|
||||
<element freq1="400" freq2="0" min="256" max="288"/>
|
||||
<element freq1="0" freq2="0" min="512" max="544"/>
|
||||
</tone>
|
||||
<tone name="BUSY_TONE">
|
||||
<element freq1="400" freq2="0" min="352" max="384"/>
|
||||
<element freq1="0" freq2="0" min="352" max="384"/>
|
||||
<element freq1="400" freq2="0" min="352" max="384"/>
|
||||
<element freq1="0" freq2="0" min="352" max="384"/>
|
||||
</tone>
|
||||
</descriptor>
|
||||
|
||||
<!-- Germany -->
|
||||
<descriptor name="49">
|
||||
<tone name="CED_TONE">
|
||||
<element freq1="2100" freq2="0" min="500" max="0"/>
|
||||
</tone>
|
||||
<tone name="SIT">
|
||||
<element freq1="900" freq2="0" min="256" max="400"/>
|
||||
<element freq1="1400" freq2="0" min="256" max="400"/>
|
||||
<element freq1="1800" freq2="0" min="256" max="400"/>
|
||||
</tone>
|
||||
<tone name="REORDER_TONE">
|
||||
<element freq1="425" freq2="0" min="224" max="272"/>
|
||||
<element freq1="0" freq2="0" min="224" max="272"/>
|
||||
</tone>
|
||||
<tone name="BUSY_TONE">
|
||||
<element freq1="425" freq2="0" min="464" max="516"/>
|
||||
<element freq1="0" freq2="0" min="464" max="516"/>
|
||||
</tone>
|
||||
</descriptor>
|
||||
</descriptors>
|
||||
|
||||
</configuration>
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
CountryCode: 1
|
||||
AreaCode: 800
|
||||
FAXNumber: +1.800.555.1212
|
||||
LongDistancePrefix: 1
|
||||
InternationalPrefix: 011
|
||||
DialStringRules: etc/dialrules
|
||||
ServerTracing: 0xFFF
|
||||
SessionTracing: 0xFFF
|
||||
RecvFileMode: 0600
|
||||
LogFileMode: 0600
|
||||
DeviceMode: 0600
|
||||
RingsBeforeAnswer: 1
|
||||
SpeakerVolume: off
|
||||
GettyArgs: "-h %l dx_%s"
|
||||
LocalIdentifier: "FS"
|
||||
TagLineFont: etc/lutRS18.pcf
|
||||
TagLineFormat: "From %%l|%c|Page %%P of %%T"
|
||||
MaxRecvPages: 200
|
||||
#
|
||||
#
|
||||
# Modem-related stuff: should reflect modem command interface
|
||||
# and hardware connection/cabling (e.g. flow control).
|
||||
#
|
||||
ModemType: Class1 # use this to supply a hint
|
||||
|
||||
#
|
||||
# Enabling this will use the hfaxd-protocol to set Caller*ID
|
||||
#
|
||||
#ModemSetOriginCmd: AT+VSID="%s","%d"
|
||||
|
||||
#
|
||||
# If "glare" during initialization becomes a problem then take
|
||||
# the modem off-hook during initialization, and then place it
|
||||
# back on-hook when done.
|
||||
#
|
||||
#ModemResetCmds: "ATH1\nAT+VCID=1" # enables CallID display
|
||||
#ModemReadyCmds: ATH0
|
||||
|
||||
Class1AdaptRecvCmd: AT+FAR=1
|
||||
Class1TMConnectDelay: 400 # counteract quick CONNECT response
|
||||
|
||||
#
|
||||
# If you have trouble with V.17 receiving or sending,
|
||||
# you may want to enable one of these, respectively.
|
||||
#
|
||||
#Class1RMQueryCmd: "!24,48,72,96" # enable this to disable V.17 receiving
|
||||
#Class1TMQueryCmd: "!24,48,72,96" # enable this to disable V.17 sending
|
||||
|
||||
#
|
||||
# You'll likely want Caller*ID display (also displays DID) enabled.
|
||||
#
|
||||
ModemResetCmds: AT+VCID=1 # enables CallID display
|
||||
|
||||
#
|
||||
# The pty does not support changing parity.
|
||||
#
|
||||
PagerTTYParity: none
|
||||
|
||||
#
|
||||
# If you are "missing" Caller*ID data on some calls (but not all)
|
||||
# and if you do not have adequate glare protection you may want to
|
||||
# not answer based on RINGs, but rather enable the CallIDAnswerLength
|
||||
# for NDID, disable AT+VCID=1 and do this:
|
||||
#
|
||||
#RingsBeforeAnswer: 0
|
||||
#ModemRingResponse: AT+VRID=1
|
||||
|
||||
# Uncomment DATE and TIME if you really want them, but you probably don't.
|
||||
#CallIDPattern: "DATE="
|
||||
#CallIDPattern: "TIME="
|
||||
CallIDPattern: "NMBR="
|
||||
CallIDPattern: "NAME="
|
||||
CallIDPattern: "ANID="
|
||||
#CallIDPattern: "USER=" # username provided by call
|
||||
#CallIDPattern: "PASS=" # password provided by call
|
||||
#CallIDPattern: "CDID=" # DID context in call
|
||||
CallIDPattern: "NDID="
|
||||
#CallIDAnswerLength: 4
|
||||
@@ -0,0 +1,26 @@
|
||||
<extension name="fax_receive">
|
||||
<condition field="destination_number" expression="^9178$">
|
||||
<action application="answer" />
|
||||
<action application="playback" data="silence_stream://2000"/>
|
||||
<action application="rxfax" data="/tmp/rxfax.tif"/>
|
||||
<action application="hangup"/>
|
||||
</condition>
|
||||
</extension>
|
||||
|
||||
<extension name="fax_transmit">
|
||||
<condition field="destination_number" expression="^9179$">
|
||||
<action application="txfax" data="/tmp/txfax.tif"/>
|
||||
<action application="hangup"/>
|
||||
</condition>
|
||||
</extension>
|
||||
|
||||
<extension name="fax_receive">
|
||||
<condition field="destination_number" expression="^9978$">
|
||||
<action application="answer" />
|
||||
<action application="playback" data="silence_stream://2000"/>
|
||||
<action application="set" data="fax_enable_t38_request=true"/>
|
||||
<action application="set" data="fax_enable_t38=true"/>
|
||||
<action application="rxfax" data="/tmp/FAX-${uuid}.tif"/>
|
||||
<action application="hangup"/>
|
||||
</condition>
|
||||
</extension>
|
||||
@@ -337,7 +337,7 @@ switch_status_t load_configuration(switch_bool_t reload)
|
||||
spandsp_globals.timezone = "";
|
||||
|
||||
/* TODO make configuration param */
|
||||
spandsp_globals.tonedebug = 1;
|
||||
spandsp_globals.tonedebug = 0;
|
||||
|
||||
if ((xml = switch_xml_open_cfg("spandsp.conf", &cfg, NULL)) || (xml = switch_xml_open_cfg("fax.conf", &cfg, NULL))) {
|
||||
status = SWITCH_STATUS_SUCCESS;
|
||||
|
||||
@@ -137,6 +137,6 @@ switch_status_t spandsp_fax_detect_session(switch_core_session_t *session,
|
||||
int hits, const char *app, const char *data, switch_tone_detect_callback_t callback);
|
||||
|
||||
switch_status_t spandsp_fax_stop_detect_session(switch_core_session_t *session);
|
||||
void spanfax_log_message(int level, const char *msg);
|
||||
void spanfax_log_message(void *user_data, int level, const char *msg);
|
||||
switch_status_t load_configuration(switch_bool_t reload);
|
||||
void mod_spandsp_indicate_data(switch_core_session_t *session, switch_bool_t self, switch_bool_t on);
|
||||
|
||||
@@ -259,7 +259,7 @@ static void counter_increment(void)
|
||||
switch_mutex_unlock(spandsp_globals.mutex);
|
||||
}
|
||||
|
||||
void spanfax_log_message(int level, const char *msg)
|
||||
void spanfax_log_message(void *user_data, int level, const char *msg)
|
||||
{
|
||||
int fs_log_level;
|
||||
|
||||
@@ -341,6 +341,7 @@ static int phase_b_handler(t30_state_t *s, void *user_data, int result)
|
||||
/* Fire event */
|
||||
|
||||
if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, pvt->app_mode == FUNCTION_TX ? SPANDSP_EVENT_TXFAXNEGOCIATERESULT : SPANDSP_EVENT_RXFAXNEGOCIATERESULT) == SWITCH_STATUS_SUCCESS) {
|
||||
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "uuid", switch_core_session_get_uuid(session));
|
||||
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "fax-transfer-rate", fax_transfer_rate);
|
||||
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "fax-ecm-used", (t30_stats.error_correcting_mode) ? "on" : "off");
|
||||
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "fax-local-station-id", local_ident);
|
||||
@@ -437,6 +438,7 @@ static int phase_d_handler(t30_state_t *s, void *user_data, int msg)
|
||||
switch_channel_execute_on(channel, "execute_on_fax_phase_d");
|
||||
|
||||
if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, pvt->app_mode == FUNCTION_TX ? SPANDSP_EVENT_TXFAXPAGERESULT : SPANDSP_EVENT_RXFAXPAGERESULT) == SWITCH_STATUS_SUCCESS) {
|
||||
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "uuid", switch_core_session_get_uuid(session));
|
||||
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "fax-document-transferred-pages", fax_document_transferred_pages);
|
||||
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "fax-image-resolution", fax_image_resolution);
|
||||
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "fax-image-size", fax_image_size);
|
||||
@@ -711,8 +713,8 @@ static switch_status_t spanfax_init(pvt_t *pvt, transport_mode_t trans_mode)
|
||||
|
||||
fax_set_transmit_on_idle(fax, TRUE);
|
||||
|
||||
span_log_set_message_handler(&fax->logging, spanfax_log_message);
|
||||
span_log_set_message_handler(&t30->logging, spanfax_log_message);
|
||||
span_log_set_message_handler(&fax->logging, spanfax_log_message, NULL);
|
||||
span_log_set_message_handler(&t30->logging, spanfax_log_message, NULL);
|
||||
|
||||
if (pvt->verbose) {
|
||||
span_log_set_level(&fax->logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW);
|
||||
@@ -767,8 +769,8 @@ static switch_status_t spanfax_init(pvt_t *pvt, transport_mode_t trans_mode)
|
||||
}
|
||||
}
|
||||
|
||||
span_log_set_message_handler(&t38->logging, spanfax_log_message);
|
||||
span_log_set_message_handler(&t30->logging, spanfax_log_message);
|
||||
span_log_set_message_handler(&t38->logging, spanfax_log_message, NULL);
|
||||
span_log_set_message_handler(&t30->logging, spanfax_log_message, NULL);
|
||||
|
||||
if (pvt->verbose) {
|
||||
span_log_set_level(&t38->logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW);
|
||||
@@ -822,8 +824,8 @@ static switch_status_t spanfax_init(pvt_t *pvt, transport_mode_t trans_mode)
|
||||
}
|
||||
|
||||
|
||||
span_log_set_message_handler(&pvt->t38_gateway_state->logging, spanfax_log_message);
|
||||
span_log_set_message_handler(&pvt->t38_core->logging, spanfax_log_message);
|
||||
span_log_set_message_handler(&pvt->t38_gateway_state->logging, spanfax_log_message, NULL);
|
||||
span_log_set_message_handler(&pvt->t38_core->logging, spanfax_log_message, NULL);
|
||||
|
||||
if (pvt->verbose) {
|
||||
span_log_set_level(&pvt->t38_gateway_state->logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW);
|
||||
|
||||
@@ -346,15 +346,15 @@ switch_status_t modem_init(modem_t *modem, modem_control_handler_t control_handl
|
||||
}
|
||||
|
||||
if (spandsp_globals.modem_verbose) {
|
||||
span_log_set_message_handler(&modem->t31_state->logging, spanfax_log_message);
|
||||
span_log_set_message_handler(&modem->t31_state->audio.modems.v17_rx.logging, spanfax_log_message);
|
||||
span_log_set_message_handler(&modem->t31_state->audio.modems.v29_rx.logging, spanfax_log_message);
|
||||
span_log_set_message_handler(&modem->t31_state->audio.modems.v27ter_rx.logging, spanfax_log_message);
|
||||
span_log_set_message_handler(&modem->t31_state->logging, spanfax_log_message, NULL);
|
||||
span_log_set_message_handler(&modem->t31_state->audio.modems.fast_modems.v17_rx.logging, spanfax_log_message, NULL);
|
||||
span_log_set_message_handler(&modem->t31_state->audio.modems.fast_modems.v29_rx.logging, spanfax_log_message, NULL);
|
||||
span_log_set_message_handler(&modem->t31_state->audio.modems.fast_modems.v27ter_rx.logging, spanfax_log_message, NULL);
|
||||
|
||||
modem->t31_state->logging.level = SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW;
|
||||
modem->t31_state->audio.modems.v17_rx.logging.level = SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW;
|
||||
modem->t31_state->audio.modems.v29_rx.logging.level = SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW;
|
||||
modem->t31_state->audio.modems.v27ter_rx.logging.level = SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW;
|
||||
modem->t31_state->audio.modems.fast_modems.v17_rx.logging.level = SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW;
|
||||
modem->t31_state->audio.modems.fast_modems.v29_rx.logging.level = SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW;
|
||||
modem->t31_state->audio.modems.fast_modems.v27ter_rx.logging.level = SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW;
|
||||
}
|
||||
|
||||
modem->control_handler = control_handler;
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
<include>
|
||||
<!--
|
||||
Valet park retrieval, works with valet_park extension below.
|
||||
Retrieve a valet parked call by dialing 6000 + park number + #
|
||||
-->
|
||||
<extension name="valet_park">
|
||||
<condition field="destination_number" expression="^(6000)$">
|
||||
<action application="answer"/>
|
||||
<action application="valet_park" data="valet_parking_lot ask 1 11 10000 ivr/ivr-enter_ext_pound.wav"/>
|
||||
</condition>
|
||||
</extension>
|
||||
|
||||
<!--
|
||||
Valet park 6001-6099. Blind x-fer to 6001, 6002, etc. to valet park the call.
|
||||
Dial 6001, 6002, etc. to retrieve a call that is already valet parked.
|
||||
After call is retrieved, park extension is free for another call.
|
||||
-->
|
||||
<extension name="valet_park">
|
||||
<condition field="destination_number" expression="^(60\d[1-9])$">
|
||||
<action application="answer"/>
|
||||
<action application="valet_park" data="valet_parking_lot $1"/>
|
||||
</condition>
|
||||
</extension>
|
||||
</include>
|
||||
@@ -0,0 +1,12 @@
|
||||
<include>
|
||||
<extension name="vmdtest">
|
||||
<condition field="destination_number" expression="^vmd(\d{10})$">
|
||||
<action application="answer"/>
|
||||
<action application="info"/>
|
||||
<action application="vmd"/>
|
||||
<action application="sleep" data="25000"/>
|
||||
<action application="info"/> <!-- Look for chan var "vmd_detect" here -->
|
||||
<action application="hangup"/>
|
||||
</condition>
|
||||
</extension>
|
||||
</include>
|
||||
@@ -0,0 +1,27 @@
|
||||
function onInput(s, type, obj, arg)
|
||||
{
|
||||
try
|
||||
{
|
||||
if(type == "dtmf")
|
||||
{
|
||||
console_log("info", "DTMF digit: "+s.name+" ["+obj.digit+"] len ["+obj.duration+"]\n");
|
||||
}
|
||||
else if(type == "event" && session.getVariable("vmd_detect") == "TRUE")
|
||||
{
|
||||
console_log("info", "Voicemail Detected\n");
|
||||
}
|
||||
|
||||
}
|
||||
catch(e)
|
||||
{
|
||||
console_log("err", e + "\n");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
session.answer();
|
||||
session.execute("vmd", "start");
|
||||
while(session.ready())
|
||||
{
|
||||
session.streamFile(argv[0], onInput);
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
local human_detected = false;
|
||||
local voicemail_detected = false;
|
||||
|
||||
function onInput(session, type, obj)
|
||||
if type == "dtmf" and obj['digit'] == '1' and human_detected == false then
|
||||
human_detected = true;
|
||||
return "break";
|
||||
end
|
||||
|
||||
if type == "event" and voicemail_detected == false then
|
||||
voicemail_detected = true;
|
||||
return "break";
|
||||
end
|
||||
end
|
||||
|
||||
session:setInputCallback("onInput");
|
||||
session:execute("vmd","start");
|
||||
@@ -0,0 +1,70 @@
|
||||
<configuration name="voicemail.conf" description="Voicemail">
|
||||
<settings>
|
||||
</settings>
|
||||
<profiles>
|
||||
<profile name="default">
|
||||
<param name="file-extension" value="wav"/>
|
||||
<param name="terminator-key" value="#"/>
|
||||
<param name="max-login-attempts" value="3"/>
|
||||
<param name="digit-timeout" value="10000"/>
|
||||
<param name="min-record-len" value="3"/>
|
||||
<param name="max-record-len" value="300"/>
|
||||
<param name="max-retries" value="3"/>
|
||||
<param name="tone-spec" value="%(1000, 0, 640)"/>
|
||||
<param name="callback-dialplan" value="XML"/>
|
||||
<param name="callback-context" value="default"/>
|
||||
<param name="play-new-messages-key" value="1"/>
|
||||
<param name="play-saved-messages-key" value="2"/>
|
||||
<param name="login-keys" value="0"/>
|
||||
<param name="main-menu-key" value="0"/>
|
||||
<param name="config-menu-key" value="5"/>
|
||||
<param name="record-greeting-key" value="1"/>
|
||||
<param name="choose-greeting-key" value="2"/>
|
||||
<param name="change-pass-key" value="6"/>
|
||||
<param name="record-name-key" value="3"/>
|
||||
<param name="record-file-key" value="3"/>
|
||||
<param name="listen-file-key" value="1"/>
|
||||
<param name="save-file-key" value="2"/>
|
||||
<param name="delete-file-key" value="7"/>
|
||||
<param name="undelete-file-key" value="8"/>
|
||||
<param name="email-key" value="4"/>
|
||||
<param name="pause-key" value="0"/>
|
||||
<param name="restart-key" value="1"/>
|
||||
<param name="ff-key" value="6"/>
|
||||
<param name="rew-key" value="4"/>
|
||||
<param name="skip-greet-key" value="#"/>
|
||||
<param name="previous-message-key" value="1"/>
|
||||
<param name="next-message-key" value="3"/>
|
||||
<param name="skip-info-key" value="*"/>
|
||||
<param name="repeat-message-key" value="0"/>
|
||||
<param name="record-silence-threshold" value="200"/>
|
||||
<param name="record-silence-hits" value="2"/>
|
||||
<param name="web-template-file" value="web-vm.tpl"/>
|
||||
<param name="db-password-override" value="false"/>
|
||||
<param name="allow-empty-password-auth" value="true"/>
|
||||
<!-- if you need to change the sample rate of the recorded files e.g. gmail voicemail player -->
|
||||
<!--<param name="record-sample-rate" value="11025"/>-->
|
||||
<!-- the next two both must be set for this to be enabled
|
||||
the extension is in the format of <dest> [<dialplan>] [<context>]
|
||||
-->
|
||||
<param name="operator-extension" value="operator XML default"/>
|
||||
<param name="operator-key" value="9"/>
|
||||
<param name="vmain-extension" value="vmain XML default"/>
|
||||
<param name="vmain-key" value="*"/>
|
||||
<!-- playback created files as soon as they were recorded by default -->
|
||||
<!--<param name="auto-playback-recordings" value="true"/>-->
|
||||
<email>
|
||||
<param name="template-file" value="voicemail.tpl"/>
|
||||
<param name="notify-template-file" value="notify-voicemail.tpl"/>
|
||||
<!-- this is the format voicemail_time will have -->
|
||||
<param name="date-fmt" value="%A, %B %d %Y, %I %M %p"/>
|
||||
<param name="email-from" value="${voicemail_account}@${voicemail_domain}"/>
|
||||
</email>
|
||||
<!--<param name="storage-dir" value="/tmp"/>-->
|
||||
<!--<param name="odbc-dsn" value="dsn:user:pass"/>-->
|
||||
<!--<param name="record-comment" value="Your Comment"/>-->
|
||||
<!--<param name="record-title" value="Your Title"/>-->
|
||||
<!--<param name="record-copyright" value="Your Copyright"/>-->
|
||||
</profile>
|
||||
</profiles>
|
||||
</configuration>
|
||||
@@ -0,0 +1,20 @@
|
||||
<include>
|
||||
<!-- This is a _VERY_ abbreviated demo for voicemail. A better demo would be useful -->
|
||||
|
||||
<!-- voicemail main extension -->
|
||||
<extension name="vmain">
|
||||
<condition field="destination_number" expression="^vmain$|^4000$|^\*98$">
|
||||
<action application="answer"/>
|
||||
<action application="sleep" data="1000"/>
|
||||
<action application="voicemail" data="check default ${domain_name}"/>
|
||||
</condition>
|
||||
</extension>
|
||||
|
||||
<extension name="Local_Voicemail">
|
||||
<condition field="destination_number" expression="^(10[01][0-9])$">
|
||||
<action application="export" data="dialed_extension=$1"/>
|
||||
<action application="export" data="domain=default"/>
|
||||
<action application="bridge" data="loopback/app=voicemail:default ${domain_name} ${dialed_extension}"/>
|
||||
</condition>
|
||||
</extension>
|
||||
</include>
|
||||
@@ -0,0 +1,44 @@
|
||||
From: "${voicemail_caller_id_name}" <${voicemail_caller_id_number}@${voicemail_domain}>
|
||||
Date: ${RFC2822_DATE}
|
||||
To: <${voicemail_notify_email}>
|
||||
Subject: Voicemail from "${voicemail_caller_id_name}" <${voicemail_caller_id_number}> ${voicemail_message_len}
|
||||
X-Priority: ${voicemail_priority}
|
||||
X-Mailer: FreeSWITCH
|
||||
|
||||
Content-Type: multipart/alternative;
|
||||
boundary="000XXX000"
|
||||
|
||||
--000XXX000
|
||||
Content-Type: text/plain; charset=ISO-8859-1; Format=Flowed
|
||||
Content-Disposition: inline
|
||||
Content-Transfer-Encoding: 7bit
|
||||
|
||||
Created: ${voicemail_time}
|
||||
From: "${voicemail_caller_id_name}" <${voicemail_caller_id_number}>
|
||||
Duration: ${voicemail_message_len}
|
||||
Account: ${voicemail_account}@${voicemail_domain}
|
||||
|
||||
--000XXX000
|
||||
Content-Type: text/html; charset=ISO-8859-1
|
||||
Content-Disposition: inline
|
||||
Content-Transfer-Encoding: 7bit
|
||||
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<META http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||
<title>Voicemail from "${voicemail_caller_id_name}" <${voicemail_caller_id_number}> ${voicemail_message_len}</title>
|
||||
<meta content="text/html; charset=iso-8859-1" http-equiv="content-type"/>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<font face=arial>
|
||||
<b>Message From "${voicemail_caller_id_name}" <A HREF="tel:${voicemail_caller_id_number}">${voicemail_caller_id_number}</A></b><br>
|
||||
<hr noshade size=1>
|
||||
Created: ${voicemail_time}<br>
|
||||
Duration: ${voicemail_message_len}<br>
|
||||
Account: ${voicemail_account}@${voicemail_domain}<br>
|
||||
</font>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
--000XXX000--
|
||||
@@ -0,0 +1,44 @@
|
||||
From: "${voicemail_caller_id_name}" <${voicemail_caller_id_number}@${voicemail_domain}>
|
||||
Date: ${RFC2822_DATE}
|
||||
To: <${voicemail_email}>
|
||||
Subject: Voicemail from "${voicemail_caller_id_name}" <${voicemail_caller_id_number}> ${voicemail_message_len}
|
||||
X-Priority: ${voicemail_priority}
|
||||
X-Mailer: FreeSWITCH
|
||||
|
||||
Content-Type: multipart/alternative;
|
||||
boundary="000XXX000"
|
||||
|
||||
--000XXX000
|
||||
Content-Type: text/plain; charset=ISO-8859-1; Format=Flowed
|
||||
Content-Disposition: inline
|
||||
Content-Transfer-Encoding: 7bit
|
||||
|
||||
Created: ${voicemail_time}
|
||||
From: "${voicemail_caller_id_name}" <${voicemail_caller_id_number}>
|
||||
Duration: ${voicemail_message_len}
|
||||
Account: ${voicemail_account}@${voicemail_domain}
|
||||
|
||||
--000XXX000
|
||||
Content-Type: text/html; charset=ISO-8859-1
|
||||
Content-Disposition: inline
|
||||
Content-Transfer-Encoding: 7bit
|
||||
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<META http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||
<title>Voicemail from "${voicemail_caller_id_name}" <${voicemail_caller_id_number}> ${voicemail_message_len}</title>
|
||||
<meta content="text/html; charset=iso-8859-1" http-equiv="content-type"/>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<font face=arial>
|
||||
<b>Message From "${voicemail_caller_id_name}" <A HREF="tel:${voicemail_caller_id_number}">${voicemail_caller_id_number}</A></b><br>
|
||||
<hr noshade size=1>
|
||||
Created: ${voicemail_time}<br>
|
||||
Duration: ${voicemail_message_len}<br>
|
||||
Account: ${voicemail_account}@${voicemail_domain}<br>
|
||||
</font>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
--000XXX000--
|
||||
@@ -1544,8 +1544,6 @@ static switch_status_t listen_file(switch_core_session_t *session, vm_profile_t
|
||||
char cid_buf[1024] = "";
|
||||
|
||||
if (switch_channel_ready(channel)) {
|
||||
const char *vm_announce_cid = NULL;
|
||||
|
||||
switch_snprintf(cid_buf, sizeof(cid_buf), "%s|%s", cbt->cid_number, cbt->cid_name);
|
||||
|
||||
msg.from = __FILE__;
|
||||
@@ -1556,10 +1554,8 @@ static switch_status_t listen_file(switch_core_session_t *session, vm_profile_t
|
||||
cid_buf, switch_channel_get_name(channel));
|
||||
switch_core_session_receive_message(session, &msg);
|
||||
|
||||
if (!zstr(cbt->cid_number) && (vm_announce_cid = switch_channel_get_variable(channel, "vm_announce_cid"))) {
|
||||
switch_ivr_play_file(session, NULL, vm_announce_cid, NULL);
|
||||
switch_ivr_sleep(session, 500, SWITCH_TRUE, NULL);
|
||||
switch_ivr_say(session, cbt->cid_number, NULL, "name_spelled", "pronounced", NULL, NULL);
|
||||
if (!zstr(cbt->cid_number) && (switch_true(switch_channel_get_variable(channel, "vm_announce_cid")))) {
|
||||
TRY_CODE(switch_ivr_phrase_macro(session, VM_SAY_PHONE_NUMBER_MACRO, cbt->cid_number, NULL, NULL));
|
||||
}
|
||||
|
||||
args.input_callback = cancel_on_dtmf;
|
||||
@@ -1865,6 +1861,7 @@ static void voicemail_check_main(switch_core_session_t *session, vm_profile_t *p
|
||||
const char *caller_id_name = NULL;
|
||||
const char *caller_id_number = NULL;
|
||||
int auth_only = 0, authed = 0;
|
||||
switch_event_t *event;
|
||||
|
||||
if (!(caller_id_name = switch_channel_get_variable(channel, "effective_caller_id_name"))) {
|
||||
caller_id_name = caller_profile->caller_id_name;
|
||||
@@ -2458,6 +2455,14 @@ static void voicemail_check_main(switch_core_session_t *session, vm_profile_t *p
|
||||
}
|
||||
}
|
||||
|
||||
switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, VM_EVENT_MAINT);
|
||||
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "VM-Action", "authentication");
|
||||
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "VM-Auth-Result", auth ? "success" : "fail");
|
||||
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "VM-User", myid);
|
||||
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "VM-Domain", domain_name);
|
||||
switch_channel_event_set_data(channel, event);
|
||||
switch_event_fire(&event);
|
||||
|
||||
FREE_DOMAIN_ROOT();
|
||||
|
||||
if (auth) {
|
||||
@@ -4378,7 +4383,7 @@ SWITCH_STANDARD_API(voicemail_inject_api_function)
|
||||
static int api_del_callback(void *pArg, int argc, char **argv, char **columnNames)
|
||||
{
|
||||
|
||||
unlink(argv[2]);
|
||||
unlink(argv[3]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,208 @@
|
||||
<configuration name="voicemail_ivr.conf" description="Voicemail IVR">
|
||||
<profiles>
|
||||
<profile name="default">
|
||||
<settings>
|
||||
<param name="IVR-Maximum-Attempts" value="3" />
|
||||
<param name="IVR-Entry-Timeout" value="3000" />
|
||||
<param name="Record-Format" value="wav" />
|
||||
<!--<param name="Record-Sample-Rate" value="8000" />-->
|
||||
<param name="Record-Silence-Hits" value="4" />
|
||||
<param name="Record-Silence-Threshold" value="200" />
|
||||
<param name="Record-Maximum-Length" value="30" />
|
||||
<!--<param name="Record-Minimum-Length" value="3" />-->
|
||||
<param name="Exit-Purge" value="true" />
|
||||
<param name="Password-Mask" value="XXX." />
|
||||
<param name="User-Mask" value="X." />
|
||||
|
||||
</settings>
|
||||
<apis>
|
||||
<api name="auth_login" value="vm_fsdb_auth_login" />
|
||||
<api name="msg_list" value="vm_fsdb_msg_list" />
|
||||
<api name="msg_count" value="vm_fsdb_msg_count" />
|
||||
<api name="msg_delete" value="vm_fsdb_msg_delete" />
|
||||
<api name="msg_undelete" value="vm_fsdb_msg_undelete" />
|
||||
<api name="msg_save" value="vm_fsdb_msg_save" />
|
||||
<api name="msg_purge" value="vm_fsdb_msg_purge" />
|
||||
<api name="msg_get" value="vm_fsdb_msg_get" />
|
||||
<api name="msg_forward" value="vm_fsdb_msg_forward" />
|
||||
<api name="pref_greeting_set" value="vm_fsdb_pref_greeting_set" />
|
||||
<api name="pref_recname_set" value="vm_fsdb_pref_recname_set" />
|
||||
<api name="pref_password_set" value="vm_fsdb_pref_password_set" />
|
||||
</apis>
|
||||
<menus>
|
||||
<menu name="std_authenticate">
|
||||
<phrases>
|
||||
<phrase name="fail_auth" value="fail_auth@voicemail_ivr" />
|
||||
</phrases>
|
||||
<keys>
|
||||
</keys>
|
||||
</menu>
|
||||
|
||||
<menu name="std_authenticate_ask_user">
|
||||
<phrases>
|
||||
<phrase name="instructions" value="enter_id@voicemail_ivr" />
|
||||
</phrases>
|
||||
<keys>
|
||||
<key dtmf="#" action="ivrengine:terminate_entry" variable="VM-Key-Terminator" />
|
||||
</keys>
|
||||
</menu>
|
||||
|
||||
<menu name="std_authenticate_ask_password">
|
||||
<phrases>
|
||||
<phrase name="instructions" value="enter_pass@voicemail_ivr" />
|
||||
</phrases>
|
||||
<keys>
|
||||
<key dtmf="#" action="ivrengine:terminate_entry" variable="VM-Key-Terminator" />
|
||||
</keys>
|
||||
</menu>
|
||||
|
||||
<menu name="std_main_menu">
|
||||
<phrases>
|
||||
<phrase name="msg_count" value="message_count@mtvoicemail" />
|
||||
<phrase name="say_date" value="say_date_event@mtvoicemail" />
|
||||
<phrase name="say_msg_number" value="say_message_number@mtvoicemail" />
|
||||
<phrase name="menu_options" value="menu@mtvoicemail" />
|
||||
</phrases>
|
||||
<keys>
|
||||
<key dtmf="1" action="new_msg:std_navigator" variable="VM-Key-Play-New-Messages" />
|
||||
<key dtmf="2" action="saved_msg:std_navigator" variable="VM-Key-Play-Saved-Messages" />
|
||||
<key dtmf="5" action="menu:std_preference" variable="VM-Key-Config-Menu"/>
|
||||
<key dtmf="#" action="return" variable="VM-Key-Terminator" />
|
||||
</keys>
|
||||
</menu>
|
||||
|
||||
<menu name="std_navigator">
|
||||
<settings>
|
||||
<!--<param name="Nav-Action-On-Delete" value="next_msg" />-->
|
||||
</settings>
|
||||
<phrases>
|
||||
<phrase name="msg_count" value="message_count@voicemail_ivr" />
|
||||
<phrase name="say_date" value="say_date_event@voicemail_ivr" />
|
||||
<phrase name="say_msg_number" value="say_message_number@voicemail_ivr" />
|
||||
<phrase name="menu_options" value="listen_file_check@voicemail_ivr" />
|
||||
<phrase name="ack" value="ack@voicemail_ivr" />
|
||||
<phrase name="play_message" value="play_message@voicemail_ivr" />
|
||||
</phrases>
|
||||
<keys>
|
||||
<key dtmf="1" action="skip_intro" variable="VM-Key-Main-Listen-File" />
|
||||
<key dtmf="6" action="next_msg" variable="VM-Key-Main-Next-Msg" />
|
||||
<key dtmf="4" action="prev_msg" />
|
||||
<key dtmf="7" action="delete_msg" variable="VM-Key-Main-Delete-File" /> <!-- Same key for undelete if it already deleted -->
|
||||
<key dtmf="8" action="menu:std_forward" variable="VM-Key-Main-Forward" />
|
||||
<key dtmf="3" action="save_msg" variable="VM-Key-Main-Save-File" />
|
||||
<key dtmf="2" action="callback" variable="VM-Key-Main-Callback" />
|
||||
<key dtmf="5" action="menu:std_preference" />
|
||||
<key dtmf="#" action="return" /> <!-- TODO Might Conflict with future fast-forward -->
|
||||
</keys>
|
||||
</menu>
|
||||
|
||||
<menu name="std_preference">
|
||||
<phrases>
|
||||
<phrase name="menu_options" value="config_menu@voicemail_ivr" />
|
||||
</phrases>
|
||||
<keys>
|
||||
<key dtmf="1" action="menu:std_record_greeting_with_slot" variable="VM-Key-Record-Greeting" />
|
||||
<key dtmf="2" action="menu:std_select_greeting_slot" variable="VM-Key-Choose-Greeting" />
|
||||
<key dtmf="3" action="menu:std_record_name" variable="VM-Key-Record-Name" />
|
||||
<key dtmf="6" action="menu:std_set_password" variable="VM-Key-Change-Password" />
|
||||
<key dtmf="#" action="return" variable="VM-Key-Main-Menu" />
|
||||
</keys>
|
||||
</menu>
|
||||
|
||||
<menu name="std_record_greeting">
|
||||
<phrases>
|
||||
<phrase name="instructions" value="record_greeting@voicemail_ivr" />
|
||||
<phrase name="play_recording" value="play_recording@voicemail_ivr" />
|
||||
<phrase name="menu_options" value="record_file_check@voicemail_ivr" />
|
||||
</phrases>
|
||||
<keys>
|
||||
<key dtmf="1" action="listen" variable="VM-Key-Listen-File" />
|
||||
<key dtmf="3" action="save" variable="VM-Key-Save-File" />
|
||||
<key dtmf="4" action="rerecord" variable="VM-Key-ReRecord-File" />
|
||||
<key dtmf="#" action="skip_instruction" />
|
||||
</keys>
|
||||
</menu>
|
||||
|
||||
|
||||
<menu name="std_record_name">
|
||||
<phrases>
|
||||
<phrase name="instructions" value="record_name@voicemail_ivr" />
|
||||
<phrase name="play_recording" value="play_recording@voicemail_ivr" />
|
||||
<phrase name="menu_options" value="record_file_check@voicemail_ivr" />
|
||||
</phrases>
|
||||
<keys>
|
||||
<key dtmf="1" action="listen" variable="VM-Key-Listen-File" />
|
||||
<key dtmf="3" action="save" variable="VM-Key-Save-File" />
|
||||
<key dtmf="4" action="rerecord" variable="VM-Key-ReRecord-File" />
|
||||
<key dtmf="#" action="skip_instruction" />
|
||||
</keys>
|
||||
</menu>
|
||||
|
||||
<menu name="std_record_message">
|
||||
<phrases>
|
||||
<phrase name="instructions" value="record_message@voicemail_ivr" />
|
||||
<phrase name="play_recording" value="play_recording@voicemail_ivr" />
|
||||
<phrase name="menu_options" value="record_file_check@voicemail_ivr" />
|
||||
</phrases>
|
||||
<keys>
|
||||
<key dtmf="1" action="listen" variable="VM-Key-Listen-File" />
|
||||
<key dtmf="3" action="save" variable="VM-Key-Save-File" />
|
||||
<key dtmf="4" action="rerecord" variable="VM-Key-ReRecord-File" />
|
||||
<key dtmf="#" action="skip_instruction" />
|
||||
</keys>
|
||||
</menu>
|
||||
|
||||
<menu name="std_forward_ask_prepend">
|
||||
<phrases>
|
||||
<phrase name="menu_options" value="forward_ask_prepend@voicemail_ivr" />
|
||||
</phrases>
|
||||
<keys>
|
||||
<key dtmf="1" action="prepend" variable="VM-Key-Prepend" />
|
||||
<key dtmf="8" action="forward" variable="VM-Key-Forward" />
|
||||
<key dtmf="#" action="return" variable="VM-Key-Return" />
|
||||
</keys>
|
||||
</menu>
|
||||
|
||||
<menu name="std_forward_ask_extension">
|
||||
<phrases>
|
||||
<phrase name="instructions" value="forward_ask_extension@voicemail_ivr" />
|
||||
<phrase name="ack" value="ack@voicemail_ivr" />
|
||||
<phrase name="invalid_extension" value="invalid_extension@voicemail_ivr" />
|
||||
</phrases>
|
||||
<keys>
|
||||
<key dtmf="#" action="ivrengine:terminate_entry" variable="VM-Key-Terminator" />
|
||||
</keys>
|
||||
</menu>
|
||||
|
||||
<menu name="std_select_greeting_slot">
|
||||
<phrases>
|
||||
<phrase name="instructions" value="choose_greeting@voicemail_ivr" />
|
||||
<phrase name="invalid_slot" value="choose_greeting_fail@voicemail_ivr" />
|
||||
<phrase name="selected_slot" value="greeting_selected@voicemail_ivr" />
|
||||
</phrases>
|
||||
<keys>
|
||||
</keys>
|
||||
</menu>
|
||||
|
||||
<menu name="std_record_greeting_with_slot">
|
||||
<phrases>
|
||||
<phrase name="instructions" value="choose_greeting@voicemail_ivr" />
|
||||
</phrases>
|
||||
<keys>
|
||||
</keys>
|
||||
</menu>
|
||||
|
||||
<menu name="std_set_password">
|
||||
<phrases>
|
||||
<phrase name="instructions" value="enter_pass@voicemail_ivr" />
|
||||
</phrases>
|
||||
<keys>
|
||||
<key dtmf="#" action="ivrengine:terminate_entry" variable="VM-Key-Terminator" />
|
||||
</keys>
|
||||
</menu>
|
||||
</menus>
|
||||
</profile>
|
||||
</profiles>
|
||||
</configuration>
|
||||
|
||||
|
||||
@@ -93,6 +93,11 @@ void menu_init(vmivr_profile_t *profile, vmivr_menu_t *menu) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!menu->phrase_params) {
|
||||
switch_event_create(&menu->phrase_params, SWITCH_EVENT_REQUEST_PARAMS);
|
||||
}
|
||||
|
||||
end:
|
||||
if (xml)
|
||||
switch_xml_free(xml);
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
<configuration name="cepstral.conf" description="Cepstral TTS configuration">
|
||||
<settings>
|
||||
<!--
|
||||
Possible encodings:
|
||||
* utf-8
|
||||
* us-ascii
|
||||
* iso8859-1 (default)
|
||||
* iso8859-15
|
||||
-->
|
||||
<param name="encoding" value="utf-8"/>
|
||||
</settings>
|
||||
</configuration>
|
||||
@@ -1,4 +1,4 @@
|
||||
FLITE=flite-1.5.1
|
||||
FLITE=flite-1.5.4
|
||||
|
||||
FLITE_DIR=$(switch_srcdir)/libs/$(FLITE)-current
|
||||
FLITE_BUILDDIR=$(switch_builddir)/libs/$(FLITE)-current
|
||||
@@ -6,6 +6,7 @@ FLITE_BUILDDIR=$(switch_builddir)/libs/$(FLITE)-current
|
||||
FLITE_LIBDIR=$(FLITE_BUILDDIR)/build/libs
|
||||
FLITE_A=$(FLITE_LIBDIR)/libflite_cmu_us_awb.a \
|
||||
$(FLITE_LIBDIR)/libflite_cmu_us_kal.a \
|
||||
$(FLITE_LIBDIR)/libflite_cmu_us_kal16.a \
|
||||
$(FLITE_LIBDIR)/libflite_cmu_us_rms.a \
|
||||
$(FLITE_LIBDIR)/libflite_cmu_us_slt.a \
|
||||
$(FLITE_LIBDIR)/libflite_cmulex.a $(FLITE_LIBDIR)/libflite_usenglish.a $(FLITE_LIBDIR)/libflite.a -lm
|
||||
|
||||
@@ -42,7 +42,7 @@
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
AdditionalIncludeDirectories="../../../../libs/flite-1.3.99/include"
|
||||
AdditionalIncludeDirectories="../../../../libs/flite-1.5.4/include"
|
||||
PreprocessorDefinitions="APT_LIB_EXPORT"
|
||||
UsePrecompiledHeader="0"
|
||||
/>
|
||||
@@ -108,7 +108,7 @@
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
AdditionalIncludeDirectories="../../../../libs/flite-1.3.99/include"
|
||||
AdditionalIncludeDirectories="../../../../libs/flite-1.5.4/include"
|
||||
PreprocessorDefinitions="APT_LIB_EXPORT"
|
||||
UsePrecompiledHeader="0"
|
||||
/>
|
||||
@@ -175,7 +175,7 @@
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
AdditionalIncludeDirectories="../../../../libs/flite-1.3.99/include"
|
||||
AdditionalIncludeDirectories="../../../../libs/flite-1.5.4/include"
|
||||
PreprocessorDefinitions="APT_LIB_EXPORT"
|
||||
UsePrecompiledHeader="0"
|
||||
/>
|
||||
@@ -241,7 +241,7 @@
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
AdditionalIncludeDirectories="../../../../libs/flite-1.3.99/include"
|
||||
AdditionalIncludeDirectories="../../../../libs/flite-1.5.4/include"
|
||||
PreprocessorDefinitions="APT_LIB_EXPORT"
|
||||
UsePrecompiledHeader="0"
|
||||
/>
|
||||
@@ -308,7 +308,7 @@
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
AdditionalIncludeDirectories="../../../../libs/flite-1.3.99/include"
|
||||
AdditionalIncludeDirectories="../../../../libs/flite-1.5.4/include"
|
||||
UsePrecompiledHeader="0"
|
||||
/>
|
||||
<Tool
|
||||
@@ -375,7 +375,7 @@
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
AdditionalIncludeDirectories="../../../../libs/flite-1.3.99/include"
|
||||
AdditionalIncludeDirectories="../../../../libs/flite-1.5.4/include"
|
||||
UsePrecompiledHeader="0"
|
||||
/>
|
||||
<Tool
|
||||
@@ -440,7 +440,7 @@
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
AdditionalIncludeDirectories="../../../../libs/flite-1.3.99/include"
|
||||
AdditionalIncludeDirectories="../../../../libs/flite-1.5.4/include"
|
||||
UsePrecompiledHeader="0"
|
||||
/>
|
||||
<Tool
|
||||
@@ -507,7 +507,7 @@
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
AdditionalIncludeDirectories="../../../../libs/flite-1.3.99/include"
|
||||
AdditionalIncludeDirectories="../../../../libs/flite-1.5.4/include"
|
||||
UsePrecompiledHeader="0"
|
||||
/>
|
||||
<Tool
|
||||
|
||||
@@ -120,7 +120,7 @@
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<AdditionalIncludeDirectories>../../../../libs/flite-1.3.99/include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>../../../../libs/flite-1.5.4/include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>APT_LIB_EXPORT;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
@@ -137,7 +137,7 @@
|
||||
<TargetEnvironment>X64</TargetEnvironment>
|
||||
</Midl>
|
||||
<ClCompile>
|
||||
<AdditionalIncludeDirectories>../../../../libs/flite-1.3.99/include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>../../../../libs/flite-1.5.4/include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>APT_LIB_EXPORT;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
@@ -152,7 +152,7 @@
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<AdditionalIncludeDirectories>../../../../libs/flite-1.3.99/include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>../../../../libs/flite-1.5.4/include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>APT_LIB_EXPORT;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
@@ -170,7 +170,7 @@
|
||||
<TargetEnvironment>X64</TargetEnvironment>
|
||||
</Midl>
|
||||
<ClCompile>
|
||||
<AdditionalIncludeDirectories>../../../../libs/flite-1.3.99/include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>../../../../libs/flite-1.5.4/include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>APT_LIB_EXPORT;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
@@ -186,7 +186,7 @@
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug Static|Win32'">
|
||||
<ClCompile>
|
||||
<AdditionalIncludeDirectories>../../../../libs/flite-1.3.99/include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>../../../../libs/flite-1.5.4/include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
@@ -203,7 +203,7 @@
|
||||
<TargetEnvironment>X64</TargetEnvironment>
|
||||
</Midl>
|
||||
<ClCompile>
|
||||
<AdditionalIncludeDirectories>../../../../libs/flite-1.3.99/include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>../../../../libs/flite-1.5.4/include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
@@ -218,7 +218,7 @@
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release Static|Win32'">
|
||||
<ClCompile>
|
||||
<AdditionalIncludeDirectories>../../../../libs/flite-1.3.99/include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>../../../../libs/flite-1.5.4/include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
@@ -235,7 +235,7 @@
|
||||
<TargetEnvironment>X64</TargetEnvironment>
|
||||
</Midl>
|
||||
<ClCompile>
|
||||
<AdditionalIncludeDirectories>../../../../libs/flite-1.3.99/include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>../../../../libs/flite-1.5.4/include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
@@ -258,7 +258,6 @@
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\..\..\libs\win32\flite\flite.2010.vcxproj">
|
||||
<Project>{0ad1177e-1fd8-4643-9391-431467a11084}</Project>
|
||||
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\..\..\w32\Library\FreeSwitchCore.2010.vcxproj">
|
||||
<Project>{202d7a4e-760d-4d0e-afa1-d7459ced30ff}</Project>
|
||||
|
||||
@@ -44,6 +44,10 @@ void unregister_cmu_us_rms(cst_voice * v);
|
||||
cst_voice *register_cmu_us_slt(void);
|
||||
void unregister_cmu_us_slt(cst_voice * v);
|
||||
|
||||
cst_voice *register_cmu_us_kal16(void);
|
||||
void unregister_cmu_us_kal16(cst_voice * v);
|
||||
|
||||
|
||||
SWITCH_MODULE_LOAD_FUNCTION(mod_flite_load);
|
||||
SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_flite_shutdown);
|
||||
SWITCH_MODULE_DEFINITION(mod_flite, mod_flite_load, mod_flite_shutdown, NULL);
|
||||
@@ -53,6 +57,7 @@ static struct {
|
||||
cst_voice *kal;
|
||||
cst_voice *rms;
|
||||
cst_voice *slt;
|
||||
cst_voice *kal16;
|
||||
} globals;
|
||||
|
||||
struct flite_data {
|
||||
@@ -75,13 +80,18 @@ static switch_status_t flite_speech_open(switch_speech_handle_t *sh, const char
|
||||
if (!strcasecmp(voice_name, "awb")) {
|
||||
flite->v = globals.awb;
|
||||
} else if (!strcasecmp(voice_name, "kal")) {
|
||||
flite->v = globals.kal;
|
||||
/* "kal" is 8kHz and the native rate is set to 16kHz
|
||||
* so kal talks a little bit too fast ...
|
||||
* for now: "symlink" kal to kal16
|
||||
*/ flite->v = globals.kal16;
|
||||
} else if (!strcasecmp(voice_name, "rms")) {
|
||||
flite->v = globals.rms;
|
||||
} else if (!strcasecmp(voice_name, "slt")) {
|
||||
flite->v = globals.slt;
|
||||
} else if (!strcasecmp(voice_name, "kal16")) {
|
||||
flite->v = globals.kal16;
|
||||
} else {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Valid voice names are awb, kal, rms or slt.\n");
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Valid voice names are awb, rms, slt or kal.\n");
|
||||
}
|
||||
|
||||
if (flite->v) {
|
||||
@@ -179,6 +189,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_flite_load)
|
||||
globals.kal = register_cmu_us_kal();
|
||||
globals.rms = register_cmu_us_rms();
|
||||
globals.slt = register_cmu_us_slt();
|
||||
globals.kal16 = register_cmu_us_kal16();
|
||||
|
||||
/* connect my internal structure to the blank pointer passed to me */
|
||||
*module_interface = switch_loadable_module_create_module_interface(pool, modname);
|
||||
@@ -203,6 +214,7 @@ SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_flite_shutdown)
|
||||
unregister_cmu_us_kal(globals.kal);
|
||||
unregister_cmu_us_rms(globals.rms);
|
||||
unregister_cmu_us_slt(globals.slt);
|
||||
unregister_cmu_us_kal16(globals.kal16);
|
||||
|
||||
return SWITCH_STATUS_UNLOAD;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
|
||||
* Copyright (C) 2005-2011, Anthony Minessale II <anthm@freeswitch.org>
|
||||
* Copyright (C) 2005-2012, Anthony Minessale II <anthm@freeswitch.org>
|
||||
*
|
||||
* Version: MPL 1.1
|
||||
*
|
||||
@@ -24,6 +24,7 @@
|
||||
* Contributor(s):
|
||||
*
|
||||
* Anthony Minessale II <anthm@freeswitch.org>
|
||||
* Chris Rienzo <chris@rienzo.net>
|
||||
*
|
||||
*
|
||||
* mod_speex.c -- Speex Codec Module
|
||||
@@ -279,10 +280,11 @@ static switch_status_t switch_speex_encode(switch_codec_t *codec,
|
||||
if (is_speech) {
|
||||
switch_clear_flag(context, SWITCH_CODEC_FLAG_SILENCE);
|
||||
*flag |= SWITCH_CODEC_FLAG_SILENCE_STOP;
|
||||
*flag &= ~SFF_CNG;
|
||||
} else {
|
||||
if (switch_test_flag(context, SWITCH_CODEC_FLAG_SILENCE)) {
|
||||
*encoded_data_len = 0;
|
||||
*flag |= SWITCH_CODEC_FLAG_SILENCE;
|
||||
*flag |= SWITCH_CODEC_FLAG_SILENCE | SFF_CNG;
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -353,6 +355,126 @@ static switch_status_t switch_speex_destroy(switch_codec_t *codec)
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* read default settings from speex.conf
|
||||
*/
|
||||
static void load_configuration()
|
||||
{
|
||||
switch_xml_t xml = NULL, cfg = NULL;
|
||||
|
||||
if ((xml = switch_xml_open_cfg("speex.conf", &cfg, NULL))) {
|
||||
switch_xml_t x_lists;
|
||||
if ((x_lists = switch_xml_child(cfg, "settings"))) {
|
||||
const char *settings_name = switch_xml_attr(x_lists, "name");
|
||||
switch_xml_t x_list;
|
||||
if (zstr(settings_name)) {
|
||||
settings_name = "";
|
||||
}
|
||||
for (x_list = switch_xml_child(x_lists, "param"); x_list; x_list = x_list->next) {
|
||||
const char *name = switch_xml_attr(x_list, "name");
|
||||
const char *value = switch_xml_attr(x_list, "value");
|
||||
if (zstr(name)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (zstr(value)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s %s = %s\n", settings_name, name, value);
|
||||
|
||||
if (!strcasecmp("quality", name)) {
|
||||
/* compression quality, integer 0-10 */
|
||||
int tmp = atoi(value);
|
||||
if (switch_is_number(value) && tmp >= 0 && tmp <= 10) {
|
||||
default_codec_settings.quality = tmp;
|
||||
} else {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "ignoring invalid quality value: %s\n", value);
|
||||
}
|
||||
} else if (!strcasecmp("complexity", name)) {
|
||||
/* compression complexity, integer 1-10 */
|
||||
int tmp = atoi(value);
|
||||
if (switch_is_number(value) && tmp >= 1 && tmp <= 10) {
|
||||
default_codec_settings.complexity = tmp;
|
||||
} else {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "ignoring invalid complexity value: %s\n", value);
|
||||
}
|
||||
} else if (!strcasecmp("enhancement", name)) {
|
||||
/* enable perceptual enhancement, boolean */
|
||||
default_codec_settings.enhancement = switch_true(value);
|
||||
} else if (!strcasecmp("vad", name)) {
|
||||
/* enable voice activity detection, boolean */
|
||||
default_codec_settings.vad = switch_true(value);
|
||||
} else if (!strcasecmp("vbr", name)) {
|
||||
/* enable variable bit rate, boolean */
|
||||
default_codec_settings.vbr = switch_true(value);
|
||||
} else if (!strcasecmp("vbr-quality", name)) {
|
||||
/* variable bit rate quality, float 0-10 */
|
||||
float tmp = atof(value);
|
||||
if (switch_is_number(value) && tmp >= 0 && tmp <= 10) {
|
||||
default_codec_settings.vbr_quality = tmp;
|
||||
} else {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "ignoring invalid vbr-quality value: %s\n", value);
|
||||
}
|
||||
} else if (!strcasecmp("abr", name)) {
|
||||
/* average bit rate, integer bits per sec */
|
||||
int tmp = atoi(value);
|
||||
if (switch_is_number(value) && tmp >= 0) {
|
||||
default_codec_settings.abr = tmp;
|
||||
} else {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "ignoring invalid abr value: %s\n", value);
|
||||
}
|
||||
} else if (!strcasecmp("dtx", name)) {
|
||||
/* discontinuous transmit, boolean */
|
||||
default_codec_settings.dtx = switch_true(value);
|
||||
} else if (!strcasecmp("preproc", name)) {
|
||||
/* enable preprocessor, boolean */
|
||||
default_codec_settings.preproc = switch_true(value);
|
||||
} else if (!strcasecmp("pp-vad", name)) {
|
||||
/* enable preprocessor VAD, boolean */
|
||||
default_codec_settings.pp_vad = switch_true(value);
|
||||
} else if (!strcasecmp("pp-agc", name)) {
|
||||
/* enable preprocessor automatic gain control, boolean */
|
||||
default_codec_settings.pp_agc = switch_true(value);
|
||||
} else if (!strcasecmp("pp-agc-level", name)) {
|
||||
/* agc level, float */
|
||||
float tmp = atof(value);
|
||||
if (switch_is_number(value) && tmp >= 0.0f) {
|
||||
default_codec_settings.pp_agc_level = tmp;
|
||||
} else {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "ignoring invalid pp-agc-level value: %s\n", value);
|
||||
}
|
||||
} else if (!strcasecmp("pp-denoise", name)) {
|
||||
/* enable preprocessor denoiser, boolean */
|
||||
default_codec_settings.pp_denoise = switch_true(value);
|
||||
} else if (!strcasecmp("pp-dereverb", name)) {
|
||||
/* enable preprocessor reverberation removal, boolean */
|
||||
default_codec_settings.pp_dereverb = switch_true(value);
|
||||
} else if (!strcasecmp("pp-dereverb-decay", name)) {
|
||||
/* reverberation removal decay, float */
|
||||
float tmp = atof(value);
|
||||
if (switch_is_number(value) && tmp >= 0.0f) {
|
||||
default_codec_settings.pp_dereverb_decay = tmp;
|
||||
} else {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "ignoring invalid pp-dereverb-decay value: %s\n", value);
|
||||
}
|
||||
} else if (!strcasecmp("pp-dereverb-level", name)) {
|
||||
/* reverberation removal level, float */
|
||||
float tmp = atof(value);
|
||||
if (switch_is_number(value) && tmp >= 0.0f) {
|
||||
default_codec_settings.pp_dereverb_level = tmp;
|
||||
} else {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "ignoring invalid pp-dereverb-level value: %s\n", value);
|
||||
}
|
||||
} else {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "ignoring invalid unknown param: %s = %s\n", name, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
switch_xml_free(xml);
|
||||
}
|
||||
}
|
||||
|
||||
SWITCH_MODULE_LOAD_FUNCTION(mod_speex_load)
|
||||
{
|
||||
switch_codec_interface_t *codec_interface;
|
||||
@@ -361,6 +483,9 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_speex_load)
|
||||
int bps[4] = { 0, 24600, 42200, 44000 };
|
||||
/* connect my internal structure to the blank pointer passed to me */
|
||||
*module_interface = switch_loadable_module_create_module_interface(pool, modname);
|
||||
|
||||
load_configuration();
|
||||
|
||||
SWITCH_ADD_CODEC(codec_interface, "Speex");
|
||||
codec_interface->parse_fmtp = switch_speex_fmtp_parse;
|
||||
for (counta = 1; counta <= 3; counta++) {
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
[default]
|
||||
|
||||
; Things you're used to....
|
||||
exten => music,n,Dial(SIP/1234@conference.freeswitch.org|120)
|
||||
|
||||
exten => _1XXXXX,n,set(cool=${EXTEN})
|
||||
exten => _1XXXXX,n,set(myvar=true)
|
||||
exten => _1XXXXX,n,Goto(default|music)
|
||||
exten => 2137991400/1000,n,Goto(default|music)
|
||||
|
||||
|
||||
; Some new magic you can do....
|
||||
exten => ~^(18(0{2}|8{2}|7{2}|6{2})\d{7})$,n,enum($1)
|
||||
exten => ~^(18(0{2}|8{2}|7{2}|6{2})\d{7})$,n,bridge(${enum_auto_route})
|
||||
|
||||
; instead of exten, put anything about the call you would rather match on.
|
||||
; either the names of a field in caller_profile or a string of variables to expand.
|
||||
caller_id_number => 2137991400,n,Goto(default|music)
|
||||
${sip_from_user} => bill,n,Goto(default|music)
|
||||
|
||||
|
||||
@@ -143,6 +143,7 @@ static int parse_exten(switch_core_session_t *session, switch_caller_profile_t *
|
||||
"Dialplan: %s Date/Time Match (PASS) [%s] break=%s\n",
|
||||
switch_channel_get_name(channel), exten_name, do_break_a ? do_break_a : "on-false");
|
||||
anti_action = SWITCH_FALSE;
|
||||
proceed = 1;
|
||||
} else if (time_match == 0) {
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG_CLEAN(session), SWITCH_LOG_DEBUG,
|
||||
"Dialplan: %s Date/TimeMatch (FAIL) [%s] break=%s\n",
|
||||
@@ -189,7 +190,7 @@ static int parse_exten(switch_core_session_t *session, switch_caller_profile_t *
|
||||
total++;
|
||||
|
||||
field = (char *) switch_xml_attr(xregex, "field");
|
||||
|
||||
|
||||
if (field) {
|
||||
if (strchr(field, '$')) {
|
||||
if ((field_expanded = switch_channel_expand_variables(channel, field)) == field) {
|
||||
@@ -222,9 +223,11 @@ static int parse_exten(switch_core_session_t *session, switch_caller_profile_t *
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG_CLEAN(session), SWITCH_LOG_DEBUG,
|
||||
"Dialplan: %s Absolute Condition [%s] match=%s\n", switch_channel_get_name(channel), exten_name, all ? "all" : "any");
|
||||
pass++;
|
||||
proceed = 1;
|
||||
if (!all && !xor) break;
|
||||
} else if (time_match == 1) {
|
||||
pass++;
|
||||
proceed = 1;
|
||||
if (!all && !xor) break;
|
||||
}
|
||||
|
||||
@@ -310,6 +313,7 @@ static int parse_exten(switch_core_session_t *session, switch_caller_profile_t *
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG_CLEAN(session), SWITCH_LOG_DEBUG,
|
||||
"Dialplan: %s Absolute Condition [%s]\n", switch_channel_get_name(channel), exten_name);
|
||||
anti_action = SWITCH_FALSE;
|
||||
proceed = 1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
<configuration name="alsa.conf" description="Soundcard Endpoint">
|
||||
<settings>
|
||||
<!--Default dialplan and caller-id info -->
|
||||
<param name="dialplan" value="XML"/>
|
||||
<param name="cid-name" value="N800 Alsa"/>
|
||||
<param name="cid-num" value="5555551212"/>
|
||||
|
||||
<!--audio sample rate and interval -->
|
||||
<param name="sample-rate" value="8000"/>
|
||||
<param name="codec-ms" value="20"/>
|
||||
</settings>
|
||||
</configuration>
|
||||
@@ -1,4 +1,3 @@
|
||||
!/gsmlib/gsmlib-*/aclocal.m4
|
||||
!/gsmlib/gsmlib-*/configure
|
||||
!/gsmlib/gsmlib-1.10.tar.gz
|
||||
!/gsmlib/gsmlib_1.10-12ubuntu1.diff.gz
|
||||
!/gsmlib/gsmlib_1.10.orig.tar.gz
|
||||
|
||||
@@ -68,7 +68,7 @@
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>..\..\..\..\..\ptlib\include;..\..\..\..\..\h323plus\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;MOD_EXPORTS;ALLOW_SMP_DANGERS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
@@ -77,7 +77,7 @@
|
||||
<Link>
|
||||
<AdditionalOptions>/NODEFAULTLIB:LIMBCTD %(AdditionalOptions)</AdditionalOptions>
|
||||
<AdditionalDependencies>h323plusd.lib;ptlibsd.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<AdditionalLibraryDirectories>..\..\..\..\..\ptlib\lib;..\..\..\..\..\h323plus\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<RandomizedBaseAddress>false</RandomizedBaseAddress>
|
||||
<DataExecutionPrevention>
|
||||
</DataExecutionPrevention>
|
||||
@@ -85,7 +85,7 @@
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>..\..\..\..\..\ptlib\include;..\..\..\..\..\h323plus\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;MOD_EXPORTS;ALLOW_SMP_DANGERS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
@@ -94,7 +94,7 @@
|
||||
<Link>
|
||||
<AdditionalOptions>/NODEFAULTLIB:LIMBCTD %(AdditionalOptions)</AdditionalOptions>
|
||||
<AdditionalDependencies>h323plusd.lib;ptlibsd.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<AdditionalLibraryDirectories>..\..\..\..\..\ptlib\lib\x64;..\..\..\..\..\h323plus\lib\x64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<RandomizedBaseAddress>false</RandomizedBaseAddress>
|
||||
<DataExecutionPrevention>
|
||||
</DataExecutionPrevention>
|
||||
@@ -102,7 +102,7 @@
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>..\..\..\..\..\ptlib\include;..\..\..\..\..\h323plus\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>WIN32;_WINDOWS;_USRDLL;MOD_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
@@ -110,7 +110,7 @@
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>h323plus.lib;ptlibs.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<AdditionalLibraryDirectories>..\..\..\..\..\ptlib\lib;..\..\..\..\..\h323plus\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<GenerateDebugInformation>false</GenerateDebugInformation>
|
||||
<RandomizedBaseAddress>false</RandomizedBaseAddress>
|
||||
<DataExecutionPrevention>
|
||||
@@ -119,7 +119,7 @@
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>..\..\..\..\..\ptlib\include;..\..\..\..\..\h323plus\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>WIN32;_WINDOWS;_USRDLL;MOD_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
@@ -127,11 +127,12 @@
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>h323plus.lib;ptlibs.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<AdditionalLibraryDirectories>..\..\..\..\..\ptlib\lib\x64;..\..\..\..\..\h323plus\lib\x64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<GenerateDebugInformation>false</GenerateDebugInformation>
|
||||
<RandomizedBaseAddress>false</RandomizedBaseAddress>
|
||||
<DataExecutionPrevention>
|
||||
</DataExecutionPrevention>
|
||||
<PerUserRedirection>false</PerUserRedirection>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
|
||||
@@ -0,0 +1,218 @@
|
||||
<configuration name="portaudio.conf" description="Soundcard Endpoint">
|
||||
<settings>
|
||||
<!-- indev, outdev, ringdev:
|
||||
partial case sensitive string match on something in the name
|
||||
or the device number prefixed with # eg "#1" (or blank for default) -->
|
||||
|
||||
<!-- device to use for input -->
|
||||
<param name="indev" value=""/>
|
||||
<!-- device to use for output -->
|
||||
<param name="outdev" value=""/>
|
||||
|
||||
<!--device to use for inbound ring -->
|
||||
<!--<param name="ringdev" value=""/>-->
|
||||
<!--File to play as the ring sound -->
|
||||
<!--<param name="ring-file" value="/sounds/ring.wav"/>-->
|
||||
<!--Number of seconds to pause between rings -->
|
||||
<!--<param name="ring-interval" value="5"/>-->
|
||||
<!--Enable or Disable dual_streams-->
|
||||
<!--<param name="dual-streams" value="true"/>-->
|
||||
|
||||
<!--file to play when calls are on hold-->
|
||||
<param name="hold-file" value="$${hold_music}"/>
|
||||
<!--Timer to use for hold music (i'd leave this one commented)-->
|
||||
<!--<param name="timer-name" value="soft"/>-->
|
||||
|
||||
<!--Default dialplan and caller-id info -->
|
||||
<param name="dialplan" value="XML"/>
|
||||
<param name="cid-name" value="$${outbound_caller_name}"/>
|
||||
<param name="cid-num" value="$${outbound_caller_id}"/>
|
||||
|
||||
<!--audio sample rate and interval -->
|
||||
<param name="sample-rate" value="48000"/>
|
||||
<param name="codec-ms" value="20"/>
|
||||
</settings>
|
||||
|
||||
<!--
|
||||
mod_portaudio "streams"
|
||||
|
||||
The portaudio streams were introduced to support multiple devices and multiple channels in mod_portaudio.
|
||||
For example, if you have a sound card that supports multiple channels or have multiple sound cards and you
|
||||
want to use them at the same time, you can do it configuring streams and endpoints here.
|
||||
|
||||
A "stream" is just a logical container for some settings required by portaudio in order to stream audio and
|
||||
define a friendly name for that configuration. Streams in itself do not do anything else than contain configs.
|
||||
Once you have your streams defined you can proceed to define "endpoints". Go to the "<endpoints>" section
|
||||
for more information on endpoints.
|
||||
|
||||
You can use the command "pa shstreams" (portaudio shared streams) to show the configured streams.
|
||||
-->
|
||||
<streams>
|
||||
<!--
|
||||
In this example we define 2 streams, one for a usb audio device and another for the usual Mac defaults
|
||||
The name="" attribute in the <stream> tag must uniquely identify the stream configuration and can be
|
||||
later used when creating endpoints in the "instream" and "outstream" parameters of the endpoint.
|
||||
-->
|
||||
|
||||
<!-- This sample "usb1" configuration was tested with a USB Griffin iMic device -->
|
||||
<stream name="usb1">
|
||||
<!--
|
||||
Which device to use for input in this stream
|
||||
The value for this parameter must be either in the form '#devno',
|
||||
for example '#2' for device number 2, or 'device-name', like 'iMic USB audio system'
|
||||
The output of command "pa devlist" will show you device names and numbers as enumerated
|
||||
by portaudio.
|
||||
-->
|
||||
<param name="indev" value="#2" />
|
||||
|
||||
<!--
|
||||
Same as the indev but for output. In this case the device is capable of input and output
|
||||
Some devices are capable of input only or output only (see the default example)
|
||||
-->
|
||||
<param name="outdev" value="#2" />
|
||||
|
||||
<!-- The sample rate to use for this stream -->
|
||||
<param name="sample-rate" value="48000" />
|
||||
|
||||
<!--
|
||||
Size of the packets in milliseconds. The smaller the number the less latency you'll have
|
||||
The minimum value is 10ms
|
||||
-->
|
||||
<param name="codec-ms" value="10" />
|
||||
|
||||
<!--
|
||||
How many channels to open for this stream.
|
||||
If you're device is stereo, you can choose 2 here. However, bear in mind that then
|
||||
your left and right channels will be separated and when creating endpoints you will have
|
||||
to either choose the left or right channel. This may or may not be what you want. This separation
|
||||
means that you can have 2 separate FreeSWITCH calls, listening to one of them in your left channel
|
||||
and the other in the right chanel.
|
||||
-->
|
||||
<param name="channels" value="2" />
|
||||
</stream>
|
||||
|
||||
<!-- This default stream was tested using the default Macbook Pro input/output devices -->
|
||||
<stream name="default">
|
||||
<!-- The default system input device -->
|
||||
<param name="indev" value="#0" />
|
||||
<!-- The default system output device -->
|
||||
<param name="outdev" value="#1" />
|
||||
<!-- CD quality sampling rate ftw -->
|
||||
<param name="sample-rate" value="48000" />
|
||||
<!-- Low latency -->
|
||||
<param name="codec-ms" value="10" />
|
||||
<!-- Choosing 1 channel allows to hear in both left-right channel when using a headset -->
|
||||
<param name="channels" value="1" />
|
||||
</stream>
|
||||
</streams>
|
||||
|
||||
<!--
|
||||
mod_portaudio "endpoints"
|
||||
|
||||
Endpoints is a way to define the input and output that a given portaudio channel will use.
|
||||
There is a lot of flexibility. You can create endpoints which are "send-only", which means
|
||||
audio will be read from FreeSWITCH and sent down to the provided stream, but no audio will
|
||||
be read from that stream and only silence provided back to FreeSWITCH.
|
||||
|
||||
send-only endpoint:
|
||||
(FS CORE) ->-> audio ->-> sound-card-x
|
||||
|
||||
You can also create a read-only endpoint.
|
||||
|
||||
read-only-endpoint:
|
||||
(FS CORE) <-<- audio <-<- sound-card-x
|
||||
|
||||
And of course you can create a bidirectional endpoint:
|
||||
bidirectional-endpoint:
|
||||
(FS CORE) <-> audio <-> sound-card-x
|
||||
|
||||
You can also define a stream which uses only the left or only the right channel of a given device stream.
|
||||
This means you can have 2 SIP calls connected to the same device haring one call in your left ear and
|
||||
the other call to your right ear :-)
|
||||
|
||||
The name="parameter" of the endpoint allows you to use it in the FreeSWITCH dial plan to dial, ie:
|
||||
|
||||
<action application="bridge" data="portaudio/endpoint/usb1out-left" />
|
||||
|
||||
You can use the command "pa endpoints" to show the configured endpoints.
|
||||
-->
|
||||
<endpoints>
|
||||
|
||||
<!--
|
||||
An endpoint is a handle name to refer to a configuration that determines where to read media from
|
||||
and write media to. The endpoint can use any input/output stream combination for that purpose as
|
||||
long as the streams match the sampling rate and codec-ms (see <streams> XML tag).
|
||||
You can also omit the instream or the outstream parameter (but obviously not both).
|
||||
-->
|
||||
|
||||
<!--
|
||||
Configuration for a "default" bidirectional endpoint that uses the default stream defined previously in
|
||||
the <streams> section.
|
||||
-->
|
||||
<endpoint name="default">
|
||||
<!--
|
||||
The instream, outstream is the name of the stream and channel to use. The stream
|
||||
name is the same you configured in the <streams> section. This parameters follow
|
||||
the syntax <stream-name>:<channel index>. You can omit either the outstream
|
||||
or the instream, but not both! The channel index is zero-based and must be consistent
|
||||
with the number of channels available for that stream (as configured in the <stream> section).
|
||||
You cannot use index 1 if you chose channels=1 in the stream configuration.
|
||||
-->
|
||||
<param name="instream" value="default:0" />
|
||||
<param name="outstream" value="default:0" />
|
||||
</endpoint>
|
||||
|
||||
<!--
|
||||
This endpoint uses the USB stream defined previously in the <streams> section and
|
||||
is 'send-only' or 'output-only' and uses the channel index 0 (left channel in a stereo device)
|
||||
-->
|
||||
<endpoint name="usb1out-left">
|
||||
<param name="outstream" value="usb1:0" />
|
||||
</endpoint>
|
||||
|
||||
<!--
|
||||
This endpoint uses the USB stream defined previously in the <streams> section and
|
||||
is 'send-only' or 'output-only' and uses the channel index 1 (right channel in a stereo device)
|
||||
-->
|
||||
<endpoint name="usb1out-right">
|
||||
<param name="outstream" value="usb1:1" />
|
||||
</endpoint>
|
||||
|
||||
<!--
|
||||
This endpoint uses the USB stream defined previously in the <streams> section and
|
||||
is 'receive-only' or 'input-only' and uses the channel index 0 (left channel in a stereo device)
|
||||
-->
|
||||
<endpoint name="usb1in-left">
|
||||
<param name="instream" value="usb1:0" />
|
||||
</endpoint>
|
||||
|
||||
<!--
|
||||
This endpoint uses the USB stream defined previously in the <streams> section and
|
||||
is 'receive-only' or 'input-only' and uses the channel index 1 (right channel in a stereo device)
|
||||
-->
|
||||
<endpoint name="usb1in-right">
|
||||
<param name="instream" value="usb1:1" />
|
||||
</endpoint>
|
||||
|
||||
<!--
|
||||
This endpoint uses the USB stream defined previously in the <streams> section and
|
||||
is 'bidirectional' or 'send-receive' and uses the channel index 0 (left channel in a stereo device)
|
||||
-->
|
||||
<endpoint name="usb1-left">
|
||||
<param name="instream" value="usb1:0" />
|
||||
<param name="outstream" value="usb1:0" />
|
||||
</endpoint>
|
||||
|
||||
<!--
|
||||
This endpoint uses the USB stream defined previously in the <streams> section and
|
||||
is 'bidirectional' or 'send-receive' and uses the channel index 1 (right channel in a stereo device)
|
||||
-->
|
||||
<endpoint name="usb1-right">
|
||||
<param name="instream" value="usb1:1" />
|
||||
<param name="outstream" value="usb1:1" />
|
||||
</endpoint>
|
||||
|
||||
</endpoints>
|
||||
|
||||
</configuration>
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
<configuration name="rtmp.conf" description="RTMP Endpoint">
|
||||
<profiles>
|
||||
<profile name="default">
|
||||
<settings>
|
||||
<param name="bind-address" value="0.0.0.0:1935" />
|
||||
<param name="context" value="public" />
|
||||
<param name="dialplan" value="XML" />
|
||||
<!-- If this is set to true, no unauthenticated inbound calls will be allowed -->
|
||||
<param name="auth-calls" value="true" />
|
||||
<!-- How much time should the clients buffer the media stream (miliseconds) -->
|
||||
<param name="buffer-len" value="50" />
|
||||
<!-- Sets the maximum size of outbound RTMP chunks -->
|
||||
<param name="chunksize" value="512" />
|
||||
</settings>
|
||||
</profile>
|
||||
</profiles>
|
||||
</configuration>
|
||||
@@ -843,7 +843,7 @@ switch_call_cause_t rtmp_session_create_call(rtmp_session_t *rsession, switch_co
|
||||
switch_channel_t *channel;
|
||||
const char *dialplan, *context;
|
||||
|
||||
if (!(*newsession = switch_core_session_request(rtmp_globals.rtmp_endpoint_interface, SOF_NONE, SWITCH_CALL_DIRECTION_INBOUND, NULL))) {
|
||||
if (!(*newsession = switch_core_session_request(rtmp_globals.rtmp_endpoint_interface, SWITCH_CALL_DIRECTION_INBOUND, SOF_NONE, NULL))) {
|
||||
return SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER;
|
||||
}
|
||||
|
||||
|
||||
@@ -886,6 +886,11 @@ switch_status_t rtmp_handle_data(rtmp_session_t *rsession)
|
||||
if (rsession->tech_pvt) {
|
||||
uint16_t len = state->origlen;
|
||||
|
||||
if (!rsession->tech_pvt->readbuf) {
|
||||
return SWITCH_STATUS_FALSE;
|
||||
}
|
||||
|
||||
|
||||
switch_mutex_lock(rsession->tech_pvt->readbuf_mutex);
|
||||
if (rsession->tech_pvt->maxlen && switch_buffer_inuse(rsession->tech_pvt->readbuf) > rsession->tech_pvt->maxlen * 40) {
|
||||
rsession->tech_pvt->over_size++;
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
<configuration name="skinny.conf" description="Skinny Endpoints">
|
||||
<profiles>
|
||||
<X-PRE-PROCESS cmd="include" data="../skinny_profiles/*.xml"/>
|
||||
</profiles>
|
||||
</configuration>
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
NOTICE:
|
||||
|
||||
This context is used for skinny to match dialed number
|
||||
|
||||
The special applications:
|
||||
- skinny-process tells skinny to process the call (route, set call forwarding, ...)
|
||||
- skinny-drop tells skinny to drop the call
|
||||
- skinny-wait tells skinny to wait 'data' seconds for more numbers before drop
|
||||
-->
|
||||
<!-- http://wiki.freeswitch.org/wiki/Mod_skinny -->
|
||||
<include>
|
||||
<context name="skinny-patterns">
|
||||
<!--
|
||||
Wait 10 seconds for another digit by default
|
||||
-->
|
||||
<extension name="Default">
|
||||
<condition>
|
||||
<action application="skinny-wait" data="10"/>
|
||||
</condition>
|
||||
</extension>
|
||||
|
||||
<!--
|
||||
You can place files in the skinny-patterns directory to get included.
|
||||
-->
|
||||
<X-PRE-PROCESS cmd="include" data="skinny-patterns/*.xml"/>
|
||||
|
||||
</context>
|
||||
</include>
|
||||
@@ -0,0 +1,8 @@
|
||||
<include>
|
||||
<extension name="Demo">
|
||||
<condition field="destination_number" expression="^(9[0-9]{3})$">
|
||||
<action application="skinny-process"/>
|
||||
</condition>
|
||||
</extension>
|
||||
</include>
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
<include>
|
||||
<extension name="Local_Extension">
|
||||
<condition field="destination_number" expression="^(10[01][0-9])$">
|
||||
<action application="skinny-process"/>
|
||||
</condition>
|
||||
</extension>
|
||||
<extension name="Local_Extension_Skinny">
|
||||
<condition field="destination_number" expression="^(11[01][0-9])$">
|
||||
<action application="skinny-process"/>
|
||||
</condition>
|
||||
</extension>
|
||||
</include>
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
<include>
|
||||
<extension name="External">
|
||||
<condition field="destination_number" expression="^(0[0-9]{10,})$">
|
||||
<action application="skinny-process"/>
|
||||
</condition>
|
||||
</extension>
|
||||
</include>
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
<include>
|
||||
<!-- drop long dialed number -->
|
||||
<extension name="Default_Drop">
|
||||
<condition field="destination_number" expression="^(.{14,})$">
|
||||
<action application="skinny-drop"/>
|
||||
</condition>
|
||||
</extension>
|
||||
</include>
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
<include>
|
||||
<user id="SEP001120AABBCC">
|
||||
<params>
|
||||
<!-- for devices requesting firmware via SCCP, like ATA186
|
||||
<param name="skinny-firmware-version" value="ATA030101SCCP04"
|
||||
<param name="skinny-soft-key-set-set" value="default"
|
||||
-->
|
||||
<param name="foo" value="bar"/>
|
||||
</params>
|
||||
<skinny>
|
||||
<buttons>
|
||||
<!--
|
||||
position: 1..
|
||||
type: one of line, speed-dial
|
||||
label: button label
|
||||
-->
|
||||
<!--
|
||||
value is the directory number (or user)
|
||||
caller-name is shown to the calling party during call
|
||||
-->
|
||||
<button position="1" type="Line" label="Line 1" value="1101" caller-name="Calling as 1101"/>
|
||||
<button position="3" type="Line" label="Shared Line 10" value="1110" caller-name="Calling as 1110"/>
|
||||
<!--
|
||||
value is the directory number to call
|
||||
-->
|
||||
<button position="5" type="SpeedDial" label="Call 1001" value="1001"/>
|
||||
<!--
|
||||
value is the URL
|
||||
-->
|
||||
<button position="6" type="ServiceUrl" label="Some URL" value="http://phone-xml.berbee.com/menu.xml"/>
|
||||
</buttons>
|
||||
</skinny>
|
||||
</user>
|
||||
</include>
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
<profile name="internal">
|
||||
<settings>
|
||||
<param name="domain" value="$${domain}"/>
|
||||
<param name="ip" value="$${local_ip_v4}"/>
|
||||
<param name="port" value="2000"/>
|
||||
<param name="patterns-dialplan" value="XML"/>
|
||||
<param name="patterns-context" value="skinny-patterns"/>
|
||||
<param name="dialplan" value="XML"/>
|
||||
<param name="context" value="default"/>
|
||||
<param name="keep-alive" value="60"/>
|
||||
<param name="date-format" value="D/M/Y"/>
|
||||
<param name="odbc-dsn" value=""/>
|
||||
<param name="debug" value="4"/>
|
||||
<param name="auto-restart" value="true"/>
|
||||
</settings>
|
||||
<soft-key-set-sets>
|
||||
<soft-key-set-set name="default">
|
||||
<soft-key-set name="KeySetOnHook" value="SoftkeyNewcall,SoftkeyRedial"/>
|
||||
<soft-key-set name="KeySetConnected" value="SoftkeyEndcall,SoftkeyHold,SoftkeyNewcall,SoftkeyTransfer"/>
|
||||
<soft-key-set name="KeySetOnHold" value="SoftkeyNewcall,SoftkeyResume,SoftkeyEndcall"/>
|
||||
<soft-key-set name="KeySetRingIn" value="SoftkeyAnswer,SoftkeyEndcall,SoftkeyNewcall"/>
|
||||
<soft-key-set name="KeySetOffHook" value=",SoftkeyRedial,SoftkeyEndcall"/>
|
||||
<soft-key-set name="KeySetConnectedWithTransfer" value="SoftkeyEndcall,SoftkeyHold,SoftkeyNewcall,SoftkeyTransfer"/>
|
||||
<soft-key-set name="KeySetDigitsAfterDialingFirstDigit" value="SoftkeyBackspace,,SoftkeyEndcall"/>
|
||||
<!-- <soft-key-set name="KeySetConnectedWithConference" value=""/> -->
|
||||
<soft-key-set name="KeySetRingOut" value=",,SoftkeyEndcall,SoftkeyTransfer"/>
|
||||
<soft-key-set name="KeySetOffHookWithFeatures" value=",SoftkeyRedial,SoftkeyEndcall"/>
|
||||
<soft-key-set name="KeySetInUseHint" value="SoftkeyNewcall,SoftkeyRedial"/>
|
||||
</soft-key-set-set>
|
||||
</soft-key-set-sets>
|
||||
<device-types>
|
||||
<device-type id="Cisco ATA 186">
|
||||
<param name="firmware-version" value="ATA030101SCCP04"/>
|
||||
</device-type>
|
||||
</device-types>
|
||||
</profile>
|
||||
|
||||
@@ -6,4 +6,3 @@ tricks and tweaks, possible problems at:
|
||||
http://wiki.freeswitch.org/wiki/Mod_skypopen_Skype_Endpoint_and_Trunk
|
||||
|
||||
< gmaruzz at gmail dot com >
|
||||
|
||||
|
||||
@@ -5,10 +5,18 @@
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectName>mod_skypopen</ProjectName>
|
||||
@@ -21,10 +29,18 @@
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
@@ -32,10 +48,18 @@
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
<Import Project="..\..\..\..\w32\module_release.props" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
<Import Project="..\..\..\..\w32\module_release.props" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
<Import Project="..\..\..\..\w32\module_debug.props" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
<Import Project="..\..\..\..\w32\module_debug.props" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup>
|
||||
<_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
|
||||
@@ -55,6 +79,21 @@
|
||||
</DataExecutionPrevention>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<AdditionalIncludeDirectories>%(RootDir)%(Directory)..\..\..\..\libs\spandsp\src\msvc;%(RootDir)%(Directory)..\..\..\..\libs\spandsp\src;%(RootDir)%(Directory)..\..\..\..\libs\tiff-3.8.2\libtiff;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
<TreatWarningAsError>false</TreatWarningAsError>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalOptions>rpcrt4.lib "..\..\..\..\libs\spandsp\src\x64\Debug\libtiff.lib" "..\..\..\..\x64\Debug\libspandsp.lib" %(AdditionalOptions)</AdditionalOptions>
|
||||
<RandomizedBaseAddress>false</RandomizedBaseAddress>
|
||||
<DataExecutionPrevention>
|
||||
</DataExecutionPrevention>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<AdditionalIncludeDirectories>%(RootDir)%(Directory)..\..\..\..\libs\spandsp\src\msvc;%(RootDir)%(Directory)..\..\..\..\libs\spandsp\src;%(RootDir)%(Directory)..\..\..\..\libs\tiff-3.8.2\libtiff;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
@@ -68,6 +107,19 @@
|
||||
</DataExecutionPrevention>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<AdditionalIncludeDirectories>%(RootDir)%(Directory)..\..\..\..\libs\spandsp\src\msvc;%(RootDir)%(Directory)..\..\..\..\libs\spandsp\src;%(RootDir)%(Directory)..\..\..\..\libs\tiff-3.8.2\libtiff;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalOptions>rpcrt4.lib "..\..\..\..\libs\spandsp\src\x64\Release\libtiff.lib" "..\..\..\..\x64\Release\libspandsp.lib" %(AdditionalOptions)</AdditionalOptions>
|
||||
<RandomizedBaseAddress>false</RandomizedBaseAddress>
|
||||
<DataExecutionPrevention>
|
||||
</DataExecutionPrevention>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="mod_skypopen.c" />
|
||||
<ClCompile Include="skypopen_protocol.c" />
|
||||
|
||||
@@ -1329,7 +1329,7 @@ LRESULT APIENTRY skypopen_present(HWND hWindow, UINT uiMessage, WPARAM uiParam,
|
||||
|
||||
lReturnCode = 0;
|
||||
fIssueDefProc = 0;
|
||||
tech_pvt = (private_t *) GetWindowLong(hWindow, GWL_USERDATA);
|
||||
tech_pvt = (private_t *) GetWindowLong(hWindow, GWLP_USERDATA);
|
||||
|
||||
if (!running) {
|
||||
DEBUGA_SKYPE("let's DIE!\n", SKYPOPEN_P_LOG);
|
||||
@@ -1340,7 +1340,7 @@ LRESULT APIENTRY skypopen_present(HWND hWindow, UINT uiMessage, WPARAM uiParam,
|
||||
switch (uiMessage) {
|
||||
case WM_CREATE:
|
||||
tech_pvt = (private_t *) ((LPCREATESTRUCT) ulParam)->lpCreateParams;
|
||||
SetWindowLong(hWindow, GWL_USERDATA, (LONG) tech_pvt);
|
||||
SetWindowLong(hWindow, GWLP_USERDATA, (LONG) tech_pvt);
|
||||
DEBUGA_SKYPE("got CREATE\n", SKYPOPEN_P_LOG);
|
||||
break;
|
||||
case WM_DESTROY:
|
||||
|
||||
@@ -0,0 +1,95 @@
|
||||
<profile name="external">
|
||||
<!-- http://wiki.freeswitch.org/wiki/Sofia_Configuration_Files -->
|
||||
<!-- This profile is only for outbound registrations to providers -->
|
||||
<gateways>
|
||||
<X-PRE-PROCESS cmd="include" data="external/*.xml"/>
|
||||
</gateways>
|
||||
|
||||
<aliases>
|
||||
<!--
|
||||
<alias name="outbound"/>
|
||||
<alias name="nat"/>
|
||||
-->
|
||||
</aliases>
|
||||
|
||||
<domains>
|
||||
<domain name="all" alias="false" parse="true"/>
|
||||
</domains>
|
||||
|
||||
<settings>
|
||||
<param name="debug" value="0"/>
|
||||
<!-- If you want FreeSWITCH to shutdown if this profile fails to load, uncomment the next line. -->
|
||||
<!-- <param name="shutdown-on-fail" value="true"/> -->
|
||||
<param name="sip-trace" value="no"/>
|
||||
<param name="sip-capture" value="no"/>
|
||||
<param name="rfc2833-pt" value="101"/>
|
||||
<!-- RFC 5626 : Send reg-id and sip.instance -->
|
||||
<!--<param name="enable-rfc-5626" value="true"/> -->
|
||||
<param name="sip-port" value="$${external_sip_port}"/>
|
||||
<param name="dialplan" value="XML"/>
|
||||
<param name="context" value="public"/>
|
||||
<param name="dtmf-duration" value="2000"/>
|
||||
<param name="inbound-codec-prefs" value="$${global_codec_prefs}"/>
|
||||
<param name="outbound-codec-prefs" value="$${outbound_codec_prefs}"/>
|
||||
<param name="hold-music" value="$${hold_music}"/>
|
||||
<param name="rtp-timer-name" value="soft"/>
|
||||
<!--<param name="enable-100rel" value="true"/>-->
|
||||
<!--<param name="disable-srv503" value="true"/>-->
|
||||
<!-- This could be set to "passive" -->
|
||||
<param name="local-network-acl" value="localnet.auto"/>
|
||||
<param name="manage-presence" value="false"/>
|
||||
|
||||
<!-- used to share presence info across sofia profiles
|
||||
manage-presence needs to be set to passive on this profile
|
||||
if you want it to behave as if it were the internal profile
|
||||
for presence.
|
||||
-->
|
||||
<!-- Name of the db to use for this profile -->
|
||||
<!--<param name="dbname" value="share_presence"/>-->
|
||||
<!--<param name="presence-hosts" value="$${domain}"/>-->
|
||||
<!--<param name="force-register-domain" value="$${domain}"/>-->
|
||||
<!--all inbound reg will stored in the db using this domain -->
|
||||
<!--<param name="force-register-db-domain" value="$${domain}"/>-->
|
||||
<!-- ************************************************* -->
|
||||
|
||||
<!--<param name="aggressive-nat-detection" value="true"/>-->
|
||||
<param name="inbound-codec-negotiation" value="generous"/>
|
||||
<param name="nonce-ttl" value="60"/>
|
||||
<param name="auth-calls" value="false"/>
|
||||
<!--
|
||||
DO NOT USE HOSTNAMES, ONLY IP ADDRESSES IN THESE SETTINGS!
|
||||
-->
|
||||
<param name="rtp-ip" value="$${local_ip_v4}"/>
|
||||
<param name="sip-ip" value="$${local_ip_v4}"/>
|
||||
<param name="ext-rtp-ip" value="auto-nat"/>
|
||||
<param name="ext-sip-ip" value="auto-nat"/>
|
||||
<param name="rtp-timeout-sec" value="300"/>
|
||||
<param name="rtp-hold-timeout-sec" value="1800"/>
|
||||
<!--<param name="enable-3pcc" value="true"/>-->
|
||||
|
||||
<!-- TLS: disabled by default, set to "true" to enable -->
|
||||
<param name="tls" value="$${external_ssl_enable}"/>
|
||||
<!-- Set to true to not bind on the normal sip-port but only on the TLS port -->
|
||||
<param name="tls-only" value="false"/>
|
||||
<!-- additional bind parameters for TLS -->
|
||||
<param name="tls-bind-params" value="transport=tls"/>
|
||||
<!-- Port to listen on for TLS requests. (5081 will be used if unspecified) -->
|
||||
<param name="tls-sip-port" value="$${external_tls_port}"/>
|
||||
<!-- Location of the agent.pem and cafile.pem ssl certificates (needed for TLS server) -->
|
||||
<param name="tls-cert-dir" value="$${external_ssl_dir}"/>
|
||||
<!-- Optionally set the passphrase password used by openSSL to encrypt/decrypt TLS private key files -->
|
||||
<param name="tls-passphrase" value=""/>
|
||||
<!-- Verify the date on TLS certificates -->
|
||||
<param name="tls-verify-date" value="true"/>
|
||||
<!-- TLS verify policy, when registering/inviting gateways with other servers (outbound) or handling inbound registration/invite requests how should we verify their certificate -->
|
||||
<!-- set to 'in' to only verify incoming connections, 'out' to only verify outgoing connections, 'all' to verify all connections, also 'in_subjects', 'out_subjects' and 'all_subjects' for subject validation. Multiple policies can be split with a '|' pipe -->
|
||||
<param name="tls-verify-policy" value="none"/>
|
||||
<!-- Certificate max verify depth to use for validating peer TLS certificates when the verify policy is not none -->
|
||||
<param name="tls-verify-depth" value="2"/>
|
||||
<!-- If the tls-verify-policy is set to subjects_all or subjects_in this sets which subjects are allowed, multiple subjects can be split with a '|' pipe -->
|
||||
<param name="tls-verify-in-subjects" value=""/>
|
||||
<!-- TLS version ("sslv23" (default), "tlsv1"). NOTE: Phones may not work with TLSv1 -->
|
||||
<param name="tls-version" value="$${sip_tls_version}"/>
|
||||
|
||||
</settings>
|
||||
</profile>
|
||||
@@ -0,0 +1,38 @@
|
||||
<include>
|
||||
<!--<gateway name="asterlink.com">-->
|
||||
<!--/// account username *required* ///-->
|
||||
<!--<param name="username" value="cluecon"/>-->
|
||||
<!--/// auth realm: *optional* same as gateway name, if blank ///-->
|
||||
<!--<param name="realm" value="asterlink.com"/>-->
|
||||
<!--/// username to use in from: *optional* same as username, if blank ///-->
|
||||
<!--<param name="from-user" value="cluecon"/>-->
|
||||
<!--/// domain to use in from: *optional* same as realm, if blank ///-->
|
||||
<!--<param name="from-domain" value="asterlink.com"/>-->
|
||||
<!--/// account password *required* ///-->
|
||||
<!--<param name="password" value="2007"/>-->
|
||||
<!--/// extension for inbound calls: *optional* same as username, if blank ///-->
|
||||
<!--<param name="extension" value="cluecon"/>-->
|
||||
<!--/// proxy host: *optional* same as realm, if blank ///-->
|
||||
<!--<param name="proxy" value="asterlink.com"/>-->
|
||||
<!--/// send register to this proxy: *optional* same as proxy, if blank ///-->
|
||||
<!--<param name="register-proxy" value="mysbc.com"/>-->
|
||||
<!--/// expire in seconds: *optional* 3600, if blank ///-->
|
||||
<!--<param name="expire-seconds" value="60"/>-->
|
||||
<!--/// do not register ///-->
|
||||
<!--<param name="register" value="false"/>-->
|
||||
<!-- which transport to use for register -->
|
||||
<!--<param name="register-transport" value="udp"/>-->
|
||||
<!--How many seconds before a retry when a failure or timeout occurs -->
|
||||
<!--<param name="retry-seconds" value="30"/>-->
|
||||
<!--Use the callerid of an inbound call in the from field on outbound calls via this gateway -->
|
||||
<!--<param name="caller-id-in-from" value="false"/>-->
|
||||
<!--extra sip params to send in the contact-->
|
||||
<!--<param name="contact-params" value="tport=tcp"/>-->
|
||||
<!--send an options ping every x seconds, failure will unregister and/or mark it down-->
|
||||
<!--<param name="ping" value="25"/>-->
|
||||
<!--</gateway>-->
|
||||
<!--rfc5626 : Abilitazione rfc5626 ///-->
|
||||
<!--<param name="rfc-5626" value="true"/>-->
|
||||
<!--rfc5626 : extra sip params to send in the contact-->
|
||||
<!--<param name="reg-id" value="1"/>-->
|
||||
</include>
|
||||
@@ -0,0 +1,130 @@
|
||||
<profile name="internal-ipv6">
|
||||
<!--
|
||||
This is an example of a sofia profile setup to listen on IPv6.
|
||||
-->
|
||||
<!-- http://wiki.freeswitch.org/wiki/Sofia_Configuration_Files -->
|
||||
<!--aliases are other names that will work as a valid profile name for this profile-->
|
||||
<settings>
|
||||
<!-- <param name="user-agent-string" value="FreeSWITCH Rocks!"/> -->
|
||||
<param name="debug" value="0"/>
|
||||
<param name="sip-trace" value="no"/>
|
||||
<param name="context" value="public"/>
|
||||
<param name="rfc2833-pt" value="101"/>
|
||||
<!-- port to bind to for sip traffic -->
|
||||
<param name="sip-port" value="$${internal_sip_port}"/>
|
||||
<param name="dialplan" value="XML"/>
|
||||
<param name="dtmf-duration" value="2000"/>
|
||||
<param name="inbound-codec-prefs" value="$${global_codec_prefs}"/>
|
||||
<param name="outbound-codec-prefs" value="$${global_codec_prefs}"/>
|
||||
<param name="use-rtp-timer" value="true"/>
|
||||
<param name="rtp-timer-name" value="soft"/>
|
||||
<!-- ip address to use for rtp -->
|
||||
<param name="rtp-ip" value="$${local_ip_v6}"/>
|
||||
<!-- ip address to bind to -->
|
||||
<param name="sip-ip" value="$${local_ip_v6}"/>
|
||||
<param name="hold-music" value="$${hold_music}"/>
|
||||
<!--<param name="enable-100rel" value="false"/>-->
|
||||
<!--<param name="disable-srv503" value="true"/>-->
|
||||
<param name="apply-inbound-acl" value="domains"/>
|
||||
<!--<param name="apply-register-acl" value="domains"/>-->
|
||||
<!--<param name="dtmf-type" value="info"/>-->
|
||||
<param name="record-template" value="$${recordings_dir}/${caller_id_number}.${strftime(%Y-%m-%d-%H-%M-%S)}.wav"/>
|
||||
<!--enable to use presence and mwi -->
|
||||
<param name="manage-presence" value="true"/>
|
||||
<!-- This setting is for AAL2 bitpacking on G726 -->
|
||||
<!-- <param name="bitpacking" value="aal2"/> -->
|
||||
<!--max number of open dialogs in proceeding -->
|
||||
<!--<param name="max-proceeding" value="1000"/>-->
|
||||
<!--session timers for all call to expire after the specified seconds -->
|
||||
<!--<param name="session-timeout" value="1800"/>-->
|
||||
<!--<param name="multiple-registrations" value="true"/>-->
|
||||
<!--set to 'greedy' if you want your codec list to take precedence -->
|
||||
<param name="inbound-codec-negotiation" value="generous"/>
|
||||
<!-- if you want to send any special bind params of your own -->
|
||||
<!--<param name="bind-params" value="transport=udp"/>-->
|
||||
<!--<param name="unregister-on-options-fail" value="true"/>-->
|
||||
|
||||
<!-- TLS: disabled by default, set to "true" to enable -->
|
||||
<param name="tls" value="$${internal_ssl_enable}"/>
|
||||
<!-- additional bind parameters for TLS -->
|
||||
<param name="tls-bind-params" value="transport=tls"/>
|
||||
<!-- Port to listen on for TLS requests. (5061 will be used if unspecified) -->
|
||||
<param name="tls-sip-port" value="$${internal_tls_port}"/>
|
||||
<!-- Location of the agent.pem and cafile.pem ssl certificates (needed for TLS server) -->
|
||||
<param name="tls-cert-dir" value="$${internal_ssl_dir}"/>
|
||||
<!-- TLS version ("sslv23" (default), "tlsv1"). NOTE: Phones may not work with TLSv1 -->
|
||||
<param name="tls-version" value="$${sip_tls_version}"/>
|
||||
|
||||
<!--If you don't want to pass through timestampes from 1 RTP call to another (on a per call basis with rtp_rewrite_timestamps chanvar)-->
|
||||
<!--<param name="rtp-rewrite-timestamps" value="true"/>-->
|
||||
<!--<param name="pass-rfc2833" value="true"/>-->
|
||||
<!--If you have ODBC support and a working dsn you can use it instead of SQLite-->
|
||||
<!--<param name="odbc-dsn" value="dsn:user:pass"/>-->
|
||||
|
||||
<!--Uncomment to set all inbound calls to no media mode-->
|
||||
<!--<param name="inbound-bypass-media" value="true"/>-->
|
||||
|
||||
<!--Uncomment to set all inbound calls to proxy media mode-->
|
||||
<!--<param name="inbound-proxy-media" value="true"/>-->
|
||||
|
||||
<!--Uncomment to let calls hit the dialplan *before* you decide if the codec is ok-->
|
||||
<!--<param name="inbound-late-negotiation" value="true"/>-->
|
||||
|
||||
<!-- this lets anything register -->
|
||||
<!-- comment the next line and uncomment one or both of the other 2 lines for call authentication -->
|
||||
<!-- <param name="accept-blind-reg" value="true"/> -->
|
||||
|
||||
<!-- accept any authentication without actually checking (not a good feature for most people) -->
|
||||
<!-- <param name="accept-blind-auth" value="true"/> -->
|
||||
|
||||
<!-- suppress CNG on this profile or per call with the 'suppress_cng' variable -->
|
||||
<!-- <param name="suppress-cng" value="true"/> -->
|
||||
|
||||
<!--TTL for nonce in sip auth-->
|
||||
<param name="nonce-ttl" value="60"/>
|
||||
<!--Uncomment if you want to force the outbound leg of a bridge to only offer the codec
|
||||
that the originator is using-->
|
||||
<!--<param name="disable-transcoding" value="true"/>-->
|
||||
<!-- Used for when phones respond to a challenged ACK with method INVITE in the hash -->
|
||||
<!--<param name="NDLB-broken-auth-hash" value="true"/>-->
|
||||
<!-- add a ;received="<ip>:<port>" to the contact when replying to register for nat handling -->
|
||||
<!--<param name="NDLB-received-in-nat-reg-contact" value="true"/>-->
|
||||
<param name="auth-calls" value="$${internal_auth_calls}"/>
|
||||
<!-- on authed calls, authenticate *all* the packets not just invite -->
|
||||
<param name="auth-all-packets" value="false"/>
|
||||
<!-- <param name="ext-rtp-ip" value="$${external_rtp_ip}"/> -->
|
||||
<!-- <param name="ext-sip-ip" value="$${external_sip_ip}"/> -->
|
||||
<!-- rtp inactivity timeout -->
|
||||
<param name="rtp-timeout-sec" value="300"/>
|
||||
<param name="rtp-hold-timeout-sec" value="1800"/>
|
||||
<!-- VAD choose one (out is a good choice); -->
|
||||
<!-- <param name="vad" value="in"/> -->
|
||||
<!-- <param name="vad" value="out"/> -->
|
||||
<!-- <param name="vad" value="both"/> -->
|
||||
<!--<param name="alias" value="sip:10.0.1.251:5555"/>-->
|
||||
<!--
|
||||
These are enabled to make the default config work better out of the box.
|
||||
If you need more than ONE domain you'll need to not use these options.
|
||||
|
||||
-->
|
||||
<!--all inbound reg will look in this domain for the users -->
|
||||
<param name="force-register-domain" value="$${domain}"/>
|
||||
<!--all inbound reg will stored in the db using this domain -->
|
||||
<param name="force-register-db-domain" value="$${domain}"/>
|
||||
<!-- disable register and transfer which may be undesirable in a public switch -->
|
||||
<!--<param name="disable-transfer" value="true"/>-->
|
||||
<!--<param name="disable-register" value="true"/>-->
|
||||
<!--<param name="enable-3pcc" value="true"/>-->
|
||||
<!-- use stun when specified (default is true) -->
|
||||
<!--<param name="stun-enabled" value="true"/>-->
|
||||
<!-- use stun when specified (default is true) -->
|
||||
<!-- set to true to have the profile determine stun is not useful and turn it off globally-->
|
||||
<!--<param name="stun-auto-disable" value="true"/>-->
|
||||
|
||||
<!-- the following can be used as workaround with bogus SRV/NAPTR records -->
|
||||
<!--<param name="disable-srv" value="false" />-->
|
||||
<!--<param name="disable-naptr" value="false" />-->
|
||||
|
||||
</settings>
|
||||
</profile>
|
||||
|
||||
@@ -0,0 +1,385 @@
|
||||
<profile name="internal">
|
||||
<!--
|
||||
This is a sofia sip profile/user agent. This will service exactly one ip and port.
|
||||
In FreeSWITCH you can run multiple sip user agents on their own ip and port.
|
||||
|
||||
When you hear someone say "sofia profile" this is what they are talking about.
|
||||
-->
|
||||
|
||||
<!-- http://wiki.freeswitch.org/wiki/Sofia_Configuration_Files -->
|
||||
<!--aliases are other names that will work as a valid profile name for this profile-->
|
||||
<aliases>
|
||||
<!--
|
||||
<alias name="default"/>
|
||||
-->
|
||||
</aliases>
|
||||
<!-- Outbound Registrations -->
|
||||
<gateways>
|
||||
<X-PRE-PROCESS cmd="include" data="internal/*.xml"/>
|
||||
</gateways>
|
||||
|
||||
<domains>
|
||||
<!-- indicator to parse the directory for domains with parse="true" to get gateways-->
|
||||
<!--<domain name="$${domain}" parse="true"/>-->
|
||||
<!-- indicator to parse the directory for domains with parse="true" to get gateways and alias every domain to this profile -->
|
||||
<!--<domain name="all" alias="true" parse="true"/>-->
|
||||
<domain name="all" alias="true" parse="false"/>
|
||||
</domains>
|
||||
|
||||
<settings>
|
||||
<!--
|
||||
When calls are in no media this will bring them back to media
|
||||
when you press the hold button.
|
||||
-->
|
||||
<!--<param name="media-option" value="resume-media-on-hold"/> -->
|
||||
<!--
|
||||
This will allow a call after an attended transfer go back to
|
||||
bypass media after an attended transfer.
|
||||
-->
|
||||
<!--<param name="media-option" value="bypass-media-after-att-xfer"/>-->
|
||||
<!-- <param name="user-agent-string" value="FreeSWITCH Rocks!"/> -->
|
||||
<param name="debug" value="0"/>
|
||||
<!-- If you want FreeSWITCH to shutdown if this profile fails to load, uncomment the next line. -->
|
||||
<!-- <param name="shutdown-on-fail" value="true"/> -->
|
||||
<param name="sip-trace" value="no"/>
|
||||
<param name="sip-capture" value="no"/>
|
||||
|
||||
<!-- Use presence_map.conf.xml to convert extension regex to presence protos for routing -->
|
||||
<!-- <param name="presence-proto-lookup" value="true"/> -->
|
||||
|
||||
|
||||
<!-- Don't be picky about negotiated DTMF just always offer 2833 and accept both 2833 and INFO -->
|
||||
<!--<param name="liberal-dtmf" value="true"/>-->
|
||||
|
||||
|
||||
<!--
|
||||
Sometimes, in extremely rare edge cases, the Sofia SIP stack may stop
|
||||
responding. These options allow you to enable and control a watchdog
|
||||
on the Sofia SIP stack so that if it stops responding for the
|
||||
specified number of milliseconds, it will cause FreeSWITCH to crash
|
||||
immediately. This is useful if you run in an HA environment and
|
||||
need to ensure automated recovery from such a condition. Note that if
|
||||
your server is idle a lot, the watchdog may fire due to not receiving
|
||||
any SIP messages. Thus, if you expect your system to be idle, you
|
||||
should leave the watchdog disabled. It can be toggled on and off
|
||||
through the FreeSWITCH CLI either on an individual profile basis or
|
||||
globally for all profiles. So, if you run in an HA environment with a
|
||||
master and slave, you should use the CLI to make sure the watchdog is
|
||||
only enabled on the master.
|
||||
If such crash occurs, FreeSWITCH will dump core if allowed. The
|
||||
stacktrace will include function watchdog_triggered_abort().
|
||||
-->
|
||||
<param name="watchdog-enabled" value="no"/>
|
||||
<param name="watchdog-step-timeout" value="30000"/>
|
||||
<param name="watchdog-event-timeout" value="30000"/>
|
||||
|
||||
<param name="log-auth-failures" value="false"/>
|
||||
<param name="forward-unsolicited-mwi-notify" value="false"/>
|
||||
|
||||
<param name="context" value="public"/>
|
||||
<param name="rfc2833-pt" value="101"/>
|
||||
<!-- port to bind to for sip traffic -->
|
||||
<param name="sip-port" value="$${internal_sip_port}"/>
|
||||
<param name="dialplan" value="XML"/>
|
||||
<param name="dtmf-duration" value="2000"/>
|
||||
<param name="inbound-codec-prefs" value="$${global_codec_prefs}"/>
|
||||
<param name="outbound-codec-prefs" value="$${global_codec_prefs}"/>
|
||||
<param name="rtp-timer-name" value="soft"/>
|
||||
<!-- ip address to use for rtp, DO NOT USE HOSTNAMES ONLY IP ADDRESSES -->
|
||||
<param name="rtp-ip" value="$${local_ip_v4}"/>
|
||||
<!-- ip address to bind to, DO NOT USE HOSTNAMES ONLY IP ADDRESSES -->
|
||||
<param name="sip-ip" value="$${local_ip_v4}"/>
|
||||
<param name="hold-music" value="$${hold_music}"/>
|
||||
<param name="apply-nat-acl" value="nat.auto"/>
|
||||
|
||||
|
||||
<!-- (default true) set to false if you do not wish to have called party info in 1XX responses -->
|
||||
<!-- <param name="cid-in-1xx" value="false"/> -->
|
||||
|
||||
<!-- extended info parsing -->
|
||||
<!-- <param name="extended-info-parsing" value="true"/> -->
|
||||
|
||||
<!--<param name="aggressive-nat-detection" value="true"/>-->
|
||||
<!--
|
||||
There are known issues (asserts and segfaults) when 100rel is enabled.
|
||||
It is not recommended to enable 100rel at this time.
|
||||
-->
|
||||
<!--<param name="enable-100rel" value="true"/>-->
|
||||
|
||||
<!-- uncomment if you don't wish to try a next SRV destination on 503 response -->
|
||||
<!-- RFC3263 Section 4.3 -->
|
||||
<!--<param name="disable-srv503" value="true"/>-->
|
||||
|
||||
<!-- Enable Compact SIP headers. -->
|
||||
<!--<param name="enable-compact-headers" value="true"/>-->
|
||||
<!--
|
||||
enable/disable session timers
|
||||
-->
|
||||
<!--<param name="enable-timer" value="false"/>-->
|
||||
<!--<param name="minimum-session-expires" value="120"/>-->
|
||||
<param name="apply-inbound-acl" value="domains"/>
|
||||
<!--
|
||||
This defines your local network, by default we detect your local network
|
||||
and create this localnet.auto ACL for this.
|
||||
-->
|
||||
<param name="local-network-acl" value="localnet.auto"/>
|
||||
<!--<param name="apply-register-acl" value="domains"/>-->
|
||||
<!--<param name="dtmf-type" value="info"/>-->
|
||||
|
||||
|
||||
<!-- 'true' means every time 'first-only' means on the first register -->
|
||||
<!--<param name="send-message-query-on-register" value="true"/>-->
|
||||
|
||||
<!-- 'true' means every time 'first-only' means on the first register -->
|
||||
<!--<param name="send-presence-on-register" value="first-only"/> -->
|
||||
|
||||
|
||||
<!-- Caller-ID type (choose one, can be overridden by inbound call type and/or sip_cid_type channel variable -->
|
||||
<!-- Remote-Party-ID header -->
|
||||
<!--<param name="caller-id-type" value="rpid"/>-->
|
||||
|
||||
<!-- P-*-Identity family of headers -->
|
||||
<!--<param name="caller-id-type" value="pid"/>-->
|
||||
|
||||
<!-- neither one -->
|
||||
<!--<param name="caller-id-type" value="none"/>-->
|
||||
|
||||
|
||||
|
||||
<param name="record-path" value="$${recordings_dir}"/>
|
||||
<param name="record-template" value="${caller_id_number}.${target_domain}.${strftime(%Y-%m-%d-%H-%M-%S)}.wav"/>
|
||||
<!--enable to use presence -->
|
||||
<param name="manage-presence" value="true"/>
|
||||
<!-- send a presence probe on each register to query devices to send presence instead of sending presence with less info -->
|
||||
<!--<param name="presence-probe-on-register" value="true"/>-->
|
||||
<!--<param name="manage-shared-appearance" value="true"/>-->
|
||||
<!-- used to share presence info across sofia profiles -->
|
||||
<!-- Name of the db to use for this profile -->
|
||||
<!--<param name="dbname" value="share_presence"/>-->
|
||||
<param name="presence-hosts" value="$${domain},$${local_ip_v4}"/>
|
||||
<param name="presence-privacy" value="$${presence_privacy}"/>
|
||||
<!-- ************************************************* -->
|
||||
|
||||
<!-- This setting is for AAL2 bitpacking on G726 -->
|
||||
<!-- <param name="bitpacking" value="aal2"/> -->
|
||||
<!--max number of open dialogs in proceeding -->
|
||||
<!--<param name="max-proceeding" value="1000"/>-->
|
||||
<!--session timers for all call to expire after the specified seconds -->
|
||||
<!--<param name="session-timeout" value="1800"/>-->
|
||||
<!-- Can be 'true' or 'contact' -->
|
||||
<!--<param name="multiple-registrations" value="contact"/>-->
|
||||
<!--set to 'greedy' if you want your codec list to take precedence -->
|
||||
<param name="inbound-codec-negotiation" value="generous"/>
|
||||
<!-- if you want to send any special bind params of your own -->
|
||||
<!--<param name="bind-params" value="transport=udp"/>-->
|
||||
<!--<param name="unregister-on-options-fail" value="true"/>-->
|
||||
|
||||
<!-- TLS: disabled by default, set to "true" to enable -->
|
||||
<param name="tls" value="$${internal_ssl_enable}"/>
|
||||
<!-- Set to true to not bind on the normal sip-port but only on the TLS port -->
|
||||
<param name="tls-only" value="false"/>
|
||||
<!-- additional bind parameters for TLS -->
|
||||
<param name="tls-bind-params" value="transport=tls"/>
|
||||
<!-- Port to listen on for TLS requests. (5061 will be used if unspecified) -->
|
||||
<param name="tls-sip-port" value="$${internal_tls_port}"/>
|
||||
<!-- Location of the agent.pem and cafile.pem ssl certificates (needed for TLS server) -->
|
||||
<param name="tls-cert-dir" value="$${internal_ssl_dir}"/>
|
||||
<!-- Optionally set the passphrase password used by openSSL to encrypt/decrypt TLS private key files -->
|
||||
<param name="tls-passphrase" value=""/>
|
||||
<!-- Verify the date on TLS certificates -->
|
||||
<param name="tls-verify-date" value="true"/>
|
||||
<!-- TLS verify policy, when registering/inviting gateways with other servers (outbound) or handling inbound registration/invite requests how should we verify their certificate -->
|
||||
<!-- set to 'in' to only verify incoming connections, 'out' to only verify outgoing connections, 'all' to verify all connections, also 'in_subjects', 'out_subjects' and 'all_subjects' for subject validation. Multiple policies can be split with a '|' pipe -->
|
||||
<param name="tls-verify-policy" value="none"/>
|
||||
<!-- Certificate max verify depth to use for validating peer TLS certificates when the verify policy is not none -->
|
||||
<param name="tls-verify-depth" value="2"/>
|
||||
<!-- If the tls-verify-policy is set to subjects_all or subjects_in this sets which subjects are allowed, multiple subjects can be split with a '|' pipe -->
|
||||
<param name="tls-verify-in-subjects" value=""/>
|
||||
<!-- TLS version ("sslv23" (default), "tlsv1"). NOTE: Phones may not work with TLSv1 -->
|
||||
<param name="tls-version" value="$${sip_tls_version}"/>
|
||||
|
||||
<!-- turn on auto-flush during bridge (skip timer sleep when the socket already has data)
|
||||
(reduces delay on latent connections default true, must be disabled explicitly)-->
|
||||
<!--<param name="rtp-autoflush-during-bridge" value="false"/>-->
|
||||
|
||||
<!--If you don't want to pass through timestamps from 1 RTP call to another (on a per call basis with rtp_rewrite_timestamps chanvar)-->
|
||||
<!--<param name="rtp-rewrite-timestamps" value="true"/>-->
|
||||
<!--<param name="pass-rfc2833" value="true"/>-->
|
||||
<!--If you have ODBC support and a working dsn you can use it instead of SQLite-->
|
||||
<!--<param name="odbc-dsn" value="dsn:user:pass"/>-->
|
||||
|
||||
<!--Uncomment to set all inbound calls to no media mode-->
|
||||
<!--<param name="inbound-bypass-media" value="true"/>-->
|
||||
|
||||
<!--Uncomment to set all inbound calls to proxy media mode-->
|
||||
<!--<param name="inbound-proxy-media" value="true"/>-->
|
||||
|
||||
<!--Uncomment to let calls hit the dialplan *before* you decide if the codec is ok-->
|
||||
<!--<param name="inbound-late-negotiation" value="true"/>-->
|
||||
|
||||
<!-- this lets anything register -->
|
||||
<!-- comment the next line and uncomment one or both of the other 2 lines for call authentication -->
|
||||
<!-- <param name="accept-blind-reg" value="true"/> -->
|
||||
|
||||
<!-- accept any authentication without actually checking (not a good feature for most people) -->
|
||||
<!-- <param name="accept-blind-auth" value="true"/> -->
|
||||
|
||||
<!-- suppress CNG on this profile or per call with the 'suppress_cng' variable -->
|
||||
<!-- <param name="suppress-cng" value="true"/> -->
|
||||
|
||||
<!--TTL for nonce in sip auth-->
|
||||
<param name="nonce-ttl" value="60"/>
|
||||
<!--Uncomment if you want to force the outbound leg of a bridge to only offer the codec
|
||||
that the originator is using-->
|
||||
<!--<param name="disable-transcoding" value="true"/>-->
|
||||
<!-- Handle 302 Redirect in the dialplan -->
|
||||
<!--<param name="manual-redirect" value="true"/> -->
|
||||
<!-- Disable Transfer -->
|
||||
<!--<param name="disable-transfer" value="true"/> -->
|
||||
<!-- Disable Register -->
|
||||
<!--<param name="disable-register" value="true"/> -->
|
||||
<!-- Used for when phones respond to a challenged ACK with method INVITE in the hash -->
|
||||
<!--<param name="NDLB-broken-auth-hash" value="true"/>-->
|
||||
<!-- add a ;received="<ip>:<port>" to the contact when replying to register for nat handling -->
|
||||
<!--<param name="NDLB-received-in-nat-reg-contact" value="true"/>-->
|
||||
<param name="auth-calls" value="$${internal_auth_calls}"/>
|
||||
<!-- Force the user and auth-user to match. -->
|
||||
<param name="inbound-reg-force-matching-username" value="true"/>
|
||||
<!-- on authed calls, authenticate *all* the packets not just invite -->
|
||||
<param name="auth-all-packets" value="false"/>
|
||||
|
||||
<!-- external_sip_ip
|
||||
Used as the public IP address for SDP.
|
||||
Can be an one of:
|
||||
ip address - "12.34.56.78"
|
||||
a stun server lookup - "stun:stun.server.com"
|
||||
a DNS name - "host:host.server.com"
|
||||
auto - Use guessed ip.
|
||||
auto-nat - Use ip learned from NAT-PMP or UPNP
|
||||
-->
|
||||
<param name="ext-rtp-ip" value="auto-nat"/>
|
||||
<param name="ext-sip-ip" value="auto-nat"/>
|
||||
|
||||
<!-- rtp inactivity timeout -->
|
||||
<param name="rtp-timeout-sec" value="300"/>
|
||||
<param name="rtp-hold-timeout-sec" value="1800"/>
|
||||
<!-- VAD choose one (out is a good choice); -->
|
||||
<!-- <param name="vad" value="in"/> -->
|
||||
<!-- <param name="vad" value="out"/> -->
|
||||
<!-- <param name="vad" value="both"/> -->
|
||||
<!--<param name="alias" value="sip:10.0.1.251:5555"/>-->
|
||||
<!--
|
||||
These are enabled to make the default config work better out of the box.
|
||||
If you need more than ONE domain you'll need to not use these options.
|
||||
|
||||
-->
|
||||
<!--all inbound reg will look in this domain for the users -->
|
||||
<param name="force-register-domain" value="$${domain}"/>
|
||||
<!--force the domain in subscriptions to this value -->
|
||||
<param name="force-subscription-domain" value="$${domain}"/>
|
||||
<!--all inbound reg will stored in the db using this domain -->
|
||||
<param name="force-register-db-domain" value="$${domain}"/>
|
||||
|
||||
<!--<param name="delete-subs-on-register" value="false"/>-->
|
||||
|
||||
<!-- enable rtcp on every channel also can be done per leg basis with rtcp_audio_interval_msec variable set to passthru to pass it across a call-->
|
||||
<!--<param name="rtcp-audio-interval-msec" value="5000"/>-->
|
||||
<!--<param name="rtcp-video-interval-msec" value="5000"/>-->
|
||||
|
||||
<!--force suscription expires to a lower value than requested-->
|
||||
<!--<param name="force-subscription-expires" value="60"/>-->
|
||||
<!-- disable register and transfer which may be undesirable in a public switch -->
|
||||
<!--<param name="disable-transfer" value="true"/>-->
|
||||
<!--<param name="disable-register" value="true"/>-->
|
||||
|
||||
<!--
|
||||
enable-3pcc can be set to either 'true' or 'proxy', true accepts the call
|
||||
right away, proxy waits until the call has been answered then sends accepts
|
||||
-->
|
||||
<!--<param name="enable-3pcc" value="true"/>-->
|
||||
|
||||
<!-- use at your own risk or if you know what this does.-->
|
||||
<!--<param name="NDLB-force-rport" value="true"/>-->
|
||||
<!--
|
||||
Choose the realm challenge key. Default is auto_to if not set.
|
||||
|
||||
auto_from - uses the from field as the value for the sip realm.
|
||||
auto_to - uses the to field as the value for the sip realm.
|
||||
<anyvalue> - you can input any value to use for the sip realm.
|
||||
|
||||
If you want URL dialing to work you'll want to set this to auto_from.
|
||||
|
||||
If you use any other value besides auto_to or auto_from you'll loose
|
||||
the ability to do multiple domains.
|
||||
|
||||
Note: comment out to restore the behavior before 2008-09-29
|
||||
|
||||
-->
|
||||
<param name="challenge-realm" value="auto_from"/>
|
||||
<!--<param name="disable-rtp-auto-adjust" value="true"/>-->
|
||||
<!-- on inbound calls make the uuid of the session equal to the sip call id of that call -->
|
||||
<!--<param name="inbound-use-callid-as-uuid" value="true"/>-->
|
||||
<!-- on outbound calls set the callid to match the uuid of the session -->
|
||||
<!--<param name="outbound-use-uuid-as-callid" value="true"/>-->
|
||||
<!-- set to false disable this feature -->
|
||||
<!--<param name="rtp-autofix-timing" value="false"/>-->
|
||||
|
||||
<!-- set this param to false if your gateway for some reason hates X- headers that it is supposed to ignore-->
|
||||
<!--<param name="pass-callee-id" value="false"/>-->
|
||||
|
||||
<!-- clear clears them all or supply the name to add or the name prefixed with ~ to remove
|
||||
valid values:
|
||||
|
||||
clear
|
||||
CISCO_SKIP_MARK_BIT_2833
|
||||
SONUS_SEND_INVALID_TIMESTAMP_2833
|
||||
|
||||
-->
|
||||
<!--<param name="auto-rtp-bugs" data="clear"/>-->
|
||||
|
||||
<!-- the following can be used as workaround with bogus SRV/NAPTR records -->
|
||||
<!--<param name="disable-srv" value="false" />-->
|
||||
<!--<param name="disable-naptr" value="false" />-->
|
||||
|
||||
<!-- The following can be used to fine-tune timers within sofia's transport layer
|
||||
Those settings are for advanced users and can safely be left as-is -->
|
||||
|
||||
<!-- Initial retransmission interval (in milliseconds).
|
||||
Set the T1 retransmission interval used by the SIP transaction engine.
|
||||
The T1 is the initial duration used by request retransmission timers A and E (UDP) as well as response retransmission timer G. -->
|
||||
<!-- <param name="timer-T1" value="500" /> -->
|
||||
|
||||
<!-- Transaction timeout (defaults to T1 * 64).
|
||||
Set the T1x64 timeout value used by the SIP transaction engine.
|
||||
The T1x64 is duration used for timers B, F, H, and J (UDP) by the SIP transaction engine.
|
||||
The timeout value T1x64 can be adjusted separately from the initial retransmission interval T1. -->
|
||||
<!-- <param name="timer-T1X64" value="32000" /> -->
|
||||
|
||||
|
||||
<!-- Maximum retransmission interval (in milliseconds).
|
||||
Set the maximum retransmission interval used by the SIP transaction engine.
|
||||
The T2 is the maximum duration used for the timers E (UDP) and G by the SIP transaction engine.
|
||||
Note that the timer A is not capped by T2. Retransmission interval of INVITE requests grows exponentially
|
||||
until the timer B fires. -->
|
||||
<!-- <param name="timer-T2" value="4000" /> -->
|
||||
|
||||
<!--
|
||||
Transaction lifetime (in milliseconds).
|
||||
Set the lifetime for completed transactions used by the SIP transaction engine.
|
||||
A completed transaction is kept around for the duration of T4 in order to catch late responses.
|
||||
The T4 is the maximum duration for the messages to stay in the network and the duration of SIP timer K. -->
|
||||
<!-- <param name="timer-T4" value="4000" /> -->
|
||||
|
||||
<!-- Turn on a jitterbuffer for every call -->
|
||||
<!-- <param name="auto-jitterbuffer-msec" value="60"/> -->
|
||||
|
||||
|
||||
<!-- By default mod_sofia will ignore the codecs in the sdp for hold/unhold operations
|
||||
Set this to true if you want to actually parse the sdp and re-negotiate the codec during hold/unhold.
|
||||
It's probably not what you want so stick with the default unless you really need to change this.
|
||||
-->
|
||||
<!--<param name="renegotiate-codec-on-hold" value="true"/>-->
|
||||
|
||||
</settings>
|
||||
</profile>
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
<include>
|
||||
<!--<gateway name="asterlink.com">-->
|
||||
<!--/// account username *required* ///-->
|
||||
<!--<param name="username" value="cluecon"/>-->
|
||||
<!--/// auth realm: *optional* same as gateway name, if blank ///-->
|
||||
<!--<param name="realm" value="asterlink.com"/>-->
|
||||
<!--/// username to use in from: *optional* same as username, if blank ///-->
|
||||
<!--<param name="from-user" value="cluecon"/>-->
|
||||
<!--/// domain to use in from: *optional* same as realm, if blank ///-->
|
||||
<!--<param name="from-domain" value="asterlink.com"/>-->
|
||||
<!--/// account password *required* ///-->
|
||||
<!--<param name="password" value="2007"/>-->
|
||||
<!--/// extension for inbound calls: *optional* same as username, if blank ///-->
|
||||
<!--<param name="extension" value="cluecon"/>-->
|
||||
<!--/// proxy host: *optional* same as realm, if blank ///-->
|
||||
<!--<param name="proxy" value="asterlink.com"/>-->
|
||||
<!--/// send register to this proxy: *optional* same as proxy, if blank ///-->
|
||||
<!--<param name="register-proxy" value="mysbc.com"/>-->
|
||||
<!--/// expire in seconds: *optional* 3600, if blank ///-->
|
||||
<!--<param name="expire-seconds" value="60"/>-->
|
||||
<!--/// do not register ///-->
|
||||
<!--<param name="register" value="false"/>-->
|
||||
<!-- which transport to use for register -->
|
||||
<!--<param name="register-transport" value="udp"/>-->
|
||||
<!--How many seconds before a retry when a failure or timeout occurs -->
|
||||
<!--<param name="retry-seconds" value="30"/>-->
|
||||
<!--Use the callerid of an inbound call in the from field on outbound calls via this gateway -->
|
||||
<!--<param name="caller-id-in-from" value="false"/>-->
|
||||
<!--extra sip params to send in the contact-->
|
||||
<!--<param name="contact-params" value="tport=tcp"/>-->
|
||||
<!-- Put the extension in the contact -->
|
||||
<!--<param name="extension-in-contact" value="true"/>-->
|
||||
<!--send an options ping every x seconds, failure will unregister and/or mark it down-->
|
||||
<!--<param name="ping" value="25"/>-->
|
||||
<!--<param name="cid-type" value="rpid"/>-->
|
||||
<!--</gateway>-->
|
||||
</include>
|
||||
@@ -495,12 +495,16 @@ switch_status_t sofia_on_hangup(switch_core_session_t *session)
|
||||
val = switch_channel_get_variable(tech_pvt->channel, "disable_q850_reason");
|
||||
|
||||
if (!val || 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));
|
||||
if ((val = switch_channel_get_variable(tech_pvt->channel, "sip_reason_str"))) {
|
||||
switch_snprintf(reason, sizeof(reason), "%s", val);
|
||||
} else {
|
||||
switch_snprintf(reason, sizeof(reason), "%s;cause=%d;text=\"%s\"", tech_pvt->profile->username, cause, switch_channel_cause2str(cause));
|
||||
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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1728,7 +1732,8 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi
|
||||
}
|
||||
|
||||
|
||||
if ((var = switch_channel_get_variable(channel, SOFIA_SECURE_MEDIA_VARIABLE)) && switch_true(var)) {
|
||||
if ((var = switch_channel_get_variable(channel, SOFIA_SECURE_MEDIA_VARIABLE)) &&
|
||||
(switch_true(var) || !strcasecmp(var, SWITCH_RTP_CRYPTO_KEY_32) || !strcasecmp(var, SWITCH_RTP_CRYPTO_KEY_80))) {
|
||||
sofia_set_flag_locked(tech_pvt, TFLAG_SECURE);
|
||||
}
|
||||
|
||||
@@ -1917,13 +1922,18 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi
|
||||
{
|
||||
switch_t38_options_t *t38_options = switch_channel_get_private(tech_pvt->channel, "t38_options");
|
||||
|
||||
sofia_glue_set_image_sdp(tech_pvt, t38_options, msg->numeric_arg);
|
||||
if (t38_options) {
|
||||
sofia_glue_set_image_sdp(tech_pvt, t38_options, msg->numeric_arg);
|
||||
|
||||
if (!switch_channel_test_flag(channel, CF_PROXY_MEDIA)) {
|
||||
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);
|
||||
} else {
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "%s Request to send IMAGE on channel with not t38 options.\n",
|
||||
switch_channel_get_name(channel));
|
||||
}
|
||||
sofia_set_flag_locked(tech_pvt, TFLAG_SENT_UPDATE);
|
||||
sofia_glue_do_invite(session);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -2033,7 +2043,7 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi
|
||||
const char *uuid;
|
||||
const char *call_id = NULL, *to_user = NULL, *to_host = NULL, *to_tag = NULL, *from_tag = NULL, *from_user = NULL, *from_host = NULL;
|
||||
|
||||
if ((uuid = switch_channel_get_variable(channel, SWITCH_SIGNAL_BOND_VARIABLE))) {
|
||||
if ((uuid = switch_channel_get_variable(channel, SWITCH_SIGNAL_BOND_VARIABLE)) || (uuid = switch_channel_get_variable(channel, "originate_signal_bond"))) {
|
||||
switch_core_session_t *rsession;
|
||||
if ((rsession = switch_core_session_locate(uuid))) {
|
||||
switch_channel_t *rchannel = switch_core_session_get_channel(rsession);
|
||||
@@ -2103,12 +2113,7 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi
|
||||
number = tech_pvt->caller_profile->destination_number;
|
||||
}
|
||||
|
||||
if (sofia_test_flag(tech_pvt, TFLAG_UPDATING_DISPLAY) || !switch_channel_test_flag(channel, CF_ANSWERED)) {
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_WARNING,
|
||||
"Cannot send display update to %s "
|
||||
"Did not receive reply to last update or channel has not been answered yet.\n",
|
||||
switch_channel_get_name(tech_pvt->channel));
|
||||
} else {
|
||||
if (!sofia_test_flag(tech_pvt, TFLAG_UPDATING_DISPLAY) && switch_channel_test_flag(channel, CF_ANSWERED)) {
|
||||
if (zstr(tech_pvt->last_sent_callee_id_name) || strcmp(tech_pvt->last_sent_callee_id_name, name) ||
|
||||
zstr(tech_pvt->last_sent_callee_id_number) || strcmp(tech_pvt->last_sent_callee_id_number, number)) {
|
||||
|
||||
@@ -2159,6 +2164,7 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi
|
||||
nua_update(tech_pvt->nh,
|
||||
NUTAG_SESSION_TIMER(tech_pvt->session_timeout),
|
||||
NUTAG_SESSION_REFRESHER(tech_pvt->session_refresher),
|
||||
TAG_IF(!zstr(tech_pvt->route_uri), NUTAG_PROXY(tech_pvt->route_uri)),
|
||||
TAG_IF(!zstr_buf(message), SIPTAG_HEADER_STR(message)),
|
||||
TAG_IF(!zstr(tech_pvt->user_via), SIPTAG_VIA_STR(tech_pvt->user_via)), TAG_END());
|
||||
} else if ((ua && (switch_stristr("Yealink", ua)))) {
|
||||
@@ -2168,6 +2174,7 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi
|
||||
nua_update(tech_pvt->nh,
|
||||
NUTAG_SESSION_TIMER(tech_pvt->session_timeout),
|
||||
NUTAG_SESSION_REFRESHER(tech_pvt->session_refresher),
|
||||
TAG_IF(!zstr(tech_pvt->route_uri), NUTAG_PROXY(tech_pvt->route_uri)),
|
||||
TAG_IF(!zstr_buf(message), SIPTAG_HEADER_STR(message)),
|
||||
TAG_IF(!zstr(tech_pvt->user_via), SIPTAG_VIA_STR(tech_pvt->user_via)), TAG_END());
|
||||
}
|
||||
@@ -2566,6 +2573,8 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi
|
||||
}
|
||||
}
|
||||
|
||||
switch_channel_check_zrtp(tech_pvt->channel);
|
||||
|
||||
if ((status = sofia_glue_tech_choose_port(tech_pvt, 0)) != SWITCH_STATUS_SUCCESS) {
|
||||
switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
|
||||
goto end_lock;
|
||||
@@ -2803,8 +2812,29 @@ static int show_reg_callback_xml(void *pArg, int argc, char **argv, char **colum
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const char *status_names[] = { "DOWN", "UP", NULL };
|
||||
static int sql2str_callback(void *pArg, int argc, char **argv, char **columnNames)
|
||||
{
|
||||
struct cb_helper_sql2str *cbt = (struct cb_helper_sql2str *) pArg;
|
||||
|
||||
switch_copy_string(cbt->buf, argv[0], cbt->len);
|
||||
cbt->matches++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint32_t sofia_profile_reg_count(sofia_profile_t *profile)
|
||||
{
|
||||
struct cb_helper_sql2str cb;
|
||||
char reg_count[80] = "";
|
||||
char *sql;
|
||||
cb.buf = reg_count;
|
||||
cb.len = sizeof(reg_count);
|
||||
sql = switch_mprintf("select count(*) from sip_registrations where profile_name = '%q'", profile->name);
|
||||
sofia_glue_execute_sql_callback(profile, profile->ireg_mutex, sql, sql2str_callback, &cb);
|
||||
free(sql);
|
||||
return strtoul(reg_count, NULL, 10);
|
||||
}
|
||||
|
||||
static const char *status_names[] = { "DOWN", "UP", NULL };
|
||||
|
||||
static switch_status_t cmd_status(char **argv, int argc, switch_stream_handle_t *stream)
|
||||
{
|
||||
@@ -2978,6 +3008,7 @@ static switch_status_t cmd_status(char **argv, int argc, switch_stream_handle_t
|
||||
stream->write_function(stream, "FAILED-CALLS-IN \t%u\n", profile->ib_failed_calls);
|
||||
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, "REGISTRATIONS \t%lu\n", sofia_profile_reg_count(profile));
|
||||
}
|
||||
|
||||
cb.profile = profile;
|
||||
@@ -3254,9 +3285,9 @@ static switch_status_t cmd_xml_status(char **argv, int argc, switch_stream_handl
|
||||
stream->write_function(stream, " <calls-out>%u</calls-out>\n", profile->ob_calls);
|
||||
stream->write_function(stream, " <failed-calls-in>%u</failed-calls-in>\n", profile->ib_failed_calls);
|
||||
stream->write_function(stream, " <failed-calls-out>%u</failed-calls-out>\n", profile->ob_failed_calls);
|
||||
stream->write_function(stream, " <registrations>%lu</registrations>\n", sofia_profile_reg_count(profile));
|
||||
stream->write_function(stream, " </profile-info>\n");
|
||||
}
|
||||
stream->write_function(stream, " <registrations>\n");
|
||||
|
||||
cb.profile = profile;
|
||||
cb.stream = stream;
|
||||
@@ -3275,6 +3306,13 @@ static switch_status_t cmd_xml_status(char **argv, int argc, switch_stream_handl
|
||||
"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;
|
||||
@@ -3305,17 +3343,15 @@ static switch_status_t cmd_xml_status(char **argv, int argc, switch_stream_handl
|
||||
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, " <registrations>\n");
|
||||
|
||||
sofia_glue_execute_sql_callback(profile, profile->ireg_mutex, sql, show_reg_callback_xml, &cb);
|
||||
switch_safe_free(sql);
|
||||
|
||||
stream->write_function(stream, " </registrations>\n");
|
||||
}
|
||||
|
||||
sofia_glue_execute_sql_callback(profile, profile->ireg_mutex, sql, show_reg_callback_xml, &cb);
|
||||
switch_safe_free(sql);
|
||||
|
||||
stream->write_function(stream, " </registrations>\n");
|
||||
stream->write_function(stream, "</profile>\n");
|
||||
|
||||
sofia_glue_release_profile(profile);
|
||||
@@ -3684,15 +3720,6 @@ static int contact_callback(void *pArg, int argc, char **argv, char **columnName
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sql2str_callback(void *pArg, int argc, char **argv, char **columnNames)
|
||||
{
|
||||
struct cb_helper_sql2str *cbt = (struct cb_helper_sql2str *) pArg;
|
||||
|
||||
switch_copy_string(cbt->buf, argv[0], cbt->len);
|
||||
cbt->matches++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
SWITCH_STANDARD_API(sofia_count_reg_function)
|
||||
{
|
||||
char *data;
|
||||
@@ -4650,8 +4677,8 @@ static switch_call_cause_t sofia_outgoing_channel(switch_core_session_t *session
|
||||
}
|
||||
|
||||
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),
|
||||
sql = switch_mprintf("insert into sip_dialogs (uuid,presence_id,presence_data,profile_name,hostname,rcd,call_info_state) "
|
||||
"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);
|
||||
@@ -5337,6 +5364,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_sofia_load)
|
||||
switch_chat_interface_t *chat_interface;
|
||||
switch_api_interface_t *api_interface;
|
||||
switch_management_interface_t *management_interface;
|
||||
uint32_t cpus = switch_core_cpu_count();
|
||||
struct in_addr in;
|
||||
|
||||
memset(&mod_sofia_globals, 0, sizeof(mod_sofia_globals));
|
||||
@@ -5374,6 +5402,10 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_sofia_load)
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Waiting for profiles to start\n");
|
||||
switch_yield(1500000);
|
||||
|
||||
/* start one message thread per cpu */
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Starting %u message threads.\n", cpus);
|
||||
sofia_msg_thread_start(cpus);
|
||||
|
||||
if (switch_event_bind_removable(modname, SWITCH_EVENT_CUSTOM, MULTICAST_EVENT, event_handler, NULL,
|
||||
&mod_sofia_globals.custom_node) != SWITCH_STATUS_SUCCESS) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't bind!\n");
|
||||
|
||||
@@ -262,6 +262,7 @@ typedef enum {
|
||||
PFLAG_SHUTDOWN,
|
||||
PFLAG_PRESENCE_MAP,
|
||||
PFLAG_OPTIONS_RESPOND_503_ON_BUSY,
|
||||
PFLAG_PRESENCE_DISABLE_EARLY,
|
||||
/* No new flags below this line */
|
||||
PFLAG_MAX
|
||||
} PFLAGS;
|
||||
@@ -1116,6 +1117,7 @@ switch_status_t sofia_glue_send_notify(sofia_profile_t *profile, const char *use
|
||||
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_core_session_t *session, sip_t const *sip, const char *prefix);
|
||||
char *sofia_glue_get_extra_headers_from_event(switch_event_t *event, 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);
|
||||
@@ -1149,3 +1151,4 @@ void sofia_glue_pause_jitterbuffer(switch_core_session_t *session, switch_bool_t
|
||||
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);
|
||||
void sofia_msg_thread_start(int idx);
|
||||
|
||||
+220
-107
@@ -88,9 +88,9 @@ void sofia_handle_sip_r_notify(switch_core_session_t *session, int status,
|
||||
sofia_dispatch_event_t *de, tagi_t tags[])
|
||||
{
|
||||
|
||||
if (status >= 300 && sip && sip->sip_call_id && (!sofia_private || !sofia_private->is_call)) {
|
||||
if (status == 481 && sip && !sip->sip_retry_after && 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);
|
||||
switch_assert(sql != NULL);
|
||||
sofia_glue_execute_sql(profile, &sql, SWITCH_TRUE);
|
||||
@@ -239,21 +239,25 @@ static void extract_header_vars(sofia_profile_t *profile, sip_t const *sip,
|
||||
switch_stream_handle_t stream = { 0 };
|
||||
int x = 0;
|
||||
|
||||
if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) {
|
||||
SWITCH_STANDARD_STREAM(stream);
|
||||
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++;
|
||||
}
|
||||
for(vp = sip->sip_via; vp; vp = vp->v_next) {
|
||||
char *v = sip_header_as_string(nh->nh_home, (void *) vp);
|
||||
|
||||
switch_channel_set_variable(channel, "sip_recover_via", (char *)stream.data);
|
||||
free(stream.data);
|
||||
stream.write_function(&stream, x == 0 ? "%s" : ",%s", v);
|
||||
su_free(nh->nh_home, v);
|
||||
|
||||
x++;
|
||||
}
|
||||
|
||||
switch_channel_set_variable(channel, "sip_full_via", (char *)stream.data);
|
||||
|
||||
if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) {
|
||||
switch_channel_set_variable(channel, "sip_recover_via", (char *)stream.data);
|
||||
}
|
||||
|
||||
free(stream.data);
|
||||
|
||||
}
|
||||
|
||||
if (sip->sip_from) {
|
||||
@@ -577,6 +581,14 @@ void sofia_handle_sip_i_bye(switch_core_session_t *session, int status,
|
||||
sofia_set_flag_locked(tech_pvt, TFLAG_BYE);
|
||||
call_info = switch_channel_get_variable(channel, "presence_call_info_full");
|
||||
|
||||
if (sip->sip_reason) {
|
||||
char *reason_header = sip_header_as_string(nh->nh_home, (void *) sip->sip_reason);
|
||||
|
||||
if (!zstr(reason_header)) {
|
||||
switch_channel_set_variable_partner(channel, "sip_reason", reason_header);
|
||||
}
|
||||
}
|
||||
|
||||
if (sip->sip_reason && sip->sip_reason->re_protocol && (!strcasecmp(sip->sip_reason->re_protocol, "Q.850")
|
||||
|| !strcasecmp(sip->sip_reason->re_protocol, "FreeSWITCH")
|
||||
|| !strcasecmp(sip->sip_reason->re_protocol, profile->username)) && sip->sip_reason->re_cause) {
|
||||
@@ -977,7 +989,6 @@ static void our_sofia_event_callback(nua_event_t event,
|
||||
case nua_r_unregister:
|
||||
case nua_r_unsubscribe:
|
||||
case nua_r_publish:
|
||||
case nua_i_cancel:
|
||||
case nua_i_error:
|
||||
case nua_i_active:
|
||||
case nua_i_terminated:
|
||||
@@ -985,6 +996,19 @@ static void our_sofia_event_callback(nua_event_t event,
|
||||
case nua_i_prack:
|
||||
case nua_r_prack:
|
||||
break;
|
||||
|
||||
case nua_i_cancel:
|
||||
|
||||
if (sip && channel && sip->sip_reason) {
|
||||
char *reason_header = sip_header_as_string(nh->nh_home, (void *) sip->sip_reason);
|
||||
|
||||
if (!zstr(reason_header)) {
|
||||
switch_channel_set_variable_partner(channel, "sip_reason", reason_header);
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case nua_r_cancel:
|
||||
{
|
||||
if (status > 299 && nh) {
|
||||
@@ -1228,7 +1252,7 @@ void *SWITCH_THREAD_FUNC sofia_msg_thread_run(switch_thread_t *thread, void *obj
|
||||
|
||||
static int IDX = 0;
|
||||
|
||||
static void sofia_msg_thread_start(int idx)
|
||||
void sofia_msg_thread_start(int idx)
|
||||
{
|
||||
|
||||
if (idx >= SOFIA_MAX_MSG_QUEUE || (idx < mod_sofia_globals.msg_queue_len && mod_sofia_globals.msg_queue_thread[idx])) {
|
||||
@@ -2618,8 +2642,9 @@ static void parse_gateways(sofia_profile_t *profile, switch_xml_t gateways_tag)
|
||||
gateway->ping = switch_epoch_time_now(NULL) + ping_freq;
|
||||
gateway->options_to_uri = switch_core_sprintf(gateway->pool, "<sip:%s;transport=%s>",
|
||||
!zstr(from_domain) ? from_domain : proxy, register_transport);
|
||||
gateway->options_from_uri = switch_core_sprintf(gateway->pool, "<sip:%s;transport=%s>",
|
||||
profile->extrtpip ? profile->extrtpip : profile->sipip, register_transport);
|
||||
//gateway->options_from_uri = switch_core_sprintf(gateway->pool, "<sip:%s;transport=%s>",
|
||||
// profile->extrtpip ? profile->extrtpip : profile->sipip, register_transport);
|
||||
gateway->options_from_uri = gateway->options_to_uri;
|
||||
} else {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "ERROR: invalid ping!\n");
|
||||
}
|
||||
@@ -3031,6 +3056,12 @@ switch_status_t reconfig_sofia(sofia_profile_t *profile)
|
||||
} else {
|
||||
sofia_clear_pflag(profile, PFLAG_T38_PASSTHRU);
|
||||
}
|
||||
} else if (!strcasecmp(var, "presence-disable-early")) {
|
||||
if (switch_true(val)) {
|
||||
sofia_set_pflag(profile, PFLAG_PRESENCE_DISABLE_EARLY);
|
||||
} else {
|
||||
sofia_clear_pflag(profile, PFLAG_PRESENCE_DISABLE_EARLY);
|
||||
}
|
||||
} else if (!strcasecmp(var, "ignore-183nosdp")) {
|
||||
if (switch_true(val)) {
|
||||
sofia_set_pflag(profile, PFLAG_IGNORE_183NOSDP);
|
||||
@@ -3356,7 +3387,7 @@ switch_status_t reconfig_sofia(sofia_profile_t *profile)
|
||||
} else if (!strcasecmp(var, "context")) {
|
||||
profile->context = switch_core_strdup(profile->pool, val);
|
||||
} else if (!strcasecmp(var, "local-network-acl")) {
|
||||
if (!strcasecmp(var, "none")) {
|
||||
if (!strcasecmp(val, "none")) {
|
||||
profile->local_network = NULL;
|
||||
} else {
|
||||
profile->local_network = switch_core_strdup(profile->pool, val);
|
||||
@@ -3605,6 +3636,18 @@ switch_status_t config_sofia(int reload, char *profile_name)
|
||||
mod_sofia_globals.debug_sla = atoi(val);
|
||||
} else if (!strcasecmp(var, "auto-restart")) {
|
||||
mod_sofia_globals.auto_restart = switch_true(val);
|
||||
} else if (!strcasecmp(var, "message-threads")) {
|
||||
int num = atoi(val);
|
||||
|
||||
if (num < 1 || num > SOFIA_MAX_MSG_QUEUE - 1) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "message-threads must be between 1 and %d", SOFIA_MAX_MSG_QUEUE -1);
|
||||
}
|
||||
|
||||
if (num < 1) num = 1;
|
||||
if (num > SOFIA_MAX_MSG_QUEUE - 1) num = SOFIA_MAX_MSG_QUEUE -1;
|
||||
|
||||
sofia_msg_thread_start(num);
|
||||
|
||||
} else if (!strcasecmp(var, "reg-deny-binding-fetch-and-no-lookup")) { /* backwards compatibility */
|
||||
mod_sofia_globals.reg_deny_binding_fetch_and_no_lookup = switch_true(val); /* remove when noone complains about the extra lookup */
|
||||
if (switch_true(val)) {
|
||||
@@ -3805,6 +3848,12 @@ switch_status_t config_sofia(int reload, char *profile_name)
|
||||
} else {
|
||||
sofia_clear_pflag(profile, PFLAG_T38_PASSTHRU);
|
||||
}
|
||||
} else if (!strcasecmp(var, "presence-disable-early")) {
|
||||
if (switch_true(val)) {
|
||||
sofia_set_pflag(profile, PFLAG_PRESENCE_DISABLE_EARLY);
|
||||
} else {
|
||||
sofia_clear_pflag(profile, PFLAG_PRESENCE_DISABLE_EARLY);
|
||||
}
|
||||
} else if (!strcasecmp(var, "ignore-183nosdp")) {
|
||||
if (switch_true(val)) {
|
||||
sofia_set_pflag(profile, PFLAG_IGNORE_183NOSDP);
|
||||
@@ -3845,19 +3894,7 @@ switch_status_t config_sofia(int reload, char *profile_name)
|
||||
} else {
|
||||
sofia_clear_pflag(profile, PFLAG_CID_IN_1XX);
|
||||
}
|
||||
} else if (!strcasecmp(var, "message-threads")) {
|
||||
int num = atoi(val);
|
||||
|
||||
if (num < 1 || num > SOFIA_MAX_MSG_QUEUE - 1) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "message-threads must be between 1 and %d", SOFIA_MAX_MSG_QUEUE -1);
|
||||
}
|
||||
|
||||
if (num < 1) num = 1;
|
||||
if (num > SOFIA_MAX_MSG_QUEUE - 1) num = SOFIA_MAX_MSG_QUEUE -1;
|
||||
|
||||
sofia_msg_thread_start(num);
|
||||
|
||||
|
||||
} else if (!strcasecmp(var, "disable-hold")) {
|
||||
if (switch_true(val)) {
|
||||
sofia_set_pflag(profile, PFLAG_DISABLE_HOLD);
|
||||
@@ -4719,7 +4756,7 @@ static void sofia_handle_sip_r_options(switch_core_session_t *session, int statu
|
||||
gateway->ping = switch_epoch_time_now(NULL) + gateway->ping_freq;
|
||||
sofia_reg_release_gateway(gateway);
|
||||
gateway->pinging = 0;
|
||||
} else if (sofia_test_pflag(profile, PFLAG_UNREG_OPTIONS_FAIL) && status != 200 && sip && sip->sip_to) {
|
||||
} else if (sofia_test_pflag(profile, PFLAG_UNREG_OPTIONS_FAIL) && (status != 200 && status != 486) && sip && sip->sip_to) {
|
||||
char *sql;
|
||||
time_t now = switch_epoch_time_now(NULL);
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Expire registration '%s@%s' due to options failure\n",
|
||||
@@ -4757,6 +4794,13 @@ static void sofia_handle_sip_r_invite(switch_core_session_t *session, int status
|
||||
return;
|
||||
}
|
||||
|
||||
if (status >= 500 && sip->sip_reason && sip->sip_reason->re_protocol && (!strcasecmp(sip->sip_reason->re_protocol, "Q.850")
|
||||
|| !strcasecmp(sip->sip_reason->re_protocol, "FreeSWITCH")
|
||||
|| !strcasecmp(sip->sip_reason->re_protocol, profile->username)) && sip->sip_reason->re_cause) {
|
||||
tech_pvt->q850_cause = atoi(sip->sip_reason->re_cause);
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Remote Reason: %d\n", tech_pvt->q850_cause);
|
||||
}
|
||||
|
||||
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);
|
||||
@@ -4789,6 +4833,7 @@ static void sofia_handle_sip_r_invite(switch_core_session_t *session, int status
|
||||
if (channel && sip->sip_call_info) {
|
||||
char *p;
|
||||
call_info = sip_header_as_string(nua_handle_home(nh), (void *) sip->sip_call_info);
|
||||
|
||||
if (switch_stristr("appearance", call_info)) {
|
||||
switch_channel_set_variable(channel, "presence_call_info_full", call_info);
|
||||
if ((p = strchr(call_info, ';'))) {
|
||||
@@ -4825,10 +4870,15 @@ static void sofia_handle_sip_r_invite(switch_core_session_t *session, int status
|
||||
if (mod_sofia_globals.debug_sla > 1) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "QUERY SQL %s\n", sql);
|
||||
}
|
||||
|
||||
|
||||
sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE);
|
||||
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Auto-Fixing Broken SLA [<sip:%s>;%s]\n",
|
||||
sip->sip_from->a_url->url_host, buf);
|
||||
switch_channel_set_variable_printf(channel, "presence_call_info_full", "<sip:%s>;%s", sip->sip_from->a_url->url_host, buf);
|
||||
switch_channel_set_variable(channel, "presence_call_info", buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5003,14 +5053,16 @@ static void sofia_handle_sip_r_invite(switch_core_session_t *session, int status
|
||||
}
|
||||
|
||||
if (sofia_test_pflag(profile, PFLAG_MANUAL_REDIRECT)) {
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Redirect: Transfering to %s %s %s\n",
|
||||
p_contact->m_url->url_user, sip_redirect_dialplan, sip_redirect_context);
|
||||
if (!(v = switch_channel_get_variable(channel, "outbound_redirect_info"))) {
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Redirect: Transfering to %s %s %s\n",
|
||||
p_contact->m_url->url_user, sip_redirect_dialplan, sip_redirect_context);
|
||||
|
||||
if (switch_true(switch_channel_get_variable(channel, "recording_follow_transfer"))) {
|
||||
switch_core_media_bug_transfer_recordings(session, a_session);
|
||||
if (switch_true(switch_channel_get_variable(channel, "recording_follow_transfer"))) {
|
||||
switch_core_media_bug_transfer_recordings(session, a_session);
|
||||
}
|
||||
|
||||
switch_ivr_session_transfer(a_session, p_contact->m_url->url_user, sip_redirect_dialplan, sip_redirect_context);
|
||||
}
|
||||
|
||||
switch_ivr_session_transfer(a_session, p_contact->m_url->url_user, sip_redirect_dialplan, sip_redirect_context);
|
||||
switch_channel_hangup(channel, SWITCH_CAUSE_REDIRECTION_TO_NEW_DESTINATION);
|
||||
} else if ((!strcmp(profile->sipip, p_contact->m_url->url_host))
|
||||
|| (profile->extsipip && !strcmp(profile->extsipip, p_contact->m_url->url_host))
|
||||
@@ -5248,8 +5300,9 @@ static void sofia_handle_sip_r_invite(switch_core_session_t *session, int status
|
||||
|
||||
sql = switch_mprintf("insert into sip_dialogs "
|
||||
"(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)",
|
||||
"contact_host,state,direction,user_agent,profile_name,hostname,contact,presence_id,presence_data,"
|
||||
"call_info,rcd,call_info_state) "
|
||||
"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, to_tag, from_user, from_host, from_tag, contact_user,
|
||||
@@ -5672,11 +5725,13 @@ static void sofia_handle_sip_i_state(switch_core_session_t *session, int status,
|
||||
const char *invite_route_uri = switch_channel_get_variable(tech_pvt->channel, "sip_invite_route_uri");
|
||||
|
||||
nua_ack(nh,
|
||||
TAG_IF(invite_full_from, SIPTAG_FROM_STR(invite_full_from)),
|
||||
TAG_IF(invite_full_to, SIPTAG_TO_STR(invite_full_to)),
|
||||
TAG_IF(!zstr(invite_full_via), SIPTAG_VIA_STR(invite_full_via)),
|
||||
TAG_IF(!zstr(invite_route_uri), SIPTAG_ROUTE_STR(invite_route_uri)),
|
||||
TAG_END());
|
||||
TAG_IF(invite_full_from, SIPTAG_FROM_STR(invite_full_from)),
|
||||
TAG_IF(invite_full_to, SIPTAG_TO_STR(invite_full_to)),
|
||||
TAG_IF(!zstr(tech_pvt->user_via), SIPTAG_VIA_STR(tech_pvt->user_via)),
|
||||
TAG_IF((zstr(tech_pvt->user_via) && !zstr(invite_full_via)), SIPTAG_VIA_STR(invite_full_via)),
|
||||
|
||||
TAG_IF(!zstr(invite_route_uri), SIPTAG_ROUTE_STR(invite_route_uri)),
|
||||
TAG_END());
|
||||
|
||||
} else {
|
||||
nua_ack(nh,
|
||||
@@ -5788,11 +5843,11 @@ static void sofia_handle_sip_i_state(switch_core_session_t *session, int status,
|
||||
}
|
||||
} else {
|
||||
if (sofia_test_pflag(profile, PFLAG_3PCC)) {
|
||||
if (switch_channel_test_flag(channel, CF_PROXY_MODE) || switch_channel_test_flag(channel, CF_PROXY_MEDIA)) {
|
||||
if (switch_channel_test_flag(channel, CF_PROXY_MODE) || switch_channel_test_flag(channel, CF_PROXY_MEDIA)) {
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "No SDP in INVITE and 3pcc=yes cannot work with bypass or proxy media, hanging up.\n");
|
||||
switch_channel_set_variable(channel, SWITCH_ENDPOINT_DISPOSITION_VARIABLE, "3PCC DISABLED");
|
||||
switch_channel_hangup(channel, SWITCH_CAUSE_MANDATORY_IE_MISSING);
|
||||
} else {
|
||||
} else {
|
||||
switch_channel_set_variable(channel, SWITCH_ENDPOINT_DISPOSITION_VARIABLE, "RECEIVED_NOSDP");
|
||||
sofia_glue_tech_choose_port(tech_pvt, 0);
|
||||
sofia_glue_set_local_sdp(tech_pvt, NULL, 0, NULL, 0);
|
||||
@@ -5812,23 +5867,23 @@ static void sofia_handle_sip_i_state(switch_core_session_t *session, int status,
|
||||
SIPTAG_CONTENT_TYPE_STR("application/sdp"), SIPTAG_PAYLOAD_STR(tech_pvt->local_sdp_str), TAG_END());
|
||||
}
|
||||
}
|
||||
} else if (sofia_test_pflag(profile, PFLAG_3PCC_PROXY)) {
|
||||
//3PCC proxy mode delays the 200 OK until the call is answered
|
||||
} else if (sofia_test_pflag(profile, PFLAG_3PCC_PROXY)) {
|
||||
//3PCC proxy mode delays the 200 OK until the call is answered
|
||||
// so can be made to work with bypass media as we have time to find out what the other end thinks codec offer should be...
|
||||
switch_channel_set_variable(channel, SWITCH_ENDPOINT_DISPOSITION_VARIABLE, "RECEIVED_NOSDP");
|
||||
sofia_set_flag_locked(tech_pvt, TFLAG_3PCC);
|
||||
//sofia_glue_tech_choose_port(tech_pvt, 0);
|
||||
//sofia_glue_set_local_sdp(tech_pvt, NULL, 0, NULL, 0);
|
||||
sofia_set_flag(tech_pvt, TFLAG_LATE_NEGOTIATION);
|
||||
//Moves into CS_INIT so call moves forward into the dialplan
|
||||
switch_channel_set_state(channel, CS_INIT);
|
||||
} else {
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "No SDP in INVITE and 3pcc not enabled, hanging up.\n");
|
||||
switch_channel_set_variable(channel, SWITCH_ENDPOINT_DISPOSITION_VARIABLE, "3PCC DISABLED");
|
||||
switch_channel_hangup(channel, SWITCH_CAUSE_MANDATORY_IE_MISSING);
|
||||
}
|
||||
goto done;
|
||||
switch_channel_set_variable(channel, SWITCH_ENDPOINT_DISPOSITION_VARIABLE, "RECEIVED_NOSDP");
|
||||
sofia_set_flag_locked(tech_pvt, TFLAG_3PCC);
|
||||
//sofia_glue_tech_choose_port(tech_pvt, 0);
|
||||
//sofia_glue_set_local_sdp(tech_pvt, NULL, 0, NULL, 0);
|
||||
sofia_set_flag(tech_pvt, TFLAG_LATE_NEGOTIATION);
|
||||
//Moves into CS_INIT so call moves forward into the dialplan
|
||||
switch_channel_set_state(channel, CS_INIT);
|
||||
} else {
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "No SDP in INVITE and 3pcc not enabled, hanging up.\n");
|
||||
switch_channel_set_variable(channel, SWITCH_ENDPOINT_DISPOSITION_VARIABLE, "3PCC DISABLED");
|
||||
switch_channel_hangup(channel, SWITCH_CAUSE_MANDATORY_IE_MISSING);
|
||||
}
|
||||
goto done;
|
||||
}
|
||||
|
||||
} else if (tech_pvt && sofia_test_flag(tech_pvt, TFLAG_SDP) && !r_sdp) {
|
||||
sofia_set_flag_locked(tech_pvt, TFLAG_NOSDP_REINVITE);
|
||||
@@ -5883,53 +5938,56 @@ static void sofia_handle_sip_i_state(switch_core_session_t *session, int status,
|
||||
switch_core_session_message_t *msg;
|
||||
|
||||
if (switch_channel_test_flag(channel, CF_PROXY_MODE) && !is_t38 && profile->media_options & MEDIA_OPT_MEDIA_ON_HOLD) {
|
||||
tech_pvt->hold_laps = 1;
|
||||
switch_channel_set_variable(channel, SWITCH_R_SDP_VARIABLE, r_sdp);
|
||||
switch_channel_clear_flag(channel, CF_PROXY_MODE);
|
||||
sofia_glue_tech_set_local_sdp(tech_pvt, NULL, SWITCH_FALSE);
|
||||
if (switch_stristr("sendonly", r_sdp) || switch_stristr("0.0.0.0", r_sdp)) {
|
||||
tech_pvt->hold_laps = 1;
|
||||
switch_channel_set_variable(channel, SWITCH_R_SDP_VARIABLE, r_sdp);
|
||||
switch_channel_clear_flag(channel, CF_PROXY_MODE);
|
||||
sofia_glue_tech_set_local_sdp(tech_pvt, NULL, SWITCH_FALSE);
|
||||
|
||||
if (!switch_channel_media_ready(channel)) {
|
||||
if (switch_channel_direction(tech_pvt->channel) == SWITCH_CALL_DIRECTION_INBOUND) {
|
||||
//const char *r_sdp = switch_channel_get_variable(channel, SWITCH_R_SDP_VARIABLE);
|
||||
if (!switch_channel_media_ready(channel)) {
|
||||
if (switch_channel_direction(tech_pvt->channel) == SWITCH_CALL_DIRECTION_INBOUND) {
|
||||
//const char *r_sdp = switch_channel_get_variable(channel, SWITCH_R_SDP_VARIABLE);
|
||||
|
||||
tech_pvt->num_codecs = 0;
|
||||
tech_pvt->num_codecs = 0;
|
||||
sofia_glue_tech_prepare_codecs(tech_pvt);
|
||||
if (sofia_glue_tech_media(tech_pvt, r_sdp) != SWITCH_STATUS_SUCCESS) {
|
||||
switch_channel_set_variable(channel, SWITCH_ENDPOINT_DISPOSITION_VARIABLE, "CODEC NEGOTIATION ERROR");
|
||||
status = SWITCH_STATUS_FALSE;
|
||||
switch_core_session_rwunlock(other_session);
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (!switch_rtp_ready(tech_pvt->rtp_session)) {
|
||||
sofia_glue_tech_prepare_codecs(tech_pvt);
|
||||
if (sofia_glue_tech_media(tech_pvt, r_sdp) != SWITCH_STATUS_SUCCESS) {
|
||||
switch_channel_set_variable(channel, SWITCH_ENDPOINT_DISPOSITION_VARIABLE, "CODEC NEGOTIATION ERROR");
|
||||
status = SWITCH_STATUS_FALSE;
|
||||
if ((status = sofia_glue_tech_choose_port(tech_pvt, 0)) != SWITCH_STATUS_SUCCESS) {
|
||||
switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
|
||||
switch_core_session_rwunlock(other_session);
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
}
|
||||
sofia_glue_set_local_sdp(tech_pvt, NULL, 0, NULL, 1);
|
||||
|
||||
if (!switch_rtp_ready(tech_pvt->rtp_session)) {
|
||||
sofia_glue_tech_prepare_codecs(tech_pvt);
|
||||
if ((status = sofia_glue_tech_choose_port(tech_pvt, 0)) != SWITCH_STATUS_SUCCESS) {
|
||||
switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
|
||||
switch_core_session_rwunlock(other_session);
|
||||
goto done;
|
||||
if (sofia_use_soa(tech_pvt)) {
|
||||
nua_respond(tech_pvt->nh, SIP_200_OK,
|
||||
SIPTAG_CONTACT_STR(tech_pvt->reply_contact),
|
||||
SOATAG_USER_SDP_STR(tech_pvt->local_sdp_str),
|
||||
SOATAG_REUSE_REJECTED(1),
|
||||
SOATAG_ORDERED_USER(1), SOATAG_AUDIO_AUX("cn telephone-event"),
|
||||
TAG_IF(sofia_test_pflag(profile, PFLAG_DISABLE_100REL), NUTAG_INCLUDE_EXTRA_SDP(1)), TAG_END());
|
||||
} else {
|
||||
nua_respond(tech_pvt->nh, SIP_200_OK,
|
||||
NUTAG_MEDIA_ENABLE(0),
|
||||
SIPTAG_CONTACT_STR(tech_pvt->reply_contact),
|
||||
SIPTAG_CONTENT_TYPE_STR("application/sdp"), SIPTAG_PAYLOAD_STR(tech_pvt->local_sdp_str), TAG_END());
|
||||
}
|
||||
}
|
||||
sofia_glue_set_local_sdp(tech_pvt, NULL, 0, NULL, 1);
|
||||
launch_media_on_hold(session);
|
||||
|
||||
if (sofia_use_soa(tech_pvt)) {
|
||||
nua_respond(tech_pvt->nh, SIP_200_OK,
|
||||
SIPTAG_CONTACT_STR(tech_pvt->reply_contact),
|
||||
SOATAG_USER_SDP_STR(tech_pvt->local_sdp_str),
|
||||
SOATAG_REUSE_REJECTED(1),
|
||||
SOATAG_ORDERED_USER(1), SOATAG_AUDIO_AUX("cn telephone-event"),
|
||||
TAG_IF(sofia_test_pflag(profile, PFLAG_DISABLE_100REL), NUTAG_INCLUDE_EXTRA_SDP(1)), TAG_END());
|
||||
} else {
|
||||
nua_respond(tech_pvt->nh, SIP_200_OK,
|
||||
NUTAG_MEDIA_ENABLE(0),
|
||||
SIPTAG_CONTACT_STR(tech_pvt->reply_contact),
|
||||
SIPTAG_CONTENT_TYPE_STR("application/sdp"), SIPTAG_PAYLOAD_STR(tech_pvt->local_sdp_str), TAG_END());
|
||||
switch_core_session_rwunlock(other_session);
|
||||
goto done;
|
||||
}
|
||||
launch_media_on_hold(session);
|
||||
|
||||
switch_core_session_rwunlock(other_session);
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (switch_channel_test_flag(channel, CF_PROXY_MEDIA)) {
|
||||
@@ -6212,6 +6270,8 @@ static void sofia_handle_sip_i_state(switch_core_session_t *session, int status,
|
||||
sofia_set_flag_locked(tech_pvt, TFLAG_ANS);
|
||||
|
||||
if (match) {
|
||||
switch_channel_check_zrtp(channel);
|
||||
|
||||
if (sofia_glue_tech_choose_port(tech_pvt, 0) == SWITCH_STATUS_SUCCESS) {
|
||||
if (sofia_glue_activate_rtp(tech_pvt, 0) == SWITCH_STATUS_SUCCESS) {
|
||||
switch_channel_mark_answered(channel);
|
||||
@@ -8000,12 +8060,62 @@ void sofia_handle_sip_i_invite(nua_t *nua, sofia_profile_t *profile, nua_handle_
|
||||
|
||||
if ((call_info = sip_call_info(sip))) {
|
||||
call_info_str = sip_header_as_string(nh->nh_home, (void *) call_info);
|
||||
|
||||
if (sofia_test_pflag(profile, PFLAG_MANAGE_SHARED_APPEARANCE) && switch_stristr("appearance", call_info_str)) {
|
||||
char *p;
|
||||
|
||||
switch_channel_set_variable(channel, "presence_call_info_full", call_info_str);
|
||||
if ((p = strchr(call_info_str, ';'))) {
|
||||
p++;
|
||||
switch_channel_set_variable(channel, "presence_call_info", p);
|
||||
}
|
||||
}
|
||||
|
||||
if (call_info->ci_params && (msg_params_find(call_info->ci_params, "answer-after=0"))) {
|
||||
switch_channel_set_variable(channel, "sip_auto_answer_detected", "true");
|
||||
}
|
||||
switch_channel_set_variable(channel, "sip_call_info", call_info_str);
|
||||
} else if (sofia_test_pflag(profile, PFLAG_MANAGE_SHARED_APPEARANCE)) {
|
||||
char buf[128] = "";
|
||||
char *sql;
|
||||
char *state = "progressing";
|
||||
|
||||
if (sip &&
|
||||
sip->sip_from && sip->sip_from->a_url && sip->sip_from->a_url->url_user && sip->sip_from->a_url->url_host &&
|
||||
sip->sip_to && sip->sip_to->a_url && sip->sip_to->a_url->url_user && sip->sip_to->a_url->url_host) {
|
||||
sql =
|
||||
switch_mprintf("select 'appearance-index=1' from sip_subscriptions where expires > -1 and hostname='%q' and event='call-info' and "
|
||||
"sub_to_user='%q' and sub_to_host='%q'", mod_sofia_globals.hostname, sip->sip_to->a_url->url_user,
|
||||
sip->sip_from->a_url->url_host);
|
||||
sofia_glue_execute_sql2str(profile, profile->ireg_mutex, sql, buf, sizeof(buf));
|
||||
|
||||
if (mod_sofia_globals.debug_sla > 1) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "QUERY SQL %s [%s]\n", sql, buf);
|
||||
}
|
||||
free(sql);
|
||||
|
||||
if (!zstr(buf)) {
|
||||
sql = switch_mprintf("update sip_dialogs set call_info='%q',call_info_state='%q' "
|
||||
"where uuid='%q'", buf, state, switch_core_session_get_uuid(session));
|
||||
|
||||
if (mod_sofia_globals.debug_sla > 1) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "QUERY SQL %s\n", sql);
|
||||
}
|
||||
|
||||
sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE);
|
||||
|
||||
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Auto-Fixing Broken SLA [<sip:%s>;%s]\n",
|
||||
sip->sip_from->a_url->url_host, buf);
|
||||
|
||||
switch_channel_set_variable_printf(channel, "presence_call_info_full", "<sip:%s>;%s", sip->sip_from->a_url->url_host, buf);
|
||||
switch_channel_set_variable(channel, "presence_call_info", buf);
|
||||
call_info_str = switch_core_session_sprintf(session, "<sip:%s>;%s", sip->sip_from->a_url->url_host, buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (profile->pres_type) {
|
||||
const char *presence_id = switch_channel_get_variable(channel, "presence_id");
|
||||
if (zstr(presence_id)) {
|
||||
@@ -8124,7 +8234,8 @@ void sofia_handle_sip_i_invite(nua_t *nua, sofia_profile_t *profile, nua_handle_
|
||||
|
||||
free(sql);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
check_decode(displayname, session);
|
||||
tech_pvt->caller_profile = switch_caller_profile_new(switch_core_session_get_pool(session),
|
||||
@@ -8176,7 +8287,7 @@ void sofia_handle_sip_i_invite(nua_t *nua, sofia_profile_t *profile, nua_handle_
|
||||
|
||||
|
||||
if (app && data && !strcasecmp(app, "conference")) {
|
||||
tech_pvt->caller_profile->destination_number = switch_core_sprintf(tech_pvt->caller_profile->pool, "answer,conference:%s", data);
|
||||
tech_pvt->caller_profile->destination_number = switch_core_sprintf(tech_pvt->caller_profile->pool, "answer,conference:%s+flags{dist-dtmf}", data);
|
||||
tech_pvt->caller_profile->dialplan = "inline";
|
||||
} else {
|
||||
if (switch_core_session_check_interface(b_session, sofia_endpoint_interface)) {
|
||||
@@ -8212,7 +8323,7 @@ void sofia_handle_sip_i_invite(nua_t *nua, sofia_profile_t *profile, nua_handle_
|
||||
if (!one_leg &&
|
||||
(!b_tech_pvt || !sofia_test_flag(b_tech_pvt, TFLAG_SIP_HOLD)) &&
|
||||
(!c_tech_pvt || !sofia_test_flag(c_tech_pvt, TFLAG_SIP_HOLD))) {
|
||||
char *ext = switch_core_session_sprintf(session, "answer,conference:%s@sla+flags{mintwo}", uuid);
|
||||
char *ext = switch_core_session_sprintf(session, "answer,conference:%s@sla+flags{mintwo|dist-dtmf}", uuid);
|
||||
|
||||
switch_channel_set_flag(c_channel, CF_REDIRECT);
|
||||
switch_ivr_session_transfer(b_session, ext, "inline", NULL);
|
||||
@@ -8225,7 +8336,7 @@ void sofia_handle_sip_i_invite(nua_t *nua, sofia_profile_t *profile, nua_handle_
|
||||
|
||||
if (do_conf) {
|
||||
tech_pvt->caller_profile->destination_number = switch_core_sprintf(tech_pvt->caller_profile->pool,
|
||||
"answer,conference:%s@sla+flags{mintwo}", uuid);
|
||||
"answer,conference:%s@sla+flags{mintwo|dist-dtmf}", uuid);
|
||||
} else {
|
||||
if (one_leg && c_app) {
|
||||
if (c_data) {
|
||||
@@ -8426,8 +8537,9 @@ void sofia_handle_sip_i_invite(nua_t *nua, sofia_profile_t *profile, nua_handle_
|
||||
|
||||
sql = switch_mprintf("insert into sip_dialogs "
|
||||
"(call_id,uuid,sip_to_user,sip_to_host,sip_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)",
|
||||
"contact_host,state,direction,user_agent,profile_name,hostname,contact,presence_id,presence_data,"
|
||||
"call_info,rcd,call_info_state) "
|
||||
"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, to_tag, dialog_from_user, dialog_from_host, from_tag,
|
||||
@@ -8493,7 +8605,8 @@ void sofia_handle_sip_i_options(int status,
|
||||
(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());
|
||||
nua_respond(nh, SIP_200_OK, NUTAG_WITH_THIS_MSG(de->data->e_msg),
|
||||
TAG_IF(sip->sip_record_route, SIPTAG_RECORD_ROUTE(sip->sip_record_route)), TAG_END());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -44,10 +44,10 @@ void sofia_glue_set_image_sdp(private_object_t *tech_pvt, switch_t38_options_t *
|
||||
char buf[2048] = "";
|
||||
char max_buf[128] = "";
|
||||
char max_data[128] = "";
|
||||
const char *ip = t38_options->local_ip;
|
||||
uint32_t port = t38_options->local_port;
|
||||
const char *ip;
|
||||
uint32_t port;
|
||||
const char *family = "IP4";
|
||||
const char *username = tech_pvt->profile->username;
|
||||
const char *username;
|
||||
const char *bit_removal_on = "a=T38FaxFillBitRemoval\n";
|
||||
const char *bit_removal_off = "";
|
||||
|
||||
@@ -59,6 +59,13 @@ void sofia_glue_set_image_sdp(private_object_t *tech_pvt, switch_t38_options_t *
|
||||
const char *var;
|
||||
int broken_boolean;
|
||||
|
||||
switch_assert(tech_pvt);
|
||||
switch_assert(t38_options);
|
||||
|
||||
ip = t38_options->local_ip;
|
||||
port = t38_options->local_port;
|
||||
username = tech_pvt->profile->username;
|
||||
|
||||
//sofia_clear_flag(tech_pvt, TFLAG_ENABLE_SOA);
|
||||
|
||||
var = switch_channel_get_variable(tech_pvt->channel, "t38_broken_boolean");
|
||||
@@ -177,7 +184,8 @@ static void generate_m(private_object_t *tech_pvt, char *buf, size_t buflen,
|
||||
int rate;
|
||||
int already_did[128] = { 0 };
|
||||
int ptime = 0, noptime = 0;
|
||||
|
||||
const char *zrtp;
|
||||
|
||||
switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "m=audio %d RTP/%sAVP",
|
||||
port, secure ? "S" : "");
|
||||
|
||||
@@ -336,6 +344,10 @@ static void generate_m(private_object_t *tech_pvt, char *buf, size_t buflen,
|
||||
switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=ptime:%d\n", cur_ptime);
|
||||
}
|
||||
|
||||
if ((zrtp = switch_channel_get_variable(tech_pvt->channel, "sdp_zrtp_hash_string"))) {
|
||||
switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=zrtp-hash:%s\n", zrtp);
|
||||
}
|
||||
|
||||
if (sr) {
|
||||
switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=%s\n", sr);
|
||||
}
|
||||
@@ -379,6 +391,7 @@ void sofia_glue_set_local_sdp(private_object_t *tech_pvt, const char *ip, switch
|
||||
switch_event_t *map = NULL, *ptmap = NULL;
|
||||
const char *b_sdp = NULL;
|
||||
int verbose_sdp = 0;
|
||||
const char *zrtp;
|
||||
|
||||
sofia_glue_check_dtmf_type(tech_pvt);
|
||||
|
||||
@@ -532,6 +545,10 @@ void sofia_glue_set_local_sdp(private_object_t *tech_pvt, const char *ip, switch
|
||||
switch_snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "a=ptime:%d\n", ptime);
|
||||
}
|
||||
|
||||
if ((zrtp = switch_channel_get_variable(tech_pvt->channel, "sdp_zrtp_hash_string"))) {
|
||||
switch_snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "a=zrtp-hash:%s\n", zrtp);
|
||||
}
|
||||
|
||||
if (sr) {
|
||||
switch_snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "a=%s\n", sr);
|
||||
}
|
||||
@@ -558,13 +575,22 @@ void sofia_glue_set_local_sdp(private_object_t *tech_pvt, const char *ip, switch
|
||||
|
||||
if (mult && switch_false(mult)) {
|
||||
char *bp = buf;
|
||||
|
||||
int both = 1;
|
||||
|
||||
if ((!zstr(tech_pvt->local_crypto_key) && sofia_test_flag(tech_pvt, TFLAG_SECURE))) {
|
||||
generate_m(tech_pvt, buf, sizeof(buf), port, 0, append_audio, sr, use_cng, cng_type, map, verbose_sdp, 1);
|
||||
bp = (buf + strlen(buf));
|
||||
|
||||
/* asterisk can't handle AVP and SAVP in sep streams, way to blow off the spec....*/
|
||||
if (switch_true(switch_channel_get_variable(tech_pvt->channel, "sdp_secure_savp_only"))) {
|
||||
both = 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
generate_m(tech_pvt, bp, sizeof(buf) - strlen(buf), port, 0, append_audio, sr, use_cng, cng_type, map, verbose_sdp, 0);
|
||||
if (both) {
|
||||
generate_m(tech_pvt, bp, sizeof(buf) - strlen(buf), port, 0, append_audio, sr, use_cng, cng_type, map, verbose_sdp, 0);
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
@@ -583,14 +609,23 @@ void sofia_glue_set_local_sdp(private_object_t *tech_pvt, const char *ip, switch
|
||||
|
||||
if (cur_ptime != this_ptime) {
|
||||
char *bp = buf;
|
||||
cur_ptime = this_ptime;
|
||||
int both = 1;
|
||||
|
||||
cur_ptime = this_ptime;
|
||||
|
||||
if ((!zstr(tech_pvt->local_crypto_key) && sofia_test_flag(tech_pvt, TFLAG_SECURE))) {
|
||||
generate_m(tech_pvt, buf, sizeof(buf), port, cur_ptime, append_audio, sr, use_cng, cng_type, map, verbose_sdp, 1);
|
||||
bp = (buf + strlen(buf));
|
||||
|
||||
/* asterisk can't handle AVP and SAVP in sep streams, way to blow off the spec....*/
|
||||
if (switch_true(switch_channel_get_variable(tech_pvt->channel, "sdp_secure_savp_only"))) {
|
||||
both = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (both) {
|
||||
generate_m(tech_pvt, bp, sizeof(buf) - strlen(buf), port, cur_ptime, append_audio, sr, use_cng, cng_type, map, verbose_sdp, 0);
|
||||
}
|
||||
|
||||
generate_m(tech_pvt, bp, sizeof(buf) - strlen(buf), port, cur_ptime, append_audio, sr, use_cng, cng_type, map, verbose_sdp, 0);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -762,6 +797,11 @@ void sofia_glue_tech_prepare_codecs(private_object_t *tech_pvt)
|
||||
switch_assert(tech_pvt->session != NULL);
|
||||
|
||||
if ((abs = switch_channel_get_variable(tech_pvt->channel, "absolute_codec_string"))) {
|
||||
/* inherit_codec == true will implicitly clear the absolute_codec_string
|
||||
variable if used since it was the reason it was set in the first place and is no longer needed */
|
||||
if (switch_true(switch_channel_get_variable(tech_pvt->channel, "inherit_codec"))) {
|
||||
switch_channel_set_variable(tech_pvt->channel, "absolute_codec_string", NULL);
|
||||
}
|
||||
codec_string = abs;
|
||||
goto ready;
|
||||
}
|
||||
@@ -1968,6 +2008,30 @@ void sofia_glue_set_extra_headers(switch_core_session_t *session, sip_t const *s
|
||||
switch_channel_api_on(channel, "api_on_sip_extra_headers");
|
||||
}
|
||||
|
||||
char *sofia_glue_get_extra_headers_from_event(switch_event_t *event, const char *prefix)
|
||||
{
|
||||
char *extra_headers = NULL;
|
||||
switch_stream_handle_t stream = { 0 };
|
||||
switch_event_header_t *hp;
|
||||
|
||||
SWITCH_STANDARD_STREAM(stream);
|
||||
for (hp = event->headers; hp; hp = hp->next) {
|
||||
if (!zstr(hp->name) && !zstr(hp->value) && !strncasecmp(hp->name, prefix, strlen(prefix))) {
|
||||
char *name = strdup(hp->name);
|
||||
const char *hname = name + strlen(prefix);
|
||||
stream.write_function(&stream, "%s: %s\r\n", hname, (char *)hp->value);
|
||||
free(name);
|
||||
}
|
||||
}
|
||||
|
||||
if (!zstr((char *) stream.data)) {
|
||||
extra_headers = stream.data;
|
||||
} else {
|
||||
switch_safe_free(stream.data);
|
||||
}
|
||||
|
||||
return extra_headers;
|
||||
}
|
||||
|
||||
switch_status_t sofia_glue_do_invite(switch_core_session_t *session)
|
||||
{
|
||||
@@ -2291,6 +2355,29 @@ switch_status_t sofia_glue_do_invite(switch_core_session_t *session)
|
||||
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 (!switch_channel_get_variable(channel, "presence_id")) {
|
||||
char *from = switch_core_session_strdup(session, from_str);
|
||||
const char *s;
|
||||
|
||||
if ((s = switch_stristr("<", from))) {
|
||||
from = (char *)s + 1;
|
||||
}
|
||||
|
||||
if (!strncasecmp(from, "sip:", 4)) {
|
||||
from += 4;
|
||||
}
|
||||
|
||||
if (!strncasecmp(from, "sips:", 5)) {
|
||||
from += 5;
|
||||
}
|
||||
|
||||
if ((p = strchr(from, ':')) || (p = strchr(from, ';')) || (p = strchr(from, '>'))) {
|
||||
*p++ = '\0';
|
||||
}
|
||||
|
||||
switch_channel_set_variable(channel, "presence_id", from);
|
||||
}
|
||||
|
||||
if (!(tech_pvt->nh = nua_handle(tech_pvt->profile->nua, NULL,
|
||||
NUTAG_URL(url_str),
|
||||
TAG_IF(call_id, SIPTAG_CALL_ID_STR(call_id)),
|
||||
@@ -2352,11 +2439,22 @@ switch_status_t sofia_glue_do_invite(switch_core_session_t *session)
|
||||
switch (cid_type) {
|
||||
case CID_TYPE_PID:
|
||||
if (switch_test_flag(caller_profile, SWITCH_CPF_SCREEN)) {
|
||||
tech_pvt->asserted_id = switch_core_session_sprintf(tech_pvt->session, "\"%s\"<sip:%s@%s>", use_name, use_number, rpid_domain);
|
||||
if (zstr(tech_pvt->caller_profile->caller_id_name) || !strcasecmp(tech_pvt->caller_profile->caller_id_name, "_undef_")) {
|
||||
tech_pvt->asserted_id = switch_core_session_sprintf(tech_pvt->session, "<sip:%s@%s>",
|
||||
use_number, rpid_domain);
|
||||
} else {
|
||||
tech_pvt->asserted_id = switch_core_session_sprintf(tech_pvt->session, "\"%s\"<sip:%s@%s>",
|
||||
use_name, use_number, rpid_domain);
|
||||
}
|
||||
} else {
|
||||
tech_pvt->preferred_id = switch_core_session_sprintf(tech_pvt->session, "\"%s\"<sip:%s@%s>",
|
||||
tech_pvt->caller_profile->caller_id_name,
|
||||
tech_pvt->caller_profile->caller_id_number, rpid_domain);
|
||||
if (zstr(tech_pvt->caller_profile->caller_id_name) || !strcasecmp(tech_pvt->caller_profile->caller_id_name, "_undef_")) {
|
||||
tech_pvt->preferred_id = switch_core_session_sprintf(tech_pvt->session, "<sip:%s@%s>",
|
||||
tech_pvt->caller_profile->caller_id_number, rpid_domain);
|
||||
} else {
|
||||
tech_pvt->preferred_id = switch_core_session_sprintf(tech_pvt->session, "\"%s\"<sip:%s@%s>",
|
||||
tech_pvt->caller_profile->caller_id_name,
|
||||
tech_pvt->caller_profile->caller_id_number, rpid_domain);
|
||||
}
|
||||
}
|
||||
|
||||
if (switch_test_flag(caller_profile, SWITCH_CPF_HIDE_NUMBER)) {
|
||||
@@ -2503,7 +2601,7 @@ switch_status_t sofia_glue_do_invite(switch_core_session_t *session)
|
||||
} else {
|
||||
tech_pvt->session_refresher = nua_no_refresher;
|
||||
}
|
||||
|
||||
|
||||
if (sofia_use_soa(tech_pvt)) {
|
||||
nua_invite(tech_pvt->nh,
|
||||
NUTAG_AUTOANSWER(0),
|
||||
@@ -2517,8 +2615,8 @@ switch_status_t sofia_glue_do_invite(switch_core_session_t *session)
|
||||
TAG_IF(invite_full_from, SIPTAG_FROM_STR(invite_full_from)),
|
||||
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(recover_via), SIPTAG_VIA_STR(recover_via)),
|
||||
TAG_IF(!zstr(tech_pvt->user_via), SIPTAG_VIA_STR(tech_pvt->user_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)),
|
||||
@@ -2551,8 +2649,8 @@ switch_status_t sofia_glue_do_invite(switch_core_session_t *session)
|
||||
TAG_IF(invite_full_from, SIPTAG_FROM_STR(invite_full_from)),
|
||||
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(recover_via), SIPTAG_VIA_STR(recover_via)),
|
||||
TAG_IF(!zstr(tech_pvt->user_via), SIPTAG_VIA_STR(tech_pvt->user_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)),
|
||||
@@ -3475,6 +3573,14 @@ switch_status_t sofia_glue_activate_rtp(private_object_t *tech_pvt, switch_rtp_f
|
||||
switch_channel_set_variable(tech_pvt->channel, SWITCH_REMOTE_MEDIA_IP_VARIABLE, tech_pvt->remote_sdp_audio_ip);
|
||||
switch_channel_set_variable(tech_pvt->channel, SWITCH_REMOTE_MEDIA_PORT_VARIABLE, tmp);
|
||||
|
||||
|
||||
if (switch_channel_test_flag(tech_pvt->channel, CF_ZRTP_PASS)) {
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_INFO, "Activating ZRTP PROXY MODE\n");
|
||||
sofia_clear_flag(tech_pvt, TFLAG_NOTIMER_DURING_BRIDGE);
|
||||
switch_rtp_udptl_mode(tech_pvt->rtp_session);
|
||||
}
|
||||
|
||||
|
||||
video:
|
||||
|
||||
sofia_glue_check_video_codecs(tech_pvt);
|
||||
@@ -3969,7 +4075,6 @@ int sofia_glue_toggle_hold(private_object_t *tech_pvt, int sendonly)
|
||||
}
|
||||
|
||||
sofia_set_flag_locked(tech_pvt, TFLAG_SIP_HOLD);
|
||||
switch_channel_set_flag(tech_pvt->channel, CF_LEG_HOLDING);
|
||||
switch_channel_mark_hold(tech_pvt->channel, SWITCH_TRUE);
|
||||
switch_channel_presence(tech_pvt->channel, "unknown", msg, NULL);
|
||||
changed = 1;
|
||||
@@ -3997,7 +4102,6 @@ int sofia_glue_toggle_hold(private_object_t *tech_pvt, int sendonly)
|
||||
} else {
|
||||
if (sofia_test_flag(tech_pvt, TFLAG_HOLD_LOCK)) {
|
||||
sofia_set_flag(tech_pvt, TFLAG_SIP_HOLD);
|
||||
switch_channel_set_flag(tech_pvt->channel, CF_LEG_HOLDING);
|
||||
switch_channel_mark_hold(tech_pvt->channel, SWITCH_TRUE);
|
||||
changed = 1;
|
||||
}
|
||||
@@ -4030,7 +4134,6 @@ int sofia_glue_toggle_hold(private_object_t *tech_pvt, int sendonly)
|
||||
}
|
||||
|
||||
sofia_clear_flag_locked(tech_pvt, TFLAG_SIP_HOLD);
|
||||
switch_channel_clear_flag(tech_pvt->channel, CF_LEG_HOLDING);
|
||||
switch_channel_mark_hold(tech_pvt->channel, SWITCH_FALSE);
|
||||
switch_channel_presence(tech_pvt->channel, "unknown", "unhold", NULL);
|
||||
changed = 1;
|
||||
@@ -4398,9 +4501,12 @@ uint8_t sofia_glue_negotiate_sdp(switch_core_session_t *session, const char *r_s
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!strcasecmp(attr->a_name, "sendonly") || !strcasecmp(attr->a_name, "inactive")) {
|
||||
if (!strcasecmp(attr->a_name, "sendonly")) {
|
||||
sendonly = 1;
|
||||
switch_channel_set_variable(tech_pvt->channel, "media_audio_mode", "recvonly");
|
||||
} else if (!strcasecmp(attr->a_name, "inactive")) {
|
||||
sendonly = 1;
|
||||
switch_channel_set_variable(tech_pvt->channel, "media_audio_mode", "inactive");
|
||||
} else if (!strcasecmp(attr->a_name, "recvonly")) {
|
||||
switch_channel_set_variable(tech_pvt->channel, "media_audio_mode", "sendonly");
|
||||
recvonly = 1;
|
||||
@@ -4580,12 +4686,13 @@ uint8_t sofia_glue_negotiate_sdp(switch_core_session_t *session, const char *r_s
|
||||
|
||||
if (!strcasecmp(attr->a_name, "rtcp") && attr->a_value) {
|
||||
switch_channel_set_variable(tech_pvt->channel, "sip_remote_audio_rtcp_port", attr->a_value);
|
||||
}
|
||||
|
||||
if (!strcasecmp(attr->a_name, "ptime") && attr->a_value) {
|
||||
} else if (!strcasecmp(attr->a_name, "ptime") && attr->a_value) {
|
||||
ptime = atoi(attr->a_value);
|
||||
} else if (!strcasecmp(attr->a_name, "maxptime") && attr->a_value) {
|
||||
maxptime = atoi(attr->a_value);
|
||||
} else if (!strcasecmp(attr->a_name, "zrtp-hash") && attr->a_value) {
|
||||
switch_channel_set_variable(tech_pvt->channel, "sdp_zrtp_hash_string", attr->a_value);
|
||||
switch_channel_set_flag(tech_pvt->channel, CF_ZRTP_HASH);
|
||||
} else if (!got_crypto && !strcasecmp(attr->a_name, "crypto") && !zstr(attr->a_value)) {
|
||||
int crypto_tag;
|
||||
|
||||
@@ -4599,7 +4706,8 @@ uint8_t sofia_glue_negotiate_sdp(switch_core_session_t *session, const char *r_s
|
||||
crypto_tag = atoi(crypto);
|
||||
|
||||
if (tech_pvt->remote_crypto_key && switch_rtp_ready(tech_pvt->rtp_session)) {
|
||||
if (crypto_tag && crypto_tag == tech_pvt->crypto_tag) {
|
||||
/* Compare all the key. The tag may remain the same even if key changed */
|
||||
if (crypto && !strcmp(crypto, tech_pvt->remote_crypto_key)) {
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Existing key is still valid.\n");
|
||||
} else {
|
||||
const char *a = switch_stristr("AES", tech_pvt->remote_crypto_key);
|
||||
@@ -5139,6 +5247,8 @@ char *sofia_glue_get_url_from_contact(char *buf, uint8_t to_dup)
|
||||
{
|
||||
char *url = NULL, *e;
|
||||
|
||||
switch_assert(buf);
|
||||
|
||||
while(*buf == ' ') {
|
||||
buf++;
|
||||
}
|
||||
@@ -5956,7 +6066,7 @@ int sofia_glue_init_sql(sofia_profile_t *profile)
|
||||
" presence_id VARCHAR(255),\n"
|
||||
" presence_data VARCHAR(255),\n"
|
||||
" call_info VARCHAR(255),\n"
|
||||
" call_info_state VARCHAR(255),\n"
|
||||
" call_info_state VARCHAR(255) default '',\n"
|
||||
" expires INTEGER default 0,\n"
|
||||
" status VARCHAR(255),\n"
|
||||
" rpid VARCHAR(255),\n"
|
||||
@@ -6868,24 +6978,6 @@ char *sofia_glue_gen_contact_str(sofia_profile_t *profile, sip_t const *sip, nua
|
||||
np->is_nat = NULL;
|
||||
}
|
||||
|
||||
if (zstr(contact_host)) {
|
||||
np->is_nat = "No contact host";
|
||||
}
|
||||
|
||||
|
||||
if (np->is_nat && !np->fs_path) {
|
||||
contact_host = np->network_ip;
|
||||
switch_snprintf(new_port, sizeof(new_port), ":%d", np->network_port);
|
||||
port = NULL;
|
||||
}
|
||||
|
||||
|
||||
if (port) {
|
||||
switch_snprintf(new_port, sizeof(new_port), ":%s", port);
|
||||
}
|
||||
|
||||
ipv6 = strchr(contact_host, ':');
|
||||
|
||||
if (np->is_nat && np->fs_path) {
|
||||
char *full_contact = sip_header_as_string(nh->nh_home, (void *) contact);
|
||||
char *full_contact_dup;
|
||||
@@ -6918,6 +7010,25 @@ char *sofia_glue_gen_contact_str(sofia_profile_t *profile, sip_t const *sip, nua
|
||||
free(path_val);
|
||||
|
||||
} else {
|
||||
|
||||
if (zstr(contact_host)) {
|
||||
np->is_nat = "No contact host";
|
||||
}
|
||||
|
||||
if (np->is_nat) {
|
||||
contact_host = np->network_ip;
|
||||
switch_snprintf(new_port, sizeof(new_port), ":%d", np->network_port);
|
||||
port = NULL;
|
||||
}
|
||||
|
||||
|
||||
if (port) {
|
||||
switch_snprintf(new_port, sizeof(new_port), ":%s", port);
|
||||
}
|
||||
|
||||
ipv6 = strchr(contact_host, ':');
|
||||
|
||||
|
||||
if (contact->m_url->url_params) {
|
||||
contact_str = switch_mprintf("%s <sip:%s@%s%s%s%s;%s>%s",
|
||||
display, contact->m_url->url_user,
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user