Compare commits

...

18 Commits

Author SHA1 Message Date
Abdelkader Boudih 059a95dfa6
Merge branch 'master' into remove_redis 2025-01-21 15:44:38 +01:00
junction1153b 3b58ebc5f3
[mod_sofia] Update Polycom UA to recognize new Poly phones
We observed that the new Poly phones (formerly known as Polycom) were not getting sent a SIP UPDATE in certain circumstances (example: retrieving a parked call, and therefore, Caller ID would not show the parked caller). I renamed Polycom to Poly which will catch all Poly AND Polycom UA's. I also added Acrobits, and Ringotel to extend such functionality to those UA's. There were also other minor compatibility issues with the new Poly phones which have been resolved with tweaking the UA recognition on the code.

Co-authored-by: Joseph <junction1153@gmail.com>
2025-01-21 00:57:25 +03:00
Aron Podrigal 5cb74797fe
[mod_pgsql] err is now set correctly (dbh:last_error())
New function, `void pgsql_handle_set_error_if_not_set(switch_pgsql_handle_t *handle, char **err)` has been added to mod_pgsql module. This function is now called at several points where an error occurred but *err was not yet set.
2025-01-17 18:51:45 +03:00
Aron Podrigal 96de8fd377
[mod_timerfd] Fixed - continue timer loop after receiving a SIGSTOP
When taking a snapshot of a machine which pauses the process, mod_timerfd exits and FreeSWITCH, causing all channels to wait indefinitely.

Check `errno == EINTR` and continue the timer loop.
2025-01-16 19:13:31 +03:00
Andrey Volk 55d8f3ff97
Merge pull request #2738 from signalwire/clearmode
[mod_clearmode] Remove from tree
2025-01-16 18:25:04 +03:00
Andrey Volk 6bad50d875 [mod_clearmode] Remove from tree 2025-01-16 13:53:57 +03:00
Andrey Volk 2970101bd8
Merge pull request #2737 from signalwire/oreka
[mod_oreka] Remove from tree
2025-01-16 13:43:50 +03:00
Andrey Volk b3cdc8a783 [mod_oreka] Remove from tree 2025-01-16 02:57:37 +03:00
Andrey Volk f1524d397c
Merge pull request #2736 from signalwire/yaml
[mod_yaml] Remove from tree
2025-01-16 02:44:50 +03:00
Andrey Volk 74c6433955 [mod_yaml] Remove from tree 2025-01-16 02:05:17 +03:00
Andrey Volk 4f17bc760c
Merge pull request #2735 from signalwire/theora
[mod_theora] Remove from tree
2025-01-16 02:01:49 +03:00
Andrey Volk e600ab66a7 [mod_theora] Remove from tree 2025-01-16 01:27:53 +03:00
Andrey Volk ca5b32701c
Merge pull request #2729 from ar45/mod_curl_fix_argv
[mod_curl] Fix off-by-one error in argument limit checks.
2025-01-15 23:43:23 +03:00
Aron Podrigal 083e6ae80f [mod_curl] Fix off-by-one error in argument limit checks.
refs: #2727
2025-01-15 14:03:07 -06:00
Andrey Volk 53abb53f2b
Merge pull request #2375 from ar45/mod_lua_query_rows
[mod_lua] Add Dbh:query_rows
2025-01-15 18:51:49 +03:00
Andrey Volk 7d2befa5fa [mod_lua] reswig 2025-01-15 16:30:59 +03:00
Andrey Volk d6a7bb9ee5 [mod_lua] Fix hack.diff 2025-01-15 16:30:59 +03:00
Aron Podrigal 4e2e8151b0 [mod_lua] Add Dbh:query_rows
The added method, query_rows, allows the retrieval of rows from a database without the need for a callback function, it fetches the rows and returns 3 arguments as show below.

```
lua
local success, rows, err = dbh:query_rows(sql)
```

This function performs better with large number of rows. Test results below 50k rows returned.

dbh:query(sql, callback) - 0.335949 seconds
dbh:query_rows(sql) - 0.253178 seconds
2025-01-15 16:30:59 +03:00
32 changed files with 177 additions and 1678 deletions

View File

@ -588,10 +588,6 @@ libs/srtp/libsrtp.la: libs/srtp libs/srtp/.update $(SRTP_SRC)
##
## helper targets
##
yaml-files:
@echo `mkdir $(DESTDIR)$(confdir)/yaml 2>/dev/null`
$(INSTALL) -m 644 $(switch_srcdir)/conf/default/yaml/*.yaml $(DESTDIR)$(confdir)/yaml
vm-sync:
test -d $(DESTDIR)$(confdir) || $(mkinstalldirs) $(DESTDIR)$(confdir)
test -d $(DESTDIR)$(confdir)/lang || $(mkinstalldirs) $(DESTDIR)$(confdir)/lang

View File

@ -29,7 +29,6 @@ applications/mod_httapi
#applications/mod_memcache
#applications/mod_mongo
#applications/mod_nibblebill
#applications/mod_oreka
#applications/mod_osp
#applications/mod_prefix
applications/mod_signalwire
@ -51,7 +50,6 @@ codecs/mod_amr
#codecs/mod_amrwb
codecs/mod_b64
#codecs/mod_bv
#codecs/mod_clearmode
#codecs/mod_codec2
#codecs/mod_com_g729
codecs/mod_g723_1
@ -60,7 +58,6 @@ codecs/mod_g729
codecs/mod_opus
#codecs/mod_silk
#codecs/mod_siren
#codecs/mod_theora
#databases/mod_mariadb
databases/mod_pgsql
dialplans/mod_dialplan_asterisk
@ -108,7 +105,6 @@ languages/mod_lua
#languages/mod_python
#languages/mod_python3
#languages/mod_v8
#languages/mod_yaml
loggers/mod_console
#loggers/mod_graylog2
loggers/mod_logfile

View File

@ -29,7 +29,6 @@ applications/mod_lcr
applications/mod_memcache
applications/mod_mongo
applications/mod_nibblebill
applications/mod_oreka
#applications/mod_osp
applications/mod_prefix
applications/mod_signalwire
@ -59,7 +58,6 @@ codecs/mod_ilbc
codecs/mod_opus
codecs/mod_silk
codecs/mod_siren
codecs/mod_theora
#databases/mod_mariadb
databases/mod_pgsql
dialplans/mod_dialplan_asterisk
@ -103,7 +101,6 @@ languages/mod_managed
languages/mod_perl
languages/mod_python3
#languages/mod_v8
languages/mod_yaml
loggers/mod_console
loggers/mod_graylog2
loggers/mod_logfile

View File

@ -6,8 +6,6 @@
<load module="mod_logfile"/>
<!-- <load module="mod_syslog"/> -->
<!--<load module="mod_yaml"/>-->
<!-- Multi-Faceted -->
<!-- mod_enum is a dialplan interface, an application interface and an api command interface -->
<load module="mod_enum"/>

View File

@ -6,8 +6,6 @@
<load module="mod_logfile"/>
<!-- <load module="mod_syslog"/> -->
<!--<load module="mod_yaml"/>-->
<!-- Multi-Faceted -->
<!-- mod_enum is a dialplan interface, an application interface and an api command interface -->
<load module="mod_enum"/>

View File

@ -1,13 +0,0 @@
<!--
To use this application simply install the open source Oreka recorder server (Orkaudio) and point
the sip-server-addr and sip-server-port to the oreka server
-->
<configuration name="oreka.conf" description="Oreka Recorder configuration">
<settings>
<!-- Oreka/Orkaudio recording server address -->
<!-- <param name="sip-server-addr" value="192.168.1.200"/> -->
<!-- Which port to send signaling to in the recording server -->
<!-- <param name="sip-server-port" value="6000"/> -->
</settings>
</configuration>

View File

@ -1,4 +0,0 @@
default:
${destination_number} =~ (9664):
set: foo=bar
playback: ${hold_music}

View File

@ -1,6 +0,0 @@
settings:
#look for foo.conf.yaml when foo.conf is looked for in the xml
bind_config: true

View File

@ -1330,9 +1330,6 @@ PKG_CHECK_MODULES([SQLITE], [sqlite3 >= 3.6.20])
PKG_CHECK_MODULES([CURL], [libcurl >= 7.19])
PKG_CHECK_MODULES([PCRE], [libpcre >= 7.8])
PKG_CHECK_MODULES([SPEEX], [speex >= 1.2rc1 speexdsp >= 1.2rc1])
PKG_CHECK_MODULES([YAML], [yaml-0.1 >= 0.1.4],[
AM_CONDITIONAL([HAVE_YAML],[true])],[
AC_MSG_RESULT([no]); AM_CONDITIONAL([HAVE_YAML],[false])])
PKG_CHECK_MODULES([LDNS], [libldns-fs >= 1.6.6],[
AM_CONDITIONAL([HAVE_LDNS],[true])],[
PKG_CHECK_MODULES([LDNS], [libldns >= 1.6.6],[
@ -2121,7 +2118,6 @@ AC_CONFIG_FILES([Makefile
src/mod/applications/mod_memcache/Makefile
src/mod/applications/mod_mongo/Makefile
src/mod/applications/mod_nibblebill/Makefile
src/mod/applications/mod_oreka/Makefile
src/mod/applications/mod_osp/Makefile
src/mod/applications/mod_prefix/Makefile
src/mod/applications/mod_random/Makefile
@ -2144,7 +2140,6 @@ AC_CONFIG_FILES([Makefile
src/mod/codecs/mod_amrwb/Makefile
src/mod/codecs/mod_b64/Makefile
src/mod/codecs/mod_bv/Makefile
src/mod/codecs/mod_clearmode/Makefile
src/mod/codecs/mod_codec2/Makefile
src/mod/codecs/mod_com_g729/Makefile
src/mod/codecs/mod_g723_1/Makefile
@ -2155,7 +2150,6 @@ AC_CONFIG_FILES([Makefile
src/mod/codecs/mod_silk/Makefile
src/mod/codecs/mod_siren/Makefile
src/mod/codecs/mod_skel_codec/Makefile
src/mod/codecs/mod_theora/Makefile
src/mod/databases/mod_mariadb/Makefile
src/mod/databases/mod_pgsql/Makefile
src/mod/dialplans/mod_dialplan_asterisk/Makefile
@ -2204,7 +2198,6 @@ AC_CONFIG_FILES([Makefile
src/mod/languages/mod_python/Makefile
src/mod/languages/mod_python3/Makefile
src/mod/languages/mod_v8/Makefile
src/mod/languages/mod_yaml/Makefile
src/mod/languages/mod_basic/Makefile
src/mod/loggers/mod_console/Makefile
src/mod/loggers/mod_graylog2/Makefile

7
debian/bootstrap.sh vendored
View File

@ -529,7 +529,6 @@ Recommends:
freeswitch-mod-http-cache (= \${binary:Version}),
freeswitch-mod-lcr (= \${binary:Version}),
freeswitch-mod-nibblebill (= \${binary:Version}),
freeswitch-mod-oreka (= \${binary:Version}),
freeswitch-mod-pgsql (= \${binary:Version}),
freeswitch-mod-redis (= \${binary:Version}),
freeswitch-mod-sms (= \${binary:Version}),
@ -610,7 +609,6 @@ Depends: \${misc:Depends}, freeswitch (= \${binary:Version}),
freeswitch-mod-lcr (= \${binary:Version}),
freeswitch-mod-memcache (= \${binary:Version}),
freeswitch-mod-nibblebill (= \${binary:Version}),
freeswitch-mod-oreka (= \${binary:Version}),
freeswitch-mod-mariadb (= \${binary:Version}),
freeswitch-mod-pgsql (= \${binary:Version}),
freeswitch-mod-png (= \${binary:Version}),
@ -655,7 +653,6 @@ Depends: \${misc:Depends}, freeswitch (= \${binary:Version}),
freeswitch-mod-lua (= \${binary:Version}),
freeswitch-mod-perl (= \${binary:Version}),
freeswitch-mod-python3 (= \${binary:Version}),
freeswitch-mod-yaml (= \${binary:Version}),
freeswitch-mod-console (= \${binary:Version}),
freeswitch-mod-logfile (= \${binary:Version}),
freeswitch-mod-syslog (= \${binary:Version}),
@ -688,7 +685,6 @@ Depends: \${misc:Depends}, freeswitch (= \${binary:Version}),
freeswitch-mod-opus (= \${binary:Version}),
freeswitch-mod-silk (= \${binary:Version}),
freeswitch-mod-spandsp (= \${binary:Version}),
freeswitch-mod-theora (= \${binary:Version}),
Suggests:
freeswitch-mod-ilbc (= \${binary:Version}),
freeswitch-mod-siren (= \${binary:Version})
@ -711,7 +707,6 @@ Depends: \${misc:Depends}, freeswitch (= \${binary:Version}),
freeswitch-mod-opus-dbg (= \${binary:Version}),
freeswitch-mod-silk-dbg (= \${binary:Version}),
freeswitch-mod-spandsp-dbg (= \${binary:Version}),
freeswitch-mod-theora-dbg (= \${binary:Version}),
Suggests:
freeswitch-mod-ilbc-dbg (= \${binary:Version}),
freeswitch-mod-siren-dbg (= \${binary:Version})
@ -832,7 +827,6 @@ Depends: \${misc:Depends}, freeswitch (= \${binary:Version}),
freeswitch-mod-lcr-dbg (= \${binary:Version}),
freeswitch-mod-memcache-dbg (= \${binary:Version}),
freeswitch-mod-nibblebill-dbg (= \${binary:Version}),
freeswitch-mod-oreka-dbg (= \${binary:Version}),
freeswitch-mod-mariadb-dbg (= \${binary:Version}),
freeswitch-mod-pgsql-dbg (= \${binary:Version}),
freeswitch-mod-png-dbg (= \${binary:Version}),
@ -875,7 +869,6 @@ Depends: \${misc:Depends}, freeswitch (= \${binary:Version}),
freeswitch-mod-lua-dbg (= \${binary:Version}),
freeswitch-mod-perl-dbg (= \${binary:Version}),
freeswitch-mod-python3-dbg (= \${binary:Version}),
freeswitch-mod-yaml-dbg (= \${binary:Version}),
freeswitch-mod-console-dbg (= \${binary:Version}),
freeswitch-mod-logfile-dbg (= \${binary:Version}),
freeswitch-mod-syslog-dbg (= \${binary:Version}),

View File

@ -149,11 +149,6 @@ Description: Nibblebill
This module allows for real-time accounting of a cash balance and
using that information for call routing.
Module: applications/mod_oreka
Description: Media recording with Oreka
This module provides media recording with the Oreka cross-platfor
audio stream recording and retrieval system.
Module: applications/mod_osp
Description: Open Settlement Protocol
This module adds support for the Open Settlement Protocol (OSP).
@ -303,10 +298,6 @@ Module: codecs/mod_skel_codec
Description: Adds mod_skel_codec
Adds mod_skel_codec.
Module: codecs/mod_theora
Description: mod_theora
Adds mod_theora.
Module: codecs/mod_yuv
Description: Adds mod_yuv
Adds mod_yuv.
@ -557,11 +548,6 @@ Description: mod_v8
Adds mod_v8.
Build-Depends: git, libv8-6.1-dev
Module: languages/mod_yaml
Description: mod_yaml
Adds mod_yaml.
Build-Depends: libyaml-dev, libglib2.0-dev
## mod/loggers
Module: loggers/mod_console

View File

@ -674,14 +674,6 @@ see http://www.polycom.com/usa/en/company/about_us/technology/siren_g7221/siren_
and http://www.polycom.com/usa/en/company/about_us/technology/siren14_g7221c/siren14_g7221c.html
At the time of this packaging, Polycom does not charge for licensing.
%package codec-theora
Summary: Theora Video Codec support for FreeSWITCH open source telephony platform
Group: System/Libraries
Requires: %{name} = %{version}-%{release}
%description codec-theora
Theora Video Codec support for FreeSWITCH open source telephony platform.
######################################################################################################################
# FreeSWITCH Database Modules
######################################################################################################################
@ -1233,7 +1225,7 @@ ASR_TTS_MODULES="asr_tts/mod_flite asr_tts/mod_pocketsphinx asr_tts/mod_tts_comm
######################################################################################################################
CODECS_MODULES="codecs/mod_amr codecs/mod_amrwb codecs/mod_bv codecs/mod_codec2 codecs/mod_g723_1 \
codecs/mod_g729 codecs/mod_ilbc codecs/mod_opus codecs/mod_silk \
codecs/mod_siren codecs/mod_theora"
codecs/mod_siren"
#
######################################################################################################################
@ -1700,7 +1692,6 @@ fi
%config(noreplace) %attr(0640, freeswitch, daemon) %{sysconfdir}/autoload_configs/msrp.conf.xml
%config(noreplace) %attr(0640, freeswitch, daemon) %{sysconfdir}/autoload_configs/nibblebill.conf.xml
%config(noreplace) %attr(0640, freeswitch, daemon) %{sysconfdir}/autoload_configs/opal.conf.xml
%config(noreplace) %attr(0640, freeswitch, daemon) %{sysconfdir}/autoload_configs/oreka.conf.xml
%config(noreplace) %attr(0640, freeswitch, daemon) %{sysconfdir}/autoload_configs/osp.conf.xml
%config(noreplace) %attr(0640, freeswitch, daemon) %{sysconfdir}/autoload_configs/pocketsphinx.conf.xml
%config(noreplace) %attr(0640, freeswitch, daemon) %{sysconfdir}/autoload_configs/post_load_modules.conf.xml
@ -1935,9 +1926,6 @@ fi
%files codec-siren
%{MODINSTDIR}/mod_siren.so*
%files codec-theora
%{MODINSTDIR}/mod_theora.so*
######################################################################################################################
#
# FreeSWITCH Database Modules

View File

@ -898,7 +898,7 @@ SWITCH_STANDARD_APP(curl_app_function)
if ((argc = switch_separate_string(mydata, ' ', argv, (sizeof(argv) / sizeof(argv[0]))))) {
if (argc == 0) {
switch_goto_status(SWITCH_STATUS_SUCCESS, usage);
} else if (argc >= MOD_CURL_MAX_ARGS) {
} else if (argc > MOD_CURL_MAX_ARGS) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Max args exceeded: %d\n", MOD_CURL_MAX_ARGS);
switch_goto_status(SWITCH_STATUS_FALSE, done);
}
@ -1021,7 +1021,7 @@ SWITCH_STANDARD_API(curl_function)
if ((argc = switch_separate_string(mydata, ' ', argv, (sizeof(argv) / sizeof(argv[0]))))) {
if (argc < 1) {
switch_goto_status(SWITCH_STATUS_SUCCESS, usage);
} else if (argc >= MOD_CURL_MAX_ARGS) {
} else if (argc > MOD_CURL_MAX_ARGS) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Max args exceeded: %d\n", MOD_CURL_MAX_ARGS);
switch_goto_status(SWITCH_STATUS_FALSE, done);
}

View File

@ -1,8 +0,0 @@
include $(top_srcdir)/build/modmake.rulesam
MODNAME=mod_oreka
mod_LTLIBRARIES = mod_oreka.la
mod_oreka_la_SOURCES = mod_oreka.c
mod_oreka_la_CFLAGS = $(AM_CFLAGS)
mod_oreka_la_LIBADD = $(switch_builddir)/libfreeswitch.la
mod_oreka_la_LDFLAGS = -avoid-version -module -no-undefined -shared

View File

@ -1,786 +0,0 @@
/*
* FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
* Copyright (C) 2005-2011, Anthony Minessale II <anthm@freeswitch.org>
*
* Version: MPL 1.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is FreeSWITCH Modular Media Switching Software Library / Oreka Recording Module
*
* The Initial Developer of the Original Code is
* Moises Silva <moises.silva@gmail.com>
* Portions created by the Initial Developer are Copyright (C)
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Moises Silva <moises.silva@gmail.com>
*
* mod_oreka -- Module for Media Recording with Oreka
*
*/
#include <switch.h>
#include <g711.h>
static const char SIP_OREKA_HEADER_PREFIX[] = "oreka_sip_h_";
#define OREKA_PRIVATE "_oreka_"
#define OREKA_BUG_NAME_READ "oreka_read"
#define OREKA_BUG_NAME_WRITE "oreka_write"
#define SIP_OREKA_HEADER_PREFIX_LEN (sizeof(SIP_OREKA_HEADER_PREFIX)-1)
SWITCH_MODULE_LOAD_FUNCTION(mod_oreka_load);
SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_oreka_shutdown);
SWITCH_MODULE_DEFINITION(mod_oreka, mod_oreka_load, mod_oreka_shutdown, NULL);
typedef struct oreka_session_s {
switch_core_session_t *session;
switch_port_t read_rtp_port;
switch_port_t write_rtp_port;
switch_rtp_t *read_rtp_stream;
switch_rtp_t *write_rtp_stream;
switch_codec_implementation_t read_impl;
switch_codec_implementation_t write_impl;
uint32_t read_cnt;
uint32_t write_cnt;
switch_media_bug_t *read_bug;
switch_event_t *invite_extra_headers;
switch_event_t *bye_extra_headers;
int usecnt;
switch_audio_resampler_t *read_resampler;
switch_audio_resampler_t *write_resampler;
int mux_streams;
} oreka_session_t;
static struct {
char local_ipv4_str[256];
char sip_server_addr_str[256];
char sip_server_ipv4_str[256];
int sip_server_port;
switch_sockaddr_t *sip_server_addr;
switch_socket_t *sip_socket;
pid_t our_pid;
int mux_streams;
} globals;
typedef enum {
FS_OREKA_START,
FS_OREKA_STOP
} oreka_recording_status_t;
typedef enum {
FS_OREKA_READ,
FS_OREKA_WRITE
} oreka_stream_type_t;
static int oreka_write_udp(oreka_session_t *oreka, switch_stream_handle_t *udp)
{
switch_size_t udplen = udp->data_len;
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(oreka->session), SWITCH_LOG_DEBUG, "Oreka SIP Packet:\n%s", (const char *)udp->data);
switch_socket_sendto(globals.sip_socket, globals.sip_server_addr, 0, (void *)udp->data, &udplen);
if (udplen != udp->data_len) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(oreka->session), SWITCH_LOG_ERROR, "Failed to write SIP Packet of len %zd (wrote=%zd)",
udp->data_len, udplen);
}
return 0;
}
static int oreka_tear_down_rtp(oreka_session_t *oreka, oreka_stream_type_t type)
{
if (type == FS_OREKA_READ && oreka->read_rtp_stream) {
switch_rtp_release_port(globals.local_ipv4_str, oreka->read_rtp_port);
switch_rtp_destroy(&oreka->read_rtp_stream);
oreka->read_rtp_port = 0;
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(oreka->session), SWITCH_LOG_DEBUG, "Destroyed read rtp\n");
} else if (oreka->write_rtp_stream) {
switch_rtp_release_port(globals.local_ipv4_str, oreka->write_rtp_port);
switch_rtp_destroy(&oreka->write_rtp_stream);
oreka->write_rtp_port = 0;
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(oreka->session), SWITCH_LOG_DEBUG, "Destroyed write rtp\n");
}
return 0;
}
static int oreka_setup_rtp(oreka_session_t *oreka, oreka_stream_type_t type)
{
switch_port_t rtp_port = 0;
switch_rtp_flag_t flags[SWITCH_RTP_FLAG_INVALID] = {0};
switch_rtp_t *rtp_stream = NULL;
switch_codec_implementation_t *codec_impl = NULL;
switch_status_t status = SWITCH_STATUS_SUCCESS;
int res = 0;
const char *err = "unknown error";
const char *type_str = type == FS_OREKA_READ ? "read" : "write";
if (type == FS_OREKA_READ) {
status = switch_core_session_get_read_impl(oreka->session, &oreka->read_impl);
codec_impl = &oreka->read_impl;
} else {
status = switch_core_session_get_write_impl(oreka->session, &oreka->write_impl);
codec_impl = &oreka->write_impl;
}
if (status != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "No %s codec implementation available!\n", type_str);
res = -1;
goto done;
}
if (!(rtp_port = switch_rtp_request_port(globals.local_ipv4_str))) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to allocate %s RTP port for IP %s\n", type_str, globals.local_ipv4_str);
res = -1;
goto done;
}
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Allocated %s port %d for local IP %s, destination IP %s\n", type_str,
rtp_port, globals.local_ipv4_str, globals.sip_server_ipv4_str);
rtp_stream = switch_rtp_new(globals.local_ipv4_str, rtp_port,
globals.sip_server_ipv4_str, rtp_port,
0, /* PCMU IANA*/
codec_impl->samples_per_packet,
codec_impl->microseconds_per_packet,
flags, NULL, &err, switch_core_session_get_pool(oreka->session), 0, 0);
if (!rtp_stream) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to create %s RTP stream at %s:%d: %s\n",
type_str, globals.local_ipv4_str, rtp_port, err);
res = -1;
goto done;
}
switch_rtp_intentional_bugs(rtp_stream, RTP_BUG_SEND_LINEAR_TIMESTAMPS);
done:
if (res == -1) {
if (rtp_port) {
switch_rtp_release_port(globals.local_ipv4_str, rtp_port);
}
if (rtp_stream) {
switch_rtp_destroy(&rtp_stream);
}
} else {
if (type == FS_OREKA_READ) {
oreka->read_rtp_stream = rtp_stream;
oreka->read_rtp_port = rtp_port;
} else {
oreka->write_rtp_stream = rtp_stream;
oreka->write_rtp_port = rtp_port;
}
}
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Successfully created %s RTP stream at %s:%d at %dms@%dHz\n",
type_str, globals.local_ipv4_str, rtp_port, codec_impl->microseconds_per_packet/1000, codec_impl->samples_per_second);
return res;
}
static void save_extra_headers(switch_event_t *extra_headers, switch_channel_t *channel)
{
switch_event_header_t *ei = NULL;
for (ei = switch_channel_variable_first(channel);
ei;
ei = ei->next) {
const char *name = ei->name;
char *value = ei->value;
if (!strncasecmp(name, SIP_OREKA_HEADER_PREFIX, SIP_OREKA_HEADER_PREFIX_LEN)) {
switch_event_add_header_string(extra_headers, SWITCH_STACK_BOTTOM, name, value);
}
}
switch_channel_variable_last(channel);
/* Remove the custom header variables that were saved */
for (ei = extra_headers->headers;
ei;
ei = ei->next) {
char *varname = ei->name;
switch_channel_set_variable(channel, varname, NULL);
}
}
static switch_event_t *get_extra_headers(oreka_session_t *oreka, oreka_recording_status_t status)
{
switch_event_t *extra_headers = NULL;
switch_channel_t *channel = NULL;
switch_core_session_t *session = oreka->session;
channel = switch_core_session_get_channel(session);
if (status == FS_OREKA_START) {
if (!oreka->invite_extra_headers) {
switch_event_create_subclass(&oreka->invite_extra_headers, SWITCH_EVENT_CLONE, NULL);
switch_assert(oreka->invite_extra_headers);
save_extra_headers(oreka->invite_extra_headers, channel);
}
extra_headers = oreka->invite_extra_headers;
} else if (status == FS_OREKA_STOP) {
if (!oreka->bye_extra_headers) {
switch_event_create_subclass(&oreka->bye_extra_headers, SWITCH_EVENT_CLONE, NULL);
switch_assert(oreka->bye_extra_headers);
save_extra_headers(oreka->bye_extra_headers, channel);
}
extra_headers = oreka->bye_extra_headers;
}
return extra_headers;
}
static void oreka_destroy(oreka_session_t *oreka)
{
oreka->usecnt--;
if (!oreka->usecnt) {
if (oreka->invite_extra_headers) {
switch_event_destroy(&oreka->invite_extra_headers);
}
if (oreka->bye_extra_headers) {
switch_event_destroy(&oreka->bye_extra_headers);
}
/* Actual memory for the oreka session was taken from the switch core session pool, the core will take care of it */
}
}
static int oreka_send_sip_message(oreka_session_t *oreka, oreka_recording_status_t status, oreka_stream_type_t type)
{
switch_stream_handle_t sip_header = { 0 };
switch_stream_handle_t sdp = { 0 };
switch_stream_handle_t udp_packet = { 0 };
switch_caller_profile_t *caller_profile = NULL;
switch_channel_t *channel = NULL;
switch_event_t *extra_headers = NULL;
switch_event_header_t *ei = NULL;
switch_core_session_t *session = oreka->session;
const char *method = status == FS_OREKA_START ? "INVITE" : "BYE";
const char *session_uuid = switch_core_session_get_uuid(oreka->session);
const char *caller_id_number = NULL;
const char *caller_id_name = NULL;
const char *callee_id_number = NULL;
const char *callee_id_name = NULL;
int rc = 0;
channel = switch_core_session_get_channel(session);
SWITCH_STANDARD_STREAM(sip_header);
SWITCH_STANDARD_STREAM(sdp);
SWITCH_STANDARD_STREAM(udp_packet);
extra_headers = get_extra_headers(oreka, status);
caller_profile = switch_channel_get_caller_profile(channel);
/* Get caller meta data */
caller_id_number = switch_caller_get_field_by_name(caller_profile, "caller_id_number");
caller_id_name = switch_caller_get_field_by_name(caller_profile, "caller_id_name");
if (zstr(caller_id_name)) {
caller_id_name = caller_id_number;
}
callee_id_number = switch_caller_get_field_by_name(caller_profile, "callee_id_number");
if (zstr(callee_id_number)) {
callee_id_number = switch_caller_get_field_by_name(caller_profile, "destination_number");
}
callee_id_name = switch_caller_get_field_by_name(caller_profile, "callee_id_name");
if (zstr(callee_id_name)) {
callee_id_name = callee_id_number;
}
/* Setup the RTP */
if (status == FS_OREKA_START) {
if (oreka_setup_rtp(oreka, type)) {
rc = -1;
goto done;
}
}
if (status == FS_OREKA_STOP) {
oreka_tear_down_rtp(oreka, type);
}
/* Fill in the SDP first if this is the beginning */
if (status == FS_OREKA_START) {
sdp.write_function(&sdp, "v=0\r\n");
sdp.write_function(&sdp, "o=freeswitch %s 1 IN IP4 %s\r\n", session_uuid, globals.local_ipv4_str);
sdp.write_function(&sdp, "c=IN IP4 %s\r\n", globals.sip_server_ipv4_str);
sdp.write_function(&sdp, "s=Phone Recording (%s)\r\n", type == FS_OREKA_READ ? "RX" : "TX");
sdp.write_function(&sdp, "i=FreeSWITCH Oreka Recorder (pid=%d)\r\n", globals.our_pid);
sdp.write_function(&sdp, "m=audio %d RTP/AVP 0\r\n", type == FS_OREKA_READ ? oreka->read_rtp_port : oreka->write_rtp_port);
sdp.write_function(&sdp, "a=rtpmap:0 PCMU/%d\r\n", type == FS_OREKA_READ
? oreka->read_impl.samples_per_second : oreka->write_impl.samples_per_second);
}
/* Request line */
sip_header.write_function(&sip_header, "%s sip:%s@%s:5060 SIP/2.0\r\n", method, callee_id_name, globals.local_ipv4_str);
/* Via */
sip_header.write_function(&sip_header, "Via: SIP/2.0/UDP %s:5061;branch=z9hG4bK-%s\r\n", globals.local_ipv4_str, session_uuid);
/* From */
sip_header.write_function(&sip_header, "From: <sip:%s@%s:5061;tag=1>\r\n", caller_id_number, globals.local_ipv4_str);
/* To */
sip_header.write_function(&sip_header, "To: <sip:%s@%s:5060>\r\n", callee_id_number, globals.local_ipv4_str);
/* Call-ID */
sip_header.write_function(&sip_header, "Call-ID: %s\r\n", session_uuid);
/* CSeq */
sip_header.write_function(&sip_header, "CSeq: 1 %s\r\n", method);
/* Contact */
sip_header.write_function(&sip_header, "Contact: sip:freeswitch@%s:5061\r\n", globals.local_ipv4_str);
/* Max-Forwards */
sip_header.write_function(&sip_header, "Max-Forwards: 70\r\n", method);
/* Subject */
sip_header.write_function(&sip_header, "Subject: %s %s recording of %s\r\n",
status == FS_OREKA_START ? "BEGIN": "END",
type == FS_OREKA_READ ? "RX" : "TX", caller_id_name);
/* Add any custom extra headers */
for (ei = extra_headers->headers;
ei;
ei = ei->next) {
const char *name = ei->name;
char *value = ei->value;
if (!strncasecmp(name, SIP_OREKA_HEADER_PREFIX, SIP_OREKA_HEADER_PREFIX_LEN)) {
const char *hname = name + SIP_OREKA_HEADER_PREFIX_LEN;
sip_header.write_function(&sip_header, "%s: %s\r\n", hname, value);
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Adding custom oreka SIP header %s: %s\n", hname, value);
}
}
if (status == FS_OREKA_START) {
/* Content-Type */
sip_header.write_function(&sip_header, "Content-Type: application/sdp\r\n");
}
/* Content-Length */
sip_header.write_function(&sip_header, "Content-Length: %d\r\n", sdp.data_len);
udp_packet.write_function(&udp_packet, "%s\r\n%s\n", sip_header.data, sdp.data);
oreka_write_udp(oreka, &udp_packet);
done:
if (sip_header.data) {
free(sip_header.data);
}
if (sdp.data) {
free(sdp.data);
}
if (udp_packet.data) {
free(udp_packet.data);
}
if (status == FS_OREKA_STOP) {
oreka_destroy(oreka);
}
return rc;
}
static switch_bool_t oreka_audio_callback(switch_media_bug_t *bug, void *user_data, switch_abc_type_t type)
{
oreka_session_t *oreka = user_data;
switch_core_session_t *session = oreka->session;
switch_frame_t pcmu_frame = { 0 };
switch_frame_t *linear_frame, raw_frame = { 0 };
uint8_t pcmu_data[SWITCH_RECOMMENDED_BUFFER_SIZE];
uint8_t raw_data[SWITCH_RECOMMENDED_BUFFER_SIZE] = { 0 };
uint8_t resample_data[SWITCH_RECOMMENDED_BUFFER_SIZE];
uint32_t linear_len = 0;
uint32_t i = 0;
int16_t *linear_samples = NULL;
if (type == SWITCH_ABC_TYPE_READ_REPLACE || type == SWITCH_ABC_TYPE_WRITE_REPLACE || type == SWITCH_ABC_TYPE_READ_PING) {
int16_t *data;
if (type == SWITCH_ABC_TYPE_READ_REPLACE || type == SWITCH_ABC_TYPE_READ_PING) {
if (type == SWITCH_ABC_TYPE_READ_REPLACE) {
linear_frame = switch_core_media_bug_get_read_replace_frame(bug);
} else {
switch_status_t status;
raw_frame.data = raw_data;
raw_frame.buflen = SWITCH_RECOMMENDED_BUFFER_SIZE;
linear_frame = &raw_frame;
status = switch_core_media_bug_read(bug, &raw_frame, SWITCH_FALSE);
if (status != SWITCH_STATUS_SUCCESS && status != SWITCH_STATUS_BREAK) {
return SWITCH_TRUE;
}
}
if (oreka->read_resampler) {
data = (int16_t *) linear_frame->data;
switch_resample_process(oreka->read_resampler, data, (int) linear_frame->datalen / 2);
linear_len = oreka->read_resampler->to_len * 2;
memcpy(resample_data, oreka->read_resampler->to, linear_len);
linear_samples = (int16_t *)resample_data;
} else {
linear_samples = linear_frame->data;
linear_len = linear_frame->datalen;
}
}
if (type == SWITCH_ABC_TYPE_WRITE_REPLACE) {
linear_frame = switch_core_media_bug_get_write_replace_frame(bug);
if (oreka->write_resampler) {
data = (int16_t *) linear_frame->data;
switch_resample_process(oreka->write_resampler, data, (int) linear_frame->datalen / 2);
linear_len = oreka->write_resampler->to_len * 2;
memcpy(resample_data, oreka->write_resampler->to, linear_len);
linear_samples = (int16_t *)resample_data;
} else {
linear_samples = linear_frame->data;
linear_len = linear_frame->datalen;
}
}
/* convert the L16 frame into PCMU */
memset(&pcmu_frame, 0, sizeof(pcmu_frame));
for (i = 0; i < linear_len / sizeof(int16_t); i++) {
pcmu_data[i] = linear_to_ulaw(linear_samples[i]);
}
pcmu_frame.source = __SWITCH_FUNC__;
pcmu_frame.data = pcmu_data;
pcmu_frame.datalen = i;
pcmu_frame.payload = 0;
}
switch (type) {
case SWITCH_ABC_TYPE_INIT:
{
switch_codec_implementation_t read_impl;
switch_core_session_get_read_impl(session, &read_impl);
if (read_impl.actual_samples_per_second != 8000) {
switch_resample_create(&oreka->read_resampler,
read_impl.actual_samples_per_second,
8000,
320, SWITCH_RESAMPLE_QUALITY, 1);
switch_resample_create(&oreka->write_resampler,
read_impl.actual_samples_per_second,
8000,
320, SWITCH_RESAMPLE_QUALITY, 1);
}
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "Starting Oreka recording for audio stream\n");
oreka_send_sip_message(oreka, FS_OREKA_START, FS_OREKA_READ);
if (!oreka->mux_streams) {
oreka_send_sip_message(oreka, FS_OREKA_START, FS_OREKA_WRITE);
}
}
break;
case SWITCH_ABC_TYPE_CLOSE:
{
if (oreka->mux_streams) {
int16_t *data;
raw_frame.data = raw_data;
raw_frame.buflen = SWITCH_RECOMMENDED_BUFFER_SIZE;
while (switch_core_media_bug_read(bug, &raw_frame, SWITCH_TRUE) == SWITCH_STATUS_SUCCESS) {
linear_frame = &raw_frame;
if (oreka->read_resampler) {
data = (int16_t *) linear_frame->data;
switch_resample_process(oreka->read_resampler, data, (int) linear_frame->datalen / 2);
linear_len = oreka->read_resampler->to_len * 2;
memcpy(resample_data, oreka->read_resampler->to, linear_len);
linear_samples = (int16_t *)resample_data;
} else {
linear_samples = linear_frame->data;
linear_len = linear_frame->datalen;
}
memset(&pcmu_frame, 0, sizeof(pcmu_frame));
for (i = 0; i < linear_len / sizeof(int16_t); i++) {
pcmu_data[i] = linear_to_ulaw(linear_samples[i]);
}
pcmu_frame.source = __SWITCH_FUNC__;
pcmu_frame.data = pcmu_data;
pcmu_frame.datalen = i;
pcmu_frame.payload = 0;
switch_rtp_write_frame(oreka->read_rtp_stream, &pcmu_frame);
}
}
if (oreka->read_resampler) {
switch_resample_destroy(&oreka->read_resampler);
}
if (oreka->write_resampler) {
switch_resample_destroy(&oreka->write_resampler);
}
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "Stopping Oreka recording for audio stream\n");
oreka_send_sip_message(oreka, FS_OREKA_STOP, FS_OREKA_READ);
if (!oreka->mux_streams) {
oreka_send_sip_message(oreka, FS_OREKA_STOP, FS_OREKA_WRITE);
}
}
break;
case SWITCH_ABC_TYPE_READ_REPLACE:
case SWITCH_ABC_TYPE_READ_PING:
{
if (pcmu_frame.datalen) {
if (switch_rtp_write_frame(oreka->read_rtp_stream, &pcmu_frame) > 0) {
oreka->read_cnt++;
if (oreka->read_cnt < 10) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Oreka wrote %u bytes! (read)\n", pcmu_frame.datalen);
}
} else {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Failed to write %u bytes! (read)\n", pcmu_frame.datalen);
}
}
}
break;
case SWITCH_ABC_TYPE_WRITE_REPLACE:
{
if (pcmu_frame.datalen) {
if (switch_rtp_write_frame(oreka->write_rtp_stream, &pcmu_frame) > 0) {
oreka->write_cnt++;
if (oreka->write_cnt < 10) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Oreka wrote %u bytes! (write)\n", pcmu_frame.datalen);
}
} else {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Failed to write %u bytes! (write)\n", pcmu_frame.datalen);
}
}
}
break;
default:
break;
}
return SWITCH_TRUE;
}
SWITCH_STANDARD_APP(oreka_start_function)
{
switch_status_t status;
switch_channel_t *channel = switch_core_session_get_channel(session);
oreka_session_t *oreka = NULL;
switch_media_bug_t *bug = NULL;
char *argv[6];
int flags = 0;
char *lbuf = NULL;
const char *var;
if ((oreka = (oreka_session_t *) switch_channel_get_private(channel, OREKA_PRIVATE))) {
if (!zstr(data) && !strcasecmp(data, "stop")) {
switch_channel_set_private(channel, OREKA_PRIVATE, NULL);
if (oreka->read_bug) {
switch_core_media_bug_remove(session, &oreka->read_bug);
oreka->read_bug = NULL;
}
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Stopped oreka recorder\n");
} else {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Cannot run oreka recording 2 times on the same session!\n");
}
return;
}
oreka = switch_core_session_alloc(session, sizeof(*oreka));
switch_assert(oreka);
memset(oreka, 0, sizeof(*oreka));
oreka->mux_streams = globals.mux_streams;
if ((var = switch_channel_get_variable(channel, "oreka_mux_streams"))) {
oreka->mux_streams = switch_true(var);
}
if (data && (lbuf = switch_core_session_strdup(session, data))
&& switch_separate_string(lbuf, ' ', argv, (sizeof(argv) / sizeof(argv[0])))) {
#if 0
if (!strncasecmp(argv[x], "server", sizeof("server"))) {
/* parse server=192.168.1.144 string */
}
#endif
}
oreka->session = session;
if (oreka->mux_streams) {
flags = SMBF_READ_STREAM | SMBF_WRITE_STREAM | SMBF_READ_PING | SMBF_ANSWER_REQ;
} else {
flags = SMBF_READ_REPLACE | SMBF_WRITE_REPLACE | SMBF_ANSWER_REQ;
}
status = switch_core_media_bug_add(session, OREKA_BUG_NAME_READ, NULL, oreka_audio_callback, oreka, 0, flags, &bug);
if (status != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Failed to attach oreka to media stream!\n");
return;
}
oreka->read_bug = bug;
oreka->usecnt++;
bug = NULL;
oreka->usecnt++;
switch_channel_set_private(channel, OREKA_PRIVATE, oreka);
}
#define OREKA_XML_CONFIG "oreka.conf"
static int load_config(void)
{
switch_xml_t cfg, xml, settings, param;
if (!(xml = switch_xml_open_cfg(OREKA_XML_CONFIG, &cfg, NULL))) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to open XML configuration '%s'\n", OREKA_XML_CONFIG);
return -1;
}
if ((settings = switch_xml_child(cfg, "settings"))) {
for (param = switch_xml_child(settings, "param"); param; param = param->next) {
char *var = (char *) switch_xml_attr_soft(param, "name");
char *val = (char *) switch_xml_attr_soft(param, "value");
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Found parameter %s=%s\n", var, val);
if (!strcasecmp(var, "sip-server-addr")) {
snprintf(globals.sip_server_addr_str, sizeof(globals.sip_server_addr_str), "%s", val);
} else if (!strcasecmp(var, "sip-server-port")) {
globals.sip_server_port = atoi(val);
} else if (!strcasecmp(var, "mux-all-streams")) {
globals.mux_streams = 1;
}
}
}
switch_xml_free(xml);
return 0;
}
SWITCH_MODULE_LOAD_FUNCTION(mod_oreka_load)
{
switch_application_interface_t *app_interface = NULL;
int mask = 0;
#if 0
switch_status_t status = SWITCH_STATUS_FALSE;
int x = 0;
switch_size_t len = 0;
switch_size_t ilen = 0;
char dummy_output[] = "Parangaricutirimicuaro";
char dummy_input[sizeof(dummy_output)] = "";
switch_sockaddr_t *from_addr = NULL;
#endif
memset(&globals, 0, sizeof(globals));
if (load_config()) {
return SWITCH_STATUS_UNLOAD;
}
if (zstr(globals.sip_server_addr_str)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "No sip server address specified!\n");
return SWITCH_STATUS_UNLOAD;
}
if (!globals.sip_server_port) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "No sip server port specified!\n");
return SWITCH_STATUS_UNLOAD;
}
//switch_sockaddr_info_get(&globals.sip_server_addr, "sigchld.sangoma.local", SWITCH_UNSPEC, 5080, 0, pool);
switch_sockaddr_info_get(&globals.sip_server_addr, globals.sip_server_addr_str, SWITCH_UNSPEC, globals.sip_server_port, 0, pool);
if (!globals.sip_server_addr) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid sip server address specified: %s!\n", globals.sip_server_addr_str);
return SWITCH_STATUS_UNLOAD;
}
if (switch_socket_create(&globals.sip_socket, switch_sockaddr_get_family(globals.sip_server_addr), SOCK_DGRAM, 0, pool) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to create socket!\n");
return SWITCH_STATUS_UNLOAD;
}
switch_find_local_ip(globals.local_ipv4_str, sizeof(globals.local_ipv4_str), &mask, AF_INET);
switch_get_addr(globals.sip_server_ipv4_str, sizeof(globals.sip_server_ipv4_str), globals.sip_server_addr);
globals.our_pid = getpid();
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO,
"Loading mod_oreka, sip_server_addr=%s, sip_server_ipv4_str=%s, sip_server_port=%d, local_ipv4_str=%s\n",
globals.sip_server_addr_str, globals.sip_server_ipv4_str, globals.sip_server_port, globals.local_ipv4_str);
#if 0
if (switch_socket_bind(globals.sip_socket, globals.sip_addr) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to bind to SIP address: %s!\n", strerror(errno));
return SWITCH_STATUS_UNLOAD;
}
#endif
#if 0
len = sizeof(dummy_output);
#ifndef WIN32
switch_socket_opt_set(globals.sip_socket, SWITCH_SO_NONBLOCK, TRUE);
status = switch_socket_sendto(globals.sip_socket, globals.sip_addr, 0, (void *)dummy_output, &len);
if (status != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to send UDP message! (status=%d)\n", status);
}
status = switch_sockaddr_create(&from_addr, pool);
if (status != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to creat socket address\n");
}
while (!ilen) {
ilen = sizeof(dummy_input);
status = switch_socket_recvfrom(from_addr, globals.sip_socket, 0, (void *)dummy_input, &ilen);
if (status != SWITCH_STATUS_SUCCESS && status != SWITCH_STATUS_BREAK) {
break;
}
if (++x > 1000) {
break;
}
switch_cond_next();
}
switch_socket_opt_set(globals.sip_socket, SWITCH_SO_NONBLOCK, FALSE);
#endif
#endif
*module_interface = switch_loadable_module_create_module_interface(pool, modname);
SWITCH_ADD_APP(app_interface, "oreka_record", "Send media to Oreka recording server", "Send media to Oreka recording server",
oreka_start_function, "[stop]", SAF_NONE);
return SWITCH_STATUS_SUCCESS;
}
SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_oreka_shutdown)
{
switch_socket_close(globals.sip_socket);
return SWITCH_STATUS_UNLOAD;
}
/* For Emacs:
* Local Variables:
* mode:c
* indent-tabs-mode:t
* tab-width:4
* c-basic-offset:4
* End:
* For VIM:
* vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
*/

View File

@ -1,8 +0,0 @@
include $(top_srcdir)/build/modmake.rulesam
MODNAME=mod_clearmode
mod_LTLIBRARIES = mod_clearmode.la
mod_clearmode_la_SOURCES = mod_clearmode.c
mod_clearmode_la_CFLAGS = $(AM_CFLAGS)
mod_clearmode_la_LIBADD = $(switch_builddir)/libfreeswitch.la
mod_clearmode_la_LDFLAGS = -avoid-version -module -no-undefined -shared

View File

@ -1,107 +0,0 @@
/*
* FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
* Copyright (C) 2005-2014, Anthony Minessale II <anthm@freeswitch.org>
*
* Version: MPL 1.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
*
* The Initial Developer of the Original Code is
* Anthony Minessale II <anthm@freeswitch.org>
* Portions created by the Initial Developer are Copyright (C)
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Anthony Minessale II <anthm@freeswitch.org>
* Brian West <brian@freeswitch.org>
*
* mod_clear.c -- CLEARMODE Passthru Codec
*
*/
#include <switch.h>
SWITCH_MODULE_LOAD_FUNCTION(mod_clearmode_load);
SWITCH_MODULE_DEFINITION(mod_clearmode, mod_clearmode_load, NULL, NULL);
static switch_status_t switch_clearmode_init(switch_codec_t *codec, switch_codec_flag_t flags, const switch_codec_settings_t *codec_settings)
{
int encoding, decoding;
encoding = (flags & SWITCH_CODEC_FLAG_ENCODE);
decoding = (flags & SWITCH_CODEC_FLAG_DECODE);
if (!(encoding || decoding)) {
return SWITCH_STATUS_FALSE;
} else {
if (codec->fmtp_in) {
codec->fmtp_out = switch_core_strdup(codec->memory_pool, codec->fmtp_in);
}
return SWITCH_STATUS_SUCCESS;
}
}
static switch_status_t switch_clearmode_encode(switch_codec_t *codec,
switch_codec_t *other_codec,
void *decoded_data,
uint32_t decoded_data_len,
uint32_t decoded_rate, void *encoded_data, uint32_t *encoded_data_len, uint32_t *encoded_rate,
unsigned int *flag)
{
return SWITCH_STATUS_FALSE;
}
static switch_status_t switch_clearmode_decode(switch_codec_t *codec,
switch_codec_t *other_codec,
void *encoded_data,
uint32_t encoded_data_len,
uint32_t encoded_rate, void *decoded_data, uint32_t *decoded_data_len, uint32_t *decoded_rate,
unsigned int *flag)
{
return SWITCH_STATUS_FALSE;
}
static switch_status_t switch_clearmode_destroy(switch_codec_t *codec)
{
return SWITCH_STATUS_SUCCESS;
}
SWITCH_MODULE_LOAD_FUNCTION(mod_clearmode_load)
{
switch_codec_interface_t *codec_interface;
/* connect my internal structure to the blank pointer passed to me */
*module_interface = switch_loadable_module_create_module_interface(pool, modname);
SWITCH_ADD_CODEC(codec_interface, "Clearmode (passthru)");
switch_core_codec_add_implementation(pool, codec_interface,
SWITCH_CODEC_TYPE_AUDIO, 106, "CLEARMODE", NULL, 8000, 8000, 64000,
20000, 160, 320, 320, 1, 1,
switch_clearmode_init, switch_clearmode_encode, switch_clearmode_decode, switch_clearmode_destroy);
switch_core_codec_add_implementation(pool, codec_interface,
SWITCH_CODEC_TYPE_AUDIO, 106, "CLEARMODE", NULL, 8000, 8000, 64000,
30000, 240, 480, 480, 1, 1,
switch_clearmode_init, switch_clearmode_encode, switch_clearmode_decode, switch_clearmode_destroy);
/* indicate that the module should continue to be loaded */
return SWITCH_STATUS_SUCCESS;
}
/* For Emacs:
* Local Variables:
* mode:c
* indent-tabs-mode:t
* tab-width:4
* c-basic-offset:4
* End:
* For VIM:
* vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
*/

View File

@ -1,8 +0,0 @@
include $(top_srcdir)/build/modmake.rulesam
MODNAME=mod_theora
mod_LTLIBRARIES = mod_theora.la
mod_theora_la_SOURCES = mod_theora.c
mod_theora_la_CFLAGS = $(AM_CFLAGS)
mod_theora_la_LIBADD = $(switch_builddir)/libfreeswitch.la
mod_theora_la_LDFLAGS = -avoid-version -module -no-undefined -shared

View File

@ -1,102 +0,0 @@
/*
* FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
* Copyright (C) 2005-2014, Anthony Minessale II <anthm@freeswitch.org>
*
* Version: MPL 1.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
*
* The Initial Developer of the Original Code is
* Anthony Minessale II <anthm@freeswitch.org>
* Portions created by the Initial Developer are Copyright (C)
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Anthony Minessale II <anthm@freeswitch.org>
*
*
* mod_theora.c -- THEORA Video Codec
*
*/
#include <switch.h>
SWITCH_MODULE_LOAD_FUNCTION(mod_theora_load);
SWITCH_MODULE_DEFINITION(mod_theora, mod_theora_load, NULL, NULL);
static switch_status_t switch_theora_init(switch_codec_t *codec, switch_codec_flag_t flags, const switch_codec_settings_t *codec_settings)
{
int encoding, decoding;
encoding = (flags & SWITCH_CODEC_FLAG_ENCODE);
decoding = (flags & SWITCH_CODEC_FLAG_DECODE);
if (!(encoding || decoding)) {
return SWITCH_STATUS_FALSE;
} else {
if (codec->fmtp_in) {
codec->fmtp_out = switch_core_strdup(codec->memory_pool, codec->fmtp_in);
}
return SWITCH_STATUS_SUCCESS;
}
}
static switch_status_t switch_theora_encode(switch_codec_t *codec,
switch_codec_t *other_codec,
void *decoded_data,
uint32_t decoded_data_len,
uint32_t decoded_rate, void *encoded_data, uint32_t *encoded_data_len, uint32_t *encoded_rate,
unsigned int *flag)
{
return SWITCH_STATUS_FALSE;
}
static switch_status_t switch_theora_decode(switch_codec_t *codec,
switch_codec_t *other_codec,
void *encoded_data,
uint32_t encoded_data_len,
uint32_t encoded_rate, void *decoded_data, uint32_t *decoded_data_len, uint32_t *decoded_rate,
unsigned int *flag)
{
return SWITCH_STATUS_FALSE;
}
static switch_status_t switch_theora_destroy(switch_codec_t *codec)
{
return SWITCH_STATUS_SUCCESS;
}
SWITCH_MODULE_LOAD_FUNCTION(mod_theora_load)
{
switch_codec_interface_t *codec_interface;
/* connect my internal structure to the blank pointer passed to me */
*module_interface = switch_loadable_module_create_module_interface(pool, modname);
SWITCH_ADD_CODEC(codec_interface, "THEORA Video (passthru)");
switch_core_codec_add_implementation(pool, codec_interface,
SWITCH_CODEC_TYPE_VIDEO, 99, "THEORA", NULL, 90000, 90000, 0,
0, 0, 0, 0, 1, 1, switch_theora_init, switch_theora_encode, switch_theora_decode, switch_theora_destroy);
/* indicate that the module should continue to be loaded */
return SWITCH_STATUS_SUCCESS;
}
/* For Emacs:
* Local Variables:
* mode:c
* indent-tabs-mode:t
* tab-width:4
* c-basic-offset:4
* End:
* For VIM:
* vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
*/

View File

@ -106,6 +106,22 @@ char * pgsql_handle_get_error(switch_pgsql_handle_t *handle)
return err_str;
}
void pgsql_handle_set_error_if_not_set(switch_pgsql_handle_t *handle, char **err)
{
char *err_str;
if (err && !(*err)) {
err_str = pgsql_handle_get_error(handle);
if (zstr(err_str)) {
switch_safe_free(err_str);
err_str = strdup((char *)"SQL ERROR!");
}
*err = err_str;
}
}
static int db_is_up(switch_pgsql_handle_t *handle)
{
int ret = 0;
@ -553,8 +569,15 @@ switch_status_t pgsql_handle_exec_detailed(const char *file, const char *func, i
goto error;
}
return pgsql_finish_results(handle);
if (pgsql_finish_results(handle) != SWITCH_STATUS_SUCCESS) {
goto error;
}
return SWITCH_STATUS_SUCCESS;
error:
pgsql_handle_set_error_if_not_set(handle, err);
return SWITCH_STATUS_FALSE;
}
@ -630,6 +653,7 @@ done:
pgsql_free_result(&result);
if (pgsql_finish_results(handle) != SWITCH_STATUS_SUCCESS) {
pgsql_handle_set_error_if_not_set(handle, err);
sstatus = SWITCH_STATUS_FALSE;
}
@ -638,6 +662,7 @@ done:
error:
pgsql_free_result(&result);
pgsql_handle_set_error_if_not_set(handle, err);
return SWITCH_STATUS_FALSE;
}
@ -1050,6 +1075,8 @@ switch_status_t pgsql_handle_callback_exec_detailed(const char *file, const char
return SWITCH_STATUS_SUCCESS;
error:
pgsql_handle_set_error_if_not_set(handle, err);
return SWITCH_STATUS_FALSE;
}

View File

@ -254,7 +254,7 @@ char *generate_pai_str(private_object_t *tech_pvt)
callee_number = switch_sanitize_number(switch_core_session_strdup(session, callee_number));
callee_name = switch_sanitize_number(switch_core_session_strdup(session, callee_name));
if (!zstr(callee_number) && (zstr(ua) || !switch_stristr("polycom", ua))) {
if (!zstr(callee_number) && (zstr(ua) || !switch_stristr("poly", ua))) {
callee_number = switch_core_session_sprintf(session, "sip:%s@%s", callee_number, host);
}
@ -2075,13 +2075,15 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi
nua_info(tech_pvt->nh, SIPTAG_CONTENT_TYPE_STR("message/sipfrag"),
TAG_IF(!zstr(tech_pvt->user_via), SIPTAG_VIA_STR(tech_pvt->user_via)), SIPTAG_PAYLOAD_STR(message), TAG_END());
} else if (update_allowed && ua && (switch_channel_var_true(tech_pvt->channel, "update_ignore_ua") ||
switch_stristr("polycom", ua) ||
switch_stristr("poly", ua) ||
(switch_stristr("aastra", ua) && !switch_stristr("Intelligate", ua)) ||
(switch_stristr("cisco/spa50", ua) ||
switch_stristr("cisco/spa525", ua)) ||
switch_stristr("cisco/spa30", ua) ||
switch_stristr("Fanvil", ua) ||
switch_stristr("Grandstream", ua) ||
switch_stristr("Ringotel", ua) ||
switch_stristr("Groundwire", ua) ||
switch_stristr("Yealink", ua) ||
switch_stristr("Mitel", ua) ||
switch_stristr("Panasonic", ua))) {
@ -2152,7 +2154,7 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi
SIPTAG_PAYLOAD_STR(message),
TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header)),
TAG_END());
} else if (ua && switch_stristr("polycom", ua)) {
} else if (ua && switch_stristr("poly", ua)) {
snprintf(message, sizeof(message), "P-Asserted-Identity: \"%s\" <%s>", msg->string_arg, tech_pvt->caller_profile->destination_number);
nua_update(tech_pvt->nh,
NUTAG_SESSION_TIMER(tech_pvt->session_timeout),

View File

@ -10476,7 +10476,7 @@ void sofia_handle_sip_i_invite(switch_core_session_t *session, nua_t *nua, sofia
(!is_tcp && !is_tls && (zstr(network_ip) || !switch_check_network_list_ip(network_ip, profile->local_network)) &&
profile->server_rport_level >= 2 && sip->sip_user_agent &&
sip->sip_user_agent->g_string &&
(!strncasecmp(sip->sip_user_agent->g_string, "Polycom", 7) || !strncasecmp(sip->sip_user_agent->g_string, "KIRK Wireless Server", 20)))
(!strncasecmp(sip->sip_user_agent->g_string, "Poly", 4) || !strncasecmp(sip->sip_user_agent->g_string, "KIRK Wireless Server", 20)))
) {
if (sip->sip_via) {
const char *port = sip->sip_via->v_port;

View File

@ -2501,7 +2501,7 @@ static char *gen_pidf(char *user_agent, char *id, char *url, char *open, char *r
{
char *ret = NULL;
if (switch_stristr("polycom", user_agent)) {
if (switch_stristr("poly", user_agent)) {
*ct = "application/xpidf+xml";
/* If unknown/none prpid is provided, just show the user as online. */

View File

@ -1661,7 +1661,7 @@ uint8_t sofia_reg_handle_register_token(nua_t *nua, sofia_profile_t *profile, nu
if (!is_tcp && !is_tls && (zstr(network_ip) || !switch_check_network_list_ip(network_ip, profile->local_network)) &&
profile->server_rport_level >= 2 && sip->sip_user_agent &&
sip->sip_user_agent->g_string &&
( !strncasecmp(sip->sip_user_agent->g_string, "Polycom", 7) ||
( !strncasecmp(sip->sip_user_agent->g_string, "Poly", 4) ||
!strncasecmp(sip->sip_user_agent->g_string, "KIRK Wireless Server", 20) ||
!strncasecmp(sip->sip_user_agent->g_string, "ADTRAN_Total_Access", 19) )) {
if (sip->sip_via) {

View File

@ -61,6 +61,11 @@
%include "typemaps.i"
%apply int *OUTPUT { int *len };
%typemap(out) DbhQueryRowsReturn {
SWIG_arg += result;
}
/**
* tell swig to grok everything defined in these header files and
* build all sorts of c wrappers and lua shadows of the c wrappers.
@ -115,6 +120,7 @@ class Dbh {
bool connected();
bool test_reactive(char *test_sql, char *drop_sql = NULL, char *reactive_sql = NULL);
bool query(char *sql, SWIGLUA_FN lua_fun);
DbhQueryRowsReturn query_rows(lua_State* L, char *sql);
int affected_rows();
char *last_error();
void clear_error();

View File

@ -482,6 +482,62 @@ bool Dbh::query(char *sql, SWIGLUA_FN lua_fun)
return false;
}
struct query_callback_data {
lua_State *L;
int stack_index;
int *row_num;
};
int query2_callback(void *pArg, int argc, char **argv, char **columnNames)
{
struct query_callback_data *data = (struct query_callback_data *) pArg;
lua_State *tL = data->L;
lua_createtable(tL, 0, argc);
for (int i = 0; i < argc; i++) {
lua_pushstring(tL, argv[i]);
lua_setfield(tL, -2, switch_str_nil(columnNames[i]));
}
lua_rawseti(tL, data->stack_index + 2, (*data->row_num)++);
return 0;
}
DbhQueryRowsReturn Dbh::query_rows(lua_State* L, char *sql)
{
int stack_index = lua_gettop(L);
clear_error();
lua_pushboolean(L, 0); // result success error: stack_index + 1
lua_newtable(L); // the rows: stack_index + 2
lua_pushnil(L); // error message if any: stack_index + 3
if (zstr(sql)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Missing SQL query.\n");
lua_pushstring(L, "Missing SQL query.");
lua_replace(L, stack_index + 3);
return 3;
}
if (dbh) {
int index = 1;
struct query_callback_data pData = {L, stack_index, &index};
if (switch_cache_db_execute_sql_callback(dbh, sql, query2_callback, &pData, &err) == SWITCH_STATUS_SUCCESS) {
// no errors
lua_pushboolean(L, 1);
lua_replace(L, stack_index + 1);
} else {
lua_pushstring(L, !zstr(err) ? err : "Failed to execute sql query");
lua_replace(L, stack_index + 3);
}
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "DBH NOT Connected.\n");
lua_pushstring(L, "DBH NOT Connected.");
lua_replace(L, stack_index + 3);
}
return 3;
}
int Dbh::affected_rows()
{
if (dbh) {

View File

@ -28,6 +28,7 @@ typedef struct{
#define SWIGLUA_TABLE_GET(fn) {lua_pushvalue(fn.L,fn.idx);}
typedef int DbhQueryRowsReturn;
namespace LUA {
class Session:public CoreSession {
@ -76,6 +77,7 @@ namespace LUA {
bool connected();
bool test_reactive(char *test_sql, char *drop_sql = NULL, char *reactive_sql = NULL);
bool query(char *sql, SWIGLUA_FN lua_fun);
DbhQueryRowsReturn query_rows(lua_State* L, char *sql);
int affected_rows();
char *last_error();
void clear_error();

View File

@ -1,6 +1,6 @@
--- mod_lua_wrap.cpp.old 2015-06-16 12:27:19.024000000 -0500
+++ mod_lua_wrap.cpp 2015-06-16 12:34:51.540000000 -0500
@@ -4242,7 +4242,7 @@ static int _wrap_Stream_read(lua_State* L) {
--- mod_lua_wrap.cpp.old 2025-01-15 13:22:48.705853645 +0000
+++ mod_lua_wrap.cpp 2025-01-15 13:23:33.161847705 +0000
@@ -4242,7 +4242,7 @@
}
result = (char *)(arg1)->read(arg2);
@ -9,7 +9,7 @@
lua_pushnumber(L, (lua_Number) *arg2); SWIG_arg++;
return SWIG_arg;
@@ -8304,7 +8304,7 @@ static int _wrap_new_Session__SWIG_0(lua_State* L) {
@@ -8336,7 +8336,7 @@
SWIG_check_num_args("LUA::Session::Session",0,0)
result = (LUA::Session *)new LUA::Session();
@ -18,7 +18,7 @@
return SWIG_arg;
if(0) SWIG_fail;
@@ -8331,7 +8331,7 @@ static int _wrap_new_Session__SWIG_1(lua_State* L) {
@@ -8363,7 +8363,7 @@
}
result = (LUA::Session *)new LUA::Session(arg1,arg2);
@ -27,7 +27,7 @@
return SWIG_arg;
if(0) SWIG_fail;
@@ -8351,7 +8351,7 @@ static int _wrap_new_Session__SWIG_2(lua_State* L) {
@@ -8383,7 +8383,7 @@
if(!SWIG_lua_isnilstring(L,1)) SWIG_fail_arg("LUA::Session::Session",1,"char *");
arg1 = (char *)lua_tostring(L, 1);
result = (LUA::Session *)new LUA::Session(arg1);
@ -36,7 +36,7 @@
return SWIG_arg;
if(0) SWIG_fail;
@@ -8375,7 +8375,7 @@ static int _wrap_new_Session__SWIG_3(lua_State* L) {
@@ -8407,7 +8407,7 @@
}
result = (LUA::Session *)new LUA::Session(arg1);
@ -45,7 +45,7 @@
return SWIG_arg;
if(0) SWIG_fail;
@@ -9485,6 +9485,7 @@ static int _wrap_Dbh_test_reactive__SWIG_0(lua_State* L) {
@@ -9517,6 +9517,7 @@
arg2 = (char *)lua_tostring(L, 2);
arg3 = (char *)lua_tostring(L, 3);
arg4 = (char *)lua_tostring(L, 4);
@ -53,7 +53,7 @@
result = (bool)(arg1)->test_reactive(arg2,arg3,arg4);
lua_pushboolean(L,(int)(result!=0)); SWIG_arg++;
return SWIG_arg;
@@ -9516,6 +9516,7 @@ static int _wrap_Dbh_test_reactive__SWIG_1(lua_State* L) {
@@ -9547,6 +9548,7 @@
arg2 = (char *)lua_tostring(L, 2);
arg3 = (char *)lua_tostring(L, 3);
@ -61,7 +61,7 @@
result = (bool)(arg1)->test_reactive(arg2,arg3);
lua_pushboolean(L,(int)(result!=0)); SWIG_arg++;
return SWIG_arg;
@@ -9543,6 +9544,7 @@ static int _wrap_Dbh_test_reactive__SWIG_2(lua_State* L) {
@@ -9574,6 +9576,7 @@
}
arg2 = (char *)lua_tostring(L, 2);
@ -69,7 +69,7 @@
result = (bool)(arg1)->test_reactive(arg2);
lua_pushboolean(L,(int)(result!=0)); SWIG_arg++;
return SWIG_arg;
@@ -9672,6 +9673,7 @@ static int _wrap_Dbh_query(lua_State* L) {
@@ -9704,6 +9707,7 @@
(&arg3)->idx = 3;
}
}
@ -77,7 +77,15 @@
result = (bool)(arg1)->query(arg2,arg3);
lua_pushboolean(L,(int)(result!=0)); SWIG_arg++;
return SWIG_arg;
@@ -9695,7 +9697,7 @@ static int _wrap_Dbh_affected_rows(lua_State* L) {
@@ -9733,6 +9737,7 @@
}
arg3 = (char *)lua_tostring(L, 2);
+ switch_assert(arg1);
result = (arg1)->query_rows(arg2,arg3);
{
SWIG_arg += result;
@@ -9758,7 +9763,7 @@
if (!SWIG_IsOK(SWIG_ConvertPtr(L,1,(void**)&arg1,SWIGTYPE_p_LUA__Dbh,0))){
SWIG_fail_ptr("Dbh_affected_rows",1,SWIGTYPE_p_LUA__Dbh);
}
@ -86,7 +94,7 @@
result = (int)(arg1)->affected_rows();
lua_pushnumber(L, (lua_Number) result); SWIG_arg++;
return SWIG_arg;
@@ -9719,7 +9721,7 @@ static int _wrap_Dbh_last_error(lua_State* L) {
@@ -9782,7 +9787,7 @@
if (!SWIG_IsOK(SWIG_ConvertPtr(L,1,(void**)&arg1,SWIGTYPE_p_LUA__Dbh,0))){
SWIG_fail_ptr("Dbh_last_error",1,SWIGTYPE_p_LUA__Dbh);
}
@ -95,7 +103,7 @@
result = (char *)(arg1)->last_error();
lua_pushstring(L,(const char *)result); SWIG_arg++;
return SWIG_arg;
@@ -9742,7 +9744,7 @@ static int _wrap_Dbh_clear_error(lua_State* L) {
@@ -9805,7 +9810,7 @@
if (!SWIG_IsOK(SWIG_ConvertPtr(L,1,(void**)&arg1,SWIGTYPE_p_LUA__Dbh,0))){
SWIG_fail_ptr("Dbh_clear_error",1,SWIGTYPE_p_LUA__Dbh);
}
@ -104,7 +112,7 @@
(arg1)->clear_error();
return SWIG_arg;
@@ -9770,6 +9772,7 @@ static int _wrap_Dbh_load_extension(lua_State* L) {
@@ -9833,6 +9838,7 @@
}
arg2 = (char *)lua_tostring(L, 2);
@ -112,7 +120,7 @@
result = (int)(arg1)->load_extension((char const *)arg2);
lua_pushnumber(L, (lua_Number) result); SWIG_arg++;
return SWIG_arg;
@@ -9869,6 +9872,7 @@ static int _wrap_JSON_decode(lua_State* L) {
@@ -9933,6 +9939,7 @@
}
arg2 = (char *)lua_tostring(L, 2);
@ -120,7 +128,7 @@
result = (cJSON *)(arg1)->decode((char const *)arg2);
{
SWIG_arg += LUA::JSON::cJSON2LuaTable(L, result);
@@ -9902,6 +9906,7 @@ static int _wrap_JSON_encode(lua_State* L) {
@@ -9966,6 +9973,7 @@
(&arg2)->L = L;
(&arg2)->idx = 2;
}
@ -128,7 +136,7 @@
result = (arg1)->encode(arg2);
lua_pushlstring(L,(&result)->data(),(&result)->size()); SWIG_arg++;
return SWIG_arg;
@@ -9929,6 +9934,7 @@ static int _wrap_JSON_execute__SWIG_0(lua_State* L) {
@@ -9993,6 +10001,7 @@
}
arg2 = (char *)lua_tostring(L, 2);
@ -136,7 +144,7 @@
result = (cJSON *)(arg1)->execute((char const *)arg2);
{
SWIG_arg += LUA::JSON::cJSON2LuaTable(L, result);
@@ -9962,6 +9968,7 @@ static int _wrap_JSON_execute__SWIG_1(lua_State* L) {
@@ -10026,6 +10035,7 @@
(&arg2)->L = L;
(&arg2)->idx = 2;
}
@ -144,7 +152,7 @@
result = (cJSON *)(arg1)->execute(arg2);
{
SWIG_arg += LUA::JSON::cJSON2LuaTable(L, result);
@@ -10046,6 +10053,7 @@ static int _wrap_JSON_execute2__SWIG_0(lua_State* L) {
@@ -10110,6 +10120,7 @@
}
arg2 = (char *)lua_tostring(L, 2);
@ -152,7 +160,7 @@
result = (arg1)->execute2((char const *)arg2);
lua_pushlstring(L,(&result)->data(),(&result)->size()); SWIG_arg++;
return SWIG_arg;
@@ -10076,6 +10084,7 @@ static int _wrap_JSON_execute2__SWIG_1(lua_State* L) {
@@ -10140,6 +10151,7 @@
(&arg2)->L = L;
(&arg2)->idx = 2;
}
@ -160,7 +168,7 @@
result = (arg1)->execute2(arg2);
lua_pushlstring(L,(&result)->data(),(&result)->size()); SWIG_arg++;
return SWIG_arg;
@@ -10156,6 +10165,7 @@ static int _wrap_JSON_encode_empty_table_as_object(lua_State* L) {
@@ -10220,6 +10232,7 @@
}
arg2 = (lua_toboolean(L, 2)!=0);
@ -168,7 +176,7 @@
(arg1)->encode_empty_table_as_object(arg2);
return SWIG_arg;
@@ -10182,6 +10192,7 @@ static int _wrap_JSON_return_unformatted_json(lua_State* L) {
@@ -10246,6 +10259,7 @@
}
arg2 = (lua_toboolean(L, 2)!=0);

View File

@ -9720,6 +9720,38 @@ fail:
}
static int _wrap_Dbh_query_rows(lua_State* L) {
int SWIG_arg = 0;
LUA::Dbh *arg1 = (LUA::Dbh *) 0 ;
lua_State *arg2 = (lua_State *) 0 ;
char *arg3 = (char *) 0 ;
DbhQueryRowsReturn result;
arg2 = L;
SWIG_check_num_args("LUA::Dbh::query_rows",2,2)
if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("LUA::Dbh::query_rows",1,"LUA::Dbh *");
if(!SWIG_lua_isnilstring(L,2)) SWIG_fail_arg("LUA::Dbh::query_rows",2,"char *");
if (!SWIG_IsOK(SWIG_ConvertPtr(L,1,(void**)&arg1,SWIGTYPE_p_LUA__Dbh,0))){
SWIG_fail_ptr("Dbh_query_rows",1,SWIGTYPE_p_LUA__Dbh);
}
arg3 = (char *)lua_tostring(L, 2);
switch_assert(arg1);
result = (arg1)->query_rows(arg2,arg3);
{
SWIG_arg += result;
}
return SWIG_arg;
if(0) SWIG_fail;
fail:
lua_error(L);
return SWIG_arg;
}
static int _wrap_Dbh_affected_rows(lua_State* L) {
int SWIG_arg = 0;
LUA::Dbh *arg1 = (LUA::Dbh *) 0 ;
@ -9839,6 +9871,7 @@ static swig_lua_method swig_Dbh_methods[]= {
{ "connected", _wrap_Dbh_connected},
{ "test_reactive", _wrap_Dbh_test_reactive},
{ "query", _wrap_Dbh_query},
{ "query_rows", _wrap_Dbh_query_rows},
{ "affected_rows", _wrap_Dbh_affected_rows},
{ "last_error", _wrap_Dbh_last_error},
{ "clear_error", _wrap_Dbh_clear_error},

View File

@ -1,18 +0,0 @@
include $(top_srcdir)/build/modmake.rulesam
MODNAME=mod_yaml
if HAVE_YAML
mod_LTLIBRARIES = mod_yaml.la
mod_yaml_la_SOURCES = mod_yaml.c
mod_yaml_la_CFLAGS = $(AM_CFLAGS)
mod_yaml_la_CPPFLAGS = $(AM_CPPFLAGS) $(YAML_CFLAGS)
mod_yaml_la_LIBADD = $(switch_builddir)/libfreeswitch.la $(YAML_LIBS)
mod_yaml_la_LDFLAGS = -avoid-version -module -no-undefined -shared
else
install: error
all: error
error:
$(error You must install libyaml-dev to build mod_yaml)
endif

View File

@ -1,529 +0,0 @@
/*
* FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
* Copyright (C) 2005-2014, Anthony Minessale II <anthm@freeswitch.org>
*
* Version: MPL 1.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
*
* The Initial Developer of the Original Code is
* Anthony Minessale II <anthm@freeswitch.org>
* Portions created by the Initial Developer are Copyright (C)
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Anthony Minessale II <anthm@freeswitch.org>
*
* mod_yaml.c -- YAML Module
*
*/
#include <switch.h>
#include <yaml.h>
SWITCH_MODULE_LOAD_FUNCTION(mod_yaml_load);
SWITCH_MODULE_DEFINITION(mod_yaml, mod_yaml_load, NULL, NULL);
static void print_error(yaml_parser_t *parser)
{
switch (parser->error) {
case YAML_MEMORY_ERROR:
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Memory error: Not enough memory for parsing\n");
break;
case YAML_READER_ERROR:
if (parser->problem_value != -1) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Reader error: %s: #%X at %d\n", parser->problem,
parser->problem_value, (int) parser->problem_offset);
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Reader error: %s at %d\n", parser->problem, (int) parser->problem_offset);
}
break;
case YAML_SCANNER_ERROR:
if (parser->context) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Scanner error: %s at line %d, column %d\n"
"%s at line %d, column %d\n", parser->context,
(int) parser->context_mark.line + 1, (int) parser->context_mark.column + 1,
parser->problem, (int) parser->problem_mark.line + 1, (int) parser->problem_mark.column + 1);
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Scanner error: %s at line %d, column %d\n",
parser->problem, (int) parser->problem_mark.line + 1, (int) parser->problem_mark.column + 1);
}
break;
case YAML_PARSER_ERROR:
if (parser->context) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Parser error: %s at line %d, column %d\n"
"%s at line %d, column %d\n", parser->context,
(int) parser->context_mark.line + 1, (int) parser->context_mark.column + 1,
parser->problem, (int) parser->problem_mark.line + 1, (int) parser->problem_mark.column + 1);
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Parser error: %s at line %d, column %d\n",
parser->problem, (int) parser->problem_mark.line + 1, (int) parser->problem_mark.column + 1);
}
break;
default:
/* Couldn't happen. */
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Internal error\n");
break;
}
}
static switch_xml_t parse_file(FILE * input, const char *file_name)
{
yaml_parser_t parser;
yaml_event_t event = { 0 };
char *scalar_data;
int done = 0;
int depth = 0;
char name[128] = "";
char value[128] = "";
char category[128] = "";
int nv = 0, p_off = 0;
switch_xml_t xml, param, top, current = NULL;
yaml_parser_initialize(&parser);
yaml_parser_set_input_file(&parser, input);
if (!(xml = switch_xml_new("document"))) {
return NULL;
}
switch_xml_set_attr_d(xml, "type", "freeswitch/xml");
current = switch_xml_add_child_d(xml, "section", 0);
switch_xml_set_attr_d(current, "name", "configuration");
top = switch_xml_add_child_d(current, "configuration", 0);
switch_xml_set_attr_d(top, "name", file_name);
while (!done) {
if (!yaml_parser_parse(&parser, &event)) {
print_error(&parser);
break;
} else {
switch (event.type) {
case YAML_MAPPING_START_EVENT:
depth++;
break;
case YAML_MAPPING_END_EVENT:
depth--;
break;
case YAML_STREAM_END_EVENT:
done = 1;
break;
case YAML_SCALAR_EVENT:
scalar_data = (char *) event.data.scalar.value;
switch (depth) {
case 1:
if (!(current = switch_xml_add_child_d(top, scalar_data, depth - 1))) {
done = 1;
}
switch_set_string(category, scalar_data);
nv = 0;
p_off = 0;
break;
case 2:
if (current) {
if (nv == 0) {
switch_set_string(name, scalar_data);
nv++;
} else {
switch_set_string(value, scalar_data);
param = switch_xml_add_child_d(current, "param", p_off++);
switch_xml_set_attr_d_buf(param, "name", name);
switch_xml_set_attr_d(param, "value", scalar_data);
nv = 0;
}
}
break;
}
break;
default:
break;
}
}
yaml_event_delete(&event);
}
yaml_parser_delete(&parser);
if (input) {
fclose(input);
}
#ifdef DEBUG_XML
if (xml) {
char *foo = switch_xml_toxml(xml, SWITCH_FALSE);
printf("%s\n", foo);
free(foo);
}
#endif
return xml;
}
static switch_xml_t yaml_fetch(const char *section,
const char *tag_name, const char *key_name, const char *key_value, switch_event_t *params, void *user_data)
{
char *path;
FILE *input;
switch_xml_t xml = NULL;
path = switch_mprintf("%s/yaml/%s.yaml", SWITCH_GLOBAL_dirs.conf_dir, key_value);
if ((input = fopen(path, "r"))) {
xml = parse_file(input, key_value);
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "cannot open %s\n", path);
}
switch_safe_free(path);
return xml;
}
static switch_caller_extension_t *parse_dp(FILE * input, switch_core_session_t *session, switch_caller_profile_t *caller_profile)
{
yaml_parser_t parser;
yaml_event_t event = { 0 };
char *scalar_data;
int done = 0;
int depth = 0;
char name[128] = "";
char value[128] = "";
char category[128] = "";
char *last_field = NULL;
int nv = 0;
switch_caller_extension_t *extension = NULL;
switch_channel_t *channel = switch_core_session_get_channel(session);
int context_hit = 0;
int proceed = 0;
switch_regex_t *re = NULL;
int ovector[30];
int parens = 0;
if (!caller_profile) {
if (!(caller_profile = switch_channel_get_caller_profile(channel))) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error Obtaining Profile!\n");
return NULL;
}
}
if (!caller_profile->context) {
caller_profile->context = "default";
}
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Processing %s->%s@%s\n",
caller_profile->caller_id_name, caller_profile->destination_number, caller_profile->context);
yaml_parser_initialize(&parser);
yaml_parser_set_input_file(&parser, input);
while (!done) {
if (!yaml_parser_parse(&parser, &event)) {
print_error(&parser);
break;
} else {
switch (event.type) {
case YAML_MAPPING_START_EVENT:
depth++;
break;
case YAML_MAPPING_END_EVENT:
depth--;
break;
case YAML_STREAM_END_EVENT:
done = 1;
break;
case YAML_SCALAR_EVENT:
scalar_data = (char *) event.data.scalar.value;
switch (depth) {
case 1:
switch_set_string(category, scalar_data);
context_hit = (!strcasecmp(category, caller_profile->context));
nv = 0;
break;
case 2:
if (context_hit) {
char *field = switch_core_session_strdup(session, scalar_data);
char *p, *e, *expression = NULL, *field_expanded = NULL, *expression_expanded = NULL;
const char *field_data = NULL;
parens = 0;
proceed = 0;
switch_regex_safe_free(re);
if ((p = strstr(field, "=~"))) {
*p = '\0';
e = p - 1;
while (*e == ' ') {
*e-- = '\0';
}
e = p + 2;
while (*e == ' ') {
*e++ = '\0';
}
expression = e;
}
if (field && expression) {
if ((expression_expanded = switch_channel_expand_variables(channel, expression)) == expression) {
expression_expanded = NULL;
} else {
expression = expression_expanded;
}
if (strchr(field, '$')) {
if ((field_expanded = switch_channel_expand_variables(channel, field)) == field) {
field_expanded = NULL;
field_data = field;
} else {
field_data = field_expanded;
}
} else {
field_data = switch_caller_get_field_by_name(caller_profile, field);
}
if (!field_data) {
field_data = "";
}
switch_safe_free(last_field);
last_field = strdup(field_data);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "test conditions %s(%s) =~ /%s/\n", field, field_data, expression);
if (!(proceed = switch_regex_perform(field_data, expression, &re, ovector, sizeof(ovector) / sizeof(ovector[0])))) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Regex mismatch\n");
}
if (strchr(expression, '(')) {
parens++;
}
switch_safe_free(field_expanded);
switch_safe_free(expression_expanded);
}
}
break;
case 3:
if (nv == 0) {
if (!strcasecmp(scalar_data, "exit")) {
yaml_event_delete(&event);
goto end;
}
switch_set_string(name, scalar_data);
nv++;
} else {
switch_set_string(value, scalar_data);
nv = 0;
if (proceed) {
uint32_t len = 0;
char *substituted = NULL;
char *app_data;
if (!extension) {
extension = switch_caller_extension_new(session, "YAML", caller_profile->destination_number);
switch_assert(extension);
}
if (parens) {
len = (uint32_t) (strlen(value) + strlen(last_field) + 10) * proceed;
switch_zmalloc(substituted, len);
switch_perform_substitution(re, proceed, value, last_field, substituted, len, ovector);
app_data = substituted;
} else {
app_data = value;
}
switch_caller_extension_add_application(session, extension, name, app_data);
switch_safe_free(substituted);
}
}
break;
}
break;
default:
break;
}
}
yaml_event_delete(&event);
}
end:
switch_safe_free(last_field);
switch_regex_safe_free(re);
yaml_parser_delete(&parser);
if (input) {
fclose(input);
}
#ifdef DEBUG_XML
if (xml) {
char *foo = switch_xml_toxml(xml, SWITCH_FALSE);
printf("%s\n", foo);
free(foo);
}
#endif
return extension;
}
SWITCH_STANDARD_DIALPLAN(yaml_dialplan_hunt)
{
switch_caller_extension_t *extension = NULL;
char *alt_path = (char *) arg;
char *path = NULL;
FILE *input;
if (!zstr(alt_path)) {
path = strdup(alt_path);
} else {
path = switch_mprintf("%s/yaml/extensions.yaml", SWITCH_GLOBAL_dirs.conf_dir);
}
if ((input = fopen(path, "r"))) {
extension = parse_dp(input, session, caller_profile);
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error opening %s\n", path);
}
switch_safe_free(path);
return extension;
}
static switch_status_t do_config(void)
{
yaml_parser_t parser;
yaml_event_t event = { 0 };
char *path;
const char *cfg = "mod_yaml.yaml";
FILE *input;
switch_status_t status = SWITCH_STATUS_FALSE;
char *scalar_data;
int done = 0;
int depth = 0;
char name[128] = "";
char value[128] = "";
char category[128] = "";
int nv = 0;
path = switch_mprintf("%s/yaml/%s", SWITCH_GLOBAL_dirs.conf_dir, cfg);
if (!(input = fopen(path, "r"))) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error opening %s\n", path);
goto end;
}
yaml_parser_initialize(&parser);
yaml_parser_set_input_file(&parser, input);
while (!done) {
if (!yaml_parser_parse(&parser, &event)) {
print_error(&parser);
break;
} else {
switch (event.type) {
case YAML_MAPPING_START_EVENT:
depth++;
break;
case YAML_MAPPING_END_EVENT:
depth--;
break;
case YAML_STREAM_END_EVENT:
done = 1;
break;
case YAML_SCALAR_EVENT:
scalar_data = (char *) event.data.scalar.value;
switch (depth) {
case 1:
switch_set_string(category, scalar_data);
nv = 0;
break;
case 2:
if (nv == 0) {
switch_set_string(name, scalar_data);
nv++;
} else {
switch_set_string(value, scalar_data);
if (!strcasecmp(category, "settings")) {
if (!strcasecmp(name, "bind_config") && switch_true_buf(value)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Binding To XML Config\n");
switch_xml_bind_search_function(yaml_fetch, switch_xml_parse_section_string("config"), NULL);
}
}
nv = 0;
}
break;
}
break;
default:
break;
}
}
yaml_event_delete(&event);
}
yaml_parser_delete(&parser);
status = SWITCH_STATUS_SUCCESS;
end:
if (input) {
fclose(input);
}
switch_safe_free(path);
return status;
}
SWITCH_MODULE_LOAD_FUNCTION(mod_yaml_load)
{
switch_dialplan_interface_t *dp_interface;
/* connect my internal structure to the blank pointer passed to me */
*module_interface = switch_loadable_module_create_module_interface(pool, modname);
if (do_config() != SWITCH_STATUS_SUCCESS) {
return SWITCH_STATUS_TERM;
}
SWITCH_ADD_DIALPLAN(dp_interface, "YAML", yaml_dialplan_hunt);
/* indicate that the module should continue to be loaded */
return SWITCH_STATUS_SUCCESS;
}
/* For Emacs:
* Local Variables:
* mode:c
* indent-tabs-mode:t
* tab-width:4
* c-basic-offset:4
* End:
* For VIM:
* vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
*/

View File

@ -31,6 +31,7 @@
*/
#include <switch.h>
#include <errno.h>
#include <sys/timerfd.h>
#include <sys/epoll.h>
@ -228,8 +229,16 @@ SWITCH_MODULE_RUNTIME_FUNCTION(mod_timerfd_runtime)
do {
r = epoll_wait(interval_poll_fd, e, sizeof(e) / sizeof(e[0]), 1000);
if (r < 0)
if (r < 0) {
/* if we had an interrupted system call due to process pause via SIGSTOP, do not exit the timer loop */
if (errno == EINTR) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "epoll_wait interrupted by SIGINT, continue...\n");
continue;
}
break;
}
for (i = 0; i < r; i++) {
it = e[i].data.ptr;
if ((e[i].events & EPOLLIN) &&