mirror of
https://github.com/signalwire/freeswitch.git
synced 2025-04-13 07:45:26 +00:00
Merge branch 'master' of ssh://git.freeswitch.org:222/freeswitch
This commit is contained in:
commit
feb21920db
@ -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>
|
||||
|
||||
|
@ -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>
|
||||
|
@ -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
6
debian/changelog
vendored
@ -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
|
||||
|
1
debian/freeswitch.install
vendored
1
debian/freeswitch.install
vendored
@ -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
2
debian/rules
vendored
@ -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
|
||||
|
@ -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>
|
||||
|
@ -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
11
libs/.gitignore
vendored
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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:
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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);\
|
||||
|
@ -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 *);
|
||||
|
@ -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 )
|
||||
|
@ -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");
|
||||
|
@ -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] = "";
|
||||
|
@ -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) {
|
||||
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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, '@'))) {
|
||||
|
@ -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)) {
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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 ;
|
||||
|
||||
|
@ -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)
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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];
|
||||
|
@ -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;
|
||||
|
@ -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,
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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 {
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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 */
|
||||
|
@ -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) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user