Merge branch 'master' of ssh://git.freeswitch.org:222/freeswitch

This commit is contained in:
David Yat Sin 2011-06-06 10:57:30 -04:00
commit feb21920db
49 changed files with 1833 additions and 321 deletions

View File

@ -32,4 +32,187 @@
<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>

View File

@ -94,16 +94,16 @@
<input pattern="^([0-9#*]),([0-9#*]),([0-9#*]),([0-9#*])$">
<match>
<action function="play-file" data="directory/dir-to_select_entry.wav"/>
<action function="play-file" data="directory/dir-press.wav"/>
<action function="play-file" data="voicemail/vm-press.wav"/>
<action function="say" data="$1" method="pronounced" type="name_spelled"/>
<action function="play-file" data="directory/dir-for_next.wav"/>
<action function="play-file" data="directory/dir-press.wav"/>
<action function="play-file" data="voicemail/vm-press.wav"/>
<action function="say" data="$2" method="pronounced" type="name_spelled"/>
<action function="play-file" data="directory/dir-for_prev.wav"/>
<action function="play-file" data="directory/dir-press.wav"/>
<action function="play-file" data="voicemail/vm-press.wav"/>
<action function="say" data="$3" method="pronounced" type="name_spelled"/>
<action function="play-file" data="directory/dir-start_new_search.wav"/>
<action function="play-file" data="directory/dir-press.wav"/>
<action function="play-file" data="voicemail/vm-press.wav"/>
<action function="say" data="$4" method="pronounced" type="name_spelled"/>
</match>

View File

@ -6,6 +6,7 @@
<!--voicemail_en_tts is purely implemented with tts, we have the files based one that is the default. -->
<X-PRE-PROCESS cmd="include" data="vm/sounds.xml"/> <!-- vm/tts.xml if you want to use tts and have cepstral -->
<X-PRE-PROCESS cmd="include" data="dir/sounds.xml"/> <!-- dir/tts.xml if you want to use tts and have cepstral -->
<X-PRE-PROCESS cmd="include" data="ivr/*.xml"/> <!-- IVR and custom phrases go here -->
</macros>
</phrases>
</language>

6
debian/changelog vendored
View File

@ -1,3 +1,9 @@
freeswitch (1.0.head-git.master.20110530.1-1) unstable; urgency=low
* added mod_cdr_sqlite
-- Michal Bielicki <michal.bielicki@seventhsignal.de> Mon, 30 May 2011 16:02:02 +0200
freeswitch (1.0.head-git.master.20110402.1-1) unstable; urgency=low
* Added Hebrew lang package

View File

@ -155,6 +155,7 @@ opt/freeswitch/mod/mod_skinny.so*
opt/freeswitch/mod/mod_skypopen.so*
opt/freeswitch/mod/mod_sndfile.so*
opt/freeswitch/mod/mod_snom.so*
opt/freeswitch/mod/mod_cdr_sqlite.so*
opt/freeswitch/mod/mod_sofia.so*
opt/freeswitch/mod/mod_spandsp.so*
opt/freeswitch/mod/mod_speex.so*

2
debian/rules vendored
View File

@ -23,7 +23,7 @@ export CODECS_MODULES= codecs/mod_bv codecs/mod_h26x codecs/mod_speex codecs/mod
export DIALPLANS_MODULES= dialplans/mod_dialplan_asterisk dialplans/mod_dialplan_directory dialplans/mod_dialplan_xml
export ENDPOINTS_MODULES= endpoints/mod_dingaling endpoints/mod_portaudio endpoints/mod_sofia endpoints/mod_loopback \
../../libs/freetdm/mod_freetdm endpoints/mod_skypopen endpoints/mod_skinny
export EVENT_HANDLERS_MODULES=event_handlers/mod_event_multicast event_handlers/mod_event_socket event_handlers/mod_cdr_csv
export EVENT_HANDLERS_MODULES=event_handlers/mod_event_multicast event_handlers/mod_event_socket event_handlers/mod_cdr_csv event_handlers/mod_cdr_sqlite
export FORMATS_MODULES= formats/mod_local_stream formats/mod_native_file formats/mod_portaudio_stream \
formats/mod_shout formats/mod_sndfile formats/mod_tone_stream
export LANGUAGES_MODULES=languages/mod_spidermonkey languages/mod_perl languages/mod_lua languages/mod_python

View File

@ -492,6 +492,8 @@
<!-- The following phrases still need to be recorded -->
<prompt phrase="This conference is full. Please contact the conference moderator." filename="conf-conference_is_full.wav"/>
<prompt phrase="You do not have permission to perform this action." filename="ivr-not_have_permission.wav"/>
<prompt phrase="" filename=""/>
</ivr>
<misc>

View File

@ -5,7 +5,7 @@
#
# includes module(s): freeswitch-devel freeswitch-codec-passthru-amr freeswitch-codec-passthru-amrwb freeswitch-codec-passthru-g729
# freeswitch-codec-passthru-g7231 freeswitch-lua freeswitch-perl freeswitch-python freeswitch-spidermonkey
# freeswitch-lan-de freeswitch-lang-en freeswitch-lang-fr freeswitch-lang-ru freeswitch-freetdm
# freeswitch-lan-de freeswitch-lang-en freeswitch-lang-fr freeswitch-lang-hu freeswitch-lang-ru freeswitch-freetdm
#
# Initial Version Copyright (C) 2007 Peter Nixon and Michal Bielicki, All Rights Reserved.
#

11
libs/.gitignore vendored
View File

@ -276,6 +276,17 @@
/ldns/packaging/ldns-config
/ldns/packaging/libldns.pc
/ldns-1.6.9/
/libcodec2/src/c2dec
/libcodec2/src/c2enc
/libcodec2/src/c2sim
/libcodec2/unittest/extract
/libcodec2/unittest/genlsp
/libcodec2/unittest/genres
/libcodec2/unittest/tcodec2
/libcodec2/unittest/tinterp
/libcodec2/unittest/tnlp
/libcodec2/unittest/tquant
/libcodec2/unittest/vqtrain
/libdingaling/Makefile
/libdingaling/Makefile.in
/libdingaling/aclocal.m4

View File

@ -365,7 +365,6 @@ ESL_DECLARE(int) esl_event_add_array(esl_event_t *event, const char *var, const
{
char *data;
char **array;
int idx;
int max = 0;
int len;
const char *p;
@ -395,7 +394,7 @@ ESL_DECLARE(int) esl_event_add_array(esl_event_t *event, const char *var, const
esl_assert(array);
memset(array, 0, len);
idx = esl_separate_string_string(data, "|:", array, max);
esl_separate_string_string(data, "|:", array, max);
for(i = 0; i < max; i++) {
esl_event_add_header_string(event, ESL_STACK_PUSH, var, array[i]);
@ -479,6 +478,13 @@ static esl_status_t esl_event_base_add_header(esl_event_t *event, esl_stack_t st
if (!header) {
if (esl_strlen_zero(data)) {
esl_event_del_header(event, header_name);
FREE(data);
goto end;
}
if (esl_test_flag(event, ESL_EF_UNIQ_HEADERS)) {
esl_event_del_header(event, header_name);
}

View File

@ -1072,16 +1072,20 @@ static __inline__ ftdm_status_t zt_channel_process_event(ftdm_channel_t *fchan,
break;
case ZT_EVENT_BADFCS:
{
ftdm_log_chan_msg(fchan, FTDM_LOG_ERROR, "Bad frame checksum (ZT_EVENT_BADFCS)!\n");
/* What else could we do? */
*event_id = FTDM_OOB_NOOP;
ftdm_log_chan_msg(fchan, FTDM_LOG_ERROR, "Bad frame checksum (ZT_EVENT_BADFCS)\n");
*event_id = FTDM_OOB_NOOP; /* What else could we do? */
}
break;
case ZT_EVENT_OVERRUN:
{
ftdm_log_chan_msg(fchan, FTDM_LOG_ERROR, "Driver overrun! (ZT_EVENT_OVERRUN)\n");
/* What else could we do? */
*event_id = FTDM_OOB_NOOP;
ftdm_log_chan_msg(fchan, FTDM_LOG_ERROR, "HDLC frame overrun (ZT_EVENT_OVERRUN)\n");
*event_id = FTDM_OOB_NOOP; /* What else could we do? */
}
break;
case ZT_EVENT_ABORT:
{
ftdm_log_chan_msg(fchan, FTDM_LOG_ERROR, "HDLC abort frame received (ZT_EVENT_ABORT)\n");
*event_id = FTDM_OOB_NOOP; /* What else could we do? */
}
break;
case ZT_EVENT_NONE:

View File

@ -231,7 +231,7 @@ void stfu_n_debug(stfu_instance_t *i, const char *name)
void stfu_n_report(stfu_instance_t *i, stfu_report_t *r)
{
assert(i);
stfu_assert(i);
r->qlen = i->qlen;
r->packet_in_count = i->period_packet_in_count;
r->clean_count = i->period_clean_count;
@ -580,7 +580,7 @@ static int stfu_n_find_any_frame(stfu_instance_t *in, stfu_queue_t *queue, stfu_
uint32_t i = 0;
stfu_frame_t *frame = NULL;
assert(r_frame);
stfu_assert(r_frame);
*r_frame = NULL;

View File

@ -40,6 +40,13 @@ extern "C" {
#include <string.h>
#include <stdarg.h>
#if (_MSC_VER >= 1400) // VC8+
#define stfu_assert(expr) assert(expr);__analysis_assume( expr )
#endif
#ifndef stfu_assert
#define stfu_assert(_x) assert(_x)
#endif
#ifdef _MSC_VER
#ifndef uint32_t

View File

@ -248,6 +248,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_bug_close(_Inout_ switch_media
SWITCH_DECLARE(switch_status_t) switch_core_media_bug_remove_all(_In_ switch_core_session_t *session);
SWITCH_DECLARE(switch_status_t) switch_core_media_bug_enumerate(switch_core_session_t *session, switch_stream_handle_t *stream);
SWITCH_DECLARE(switch_status_t) switch_core_media_bug_transfer_recordings(switch_core_session_t *orig_session, switch_core_session_t *new_session);
/*!
\brief Read a frame from the bug

View File

@ -62,6 +62,12 @@ SWITCH_BEGIN_EXTERN_C struct switch_unicast_conninfo {
};
typedef struct switch_unicast_conninfo switch_unicast_conninfo_t;
#define SWITCH_IVR_VERIFY_SILENCE_DIVISOR(divisor) \
{ \
if ((divisor) <= 0 && (divisor) != -1) { \
divisor = 400; \
} \
}
/**
* @defgroup switch_ivr IVR Library

View File

@ -137,17 +137,14 @@ typedef int gid_t;
#ifdef WIN32
#if defined(SWITCH_CORE_DECLARE_STATIC)
#define SWITCH_DECLARE(type) type __stdcall
#define SWITCH_DECLARE_TYPEDEF(type, name) type (__stdcall name)
#define SWITCH_DECLARE_NONSTD(type) type __cdecl
#define SWITCH_DECLARE_DATA
#elif defined(FREESWITCHCORE_EXPORTS)
#define SWITCH_DECLARE(type) __declspec(dllexport) type __stdcall
#define SWITCH_DECLARE_TYPEDEF(type, name) __declspec(dllexport) type (__stdcall name)
#define SWITCH_DECLARE_NONSTD(type) __declspec(dllexport) type __cdecl
#define SWITCH_DECLARE_DATA __declspec(dllexport)
#else
#define SWITCH_DECLARE(type) __declspec(dllimport) type __stdcall
#define SWITCH_DECLARE_TYPEDEF(type, name) __declspec(dllimport) type (__stdcall name)
#define SWITCH_DECLARE_NONSTD(type) __declspec(dllimport) type __cdecl
#define SWITCH_DECLARE_DATA __declspec(dllimport)
#endif
@ -177,7 +174,6 @@ typedef int gid_t;
#define O_BINARY 0
#if (defined(__GNUC__) || defined(__SUNPRO_CC) || defined (__SUNPRO_C)) && defined(SWITCH_API_VISIBILITY)
#define SWITCH_DECLARE(type) __attribute__((visibility("default"))) type
#define SWITCH_DECLARE_TYPEDEF(type, name) type (name)
#define SWITCH_DECLARE_NONSTD(type) __attribute__((visibility("default"))) type
#define SWITCH_DECLARE_DATA __attribute__((visibility("default")))
#define SWITCH_MOD_DECLARE(type) __attribute__((visibility("default"))) type
@ -186,7 +182,6 @@ typedef int gid_t;
#define SWITCH_DECLARE_CLASS __attribute__((visibility("default")))
#else
#define SWITCH_DECLARE(type) type
#define SWITCH_DECLARE_TYPEDEF(type, name) type (name)
#define SWITCH_DECLARE_NONSTD(type) type
#define SWITCH_DECLARE_DATA
#define SWITCH_MOD_DECLARE(type) type

View File

@ -73,7 +73,7 @@ SWITCH_DECLARE(switch_status_t) switch_regex_match_partial(const char *target, c
SWITCH_DECLARE(void) switch_capture_regex(switch_regex_t *re, int match_count, const char *field_data,
int *ovector, const char *var, switch_cap_callback_t callback, void *user_data);
SWITCH_DECLARE(void) switch_regex_set_var_callback(const char *var, const char *val, void *user_data);
SWITCH_DECLARE_NONSTD(void) switch_regex_set_var_callback(const char *var, const char *val, void *user_data);
#define switch_regex_safe_free(re) if (re) {\
switch_regex_free(re);\

View File

@ -1690,7 +1690,7 @@ struct switch_console_callback_match {
};
typedef struct switch_console_callback_match switch_console_callback_match_t;
typedef SWITCH_DECLARE_TYPEDEF(void, *switch_cap_callback_t) (const char *var, const char *val, void *user_data);
typedef void (*switch_cap_callback_t) (const char *var, const char *val, void *user_data);
typedef switch_status_t (*switch_console_complete_callback_t) (const char *, const char *, switch_console_callback_match_t **matches);
typedef switch_bool_t (*switch_media_bug_callback_t) (switch_media_bug_t *, void *, switch_abc_type_t);
typedef switch_bool_t (*switch_tone_detect_callback_t) (switch_core_session_t *, const char *, const char *);

View File

@ -793,9 +793,9 @@ SWITCH_DECLARE(int) switch_split_user_domain(char *in, char **user, char **domai
/* malloc or DIE macros */
#ifdef NDEBUG
#define switch_malloc(ptr, len) (void)( (!!(ptr = malloc(len))) || (fprintf(stderr,"ABORT! Malloc failure at: %s:%s", __FILE__, __LINE__),abort(), 0), ptr )
#define switch_zmalloc(ptr, len) (void)( (!!(ptr = calloc(1, (len)))) || (fprintf(stderr,"ABORT! Malloc failure at: %s:%s", __FILE__, __LINE__),abort(), 0), ptr)
#define switch_strdup(ptr, s) (void)( (!!(ptr = strdup(s))) || (fprintf(stderr,"ABORT! Malloc failure at: %s:%s", __FILE__, __LINE__),abort(), 0), ptr)
#define switch_malloc(ptr, len) (void)( (!!(ptr = malloc(len))) || (fprintf(stderr,"ABORT! Malloc failure at: %s:%d", __FILE__, __LINE__),abort(), 0), ptr )
#define switch_zmalloc(ptr, len) (void)( (!!(ptr = calloc(1, (len)))) || (fprintf(stderr,"ABORT! Malloc failure at: %s:%d", __FILE__, __LINE__),abort(), 0), ptr)
#define switch_strdup(ptr, s) (void)( (!!(ptr = strdup(s))) || (fprintf(stderr,"ABORT! Malloc failure at: %s:%d", __FILE__, __LINE__),abort(), 0), ptr)
#else
#if (_MSC_VER >= 1500) // VC9+
#define switch_malloc(ptr, len) (void)(assert(((ptr) = malloc((len)))),ptr);__analysis_assume( ptr )

View File

@ -2123,6 +2123,34 @@ SWITCH_STANDARD_API(kill_function)
return SWITCH_STATUS_SUCCESS;
}
#define OUTGOING_ANSWER_SYNTAX "<uuid>"
SWITCH_STANDARD_API(outgoing_answer_function)
{
switch_core_session_t *outgoing_session = NULL;
char *mycmd = NULL;
if (zstr(cmd) || !(mycmd = strdup(cmd))) {
stream->write_function(stream, "-USAGE: %s\n", OUTGOING_ANSWER_SYNTAX);
return SWITCH_STATUS_SUCCESS;
}
if (zstr(mycmd) || !(outgoing_session = switch_core_session_locate(mycmd))) {
stream->write_function(stream, "-ERR No Such Channel!\n");
} else {
switch_channel_t *channel = switch_core_session_get_channel(outgoing_session);
if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) {
switch_channel_mark_answered(channel);
stream->write_function(stream, "+OK\n");
} else {
stream->write_function(stream, "-ERR Not an outbound channel!\n");
}
switch_core_session_rwunlock(outgoing_session);
}
switch_safe_free(mycmd);
return SWITCH_STATUS_SUCCESS;
}
#define PREPROCESS_SYNTAX "<>"
SWITCH_STANDARD_API(preprocess_function)
{
@ -5238,6 +5266,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_commands_load)
SWITCH_ADD_API(commands_api_interface, "uuid_getvar", "uuid_getvar", uuid_getvar_function, GETVAR_SYNTAX);
SWITCH_ADD_API(commands_api_interface, "uuid_hold", "hold", uuid_hold_function, HOLD_SYNTAX);
SWITCH_ADD_API(commands_api_interface, "uuid_kill", "Kill Channel", kill_function, KILL_SYNTAX);
SWITCH_ADD_API(commands_api_interface, "uuid_outgoing_answer", "Answer Outgoing Channel", outgoing_answer_function, OUTGOING_ANSWER_SYNTAX);
SWITCH_ADD_API(commands_api_interface, "uuid_limit", "Increase limit resource", uuid_limit_function, LIMIT_SYNTAX);
SWITCH_ADD_API(commands_api_interface, "uuid_limit_release", "Release limit resource", uuid_limit_release_function, LIMIT_RELEASE_SYNTAX);
SWITCH_ADD_API(commands_api_interface, "uuid_loglevel", "set loglevel on session", uuid_loglevel, UUID_LOGLEVEL_SYNTAX);
@ -5360,6 +5389,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_commands_load)
switch_console_set_complete("add uuid_hold ::console::list_uuid");
switch_console_set_complete("add uuid_jitterbuffer ::console::list_uuid");
switch_console_set_complete("add uuid_kill ::console::list_uuid");
switch_console_set_complete("add uuid_outgoing_answer ::console::list_uuid");
switch_console_set_complete("add uuid_limit ::console::list_uuid");
switch_console_set_complete("add uuid_limit_release ::console::list_uuid");
switch_console_set_complete("add uuid_loglevel ::console::list_uuid console");

View File

@ -2529,8 +2529,7 @@ SWITCH_STANDARD_APP(audio_bridge_function)
char *tof_data = NULL;
char *tof_array[4] = { 0 };
//int tof_arrayc = 0;
const char *continue_on_fail = NULL, *failure_causes = NULL,
*v_campon = NULL, *v_campon_retries, *v_campon_sleep, *v_campon_timeout, *v_campon_fallback_exten = NULL;
const char *v_campon = NULL, *v_campon_retries, *v_campon_sleep, *v_campon_timeout, *v_campon_fallback_exten = NULL;
switch_call_cause_t cause = SWITCH_CAUSE_NORMAL_CLEARING;
int campon_retries = 100, campon_timeout = 10, campon_sleep = 10, tmp, camping = 0, fail = 0, thread_started = 0;
struct camping_stake stake = { 0 };
@ -2544,15 +2543,11 @@ SWITCH_STANDARD_APP(audio_bridge_function)
return;
}
continue_on_fail = switch_channel_get_variable(caller_channel, "continue_on_fail");
transfer_on_fail = switch_channel_get_variable(caller_channel, "transfer_on_fail");
tof_data = switch_core_session_strdup(session, transfer_on_fail);
switch_split(tof_data, ' ', tof_array);
transfer_on_fail = tof_array[0];
failure_causes = switch_channel_get_variable(caller_channel, "failure_causes");
if ((v_campon = switch_channel_get_variable(caller_channel, "campon")) && switch_true(v_campon)) {
const char *cid_name = NULL;
const char *cid_number = NULL;
@ -2693,6 +2688,11 @@ SWITCH_STANDARD_APP(audio_bridge_function)
EXCEPTION... ATTENDED_TRANSFER never is a reason to continue.......
*/
if (cause != SWITCH_CAUSE_ATTENDED_TRANSFER) {
const char *continue_on_fail = NULL, *failure_causes = NULL;
continue_on_fail = switch_channel_get_variable(caller_channel, "continue_on_fail");
failure_causes = switch_channel_get_variable(caller_channel, "failure_causes");
if (continue_on_fail || failure_causes) {
const char *cause_str;
char cause_num[35] = "";

View File

@ -51,6 +51,7 @@ struct record_helper {
switch_mutex_t *mutex;
int fd;
int up;
switch_size_t shared_ts;
};
static void *SWITCH_THREAD_FUNC record_video_thread(switch_thread_t *thread, void *obj)
@ -63,7 +64,7 @@ static void *SWITCH_THREAD_FUNC record_video_thread(switch_thread_t *thread, voi
int bytes;
eh->up = 1;
while (switch_channel_ready(channel)) {
while (switch_channel_ready(channel) && eh->up) {
status = switch_core_session_read_video_frame(session, &read_frame, SWITCH_IO_FLAG_NONE, 0);
if (!SWITCH_READ_ACCEPTABLE(status)) {
@ -108,11 +109,13 @@ SWITCH_STANDARD_APP(record_fsv_function)
switch_mutex_t *mutex = NULL;
switch_codec_t codec, *vid_codec;
switch_codec_implementation_t read_impl = { 0 };
switch_dtmf_t dtmf = { 0 };
int count = 0, sanity = 30;
switch_core_session_get_read_impl(session, &read_impl);
switch_channel_answer(channel);
switch_channel_set_variable(channel, SWITCH_PLAYBACK_TERMINATOR_USED, "");
while (switch_channel_up(channel) && !switch_channel_test_flag(channel, CF_VIDEO)) {
switch_yield(10000);
@ -125,6 +128,7 @@ SWITCH_STANDARD_APP(record_fsv_function)
if (!--sanity) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "%s timeout waiting for video.\n",
switch_channel_get_name(channel));
switch_channel_set_variable(channel, SWITCH_CURRENT_APPLICATION_RESPONSE_VARIABLE, "Got timeout while waiting for video");
return;
}
}
@ -132,11 +136,13 @@ SWITCH_STANDARD_APP(record_fsv_function)
if (!switch_channel_ready(channel)) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_CRIT, "%s not ready.\n", switch_channel_get_name(channel));
switch_channel_set_variable(channel, SWITCH_CURRENT_APPLICATION_RESPONSE_VARIABLE, "Channel not ready");
return;
}
if ((fd = open((char *) data, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, S_IRUSR | S_IWUSR)) < 0) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_CRIT, "Error opening file %s\n", (char *) data);
switch_channel_set_variable(channel, SWITCH_CURRENT_APPLICATION_RESPONSE_VARIABLE, "Got error while opening file");
return;
}
@ -150,6 +156,7 @@ SWITCH_STANDARD_APP(record_fsv_function)
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Audio Codec Activation Success\n");
} else {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Audio Codec Activation Fail\n");
switch_channel_set_variable(channel, SWITCH_CURRENT_APPLICATION_RESPONSE_VARIABLE, "Audio codec activation failed");
goto end;
}
@ -170,6 +177,7 @@ SWITCH_STANDARD_APP(record_fsv_function)
h.audio_ptime = read_impl.microseconds_per_packet / 1000;
if (write(fd, &h, sizeof(h)) != sizeof(h)) {
switch_channel_set_variable(channel, SWITCH_CURRENT_APPLICATION_RESPONSE_VARIABLE, "File write failed");
goto end;
}
@ -186,9 +194,37 @@ SWITCH_STANDARD_APP(record_fsv_function)
while (switch_channel_ready(channel)) {
status = switch_core_session_read_frame(session, &read_frame, SWITCH_IO_FLAG_NONE, 0);
status = switch_core_session_read_frame(session, &read_frame, SWITCH_IO_FLAG_SINGLE_READ, 0);
if (switch_channel_test_flag(channel, CF_BREAK)) {
switch_channel_clear_flag(channel, CF_BREAK);
eh.up = 0;
break;
}
switch_ivr_parse_all_events(session);
//check for dtmf interrupts
if (switch_channel_has_dtmf(channel)) {
const char * terminators = switch_channel_get_variable(channel, SWITCH_PLAYBACK_TERMINATORS_VARIABLE);
switch_channel_dequeue_dtmf(channel, &dtmf);
if (terminators && !strcasecmp(terminators, "none"))
{
terminators = NULL;
}
if (terminators && strchr(terminators, dtmf.digit)) {
char sbuf[2] = {dtmf.digit, '\0'};
switch_channel_set_variable(channel, SWITCH_PLAYBACK_TERMINATOR_USED, sbuf);
eh.up = 0;
break;
}
}
if (!SWITCH_READ_ACCEPTABLE(status)) {
eh.up = 0;
break;
}
@ -213,12 +249,15 @@ SWITCH_STANDARD_APP(record_fsv_function)
}
break;
}
if (mutex) {
switch_mutex_unlock(mutex);
}
switch_core_session_write_frame(session, read_frame, SWITCH_IO_FLAG_NONE, 0);
}
switch_channel_set_variable(channel, SWITCH_CURRENT_APPLICATION_RESPONSE_VARIABLE, "OK");
end:
@ -239,7 +278,7 @@ SWITCH_STANDARD_APP(play_fsv_function)
switch_frame_t write_frame = { 0 }, vid_frame = {
0};
int fd = -1;
int bytes;
int bytes;
switch_codec_t codec = { 0 }, vid_codec = {
0}, *read_vid_codec;
unsigned char *aud_buffer;
@ -248,24 +287,32 @@ SWITCH_STANDARD_APP(play_fsv_function)
uint32_t ts = 0, last = 0;
switch_timer_t timer = { 0 };
switch_payload_t pt = 0;
switch_dtmf_t dtmf = { 0 };
switch_frame_t *read_frame;
switch_codec_implementation_t read_impl = { 0 };
switch_core_session_get_read_impl(session, &read_impl);
aud_buffer = switch_core_session_alloc(session, SWITCH_RECOMMENDED_BUFFER_SIZE);
vid_buffer = switch_core_session_alloc(session, SWITCH_RECOMMENDED_BUFFER_SIZE);
switch_channel_set_variable(channel, SWITCH_PLAYBACK_TERMINATOR_USED, "");
if ((fd = open((char *) data, O_RDONLY | O_BINARY)) < 0) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_CRIT, "Error opening file %s\n", (char *) data);
switch_channel_set_variable(channel, SWITCH_CURRENT_APPLICATION_RESPONSE_VARIABLE, "Got error while opening file");
return;
}
if (read(fd, &h, sizeof(h)) != sizeof(h)) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_CRIT, "Error reading file header\n");
switch_channel_set_variable(channel, SWITCH_CURRENT_APPLICATION_RESPONSE_VARIABLE, "Got error reading file header");
goto end;
}
if (h.version != VERSION) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_CRIT, "File version does not match!\n");
switch_channel_set_variable(channel, SWITCH_CURRENT_APPLICATION_RESPONSE_VARIABLE, "File version does not match!");
goto end;
}
@ -290,6 +337,7 @@ SWITCH_STANDARD_APP(play_fsv_function)
if (switch_core_timer_init(&timer, "soft", read_impl.microseconds_per_packet / 1000,
read_impl.samples_per_packet, switch_core_session_get_pool(session)) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Timer Activation Fail\n");
switch_channel_set_variable(channel, SWITCH_CURRENT_APPLICATION_RESPONSE_VARIABLE, "Timer activation failed!");
goto end;
}
@ -303,6 +351,7 @@ SWITCH_STANDARD_APP(play_fsv_function)
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Audio Codec Activation Success\n");
} else {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Audio Codec Activation Fail\n");
switch_channel_set_variable(channel, SWITCH_CURRENT_APPLICATION_RESPONSE_VARIABLE, "Audio codec activation failed");
goto end;
}
@ -316,6 +365,7 @@ SWITCH_STANDARD_APP(play_fsv_function)
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Video Codec Activation Success\n");
} else {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Video Codec Activation Fail\n");
switch_channel_set_variable(channel, SWITCH_CURRENT_APPLICATION_RESPONSE_VARIABLE, "Video codec activation failed");
goto end;
}
switch_core_session_set_read_codec(session, &codec);
@ -353,15 +403,45 @@ SWITCH_STANDARD_APP(play_fsv_function)
if (bytes > (int) write_frame.buflen) {
bytes = write_frame.buflen;
}
if ((write_frame.datalen = read(fd, write_frame.data, bytes)) <= 0) {
break;
}
switch_core_session_write_frame(session, &write_frame, SWITCH_IO_FLAG_NONE, 0);
switch_core_timer_next(&timer);
}
switch_core_session_read_frame(session, &read_frame, SWITCH_IO_FLAG_NONE, 0);
if (switch_channel_test_flag(channel, CF_BREAK)) {
switch_channel_clear_flag(channel, CF_BREAK);
break;
}
switch_ivr_parse_all_events(session);
//check for dtmf interrupts
if (switch_channel_has_dtmf(channel)) {
const char * terminators = switch_channel_get_variable(channel, SWITCH_PLAYBACK_TERMINATORS_VARIABLE);
switch_channel_dequeue_dtmf(channel, &dtmf);
if (terminators && !strcasecmp(terminators, "none"))
{
terminators = NULL;
}
if (terminators && strchr(terminators, dtmf.digit)) {
char sbuf[2] = {dtmf.digit, '\0'};
switch_channel_set_variable(channel, SWITCH_PLAYBACK_TERMINATOR_USED, sbuf);
break;
}
}
}
}
switch_channel_set_variable(channel, SWITCH_CURRENT_APPLICATION_RESPONSE_VARIABLE, "OK");
end:
if (timer.interval) {

View File

@ -3958,8 +3958,13 @@ static mrcp_client_t *mod_unimrcp_client_create(switch_memory_pool_t *mod_pool)
client = NULL;
goto done;
}
if (zstr(param_value)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Missing SPEAK param value\n");
client = NULL;
goto done;
}
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Loading SPEAK Param %s:%s\n", param_name, param_value);
switch_core_hash_insert(mod_profile->default_synth_params, param_name, param_value);
switch_core_hash_insert(mod_profile->default_synth_params, switch_core_strdup(pool, param_name), switch_core_strdup(pool, param_value));
}
}
@ -3976,8 +3981,13 @@ static mrcp_client_t *mod_unimrcp_client_create(switch_memory_pool_t *mod_pool)
client = NULL;
goto done;
}
if (zstr(param_value)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Missing RECOGNIZE param value\n");
client = NULL;
goto done;
}
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Loading RECOGNIZE Param %s:%s\n", param_name, param_value);
switch_core_hash_insert(mod_profile->default_recog_params, param_name, param_value);
switch_core_hash_insert(mod_profile->default_recog_params, switch_core_strdup(pool, param_name), switch_core_strdup(pool, param_value));
}
}

View File

@ -224,7 +224,7 @@ static int sangoma_create_rtp_port(void *usr_priv, uint32_t host_ip, uint32_t *p
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "New allocated port %d for IP %s/%d.%d.%d.%d\n", rtp_port, local_ip,
SNGTC_NIPV4(host_ip));
*p_rtp_port = rtp_port;
*rtp_fd = (void *)(long)rtp_port;
*rtp_fd = NULL;
return 0;
}
@ -259,6 +259,9 @@ static int sangoma_create_rtp(void *usr_priv, sngtc_codec_request_leg_t *codec_r
switch_port_t rtp_port;
struct sangoma_transcoding_session *sess = usr_priv;
rtp_port = codec_req_leg->host_udp_port;
*rtp_fd = NULL;
/*
* We *MUST* use a new pool
* Do not use the session pool since the session may go away while the RTP socket should linger around
@ -271,11 +274,6 @@ static int sangoma_create_rtp(void *usr_priv, sngtc_codec_request_leg_t *codec_r
return -1;
}
rtp_port = (switch_port_t)(long)*rtp_fd;
*rtp_fd = NULL;
codec_req_leg->host_udp_port = rtp_port;
local_ip_addr.s_addr = htonl(codec_req_leg->host_ip);
switch_inet_ntop(AF_INET, &local_ip_addr, local_ip, sizeof(local_ip));
sngtc_codec_ipv4_hex_to_str(codec_reply_leg->codec_ip, codec_ip);
@ -1271,10 +1269,10 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_sangoma_codec_load)
* At this point there is an empty shell codec interface registered, but not yet implementations */
SWITCH_ADD_CODEC(codec_interface, g_codec_map[c].fs_name);
/* Now add as many codec implementations as needed, just up to 40ms for now */
/* Now add as many codec implementations as needed, just up to 200ms for now */
if (g_codec_map[c].autoinit) {
int ms = 0;
for (i = 1; i <= 4; i++) {
for (i = 1; i <= 20; i++) {
ms = i * 10;
if (g_codec_map[c].maxms < ms) {
break;

View File

@ -54,7 +54,8 @@ typedef enum {
TFLAG_BLEG = (1 << 6),
TFLAG_APP = (1 << 7),
TFLAG_RUNNING_APP = (1 << 8),
TFLAG_BOWOUT_USED = (1 << 9)
TFLAG_BOWOUT_USED = (1 << 9),
TFLAG_CLEAR = (1 << 10)
} TFLAGS;
struct private_object {
@ -105,6 +106,17 @@ static switch_status_t channel_read_frame(switch_core_session_t *session, switch
static switch_status_t channel_write_frame(switch_core_session_t *session, switch_frame_t *frame, switch_io_flag_t flags, int stream_id);
static switch_status_t channel_kill_channel(switch_core_session_t *session, int sig);
static void clear_queue(private_t *tech_pvt)
{
void *pop;
while (switch_queue_trypop(tech_pvt->frame_queue, &pop) == SWITCH_STATUS_SUCCESS && pop) {
switch_frame_t *frame = (switch_frame_t *) pop;
switch_frame_free(&frame);
}
}
static switch_status_t tech_init(private_t *tech_pvt, switch_core_session_t *session, switch_codec_t *codec)
{
const char *iananame = "L16";
@ -566,6 +578,12 @@ static switch_status_t channel_read_frame(switch_core_session_t *session, switch
mutex = tech_pvt->mutex;
switch_mutex_lock(mutex);
if (switch_test_flag(tech_pvt, TFLAG_CLEAR)) {
clear_queue(tech_pvt);
switch_clear_flag(tech_pvt, TFLAG_CLEAR);
}
if (switch_queue_trypop(tech_pvt->frame_queue, &pop) == SWITCH_STATUS_SUCCESS && pop) {
if (tech_pvt->write_frame) {
switch_frame_free(&tech_pvt->write_frame);
@ -599,17 +617,6 @@ static switch_status_t channel_read_frame(switch_core_session_t *session, switch
return status;
}
static void clear_queue(private_t *tech_pvt)
{
void *pop;
while (switch_queue_trypop(tech_pvt->frame_queue, &pop) == SWITCH_STATUS_SUCCESS && pop) {
switch_frame_t *frame = (switch_frame_t *) pop;
switch_frame_free(&frame);
}
}
static switch_status_t channel_write_frame(switch_core_session_t *session, switch_frame_t *frame, switch_io_flag_t flags, int stream_id)
{
switch_channel_t *channel = NULL;
@ -750,9 +757,9 @@ static switch_status_t channel_receive_message(switch_core_session_t *session, s
{
done = 1;
switch_set_flag(tech_pvt, TFLAG_CLEAR);
switch_set_flag(tech_pvt->other_tech_pvt, TFLAG_CLEAR);
clear_queue(tech_pvt);
clear_queue(tech_pvt->other_tech_pvt);
switch_core_timer_sync(&tech_pvt->timer);
switch_core_timer_sync(&tech_pvt->other_tech_pvt->timer);
}

File diff suppressed because it is too large Load Diff

View File

@ -78,14 +78,23 @@ static PaError PABLIO_TermFIFO(PaUtilRingBuffer * rbuf);
static int iblockingIOCallback(const void *inputBuffer, void *outputBuffer,
unsigned long framesPerBuffer, const PaStreamCallbackTimeInfo * timeInfo, PaStreamCallbackFlags statusFlags, void *userData)
{
int c = 0, i = 0, j = 0;
PABLIO_Stream *data = (PABLIO_Stream *) userData;
long numBytes = data->bytesPerFrame * framesPerBuffer;
const int16_t *inputSamples = inputBuffer;
int16_t *chanSamples = (int16_t*)data->iobuff;
/* This may get called with NULL inputBuffer during initial setup. */
if (inputBuffer != NULL) {
if (PaUtil_WriteRingBuffer(&data->inFIFO, inputBuffer, numBytes) != numBytes) {
PaUtil_FlushRingBuffer(&data->inFIFO);
PaUtil_WriteRingBuffer(&data->inFIFO, inputBuffer, numBytes);
/* retrieve the data for each channel and put it in the ring buffer */
for (c = 0; c < data->channelCount; c++) {
for (i = 0, j = c; i < framesPerBuffer; j += data->channelCount, i++) {
chanSamples[i] = inputSamples[j];
}
if (PaUtil_WriteRingBuffer(&data->inFIFOs[c], chanSamples, numBytes) != numBytes) {
PaUtil_FlushRingBuffer(&data->inFIFOs[c]);
PaUtil_WriteRingBuffer(&data->inFIFOs[c], inputBuffer, numBytes);
}
}
}
@ -97,13 +106,21 @@ static int oblockingIOCallback(const void *inputBuffer, void *outputBuffer,
{
PABLIO_Stream *data = (PABLIO_Stream *) userData;
long numBytes = data->bytesPerFrame * framesPerBuffer;
int16_t *outputSamples = outputBuffer;
int16_t *chanSamples = (short *)data->iobuff;
int c = 0, i = 0, j = 0;
if (outputBuffer != NULL) {
int i;
int numRead = PaUtil_ReadRingBuffer(&data->outFIFO, outputBuffer, numBytes);
/* Zero out remainder of buffer if we run out of data. */
for (i = numRead; i < numBytes; i++) {
((char *) outputBuffer)[i] = 0;
for (c = 0; c < data->channelCount; c++) {
int numRead = PaUtil_ReadRingBuffer(&data->outFIFOs[c], chanSamples, numBytes);
numRead = numRead / sizeof(int16_t);
for (i = 0, j = c; i < framesPerBuffer; j += data->channelCount, i++) {
if (i < numRead) {
outputSamples[j] = chanSamples[i];
} else {
outputSamples[j] = 0;
}
}
}
}
@ -143,7 +160,7 @@ static PaError PABLIO_TermFIFO(PaUtilRingBuffer * rbuf)
* Write data to ring buffer.
* Will not return until all the data has been written.
*/
long WriteAudioStream(PABLIO_Stream * aStream, void *data, long numFrames, switch_timer_t *timer)
long WriteAudioStream(PABLIO_Stream * aStream, void *data, long numFrames, int chan, switch_timer_t *timer)
{
long bytesWritten;
char *p = (char *) data;
@ -151,12 +168,12 @@ long WriteAudioStream(PABLIO_Stream * aStream, void *data, long numFrames, switc
switch_core_timer_next(timer);
bytesWritten = PaUtil_WriteRingBuffer(&aStream->outFIFO, p, numBytes);
bytesWritten = PaUtil_WriteRingBuffer(&aStream->outFIFOs[chan], p, numBytes);
numBytes -= bytesWritten;
p += bytesWritten;
if (numBytes > 0) {
PaUtil_FlushRingBuffer(&aStream->outFIFO);
PaUtil_FlushRingBuffer(&aStream->outFIFOs[chan]);
return 0;
}
return numFrames;
@ -166,7 +183,7 @@ long WriteAudioStream(PABLIO_Stream * aStream, void *data, long numFrames, switc
* Read data from ring buffer.
* Will not return until all the data has been read.
*/
long ReadAudioStream(PABLIO_Stream * aStream, void *data, long numFrames, switch_timer_t *timer)
long ReadAudioStream(PABLIO_Stream * aStream, void *data, long numFrames, int chan, switch_timer_t *timer)
{
long bytesRead = 0;
char *p = (char *) data;
@ -177,17 +194,17 @@ long ReadAudioStream(PABLIO_Stream * aStream, void *data, long numFrames, switch
while (totalBytes < neededBytes && --max > 0) {
avail = PaUtil_GetRingBufferReadAvailable(&aStream->inFIFO);
avail = PaUtil_GetRingBufferReadAvailable(&aStream->inFIFOs[chan]);
//printf("AVAILABLE BYTES %ld pass %d\n", avail, 5000 - max);
if (avail >= neededBytes * 6) {
PaUtil_FlushRingBuffer(&aStream->inFIFO);
PaUtil_FlushRingBuffer(&aStream->inFIFOs[chan]);
avail = 0;
} else {
bytesRead = 0;
if (totalBytes < neededBytes && avail >= neededBytes) {
bytesRead = PaUtil_ReadRingBuffer(&aStream->inFIFO, p, neededBytes);
bytesRead = PaUtil_ReadRingBuffer(&aStream->inFIFOs[chan], p, neededBytes);
totalBytes += bytesRead;
}
@ -206,9 +223,9 @@ long ReadAudioStream(PABLIO_Stream * aStream, void *data, long numFrames, switch
* Return the number of frames that could be written to the stream without
* having to wait.
*/
long GetAudioStreamWriteable(PABLIO_Stream * aStream)
long GetAudioStreamWriteable(PABLIO_Stream * aStream, int chan)
{
int bytesEmpty = PaUtil_GetRingBufferWriteAvailable(&aStream->outFIFO);
int bytesEmpty = PaUtil_GetRingBufferWriteAvailable(&aStream->outFIFOs[chan]);
return bytesEmpty / aStream->bytesPerFrame;
}
@ -216,9 +233,9 @@ long GetAudioStreamWriteable(PABLIO_Stream * aStream)
* Return the number of frames that are available to be read from the
* stream without having to wait.
*/
long GetAudioStreamReadable(PABLIO_Stream * aStream)
long GetAudioStreamReadable(PABLIO_Stream * aStream, int chan)
{
int bytesFull = PaUtil_GetRingBufferReadAvailable(&aStream->inFIFO);
int bytesFull = PaUtil_GetRingBufferReadAvailable(&aStream->inFIFOs[chan]);
return bytesFull / aStream->bytesPerFrame;
}
@ -251,7 +268,8 @@ PaError OpenAudioStream(PABLIO_Stream ** rwblPtr,
PABLIO_Stream *aStream;
long numFrames;
//long numBytes;
//int channels = 1;
int c = 0;
int channels = 1;
if (!(inputParameters || outputParameters)) {
return -1;
@ -262,31 +280,34 @@ PaError OpenAudioStream(PABLIO_Stream ** rwblPtr,
switch_assert(aStream);
memset(aStream, 0, sizeof(PABLIO_Stream));
/*
if (inputParameters) {
channels = inputParameters->channelCount;
} else if (outputParameters) {
channels = outputParameters->channelCount;
}
*/
numFrames = RoundUpToNextPowerOf2(samples_per_packet * 5);
aStream->bytesPerFrame = bytesPerSample;
aStream->channelCount = channels;
/* Initialize Ring Buffers */
if (inputParameters) {
err = PABLIO_InitFIFO(&aStream->inFIFO, numFrames, aStream->bytesPerFrame);
if (err != paNoError) {
goto error;
for (c = 0; c < channels; c++) {
err = PABLIO_InitFIFO(&aStream->inFIFOs[c], numFrames, aStream->bytesPerFrame);
if (err != paNoError) {
goto error;
}
}
aStream->has_in = 1;
}
if (outputParameters) {
err = PABLIO_InitFIFO(&aStream->outFIFO, numFrames, aStream->bytesPerFrame);
if (err != paNoError) {
goto error;
for (c = 0; c < channels; c++) {
err = PABLIO_InitFIFO(&aStream->outFIFOs[c], numFrames, aStream->bytesPerFrame);
if (err != paNoError) {
goto error;
}
}
aStream->has_out = 1;
}
@ -355,17 +376,21 @@ PaError CloseAudioStream(PABLIO_Stream * aStream)
{
int bytesEmpty;
int byteSize;
int c = 0;
byteSize = aStream->outFIFO.bufferSize;
if (aStream->has_out) {
/* If we are writing data, make sure we play everything written. */
if (byteSize > 0) {
bytesEmpty = PaUtil_GetRingBufferWriteAvailable(&aStream->outFIFO);
while (bytesEmpty < byteSize) {
Pa_Sleep(10);
bytesEmpty = PaUtil_GetRingBufferWriteAvailable(&aStream->outFIFO);
for (c = 0; c < aStream->channelCount; c++) {
byteSize = aStream->outFIFOs[c].bufferSize;
/* If we are writing data, make sure we play everything written. */
if (byteSize > 0) {
bytesEmpty = PaUtil_GetRingBufferWriteAvailable(&aStream->outFIFOs[c]);
while (bytesEmpty < byteSize) {
Pa_Sleep(10);
bytesEmpty = PaUtil_GetRingBufferWriteAvailable(&aStream->outFIFOs[c]);
}
}
}
}
@ -401,11 +426,15 @@ PaError CloseAudioStream(PABLIO_Stream * aStream)
}
if (aStream->has_in) {
PABLIO_TermFIFO(&aStream->inFIFO);
for (c = 0; c < aStream->channelCount; c++) {
PABLIO_TermFIFO(&aStream->inFIFOs[c]);
}
}
if (aStream->has_out) {
PABLIO_TermFIFO(&aStream->outFIFO);
for (c = 0; c < aStream->channelCount; c++) {
PABLIO_TermFIFO(&aStream->outFIFOs[c]);
}
}
free(aStream);
@ -413,3 +442,4 @@ PaError CloseAudioStream(PABLIO_Stream * aStream)
return paNoError;
}

View File

@ -56,17 +56,30 @@ extern "C" {
#include <string.h>
typedef struct {
PaUtilRingBuffer inFIFO;
PaUtilRingBuffer outFIFO;
PaStream *istream;
PaStream *ostream;
PaStream *iostream;
int bytesPerFrame;
int do_dual;
int has_in;
int has_out;
} PABLIO_Stream;
/*! Maximum number of channels per stream */
#define MAX_IO_CHANNELS 2
/*! Maximum numer of milliseconds per packet */
#define MAX_IO_MS 100
/*! Maximum sampling rate (48Khz) */
#define MAX_SAMPLING_RATE 48000
/* Maximum size of a read */
#define MAX_IO_BUFFER (((MAX_IO_MS * MAX_SAMPLING_RATE)/1000)*sizeof(int16_t))
typedef struct {
PaStream *istream;
PaStream *ostream;
PaStream *iostream;
int bytesPerFrame;
int do_dual;
int has_in;
int has_out;
PaUtilRingBuffer inFIFOs[MAX_IO_CHANNELS];
PaUtilRingBuffer outFIFOs[MAX_IO_CHANNELS];
int channelCount;
char iobuff[MAX_IO_BUFFER];
} PABLIO_Stream;
/* Values for flags for OpenAudioStream(). */
#define PABLIO_READ (1<<0)
@ -79,25 +92,25 @@ extern "C" {
* Write data to ring buffer.
* Will not return until all the data has been written.
*/
long WriteAudioStream(PABLIO_Stream * aStream, void *data, long numFrames, switch_timer_t *timer);
long WriteAudioStream(PABLIO_Stream * aStream, void *data, long numFrames, int chan, switch_timer_t *timer);
/************************************************************
* Read data from ring buffer.
* Will not return until all the data has been read.
*/
long ReadAudioStream(PABLIO_Stream * aStream, void *data, long numFrames, switch_timer_t *timer);
long ReadAudioStream(PABLIO_Stream * aStream, void *data, long numFrames, int chan, switch_timer_t *timer);
/************************************************************
* Return the number of frames that could be written to the stream without
* having to wait.
*/
long GetAudioStreamWriteable(PABLIO_Stream * aStream);
long GetAudioStreamWriteable(PABLIO_Stream * aStream, int chan);
/************************************************************
* Return the number of frames that are available to be read from the
* stream without having to wait.
*/
long GetAudioStreamReadable(PABLIO_Stream * aStream);
long GetAudioStreamReadable(PABLIO_Stream * aStream, int chan);
/************************************************************
* Opens a PortAudio stream with default characteristics.
@ -107,12 +120,12 @@ extern "C" {
* PABLIO_READ, PABLIO_WRITE, or PABLIO_READ_WRITE,
* and either PABLIO_MONO or PABLIO_STEREO
*/
PaError OpenAudioStream(PABLIO_Stream ** rwblPtr,
const PaStreamParameters * inputParameters,
const PaStreamParameters * outputParameters,
double sampleRate, PaStreamCallbackFlags statusFlags, long samples_per_packet, int do_dual);
PaError OpenAudioStream(PABLIO_Stream ** rwblPtr,
const PaStreamParameters * inputParameters,
const PaStreamParameters * outputParameters,
double sampleRate, PaStreamCallbackFlags statusFlags, long samples_per_packet, int do_dual);
PaError CloseAudioStream(PABLIO_Stream * aStream);
PaError CloseAudioStream(PABLIO_Stream * aStream);
#ifdef __cplusplus
}

View File

@ -569,9 +569,31 @@ static switch_status_t sofia_answer_channel(switch_core_session_t *session)
const char *val;
const char *b_sdp = NULL;
int is_proxy = 0;
int is_3pcc = 0;
char *sticky = NULL;
const char *call_info = switch_channel_get_variable(channel, "presence_call_info_full");
if(sofia_test_flag(tech_pvt, TFLAG_3PCC_INVITE)) {
// SNARK: complete hack to get final ack sent when a 3pcc invite has been passed from the other leg in bypass_media mode.
// This code handles the pass_indication sent after the 3pcc ack is received by the other leg in the is_3pcc && is_proxy case below.
// Is there a better place to hang this...?
b_sdp = switch_channel_get_variable(channel, SWITCH_B_SDP_VARIABLE);
sofia_glue_tech_set_local_sdp(tech_pvt, b_sdp, SWITCH_TRUE);
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "3PCC-PROXY nomedia - sending ack\n");
nua_ack(tech_pvt->nh,
TAG_IF(!zstr(tech_pvt->user_via), SIPTAG_VIA_STR(tech_pvt->user_via)),
SIPTAG_CONTACT_STR(tech_pvt->reply_contact),
SOATAG_USER_SDP_STR(tech_pvt->local_sdp_str),
SOATAG_REUSE_REJECTED(1),
SOATAG_RTP_SELECT(1), SOATAG_ORDERED_USER(1), SOATAG_AUDIO_AUX("cn telephone-event"),
TAG_IF(sofia_test_pflag(tech_pvt->profile, PFLAG_DISABLE_100REL), NUTAG_INCLUDE_EXTRA_SDP(1)),
TAG_END());
sofia_clear_flag(tech_pvt, TFLAG_3PCC_INVITE); // all done
return SWITCH_STATUS_SUCCESS;
}
if (sofia_test_flag(tech_pvt, TFLAG_ANS) || switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) {
return SWITCH_STATUS_SUCCESS;
}
@ -579,8 +601,9 @@ static switch_status_t sofia_answer_channel(switch_core_session_t *session)
b_sdp = switch_channel_get_variable(channel, SWITCH_B_SDP_VARIABLE);
is_proxy = (switch_channel_test_flag(channel, CF_PROXY_MODE) || switch_channel_test_flag(channel, CF_PROXY_MEDIA));
is_3pcc = (sofia_test_pflag(tech_pvt->profile, PFLAG_3PCC_PROXY) && sofia_test_flag(tech_pvt, TFLAG_3PCC));
if (b_sdp && is_proxy) {
if (b_sdp && is_proxy && !is_3pcc) {
sofia_glue_tech_set_local_sdp(tech_pvt, b_sdp, SWITCH_TRUE);
if (switch_channel_test_flag(channel, CF_PROXY_MEDIA)) {
@ -591,23 +614,35 @@ static switch_status_t sofia_answer_channel(switch_core_session_t *session)
}
} else {
/* This if statement check and handles the 3pcc proxy mode */
if (sofia_test_pflag(tech_pvt->profile, PFLAG_3PCC_PROXY) && sofia_test_flag(tech_pvt, TFLAG_3PCC)) {
if (is_3pcc) {
if(!is_proxy) {
tech_pvt->num_codecs = 0;
sofia_glue_tech_prepare_codecs(tech_pvt);
tech_pvt->local_sdp_str = NULL;
sofia_glue_tech_choose_port(tech_pvt, 0);
sofia_glue_set_local_sdp(tech_pvt, NULL, 0, NULL, 0);
} else {
sofia_glue_tech_set_local_sdp(tech_pvt, b_sdp, SWITCH_TRUE);
if (switch_channel_test_flag(channel, CF_PROXY_MEDIA)) {
sofia_glue_tech_patch_sdp(tech_pvt);
if (sofia_glue_activate_rtp(tech_pvt, 0) != SWITCH_STATUS_SUCCESS) {
return SWITCH_STATUS_FALSE;
}
}
}
/* Send the 200 OK */
if (!sofia_test_flag(tech_pvt, TFLAG_BYE)) {
char *extra_headers = sofia_glue_get_extra_headers(channel, SOFIA_SIP_RESPONSE_HEADER_PREFIX);
if (sofia_use_soa(tech_pvt)) {
nua_respond(tech_pvt->nh, SIP_200_OK,
TAG_IF(is_proxy, NUTAG_AUTOANSWER(0)),
SIPTAG_CONTACT_STR(tech_pvt->profile->url),
SOATAG_USER_SDP_STR(tech_pvt->local_sdp_str),
TAG_IF(call_info, SIPTAG_CALL_INFO_STR(call_info)),
SOATAG_REUSE_REJECTED(1),
SOATAG_REUSE_REJECTED(1), TAG_IF(is_proxy, SOATAG_RTP_SELECT(1)),
SOATAG_ORDERED_USER(1), SOATAG_AUDIO_AUX("cn telephone-event"), NUTAG_INCLUDE_EXTRA_SDP(1),
TAG_IF(!zstr(extra_headers), SIPTAG_HEADER_STR(extra_headers)),
TAG_IF(switch_stristr("update_display", tech_pvt->x_freeswitch_support_remote),
@ -639,6 +674,14 @@ static switch_status_t sofia_answer_channel(switch_core_session_t *session)
/* Regain lock on sofia */
switch_mutex_lock(tech_pvt->sofia_mutex);
if(is_proxy) {
sofia_clear_flag(tech_pvt, TFLAG_3PCC_HAS_ACK);
sofia_clear_flag(tech_pvt, TFLAG_3PCC);
// This sends the message to the other leg that causes it to call the TFLAG_3PCC_INVITE code at the start of this function.
// Is there another message it would be better to hang this on though?
switch_core_session_pass_indication(session, SWITCH_MESSAGE_INDICATE_ANSWER);
}
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "3PCC-PROXY, Done waiting for ACK\n");
return SWITCH_STATUS_SUCCESS;
}
@ -1345,7 +1388,7 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi
case SWITCH_MESSAGE_INDICATE_JITTER_BUFFER:
{
if (switch_rtp_ready(tech_pvt->rtp_session)) {
int len, maxlen = 0, qlen = 0, maxqlen = 50, max_drift = 0;
int len = 0, maxlen = 0, qlen = 0, maxqlen = 50, max_drift = 0;
if (msg->string_arg) {
char *p, *q;
@ -1626,7 +1669,7 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi
ip = switch_channel_get_variable(channel, SWITCH_REMOTE_MEDIA_IP_VARIABLE);
port = switch_channel_get_variable(channel, SWITCH_REMOTE_MEDIA_PORT_VARIABLE);
if (ip && port) {
sofia_glue_set_local_sdp(tech_pvt, ip, atoi(port), msg->string_arg, 1);
sofia_glue_set_local_sdp(tech_pvt, ip, (switch_port_t)atoi(port), msg->string_arg, 1);
}
if (!sofia_test_flag(tech_pvt, TFLAG_BYE)) {
@ -1666,7 +1709,7 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi
port = switch_channel_get_variable(other_channel, SWITCH_REMOTE_MEDIA_PORT_VARIABLE);
switch_core_session_rwunlock(other_session);
if (ip && port) {
sofia_glue_set_local_sdp(tech_pvt, ip, atoi(port), NULL, 1);
sofia_glue_set_local_sdp(tech_pvt, ip, (switch_port_t)atoi(port), NULL, 1);
}
}
@ -1685,6 +1728,10 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi
switch_channel_get_name(channel), msg->string_arg);
sofia_glue_tech_set_local_sdp(tech_pvt, msg->string_arg, SWITCH_TRUE);
if(zstr(tech_pvt->local_sdp_str)) {
sofia_set_flag(tech_pvt, TFLAG_3PCC_INVITE);
}
sofia_set_flag_locked(tech_pvt, TFLAG_SENT_UPDATE);
switch_channel_set_flag(channel, CF_REQ_MEDIA);
sofia_glue_do_invite(session);
@ -2183,6 +2230,23 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi
SIPTAG_PAYLOAD_STR(tech_pvt->local_sdp_str),
TAG_IF(!zstr(extra_headers), SIPTAG_HEADER_STR(extra_headers)), TAG_END());
}
if (sofia_test_pflag(tech_pvt->profile, PFLAG_3PCC_PROXY) && sofia_test_flag(tech_pvt, TFLAG_3PCC)) {
/* Unlock the session signal to allow the ack to make it in */
// Maybe we should timeout?
switch_mutex_unlock(tech_pvt->sofia_mutex);
while (switch_channel_ready(channel) && !sofia_test_flag(tech_pvt, TFLAG_3PCC_HAS_ACK)) {
switch_cond_next();
}
/* Regain lock on sofia */
switch_mutex_lock(tech_pvt->sofia_mutex);
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "3PCC-PROXY, Done waiting for ACK\n");
sofia_clear_flag(tech_pvt, TFLAG_3PCC);
sofia_clear_flag(tech_pvt, TFLAG_3PCC_HAS_ACK);
switch_core_session_pass_indication(session, SWITCH_MESSAGE_INDICATE_ANSWER);
}
} else {
nua_respond(tech_pvt->nh, code, su_strdup(nua_handle_home(tech_pvt->nh), reason), SIPTAG_CONTACT_STR(tech_pvt->reply_contact),
TAG_IF(!zstr(extra_headers), SIPTAG_HEADER_STR(extra_headers)), TAG_END());
@ -4379,6 +4443,14 @@ static switch_call_cause_t sofia_outgoing_channel(switch_core_session_t *session
} else {
sofia_clear_flag(ctech_pvt, TFLAG_ENABLE_SOA);
}
/* SNARK: lets copy this across so we can see if we're the other leg of 3PCC + bypass_media... */
if (sofia_test_flag(ctech_pvt, TFLAG_3PCC) && (switch_channel_test_flag(o_channel, CF_PROXY_MODE) || switch_channel_test_flag(o_channel, CF_PROXY_MEDIA))) {
sofia_set_flag(tech_pvt, TFLAG_3PCC_INVITE);
sofia_set_flag(tech_pvt, TFLAG_LATE_NEGOTIATION);
} else {
sofia_clear_flag(tech_pvt, TFLAG_3PCC_INVITE);
}
}
if (switch_channel_test_flag(o_channel, CF_PROXY_MEDIA)) {
@ -4634,7 +4706,7 @@ static void general_event_handler(switch_event_t *event)
id = switch_mprintf("sip:%s@%s", user, host);
switch_assert(id);
for (m = list->head; m; m = m->next) {
contact = sofia_glue_get_url_from_contact(m->val, 0);
@ -4647,10 +4719,9 @@ static void general_event_handler(switch_event_t *event)
nua_message(nh, NUTAG_NEWSUB(1), SIPTAG_CONTENT_TYPE_STR(ct),
TAG_IF(!zstr(body), SIPTAG_PAYLOAD_STR(body)), TAG_IF(!zstr(subject), SIPTAG_SUBJECT_STR(subject)), TAG_END());
free(id);
}
free(id);
switch_console_free_matches(&list);
sofia_glue_release_profile(profile);

View File

@ -294,6 +294,7 @@ typedef enum {
TFLAG_AUTOFLUSH_DURING_BRIDGE,
TFLAG_NOTIMER_DURING_BRIDGE,
TFLAG_JB_PAUSED,
TFLAG_3PCC_INVITE,
/* No new flags below this line */
TFLAG_MAX
} TFLAGS;
@ -795,7 +796,7 @@ switch_status_t sofia_glue_activate_rtp(private_object_t *tech_pvt, switch_rtp_f
void sofia_glue_deactivate_rtp(private_object_t *tech_pvt);
void sofia_glue_set_local_sdp(private_object_t *tech_pvt, const char *ip, uint32_t port, const char *sr, int force);
void sofia_glue_set_local_sdp(private_object_t *tech_pvt, const char *ip, switch_port_t port, const char *sr, int force);
void sofia_glue_tech_prepare_codecs(private_object_t *tech_pvt);
@ -1065,6 +1066,6 @@ void sofia_glue_proxy_codec(switch_core_session_t *session, const char *r_sdp);
switch_status_t sofia_glue_sdp_map(const char *r_sdp, switch_event_t **fmtp, switch_event_t **pt);
void sofia_glue_build_vid_refresh_message(switch_core_session_t *session, const char *pl);
void sofia_glue_check_dtmf_type(private_object_t *tech_pvt);
void sofia_glue_parse_rtp_bugs(uint32_t *flag_pole, const char *str);
void sofia_glue_parse_rtp_bugs(switch_rtp_bug_flag_t *flag_pole, const char *str);
char *sofia_glue_gen_contact_str(sofia_profile_t *profile, sip_t const *sip, sofia_nat_parse_t *np);
void sofia_glue_pause_jitterbuffer(switch_core_session_t *session, switch_bool_t on);

View File

@ -1326,6 +1326,10 @@ void *SWITCH_THREAD_FUNC sofia_profile_worker_thread_run(switch_thread_t *thread
(statements == 0 || (statements <= 1024 && (switch_micro_time_now() - last_commit)/1000 < profile->trans_timeout)))) {
switch_interval_time_t sleepy_time = !statements ? 1000000 : switch_micro_time_now() - last_commit - profile->trans_timeout*1000;
if (sleepy_time < 1000 || sleepy_time > 1000000) {
sleepy_time = 1000;
}
if (sql || (switch_queue_pop_timeout(profile->sql_queue, &pop, sleepy_time) == SWITCH_STATUS_SUCCESS && pop)) {
switch_size_t newlen;
@ -4373,6 +4377,11 @@ 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 (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_channel_hangup(channel, SWITCH_CAUSE_REDIRECTION_TO_NEW_DESTINATION);
} else if ((!strcmp(profile->sipip, p_contact->m_url->url_host))
@ -4380,6 +4389,11 @@ static void sofia_handle_sip_r_invite(switch_core_session_t *session, int status
|| (switch_xml_locate_domain(p_contact->m_url->url_host, NULL, &root, &domain) == SWITCH_STATUS_SUCCESS)) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Redirect: Transfering to %s\n",
p_contact->m_url->url_user);
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, NULL, NULL);
switch_channel_hangup(channel, SWITCH_CAUSE_REDIRECTION_TO_NEW_DESTINATION);
switch_xml_free(root);
@ -4520,7 +4534,9 @@ static void sofia_handle_sip_r_invite(switch_core_session_t *session, int status
}
}
switch_core_session_queue_message(other_session, msg);
/* SNARK: message to respond to reinvite wasn't being delivered in 3pcc+bypass media case. */
//switch_core_session_queue_message(other_session, msg);
switch_core_session_receive_message(other_session, msg);
switch_core_session_rwunlock(other_session);
}
@ -4694,6 +4710,7 @@ static void sofia_handle_sip_i_state(switch_core_session_t *session, int status,
const char *uuid;
switch_core_session_t *other_session = NULL;
switch_channel_t *other_channel = NULL;
private_object_t *other_tech_pvt = NULL;
char st[80] = "";
int is_dup_sdp = 0;
switch_event_t *s_event = NULL;
@ -4894,6 +4911,24 @@ static void sofia_handle_sip_i_state(switch_core_session_t *session, int status,
break;
case nua_callstate_completing:
{
if (r_sdp && sofia_test_flag(tech_pvt, TFLAG_3PCC_INVITE) && !sofia_test_flag(tech_pvt, TFLAG_SDP)) {
sofia_set_flag(tech_pvt, TFLAG_SDP);
if ((uuid = switch_channel_get_variable(channel, SWITCH_SIGNAL_BOND_VARIABLE))
&& (other_session = switch_core_session_locate(uuid))) {
other_channel = switch_core_session_get_channel(other_session);
other_tech_pvt = switch_core_session_get_private(other_session);
if (!switch_channel_get_variable(other_channel, SWITCH_B_SDP_VARIABLE)) {
switch_channel_set_variable(other_channel, SWITCH_B_SDP_VARIABLE, r_sdp);
}
switch_core_session_queue_indication(other_session, SWITCH_MESSAGE_INDICATE_ANSWER);
switch_core_session_rwunlock(other_session);
}
goto done;
}
if (sofia_test_pflag(profile, PFLAG_TRACK_CALLS)) {
const char *invite_full_via = switch_channel_get_variable(tech_pvt->channel, "sip_invite_full_via");
const char *invite_route_uri = switch_channel_get_variable(tech_pvt->channel, "sip_invite_route_uri");
@ -4971,6 +5006,14 @@ static void sofia_handle_sip_i_state(switch_core_session_t *session, int status,
char *br_a = b_private->uuid;
if (br_b) {
switch_core_session_t *tmp;
if (switch_true(switch_channel_get_variable(channel, "recording_follow_transfer")) &&
(tmp = switch_core_session_locate(br_a))) {
switch_core_media_bug_transfer_recordings(session, tmp);
switch_core_session_rwunlock(tmp);
}
switch_ivr_uuid_bridge(br_a, br_b);
switch_channel_set_variable(channel, SWITCH_ENDPOINT_DISPOSITION_VARIABLE, "ATTENDED_TRANSFER");
sofia_clear_flag_locked(tech_pvt, TFLAG_SIP_HOLD);
@ -4998,10 +5041,12 @@ static void sofia_handle_sip_i_state(switch_core_session_t *session, int status,
switch_channel_hangup(channel, SWITCH_CAUSE_INCOMPATIBLE_DESTINATION);
}
} 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)) {
goto done;
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 {
if (sofia_test_pflag(profile, PFLAG_3PCC)) {
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);
@ -5020,8 +5065,10 @@ static void sofia_handle_sip_i_state(switch_core_session_t *session, int status,
SIPTAG_CONTACT_STR(tech_pvt->profile->url),
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
// 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);
@ -5036,11 +5083,29 @@ static void sofia_handle_sip_i_state(switch_core_session_t *session, int status,
}
goto done;
}
}
} else if (tech_pvt && sofia_test_flag(tech_pvt, TFLAG_SDP) && !r_sdp) {
nua_respond(tech_pvt->nh, SIP_200_OK, TAG_END());
sofia_set_flag_locked(tech_pvt, TFLAG_NOSDP_REINVITE);
if (switch_channel_test_flag(channel, CF_PROXY_MODE) || switch_channel_test_flag(channel, CF_PROXY_MEDIA)) {
sofia_set_flag_locked(tech_pvt, TFLAG_3PCC);
if ((uuid = switch_channel_get_variable(channel, SWITCH_SIGNAL_BOND_VARIABLE))
&& (other_session = switch_core_session_locate(uuid))) {
switch_core_session_message_t *msg;
msg = switch_core_session_alloc(other_session, sizeof(*msg));
msg->message_id = SWITCH_MESSAGE_INDICATE_MEDIA_REDIRECT;
msg->from = __FILE__;
msg->string_arg = NULL;
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Passing NOSDP to other leg.\n");
switch_core_session_queue_message(other_session, msg);
switch_core_session_rwunlock(other_session);
} else {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING,
"NOSDP Re-INVITE to a proxy mode channel that is not in a bridge.\n");
switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
}
goto done;
}
nua_respond(tech_pvt->nh, SIP_200_OK, TAG_END());
goto done;
} else {
ss_state = nua_callstate_completed;
@ -5052,12 +5117,10 @@ static void sofia_handle_sip_i_state(switch_core_session_t *session, int status,
break;
case nua_callstate_completed:
if (r_sdp) {
const char *var;
uint8_t match = 0, is_ok = 1, is_t38 = 0;
tech_pvt->hold_laps = 0;
if (r_sdp) {
const char *var;
if ((var = switch_channel_get_variable(channel, "sip_ignore_reinvites")) && switch_true(var)) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Ignoring Re-invite\n");
nua_respond(tech_pvt->nh, SIP_200_OK, TAG_END());
@ -5218,7 +5281,6 @@ static void sofia_handle_sip_i_state(switch_core_session_t *session, int status,
nua_respond(tech_pvt->nh, SIP_488_NOT_ACCEPTABLE, TAG_END());
}
}
}
break;
case nua_callstate_ready:
if (r_sdp && !is_dup_sdp && switch_rtp_ready(tech_pvt->rtp_session)) {
@ -5251,10 +5313,34 @@ static void sofia_handle_sip_i_state(switch_core_session_t *session, int status,
}
if (r_sdp && sofia_test_flag(tech_pvt, TFLAG_NOSDP_REINVITE)) {
sofia_clear_flag_locked(tech_pvt, TFLAG_NOSDP_REINVITE);
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_MEDIA)) {
if (sofia_glue_activate_rtp(tech_pvt, 0) != SWITCH_STATUS_SUCCESS) {
goto done;
}
}
if ((uuid = switch_channel_get_variable(channel, SWITCH_SIGNAL_BOND_VARIABLE))
&& (other_session = switch_core_session_locate(uuid))) {
other_channel = switch_core_session_get_channel(other_session);
if (!switch_channel_get_variable(other_channel, SWITCH_B_SDP_VARIABLE)) {
switch_channel_set_variable(other_channel, SWITCH_B_SDP_VARIABLE, r_sdp);
}
if (sofia_test_flag(tech_pvt, TFLAG_3PCC) && sofia_test_pflag(profile, PFLAG_3PCC_PROXY)) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "3PCC-PROXY, Got my ACK\n");
sofia_set_flag(tech_pvt, TFLAG_3PCC_HAS_ACK);
} else {
switch_core_session_queue_indication(other_session, SWITCH_MESSAGE_INDICATE_ANSWER);
}
switch_core_session_rwunlock(other_session);
}
} else {
uint8_t match = 0;
int is_ok = 1;
sofia_clear_flag_locked(tech_pvt, TFLAG_NOSDP_REINVITE);
if (tech_pvt->num_codecs) {
match = sofia_glue_negotiate_sdp(session, r_sdp);
@ -5277,7 +5363,7 @@ static void sofia_handle_sip_i_state(switch_core_session_t *session, int status,
nua_respond(nh, SIP_488_NOT_ACCEPTABLE, TAG_END());
switch_channel_hangup(tech_pvt->channel, SWITCH_CAUSE_INCOMPATIBLE_DESTINATION);
}
}
goto done;
}
@ -5344,6 +5430,12 @@ static void sofia_handle_sip_i_state(switch_core_session_t *session, int status,
switch_core_session_rwunlock(other_session);
}
if (sofia_test_flag(tech_pvt, TFLAG_3PCC) && sofia_test_pflag(profile, PFLAG_3PCC_PROXY)) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "3PCC-PROXY, Got my ACK\n");
sofia_set_flag(tech_pvt, TFLAG_3PCC_HAS_ACK);
}
goto done;
} else {
uint8_t match = 0;
@ -5474,6 +5566,11 @@ void *SWITCH_THREAD_FUNC nightmare_xfer_thread_run(switch_thread_t *thread, void
if ((status = switch_ivr_originate(NULL, &tsession, &cause, nhelper->exten_with_params, timeout, NULL, NULL, NULL,
switch_channel_get_caller_profile(channel_a), nhelper->vars, SOF_NONE, NULL)) == SWITCH_STATUS_SUCCESS) {
if (switch_channel_up(channel_a)) {
if (switch_true(switch_channel_get_variable(channel_a, "recording_follow_transfer"))) {
switch_core_media_bug_transfer_recordings(session, a_session);
}
tuuid_str = switch_core_session_get_uuid(tsession);
switch_ivr_uuid_bridge(nhelper->bridge_to_uuid, tuuid_str);
switch_channel_set_variable(channel_a, SWITCH_ENDPOINT_DISPOSITION_VARIABLE, "ATTENDED_TRANSFER");
@ -5668,6 +5765,8 @@ void sofia_handle_sip_i_refer(nua_t *nua, sofia_profile_t *profile, nua_handle_t
switch_channel_set_variable(channel_a, SOFIA_REPLACES_HEADER, rep);
if ((b_private = nua_handle_magic(bnh))) {
int deny_refer_requests = 0;
if (!(b_session = switch_core_session_locate(b_private->uuid))) {
goto done;
}
@ -5685,7 +5784,46 @@ void sofia_handle_sip_i_refer(nua_t *nua, sofia_profile_t *profile, nua_handle_t
br_b = NULL;
}
if (switch_channel_test_flag(channel_b, CF_ORIGINATOR)) {
if (channel_a && switch_true(switch_channel_get_variable(channel_a, "deny_refer_requests"))) {
deny_refer_requests = 1;
}
if (!deny_refer_requests && channel_b && switch_true(switch_channel_get_variable(channel_b, "deny_refer_requests"))) {
deny_refer_requests = 1;
}
if (!deny_refer_requests && br_a) {
switch_core_session_t *a_session;
if ((a_session = switch_core_session_locate(br_a))) {
switch_channel_t *a_channel = switch_core_session_get_channel(a_session);
if (a_channel && switch_true(switch_channel_get_variable(a_channel, "deny_refer_requests"))) {
deny_refer_requests = 1;
}
switch_core_session_rwunlock(a_session);
}
}
if (!deny_refer_requests && br_b) {
switch_core_session_t *b_session;
if ((b_session = switch_core_session_locate(br_b))) {
switch_channel_t *b_channel = switch_core_session_get_channel(b_session);
if (b_channel && switch_true(switch_channel_get_variable(b_channel, "deny_refer_requests"))) {
deny_refer_requests = 1;
}
switch_core_session_rwunlock(b_session);
}
}
if (deny_refer_requests) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_NOTICE, "Denying Attended Transfer, variable [deny_refer_requests] was set to true\n");
nua_notify(tech_pvt->nh, NUTAG_NEWSUB(1), SIPTAG_CONTENT_TYPE_STR("message/sipfrag;version=2.0"),
NUTAG_SUBSTATE(nua_substate_terminated),
SIPTAG_PAYLOAD_STR("SIP/2.0 403 Forbidden\r\n"), SIPTAG_EVENT_STR(etmp), TAG_END());
} else if (switch_channel_test_flag(channel_b, CF_ORIGINATOR)) {
switch_core_session_t *a_session;
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_NOTICE,
@ -5783,6 +5921,21 @@ void sofia_handle_sip_i_refer(nua_t *nua, sofia_profile_t *profile, nua_handle_t
switch_core_session_rwunlock(tmp);
}
if (switch_true(switch_channel_get_variable(channel_a, "recording_follow_transfer")) &&
(tmp = switch_core_session_locate(br_a))) {
switch_core_media_bug_transfer_recordings(session, tmp);
switch_core_session_rwunlock(tmp);
}
if (switch_true(switch_channel_get_variable(channel_b, "recording_follow_transfer")) &&
(tmp = switch_core_session_locate(br_b))) {
switch_core_media_bug_transfer_recordings(b_session, tmp);
switch_core_session_rwunlock(tmp);
}
switch_ivr_uuid_bridge(br_b, br_a);
switch_channel_set_variable(channel_b, SWITCH_ENDPOINT_DISPOSITION_VARIABLE, "ATTENDED_TRANSFER");
nua_notify(tech_pvt->nh, NUTAG_NEWSUB(1), SIPTAG_CONTENT_TYPE_STR("message/sipfrag;version=2.0"),
@ -5803,17 +5956,19 @@ void sofia_handle_sip_i_refer(nua_t *nua, sofia_profile_t *profile, nua_handle_t
NUTAG_SUBSTATE(nua_substate_terminated), SIPTAG_PAYLOAD_STR("SIP/2.0 403 Forbidden\r\n"),
SIPTAG_EVENT_STR(etmp), TAG_END());
} else {
switch_core_session_t *t_session;
switch_core_session_t *t_session, *hup_session;
switch_channel_t *hup_channel;
const char *ext;
if (br_a && !br_b) {
t_session = switch_core_session_locate(br_a);
hup_channel = channel_b;
hup_session = b_session;
} else {
private_object_t *h_tech_pvt = (private_object_t *) switch_core_session_get_private(b_session);
t_session = switch_core_session_locate(br_b);
hup_channel = channel_a;
hup_session = session;
sofia_clear_flag_locked(tech_pvt, TFLAG_SIP_HOLD);
switch_channel_clear_flag(tech_pvt->channel, CF_LEG_HOLDING);
sofia_clear_flag_locked(h_tech_pvt, TFLAG_SIP_HOLD);
@ -5834,6 +5989,11 @@ void sofia_handle_sip_i_refer(nua_t *nua, sofia_profile_t *profile, nua_handle_t
switch_channel_set_variable(t_channel, SOFIA_REFER_TO_VARIABLE, full_ref_to);
}
if (switch_true(switch_channel_get_variable(hup_channel, "recording_follow_transfer"))) {
switch_core_media_bug_transfer_recordings(hup_session, t_session);
}
if (idest) {
switch_ivr_session_transfer(t_session, idest, "inline", NULL);
} else {
@ -5996,6 +6156,10 @@ void sofia_handle_sip_i_refer(nua_t *nua, sofia_profile_t *profile, nua_handle_t
switch_channel_set_variable(b_channel, SOFIA_REFER_TO_VARIABLE, full_ref_to);
}
if (switch_true(switch_channel_get_variable(channel, "recording_follow_transfer"))) {
switch_core_media_bug_transfer_recordings(session, b_session);
}
switch_ivr_session_transfer(b_session, exten, NULL, NULL);
switch_core_session_rwunlock(b_session);
}
@ -6096,6 +6260,11 @@ void sofia_handle_sip_i_info(nua_t *nua, sofia_profile_t *profile, nua_handle_t
const char *clientcode_header;
switch_dtmf_t dtmf = { 0, switch_core_default_dtmf_duration(0) };
switch_event_t *event;
private_object_t *tech_pvt = NULL;
if (session) {
tech_pvt = (private_object_t *) switch_core_session_get_private(session);
}
if (sofia_test_pflag(profile, PFLAG_EXTENDED_INFO_PARSING)) {
if (sip && sip->sip_content_type && sip->sip_content_type->c_type && sip->sip_content_type->c_subtype &&
@ -6228,7 +6397,7 @@ void sofia_handle_sip_i_info(nua_t *nua, sofia_profile_t *profile, nua_handle_t
goto end;
}
if (dtmf.digit) {
if (dtmf.digit && tech_pvt->dtmf_type == DTMF_INFO) {
/* queue it up */
switch_channel_queue_dtmf(channel, &dtmf);
@ -6253,6 +6422,9 @@ void sofia_handle_sip_i_info(nua_t *nua, sofia_profile_t *profile, nua_handle_t
/* Send 200 OK response */
nua_respond(nh, SIP_200_OK, NUTAG_WITH_THIS(nua), TAG_END());
} else {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING,
"IGNORE INFO DTMF(%c) (This channel was not configured to use INFO DTMF!)\n", dtmf.digit);
}
goto end;
}
@ -6806,7 +6978,7 @@ void sofia_handle_sip_i_invite(nua_t *nua, sofia_profile_t *profile, nua_handle_
if (sip->sip_to && sip->sip_to->a_url) {
const char *host, *user;
int port;
int port, check_nat = 0;
url_t *transport_url;
if (sip->sip_record_route && sip->sip_record_route->r_url) {
@ -6846,10 +7018,22 @@ void sofia_handle_sip_i_invite(nua_t *nua, sofia_profile_t *profile, nua_handle_
if (sofia_glue_check_nat(profile, tech_pvt->remote_ip)) {
url = (sofia_glue_transport_has_tls(transport)) ? profile->tls_public_url : profile->public_url;
check_nat = 1;
} else {
url = (sofia_glue_transport_has_tls(transport)) ? profile->tls_url : profile->url;
}
if (!url) {
if (check_nat) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Nat detected but no external address configured.\n");
}
url = profile->url;
}
if (!url) {
switch_channel_hangup(tech_pvt->channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
}
tmp = sofia_overcome_sip_uri_weakness(session, url, transport, SWITCH_TRUE, NULL);
if ((at = strchr(tmp, '@'))) {

View File

@ -358,7 +358,7 @@ void sofia_glue_check_dtmf_type(private_object_t *tech_pvt)
}
void sofia_glue_set_local_sdp(private_object_t *tech_pvt, const char *ip, uint32_t port, const char *sr, int force)
void sofia_glue_set_local_sdp(private_object_t *tech_pvt, const char *ip, switch_port_t port, const char *sr, int force)
{
char buf[2048];
int ptime = 0;
@ -2396,6 +2396,7 @@ switch_status_t sofia_glue_do_invite(switch_core_session_t *session)
if (sofia_use_soa(tech_pvt)) {
nua_invite(tech_pvt->nh,
NUTAG_AUTOANSWER(0),
NUTAG_AUTOACK(0),
NUTAG_SESSION_TIMER(session_timeout),
NUTAG_SESSION_REFRESHER(session_timeout ? nua_local_refresher : nua_no_refresher),
TAG_IF(sofia_test_flag(tech_pvt, TFLAG_RECOVERED), NUTAG_INVITE_TIMER(UINT_MAX)),
@ -2417,15 +2418,19 @@ switch_status_t sofia_glue_do_invite(switch_core_session_t *session)
TAG_IF(!zstr(route), SIPTAG_ROUTE_STR(route)),
TAG_IF(tech_pvt->profile->minimum_session_expires, NUTAG_MIN_SE(tech_pvt->profile->minimum_session_expires)),
TAG_IF(cseq, SIPTAG_CSEQ(cseq)),
SOATAG_ADDRESS(tech_pvt->adv_sdp_audio_ip),
SOATAG_USER_SDP_STR(tech_pvt->local_sdp_str),
SOATAG_REUSE_REJECTED(1),
SOATAG_ORDERED_USER(1),
SOATAG_RTP_SORT(SOA_RTP_SORT_REMOTE),
SOATAG_RTP_SELECT(SOA_RTP_SELECT_ALL), TAG_IF(rep, SIPTAG_REPLACES_STR(rep)), SOATAG_HOLD(holdstr), TAG_END());
TAG_IF(zstr(tech_pvt->local_sdp_str), SIPTAG_PAYLOAD_STR("")),
TAG_IF(!zstr(tech_pvt->local_sdp_str), SOATAG_ADDRESS(tech_pvt->adv_sdp_audio_ip)),
TAG_IF(!zstr(tech_pvt->local_sdp_str), SOATAG_USER_SDP_STR(tech_pvt->local_sdp_str)),
TAG_IF(!zstr(tech_pvt->local_sdp_str), SOATAG_REUSE_REJECTED(1)),
TAG_IF(!zstr(tech_pvt->local_sdp_str), SOATAG_ORDERED_USER(1)),
TAG_IF(!zstr(tech_pvt->local_sdp_str), SOATAG_RTP_SORT(SOA_RTP_SORT_REMOTE)),
TAG_IF(!zstr(tech_pvt->local_sdp_str), SOATAG_RTP_SELECT(SOA_RTP_SELECT_ALL)),
TAG_IF(rep, SIPTAG_REPLACES_STR(rep)),
TAG_IF(!zstr(tech_pvt->local_sdp_str), SOATAG_HOLD(holdstr)), TAG_END());
} else {
nua_invite(tech_pvt->nh,
NUTAG_AUTOANSWER(0),
NUTAG_AUTOACK(0),
NUTAG_SESSION_TIMER(session_timeout),
TAG_IF(session_timeout, NUTAG_SESSION_REFRESHER(nua_remote_refresher)),
TAG_IF(sofia_test_flag(tech_pvt, TFLAG_RECOVERED), NUTAG_INVITE_TIMER(UINT_MAX)),
@ -3579,7 +3584,7 @@ static void add_audio_codec(sdp_rtpmap_t *map, int ptime, char *buf, switch_size
codec_ms = switch_default_ptime(map->rm_encoding, map->rm_pt);
}
map_bit_rate = switch_known_bitrate(map->rm_pt);
map_bit_rate = switch_known_bitrate((switch_payload_t)map->rm_pt);
if (!ptime && !strcasecmp(map->rm_encoding, "g723")) {
ptime = codec_ms = 30;
@ -4649,7 +4654,7 @@ uint8_t sofia_glue_negotiate_sdp(switch_core_session_t *session, const char *r_s
codec_ms = switch_default_ptime(rm_encoding, map->rm_pt);
}
map_bit_rate = switch_known_bitrate(map->rm_pt);
map_bit_rate = switch_known_bitrate((switch_payload_t)map->rm_pt);
if (!ptime && !strcasecmp(map->rm_encoding, "g723")) {
ptime = codec_ms = 30;
@ -4765,7 +4770,7 @@ uint8_t sofia_glue_negotiate_sdp(switch_core_session_t *session, const char *r_s
switch_snprintf(tmp, sizeof(tmp), "%d", tech_pvt->remote_sdp_audio_port);
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);
tech_pvt->audio_recv_pt = map->rm_pt;
tech_pvt->audio_recv_pt = (switch_payload_t)map->rm_pt;
if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND && !sofia_test_flag(tech_pvt, TFLAG_REINVITE)) {
sofia_glue_get_offered_pt(tech_pvt, mimp, &tech_pvt->audio_recv_pt);
@ -4889,7 +4894,7 @@ uint8_t sofia_glue_negotiate_sdp(switch_core_session_t *session, const char *r_s
switch_channel_set_variable(tech_pvt->channel, "sip_video_pt", tmp);
sofia_glue_check_video_codecs(tech_pvt);
tech_pvt->video_recv_pt = map->rm_pt;
tech_pvt->video_recv_pt = (switch_payload_t)map->rm_pt;
if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) {
sofia_glue_get_offered_pt(tech_pvt, mimp, &tech_pvt->video_recv_pt);
@ -5458,13 +5463,13 @@ static int recover_callback(void *pArg, int argc, char **argv, char **columnName
if (switch_rtp_ready(tech_pvt->rtp_session)) {
if ((tmp = switch_channel_get_variable(channel, "sip_audio_recv_pt"))) {
switch_rtp_set_recv_pt(tech_pvt->rtp_session, atoi(tmp));
switch_rtp_set_recv_pt(tech_pvt->rtp_session, (switch_payload_t)atoi(tmp));
}
}
if (switch_rtp_ready(tech_pvt->video_rtp_session)) {
if ((tmp = switch_channel_get_variable(channel, "sip_video_recv_pt"))) {
switch_rtp_set_recv_pt(tech_pvt->rtp_session, atoi(tmp));
switch_rtp_set_recv_pt(tech_pvt->rtp_session, (switch_payload_t)atoi(tmp));
}
}
@ -6415,7 +6420,7 @@ void sofia_glue_build_vid_refresh_message(switch_core_session_t *session, const
}
void sofia_glue_parse_rtp_bugs(uint32_t *flag_pole, const char *str)
void sofia_glue_parse_rtp_bugs(switch_rtp_bug_flag_t *flag_pole, const char *str)
{
if (switch_stristr("clear", str)) {

View File

@ -1050,7 +1050,7 @@ uint8_t sofia_reg_handle_register(nua_t *nua, sofia_profile_t *profile, nua_hand
}
if (authorization) {
char *v_contact_str;
char *v_contact_str = NULL;
const char *username = "unknown";
const char *realm = reg_host;
if ((auth_res = sofia_reg_parse_auth(profile, authorization, sip, sip->sip_request->rq_method_name,

View File

@ -285,7 +285,7 @@ static void *SWITCH_THREAD_FUNC read_stream_thread(switch_thread_t *thread, void
samples = 0;
switch_mutex_lock(source->device_lock);
samples = ReadAudioStream(source->audio_stream, source->databuf,
source->read_codec.implementation->samples_per_packet, &source->timer);
source->read_codec.implementation->samples_per_packet, 0, &source->timer);
switch_mutex_unlock(source->device_lock);

View File

@ -655,9 +655,6 @@ static switch_status_t shout_file_open(switch_file_handle_t *handle, const char
}
} else if (switch_test_flag(handle, SWITCH_FILE_FLAG_WRITE)) {
if (switch_test_flag(handle, SWITCH_FILE_WRITE_APPEND)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Appending to MP3 not supported.\n");
}
if (!(context->gfp = lame_init())) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Could not allocate lame\n");
goto error;
@ -781,8 +778,13 @@ static switch_status_t shout_file_open(switch_file_handle_t *handle, const char
}
} else {
const char *mask = "wb+";
if (switch_test_flag(handle, SWITCH_FILE_WRITE_APPEND)) {
mask = "ab+";
}
/* lame being lame and all has FILE * coded into it's API for some functions so we gotta use it */
if (!(context->fp = fopen(path, "wb+"))) {
if (!(context->fp = fopen(path, mask))) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error opening %s\n", path);
goto error;
}

View File

@ -6449,6 +6449,20 @@ SWIGEXPORT int SWIGSTDCALL CSharp_switch_core_media_bug_enumerate(void * jarg1,
}
SWIGEXPORT int SWIGSTDCALL CSharp_switch_core_media_bug_transfer_recordings(void * jarg1, void * jarg2) {
int jresult ;
switch_core_session_t *arg1 = (switch_core_session_t *) 0 ;
switch_core_session_t *arg2 = (switch_core_session_t *) 0 ;
switch_status_t result;
arg1 = (switch_core_session_t *)jarg1;
arg2 = (switch_core_session_t *)jarg2;
result = (switch_status_t)switch_core_media_bug_transfer_recordings(arg1,arg2);
jresult = result;
return jresult;
}
SWIGEXPORT int SWIGSTDCALL CSharp_switch_core_media_bug_read(void * jarg1, void * jarg2, int jarg3) {
int jresult ;
switch_media_bug_t *arg1 = (switch_media_bug_t *) 0 ;
@ -25393,6 +25407,22 @@ SWIGEXPORT int SWIGSTDCALL CSharp_switch_event_del_header_val(void * jarg1, char
}
SWIGEXPORT int SWIGSTDCALL CSharp_switch_event_add_array(void * jarg1, char * jarg2, char * jarg3) {
int jresult ;
switch_event_t *arg1 = (switch_event_t *) 0 ;
char *arg2 = (char *) 0 ;
char *arg3 = (char *) 0 ;
int result;
arg1 = (switch_event_t *)jarg1;
arg2 = (char *)jarg2;
arg3 = (char *)jarg3;
result = (int)switch_event_add_array(arg1,(char const *)arg2,(char const *)arg3);
jresult = result;
return jresult;
}
SWIGEXPORT void SWIGSTDCALL CSharp_switch_event_destroy(void * jarg1) {
switch_event_t **arg1 = (switch_event_t **) 0 ;

View File

@ -1073,6 +1073,11 @@ public class freeswitch {
return ret;
}
public static switch_status_t switch_core_media_bug_transfer_recordings(SWIGTYPE_p_switch_core_session orig_session, SWIGTYPE_p_switch_core_session new_session) {
switch_status_t ret = (switch_status_t)freeswitchPINVOKE.switch_core_media_bug_transfer_recordings(SWIGTYPE_p_switch_core_session.getCPtr(orig_session), SWIGTYPE_p_switch_core_session.getCPtr(new_session));
return ret;
}
public static switch_status_t switch_core_media_bug_read(SWIGTYPE_p_switch_media_bug bug, switch_frame frame, switch_bool_t fill) {
switch_status_t ret = (switch_status_t)freeswitchPINVOKE.switch_core_media_bug_read(SWIGTYPE_p_switch_media_bug.getCPtr(bug), switch_frame.getCPtr(frame), (int)fill);
return ret;
@ -3956,6 +3961,11 @@ public class freeswitch {
return ret;
}
public static int switch_event_add_array(switch_event arg0, string var, string val) {
int ret = freeswitchPINVOKE.switch_event_add_array(switch_event.getCPtr(arg0), var, val);
return ret;
}
public static void switch_event_destroy(SWIGTYPE_p_p_switch_event arg0) {
freeswitchPINVOKE.switch_event_destroy(SWIGTYPE_p_p_switch_event.getCPtr(arg0));
}
@ -7566,6 +7576,9 @@ class freeswitchPINVOKE {
[DllImport("mod_managed", EntryPoint="CSharp_switch_core_media_bug_enumerate")]
public static extern int switch_core_media_bug_enumerate(HandleRef jarg1, HandleRef jarg2);
[DllImport("mod_managed", EntryPoint="CSharp_switch_core_media_bug_transfer_recordings")]
public static extern int switch_core_media_bug_transfer_recordings(HandleRef jarg1, HandleRef jarg2);
[DllImport("mod_managed", EntryPoint="CSharp_switch_core_media_bug_read")]
public static extern int switch_core_media_bug_read(HandleRef jarg1, HandleRef jarg2, int jarg3);
@ -12138,6 +12151,9 @@ class freeswitchPINVOKE {
[DllImport("mod_managed", EntryPoint="CSharp_switch_event_del_header_val")]
public static extern int switch_event_del_header_val(HandleRef jarg1, string jarg2, string jarg3);
[DllImport("mod_managed", EntryPoint="CSharp_switch_event_add_array")]
public static extern int switch_event_add_array(HandleRef jarg1, string jarg2, string jarg3);
[DllImport("mod_managed", EntryPoint="CSharp_switch_event_destroy")]
public static extern void switch_event_destroy(HandleRef jarg1);
@ -25168,8 +25184,7 @@ public class switch_event : IDisposable {
namespace FreeSWITCH.Native {
public enum switch_event_flag_t {
EF_UNIQ_HEADERS = (1 << 0),
EF_CONTAINS_ARRAYS = (1 << 1)
EF_UNIQ_HEADERS = (1 << 0)
}
}

View File

@ -635,7 +635,7 @@ SWITCH_DECLARE(void) switch_channel_mark_hold(switch_channel_t *channel, switch_
switch_event_t *event;
if (!!on == !!switch_channel_test_flag(channel, CF_LEG_HOLDING)) {
return;
goto end;
}
if (on) {
@ -649,6 +649,18 @@ SWITCH_DECLARE(void) switch_channel_mark_hold(switch_channel_t *channel, switch_
switch_event_fire(&event);
}
end:
if (on) {
if (switch_true(switch_channel_get_variable(channel, "flip_record_on_hold"))) {
switch_core_session_t *other_session;
if (switch_core_session_get_partner(channel->session, &other_session) == SWITCH_STATUS_SUCCESS) {
switch_core_media_bug_transfer_recordings(channel->session, other_session);
switch_core_session_rwunlock(other_session);
}
}
}
}
SWITCH_DECLARE(const char *) switch_channel_get_hold_music(switch_channel_t *channel)
@ -1032,7 +1044,9 @@ SWITCH_DECLARE(switch_status_t) switch_channel_set_variable_var_check(switch_cha
switch_mutex_lock(channel->profile_mutex);
if (channel->variables && !zstr(varname)) {
if (!zstr(value)) {
if (zstr(value)) {
switch_event_del_header(channel->variables, varname);
} else {
int ok = 1;
if (var_check) {
@ -1061,7 +1075,9 @@ SWITCH_DECLARE(switch_status_t) switch_channel_add_variable_var_check(switch_cha
switch_mutex_lock(channel->profile_mutex);
if (channel->variables && !zstr(varname)) {
if (!zstr(value)) {
if (zstr(value)) {
switch_event_del_header(channel->variables, varname);
} else {
int ok = 1;
if (var_check) {
@ -3627,7 +3643,7 @@ SWITCH_DECLARE(switch_status_t) switch_channel_set_timestamps(switch_channel_t *
switch_snprintf(tmp, sizeof(tmp), "%d", billsec);
switch_channel_set_variable(channel, "billsec", tmp);
switch_snprintf(tmp, sizeof(tmp), "%d", progresssec);
switch_snprintf(tmp, sizeof(tmp), "%"SWITCH_TIME_T_FMT, progresssec);
switch_channel_set_variable(channel, "progresssec", tmp);
switch_snprintf(tmp, sizeof(tmp), "%d", answersec);
@ -3636,7 +3652,7 @@ SWITCH_DECLARE(switch_status_t) switch_channel_set_timestamps(switch_channel_t *
switch_snprintf(tmp, sizeof(tmp), "%d", waitsec);
switch_channel_set_variable(channel, "waitsec", tmp);
switch_snprintf(tmp, sizeof(tmp), "%d", progress_mediasec);
switch_snprintf(tmp, sizeof(tmp), "%"SWITCH_TIME_T_FMT, progress_mediasec);
switch_channel_set_variable(channel, "progress_mediasec", tmp);
switch_snprintf(tmp, sizeof(tmp), "%d", legbillsec);

View File

@ -105,7 +105,7 @@ static switch_status_t console_xml_config(void)
for (param = switch_xml_child(settings, "key"); param; param = param->next) {
char *var = (char *) switch_xml_attr_soft(param, "name");
char *val = (char *) switch_xml_attr_soft(param, "value");
int i = atoi(var);
i = atoi(var);
if ((i < 1) || (i > 12)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Keybind %s is invalid, range is from 1 to 12\n", var);
} else {
@ -913,7 +913,7 @@ static unsigned char console_fnkey_pressed(int i)
{
char *c, *cmd;
assert((i > 0) && (i <= 12));
switch_assert((i > 0) && (i <= 12));
c = console_fnkeys[i - 1];
@ -1675,6 +1675,7 @@ SWITCH_DECLARE(void) switch_console_sort_matches(switch_console_callback_match_t
sort[3] = sort[2] ? sort[2]->next : NULL;
for (j = 1; j <= (matches->count - i); j++) {
switch_assert(sort[1] && sort[2]);
if (strcmp(sort[1]->val, sort[2]->val) > 0) {
sort[1]->next = sort[3];
sort[2]->next = sort[1];

View File

@ -392,6 +392,47 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_bug_flush_all(switch_core_sess
return SWITCH_STATUS_FALSE;
}
SWITCH_DECLARE(switch_status_t) switch_core_media_bug_transfer_recordings(switch_core_session_t *orig_session, switch_core_session_t *new_session)
{
switch_media_bug_t *bp;
char *list[100] = { 0 };
int stop_times[100] = { 0 };
int i = 0, x = 0;
if (orig_session->bugs) {
switch_channel_t *new_channel = switch_core_session_get_channel(new_session);
const char *save = switch_channel_get_variable(new_channel, "record_append");
switch_thread_rwlock_wrlock(orig_session->bug_rwlock);
switch_channel_set_variable(new_channel, "record_append", "true");
for (bp = orig_session->bugs; bp; bp = bp->next) {
if (!strcmp(bp->function, "session_record")) {
list[x] = switch_core_session_strdup(new_session, bp->target);
if (bp->stop_time > 0) {
stop_times[x] = (int)(bp->stop_time - switch_epoch_time_now(NULL));
}
x++;
}
}
switch_thread_rwlock_unlock(orig_session->bug_rwlock);
for(i = 0; i < x; i++) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(orig_session), SWITCH_LOG_CRIT, "Transfering %s from %s to %s\n", list[i],
switch_core_session_get_name(orig_session), switch_core_session_get_name(new_session));
switch_ivr_stop_record_session(orig_session, list[i]);
switch_ivr_record_session(new_session, list[i], stop_times[i], NULL);
}
switch_channel_set_variable(new_channel, "record_append", save);
}
return x ? SWITCH_STATUS_SUCCESS : SWITCH_STATUS_FALSE;
}
SWITCH_DECLARE(switch_status_t) switch_core_media_bug_enumerate(switch_core_session_t *session, switch_stream_handle_t *stream)
{
switch_media_bug_t *bp;

View File

@ -616,6 +616,10 @@ static const char *message_names[] = {
"APPLICATION_EXEC_COMPLETE",
"PHONE_EVENT",
"T38_DESCRIPTION"
"UDPTL_MODE",
"CLEAR_PROGRESS",
"JITTER_BUFFER",
"RECOVERY_REFRESH",
"INVALID"
};
@ -644,8 +648,8 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_perform_receive_message(swit
message->_line = line;
}
if (message->message_id > SWITCH_MESSAGE_INVALID) {
message->message_id = SWITCH_MESSAGE_INVALID;
if (message->message_id > SWITCH_MESSAGE_INVALID-1) {
message->message_id = SWITCH_MESSAGE_INVALID-1;
}
switch_log_printf(SWITCH_CHANNEL_ID_LOG, message->_file, message->_func, message->_line,

View File

@ -856,7 +856,6 @@ SWITCH_DECLARE(int) switch_event_add_array(switch_event_t *event, const char *va
{
char *data;
char **array;
int idx;
int max = 0;
int len;
const char *p;
@ -887,7 +886,7 @@ SWITCH_DECLARE(int) switch_event_add_array(switch_event_t *event, const char *va
array = malloc(len);
memset(array, 0, len);
idx = switch_separate_string_string(data, "|:", array, max);
switch_separate_string_string(data, "|:", array, max);
for(i = 0; i < max; i++) {
switch_event_add_header_string(event, SWITCH_STACK_PUSH, var, array[i]);
@ -917,7 +916,7 @@ static switch_status_t switch_event_base_add_header(switch_event_t *event, switc
}
header_name = real_header_name;
}
if (index_ptr || (stack & SWITCH_STACK_PUSH) || (stack & SWITCH_STACK_UNSHIFT)) {
if (!(header = switch_event_get_header_ptr(event, header_name)) && index_ptr) {
@ -971,6 +970,13 @@ static switch_status_t switch_event_base_add_header(switch_event_t *event, switc
if (!header) {
if (zstr(data)) {
switch_event_del_header(event, header_name);
FREE(data);
goto end;
}
if (switch_test_flag(event, EF_UNIQ_HEADERS)) {
switch_event_del_header(event, header_name);
}
@ -1296,11 +1302,10 @@ SWITCH_DECLARE(switch_status_t) switch_event_serialize(switch_event_t *event, ch
llen = strlen(hp->name) + strlen(encode_buf) + 8;
if ((len + llen) > dlen) {
char *m;
char *m = buf;
dlen += (blocksize + (len + llen));
if ((m = realloc(buf, dlen))) {
if (!(buf = realloc(buf, dlen))) {
buf = m;
} else {
abort();
}
}
@ -1323,11 +1328,10 @@ SWITCH_DECLARE(switch_status_t) switch_event_serialize(switch_event_t *event, ch
}
if ((len + llen) > dlen) {
char *m;
char *m = buf;
dlen += (blocksize + (len + llen));
if ((m = realloc(buf, dlen))) {
if (!(buf = realloc(buf, dlen))) {
buf = m;
} else {
abort();
}
}

View File

@ -155,7 +155,13 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_sleep(switch_core_session_t *session,
return SWITCH_STATUS_SUCCESS;
}
if (ms > 100 && (var = switch_channel_get_variable(channel, SWITCH_SEND_SILENCE_WHEN_IDLE_VARIABLE)) && (sval = atoi(var))) {
var = switch_channel_get_variable(channel, SWITCH_SEND_SILENCE_WHEN_IDLE_VARIABLE);
if (var) {
sval = atoi(var);
SWITCH_IVR_VERIFY_SILENCE_DIVISOR(sval);
}
if (ms > 100 && sval) {
switch_core_session_get_read_impl(session, &imp);
if (switch_core_codec_init(&codec,
@ -744,34 +750,6 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_park(switch_core_session_t *session,
unsigned char *abuf = NULL;
switch_codec_implementation_t imp = { 0 };
if ((var = switch_channel_get_variable(channel, SWITCH_SEND_SILENCE_WHEN_IDLE_VARIABLE)) && (sval = atoi(var))) {
switch_core_session_get_read_impl(session, &imp);
if (switch_core_codec_init(&codec,
"L16",
NULL,
imp.samples_per_second,
imp.microseconds_per_packet / 1000,
imp.number_of_channels,
SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE, NULL,
switch_core_session_get_pool(session)) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Codec Error L16@%uhz %u channels %dms\n",
imp.samples_per_second, imp.number_of_channels, imp.microseconds_per_packet / 1000);
return SWITCH_STATUS_FALSE;
}
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Codec Activated L16@%uhz %u channels %dms\n",
imp.samples_per_second, imp.number_of_channels, imp.microseconds_per_packet / 1000);
write_frame.codec = &codec;
switch_zmalloc(abuf, SWITCH_RECOMMENDED_BUFFER_SIZE);
write_frame.data = abuf;
write_frame.buflen = SWITCH_RECOMMENDED_BUFFER_SIZE;
write_frame.datalen = imp.decoded_bytes_per_packet;
write_frame.samples = write_frame.datalen / sizeof(int16_t);
}
if (switch_channel_test_flag(channel, CF_RECOVERED) && switch_channel_test_flag(channel, CF_CONTROLLED)) {
switch_channel_clear_flag(channel, CF_CONTROLLED);
}
@ -815,6 +793,34 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_park(switch_core_session_t *session,
switch_core_session_get_read_impl(session, &read_impl);
rate = read_impl.actual_samples_per_second;
bpf = read_impl.decoded_bytes_per_packet;
if ((var = switch_channel_get_variable(channel, SWITCH_SEND_SILENCE_WHEN_IDLE_VARIABLE)) && (sval = atoi(var))) {
switch_core_session_get_read_impl(session, &imp);
if (switch_core_codec_init(&codec,
"L16",
NULL,
imp.samples_per_second,
imp.microseconds_per_packet / 1000,
imp.number_of_channels,
SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE, NULL,
switch_core_session_get_pool(session)) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Codec Error L16@%uhz %u channels %dms\n",
imp.samples_per_second, imp.number_of_channels, imp.microseconds_per_packet / 1000);
return SWITCH_STATUS_FALSE;
}
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Codec Activated L16@%uhz %u channels %dms\n",
imp.samples_per_second, imp.number_of_channels, imp.microseconds_per_packet / 1000);
write_frame.codec = &codec;
switch_zmalloc(abuf, SWITCH_RECOMMENDED_BUFFER_SIZE);
write_frame.data = abuf;
write_frame.buflen = SWITCH_RECOMMENDED_BUFFER_SIZE;
write_frame.datalen = imp.decoded_bytes_per_packet;
write_frame.samples = write_frame.datalen / sizeof(int16_t);
}
}
if (rate) {
@ -839,7 +845,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_park(switch_core_session_t *session,
break;
}
if (write_frame.data) {
if (rate && write_frame.data && sval) {
switch_generate_sln_silence((int16_t *) write_frame.data, write_frame.samples, sval);
switch_core_session_write_frame(session, &write_frame, SWITCH_IO_FLAG_NONE, 0);
}

View File

@ -936,12 +936,6 @@ static switch_bool_t record_callback(switch_media_bug_t *bug, void *user_data, s
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Stop recording file %s\n", rh->file);
switch_channel_set_private(channel, rh->file, NULL);
if (switch_event_create(&event, SWITCH_EVENT_RECORD_STOP) == SWITCH_STATUS_SUCCESS) {
switch_channel_event_set_data(channel, event);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Record-File-Path", rh->file);
switch_event_fire(&event);
}
if (rh->fh) {
switch_size_t len;
uint8_t data[SWITCH_RECOMMENDED_BUFFER_SIZE];
@ -970,6 +964,12 @@ static switch_bool_t record_callback(switch_media_bug_t *bug, void *user_data, s
}
}
if (switch_event_create(&event, SWITCH_EVENT_RECORD_STOP) == SWITCH_STATUS_SUCCESS) {
switch_channel_event_set_data(channel, event);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Record-File-Path", rh->file);
switch_event_fire(&event);
}
if ((var = switch_channel_get_variable(channel, "record_post_process_exec_app"))) {
char *app = switch_core_session_strdup(session, var);
char *data;
@ -1444,7 +1444,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_record_session(switch_core_session_t
int file_flags = SWITCH_FILE_FLAG_WRITE | SWITCH_FILE_DATA_SHORT;
switch_bool_t hangup_on_error = SWITCH_FALSE;
char *file_path = NULL;
if ((p = switch_channel_get_variable(channel, "RECORD_HANGUP_ON_ERROR"))) {
hangup_on_error = switch_true(p);
}
@ -1463,7 +1463,36 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_record_session(switch_core_session_t
channels = read_impl.number_of_channels;
if ((bug = switch_channel_get_private(channel, file))) {
return switch_ivr_stop_record_session(session, file);
if (switch_true(switch_channel_get_variable(channel, "RECORD_TOGGLE_ON_REPEAT"))) {
return switch_ivr_stop_record_session(session, file);
}
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Already recording [%s]\n", file);
return SWITCH_STATUS_SUCCESS;
}
if ((p = switch_channel_get_variable(channel, "RECORD_CHECK_BRIDGE")) && switch_true(p)) {
switch_core_session_t *other_session;
int exist = 0;
switch_status_t rstatus = SWITCH_STATUS_SUCCESS;
if (switch_core_session_get_partner(session, &other_session) == SWITCH_STATUS_SUCCESS) {
switch_channel_t *other_channel = switch_core_session_get_channel(other_session);
if ((bug = switch_channel_get_private(other_channel, file))) {
if (switch_true(switch_channel_get_variable(other_channel, "RECORD_TOGGLE_ON_REPEAT"))) {
rstatus = switch_ivr_stop_record_session(other_session, file);
} else {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(other_session), SWITCH_LOG_WARNING, "Already recording [%s]\n", file);
}
exist = 1;
}
switch_core_session_rwunlock(other_session);
}
if (exist) {
return rstatus;
}
}
if (!fh) {
@ -1615,7 +1644,9 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_record_session(switch_core_session_t
rh->file = switch_core_session_strdup(session, file);
rh->packet_len = read_impl.decoded_bytes_per_packet;
rh->min_sec = 3;
if (file_flags & SWITCH_FILE_WRITE_APPEND) {
rh->min_sec = 3;
}
if ((p = switch_channel_get_variable(channel, "RECORD_MIN_SEC"))) {
int tmp = atoi(p);
@ -1638,6 +1669,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_record_session(switch_core_session_t
return SWITCH_STATUS_SUCCESS;
}
typedef struct {
SpeexPreprocessState *read_st;
SpeexPreprocessState *write_st;

View File

@ -910,9 +910,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_wait_for_answer(switch_core_session_t
ringback.silence = atoi(p);
}
}
if (ringback.silence <= 0) {
ringback.silence = 400;
}
SWITCH_IVR_VERIFY_SILENCE_DIVISOR(ringback.silence);
} else {
switch_buffer_create_dynamic(&ringback.audio_buffer, 512, 1024, 0);
switch_buffer_set_loops(ringback.audio_buffer, -1);
@ -1203,9 +1201,7 @@ static switch_status_t setup_ringback(originate_global_t *oglobals, originate_st
ringback->silence = atoi(c);
}
}
if (ringback->silence <= 0) {
ringback->silence = 400;
}
SWITCH_IVR_VERIFY_SILENCE_DIVISOR(ringback->silence);
} else {
switch_buffer_create_dynamic(&ringback->audio_buffer, 512, 1024, 0);
switch_buffer_set_loops(ringback->audio_buffer, -1);
@ -2938,7 +2934,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_originate(switch_core_session_t *sess
oglobals.idx = IDX_CANCEL;
}
if (oglobals.session && (ringback_data || !(switch_channel_test_flag(caller_channel, CF_PROXY_MODE) &&
if (oglobals.session && (ringback_data || !(switch_channel_test_flag(caller_channel, CF_PROXY_MODE) ||
switch_channel_test_flag(caller_channel, CF_PROXY_MEDIA)))) {
switch_core_session_reset(oglobals.session, SWITCH_FALSE, SWITCH_TRUE);
}
@ -3127,10 +3123,22 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_originate(switch_core_session_t *sess
switch_core_session_t *holding_session;
if ((holding_session = switch_core_session_locate(holding))) {
switch_channel_set_variable(switch_core_session_get_channel(holding_session), SWITCH_HANGUP_AFTER_BRIDGE_VARIABLE, "true");
switch_channel_t *holding_channel = switch_core_session_get_channel(holding_session);
switch_channel_set_variable(holding_channel, SWITCH_HANGUP_AFTER_BRIDGE_VARIABLE, "true");
if (caller_channel && switch_true(switch_channel_get_variable(caller_channel, "recording_follow_transfer"))) {
switch_core_media_bug_transfer_recordings(session, originate_status[i].peer_session);
}
if (switch_true(switch_channel_get_variable(holding_channel, "recording_follow_transfer"))) {
switch_core_media_bug_transfer_recordings(holding_session, originate_status[i].peer_session);
}
switch_core_session_rwunlock(holding_session);
}
switch_channel_set_flag(originate_status[i].peer_channel, CF_LAZY_ATTENDED_TRANSFER);
switch_ivr_uuid_bridge(holding, switch_core_session_get_uuid(originate_status[i].peer_session));
holding = NULL;
} else {

View File

@ -249,7 +249,7 @@ SWITCH_DECLARE(switch_status_t) switch_regex_match(const char *target, const cha
return switch_regex_match_partial(target, expression, &partial);
}
SWITCH_DECLARE(void) switch_regex_set_var_callback(const char *var, const char *val, void *user_data)
SWITCH_DECLARE_NONSTD(void) switch_regex_set_var_callback(const char *var, const char *val, void *user_data)
{
switch_core_session_t *session = (switch_core_session_t *) user_data;
switch_channel_t *channel = switch_core_session_get_channel(session);

View File

@ -190,6 +190,11 @@ SWITCH_DECLARE(void) switch_generate_sln_silence(int16_t *data, uint32_t samples
assert(divisor);
if (divisor == (uint32_t)-1) {
memset(data, 0, sizeof(*data));
return;
}
for (i = 0; i < samples; i++, sum_rnd = 0) {
for (x = 0; x < 6; x++) {
rnd2 = rnd2 * 31821U + 13849U;

View File

@ -2669,7 +2669,7 @@ SWITCH_DECLARE(switch_bool_t) switch_dow_cmp(const char *exp, int val)
/* Save the previous token and move to the next one */
range_start = prev;
} else if (cur == DOW_ERR) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Parse error for [%s] at position %td (%.6s)\n", exp, p - exp, p);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Parse error for [%s] at position %ld (%.6s)\n", exp, (long) (p - exp), p);
break;
} else {
/* Valid day found */

View File

@ -1125,12 +1125,12 @@ SWITCH_DECLARE(switch_xml_t) switch_xml_parse_fp(FILE * fp)
do {
len += (l = fread((s + len), 1, SWITCH_XML_BUFSIZE, fp));
if (l == SWITCH_XML_BUFSIZE) {
char *tmp = (char *) realloc(s, len + SWITCH_XML_BUFSIZE);
if (!tmp) {
free(s);
char *tmp = s;
s = (char *) realloc(s, len + SWITCH_XML_BUFSIZE);
if (!s) {
free(tmp);
return NULL;
}
s = tmp;
}
} while (s && l == SWITCH_XML_BUFSIZE);
@ -2279,10 +2279,10 @@ static char *switch_xml_toxml_r(switch_xml_t xml, char **s, switch_size_t *len,
*s = switch_xml_ampencode(txt + start, xml->off - start, s, len, max, 0);
while (*len + strlen(xml->name) + 5 + (strlen(XML_INDENT) * (*count)) + 1 > *max) { /* reallocate s */
char *tmp = (char *) realloc(*s, *max += SWITCH_XML_BUFSIZE);
if (!tmp)
return *s;
*s = tmp;
char *tmp = *s;
*s = (char *) realloc(*s, *max += SWITCH_XML_BUFSIZE);
if (!*s)
return tmp;
}
if (*len && *(*s + (*len) - 1) == '>') {
@ -2335,10 +2335,10 @@ static char *switch_xml_toxml_r(switch_xml_t xml, char **s, switch_size_t *len,
}
while (*len + strlen(xml->name) + 5 + (strlen(XML_INDENT) * (*count)) > *max) { /* reallocate s */
char *tmp = (char *) realloc(*s, *max += SWITCH_XML_BUFSIZE);
if (!tmp)
return *s;
*s = tmp;
char *tmp = *s;
*s = (char *) realloc(*s, *max += SWITCH_XML_BUFSIZE);
if (!*s)
return tmp;
}
if (xml->child || xml->txt) {