From 927c646dc7354c8a503a4f25e04398d73c7223ba Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Wed, 19 Sep 2012 10:14:32 -0500 Subject: [PATCH 001/252] update error message to explain more --- src/mod/endpoints/mod_sofia/sofia.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/mod/endpoints/mod_sofia/sofia.c b/src/mod/endpoints/mod_sofia/sofia.c index ddbbead883..01fe061f88 100644 --- a/src/mod/endpoints/mod_sofia/sofia.c +++ b/src/mod/endpoints/mod_sofia/sofia.c @@ -2491,7 +2491,9 @@ void *SWITCH_THREAD_FUNC sofia_profile_thread_run(switch_thread_t *thread, void TAG_END()); /* Last tag should always finish the sequence */ if (!profile->nua) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error Creating SIP UA for profile: %s\n", profile->name); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error Creating SIP UA for profile: %s\n" + "The likely causes for this are:\n" "1) Another application is already listening on the specified address.\n" + "2) The IP the profile is attempting to bind to is not local to this system.", profile->name); sofia_profile_start_failure(profile, profile->name); sofia_glue_del_profile(profile); goto end; From 3cf238fc9a1370a45d362c2193b8d3634ccd1d11 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Wed, 19 Sep 2012 10:49:50 -0500 Subject: [PATCH 002/252] add skip_cdr_causes variable to list call hangup causes that should not trigger cdr processing --- src/include/switch_types.h | 1 + src/switch_core_state_machine.c | 17 +++++++++++++++++ 2 files changed, 18 insertions(+) diff --git a/src/include/switch_types.h b/src/include/switch_types.h index 9fa47ac2b8..5f3a4fa258 100644 --- a/src/include/switch_types.h +++ b/src/include/switch_types.h @@ -163,6 +163,7 @@ SWITCH_BEGIN_EXTERN_C #define SWITCH_API_REPORTING_HOOK_VARIABLE "api_reporting_hook" #define SWITCH_SESSION_IN_HANGUP_HOOK_VARIABLE "session_in_hangup_hook" #define SWITCH_PROCESS_CDR_VARIABLE "process_cdr" +#define SWITCH_SKIP_CDR_CAUSES_VARIABLE "skip_cdr_causes" #define SWITCH_FORCE_PROCESS_CDR_VARIABLE "force_process_cdr" #define SWITCH_BRIDGE_CHANNEL_VARIABLE "bridge_channel" #define SWITCH_CHANNEL_NAME_VARIABLE "channel_name" diff --git a/src/switch_core_state_machine.c b/src/switch_core_state_machine.c index a3c7079dbb..0288df11a6 100644 --- a/src/switch_core_state_machine.c +++ b/src/switch_core_state_machine.c @@ -662,6 +662,7 @@ SWITCH_DECLARE(void) switch_core_session_reporting_state(switch_core_session_t * int silly = 0; int index = 0; const char *var = switch_channel_get_variable(session->channel, SWITCH_PROCESS_CDR_VARIABLE); + const char *skip_var = switch_channel_get_variable(session->channel, SWITCH_SKIP_CDR_CAUSES_VARIABLE); const char *hook_var; int use_session = 0; switch_event_t *event; @@ -695,6 +696,22 @@ SWITCH_DECLARE(void) switch_core_session_reporting_state(switch_core_session_t * } } + + if (!zstr(skip_var)) { + int x, ttl = 0; + char *list[128] = { 0 }; + char *dup = switch_core_session_strdup(session, skip_var); + + ttl = switch_split(dup, '|', list); + + for(x = 0; x < ttl; x++) { + if (switch_channel_str2cause(list[x]) == cause) { + do_extra_handlers = 0; + break; + } + } + } + if (switch_channel_test_flag(session->channel, CF_NO_CDR)) { do_extra_handlers = 0; } From cba999b551ae77a0feb015f708f9f80bfc1f70c7 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Wed, 19 Sep 2012 11:47:53 -0500 Subject: [PATCH 003/252] FS-4598 reasonable req --- src/mod/endpoints/mod_sofia/sofia.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/mod/endpoints/mod_sofia/sofia.c b/src/mod/endpoints/mod_sofia/sofia.c index 01fe061f88..304ac668dd 100644 --- a/src/mod/endpoints/mod_sofia/sofia.c +++ b/src/mod/endpoints/mod_sofia/sofia.c @@ -1723,6 +1723,7 @@ void sofia_event_callback(nua_event_t event, private_object_t *tech_pvt = switch_core_session_get_private(session); if (status == 403) { + switch_channel_set_flag(channel, CF_NO_CDR); switch_channel_hangup(channel, SWITCH_CAUSE_CALL_REJECTED); } else { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "detaching session %s\n", sofia_private->uuid); From 35a141c457bb402db50e142cfab4d67583098ccf Mon Sep 17 00:00:00 2001 From: Ken Rice Date: Wed, 19 Sep 2012 13:36:06 -0400 Subject: [PATCH 004/252] add support to RPM spec file for Spanish and Portugese language modules --- freeswitch.spec | 43 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/freeswitch.spec b/freeswitch.spec index f4e3399715..66a989882c 100644 --- a/freeswitch.spec +++ b/freeswitch.spec @@ -1118,6 +1118,22 @@ Requires: %{name} = %{version}-%{release} %description lang-he Hebrew language phrases module and directory structure for say module and voicemail +%package lang-es +Summary: Provides Spanish language dependend modules and speech config for the FreeSWITCH Open Source telephone platform. +Group: System/Libraries +Requires: %{name} = %{version}-%{release} + +%description lang-es +Spanish language phrases module and directory structure for say module and voicemail + +%package lang-pt +Summary: Provides Portugese language dependend modules and speech config for the FreeSWITCH Open Source telephone platform. +Group: System/Libraries +Requires: %{name} = %{version}-%{release} + +%description lang-pt +Hebrew language phrases module and directory structure for say module and voicemail + ###################################################################################################################### # FreeSWITCH Timer Modules ###################################################################################################################### @@ -1733,6 +1749,7 @@ fi %config(noreplace) %attr(0640, freeswitch, daemon) %{sysconfdir}/autoload_configs/mongo.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/portaudio.conf.xml @@ -2296,6 +2313,30 @@ fi %config(noreplace) %attr(0640, freeswitch, daemon) %{sysconfdir}/lang/he/dir/*.xml %{MODINSTDIR}/mod_say_he.so* +%files lang-es +%defattr(-, freeswitch, daemon) +%dir %attr(0750, freeswitch, daemon) %{sysconfdir}/lang/es +%dir %attr(0750, freeswitch, daemon) %{sysconfdir}/lang/es/demo +%dir %attr(0750, freeswitch, daemon) %{sysconfdir}/lang/es/vm +%dir %attr(0750, freeswitch, daemon) %{sysconfdir}/lang/es/dir +%config(noreplace) %attr(0640, freeswitch, daemon) %{sysconfdir}/lang/es/*.xml +%config(noreplace) %attr(0640, freeswitch, daemon) %{sysconfdir}/lang/es/demo/*.xml +%config(noreplace) %attr(0640, freeswitch, daemon) %{sysconfdir}/lang/es/vm/*.xml +%config(noreplace) %attr(0640, freeswitch, daemon) %{sysconfdir}/lang/es/dir/*.xml +%{MODINSTDIR}/mod_say_en.so* + +%files lang-en +%defattr(-, freeswitch, daemon) +%dir %attr(0750, freeswitch, daemon) %{sysconfdir}/lang/pt +%dir %attr(0750, freeswitch, daemon) %{sysconfdir}/lang/pt/demo +%dir %attr(0750, freeswitch, daemon) %{sysconfdir}/lang/pt/vm +%dir %attr(0750, freeswitch, daemon) %{sysconfdir}/lang/pt/dir +%config(noreplace) %attr(0640, freeswitch, daemon) %{sysconfdir}/lang/pt/*.xml +%config(noreplace) %attr(0640, freeswitch, daemon) %{sysconfdir}/lang/pt/demo/*.xml +%config(noreplace) %attr(0640, freeswitch, daemon) %{sysconfdir}/lang/pt/vm/*.xml +%config(noreplace) %attr(0640, freeswitch, daemon) %{sysconfdir}/lang/pt/dir/*.xml +%{MODINSTDIR}/mod_say_en.so* + ###################################################################################################################### # # Timer Modules @@ -2332,6 +2373,8 @@ fi # ###################################################################################################################### %changelog +* Thu Sep 19 2012 - krice@freeswitch.org +- Add support for Spanish and Portugese say language modules * Thu Jan 26 2012 - krice@freeswitch.org - complete rework of spec file * Tue Jun 14 2011 - michal.bielicki@seventhsignal.de From cf480c8b3a46b9abfd76e2f7a918593c103ad6bc Mon Sep 17 00:00:00 2001 From: Ken Rice Date: Wed, 19 Sep 2012 13:40:13 -0400 Subject: [PATCH 005/252] misssed a spec in the spec file --- freeswitch.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/freeswitch.spec b/freeswitch.spec index 66a989882c..4e77fc5e4a 100644 --- a/freeswitch.spec +++ b/freeswitch.spec @@ -2325,7 +2325,7 @@ fi %config(noreplace) %attr(0640, freeswitch, daemon) %{sysconfdir}/lang/es/dir/*.xml %{MODINSTDIR}/mod_say_en.so* -%files lang-en +%files lang-pt %defattr(-, freeswitch, daemon) %dir %attr(0750, freeswitch, daemon) %{sysconfdir}/lang/pt %dir %attr(0750, freeswitch, daemon) %{sysconfdir}/lang/pt/demo From cd6ead9178556b295b8f842d1a44a83d212602c3 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Wed, 19 Sep 2012 12:44:26 -0500 Subject: [PATCH 006/252] add libks (kitchen sink) as a new lib to collect random cool cross platform BSD licensed C funcs --- libs/libks/Makefile | 26 + libs/libks/src/include/cc.h | 2 + libs/libks/src/include/ks.h | 371 +++ libs/libks/src/include/ks_buffer.h | 146 + libs/libks/src/include/ks_config.h | 178 + libs/libks/src/include/ks_json.h | 127 + libs/libks/src/include/ks_threadmutex.h | 58 + libs/libks/src/include/mpool.h | 463 +++ libs/libks/src/include/mpool_loc.h | 116 + libs/libks/src/include/simclist.h | 980 ++++++ libs/libks/src/include/table.h | 1372 ++++++++ libs/libks/src/include/table_loc.h | 229 ++ libs/libks/src/ks.c | 739 ++++ libs/libks/src/ks_buffer.c | 353 ++ libs/libks/src/ks_config.c | 256 ++ libs/libks/src/ks_json.c | 529 +++ libs/libks/src/ks_threadmutex.c | 239 ++ libs/libks/src/mpool.c | 1768 ++++++++++ libs/libks/src/simclist.c | 1525 +++++++++ libs/libks/src/table.c | 4079 +++++++++++++++++++++++ libs/libks/src/table_util.c | 295 ++ 21 files changed, 13851 insertions(+) create mode 100644 libs/libks/Makefile create mode 100644 libs/libks/src/include/cc.h create mode 100644 libs/libks/src/include/ks.h create mode 100644 libs/libks/src/include/ks_buffer.h create mode 100644 libs/libks/src/include/ks_config.h create mode 100755 libs/libks/src/include/ks_json.h create mode 100644 libs/libks/src/include/ks_threadmutex.h create mode 100644 libs/libks/src/include/mpool.h create mode 100644 libs/libks/src/include/mpool_loc.h create mode 100755 libs/libks/src/include/simclist.h create mode 100644 libs/libks/src/include/table.h create mode 100644 libs/libks/src/include/table_loc.h create mode 100644 libs/libks/src/ks.c create mode 100644 libs/libks/src/ks_buffer.c create mode 100644 libs/libks/src/ks_config.c create mode 100644 libs/libks/src/ks_json.c create mode 100644 libs/libks/src/ks_threadmutex.c create mode 100644 libs/libks/src/mpool.c create mode 100755 libs/libks/src/simclist.c create mode 100644 libs/libks/src/table.c create mode 100644 libs/libks/src/table_util.c diff --git a/libs/libks/Makefile b/libs/libks/Makefile new file mode 100644 index 0000000000..250280766f --- /dev/null +++ b/libs/libks/Makefile @@ -0,0 +1,26 @@ +PWD=$(shell pwd) +INCS=-I$(PWD)/src/include +DEBUG=-g -ggdb +BASE_FLAGS=$(INCS) $(DEBUG) -I$(LIBEDIT_DIR)/src/ -fPIC +PICKY=-O2 +CFLAGS=$(BASE_FLAGS) $(PICKY) +CXXFLAGS=$(BASE_FLAGS) +MYLIB=libks.a +LIBS=-lncurses -lks -lpthread -lm +LDFLAGS=-L. +OBJS=src/ks.o src/ks_threadmutex.o src/ks_config.o src/ks_json.o src/ks_buffer.o src/mpool.o src/table.o src/table_util.o src/simclist.o +SRC=src/ks.c src/ks_json.c src/ks_threadmutex.c src/ks_config.c src/ks_json.c src/ks_buffer.c src/mpool.c src/table.c src/table_util.c src/simclist.c +HEADERS=src/include/ks_config.h src/include/ks.h src/include/ks_threadmutex.h src/include/ks_json.h src/include/ks_buffer.h src/include/mpool.h src/include/mpool_loc.h src/include/table.h src/include/table_loc.h src/include/simclist.h +SOLINK=-shared -Xlinker -x + +all: $(MYLIB) + +$(MYLIB): $(OBJS) $(HEADERS) $(SRC) + ar rcs $(MYLIB) $(OBJS) + ranlib $(MYLIB) + +%.o: %.c $(HEADERS) + $(CC) $(CC_CFLAGS) $(CFLAGS) -c $< -o $@ + +clean: + rm -f *.o src/*.o libks.a *~ src/*~ src/include/*~ diff --git a/libs/libks/src/include/cc.h b/libs/libks/src/include/cc.h new file mode 100644 index 0000000000..44666193c6 --- /dev/null +++ b/libs/libks/src/include/cc.h @@ -0,0 +1,2 @@ +const char *cc = ".========================================================================================================.\n| ____ _____ ____ _ ____ _ _ _____ |\n| / ___|___ _ __ ___ ___ |_ _|__ / ___| |_ _ ___ / ___|___ _ __ ( ) |___ / |\n| | | / _ \\| '_ ` _ \\ / _ \\ | |/ _ \\ | | | | | | |/ _ \\ | / _ \\| '_ \\ |/| | |_ \\ |\n| | |__| (_) | | | | | | __/ | | (_) | | |___| | |_| | __/ |__| (_) | | | | | |___) | |\n| \\____\\___/|_| |_| |_|\\___| |_|\\___/ \\____|_|\\__,_|\\___|\\____\\___/|_| |_| |_|____/ |\n| |\n| ____ _ _ _ _ ____ _ |\n| / ___| |__ (_) ___ __ _ __ _ ___ | | | / ___| / \\ |\n| | | | '_ \\| |/ __/ _` |/ _` |/ _ \\ | | | \\___ \\ / _ \\ |\n| | |___| | | | | (_| (_| | (_| | (_) | | |_| |___) / ___ \\ |\n| \\____|_| |_|_|\\___\\__,_|\\__, |\\___( ) \\___/|____/_/ \\_\\ |\n| |___/ |/ |\n| _ _ __ _ _ ___ _ _ ____ ___ _ _____ |\n| / \\ _ _ __ _ _ _ ___| |_ / /_ | |_| |__ ( _ )| |_| |__ |___ \\ / _ \\/ |___ / |\n| / _ \\| | | |/ _` | | | / __| __| | '_ \\| __| '_ \\ _____ / _ \\| __| '_ \\ __) | | | | | |_ \\ |\n| / ___ \\ |_| | (_| | |_| \\__ \\ |_ | (_) | |_| | | | |_____| | (_) | |_| | | | / __/| |_| | |___) | |\n| /_/ \\_\\__,_|\\__, |\\__,_|___/\\__| \\___/ \\__|_| |_| \\___/ \\__|_| |_| |_____|\\___/|_|____/ |\n| |___/ |\n| _ |\n| __ ____ ____ __ ___| |_ _ ___ ___ ___ _ __ ___ ___ _ __ ___ |\n| \\ \\ /\\ / /\\ \\ /\\ / /\\ \\ /\\ / / / __| | | | |/ _ \\/ __/ _ \\| '_ \\ / __/ _ \\| '_ ` _ \\ |\n| \\ V V / \\ V V / \\ V V / _ | (__| | |_| | __/ (_| (_) | | | | _ | (_| (_) | | | | | | |\n| \\_/\\_/ \\_/\\_/ \\_/\\_/ (_) \\___|_|\\__,_|\\___|\\___\\___/|_| |_| (_) \\___\\___/|_| |_| |_| |\n| |\n.========================================================================================================.\n"; + diff --git a/libs/libks/src/include/ks.h b/libs/libks/src/include/ks.h new file mode 100644 index 0000000000..c581544d85 --- /dev/null +++ b/libs/libks/src/include/ks.h @@ -0,0 +1,371 @@ +/* + * Copyright (c) 2007-2012, Anthony Minessale II + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name of the original author; nor the names of any contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _KS_H_ +#define _KS_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif /* defined(__cplusplus) */ + +#define ks_copy_string(_x, _y, _z) strncpy(_x, _y, _z - 1) +#define ks_set_string(_x, _y) ks_copy_string(_x, _y, sizeof(_x)) +#define KS_VA_NONE "%s", "" + + +typedef enum { + KS_POLL_READ = (1 << 0), + KS_POLL_WRITE = (1 << 1), + KS_POLL_ERROR = (1 << 2) +} ks_poll_t; + +#ifdef WIN32 +#define KS_SEQ_FWHITE FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY +#define KS_SEQ_BWHITE FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE +#define KS_SEQ_FRED FOREGROUND_RED | FOREGROUND_INTENSITY +#define KS_SEQ_BRED FOREGROUND_RED +#define KS_SEQ_FMAGEN FOREGROUND_BLUE | FOREGROUND_RED | FOREGROUND_INTENSITY +#define KS_SEQ_BMAGEN FOREGROUND_BLUE | FOREGROUND_RED +#define KS_SEQ_FCYAN FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY +#define KS_SEQ_BCYAN FOREGROUND_GREEN | FOREGROUND_BLUE +#define KS_SEQ_FGREEN FOREGROUND_GREEN | FOREGROUND_INTENSITY +#define KS_SEQ_BGREEN FOREGROUND_GREEN +#define KS_SEQ_FYELLOW FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY +#define KS_SEQ_BYELLOW FOREGROUND_RED | FOREGROUND_GREEN +#define KS_SEQ_DEFAULT_COLOR KS_SEQ_FWHITE +#define KS_SEQ_FBLUE FOREGROUND_BLUE | FOREGROUND_INTENSITY +#define KS_SEQ_BBLUE FOREGROUND_BLUE +#define KS_SEQ_FBLACK 0 | FOREGROUND_INTENSITY +#define KS_SEQ_BBLACK 0 +#else +#define KS_SEQ_ESC "\033[" +/* Ansi Control character suffixes */ +#define KS_SEQ_HOME_CHAR 'H' +#define KS_SEQ_HOME_CHAR_STR "H" +#define KS_SEQ_CLEARLINE_CHAR '1' +#define KS_SEQ_CLEARLINE_CHAR_STR "1" +#define KS_SEQ_CLEARLINEEND_CHAR "K" +#define KS_SEQ_CLEARSCR_CHAR0 '2' +#define KS_SEQ_CLEARSCR_CHAR1 'J' +#define KS_SEQ_CLEARSCR_CHAR "2J" +#define KS_SEQ_DEFAULT_COLOR KS_SEQ_ESC KS_SEQ_END_COLOR /* Reset to Default fg/bg color */ +#define KS_SEQ_AND_COLOR ";" /* To add multiple color definitions */ +#define KS_SEQ_END_COLOR "m" /* To end color definitions */ +/* Foreground colors values */ +#define KS_SEQ_F_BLACK "30" +#define KS_SEQ_F_RED "31" +#define KS_SEQ_F_GREEN "32" +#define KS_SEQ_F_YELLOW "33" +#define KS_SEQ_F_BLUE "34" +#define KS_SEQ_F_MAGEN "35" +#define KS_SEQ_F_CYAN "36" +#define KS_SEQ_F_WHITE "37" +/* Background colors values */ +#define KS_SEQ_B_BLACK "40" +#define KS_SEQ_B_RED "41" +#define KS_SEQ_B_GREEN "42" +#define KS_SEQ_B_YELLOW "43" +#define KS_SEQ_B_BLUE "44" +#define KS_SEQ_B_MAGEN "45" +#define KS_SEQ_B_CYAN "46" +#define KS_SEQ_B_WHITE "47" +/* Preset escape sequences - Change foreground colors only */ +#define KS_SEQ_FBLACK KS_SEQ_ESC KS_SEQ_F_BLACK KS_SEQ_END_COLOR +#define KS_SEQ_FRED KS_SEQ_ESC KS_SEQ_F_RED KS_SEQ_END_COLOR +#define KS_SEQ_FGREEN KS_SEQ_ESC KS_SEQ_F_GREEN KS_SEQ_END_COLOR +#define KS_SEQ_FYELLOW KS_SEQ_ESC KS_SEQ_F_YELLOW KS_SEQ_END_COLOR +#define KS_SEQ_FBLUE KS_SEQ_ESC KS_SEQ_F_BLUE KS_SEQ_END_COLOR +#define KS_SEQ_FMAGEN KS_SEQ_ESC KS_SEQ_F_MAGEN KS_SEQ_END_COLOR +#define KS_SEQ_FCYAN KS_SEQ_ESC KS_SEQ_F_CYAN KS_SEQ_END_COLOR +#define KS_SEQ_FWHITE KS_SEQ_ESC KS_SEQ_F_WHITE KS_SEQ_END_COLOR +#define KS_SEQ_BBLACK KS_SEQ_ESC KS_SEQ_B_BLACK KS_SEQ_END_COLOR +#define KS_SEQ_BRED KS_SEQ_ESC KS_SEQ_B_RED KS_SEQ_END_COLOR +#define KS_SEQ_BGREEN KS_SEQ_ESC KS_SEQ_B_GREEN KS_SEQ_END_COLOR +#define KS_SEQ_BYELLOW KS_SEQ_ESC KS_SEQ_B_YELLOW KS_SEQ_END_COLOR +#define KS_SEQ_BBLUE KS_SEQ_ESC KS_SEQ_B_BLUE KS_SEQ_END_COLOR +#define KS_SEQ_BMAGEN KS_SEQ_ESC KS_SEQ_B_MAGEN KS_SEQ_END_COLOR +#define KS_SEQ_BCYAN KS_SEQ_ESC KS_SEQ_B_CYAN KS_SEQ_END_COLOR +#define KS_SEQ_BWHITE KS_SEQ_ESC KS_SEQ_B_WHITE KS_SEQ_END_COLOR +/* Preset escape sequences */ +#define KS_SEQ_HOME KS_SEQ_ESC KS_SEQ_HOME_CHAR_STR +#define KS_SEQ_CLEARLINE KS_SEQ_ESC KS_SEQ_CLEARLINE_CHAR_STR +#define KS_SEQ_CLEARLINEEND KS_SEQ_ESC KS_SEQ_CLEARLINEEND_CHAR +#define KS_SEQ_CLEARSCR KS_SEQ_ESC KS_SEQ_CLEARSCR_CHAR KS_SEQ_HOME +#endif + +#if !defined(_XOPEN_SOURCE) && !defined(__FreeBSD__) && !defined(__NetBSD__) && !defined(__OpenBSD__) +#define _XOPEN_SOURCE 600 +#endif + +#ifndef HAVE_STRINGS_H +#define HAVE_STRINGS_H 1 +#endif +#ifndef HAVE_SYS_SOCKET_H +#define HAVE_SYS_SOCKET_H 1 +#endif + +#ifndef __WINDOWS__ +#if defined(WIN32) || defined(WIN64) || defined(_MSC_VER) || defined(_WIN32) +#define __WINDOWS__ +#endif +#endif + +#ifdef _MSC_VER +#ifndef __inline__ +#define __inline__ __inline +#endif +#if (_MSC_VER >= 1400) /* VC8+ */ +#ifndef _CRT_SECURE_NO_DEPRECATE +#define _CRT_SECURE_NO_DEPRECATE +#endif +#ifndef _CRT_NONSTDC_NO_DEPRECATE +#define _CRT_NONSTDC_NO_DEPRECATE +#endif +#endif +#ifndef strcasecmp +#define strcasecmp(s1, s2) _stricmp(s1, s2) +#endif +#ifndef strncasecmp +#define strncasecmp(s1, s2, n) _strnicmp(s1, s2, n) +#endif +#ifndef snprintf +#define snprintf _snprintf +#endif +#ifndef S_IRUSR +#define S_IRUSR _S_IREAD +#endif +#ifndef S_IWUSR +#define S_IWUSR _S_IWRITE +#endif +#undef HAVE_STRINGS_H +#undef HAVE_SYS_SOCKET_H +#endif + +#include +#ifndef WIN32 +#include +#endif + +#include +#include +#include +#include +#ifndef WIN32 +#include +#include +#include +#include +#include +#include +#endif + +#ifdef HAVE_STRINGS_H +#include +#endif +#include + +#if (_MSC_VER >= 1400) // VC8+ +#define ks_assert(expr) assert(expr);__analysis_assume( expr ) +#endif + +#ifndef ks_assert +#define ks_assert(_x) assert(_x) +#endif + +#define ks_safe_free(_x) if (_x) free(_x); _x = NULL +#define ks_strlen_zero(s) (!s || *(s) == '\0') +#define ks_strlen_zero_buf(s) (*(s) == '\0') +#define end_of(_s) *(*_s == '\0' ? _s : _s + strlen(_s) - 1) + +#ifdef WIN32 +#include +#include +typedef SOCKET ks_socket_t; +typedef unsigned __int64 uint64_t; +typedef unsigned __int32 uint32_t; +typedef unsigned __int16 uint16_t; +typedef unsigned __int8 uint8_t; +typedef __int64 int64_t; +typedef __int32 int32_t; +typedef __int16 int16_t; +typedef __int8 int8_t; +typedef intptr_t ks_ssize_t; +typedef int ks_filehandle_t; +#define KS_SOCK_INVALID INVALID_SOCKET +#define strerror_r(num, buf, size) strerror_s(buf, size, num) +#if defined(KS_DECLARE_STATIC) +#define KS_DECLARE(type) type __stdcall +#define KS_DECLARE_NONSTD(type) type __cdecl +#define KS_DECLARE_DATA +#elif defined(KS_EXPORTS) +#define KS_DECLARE(type) __declspec(dllexport) type __stdcall +#define KS_DECLARE_NONSTD(type) __declspec(dllexport) type __cdecl +#define KS_DECLARE_DATA __declspec(dllexport) +#else +#define KS_DECLARE(type) __declspec(dllimport) type __stdcall +#define KS_DECLARE_NONSTD(type) __declspec(dllimport) type __cdecl +#define KS_DECLARE_DATA __declspec(dllimport) +#endif +#else +#define KS_DECLARE(type) type +#define KS_DECLARE_NONSTD(type) type +#define KS_DECLARE_DATA +#include +#include +#include +#include +#include +#include +#include +#define KS_SOCK_INVALID -1 +typedef int ks_socket_t; +typedef ssize_t ks_ssize_t; +typedef int ks_filehandle_t; +#endif + +#include "math.h" +#include "ks_json.h" + +typedef int16_t ks_port_t; +typedef size_t ks_size_t; + +typedef enum { + KS_SUCCESS, + KS_FAIL, + KS_BREAK, + KS_DISCONNECTED, + KS_GENERR +} ks_status_t; + +#define BUF_CHUNK 65536 * 50 +#define BUF_START 65536 * 100 + +#include +#include + +#define ks_test_flag(obj, flag) ((obj)->flags & flag) +#define ks_set_flag(obj, flag) (obj)->flags |= (flag) +#define ks_clear_flag(obj, flag) (obj)->flags &= ~(flag) + +/*! \brief Used internally for truth test */ +typedef enum { + KS_TRUE = 1, + KS_FALSE = 0 +} ks_bool_t; + +#ifndef __FUNCTION__ +#define __FUNCTION__ (const char *)__func__ +#endif + +#define KS_PRE __FILE__, __FUNCTION__, __LINE__ +#define KS_LOG_LEVEL_DEBUG 7 +#define KS_LOG_LEVEL_INFO 6 +#define KS_LOG_LEVEL_NOTICE 5 +#define KS_LOG_LEVEL_WARNING 4 +#define KS_LOG_LEVEL_ERROR 3 +#define KS_LOG_LEVEL_CRIT 2 +#define KS_LOG_LEVEL_ALERT 1 +#define KS_LOG_LEVEL_EMERG 0 + +#define KS_LOG_DEBUG KS_PRE, KS_LOG_LEVEL_DEBUG +#define KS_LOG_INFO KS_PRE, KS_LOG_LEVEL_INFO +#define KS_LOG_NOTICE KS_PRE, KS_LOG_LEVEL_NOTICE +#define KS_LOG_WARNING KS_PRE, KS_LOG_LEVEL_WARNING +#define KS_LOG_ERROR KS_PRE, KS_LOG_LEVEL_ERROR +#define KS_LOG_CRIT KS_PRE, KS_LOG_LEVEL_CRIT +#define KS_LOG_ALERT KS_PRE, KS_LOG_LEVEL_ALERT +#define KS_LOG_EMERG KS_PRE, KS_LOG_LEVEL_EMERG +typedef void (*ks_logger_t)(const char *file, const char *func, int line, int level, const char *fmt, ...); +typedef void (*ks_listen_callback_t)(ks_socket_t server_sock, ks_socket_t client_sock, struct sockaddr_in *addr); + + +KS_DECLARE(int) ks_vasprintf(char **ret, const char *fmt, va_list ap); + +KS_DECLARE_DATA extern ks_logger_t ks_log; + +/*! Sets the logger for libks. Default is the null_logger */ +KS_DECLARE(void) ks_global_set_logger(ks_logger_t logger); +/*! Sets the default log level for libks */ +KS_DECLARE(void) ks_global_set_default_logger(int level); + + +#include "ks_threadmutex.h" +#include "ks_config.h" +#include "ks_buffer.h" +#include "mpool.h" +#include "simclist.h" +#include "table.h" + +KS_DECLARE(size_t) ks_url_encode(const char *url, char *buf, size_t len); +KS_DECLARE(char *)ks_url_decode(char *s); +KS_DECLARE(const char *)ks_stristr(const char *instr, const char *str); +KS_DECLARE(int) ks_toupper(int c); +KS_DECLARE(int) ks_tolower(int c); +KS_DECLARE(int) ks_snprintf(char *buffer, size_t count, const char *fmt, ...); + + +KS_DECLARE(int) ks_wait_sock(ks_socket_t sock, uint32_t ms, ks_poll_t flags); + +KS_DECLARE(unsigned int) ks_separate_string_string(char *buf, const char *delim, char **array, unsigned int arraylen); + +#define ks_recv(_h) ks_recv_event(_h, 0, NULL) +#define ks_recv_timed(_h, _ms) ks_recv_event_timed(_h, _ms, 0, NULL) + +static __inline__ int ks_safe_strcasecmp(const char *s1, const char *s2) +{ + if (!(s1 && s2)) { + return 1; + } + + return strcasecmp(s1, s2); +} + +#ifdef __cplusplus +} +#endif /* defined(__cplusplus) */ + + +#endif /* defined(_KS_H_) */ + +/* 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: + */ diff --git a/libs/libks/src/include/ks_buffer.h b/libs/libks/src/include/ks_buffer.h new file mode 100644 index 0000000000..83426c9885 --- /dev/null +++ b/libs/libks/src/include/ks_buffer.h @@ -0,0 +1,146 @@ +/* + * Copyright (c) 2010-2012, Anthony Minessale II + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name of the original author; nor the names of any contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "ks.h" +#ifndef KS_BUFFER_H +#define KS_BUFFER_H +/** + * @defgroup ks_buffer Buffer Routines + * @ingroup buffer + * The purpose of this module is to make a plain buffering interface that can be used for read/write buffers + * throughout the application. + * @{ + */ +struct ks_buffer; +typedef struct ks_buffer ks_buffer_t; + +/*! \brief Allocate a new dynamic ks_buffer + * \param buffer returned pointer to the new buffer + * \param blocksize length to realloc by as data is added + * \param start_len ammount of memory to reserve initially + * \param max_len length the buffer is allowed to grow to + * \return status + */ +KS_DECLARE(ks_status_t) ks_buffer_create(ks_buffer_t **buffer, ks_size_t blocksize, ks_size_t start_len, ks_size_t max_len); + +/*! \brief Get the length of a ks_buffer_t + * \param buffer any buffer of type ks_buffer_t + * \return int size of the buffer. + */ +KS_DECLARE(ks_size_t) ks_buffer_len(ks_buffer_t *buffer); + +/*! \brief Get the freespace of a ks_buffer_t + * \param buffer any buffer of type ks_buffer_t + * \return int freespace in the buffer. + */ +KS_DECLARE(ks_size_t) ks_buffer_freespace(ks_buffer_t *buffer); + +/*! \brief Get the in use amount of a ks_buffer_t + * \param buffer any buffer of type ks_buffer_t + * \return int ammount of buffer curently in use + */ +KS_DECLARE(ks_size_t) ks_buffer_inuse(ks_buffer_t *buffer); + +/*! \brief Read data from a ks_buffer_t up to the ammount of datalen if it is available. Remove read data from buffer. + * \param buffer any buffer of type ks_buffer_t + * \param data pointer to the read data to be returned + * \param datalen amount of data to be returned + * \return int ammount of data actually read + */ +KS_DECLARE(ks_size_t) ks_buffer_read(ks_buffer_t *buffer, void *data, ks_size_t datalen); + +KS_DECLARE(ks_size_t) ks_buffer_read_packet(ks_buffer_t *buffer, void *data, ks_size_t maxlen); +KS_DECLARE(ks_size_t) ks_buffer_packet_count(ks_buffer_t *buffer); + +/*! \brief Read data endlessly from a ks_buffer_t + * \param buffer any buffer of type ks_buffer_t + * \param data pointer to the read data to be returned + * \param datalen amount of data to be returned + * \return int ammount of data actually read + * \note Once you have read all the data from the buffer it will loop around. + */ +KS_DECLARE(ks_size_t) ks_buffer_read_loop(ks_buffer_t *buffer, void *data, ks_size_t datalen); + +/*! \brief Assign a number of loops to read + * \param buffer any buffer of type ks_buffer_t + * \param loops the number of loops (-1 for infinite) + */ +KS_DECLARE(void) ks_buffer_set_loops(ks_buffer_t *buffer, int32_t loops); + +/*! \brief Write data into a ks_buffer_t up to the length of datalen + * \param buffer any buffer of type ks_buffer_t + * \param data pointer to the data to be written + * \param datalen amount of data to be written + * \return int amount of buffer used after the write, or 0 if no space available + */ +KS_DECLARE(ks_size_t) ks_buffer_write(ks_buffer_t *buffer, const void *data, ks_size_t datalen); + +/*! \brief Remove data from the buffer + * \param buffer any buffer of type ks_buffer_t + * \param datalen amount of data to be removed + * \return int size of buffer, or 0 if unable to toss that much data + */ +KS_DECLARE(ks_size_t) ks_buffer_toss(ks_buffer_t *buffer, ks_size_t datalen); + +/*! \brief Remove all data from the buffer + * \param buffer any buffer of type ks_buffer_t + */ +KS_DECLARE(void) ks_buffer_zero(ks_buffer_t *buffer); + +/*! \brief Destroy the buffer + * \param buffer buffer to destroy + * \note only neccessary on dynamic buffers (noop on pooled ones) + */ +KS_DECLARE(void) ks_buffer_destroy(ks_buffer_t **buffer); + +/*! \brief Seek to offset from the beginning of the buffer + * \param buffer buffer to seek + * \param datalen offset in bytes + * \return new position + */ +KS_DECLARE(ks_size_t) ks_buffer_seek(ks_buffer_t *buffer, ks_size_t datalen); + +/** @} */ + +KS_DECLARE(ks_size_t) ks_buffer_zwrite(ks_buffer_t *buffer, const void *data, ks_size_t datalen); + +#endif +/* 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: + */ diff --git a/libs/libks/src/include/ks_config.h b/libs/libks/src/include/ks_config.h new file mode 100644 index 0000000000..0a90bde078 --- /dev/null +++ b/libs/libks/src/include/ks_config.h @@ -0,0 +1,178 @@ +/* + * Copyright (c) 2007-2012, Anthony Minessale II + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name of the original author; nor the names of any contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @defgroup config Config File Parser + * @ingroup config + * This module implements a basic interface and file format parser + * + *
+ *
+ * EXAMPLE 
+ * 
+ * [category1]
+ * var1 => val1
+ * var2 => val2
+ * \# lines that begin with \# are comments
+ * \#var3 => val3
+ * 
+ * @{ + */ + +#ifndef KS_CONFIG_H +#define KS_CONFIG_H + +#include "ks.h" + +#ifdef __cplusplus +extern "C" { +#endif /* defined(__cplusplus) */ + + +#define KS_URL_SEPARATOR "://" + + +#ifdef WIN32 +#define KS_PATH_SEPARATOR "\\" +#ifndef KS_CONFIG_DIR +#define KS_CONFIG_DIR "c:\\openks" +#endif +#define ks_is_file_path(file) (*(file +1) == ':' || *file == '/' || strstr(file, SWITCH_URL_SEPARATOR)) +#else +#define KS_PATH_SEPARATOR "/" +#ifndef KS_CONFIG_DIR +#define KS_CONFIG_DIR "/etc/openks" +#endif +#define ks_is_file_path(file) ((*file == '/') || strstr(file, SWITCH_URL_SEPARATOR)) +#endif + +/*! + \brief Evaluate the truthfullness of a string expression + \param expr a string expression + \return true or false +*/ +#define ks_true(expr)\ +(expr && ( !strcasecmp(expr, "yes") ||\ +!strcasecmp(expr, "on") ||\ +!strcasecmp(expr, "true") ||\ +!strcasecmp(expr, "enabled") ||\ +!strcasecmp(expr, "active") ||\ +!strcasecmp(expr, "allow") ||\ +atoi(expr))) ? 1 : 0 + +/*! + \brief Evaluate the falsefullness of a string expression + \param expr a string expression + \return true or false +*/ +#define ks_false(expr)\ +(expr && ( !strcasecmp(expr, "no") ||\ +!strcasecmp(expr, "off") ||\ +!strcasecmp(expr, "false") ||\ +!strcasecmp(expr, "disabled") ||\ +!strcasecmp(expr, "inactive") ||\ +!strcasecmp(expr, "disallow") ||\ +!atoi(expr))) ? 1 : 0 + +typedef struct ks_config ks_config_t; + +/*! \brief A simple file handle representing an open configuration file **/ +struct ks_config { + /*! FILE stream buffer to the opened file */ + FILE *file; + /*! path to the file */ + char path[512]; + /*! current category */ + char category[256]; + /*! current section */ + char section[256]; + /*! buffer of current line being read */ + char buf[1024]; + /*! current line number in file */ + int lineno; + /*! current category number in file */ + int catno; + /*! current section number in file */ + int sectno; + + int lockto; +}; + +/*! + \brief Open a configuration file + \param cfg (ks_config_t *) config handle to use + \param file_path path to the file + \return 1 (true) on success 0 (false) on failure +*/ +KS_DECLARE(int) ks_config_open_file(ks_config_t * cfg, const char *file_path); + +/*! + \brief Close a previously opened configuration file + \param cfg (ks_config_t *) config handle to use +*/ +KS_DECLARE(void) ks_config_close_file(ks_config_t * cfg); + +/*! + \brief Retrieve next name/value pair from configuration file + \param cfg (ks_config_t *) config handle to use + \param var pointer to aim at the new variable name + \param val pointer to aim at the new value +*/ +KS_DECLARE(int) ks_config_next_pair(ks_config_t * cfg, char **var, char **val); + +/*! + \brief Retrieve the CAS bits from a configuration string value + \param strvalue pointer to the configuration string value (expected to be in format whatever:xxxx) + \param outbits pointer to aim at the CAS bits +*/ +KS_DECLARE(int) ks_config_get_cas_bits(char *strvalue, unsigned char *outbits); + + +/** @} */ + +#ifdef __cplusplus +} +#endif /* defined(__cplusplus) */ + +#endif /* defined(KS_CONFIG_H) */ + +/* 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: + */ diff --git a/libs/libks/src/include/ks_json.h b/libs/libks/src/include/ks_json.h new file mode 100755 index 0000000000..1ad116e980 --- /dev/null +++ b/libs/libks/src/include/ks_json.h @@ -0,0 +1,127 @@ +/* + Copyright (c) 2009 Dave Gamble + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +*/ +#include "ks.h" +#ifndef cJSON__h +#define cJSON__h + +#ifdef __cplusplus +extern "C" +{ +#endif + +/* cJSON Types: */ +#define cJSON_False 0 +#define cJSON_True 1 +#define cJSON_NULL 2 +#define cJSON_Number 3 +#define cJSON_String 4 +#define cJSON_Array 5 +#define cJSON_Object 6 + +#define cJSON_IsReference 256 + +/* The cJSON structure: */ +typedef struct cJSON { + struct cJSON *next,*prev; /* next/prev allow you to walk array/object chains. Alternatively, use GetArraySize/GetArrayItem/GetObjectItem */ + struct cJSON *child; /* An array or object item will have a child pointer pointing to a chain of the items in the array/object. */ + + int type; /* The type of the item, as above. */ + + char *valuestring; /* The item's string, if type==cJSON_String */ + int valueint; /* The item's number, if type==cJSON_Number */ + double valuedouble; /* The item's number, if type==cJSON_Number */ + + char *string; /* The item's name string, if this item is the child of, or is in the list of subitems of an object. */ +} cJSON; + +typedef struct cJSON_Hooks { + void *(*malloc_fn)(size_t sz); + void (*free_fn)(void *ptr); +} cJSON_Hooks; + +/* Supply malloc, realloc and free functions to cJSON */ +KS_DECLARE(void) cJSON_InitHooks(cJSON_Hooks* hooks); + + +/* Supply a block of JSON, and this returns a cJSON object you can interrogate. Call cJSON_Delete when finished. */ +KS_DECLARE(cJSON *)cJSON_Parse(const char *value); +/* Render a cJSON entity to text for transfer/storage. Free the char* when finished. */ +KS_DECLARE(char *)cJSON_Print(cJSON *item); +/* Render a cJSON entity to text for transfer/storage without any formatting. Free the char* when finished. */ +KS_DECLARE(char *)cJSON_PrintUnformatted(cJSON *item); +/* Delete a cJSON entity and all subentities. */ +KS_DECLARE(void) cJSON_Delete(cJSON *c); + +/* Returns the number of items in an array (or object). */ +KS_DECLARE(int) cJSON_GetArraySize(cJSON *array); +/* Retrieve item number "item" from array "array". Returns NULL if unsuccessful. */ +KS_DECLARE(cJSON *)cJSON_GetArrayItem(cJSON *array,int item); +/* Get item "string" from object. Case insensitive. */ +KS_DECLARE(cJSON *)cJSON_GetObjectItem(cJSON *object,const char *string); + +/* For analysing failed parses. This returns a pointer to the parse error. You'll probably need to look a few chars back to make sense of it. Defined when cJSON_Parse() returns 0. 0 when cJSON_Parse() succeeds. */ +KS_DECLARE(const char *)cJSON_GetErrorPtr(); + +/* These calls create a cJSON item of the appropriate type. */ +KS_DECLARE(cJSON *)cJSON_CreateNull(); +KS_DECLARE(cJSON *)cJSON_CreateTrue(); +KS_DECLARE(cJSON *)cJSON_CreateFalse(); +KS_DECLARE(cJSON *)cJSON_CreateBool(int b); +KS_DECLARE(cJSON *)cJSON_CreateNumber(double num); +KS_DECLARE(cJSON *)cJSON_CreateString(const char *string); +KS_DECLARE(cJSON *)cJSON_CreateArray(); +KS_DECLARE(cJSON *)cJSON_CreateObject(); + +/* These utilities create an Array of count items. */ +KS_DECLARE(cJSON *)cJSON_CreateIntArray(int *numbers,int count); +KS_DECLARE(cJSON *)cJSON_CreateFloatArray(float *numbers,int count); +KS_DECLARE(cJSON *)cJSON_CreateDoubleArray(double *numbers,int count); +KS_DECLARE(cJSON *)cJSON_CreateStringArray(const char **strings,int count); + +/* Append item to the specified array/object. */ +KS_DECLARE(void) cJSON_AddItemToArray(cJSON *array, cJSON *item); +KS_DECLARE(void) cJSON_AddItemToObject(cJSON *object,const char *string,cJSON *item); +/* Append reference to item to the specified array/object. Use this when you want to add an existing cJSON to a new cJSON, but don't want to corrupt your existing cJSON. */ +KS_DECLARE(void) cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item); +KS_DECLARE(void) cJSON_AddItemReferenceToObject(cJSON *object,const char *string,cJSON *item); + +/* Remove/Detatch items from Arrays/Objects. */ +KS_DECLARE(cJSON *)cJSON_DetachItemFromArray(cJSON *array,int which); +KS_DECLARE(void) cJSON_DeleteItemFromArray(cJSON *array,int which); +KS_DECLARE(cJSON *)cJSON_DetachItemFromObject(cJSON *object,const char *string); +KS_DECLARE(void) cJSON_DeleteItemFromObject(cJSON *object,const char *string); + +/* Update array items. */ +KS_DECLARE(void) cJSON_ReplaceItemInArray(cJSON *array,int which,cJSON *newitem); +KS_DECLARE(void) cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem); + +#define cJSON_AddNullToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateNull()) +#define cJSON_AddTrueToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateTrue()) +#define cJSON_AddFalseToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateFalse()) +#define cJSON_AddNumberToObject(object,name,n) cJSON_AddItemToObject(object, name, cJSON_CreateNumber(n)) +#define cJSON_AddStringToObject(object,name,s) cJSON_AddItemToObject(object, name, cJSON_CreateString(s)) + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/libs/libks/src/include/ks_threadmutex.h b/libs/libks/src/include/ks_threadmutex.h new file mode 100644 index 0000000000..2b12acaccd --- /dev/null +++ b/libs/libks/src/include/ks_threadmutex.h @@ -0,0 +1,58 @@ +/* + * Cross Platform Thread/Mutex abstraction + * Copyright(C) 2007 Michael Jerris + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so. + * + * This work is provided under this license on an "as is" basis, without warranty of any kind, + * either expressed or implied, including, without limitation, warranties that the covered code + * is free of defects, merchantable, fit for a particular purpose or non-infringing. The entire + * risk as to the quality and performance of the covered code is with you. Should any covered + * code prove defective in any respect, you (not the initial developer or any other contributor) + * assume the cost of any necessary servicing, repair or correction. This disclaimer of warranty + * constitutes an essential part of this license. No use of any covered code is authorized hereunder + * except under this disclaimer. + * + */ + + +#ifndef _KS_THREADMUTEX_H +#define _KS_THREADMUTEX_H + +#include "ks.h" + +#ifdef __cplusplus +extern "C" { +#endif /* defined(__cplusplus) */ + +typedef struct ks_mutex ks_mutex_t; +typedef struct ks_thread ks_thread_t; +typedef void *(*ks_thread_function_t) (ks_thread_t *, void *); + +KS_DECLARE(ks_status_t) ks_thread_create_detached(ks_thread_function_t func, void *data); +ks_status_t ks_thread_create_detached_ex(ks_thread_function_t func, void *data, size_t stack_size); +void ks_thread_override_default_stacksize(size_t size); +KS_DECLARE(ks_status_t) ks_mutex_create(ks_mutex_t **mutex); +KS_DECLARE(ks_status_t) ks_mutex_destroy(ks_mutex_t **mutex); +KS_DECLARE(ks_status_t) ks_mutex_lock(ks_mutex_t *mutex); +KS_DECLARE(ks_status_t) ks_mutex_trylock(ks_mutex_t *mutex); +KS_DECLARE(ks_status_t) ks_mutex_unlock(ks_mutex_t *mutex); + +#ifdef __cplusplus +} +#endif /* defined(__cplusplus) */ + +#endif /* defined(_KS_THREADMUTEX_H) */ + +/* 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: + */ diff --git a/libs/libks/src/include/mpool.h b/libs/libks/src/include/mpool.h new file mode 100644 index 0000000000..23ac93fb91 --- /dev/null +++ b/libs/libks/src/include/mpool.h @@ -0,0 +1,463 @@ +/* + * Memory pool defines. + * + * Copyright 1996 by Gray Watson. + * + * This file is part of the mpool package. + * + * Permission to use, copy, modify, and distribute this software for + * any purpose and without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies, and that the name of Gray Watson not be used in advertising + * or publicity pertaining to distribution of the document or software + * without specific, written prior permission. + * + * Gray Watson makes no representations about the suitability of the + * software described herein for any purpose. It is provided "as is" + * without express or implied warranty. + * + * The author may be reached via http://256.com/gray/ + * + * $Id: mpool.h,v 1.4 2006/05/31 20:26:11 gray Exp $ + */ + +#ifndef __MPOOL_H__ +#define __MPOOL_H__ + +#include + +/* + * mpool flags to mpool_alloc or mpool_set_attr + */ + +/* + * Choose a best fit algorithm not first fit. This takes more CPU + * time but will result in a tighter heap. + */ +#define MPOOL_FLAG_BEST_FIT (1<<0) + +/* + * By default the library adds 2 bytes onto all allocations to insert + * a magic number that it can look for to determine how large a freed + * memory chunk is. This flag indicates that few if any frees are + * going to be performed on the pool and to not waste memory on these + * bytes. + */ +#define MPOOL_FLAG_NO_FREE (1<<1) + +/* + * This enables very heavy packing at the possible expense of CPU. + * This affects a number of parts of the library. + * + * By default the 1st page of memory is reserved for the main mpool + * structure. This flag will cause the rest of the 1st block to be + * available for use as user memory. + * + * By default the library looks through the memory when freed looking + * for a magic value. There is an internal max size that it will look + * and then it will give up. This flag forces it to look until it + * finds it. + */ +#define MPOOL_FLAG_HEAVY_PACKING (1<<2) + +/* + * Use sbrk not mmap to allocate pages. This is not recommended for + * normal use. + */ +#define MPOOL_FLAG_USE_SBRK (1<<3) + +/* + * Mpool error codes + */ +#define MPOOL_ERROR_NONE 1 /* no error */ +#define MPOOL_ERROR_ARG_NULL 2 /* function argument is null */ +#define MPOOL_ERROR_ARG_INVALID 3 /* function argument is invalid */ +#define MPOOL_ERROR_PNT 4 /* invalid mpool pointer */ +#define MPOOL_ERROR_POOL_OVER 5 /* mpool structure was overwritten */ +#define MPOOL_ERROR_PAGE_SIZE 6 /* could not get system page-size */ +#define MPOOL_ERROR_OPEN_ZERO 7 /* could not open /dev/zero */ +#define MPOOL_ERROR_NO_MEM 8 /* no memory available */ +#define MPOOL_ERROR_MMAP 9 /* problems with mmap */ +#define MPOOL_ERROR_SIZE 10 /* error processing requested size */ +#define MPOOL_ERROR_TOO_BIG 11 /* allocation exceeded max size */ +#define MPOOL_ERROR_MEM 12 /* invalid memory address */ +#define MPOOL_ERROR_MEM_OVER 13 /* memory lower bounds overwritten */ +#define MPOOL_ERROR_NOT_FOUND 14 /* memory block not found in pool */ +#define MPOOL_ERROR_IS_FREE 15 /* memory block already free */ +#define MPOOL_ERROR_BLOCK_STAT 16 /* invalid internal block status */ +#define MPOOL_ERROR_FREE_ADDR 17 /* invalid internal free address */ +#define MPOOL_ERROR_SBRK_CONTIG 18 /* sbrk did not return contiguous mem*/ +#define MPOOL_ERROR_NO_PAGES 19 /* ran out of pages in pool */ +#define MPOOL_ERROR_ALLOC 20 /* calloc,malloc,free,realloc failed */ +#define MPOOL_ERROR_PNT_OVER 21 /* pointer structure was overwritten */ + +/* + * Mpool function IDs for the mpool_log_func callback function. + */ +#define MPOOL_FUNC_CLOSE 1 /* mpool_close function called */ +#define MPOOL_FUNC_CLEAR 2 /* mpool_clear function called */ +#define MPOOL_FUNC_ALLOC 3 /* mpool_alloc function called */ +#define MPOOL_FUNC_CALLOC 4 /* mpool_calloc function called */ +#define MPOOL_FUNC_FREE 5 /* mpool_free function called */ +#define MPOOL_FUNC_RESIZE 6 /* mpool_resize function called */ + +/* + * void mpool_log_func_t + * + * DESCRIPTION: + * + * Mpool transaction log function. + * + * RETURNS: + * + * None. + * + * ARGUMENT: + * + * mp_p -> Associated mpool address. + * + * func_id -> Integer function ID which identifies which mpool + * function is being called. + * + * byte_size -> Optionally specified byte size. + * + * ele_n -> Optionally specified element number. For mpool_calloc + * only. + * + * new_addr -> Optionally specified new address. For mpool_alloc, + * mpool_calloc, and mpool_resize only. + * + * old_addr -> Optionally specified old address. For mpool_resize and + * mpool_free only. + * + * old_byte_size -> Optionally specified old byte size. For + * mpool_resize only. + */ +typedef void (*mpool_log_func_t)(const void *mp_p, + const int func_id, + const unsigned long byte_size, + const unsigned long ele_n, + const void *old_addr, const void *new_addr, + const unsigned long old_byte_size); + +#ifdef MPOOL_MAIN + +#include "mpool_loc.h" + +#else + +/* generic mpool type */ +typedef void mpool_t; + +#endif + +/*<<<<<<<<<< The below prototypes are auto-generated by fillproto */ + +/* + * mpool_t *mpool_open + * + * DESCRIPTION: + * + * Open/allocate a new memory pool. + * + * RETURNS: + * + * Success - Pool pointer which must be passed to mpool_close to + * deallocate. + * + * Failure - NULL + * + * ARGUMENTS: + * + * flags -> Flags to set attributes of the memory pool. See the top + * of mpool.h. + * + * page_size -> Set the internal memory page-size. This must be a + * multiple of the getpagesize() value. Set to 0 for the default. + * + * start_addr -> Starting address to try and allocate memory pools. + * This is ignored if the MPOOL_FLAG_USE_SBRK is enabled. + * + * error_p <- Pointer to integer which, if not NULL, will be set with + * a mpool error code. + */ +extern +mpool_t *mpool_open(const unsigned int flags, const unsigned int page_size, + void *start_addr, int *error_p); + +/* + * int mpool_close + * + * DESCRIPTION: + * + * Close/free a memory allocation pool previously opened with + * mpool_open. + * + * RETURNS: + * + * Success - MPOOL_ERROR_NONE + * + * Failure - Mpool error code + * + * ARGUMENTS: + * + * mp_p <-> Pointer to our memory pool. + */ +extern +int mpool_close(mpool_t *mp_p); + +/* + * int mpool_clear + * + * DESCRIPTION: + * + * Wipe an opened memory pool clean so we can start again. + * + * RETURNS: + * + * Success - MPOOL_ERROR_NONE + * + * Failure - Mpool error code + * + * ARGUMENTS: + * + * mp_p <-> Pointer to our memory pool. + */ +extern +int mpool_clear(mpool_t *mp_p); + +/* + * void *mpool_alloc + * + * DESCRIPTION: + * + * Allocate space for bytes inside of an already open memory pool. + * + * RETURNS: + * + * Success - Pointer to the address to use. + * + * Failure - NULL + * + * ARGUMENTS: + * + * mp_p <-> Pointer to the memory pool. If NULL then it will do a + * normal malloc. + * + * byte_size -> Number of bytes to allocate in the pool. Must be >0. + * + * error_p <- Pointer to integer which, if not NULL, will be set with + * a mpool error code. + */ +extern +void *mpool_alloc(mpool_t *mp_p, const unsigned long byte_size, + int *error_p); + +/* + * void *mpool_calloc + * + * DESCRIPTION: + * + * Allocate space for elements of bytes in the memory pool and zero + * the space afterwards. + * + * RETURNS: + * + * Success - Pointer to the address to use. + * + * Failure - NULL + * + * ARGUMENTS: + * + * mp_p <-> Pointer to the memory pool. If NULL then it will do a + * normal calloc. + * + * ele_n -> Number of elements to allocate. + * + * ele_size -> Number of bytes per element being allocated. + * + * error_p <- Pointer to integer which, if not NULL, will be set with + * a mpool error code. + */ +extern +void *mpool_calloc(mpool_t *mp_p, const unsigned long ele_n, + const unsigned long ele_size, int *error_p); + +/* + * int mpool_free + * + * DESCRIPTION: + * + * Free an address from a memory pool. + * + * RETURNS: + * + * Success - MPOOL_ERROR_NONE + * + * Failure - Mpool error code + * + * ARGUMENTS: + * + * mp_p <-> Pointer to the memory pool. If NULL then it will do a + * normal free. + * + * addr <-> Address to free. + * + * size -> Size of the address being freed. + */ +extern +int mpool_free(mpool_t *mp_p, void *addr, const unsigned long size); + +/* + * void *mpool_resize + * + * DESCRIPTION: + * + * Reallocate an address in a mmeory pool to a new size. This is + * different from realloc in that it needs the old address' size. If + * you don't have it then you need to allocate new space, copy the + * data, and free the old pointer yourself. + * + * RETURNS: + * + * Success - Pointer to the address to use. + * + * Failure - NULL + * + * ARGUMENTS: + * + * mp_p <-> Pointer to the memory pool. If NULL then it will do a + * normal realloc. + * + * old_addr -> Previously allocated address. + * + * old_byte_size -> Size of the old address. Must be known, cannot be + * 0. + * + * new_byte_size -> New size of the allocation. + * + * error_p <- Pointer to integer which, if not NULL, will be set with + * a mpool error code. + */ +extern +void *mpool_resize(mpool_t *mp_p, void *old_addr, + const unsigned long old_byte_size, + const unsigned long new_byte_size, + int *error_p); + +/* + * int mpool_stats + * + * DESCRIPTION: + * + * Return stats from the memory pool. + * + * RETURNS: + * + * Success - MPOOL_ERROR_NONE + * + * Failure - Mpool error code + * + * ARGUMENTS: + * + * mp_p -> Pointer to the memory pool. + * + * page_size_p <- Pointer to an unsigned integer which, if not NULL, + * will be set to the page-size of the pool. + * + * num_alloced_p <- Pointer to an unsigned long which, if not NULL, + * will be set to the number of pointers currently allocated in pool. + * + * user_alloced_p <- Pointer to an unsigned long which, if not NULL, + * will be set to the number of user bytes allocated in this pool. + * + * max_alloced_p <- Pointer to an unsigned long which, if not NULL, + * will be set to the maximum number of user bytes that have been + * allocated in this pool. + * + * tot_alloced_p <- Pointer to an unsigned long which, if not NULL, + * will be set to the total amount of space (including administrative + * overhead) used by the pool. + */ +extern +int mpool_stats(const mpool_t *mp_p, unsigned int *page_size_p, + unsigned long *num_alloced_p, + unsigned long *user_alloced_p, + unsigned long *max_alloced_p, + unsigned long *tot_alloced_p); + +/* + * int mpool_set_log_func + * + * DESCRIPTION: + * + * Set a logging callback function to be called whenever there was a + * memory transaction. See mpool_log_func_t. + * + * RETURNS: + * + * Success - MPOOL_ERROR_NONE + * + * Failure - Mpool error code + * + * ARGUMENTS: + * + * mp_p <-> Pointer to the memory pool. + * + * log_func -> Log function (defined in mpool.h) which will be called + * with each mpool transaction. + */ +extern +int mpool_set_log_func(mpool_t *mp_p, mpool_log_func_t log_func); + +/* + * int mpool_set_max_pages + * + * DESCRIPTION: + * + * Set the maximum number of pages that the library will use. Once it + * hits the limit it will return MPOOL_ERROR_NO_PAGES. + * + * NOTE: if the MPOOL_FLAG_HEAVY_PACKING is set then this max-pages + * value will include the page with the mpool header structure in it. + * If the flag is _not_ set then the max-pages will not include this + * first page. + * + * RETURNS: + * + * Success - MPOOL_ERROR_NONE + * + * Failure - Mpool error code + * + * ARGUMENTS: + * + * mp_p <-> Pointer to the memory pool. + * + * max_pages -> Maximum number of pages used by the library. + */ +extern +int mpool_set_max_pages(mpool_t *mp_p, const unsigned int max_pages); + +/* + * const char *mpool_strerror + * + * DESCRIPTION: + * + * Return the corresponding string for the error number. + * + * RETURNS: + * + * Success - String equivalient of the error. + * + * Failure - String "invalid error code" + * + * ARGUMENTS: + * + * error -> Error number that we are converting. + */ +extern +const char *mpool_strerror(const int error); + +/*<<<<<<<<<< This is end of the auto-generated output from fillproto. */ + +#endif /* ! __MPOOL_H__ */ diff --git a/libs/libks/src/include/mpool_loc.h b/libs/libks/src/include/mpool_loc.h new file mode 100644 index 0000000000..3d33f5d927 --- /dev/null +++ b/libs/libks/src/include/mpool_loc.h @@ -0,0 +1,116 @@ +/* + * Memory pool local defines. + * + * Copyright 1996 by Gray Watson. + * + * This file is part of the mpool package. + * + * Permission to use, copy, modify, and distribute this software for + * any purpose and without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies, and that the name of Gray Watson not be used in advertising + * or publicity pertaining to distribution of the document or software + * without specific, written prior permission. + * + * Gray Watson makes no representations about the suitability of the + * software described herein for any purpose. It is provided "as is" + * without express or implied warranty. + * + * The author may be reached via http://256.com/gray/ + * + * $Id: mpool_loc.h,v 1.2 2005/05/20 20:08:54 gray Exp $ + */ + +#ifndef __MPOOL_LOC_H__ +#define __MPOOL_LOC_H__ + +#define MPOOL_MAGIC 0xABACABA /* magic for struct */ +#define BLOCK_MAGIC 0xB1B1007 /* magic for blocks */ +#define FENCE_MAGIC0 (unsigned char)(0xFAU) /* 1st magic mem byte */ +#define FENCE_MAGIC1 (unsigned char)(0xD3U) /* 2nd magic mem byte */ + +#define FENCE_SIZE 2 /* fence space */ +#define MIN_ALLOCATION (sizeof(mpool_free_t)) /* min alloc */ +#define MAX_FREE_SEARCH 10240 /* max size to search */ +#define MAX_FREE_LIST_SEARCH 100 /* max looking for free mem */ + +/* + * bitflag tools for Variable and a Flag + */ +#define BIT_FLAG(x) (1 << (x)) +#define BIT_SET(v,f) (v) |= (f) +#define BIT_CLEAR(v,f) (v) &= ~(f) +#define BIT_IS_SET(v,f) ((v) & (f)) +#define BIT_TOGGLE(v,f) (v) ^= (f) + +#define SET_POINTER(pnt, val) \ + do { \ + if ((pnt) != NULL) { \ + (*(pnt)) = (val); \ + } \ + } while(0) + +#define BLOCK_FLAG_USED BIT_FLAG(0) /* block is used */ +#define BLOCK_FLAG_FREE BIT_FLAG(1) /* block is free */ + +#define DEFAULT_PAGE_MULT 16 /* pagesize = this * getpagesize*/ + +/* How many pages SIZE bytes resides in. We add in the block header. */ +#define PAGES_IN_SIZE(mp_p, size) (((size) + sizeof(mpool_block_t) + \ + (mp_p)->mp_page_size - 1) / \ + (mp_p)->mp_page_size) +#define SIZE_OF_PAGES(mp_p, page_n) ((page_n) * (mp_p)->mp_page_size) +#define MAX_BITS 30 /* we only can allocate 1gb chunks */ + +#define MAX_BLOCK_USER_MEMORY(mp_p) ((mp_p)->mp_page_size - \ + sizeof(mpool_block_t)) +#define FIRST_ADDR_IN_BLOCK(block_p) (void *)((char *)(block_p) + \ + sizeof(mpool_block_t)) +#define MEMORY_IN_BLOCK(block_p) ((char *)(block_p)->mb_bounds_p - \ + ((char *)(block_p) + \ + sizeof(mpool_block_t))) + +typedef struct { + unsigned int mp_magic; /* magic number for struct */ + unsigned int mp_flags; /* flags for the struct */ + unsigned long mp_alloc_c; /* number of allocations */ + unsigned long mp_user_alloc; /* user bytes allocated */ + unsigned long mp_max_alloc; /* maximum user bytes allocated */ + unsigned int mp_page_c; /* number of pages allocated */ + unsigned int mp_max_pages; /* maximum number of pages to use */ + unsigned int mp_page_size; /* page-size of our system */ + int mp_fd; /* fd for /dev/zero if mmap-ing */ + off_t mp_top; /* top of our allocations in fd */ + mpool_log_func_t mp_log_func; /* log callback function */ + void *mp_addr; /* current address for mmaping */ + void *mp_min_p; /* min address in pool for checks */ + void *mp_bounds_p; /* max address in pool for checks */ + struct mpool_block_st *mp_first_p; /* first memory block we are using */ + struct mpool_block_st *mp_last_p; /* last memory block we are using */ + struct mpool_block_st *mp_free[MAX_BITS + 1]; /* free lists based on size */ + unsigned int mp_magic2; /* upper magic for overwrite sanity */ +} mpool_t; + +/* for debuggers to be able to interrogate the generic type in the .h file */ +typedef mpool_t mpool_ext_t; + +/* + * Block header structure. This structure *MUST* be long-word + * aligned. + */ +typedef struct mpool_block_st { + unsigned int mb_magic; /* magic number for block header */ + void *mb_bounds_p; /* block boundary location */ + struct mpool_block_st *mb_next_p; /* linked list next pointer */ + unsigned int mb_magic2; /* upper magic for overwrite sanity */ +} mpool_block_t; + +/* + * Free list structure. + */ +typedef struct { + void *mf_next_p; /* pointer to the next free address */ + unsigned long mf_size; /* size of the free block */ +} mpool_free_t; + +#endif /* ! __MPOOL_LOC_H__ */ diff --git a/libs/libks/src/include/simclist.h b/libs/libks/src/include/simclist.h new file mode 100755 index 0000000000..2ce9d491ad --- /dev/null +++ b/libs/libks/src/include/simclist.h @@ -0,0 +1,980 @@ +/* + * Copyright (c) 2007,2008 Mij + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + + +/* + * SimCList library. See http://mij.oltrelinux.com/devel/simclist + */ + + +#ifndef SIMCLIST_H +#define SIMCLIST_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include + +#ifndef SIMCLIST_NO_DUMPRESTORE +# ifndef _WIN32 +# include /* list_dump_info_t's struct timeval */ +# else +# include +# endif +#endif + + +/* Be friend of both C90 and C99 compilers */ +#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L + /* "inline" and "restrict" are keywords */ +#else +# define inline /* inline */ +# define restrict /* restrict */ +#endif + + +/** + * Type representing list hashes. + * + * This is a signed integer value. + */ +typedef int32_t list_hash_t; + +#ifndef SIMCLIST_NO_DUMPRESTORE +typedef struct { + uint16_t version; /* dump version */ + struct timeval timestamp; /* when the list has been dumped, seconds since UNIX epoch */ + uint32_t list_size; + uint32_t list_numels; + list_hash_t list_hash; /* hash of the list when dumped, or 0 if invalid */ + uint32_t dumpsize; + int consistent; /* 1 if the dump is verified complete/consistent; 0 otherwise */ +} list_dump_info_t; +#endif + +/** + * a comparator of elements. + * + * A comparator of elements is a function that: + * -# receives two references to elements a and b + * -# returns {<0, 0, >0} if (a > b), (a == b), (a < b) respectively + * + * It is responsability of the function to handle possible NULL values. + */ +typedef int (*element_comparator)(const void *a, const void *b); + +/** + * a seeker of elements. + * + * An element seeker is a function that: + * -# receives a reference to an element el + * -# receives a reference to some indicator data + * -# returns non-0 if the element matches the indicator, 0 otherwise + * + * It is responsability of the function to handle possible NULL values in any + * argument. + */ +typedef int (*element_seeker)(const void *el, const void *indicator); + +/** + * an element lenght meter. + * + * An element meter is a function that: + * -# receives the reference to an element el + * -# returns its size in bytes + * + * It is responsability of the function to handle possible NULL values. + */ +typedef size_t (*element_meter)(const void *el); + +/** + * a function computing the hash of elements. + * + * An hash computing function is a function that: + * -# receives the reference to an element el + * -# returns a hash value for el + * + * It is responsability of the function to handle possible NULL values. + */ +typedef list_hash_t (*element_hash_computer)(const void *el); + +/** + * a function for serializing an element. + * + * A serializer function is one that gets a reference to an element, + * and returns a reference to a buffer that contains its serialization + * along with the length of this buffer. + * It is responsability of the function to handle possible NULL values, + * returning a NULL buffer and a 0 buffer length. + * + * These functions have 3 goals: + * -# "freeze" and "flatten" the memory representation of the element + * -# provide a portable (wrt byte order, or type size) representation of the element, if the dump can be used on different sw/hw combinations + * -# possibly extract a compressed representation of the element + * + * @param el reference to the element data + * @param serialize_buffer reference to fill with the length of the buffer + * @return reference to the buffer with the serialized data + */ +typedef void *(*element_serializer)(const void *restrict el, uint32_t *restrict serializ_len); + +/** + * a function for un-serializing an element. + * + * An unserializer function accomplishes the inverse operation of the + * serializer function. An unserializer function is one that gets a + * serialized representation of an element and turns it backe to the original + * element. The serialized representation is passed as a reference to a buffer + * with its data, and the function allocates and returns the buffer containing + * the original element, and it sets the length of this buffer into the + * integer passed by reference. + * + * @param data reference to the buffer with the serialized representation of the element + * @param data_len reference to the location where to store the length of the data in the buffer returned + * @return reference to a buffer with the original, unserialized representation of the element + */ +typedef void *(*element_unserializer)(const void *restrict data, uint32_t *restrict data_len); + +/* [private-use] list entry -- olds actual user datum */ +struct list_entry_s { + void *data; + + /* doubly-linked list service references */ + struct list_entry_s *next; + struct list_entry_s *prev; +}; + +/* [private-use] list attributes */ +struct list_attributes_s { + /* user-set routine for comparing list elements */ + element_comparator comparator; + /* user-set routing for seeking elements */ + element_seeker seeker; + /* user-set routine for determining the length of an element */ + element_meter meter; + int copy_data; + /* user-set routine for computing the hash of an element */ + element_hash_computer hasher; + /* user-set routine for serializing an element */ + element_serializer serializer; + /* user-set routine for unserializing an element */ + element_unserializer unserializer; +}; + +/** list object */ +typedef struct { + struct list_entry_s *head_sentinel; + struct list_entry_s *tail_sentinel; + struct list_entry_s *mid; + + unsigned int numels; + + /* array of spare elements */ + struct list_entry_s **spareels; + unsigned int spareelsnum; + +#ifdef SIMCLIST_WITH_THREADS + /* how many threads are currently running */ + unsigned int threadcount; +#endif + + /* service variables for list iteration */ + int iter_active; + unsigned int iter_pos; + struct list_entry_s *iter_curentry; + + /* list attributes */ + struct list_attributes_s attrs; +} list_t; + +/** + * initialize a list object for use. + * + * @param l must point to a user-provided memory location + * @return 0 for success. -1 for failure + */ +int list_init(list_t *restrict l); + +/** + * completely remove the list from memory. + * + * This function is the inverse of list_init(). It is meant to be called when + * the list is no longer going to be used. Elements and possible memory taken + * for internal use are freed. + * + * @param l list to destroy + */ +void list_destroy(list_t *restrict l); + +/** + * set the comparator function for list elements. + * + * Comparator functions are used for searching and sorting. If NULL is passed + * as reference to the function, the comparator is disabled. + * + * @param l list to operate + * @param comparator_fun pointer to the actual comparator function + * @return 0 if the attribute was successfully set; -1 otherwise + * + * @see element_comparator() + */ +int list_attributes_comparator(list_t *restrict l, element_comparator comparator_fun); + +/** + * set a seeker function for list elements. + * + * Seeker functions are used for finding elements. If NULL is passed as reference + * to the function, the seeker is disabled. + * + * @param l list to operate + * @param seeker_fun pointer to the actual seeker function + * @return 0 if the attribute was successfully set; -1 otherwise + * + * @see element_seeker() + */ +int list_attributes_seeker(list_t *restrict l, element_seeker seeker_fun); + +/** + * require to free element data when list entry is removed (default: don't free). + * + * [ advanced preference ] + * + * By default, when an element is removed from the list, it disappears from + * the list by its actual data is not free()d. With this option, every + * deletion causes element data to be freed. + * + * It is responsability of this function to correctly handle NULL values, if + * NULL elements are inserted into the list. + * + * @param l list to operate + * @param metric_fun pointer to the actual metric function + * @param copy_data 0: do not free element data (default); non-0: do free + * @return 0 if the attribute was successfully set; -1 otherwise + * + * @see element_meter() + * @see list_meter_int8_t() + * @see list_meter_int16_t() + * @see list_meter_int32_t() + * @see list_meter_int64_t() + * @see list_meter_uint8_t() + * @see list_meter_uint16_t() + * @see list_meter_uint32_t() + * @see list_meter_uint64_t() + * @see list_meter_float() + * @see list_meter_double() + * @see list_meter_string() + */ +int list_attributes_copy(list_t *restrict l, element_meter metric_fun, int copy_data); + +/** + * set the element hash computing function for the list elements. + * + * [ advanced preference ] + * + * An hash can be requested depicting the list status at a given time. An hash + * only depends on the elements and their order. By default, the hash of an + * element is only computed on its reference. With this function, the user can + * set a custom function computing the hash of an element. If such function is + * provided, the list_hash() function automatically computes the list hash using + * the custom function instead of simply referring to element references. + * + * @param l list to operate + * @param hash_computer_fun pointer to the actual hash computing function + * @return 0 if the attribute was successfully set; -1 otherwise + * + * @see element_hash_computer() + */ +int list_attributes_hash_computer(list_t *restrict l, element_hash_computer hash_computer_fun); + +/** + * set the element serializer function for the list elements. + * + * [ advanced preference ] + * + * Serialize functions are used for dumping the list to some persistent + * storage. The serializer function is called for each element; it is passed + * a reference to the element and a reference to a size_t object. It will + * provide (and return) the buffer with the serialization of the element and + * fill the size_t object with the length of this serialization data. + * + * @param l list to operate + * @param serializer_fun pointer to the actual serializer function + * @return 0 if the attribute was successfully set; -1 otherwise + * + * @see element_serializer() + * @see list_dump_filedescriptor() + * @see list_restore_filedescriptor() + */ +int list_attributes_serializer(list_t *restrict l, element_serializer serializer_fun); + +/** + * set the element unserializer function for the list elements. + * + * [ advanced preference ] + * + * Unserialize functions are used for restoring the list from some persistent + * storage. The unserializer function is called for each element segment read + * from the storage; it is passed the segment and a reference to an integer. + * It shall allocate and return a buffer compiled with the resumed memory + * representation of the element, and set the integer value to the length of + * this buffer. + * + * @param l list to operate + * @param unserializer_fun pointer to the actual unserializer function + * @return 0 if the attribute was successfully set; -1 otherwise + * + * @see element_unserializer() + * @see list_dump_filedescriptor() + * @see list_restore_filedescriptor() + */ +int list_attributes_unserializer(list_t *restrict l, element_unserializer unserializer_fun); + +/** + * append data at the end of the list. + * + * This function is useful for adding elements with a FIFO/queue policy. + * + * @param l list to operate + * @param data pointer to user data to append + * + * @return 1 for success. < 0 for failure + */ +int list_append(list_t *restrict l, const void *data); + +/** + * insert data in the head of the list. + * + * This function is useful for adding elements with a LIFO/Stack policy. + * + * @param l list to operate + * @param data pointer to user data to append + * + * @return 1 for success. < 0 for failure + */ +int list_prepend(list_t *restrict l, const void *restrict data); + +/** + * extract the element in the top of the list. + * + * This function is for using a list with a FIFO/queue policy. + * + * @param l list to operate + * @return reference to user datum, or NULL on errors + */ +void *list_fetch(list_t *restrict l); + +/** + * retrieve an element at a given position. + * + * @param l list to operate + * @param pos [0,size-1] position index of the element wanted + * @return reference to user datum, or NULL on errors + */ +void *list_get_at(const list_t *restrict l, unsigned int pos); + +/** + * return the maximum element of the list. + * + * @warning Requires a comparator function to be set for the list. + * + * Returns the maximum element with respect to the comparator function output. + * + * @see list_attributes_comparator() + * + * @param l list to operate + * @return the reference to the element, or NULL + */ +void *list_get_max(const list_t *restrict l); + +/** + * return the minimum element of the list. + * + * @warning Requires a comparator function to be set for the list. + * + * Returns the minimum element with respect to the comparator function output. + * + * @see list_attributes_comparator() + * + * @param l list to operate + * @return the reference to the element, or NULL + */ +void *list_get_min(const list_t *restrict l); + +/** + * retrieve and remove from list an element at a given position. + * + * @param l list to operate + * @param pos [0,size-1] position index of the element wanted + * @return reference to user datum, or NULL on errors + */ +void *list_extract_at(list_t *restrict l, unsigned int pos); + +/** + * insert an element at a given position. + * + * @param l list to operate + * @param data reference to data to be inserted + * @param pos [0,size-1] position index to insert the element at + * @return positive value on success. Negative on failure + */ +int list_insert_at(list_t *restrict l, const void *data, unsigned int pos); + +/** + * expunge the first found given element from the list. + * + * Inspects the given list looking for the given element; if the element + * is found, it is removed. Only the first occurence is removed. + * If a comparator function was not set, elements are compared by reference. + * Otherwise, the comparator is used to match the element. + * + * @param l list to operate + * @param data reference of the element to search for + * @return 0 on success. Negative value on failure + * + * @see list_attributes_comparator() + * @see list_delete_at() + */ +int list_delete(list_t *restrict l, const void *data); + +/** + * expunge an element at a given position from the list. + * + * @param l list to operate + * @param pos [0,size-1] position index of the element to be deleted + * @return 0 on success. Negative value on failure + */ +int list_delete_at(list_t *restrict l, unsigned int pos); + +/** + * expunge an array of elements from the list, given their position range. + * + * @param l list to operate + * @param posstart [0,size-1] position index of the first element to be deleted + * @param posend [posstart,size-1] position of the last element to be deleted + * @return the number of elements successfully removed on success, <0 on error + */ +int list_delete_range(list_t *restrict l, unsigned int posstart, unsigned int posend); + +/** + * clear all the elements off of the list. + * + * The element datums will not be freed. + * + * @see list_delete_range() + * @see list_size() + * + * @param l list to operate + * @return the number of elements removed on success, <0 on error + */ +int list_clear(list_t *restrict l); + +/** + * inspect the number of elements in the list. + * + * @param l list to operate + * @return number of elements currently held by the list + */ +unsigned int list_size(const list_t *restrict l); + +/** + * inspect whether the list is empty. + * + * @param l list to operate + * @return 0 iff the list is not empty + * + * @see list_size() + */ +int list_empty(const list_t *restrict l); + +/** + * find the position of an element in a list. + * + * @warning Requires a comparator function to be set for the list. + * + * Inspects the given list looking for the given element; if the element + * is found, its position into the list is returned. + * Elements are inspected comparing references if a comparator has not been + * set. Otherwise, the comparator is used to find the element. + * + * @param l list to operate + * @param data reference of the element to search for + * @return position of element in the list, or <0 if not found + * + * @see list_attributes_comparator() + * @see list_get_at() + */ +int list_locate(const list_t *restrict l, const void *data); + +/** + * returns an element given an indicator. + * + * @warning Requires a seeker function to be set for the list. + * + * Inspect the given list looking with the seeker if an element matches + * an indicator. If such element is found, the reference to the element + * is returned. + * + * @param l list to operate + * @param indicator indicator data to pass to the seeker along with elements + * @return reference to the element accepted by the seeker, or NULL if none found + */ +void *list_seek(list_t *restrict l, const void *indicator); + +/** + * inspect whether some data is member of the list. + * + * @warning Requires a comparator function to be set for the list. + * + * By default, a per-reference comparison is accomplished. That is, + * the data is in list if any element of the list points to the same + * location of data. + * A "semantic" comparison is accomplished, otherwise, if a comparator + * function has been set previously, with list_attributes_comparator(); + * in which case, the given data reference is believed to be in list iff + * comparator_fun(elementdata, userdata) == 0 for any element in the list. + * + * @param l list to operate + * @param data reference to the data to search + * @return 0 iff the list does not contain data as an element + * + * @see list_attributes_comparator() + */ +int list_contains(const list_t *restrict l, const void *data); + +/** + * concatenate two lists + * + * Concatenates one list with another, and stores the result into a + * user-provided list object, which must be different from both the + * lists to concatenate. Attributes from the original lists are not + * cloned. + * The destination list referred is threated as virgin room: if it + * is an existing list containing elements, memory leaks will happen. + * It is OK to specify the same list twice as source, for "doubling" + * it in the destination. + * + * @param l1 base list + * @param l2 list to append to the base + * @param dest reference to the destination list + * @return 0 for success, -1 for errors + */ +int list_concat(const list_t *l1, const list_t *l2, list_t *restrict dest); + +/** + * sort list elements. + * + * @warning Requires a comparator function to be set for the list. + * + * Sorts the list in ascending or descending order as specified by the versus + * flag. The algorithm chooses autonomously what algorithm is best suited for + * sorting the list wrt its current status. + * + * @param l list to operate + * @param versus positive: order small to big; negative: order big to small + * @return 0 iff sorting was successful + * + * @see list_attributes_comparator() + */ +int list_sort(list_t *restrict l, int versus); + +/** + * start an iteration session. + * + * This function prepares the list to be iterated. + * + * @param l list to operate + * @return 0 if the list cannot be currently iterated. >0 otherwise + * + * @see list_iterator_stop() + */ +int list_iterator_start(list_t *restrict l); + +/** + * return the next element in the iteration session. + * + * @param l list to operate + * @return element datum, or NULL on errors + */ +void *list_iterator_next(list_t *restrict l); + +/** + * inspect whether more elements are available in the iteration session. + * + * @param l list to operate + * @return 0 iff no more elements are available. + */ +int list_iterator_hasnext(const list_t *restrict l); + +/** + * end an iteration session. + * + * @param l list to operate + * @return 0 iff the iteration session cannot be stopped + */ +int list_iterator_stop(list_t *restrict l); + +/** + * return the hash of the current status of the list. + * + * @param l list to operate + * @param hash where the resulting hash is put + * + * @return 0 for success; <0 for failure + */ +int list_hash(const list_t *restrict l, list_hash_t *restrict hash); + +#ifndef SIMCLIST_NO_DUMPRESTORE +/** + * get meta informations on a list dump on filedescriptor. + * + * [ advanced function ] + * + * Extracts the meta information from a SimCList dump located in a file + * descriptor. The file descriptor must be open and positioned at the + * beginning of the SimCList dump block. + * + * @param fd file descriptor to get metadata from + * @param info reference to a dump metainformation structure to fill + * @return 0 for success; <0 for failure + * + * @see list_dump_filedescriptor() + */ +int list_dump_getinfo_filedescriptor(int fd, list_dump_info_t *restrict info); + +/** + * get meta informations on a list dump on file. + * + * [ advanced function ] + * + * Extracts the meta information from a SimCList dump located in a file. + * + * @param filename filename of the file to fetch from + * @param info reference to a dump metainformation structure to fill + * @return 0 for success; <0 for failure + * + * @see list_dump_filedescriptor() + */ +int list_dump_getinfo_file(const char *restrict filename, list_dump_info_t *restrict info); + +/** + * dump the list into an open, writable file descriptor. + * + * This function "dumps" the list to a persistent storage so it can be + * preserved across process terminations. + * When called, the file descriptor must be open for writing and positioned + * where the serialized data must begin. It writes its serialization of the + * list in a form which is portable across different architectures. Dump can + * be safely performed on stream-only (non seekable) descriptors. The file + * descriptor is not closed at the end of the operations. + * + * To use dump functions, either of these conditions must be satisfied: + * -# a metric function has been specified with list_attributes_copy() + * -# a serializer function has been specified with list_attributes_serializer() + * + * If a metric function has been specified, each element of the list is dumped + * as-is from memory, copying it from its pointer for its length down to the + * file descriptor. This might have impacts on portability of the dump to + * different architectures. + * + * If a serializer function has been specified, its result for each element is + * dumped to the file descriptor. + * + * + * @param l list to operate + * @param fd file descriptor to write to + * @param len location to store the resulting length of the dump (bytes), or NULL + * + * @return 0 if successful; -1 otherwise + * + * @see element_serializer() + * @see list_attributes_copy() + * @see list_attributes_serializer() + */ +int list_dump_filedescriptor(const list_t *restrict l, int fd, size_t *restrict len); + +/** + * dump the list to a file name. + * + * This function creates a filename and dumps the current content of the list + * to it. If the file exists it is overwritten. The number of bytes written to + * the file can be returned in a specified argument. + * + * @param l list to operate + * @param filename filename to write to + * @param len location to store the resulting length of the dump (bytes), or NULL + * + * @return 0 if successful; -1 otherwise + * + * @see list_attributes_copy() + * @see element_serializer() + * @see list_attributes_serializer() + * @see list_dump_filedescriptor() + * @see list_restore_file() + * + * This function stores a representation of the list + */ +int list_dump_file(const list_t *restrict l, const char *restrict filename, size_t *restrict len); + +/** + * restore the list from an open, readable file descriptor to memory. + * + * This function is the "inverse" of list_dump_filedescriptor(). It restores + * the list content from a (open, read-ready) file descriptor to memory. An + * unserializer might be needed to restore elements from the persistent + * representation back into memory-consistent format. List attributes can not + * be restored and must be set manually. + * + * @see list_dump_filedescriptor() + * @see list_attributes_serializer() + * @see list_attributes_unserializer() + * + * @param l list to restore to + * @param fd file descriptor to read from. + * @param len location to store the length of the dump read (bytes), or NULL + * @return 0 if successful; -1 otherwise + */ +int list_restore_filedescriptor(list_t *restrict l, int fd, size_t *restrict len); + +/** + * restore the list from a file name. + * + * This function restores the content of a list from a file into memory. It is + * the inverse of list_dump_file(). + * + * @see element_unserializer() + * @see list_attributes_unserializer() + * @see list_dump_file() + * @see list_restore_filedescriptor() + * + * @param l list to restore to + * @param filename filename to read data from + * @param len location to store the length of the dump read (bytes), or NULL + * @return 0 if successful; -1 otherwise + */ +int list_restore_file(list_t *restrict l, const char *restrict filename, size_t *len); +#endif + +/* ready-made comparators, meters and hash computers */ + /* comparator functions */ +/** + * ready-made comparator for int8_t elements. + * @see list_attributes_comparator() + */ +int list_comparator_int8_t(const void *a, const void *b); + +/** + * ready-made comparator for int16_t elements. + * @see list_attributes_comparator() + */ +int list_comparator_int16_t(const void *a, const void *b); + +/** + * ready-made comparator for int32_t elements. + * @see list_attributes_comparator() + */ +int list_comparator_int32_t(const void *a, const void *b); + +/** + * ready-made comparator for int64_t elements. + * @see list_attributes_comparator() + */ +int list_comparator_int64_t(const void *a, const void *b); + +/** + * ready-made comparator for uint8_t elements. + * @see list_attributes_comparator() + */ +int list_comparator_uint8_t(const void *a, const void *b); + +/** + * ready-made comparator for uint16_t elements. + * @see list_attributes_comparator() + */ +int list_comparator_uint16_t(const void *a, const void *b); + +/** + * ready-made comparator for uint32_t elements. + * @see list_attributes_comparator() + */ +int list_comparator_uint32_t(const void *a, const void *b); + +/** + * ready-made comparator for uint64_t elements. + * @see list_attributes_comparator() + */ +int list_comparator_uint64_t(const void *a, const void *b); + +/** + * ready-made comparator for float elements. + * @see list_attributes_comparator() + */ +int list_comparator_float(const void *a, const void *b); + +/** + * ready-made comparator for double elements. + * @see list_attributes_comparator() + */ +int list_comparator_double(const void *a, const void *b); + +/** + * ready-made comparator for string elements. + * @see list_attributes_comparator() + */ +int list_comparator_string(const void *a, const void *b); + + /* metric functions */ +/** + * ready-made metric function for int8_t elements. + * @see list_attributes_copy() + */ +size_t list_meter_int8_t(const void *el); + +/** + * ready-made metric function for int16_t elements. + * @see list_attributes_copy() + */ +size_t list_meter_int16_t(const void *el); + +/** + * ready-made metric function for int32_t elements. + * @see list_attributes_copy() + */ +size_t list_meter_int32_t(const void *el); + +/** + * ready-made metric function for int64_t elements. + * @see list_attributes_copy() + */ +size_t list_meter_int64_t(const void *el); + +/** + * ready-made metric function for uint8_t elements. + * @see list_attributes_copy() + */ +size_t list_meter_uint8_t(const void *el); + +/** + * ready-made metric function for uint16_t elements. + * @see list_attributes_copy() + */ +size_t list_meter_uint16_t(const void *el); + +/** + * ready-made metric function for uint32_t elements. + * @see list_attributes_copy() + */ +size_t list_meter_uint32_t(const void *el); + +/** + * ready-made metric function for uint64_t elements. + * @see list_attributes_copy() + */ +size_t list_meter_uint64_t(const void *el); + +/** + * ready-made metric function for float elements. + * @see list_attributes_copy() + */ +size_t list_meter_float(const void *el); + +/** + * ready-made metric function for double elements. + * @see list_attributes_copy() + */ +size_t list_meter_double(const void *el); + +/** + * ready-made metric function for string elements. + * @see list_attributes_copy() + */ +size_t list_meter_string(const void *el); + + /* hash functions */ +/** + * ready-made hash function for int8_t elements. + * @see list_attributes_hash_computer() + */ +list_hash_t list_hashcomputer_int8_t(const void *el); + +/** + * ready-made hash function for int16_t elements. + * @see list_attributes_hash_computer() + */ +list_hash_t list_hashcomputer_int16_t(const void *el); + +/** + * ready-made hash function for int32_t elements. + * @see list_attributes_hash_computer() + */ +list_hash_t list_hashcomputer_int32_t(const void *el); + +/** + * ready-made hash function for int64_t elements. + * @see list_attributes_hash_computer() + */ +list_hash_t list_hashcomputer_int64_t(const void *el); + +/** + * ready-made hash function for uint8_t elements. + * @see list_attributes_hash_computer() + */ +list_hash_t list_hashcomputer_uint8_t(const void *el); + +/** + * ready-made hash function for uint16_t elements. + * @see list_attributes_hash_computer() + */ +list_hash_t list_hashcomputer_uint16_t(const void *el); + +/** + * ready-made hash function for uint32_t elements. + * @see list_attributes_hash_computer() + */ +list_hash_t list_hashcomputer_uint32_t(const void *el); + +/** + * ready-made hash function for uint64_t elements. + * @see list_attributes_hash_computer() + */ +list_hash_t list_hashcomputer_uint64_t(const void *el); + +/** + * ready-made hash function for float elements. + * @see list_attributes_hash_computer() + */ +list_hash_t list_hashcomputer_float(const void *el); + +/** + * ready-made hash function for double elements. + * @see list_attributes_hash_computer() + */ +list_hash_t list_hashcomputer_double(const void *el); + +/** + * ready-made hash function for string elements. + * @see list_attributes_hash_computer() + */ +list_hash_t list_hashcomputer_string(const void *el); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/libs/libks/src/include/table.h b/libs/libks/src/include/table.h new file mode 100644 index 0000000000..687358683d --- /dev/null +++ b/libs/libks/src/include/table.h @@ -0,0 +1,1372 @@ +/* + * Generic table defines... + * + * Copyright 2000 by Gray Watson. + * + * This file is part of the table package. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose and without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies, + * and that the name of Gray Watson not be used in advertising or + * publicity pertaining to distribution of the document or software + * without specific, written prior permission. + * + * Gray Watson makes no representations about the suitability of the + * software described herein for any purpose. It is provided "as is" + * without express or implied warranty. + * + * The author may be reached via http://256.com/gray/ + * + * $Id: table.h,v 1.11 2000/03/09 03:30:42 gray Exp $ + */ + +#ifndef __TABLE_H__ +#define __TABLE_H__ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/* + * To build a "key" in any of the below routines, pass in a pointer to + * the key and its size [i.e. sizeof(int), etc]. With any of the + * "key" or "data" arguments, if their size is < 0, it will do an + * internal strlen of the item and add 1 for the \0. + * + * If you are using firstkey() and nextkey() functions, be careful if, + * after starting your firstkey loop, you use delete or insert, it + * will not crash but may produce interesting results. If you are + * deleting from firstkey to NULL it will work fine. + */ + +/* return types for table functions */ +#define TABLE_ERROR_NONE 1 /* no error from function */ +#define TABLE_ERROR_PNT 2 /* bad table pointer */ +#define TABLE_ERROR_ARG_NULL 3 /* buffer args were null */ +#define TABLE_ERROR_SIZE 4 /* size of data was bad */ +#define TABLE_ERROR_OVERWRITE 5 /* key exists and we cant overwrite */ +#define TABLE_ERROR_NOT_FOUND 6 /* key does not exist */ +#define TABLE_ERROR_ALLOC 7 /* memory allocation error */ +#define TABLE_ERROR_LINEAR 8 /* no linear access started */ +#define TABLE_ERROR_OPEN 9 /* could not open file */ +#define TABLE_ERROR_SEEK 10 /* could not seek to pos in file */ +#define TABLE_ERROR_READ 11 /* could not read from file */ +#define TABLE_ERROR_WRITE 12 /* could not write to file */ +#define TABLE_ERROR_MMAP_NONE 13 /* no mmap support */ +#define TABLE_ERROR_MMAP 14 /* could not mmap file */ +#define TABLE_ERROR_MMAP_OP 15 /* can't perform operation on mmap */ +#define TABLE_ERROR_EMPTY 16 /* table is empty */ +#define TABLE_ERROR_NOT_EMPTY 17 /* table contains data */ +#define TABLE_ERROR_ALIGNMENT 18 /* invalid alignment value */ +#define TABLE_ERROR_COMPARE 19 /* problems with internal comparison */ +#define TABLE_ERROR_FREE 20 /* memory free error */ + +/* + * Table flags set with table_attr. + */ + +/* + * Automatically adjust the number of table buckets on the fly. + * Whenever the number of entries gets above some threshold, the + * number of buckets is realloced to a new size and each entry is + * re-hashed. Although this may take some time when it re-hashes, the + * table will perform better over time. + */ +#define TABLE_FLAG_AUTO_ADJUST (1<<0) + +/* + * If the above auto-adjust flag is set, also adjust the number of + * table buckets down as we delete entries. + */ +#define TABLE_FLAG_ADJUST_DOWN (1<<1) + +/* structure to walk through the fields in a linear order */ +typedef struct { + unsigned int tl_magic; /* magic structure to ensure correct init */ + unsigned int tl_bucket_c; /* where in the table buck array we are */ + unsigned int tl_entry_c; /* in the bucket, which entry we are on */ +} table_linear_t; + +/* + * int (*table_compare_t) + * + * DESCRIPTION + * + * Comparison function which compares two key/data pairs for table + * order. + * + * RETURNS: + * + * -1, 0, or 1 if key1 is <, ==, or > than key2. + * + * ARGUMENTS: + * + * key1 - Pointer to the first key entry. + * + * key1_size - Pointer to the size of the first key entry. + * + * data1 - Pointer to the first data entry. + * + * data1_size - Pointer to the size of the first data entry. + * + * key2 - Pointer to the second key entry. + * + * key2_size - Pointer to the size of the second key entry. + * + * data2 - Pointer to the second data entry. + * + * data2_size - Pointer to the size of the second data entry. + */ +typedef int (*table_compare_t)(const void *key1, const int key1_size, + const void *data1, const int data1_size, + const void *key2, const int key2_size, + const void *data2, const int data2_size); + +/* + * int (*table_mem_alloc_t) + * + * DESCRIPTION + * + * Function to override the table's allocation function. + * + * RETURNS: + * + * Success - Newly allocated pointer. + * + * Failure - NULL + * + * ARGUMENTS: + * + * pool_p <-> Pointer to our memory pool. If no pool is set then this + * will be NULL. + * + * size -> Number of bytes that needs to be allocated. + */ +typedef void *(*table_mem_alloc_t)(void *pool_p, const unsigned long size); + +/* + * int (*table_mem_resize_t) + * + * DESCRIPTION + * + * Function to override the table's memory resize function. The + * difference between this and realloc is that this provides the + * previous allocation size. You can specify NULL for this function + * in which cause the library will allocate, copy, and free itself. + * + * RETURNS: + * + * Success - Newly allocated pointer. + * + * Failure - NULL + * + * ARGUMENTS: + * + * pool_p <-> Pointer to our memory pool. If no pool is set then this + * will be NULL. + * + * old_addr -> Previously allocated address. + * + * old_size -> Size of the old address. Since the system is + * lightweight, it does not store size information on the pointer. + * + * new_size -> New size of the allocation. + */ +typedef void *(*table_mem_resize_t)(void *pool_p, void *old_addr, + const unsigned long old_size, + const unsigned long new_size); + +/* + * int (*table_mem_free_t) + * + * DESCRIPTION + * + * Function to override the table's free function. + * + * RETURNS: + * + * Success - 1 + * + * Failure - 0 + * + * ARGUMENTS: + * + * pool_p <-> Pointer to our memory pool. If no pool is set then this + * will be NULL. + * + * addr -> Address that we are freeing. + * + * min_size -> Minimum size of the address being freed or 0 if not + * known. This can also be the exact size if known. + */ +typedef int (*table_mem_free_t)(void *pool_p, void *addr, + const unsigned long min_size); + +#ifdef TABLE_MAIN + +#include "table_loc.h" + +#else + +/* generic table type */ +typedef void table_t; + +/* generic table entry type */ +typedef void table_entry_t; + +#endif + +/*<<<<<<<<<< The below prototypes are auto-generated by fillproto */ + +/* + * table_t *table_alloc + * + * DESCRIPTION: + * + * Allocate a new table structure. + * + * RETURNS: + * + * A pointer to the new table structure which must be passed to + * table_free to be deallocated. On error a NULL is returned. + * + * ARGUMENTS: + * + * bucket_n - Number of buckets for the hash table. Our current hash + * value works best with base two numbers. Set to 0 to take the + * library default of 1024. + * + * error_p - Pointer to an integer which, if not NULL, will contain a + * table error code. + */ +extern +table_t *table_alloc(const unsigned int bucket_n, int *error_p); + +/* + * table_t *table_alloc_in_pool + * + * DESCRIPTION: + * + * Allocate a new table structure in a memory pool or using + * alternative allocation and free functions. + * + * RETURNS: + * + * A pointer to the new table structure which must be passed to + * table_free to be deallocated. On error a NULL is returned. + * + * ARGUMENTS: + * + * bucket_n - Number of buckets for the hash table. Our current hash + * value works best with base two numbers. Set to 0 to take the + * library default of 1024. + * + * mem_pool <-> Memory pool to associate with the table. Can be NULL. + * + * alloc_func -> Allocate function we are overriding malloc() with. + * + * resize_func -> Resize function we are overriding the standard + * memory resize/realloc with. This can be NULL in which cause the + * library will allocate, copy, and free itself. + * + * free_func -> Free function we are overriding free() with. + * + * error_p - Pointer to an integer which, if not NULL, will contain a + * table error code. + */ +extern +table_t *table_alloc_in_pool(const unsigned int bucket_n, + void *mem_pool, + table_mem_alloc_t alloc_func, + table_mem_resize_t resize_func, + table_mem_free_t free_func, int *error_p); + +/* + * int table_attr + * + * DESCRIPTION: + * + * Set the attributes for the table. The available attributes are + * specified at the top of table.h. + * + * RETURNS: + * + * Success - TABLE_ERROR_NONE + * + * Failure - Table error code. + * + * ARGUMENTS: + * + * table_p - Pointer to a table structure which we will be altering. + * + * attr - Attribute(s) that we will be applying to the table. + */ +extern +int table_attr(table_t *table_p, const int attr); + +/* + * int table_set_data_alignment + * + * DESCRIPTION: + * + * Set the alignment for the data in the table. This is used when you + * want to store binary data types and refer to them directly out of + * the table storage. For instance if you are storing integers as + * data in the table and want to be able to retrieve the location of + * the interger and then increment it as (*loc_p)++. Otherwise you + * would have to memcpy it out to an integer, increment it, and memcpy + * it back. If you are storing character data, no alignment is + * necessary. + * + * For most data elements, sizeof(long) is recommended unless you use + * smaller data types exclusively. + * + * WARNING: If necessary, you must set the data alignment before any + * data gets put into the table. Otherwise a TABLE_ERROR_NOT_EMPTY + * error will be returned. + * + * NOTE: there is no way to set the key data alignment although it + * should automatically be long aligned. + * + * RETURNS: + * + * Success - TABLE_ERROR_NONE + * + * Failure - Table error code. + * + * ARGUMENTS: + * + * table_p - Pointer to a table structure which we will be altering. + * + * alignment - Alignment requested for the data. Must be a power of + * 2. Set to 0 for none. + */ +extern +int table_set_data_alignment(table_t *table_p, const int alignment); + +/* + * int table_clear + * + * DESCRIPTION: + * + * Clear out and free all elements in a table structure. + * + * RETURNS: + * + * Success - TABLE_ERROR_NONE + * + * Failure - Table error code. + * + * ARGUMENTS: + * + * table_p - Table structure pointer that we will be clearing. + */ +extern +int table_clear(table_t *table_p); + +/* + * int table_free + * + * DESCRIPTION: + * + * Deallocates a table structure. + * + * RETURNS: + * + * Success - TABLE_ERROR_NONE + * + * Failure - Table error code. + * + * ARGUMENTS: + * + * table_p - Table structure pointer that we will be freeing. + */ +extern +int table_free(table_t *table_p); + +/* + * int table_insert_kd + * + * DESCRIPTION: + * + * Like table_insert except it passes back a pointer to the key and + * the data buffers after they have been inserted into the table + * structure. + * + * This routine adds a key/data pair both of which are made up of a + * buffer of bytes and an associated size. Both the key and the data + * will be copied into buffers allocated inside the table. If the key + * exists already, the associated data will be replaced if the + * overwrite flag is set, otherwise an error is returned. + * + * NOTE: be very careful changing the values since the table library + * provides the pointers to its memory. The key can _never_ be + * changed otherwise you will not find it again. The data can be + * changed but its length can never be altered unless you delete and + * re-insert it into the table. + * + * WARNING: The pointers to the key and data are not in any specific + * alignment. Accessing the key and/or data as an short, integer, or + * long pointer directly can cause problems. + * + * WARNING: Replacing a data cell (not inserting) will cause the table + * linked list to be temporarily invalid. Care must be taken with + * multiple threaded programs which are relying on the first/next + * linked list to be always valid. + * + * RETURNS: + * + * Success - TABLE_ERROR_NONE + * + * Failure - Table error code. + * + * ARGUMENTS: + * + * table_p - Table structure pointer into which we will be inserting a + * new key/data pair. + * + * key_buf - Buffer of bytes of the key that we are inserting. If you + * are storing an (int) as the key (for example) then key_buf should + * be a (int *). + * + * key_size - Size of the key_buf buffer. If set to < 0 then the + * library will do a strlen of key_buf and add 1 for the '\0'. If you + * are storing an (int) as the key (for example) then key_size should + * be sizeof(int). + * + * data_buf - Buffer of bytes of the data that we are inserting. If + * it is NULL then the library will allocate space for the data in the + * table without copying in any information. If data_buf is NULL and + * data_size is 0 then the library will associate a NULL data pointer + * with the key. If you are storing a (long) as the data (for + * example) then data_buf should be a (long *). + * + * data_size - Size of the data_buf buffer. If set to < 0 then the + * library will do a strlen of data_buf and add 1 for the '\0'. If + * you are storing an (long) as the key (for example) then key_size + * should be sizeof(long). + * + * key_buf_p - Pointer which, if not NULL, will be set to the address + * of the key storage that was allocated in the table. If you are + * storing an (int) as the key (for example) then key_buf_p should be + * (int **) i.e. the address of a (int *). + * + * data_buf_p - Pointer which, if not NULL, will be set to the address + * of the data storage that was allocated in the table. If you are + * storing an (long) as the data (for example) then data_buf_p should + * be (long **) i.e. the address of a (long *). + * + * overwrite - Flag which, if set to 1, will allow the overwriting of + * the data in the table with the new data if the key already exists + * in the table. + */ +extern +int table_insert_kd(table_t *table_p, + const void *key_buf, const int key_size, + const void *data_buf, const int data_size, + void **key_buf_p, void **data_buf_p, + const char overwrite_b); + +/* + * int table_insert + * + * DESCRIPTION: + * + * Exactly the same as table_insert_kd except it does not pass back a + * pointer to the key after they have been inserted into the table + * structure. This is still here for backwards compatibility. + * + * See table_insert_kd for more information. + * + * RETURNS: + * + * Success - TABLE_ERROR_NONE + * + * Failure - Table error code. + * + * ARGUMENTS: + * + * table_p - Table structure pointer into which we will be inserting a + * new key/data pair. + * + * key_buf - Buffer of bytes of the key that we are inserting. If you + * are storing an (int) as the key (for example) then key_buf should + * be a (int *). + * + * key_size - Size of the key_buf buffer. If set to < 0 then the + * library will do a strlen of key_buf and add 1 for the '\0'. If you + * are storing an (int) as the key (for example) then key_size should + * be sizeof(int). + * + * data_buf - Buffer of bytes of the data that we are inserting. If + * it is NULL then the library will allocate space for the data in the + * table without copying in any information. If data_buf is NULL and + * data_size is 0 then the library will associate a NULL data pointer + * with the key. If you are storing a (long) as the data (for + * example) then data_buf should be a (long *). + * + * data_size - Size of the data_buf buffer. If set to < 0 then the + * library will do a strlen of data_buf and add 1 for the '\0'. If + * you are storing an (long) as the key (for example) then key_size + * should be sizeof(long). + * + * data_buf_p - Pointer which, if not NULL, will be set to the address + * of the data storage that was allocated in the table. If you are + * storing an (long) as the data (for example) then data_buf_p should + * be (long **) i.e. the address of a (long *). + * + * overwrite - Flag which, if set to 1, will allow the overwriting of + * the data in the table with the new data if the key already exists + * in the table. + */ +extern +int table_insert(table_t *table_p, + const void *key_buf, const int key_size, + const void *data_buf, const int data_size, + void **data_buf_p, const char overwrite_b); + +/* + * int table_retrieve + * + * DESCRIPTION: + * + * This routine looks up a key made up of a buffer of bytes and an + * associated size in the table. If found then it returns the + * associated data information. + * + * RETURNS: + * + * Success - TABLE_ERROR_NONE + * + * Failure - Table error code. + * + * ARGUMENTS: + * + * table_p - Table structure pointer into which we will be searching + * for the key. + * + * key_buf - Buffer of bytes of the key that we are searching for. If + * you are looking for an (int) as the key (for example) then key_buf + * should be a (int *). + * + * key_size - Size of the key_buf buffer. If set to < 0 then the + * library will do a strlen of key_buf and add 1 for the '\0'. If you + * are looking for an (int) as the key (for example) then key_size + * should be sizeof(int). + * + * data_buf_p - Pointer which, if not NULL, will be set to the address + * of the data storage that was allocated in the table and that is + * associated with the key. If a (long) was stored as the data (for + * example) then data_buf_p should be (long **) i.e. the address of a + * (long *). + * + * data_size_p - Pointer to an integer which, if not NULL, will be set + * to the size of the data stored in the table that is associated with + * the key. + */ +extern +int table_retrieve(table_t *table_p, + const void *key_buf, const int key_size, + void **data_buf_p, int *data_size_p); + +/* + * int table_delete + * + * DESCRIPTION: + * + * This routine looks up a key made up of a buffer of bytes and an + * associated size in the table. If found then it will be removed + * from the table. The associated data can be passed back to the user + * if requested. + * + * RETURNS: + * + * Success - TABLE_ERROR_NONE + * + * Failure - Table error code. + * + * NOTE: this could be an allocation error if the library is to return + * the data to the user. + * + * ARGUMENTS: + * + * table_p - Table structure pointer from which we will be deleteing + * the key. + * + * key_buf - Buffer of bytes of the key that we are searching for to + * delete. If you are deleting an (int) key (for example) then + * key_buf should be a (int *). + * + * key_size - Size of the key_buf buffer. If set to < 0 then the + * library will do a strlen of key_buf and add 1 for the '\0'. If you + * are deleting an (int) key (for example) then key_size should be + * sizeof(int). + * + * data_buf_p - Pointer which, if not NULL, will be set to the address + * of the data storage that was allocated in the table and that was + * associated with the key. If a (long) was stored as the data (for + * example) then data_buf_p should be (long **) i.e. the address of a + * (long *). If a pointer is passed in, the caller is responsible for + * freeing it after use. If data_buf_p is NULL then the library will + * free up the data allocation itself. + * + * data_size_p - Pointer to an integer which, if not NULL, will be set + * to the size of the data that was stored in the table and that was + * associated with the key. + */ +extern +int table_delete(table_t *table_p, + const void *key_buf, const int key_size, + void **data_buf_p, int *data_size_p); + +/* + * int table_delete_first + * + * DESCRIPTION: + * + * This is like the table_delete routines except it deletes the first + * key/data pair in the table instead of an entry corresponding to a + * particular key. The associated key and data information can be + * passed back to the user if requested. This routines is handy to + * clear out a table. + * + * RETURNS: + * + * Success - TABLE_ERROR_NONE + * + * Failure - Table error code. + * + * NOTE: this could be an allocation error if the library is to return + * the data to the user. + * + * ARGUMENTS: + * + * table_p - Table structure pointer from which we will be deleteing + * the first key. + * + * key_buf_p - Pointer which, if not NULL, will be set to the address + * of the storage of the first key that was allocated in the table. + * If an (int) was stored as the first key (for example) then + * key_buf_p should be (int **) i.e. the address of a (int *). If a + * pointer is passed in, the caller is responsible for freeing it + * after use. If key_buf_p is NULL then the library will free up the + * key allocation itself. + * + * key_size_p - Pointer to an integer which, if not NULL, will be set + * to the size of the key that was stored in the table and that was + * associated with the key. + * + * data_buf_p - Pointer which, if not NULL, will be set to the address + * of the data storage that was allocated in the table and that was + * associated with the key. If a (long) was stored as the data (for + * example) then data_buf_p should be (long **) i.e. the address of a + * (long *). If a pointer is passed in, the caller is responsible for + * freeing it after use. If data_buf_p is NULL then the library will + * free up the data allocation itself. + * + * data_size_p - Pointer to an integer which, if not NULL, will be set + * to the size of the data that was stored in the table and that was + * associated with the key. + */ +extern +int table_delete_first(table_t *table_p, + void **key_buf_p, int *key_size_p, + void **data_buf_p, int *data_size_p); + +/* + * int table_info + * + * DESCRIPTION: + * + * Get some information about a table_p structure. + * + * RETURNS: + * + * Success - TABLE_ERROR_NONE + * + * Failure - Table error code. + * + * ARGUMENTS: + * + * table_p - Table structure pointer from which we are getting + * information. + * + * num_buckets_p - Pointer to an integer which, if not NULL, will + * contain the number of buckets in the table. + * + * num_entries_p - Pointer to an integer which, if not NULL, will + * contain the number of entries stored in the table. + */ +extern +int table_info(table_t *table_p, int *num_buckets_p, int *num_entries_p); + +/* + * int table_adjust + * + * DESCRIPTION: + * + * Set the number of buckets in a table to a certain value. + * + * RETURNS: + * + * Success - TABLE_ERROR_NONE + * + * Failure - Table error code. + * + * ARGUMENTS: + * + * table_p - Table structure pointer of which we are adjusting. + * + * bucket_n - Number buckets to adjust the table to. Set to 0 to + * adjust the table to its number of entries. + */ +extern +int table_adjust(table_t *table_p, const int bucket_n); + +/* + * int table_type_size + * + * DESCRIPTION: + * + * Return the size of the internal table type. + * + * RETURNS: + * + * The size of the table_t type. + * + * ARGUMENTS: + * + * None. + */ +extern +int table_type_size(void); + +/* + * int table_first + * + * DESCRIPTION: + * + * Find first element in a table and pass back information about the + * key/data pair. If any of the key/data pointers are NULL then they + * are ignored. + * + * NOTE: This function is not reentrant. More than one thread cannot + * be doing a first and next on the same table at the same time. Use + * the table_first_r version below for this. + * + * RETURNS: + * + * Success - TABLE_ERROR_NONE + * + * Failure - Table error code. + * + * ARGUMENTS: + * + * table_p - Table structure pointer from which we are getting the + * first element. + * + * key_buf_p - Pointer which, if not NULL, will be set to the address + * of the storage of the first key that is allocated in the table. If + * an (int) is stored as the first key (for example) then key_buf_p + * should be (int **) i.e. the address of a (int *). + * + * key_size_p - Pointer to an integer which, if not NULL, will be set + * to the size of the key that is stored in the table and that is + * associated with the first key. + * + * data_buf_p - Pointer which, if not NULL, will be set to the address + * of the data storage that is allocated in the table and that is + * associated with the first key. If a (long) is stored as the data + * (for example) then data_buf_p should be (long **) i.e. the address + * of a (long *). + * + * data_size_p - Pointer to an integer which, if not NULL, will be set + * to the size of the data that is stored in the table and that is + * associated with the first key. + */ +extern +int table_first(table_t *table_p, + void **key_buf_p, int *key_size_p, + void **data_buf_p, int *data_size_p); + +/* + * int table_next + * + * DESCRIPTION: + * + * Find the next element in a table and pass back information about + * the key/data pair. If any of the key/data pointers are NULL then + * they are ignored. + * + * NOTE: This function is not reentrant. More than one thread cannot + * be doing a first and next on the same table at the same time. Use + * the table_next_r version below for this. + * + * RETURNS: + * + * Success - TABLE_ERROR_NONE + * + * Failure - Table error code. + * + * ARGUMENTS: + * + * table_p - Table structure pointer from which we are getting the + * next element. + * + * key_buf_p - Pointer which, if not NULL, will be set to the address + * of the storage of the next key that is allocated in the table. If + * an (int) is stored as the next key (for example) then key_buf_p + * should be (int **) i.e. the address of a (int *). + * + * key_size_p - Pointer to an integer which, if not NULL, will be set + * to the size of the key that is stored in the table and that is + * associated with the next key. + * + * data_buf_p - Pointer which, if not NULL, will be set to the address + * of the data storage that is allocated in the table and that is + * associated with the next key. If a (long) is stored as the data + * (for example) then data_buf_p should be (long **) i.e. the address + * of a (long *). + * + * data_size_p - Pointer to an integer which, if not NULL, will be set + * to the size of the data that is stored in the table and that is + * associated with the next key. + */ +extern +int table_next(table_t *table_p, + void **key_buf_p, int *key_size_p, + void **data_buf_p, int *data_size_p); + +/* + * int table_this + * + * DESCRIPTION: + * + * Find the current element in a table and pass back information about + * the key/data pair. If any of the key/data pointers are NULL then + * they are ignored. + * + * NOTE: This function is not reentrant. Use the table_current_r + * version below. + * + * RETURNS: + * + * Success - TABLE_ERROR_NONE + * + * Failure - Table error code. + * + * ARGUMENTS: + * + * table_p - Table structure pointer from which we are getting the + * current element. + * + * key_buf_p - Pointer which, if not NULL, will be set to the address + * of the storage of the current key that is allocated in the table. + * If an (int) is stored as the current key (for example) then + * key_buf_p should be (int **) i.e. the address of a (int *). + * + * key_size_p - Pointer to an integer which, if not NULL, will be set + * to the size of the key that is stored in the table and that is + * associated with the current key. + * + * data_buf_p - Pointer which, if not NULL, will be set to the address + * of the data storage that is allocated in the table and that is + * associated with the current key. If a (long) is stored as the data + * (for example) then data_buf_p should be (long **) i.e. the address + * of a (long *). + * + * data_size_p - Pointer to an integer which, if not NULL, will be set + * to the size of the data that is stored in the table and that is + * associated with the current key. + */ +extern +int table_this(table_t *table_p, + void **key_buf_p, int *key_size_p, + void **data_buf_p, int *data_size_p); + +/* + * int table_first_r + * + * DESCRIPTION: + * + * Reetrant version of the table_first routine above. Find first + * element in a table and pass back information about the key/data + * pair. If any of the key/data pointers are NULL then they are + * ignored. + * + * RETURNS: + * + * Success - TABLE_ERROR_NONE + * + * Failure - Table error code. + * + * ARGUMENTS: + * + * table_p - Table structure pointer from which we are getting the + * first element. + * + * linear_p - Pointer to a table linear structure which is initialized + * here. The same pointer should then be passed to table_next_r + * below. + * + * key_buf_p - Pointer which, if not NULL, will be set to the address + * of the storage of the first key that is allocated in the table. If + * an (int) is stored as the first key (for example) then key_buf_p + * should be (int **) i.e. the address of a (int *). + * + * key_size_p - Pointer to an integer which, if not NULL, will be set + * to the size of the key that is stored in the table and that is + * associated with the first key. + * + * data_buf_p - Pointer which, if not NULL, will be set to the address + * of the data storage that is allocated in the table and that is + * associated with the first key. If a (long) is stored as the data + * (for example) then data_buf_p should be (long **) i.e. the address + * of a (long *). + * + * data_size_p - Pointer to an integer which, if not NULL, will be set + * to the size of the data that is stored in the table and that is + * associated with the first key. + */ +extern +int table_first_r(table_t *table_p, table_linear_t *linear_p, + void **key_buf_p, int *key_size_p, + void **data_buf_p, int *data_size_p); + +/* + * int table_next_r + * + * DESCRIPTION: + * + * Reetrant version of the table_next routine above. Find next + * element in a table and pass back information about the key/data + * pair. If any of the key/data pointers are NULL then they are + * ignored. + * + * RETURNS: + * + * Success - TABLE_ERROR_NONE + * + * Failure - Table error code. + * + * ARGUMENTS: + * + * table_p - Table structure pointer from which we are getting the + * next element. + * + * linear_p - Pointer to a table linear structure which is incremented + * here. The same pointer must have been passed to table_first_r + * first so that it can be initialized. + * + * key_buf_p - Pointer which, if not NULL, will be set to the address + * of the storage of the next key that is allocated in the table. If + * an (int) is stored as the next key (for example) then key_buf_p + * should be (int **) i.e. the address of a (int *). + * + * key_size_p - Pointer to an integer which, if not NULL will be set + * to the size of the key that is stored in the table and that is + * associated with the next key. + * + * data_buf_p - Pointer which, if not NULL, will be set to the address + * of the data storage that is allocated in the table and that is + * associated with the next key. If a (long) is stored as the data + * (for example) then data_buf_p should be (long **) i.e. the address + * of a (long *). + * + * data_size_p - Pointer to an integer which, if not NULL, will be set + * to the size of the data that is stored in the table and that is + * associated with the next key. + */ +extern +int table_next_r(table_t *table_p, table_linear_t *linear_p, + void **key_buf_p, int *key_size_p, + void **data_buf_p, int *data_size_p); + +/* + * int table_this_r + * + * DESCRIPTION: + * + * Reetrant version of the table_this routine above. Find current + * element in a table and pass back information about the key/data + * pair. If any of the key/data pointers are NULL then they are + * ignored. + * + * RETURNS: + * + * Success - TABLE_ERROR_NONE + * + * Failure - Table error code. + * + * ARGUMENTS: + * + * table_p - Table structure pointer from which we are getting the + * current element. + * + * linear_p - Pointer to a table linear structure which is accessed + * here. The same pointer must have been passed to table_first_r + * first so that it can be initialized. + * + * key_buf_p - Pointer which, if not NULL, will be set to the address + * of the storage of the current key that is allocated in the table. + * If an (int) is stored as the current key (for example) then + * key_buf_p should be (int **) i.e. the address of a (int *). + * + * key_size_p - Pointer to an integer which, if not NULL, will be set + * to the size of the key that is stored in the table and that is + * associated with the current key. + * + * data_buf_p - Pointer which, if not NULL, will be set to the address + * of the data storage that is allocated in the table and that is + * associated with the current key. If a (long) is stored as the data + * (for example) then data_buf_p should be (long **) i.e. the address + * of a (long *). + * + * data_size_p - Pointer to an integer which, if not NULL, will be set + * to the size of the data that is stored in the table and that is + * associated with the current key. + */ +extern +int table_this_r(table_t *table_p, table_linear_t *linear_p, + void **key_buf_p, int *key_size_p, + void **data_buf_p, int *data_size_p); + +/* + * table_t *table_mmap + * + * DESCRIPTION: + * + * Mmap a table from a file that had been written to disk earlier via + * table_write. + * + * RETURNS: + * + * A pointer to the new table structure which must be passed to + * table_munmap to be deallocated. On error a NULL is returned. + * + * ARGUMENTS: + * + * path - Table file to mmap in. + * + * error_p - Pointer to an integer which, if not NULL, will contain a + * table error code. + */ +extern +table_t *table_mmap(const char *path, int *error_p); + +/* + * int table_munmap + * + * DESCRIPTION: + * + * Unmmap a table that was previously mmapped using table_mmap. + * + * RETURNS: + * + * Returns table error codes. + * + * ARGUMENTS: + * + * table_p - Mmaped table pointer to unmap. + */ +extern +int table_munmap(table_t *table_p); + +/* + * int table_read + * + * DESCRIPTION: + * + * Read in a table from a file that had been written to disk earlier + * via table_write. + * + * RETURNS: + * + * Success - Pointer to the new table structure which must be passed + * to table_free to be deallocated. + * + * Failure - NULL + * + * ARGUMENTS: + * + * path - Table file to read in. + * + * error_p - Pointer to an integer which, if not NULL, will contain a + * table error code. + */ +extern +table_t *table_read(const char *path, int *error_p); + +/* + * int table_write + * + * DESCRIPTION: + * + * Write a table from memory to file. + * + * RETURNS: + * + * Success - TABLE_ERROR_NONE + * + * Failure - Table error code. + * + * ARGUMENTS: + * + * table_p - Pointer to the table that we are writing to the file. + * + * path - Table file to write out to. + * + * mode - Mode of the file. This argument is passed on to open when + * the file is created. + */ +extern +int table_write(const table_t *table_p, const char *path, const int mode); + +/* + * table_entry_t *table_order + * + * DESCRIPTION: + * + * Order a table by building an array of table entry pointers and then + * sorting this array using the qsort function. To retrieve the + * sorted entries, you can then use the table_entry routine to access + * each entry in order. + * + * NOTE: This routine is thread safe and makes use of an internal + * status qsort function. + * + * RETURNS: + * + * Success - An allocated list of table-linear structures which must + * be freed by table_order_free later. + * + * Failure - NULL + * + * ARGUMENTS: + * + * table_p - Pointer to the table that we are ordering. + * + * compare - Comparison function defined by the user. Its definition + * is at the top of the table.h file. If this is NULL then it will + * order the table my memcmp-ing the keys. + * + * num_entries_p - Pointer to an integer which, if not NULL, will + * contain the number of entries in the returned entry pointer array. + * + * error_p - Pointer to an integer which, if not NULL, will contain a + * table error code. + */ +extern +table_entry_t **table_order(table_t *table_p, table_compare_t compare, + int *num_entries_p, int *error_p); + +/* + * int table_order_free + * + * DESCRIPTION: + * + * Free the pointer returned by the table_order or table_order_pos + * routines. + * + * RETURNS: + * + * Success - TABLE_ERROR_NONE + * + * Failure - Table error code. + * + * ARGUMENTS: + * + * table_p - Pointer to the table. + * + * table_entries - Allocated list of entry pointers returned by + * table_order. + * + * entry_n - Number of entries in the array as passed back by + * table_order or table_order_pos in num_entries_p. + */ +extern +int table_order_free(table_t *table_p, table_entry_t **table_entries, + const int entry_n); + +/* + * int table_entry + * + * DESCRIPTION: + * + * Get information about an element. The element is one from the + * array returned by the table_order function. If any of the key/data + * pointers are NULL then they are ignored. + * + * RETURNS: + * + * Success - TABLE_ERROR_NONE + * + * Failure - Table error code. + * + * ARGUMENTS: + * + * table_p - Table structure pointer from which we are getting the + * element. + * + * entry_p - Pointer to a table entry from the array returned by the + * table_order function. + * + * key_buf_p - Pointer which, if not NULL, will be set to the address + * of the storage of this entry that is allocated in the table. If an + * (int) is stored as this entry (for example) then key_buf_p should + * be (int **) i.e. the address of a (int *). + * + * key_size_p - Pointer to an integer which, if not NULL, will be set + * to the size of the key that is stored in the table. + * + * data_buf_p - Pointer which, if not NULL, will be set to the address + * of the data storage of this entry that is allocated in the table. + * If a (long) is stored as this entry data (for example) then + * data_buf_p should be (long **) i.e. the address of a (long *). + * + * data_size_p - Pointer to an integer which, if not NULL, will be set + * to the size of the data that is stored in the table. + */ +extern +int table_entry(table_t *table_p, table_entry_t *entry_p, + void **key_buf_p, int *key_size_p, + void **data_buf_p, int *data_size_p); + +/* + * table_linear_t *table_order_pos + * + * DESCRIPTION: + * + * Order a table by building an array of table linear structures and + * then sorting this array using the qsort function. To retrieve the + * sorted entries, you can then use the table_entry_pos routine to + * access each entry in order. + * + * NOTE: This routine is thread safe and makes use of an internal + * status qsort function. + * + * RETURNS: + * + * Success - An allocated list of table-linear structures which must + * be freed by table_order_pos_free later. + * + * Failure - NULL + * + * ARGUMENTS: + * + * table_p - Pointer to the table that we are ordering. + * + * compare - Comparison function defined by the user. Its definition + * is at the top of the table.h file. If this is NULL then it will + * order the table my memcmp-ing the keys. + * + * num_entries_p - Pointer to an integer which, if not NULL, will + * contain the number of entries in the returned entry pointer array. + * + * error_p - Pointer to an integer which, if not NULL, will contain a + * table error code. + */ +extern +table_linear_t *table_order_pos(table_t *table_p, table_compare_t compare, + int *num_entries_p, int *error_p); + +/* + * int table_order_pos_free + * + * DESCRIPTION: + * + * Free the pointer returned by the table_order or table_order_pos + * routines. + * + * RETURNS: + * + * Success - TABLE_ERROR_NONE + * + * Failure - Table error code. + * + * ARGUMENTS: + * + * table_p - Pointer to the table. + * + * table_entries - Allocated list of entry pointers returned by + * table_order_pos. + * + * entry_n - Number of entries in the array as passed back by + * table_order or table_order_pos in num_entries_p. + */ +extern +int table_order_pos_free(table_t *table_p, table_linear_t *table_entries, + const int entry_n); + +/* + * int table_entry_pos + * + * DESCRIPTION: + * + * Get information about an element. The element is one from the + * array returned by the table_order function. If any of the key/data + * pointers are NULL then they are ignored. + * + * RETURNS: + * + * Success - TABLE_ERROR_NONE + * + * Failure - Table error code. + * + * ARGUMENTS: + * + * table_p - Table structure pointer from which we are getting the + * element. + * + * linear_p - Pointer to a table linear structure from the array + * returned by the table_order function. + * + * key_buf_p - Pointer which, if not NULL, will be set to the address + * of the storage of this entry that is allocated in the table. If an + * (int) is stored as this entry (for example) then key_buf_p should + * be (int **) i.e. the address of a (int *). + * + * key_size_p - Pointer to an integer which, if not NULL, will be set + * to the size of the key that is stored in the table. + * + * data_buf_p - Pointer which, if not NULL, will be set to the address + * of the data storage of this entry that is allocated in the table. + * If a (long) is stored as this entry data (for example) then + * data_buf_p should be (long **) i.e. the address of a (long *). + * + * data_size_p - Pointer to an integer which, if not NULL, will be set + * to the size of the data that is stored in the table. + */ +extern +int table_entry_pos(table_t *table_p, table_linear_t *linear_p, + void **key_buf_p, int *key_size_p, + void **data_buf_p, int *data_size_p); + +/* + * const char *table_strerror + * + * DESCRIPTION: + * + * Return the corresponding string for the error number. + * + * RETURNS: + * + * Success - String equivalient of the error. + * + * Failure - String "invalid error code" + * + * ARGUMENTS: + * + * error - Error number that we are converting. + */ +extern +const char *table_strerror(const int error); + +/*<<<<<<<<<< This is end of the auto-generated output from fillproto. */ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* ! __TABLE_H__ */ diff --git a/libs/libks/src/include/table_loc.h b/libs/libks/src/include/table_loc.h new file mode 100644 index 0000000000..02514c8211 --- /dev/null +++ b/libs/libks/src/include/table_loc.h @@ -0,0 +1,229 @@ +/* + * local defines for the table module + * + * Copyright 2000 by Gray Watson. + * + * This file is part of the table package. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose and without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies, + * and that the name of Gray Watson not be used in advertising or + * publicity pertaining to distribution of the document or software + * without specific, written prior permission. + * + * Gray Watson makes no representations about the suitability of the + * software described herein for any purpose. It is provided "as is" + * without express or implied warranty. + * + * The author may be reached via http://256.com/gray/ + * + * $Id: table_loc.h,v 1.11 2000/03/09 03:30:42 gray Exp $ + */ + +#ifndef __TABLE_LOC_H__ +#define __TABLE_LOC_H__ + +#ifndef unix +#define NO_MMAP +#endif + +#ifndef BITSPERBYTE +#define BITSPERBYTE 8 +#endif +#ifndef BITS +#define BITS(type) (BITSPERBYTE * (int)sizeof(type)) +#endif + +#define TABLE_MAGIC 0xBADF00D /* very magic magicness */ +#define LINEAR_MAGIC 0xAD00D00 /* magic value for linear struct */ +#define DEFAULT_SIZE 1024 /* default table size */ +#define MAX_ALIGNMENT 128 /* max alignment value */ + +/* + * Maximum number of splits. This should mean that these routines can + * handle at least 2^128 different values (that's _quite_ a few). And + * then you can always increase the value. + */ +#define MAX_QSORT_SPLITS 128 + +/* + * Maximum number of entries that must be in list for it to be + * partitioned. If there are fewer elements then just do our + * insertion sort. + */ +#define MAX_QSORT_MANY 8 + +/* + * Macros. + */ + +/* returns 1 when we should grow or shrink the table */ +#define SHOULD_TABLE_GROW(tab) ((tab)->ta_entry_n > (tab)->ta_bucket_n * 2) +#define SHOULD_TABLE_SHRINK(tab) ((tab)->ta_entry_n < (tab)->ta_bucket_n / 2) + +/* + * void HASH_MIX + * + * DESCRIPTION: + * + * Mix 3 32-bit values reversibly. For every delta with one or two + * bits set, and the deltas of all three high bits or all three low + * bits, whether the original value of a,b,c is almost all zero or is + * uniformly distributed. + * + * If HASH_MIX() is run forward or backward, at least 32 bits in a,b,c + * have at least 1/4 probability of changing. If mix() is run + * forward, every bit of c will change between 1/3 and 2/3 of the + * time. (Well, 22/100 and 78/100 for some 2-bit deltas.) + * + * HASH_MIX() takes 36 machine instructions, but only 18 cycles on a + * superscalar machine (like a Pentium or a Sparc). No faster mixer + * seems to work, that's the result of my brute-force search. There + * were about 2^68 hashes to choose from. I only tested about a + * billion of those. + */ +#define HASH_MIX(a, b, c) \ + do { \ + a -= b; a -= c; a ^= (c >> 13); \ + b -= c; b -= a; b ^= (a << 8); \ + c -= a; c -= b; c ^= (b >> 13); \ + a -= b; a -= c; a ^= (c >> 12); \ + b -= c; b -= a; b ^= (a << 16); \ + c -= a; c -= b; c ^= (b >> 5); \ + a -= b; a -= c; a ^= (c >> 3); \ + b -= c; b -= a; b ^= (a << 10); \ + c -= a; c -= b; c ^= (b >> 15); \ + } while(0) + +#define SET_POINTER(pnt, val) \ + do { \ + if ((pnt) != NULL) { \ + (*(pnt)) = (val); \ + } \ + } while(0) + +/* + * The following macros take care of the mmap case. When we are + * mmaping a table from a disk file, all of the pointers in the table + * structures are replaced with offsets into the file. The following + * macro, for each pointer, adds the starting address of the mmaped + * section onto each pointer/offset turning it back into a legitimate + * pointer. + */ +#ifdef NO_MMAP + +#define TABLE_POINTER(table, type, pnt) (pnt) + +#else + +#define TABLE_POINTER(tab_p, type, pnt) \ + ((tab_p)->ta_mmap == NULL || (pnt) == NULL ? (pnt) : \ + (type)((char *)((tab_p)->ta_mmap) + (long)(pnt))) + +#endif + +/* + * Macros to get at the key and the data pointers + */ +#define ENTRY_KEY_BUF(entry_p) ((entry_p)->te_key_buf) +#define ENTRY_DATA_BUF(tab_p, entry_p) \ + (ENTRY_KEY_BUF(entry_p) + (entry_p)->te_key_size) + +/* + * Table structures... + */ + +/* + * HACK: this should be equiv as the table_entry_t without the key_buf + * char. We use this with the ENTRY_SIZE() macro above which solves + * the problem with the lack of the [0] GNU hack. We use the + * table_entry_t structure to better map the memory and make things + * faster. + */ +typedef struct table_shell_st { + unsigned int te_key_size; /* size of data */ + unsigned int te_data_size; /* size of data */ + struct table_shell_st *te_next_p; /* pointer to next in the list */ + /* NOTE: this does not have the te_key_buf field here */ +} table_shell_t; + +/* + * Elements in the bucket linked-lists. The key[1] is the start of + * the key with the rest of the key and all of the data information + * packed in memory directly after the end of this structure. + * + * NOTE: if this structure is changed, the table_shell_t must be + * changed to match. + */ +typedef struct table_entry_st { + unsigned int te_key_size; /* size of data */ + unsigned int te_data_size; /* size of data */ + struct table_entry_st *te_next_p; /* pointer to next in the list */ + unsigned char te_key_buf[1]; /* 1st byte of key buf */ +} table_entry_t; + +/* external structure for debuggers be able to see void */ +typedef table_entry_t table_entry_ext_t; + +/* main table structure */ +typedef struct table_st { + unsigned int ta_magic; /* magic number */ + unsigned int ta_flags; /* table's flags defined in table.h */ + unsigned int ta_bucket_n; /* num of buckets, should be 2^X */ + unsigned int ta_entry_n; /* num of entries in all buckets */ + unsigned int ta_data_align; /* data alignment value */ + table_entry_t **ta_buckets; /* array of linked lists */ + table_linear_t ta_linear; /* linear tracking */ + struct table_st *ta_mmap; /* mmaped table */ + unsigned long ta_file_size; /* size of on-disk space */ + + void *ta_mem_pool; /* pointer to some memory pool */ + table_mem_alloc_t ta_alloc_func; /* memory allocation function */ + table_mem_resize_t ta_resize_func; /* memory resize function */ + table_mem_free_t ta_free_func; /* memory free function */ +} table_t; + +/* external table structure for debuggers */ +typedef table_t table_ext_t; + +/* local comparison functions */ +typedef int (*compare_t)(const void *element1_p, const void *element2_p, + table_compare_t user_compare, + const table_t *table_p, int *err_bp); + +/* + * to map error to string + */ +typedef struct { + int es_error; /* error number */ + char *es_string; /* assocaited string */ +} error_str_t; + +static error_str_t errors[] = { + { TABLE_ERROR_NONE, "no error" }, + { TABLE_ERROR_PNT, "invalid table pointer" }, + { TABLE_ERROR_ARG_NULL, "buffer argument is null" }, + { TABLE_ERROR_SIZE, "incorrect size argument" }, + { TABLE_ERROR_OVERWRITE, "key exists and no overwrite" }, + { TABLE_ERROR_NOT_FOUND, "key does not exist" }, + { TABLE_ERROR_ALLOC, "error allocating memory" }, + { TABLE_ERROR_LINEAR, "linear access not in progress" }, + { TABLE_ERROR_OPEN, "could not open file" }, + { TABLE_ERROR_SEEK, "could not seek to position in file" }, + { TABLE_ERROR_READ, "could not read from file" }, + { TABLE_ERROR_WRITE, "could not write to file" }, + { TABLE_ERROR_MMAP_NONE, "no mmap support compiled in library" }, + { TABLE_ERROR_MMAP, "could not mmap the file" }, + { TABLE_ERROR_MMAP_OP, "operation not valid on mmap files" }, + { TABLE_ERROR_EMPTY, "table is empty" }, + { TABLE_ERROR_NOT_EMPTY, "table contains data" }, + { TABLE_ERROR_ALIGNMENT, "invalid alignment value" }, + { TABLE_ERROR_COMPARE, "problems with internal comparison" }, + { TABLE_ERROR_FREE, "memory free error" }, + { 0 } +}; + +#define INVALID_ERROR "invalid error code" + +#endif /* ! __TABLE_LOC_H__ */ diff --git a/libs/libks/src/ks.c b/libs/libks/src/ks.c new file mode 100644 index 0000000000..b328f36798 --- /dev/null +++ b/libs/libks/src/ks.c @@ -0,0 +1,739 @@ +/* + * Copyright (c) 2007-2012, Anthony Minessale II + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name of the original author; nor the names of any contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +/* Use select on windows and poll everywhere else. + Select is the devil. Especially if you are doing a lot of small socket connections. + If your FD number is bigger than 1024 you will silently create memory corruption. + + If you have build errors on your platform because you don't have poll find a way to detect it and #define KS_USE_SELECT and #undef KS_USE_POLL + All of this will be upgraded to autoheadache eventually. +*/ + +/* TBD for win32 figure out how to tell if you have WSAPoll (vista or higher) and use it when available by #defining KS_USE_WSAPOLL (see below) */ + +#ifdef _MSC_VER +#define FD_SETSIZE 8192 +#define KS_USE_SELECT +#else +#define KS_USE_POLL +#endif + +#include +#ifndef WIN32 +#define closesocket(x) shutdown(x, 2); close(x) +#include +#include +#else +#pragma warning (disable:6386) +/* These warnings need to be ignored warning in sdk header */ +#include +#include +#ifndef errno +#define errno WSAGetLastError() +#endif +#ifndef EINTR +#define EINTR WSAEINTR +#endif +#pragma warning (default:6386) +#endif + +#ifdef KS_USE_POLL +#include +#endif + +#ifndef KS_MIN +#define KS_MIN(x,y) ((x) < (y) ? (x) : (y)) +#endif +#ifndef KS_MAX +#define KS_MAX(x,y) ((x) > (y) ? (x) : (y)) +#endif +#ifndef KS_CLAMP +#define KS_CLAMP(min,max,val) (KS_MIN(max,KS_MAX(val,min))) +#endif + + +/* Written by Marc Espie, public domain */ +#define KS_CTYPE_NUM_CHARS 256 + +const short _ks_C_toupper_[1 + KS_CTYPE_NUM_CHARS] = { + EOF, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, + 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, + 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, + 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, + 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, + 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, + 0x60, 'A', 'B', 'C', 'D', 'E', 'F', 'G', + 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', + 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', + 'X', 'Y', 'Z', 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, + 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, + 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, + 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, + 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, + 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, + 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, + 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, + 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, + 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, + 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, + 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, + 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, + 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, + 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, + 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, + 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff +}; + +const short *_ks_toupper_tab_ = _ks_C_toupper_; + +KS_DECLARE(int) ks_toupper(int c) +{ + if ((unsigned int)c > 255) + return(c); + if (c < -1) + return EOF; + return((_ks_toupper_tab_ + 1)[c]); +} + +const short _ks_C_tolower_[1 + KS_CTYPE_NUM_CHARS] = { + EOF, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, + 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, + 0x40, 'a', 'b', 'c', 'd', 'e', 'f', 'g', + 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', + 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', + 'x', 'y', 'z', 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, + 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, + 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, + 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, + 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, + 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, + 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, + 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, + 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, + 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, + 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, + 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, + 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, + 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, + 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, + 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, + 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, + 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, + 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, + 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, + 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff +}; + +const short *_ks_tolower_tab_ = _ks_C_tolower_; + +KS_DECLARE(int) ks_tolower(int c) +{ + if ((unsigned int)c > 255) + return(c); + if (c < -1) + return EOF; + return((_ks_tolower_tab_ + 1)[c]); +} + +KS_DECLARE(const char *)ks_stristr(const char *instr, const char *str) +{ +/* +** Rev History: 16/07/97 Greg Thayer Optimized +** 07/04/95 Bob Stout ANSI-fy +** 02/03/94 Fred Cole Original +** 09/01/03 Bob Stout Bug fix (lines 40-41) per Fred Bulback +** +** Hereby donated to public domain. +*/ + const char *pptr, *sptr, *start; + + if (!str || !instr) + return NULL; + + for (start = str; *start; start++) { + /* find start of pattern in string */ + for (; ((*start) && (ks_toupper(*start) != ks_toupper(*instr))); start++); + + if (!*start) + return NULL; + + pptr = instr; + sptr = start; + + while (ks_toupper(*sptr) == ks_toupper(*pptr)) { + sptr++; + pptr++; + + /* if end of pattern then pattern was found */ + if (!*pptr) + return (start); + + if (!*sptr) + return NULL; + } + } + return NULL; +} + +#ifdef WIN32 +#ifndef vsnprintf +#define vsnprintf _vsnprintf +#endif +#endif + + +int vasprintf(char **ret, const char *format, va_list ap); + +KS_DECLARE(int) ks_vasprintf(char **ret, const char *fmt, va_list ap) +{ +#if !defined(WIN32) && !defined(__sun) + return vasprintf(ret, fmt, ap); +#else + char *buf; + int len; + size_t buflen; + va_list ap2; + char *tmp = NULL; + +#ifdef _MSC_VER +#if _MSC_VER >= 1500 + /* hack for incorrect assumption in msvc header files for code analysis */ + __analysis_assume(tmp); +#endif + ap2 = ap; +#else + va_copy(ap2, ap); +#endif + + len = vsnprintf(tmp, 0, fmt, ap2); + + if (len > 0 && (buf = malloc((buflen = (size_t) (len + 1)))) != NULL) { + len = vsnprintf(buf, buflen, fmt, ap); + *ret = buf; + } else { + *ret = NULL; + len = -1; + } + + va_end(ap2); + return len; +#endif +} + + + + +KS_DECLARE(int) ks_snprintf(char *buffer, size_t count, const char *fmt, ...) +{ + va_list ap; + int ret; + + va_start(ap, fmt); + ret = vsnprintf(buffer, count-1, fmt, ap); + if (ret < 0) + buffer[count-1] = '\0'; + va_end(ap); + return ret; +} + +static void null_logger(const char *file, const char *func, int line, int level, const char *fmt, ...) +{ + if (file && func && line && level && fmt) { + return; + } + return; +} + + +static const char *LEVEL_NAMES[] = { + "EMERG", + "ALERT", + "CRIT", + "ERROR", + "WARNING", + "NOTICE", + "INFO", + "DEBUG", + NULL +}; + +static int ks_log_level = 7; + +static const char *cut_path(const char *in) +{ + const char *p, *ret = in; + char delims[] = "/\\"; + char *i; + + for (i = delims; *i; i++) { + p = in; + while ((p = strchr(p, *i)) != 0) { + ret = ++p; + } + } + return ret; +} + + +static void default_logger(const char *file, const char *func, int line, int level, const char *fmt, ...) +{ + const char *fp; + char *data; + va_list ap; + int ret; + + if (level < 0 || level > 7) { + level = 7; + } + if (level > ks_log_level) { + return; + } + + fp = cut_path(file); + + va_start(ap, fmt); + + ret = ks_vasprintf(&data, fmt, ap); + + if (ret != -1) { + fprintf(stderr, "[%s] %s:%d %s() %s", LEVEL_NAMES[level], fp, line, func, data); + free(data); + } + + va_end(ap); + +} + +ks_logger_t ks_log = null_logger; + +KS_DECLARE(void) ks_global_set_logger(ks_logger_t logger) +{ + if (logger) { + ks_log = logger; + } else { + ks_log = null_logger; + } +} + +KS_DECLARE(void) ks_global_set_default_logger(int level) +{ + if (level < 0 || level > 7) { + level = 7; + } + + ks_log = default_logger; + ks_log_level = level; +} + +KS_DECLARE(size_t) ks_url_encode(const char *url, char *buf, size_t len) +{ + const char *p; + size_t x = 0; + const char urlunsafe[] = "\r\n \"#%&+:;<=>?@[\\]^`{|}"; + const char hex[] = "0123456789ABCDEF"; + + if (!buf) { + return 0; + } + + if (!url) { + return 0; + } + + len--; + + for (p = url; *p; p++) { + if (x >= len) { + break; + } + if (*p < ' ' || *p > '~' || strchr(urlunsafe, *p)) { + if ((x + 3) >= len) { + break; + } + buf[x++] = '%'; + buf[x++] = hex[*p >> 4]; + buf[x++] = hex[*p & 0x0f]; + } else { + buf[x++] = *p; + } + } + buf[x] = '\0'; + + return x; +} + +KS_DECLARE(char *)ks_url_decode(char *s) +{ + char *o; + unsigned int tmp; + + for (o = s; *s; s++, o++) { + if (*s == '%' && strlen(s) > 2 && sscanf(s + 1, "%2x", &tmp) == 1) { + *o = (char) tmp; + s += 2; + } else { + *o = *s; + } + } + *o = '\0'; + return s; +} + + +static int ks_socket_reuseaddr(ks_socket_t socket) +{ +#ifdef WIN32 + BOOL reuse_addr = TRUE; + return setsockopt(socket, SOL_SOCKET, SO_REUSEADDR, (char *)&reuse_addr, sizeof(reuse_addr)); +#else + int reuse_addr = 1; + return setsockopt(socket, SOL_SOCKET, SO_REUSEADDR, &reuse_addr, sizeof(reuse_addr)); +#endif +} + + +struct thread_handler { + ks_listen_callback_t callback; + ks_socket_t server_sock; + ks_socket_t client_sock; + struct sockaddr_in addr; +}; + +static void *client_thread(ks_thread_t *me, void *obj) +{ + struct thread_handler *handler = (struct thread_handler *) obj; + + handler->callback(handler->server_sock, handler->client_sock, &handler->addr); + free(handler); + + return NULL; + +} + +KS_DECLARE(ks_status_t) ks_listen(const char *host, ks_port_t port, ks_listen_callback_t callback) +{ + ks_socket_t server_sock = KS_SOCK_INVALID; + struct sockaddr_in addr; + ks_status_t status = KS_SUCCESS; + + if ((server_sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) { + return KS_FAIL; + } + + ks_socket_reuseaddr(server_sock); + + memset(&addr, 0, sizeof(addr)); + addr.sin_family = AF_INET; + addr.sin_addr.s_addr = htonl(INADDR_ANY); + addr.sin_port = htons(port); + + if (bind(server_sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) { + status = KS_FAIL; + goto end; + } + + if (listen(server_sock, 10000) < 0) { + status = KS_FAIL; + goto end; + } + + for (;;) { + int client_sock; + struct sockaddr_in echoClntAddr; +#ifdef WIN32 + int clntLen; +#else + unsigned int clntLen; +#endif + + clntLen = sizeof(echoClntAddr); + + if ((client_sock = accept(server_sock, (struct sockaddr *) &echoClntAddr, &clntLen)) == KS_SOCK_INVALID) { + status = KS_FAIL; + goto end; + } + + callback(server_sock, client_sock, &echoClntAddr); + } + + end: + + if (server_sock != KS_SOCK_INVALID) { + closesocket(server_sock); + server_sock = KS_SOCK_INVALID; + } + + return status; + +} + +KS_DECLARE(ks_status_t) ks_listen_threaded(const char *host, ks_port_t port, ks_listen_callback_t callback, int max) +{ + ks_socket_t server_sock = KS_SOCK_INVALID; + struct sockaddr_in addr; + ks_status_t status = KS_SUCCESS; + struct thread_handler *handler = NULL; + + if ((server_sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) { + return KS_FAIL; + } + + ks_socket_reuseaddr(server_sock); + + memset(&addr, 0, sizeof(addr)); + addr.sin_family = AF_INET; + addr.sin_addr.s_addr = htonl(INADDR_ANY); + addr.sin_port = htons(port); + + if (bind(server_sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) { + status = KS_FAIL; + goto end; + } + + if (listen(server_sock, max) < 0) { + status = KS_FAIL; + goto end; + } + + for (;;) { + int client_sock; + struct sockaddr_in echoClntAddr; +#ifdef WIN32 + int clntLen; +#else + unsigned int clntLen; +#endif + + clntLen = sizeof(echoClntAddr); + + if ((client_sock = accept(server_sock, (struct sockaddr *) &echoClntAddr, &clntLen)) == KS_SOCK_INVALID) { + status = KS_FAIL; + goto end; + } + + handler = malloc(sizeof(*handler)); + ks_assert(handler); + + memset(handler, 0, sizeof(*handler)); + handler->callback = callback; + handler->server_sock = server_sock; + handler->client_sock = client_sock; + handler->addr = echoClntAddr; + + ks_thread_create_detached(client_thread, handler); + } + + end: + + if (server_sock != KS_SOCK_INVALID) { + closesocket(server_sock); + server_sock = KS_SOCK_INVALID; + } + + return status; + +} + + +/* USE WSAPoll on vista or higher */ +#ifdef KS_USE_WSAPOLL +KS_DECLARE(int) ks_wait_sock(ks_socket_t sock, uint32_t ms, ks_poll_t flags) +{ +} +#endif + + +#ifdef KS_USE_SELECT +#ifdef WIN32 +#pragma warning( push ) +#pragma warning( disable : 6262 ) /* warning C6262: Function uses '98348' bytes of stack: exceeds /analyze:stacksize'16384'. Consider moving some data to heap */ +#endif +KS_DECLARE(int) ks_wait_sock(ks_socket_t sock, uint32_t ms, ks_poll_t flags) +{ + int s = 0, r = 0; + fd_set rfds; + fd_set wfds; + fd_set efds; + struct timeval tv; + + FD_ZERO(&rfds); + FD_ZERO(&wfds); + FD_ZERO(&efds); + +#ifndef WIN32 + /* Wouldn't you rather know?? */ + assert(sock <= FD_SETSIZE); +#endif + + if ((flags & KS_POLL_READ)) { + +#ifdef WIN32 +#pragma warning( push ) +#pragma warning( disable : 4127 ) + FD_SET(sock, &rfds); +#pragma warning( pop ) +#else + FD_SET(sock, &rfds); +#endif + } + + if ((flags & KS_POLL_WRITE)) { + +#ifdef WIN32 +#pragma warning( push ) +#pragma warning( disable : 4127 ) + FD_SET(sock, &wfds); +#pragma warning( pop ) +#else + FD_SET(sock, &wfds); +#endif + } + + if ((flags & KS_POLL_ERROR)) { + +#ifdef WIN32 +#pragma warning( push ) +#pragma warning( disable : 4127 ) + FD_SET(sock, &efds); +#pragma warning( pop ) +#else + FD_SET(sock, &efds); +#endif + } + + tv.tv_sec = ms / 1000; + tv.tv_usec = (ms % 1000) * ms; + + s = select(sock + 1, (flags & KS_POLL_READ) ? &rfds : NULL, (flags & KS_POLL_WRITE) ? &wfds : NULL, (flags & KS_POLL_ERROR) ? &efds : NULL, &tv); + + if (s < 0) { + r = s; + } else if (s > 0) { + if ((flags & KS_POLL_READ) && FD_ISSET(sock, &rfds)) { + r |= KS_POLL_READ; + } + + if ((flags & KS_POLL_WRITE) && FD_ISSET(sock, &wfds)) { + r |= KS_POLL_WRITE; + } + + if ((flags & KS_POLL_ERROR) && FD_ISSET(sock, &efds)) { + r |= KS_POLL_ERROR; + } + } + + return r; + +} +#ifdef WIN32 +#pragma warning( pop ) +#endif +#endif + +#ifdef KS_USE_POLL +KS_DECLARE(int) ks_wait_sock(ks_socket_t sock, uint32_t ms, ks_poll_t flags) +{ + struct pollfd pfds[2] = { { 0 } }; + int s = 0, r = 0; + + pfds[0].fd = sock; + + if ((flags & KS_POLL_READ)) { + pfds[0].events |= POLLIN; + } + + if ((flags & KS_POLL_WRITE)) { + pfds[0].events |= POLLOUT; + } + + if ((flags & KS_POLL_ERROR)) { + pfds[0].events |= POLLERR; + } + + s = poll(pfds, 1, ms); + + if (s < 0) { + r = s; + } else if (s > 0) { + if ((pfds[0].revents & POLLIN)) { + r |= KS_POLL_READ; + } + if ((pfds[0].revents & POLLOUT)) { + r |= KS_POLL_WRITE; + } + if ((pfds[0].revents & POLLERR)) { + r |= KS_POLL_ERROR; + } + } + + return r; + +} +#endif + + +KS_DECLARE(unsigned int) ks_separate_string_string(char *buf, const char *delim, char **array, unsigned int arraylen) +{ + unsigned int count = 0; + char *d; + size_t dlen = strlen(delim); + + array[count++] = buf; + + while (count < arraylen && array[count - 1]) { + if ((d = strstr(array[count - 1], delim))) { + *d = '\0'; + d += dlen; + array[count++] = d; + } else + break; + } + + return count; +} + diff --git a/libs/libks/src/ks_buffer.c b/libs/libks/src/ks_buffer.c new file mode 100644 index 0000000000..469296a3a9 --- /dev/null +++ b/libs/libks/src/ks_buffer.c @@ -0,0 +1,353 @@ +/* + * Copyright (c) 2010-2012, Anthony Minessale II + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name of the original author; nor the names of any contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#include "ks_buffer.h" + +static unsigned buffer_id = 0; + +struct ks_buffer { + unsigned char *data; + unsigned char *head; + ks_size_t used; + ks_size_t actually_used; + ks_size_t datalen; + ks_size_t max_len; + ks_size_t blocksize; + unsigned id; + int loops; +}; + + +KS_DECLARE(ks_status_t) ks_buffer_create(ks_buffer_t **buffer, ks_size_t blocksize, ks_size_t start_len, ks_size_t max_len) +{ + ks_buffer_t *new_buffer; + + new_buffer = malloc(sizeof(*new_buffer)); + if (new_buffer) { + memset(new_buffer, 0, sizeof(*new_buffer)); + + if (start_len) { + new_buffer->data = malloc(start_len); + if (!new_buffer->data) { + free(new_buffer); + return KS_FAIL; + } + memset(new_buffer->data, 0, start_len); + } + + new_buffer->max_len = max_len; + new_buffer->datalen = start_len; + new_buffer->id = buffer_id++; + new_buffer->blocksize = blocksize; + new_buffer->head = new_buffer->data; + + *buffer = new_buffer; + return KS_SUCCESS; + } + + return KS_FAIL; +} + +KS_DECLARE(ks_size_t) ks_buffer_len(ks_buffer_t *buffer) +{ + + ks_assert(buffer != NULL); + + return buffer->datalen; + +} + + +KS_DECLARE(ks_size_t) ks_buffer_freespace(ks_buffer_t *buffer) +{ + ks_assert(buffer != NULL); + + if (buffer->max_len) { + return (ks_size_t) (buffer->max_len - buffer->used); + } + return 1000000; + +} + +KS_DECLARE(ks_size_t) ks_buffer_inuse(ks_buffer_t *buffer) +{ + ks_assert(buffer != NULL); + + return buffer->used; +} + +KS_DECLARE(ks_size_t) ks_buffer_seek(ks_buffer_t *buffer, ks_size_t datalen) +{ + ks_size_t reading = 0; + + ks_assert(buffer != NULL); + + if (buffer->used < 1) { + buffer->used = 0; + return 0; + } else if (buffer->used >= datalen) { + reading = datalen; + } else { + reading = buffer->used; + } + + buffer->used = buffer->actually_used - reading; + buffer->head = buffer->data + reading; + + return reading; +} + +KS_DECLARE(ks_size_t) ks_buffer_toss(ks_buffer_t *buffer, ks_size_t datalen) +{ + ks_size_t reading = 0; + + ks_assert(buffer != NULL); + + if (buffer->used < 1) { + buffer->used = 0; + return 0; + } else if (buffer->used >= datalen) { + reading = datalen; + } else { + reading = buffer->used; + } + + buffer->used -= reading; + buffer->head += reading; + + return buffer->used; +} + +KS_DECLARE(void) ks_buffer_set_loops(ks_buffer_t *buffer, int loops) +{ + buffer->loops = loops; +} + +KS_DECLARE(ks_size_t) ks_buffer_read_loop(ks_buffer_t *buffer, void *data, ks_size_t datalen) +{ + ks_size_t len; + if ((len = ks_buffer_read(buffer, data, datalen)) < datalen) { + if (buffer->loops == 0) { + return len; + } + buffer->head = buffer->data; + buffer->used = buffer->actually_used; + len = ks_buffer_read(buffer, (char*)data + len, datalen - len); + buffer->loops--; + } + return len; +} + +KS_DECLARE(ks_size_t) ks_buffer_read(ks_buffer_t *buffer, void *data, ks_size_t datalen) +{ + ks_size_t reading = 0; + + ks_assert(buffer != NULL); + ks_assert(data != NULL); + + + if (buffer->used < 1) { + buffer->used = 0; + return 0; + } else if (buffer->used >= datalen) { + reading = datalen; + } else { + reading = buffer->used; + } + + memcpy(data, buffer->head, reading); + buffer->used -= reading; + buffer->head += reading; + + /* if (buffer->id == 4) printf("%u o %d = %d\n", buffer->id, (unsigned)reading, (unsigned)buffer->used); */ + return reading; +} + + +KS_DECLARE(ks_size_t) ks_buffer_packet_count(ks_buffer_t *buffer) +{ + char *pe, *p, *e, *head = (char *) buffer->head; + ks_size_t x = 0; + + ks_assert(buffer != NULL); + + e = (head + buffer->used); + + for (p = head; p && *p && p < e; p++) { + if (*p == '\n') { + pe = p+1; + if (*pe == '\r') pe++; + if (pe <= e && *pe == '\n') { + p = pe++; + x++; + } + } + } + + return x; +} + +KS_DECLARE(ks_size_t) ks_buffer_read_packet(ks_buffer_t *buffer, void *data, ks_size_t maxlen) +{ + char *pe, *p, *e, *head = (char *) buffer->head; + ks_size_t datalen = 0; + + ks_assert(buffer != NULL); + ks_assert(data != NULL); + + e = (head + buffer->used); + + for (p = head; p && *p && p < e; p++) { + if (*p == '\n') { + pe = p+1; + if (*pe == '\r') pe++; + if (pe <= e && *pe == '\n') { + pe++; + datalen = pe - head; + if (datalen > maxlen) { + datalen = maxlen; + } + break; + } + } + } + + return ks_buffer_read(buffer, data, datalen); +} + +KS_DECLARE(ks_size_t) ks_buffer_write(ks_buffer_t *buffer, const void *data, ks_size_t datalen) +{ + ks_size_t freespace, actual_freespace; + + ks_assert(buffer != NULL); + ks_assert(data != NULL); + ks_assert(buffer->data != NULL); + + if (!datalen) { + return buffer->used; + } + + actual_freespace = buffer->datalen - buffer->actually_used; + if (actual_freespace < datalen && (!buffer->max_len || (buffer->used + datalen <= buffer->max_len))) { + memmove(buffer->data, buffer->head, buffer->used); + buffer->head = buffer->data; + buffer->actually_used = buffer->used; + } + + freespace = buffer->datalen - buffer->used; + + /* + if (buffer->data != buffer->head) { + memmove(buffer->data, buffer->head, buffer->used); + buffer->head = buffer->data; + } + */ + + if (freespace < datalen) { + ks_size_t new_size, new_block_size; + void *data1; + + new_size = buffer->datalen + datalen; + new_block_size = buffer->datalen + buffer->blocksize; + + if (new_block_size > new_size) { + new_size = new_block_size; + } + buffer->head = buffer->data; + data1 = realloc(buffer->data, new_size); + if (!data1) { + return 0; + } + buffer->data = data1; + buffer->head = buffer->data; + buffer->datalen = new_size; + } + + + freespace = buffer->datalen - buffer->used; + + if (freespace < datalen) { + return 0; + } else { + memcpy(buffer->head + buffer->used, data, datalen); + buffer->used += datalen; + buffer->actually_used += datalen; + } + /* if (buffer->id == 4) printf("%u i %d = %d\n", buffer->id, (unsigned)datalen, (unsigned)buffer->used); */ + + return buffer->used; +} + +KS_DECLARE(void) ks_buffer_zero(ks_buffer_t *buffer) +{ + ks_assert(buffer != NULL); + ks_assert(buffer->data != NULL); + + buffer->used = 0; + buffer->actually_used = 0; + buffer->head = buffer->data; +} + +KS_DECLARE(ks_size_t) ks_buffer_zwrite(ks_buffer_t *buffer, const void *data, ks_size_t datalen) +{ + ks_size_t w; + + if (!(w = ks_buffer_write(buffer, data, datalen))) { + ks_buffer_zero(buffer); + return ks_buffer_write(buffer, data, datalen); + } + + return w; +} + +KS_DECLARE(void) ks_buffer_destroy(ks_buffer_t **buffer) +{ + if (*buffer) { + free((*buffer)->data); + free(*buffer); + } + + *buffer = NULL; +} + +/* 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: + */ diff --git a/libs/libks/src/ks_config.c b/libs/libks/src/ks_config.c new file mode 100644 index 0000000000..efe410ce2c --- /dev/null +++ b/libs/libks/src/ks_config.c @@ -0,0 +1,256 @@ +/* + * Copyright (c) 2007-2012, Anthony Minessale II + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name of the original author; nor the names of any contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "ks.h" +#include "ks_config.h" + +KS_DECLARE(int) ks_config_open_file(ks_config_t *cfg, const char *file_path) +{ + FILE *f; + const char *path = NULL; + char path_buf[1024]; + + if (file_path[0] == '/') { + path = file_path; + } else { + ks_snprintf(path_buf, sizeof(path_buf), "%s%s%s", KS_CONFIG_DIR, KS_PATH_SEPARATOR, file_path); + path = path_buf; + } + + if (!path) { + return 0; + } + + memset(cfg, 0, sizeof(*cfg)); + cfg->lockto = -1; + ks_log(KS_LOG_DEBUG, "Configuration file is %s.\n", path); + f = fopen(path, "r"); + + if (!f) { + if (file_path[0] != '/') { + int last = -1; + char *var, *val; + + ks_snprintf(path_buf, sizeof(path_buf), "%s%sopenks.conf", KS_CONFIG_DIR, KS_PATH_SEPARATOR); + path = path_buf; + + if ((f = fopen(path, "r")) == 0) { + return 0; + } + + cfg->file = f; + ks_set_string(cfg->path, path); + + while (ks_config_next_pair(cfg, &var, &val)) { + if ((cfg->sectno != last) && !strcmp(cfg->section, file_path)) { + cfg->lockto = cfg->sectno; + return 1; + } + } + + ks_config_close_file(cfg); + memset(cfg, 0, sizeof(*cfg)); + return 0; + } + + return 0; + } else { + cfg->file = f; + ks_set_string(cfg->path, path); + return 1; + } +} + +KS_DECLARE(void) ks_config_close_file(ks_config_t *cfg) +{ + + if (cfg->file) { + fclose(cfg->file); + } + + memset(cfg, 0, sizeof(*cfg)); +} + + + +KS_DECLARE(int) ks_config_next_pair(ks_config_t *cfg, char **var, char **val) +{ + int ret = 0; + char *p, *end; + + *var = *val = NULL; + + if (!cfg || !cfg->file) { + return 0; + } + + for (;;) { + cfg->lineno++; + + if (!fgets(cfg->buf, sizeof(cfg->buf), cfg->file)) { + ret = 0; + break; + } + *var = cfg->buf; + + if (**var == '[' && (end = strchr(*var, ']')) != 0) { + *end = '\0'; + (*var)++; + if (**var == '+') { + (*var)++; + ks_copy_string(cfg->section, *var, sizeof(cfg->section)); + cfg->sectno++; + + if (cfg->lockto > -1 && cfg->sectno != cfg->lockto) { + break; + } + cfg->catno = 0; + cfg->lineno = 0; + *var = (char *) ""; + *val = (char *) ""; + return 1; + } else { + ks_copy_string(cfg->category, *var, sizeof(cfg->category)); + cfg->catno++; + } + continue; + } + + + + if (**var == '#' || **var == ';' || **var == '\n' || **var == '\r') { + continue; + } + + if (!strncmp(*var, "__END__", 7)) { + break; + } + + + if ((end = strchr(*var, ';')) && *(end+1) == *end) { + *end = '\0'; + end--; + } else if ((end = strchr(*var, '\n')) != 0) { + if (*(end - 1) == '\r') { + end--; + } + *end = '\0'; + } + + p = *var; + while ((*p == ' ' || *p == '\t') && p != end) { + *p = '\0'; + p++; + } + *var = p; + + + if ((*val = strchr(*var, '=')) == 0) { + ret = -1; + /* log_printf(0, server.log, "Invalid syntax on %s: line %d\n", cfg->path, cfg->lineno); */ + continue; + } else { + p = *val - 1; + *(*val) = '\0'; + (*val)++; + if (*(*val) == '>') { + *(*val) = '\0'; + (*val)++; + } + + while ((*p == ' ' || *p == '\t') && p != *var) { + *p = '\0'; + p--; + } + + p = *val; + while ((*p == ' ' || *p == '\t') && p != end) { + *p = '\0'; + p++; + } + *val = p; + ret = 1; + break; + } + } + + + return ret; + +} + +KS_DECLARE(int) ks_config_get_cas_bits(char *strvalue, unsigned char *outbits) +{ + char cas_bits[5]; + unsigned char bit = 0x8; + char *double_colon = strchr(strvalue, ':'); + int x = 0; + + if (!double_colon) { + ks_log(KS_LOG_ERROR, "No CAS bits specified: %s, :xxxx definition expected, where x is 1 or 0\n", double_colon); + return -1; + } + + double_colon++; + *outbits = 0; + cas_bits[4] = 0; + + if (sscanf(double_colon, "%c%c%c%c", &cas_bits[0], &cas_bits[1], &cas_bits[2], &cas_bits[3]) != 4) { + ks_log(KS_LOG_ERROR, "Invalid CAS bits specified: %s, :xxxx definition expected, where x is 1 or 0\n", double_colon); + return -1; + } + + ks_log(KS_LOG_DEBUG, "CAS bits specification found: %s\n", cas_bits); + + for (; cas_bits[x]; x++) { + if ('1' == cas_bits[x]) { + *outbits |= bit; + } else if ('0' != cas_bits[x]) { + ks_log(KS_LOG_ERROR, "Invalid CAS pattern specified: %s, just 0 or 1 allowed for each bit\n"); + return -1; + } + bit >>= 1; + } + return 0; +} + +/* 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: + */ diff --git a/libs/libks/src/ks_json.c b/libs/libks/src/ks_json.c new file mode 100644 index 0000000000..ffa965a609 --- /dev/null +++ b/libs/libks/src/ks_json.c @@ -0,0 +1,529 @@ +/* + Copyright (c) 2009 Dave Gamble + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +*/ + +/* cJSON */ +/* JSON parser in C. */ + +#include +#include +#include +#include +#include +#include +#include +#include "ks_json.h" +#include "ks.h" + +static const char *ep; + +KS_DECLARE(const char *)cJSON_GetErrorPtr() {return ep;} + +static int cJSON_strcasecmp(const char *s1,const char *s2) +{ + if (!s1) return (s1==s2)?0:1;if (!s2) return 1; + for(; tolower(*s1) == tolower(*s2); ++s1, ++s2) if(*s1 == 0) return 0; + return tolower(*(const unsigned char *)s1) - tolower(*(const unsigned char *)s2); +} + +static void *glue_malloc(size_t theSize) +{ + return(malloc(theSize)); +} + +static void glue_free(void *thePtr) +{ + free(thePtr); +} + +static void *(*cJSON_malloc)(size_t sz) = glue_malloc; +static void (*cJSON_free)(void *ptr) = glue_free; + +static char* cJSON_strdup(const char* str) +{ + size_t len; + char* copy; + const char *s = str ? str : ""; + + len = strlen(s) + 1; + if (!(copy = (char*)cJSON_malloc(len))) return 0; + memcpy(copy,s,len); + return copy; +} + +KS_DECLARE(void)cJSON_InitHooks(cJSON_Hooks* hooks) +{ + if (!hooks) { /* Reset hooks */ + cJSON_malloc = malloc; + cJSON_free = free; + return; + } + + cJSON_malloc = (hooks->malloc_fn)?hooks->malloc_fn:malloc; + cJSON_free = (hooks->free_fn)?hooks->free_fn:free; +} + +/* Internal constructor. */ +static cJSON *cJSON_New_Item() +{ + cJSON* node = (cJSON*)cJSON_malloc(sizeof(cJSON)); + if (node) memset(node,0,sizeof(cJSON)); + return node; +} + +/* Delete a cJSON structure. */ +KS_DECLARE(void)cJSON_Delete(cJSON *c) +{ + cJSON *next; + while (c) + { + next=c->next; + if (!(c->type&cJSON_IsReference) && c->child) cJSON_Delete(c->child); + if (!(c->type&cJSON_IsReference) && c->valuestring) cJSON_free(c->valuestring); + if (c->string) cJSON_free(c->string); + cJSON_free(c); + c=next; + } +} + +/* Parse the input text to generate a number, and populate the result into item. */ +static const char *parse_number(cJSON *item,const char *num) +{ + double n=0,sign=1,scale=0;int subscale=0,signsubscale=1; + + /* Could use sscanf for this? */ + if (*num=='-') sign=-1,num++; /* Has sign? */ + if (*num=='0') num++; /* is zero */ + if (*num>='1' && *num<='9') do n=(n*10.0)+(*num++ -'0'); while (*num>='0' && *num<='9'); /* Number? */ + if (*num=='.' && num[1]>='0' && num[1]<='9') {num++; do n=(n*10.0)+(*num++ -'0'),scale--; while (*num>='0' && *num<='9');} /* Fractional part? */ + if (*num=='e' || *num=='E') /* Exponent? */ + { num++;if (*num=='+') num++; else if (*num=='-') signsubscale=-1,num++; /* With sign? */ + while (*num>='0' && *num<='9') subscale=(subscale*10)+(*num++ - '0'); /* Number? */ + } + + n=sign*n*pow(10.0,(scale+subscale*signsubscale)); /* number = +/- number.fraction * 10^+/- exponent */ + + item->valuedouble=n; + item->valueint=(int)n; + item->type=cJSON_Number; + return num; +} + +/* Render the number nicely from the given item into a string. */ +static char *print_number(cJSON *item) +{ + char *str; + double d=item->valuedouble; + if (fabs(((double)item->valueint)-d)<=DBL_EPSILON && d<=INT_MAX && d>=INT_MIN) + { + str=(char*)cJSON_malloc(21); /* 2^64+1 can be represented in 21 chars. */ + if (str) sprintf(str,"%d",item->valueint); + } + else + { + str=(char*)cJSON_malloc(64); /* This is a nice tradeoff. */ + if (str) + { + if (fabs(floor(d)-d)<=DBL_EPSILON) sprintf(str,"%.0f",d); + else if (fabs(d)<1.0e-6 || fabs(d)>1.0e9) sprintf(str,"%e",d); + else sprintf(str,"%f",d); + } + } + return str; +} + +/* Parse the input text into an unescaped cstring, and populate item. */ +static const unsigned char firstByteMark[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC }; +static const char *parse_string(cJSON *item,const char *str) +{ + const char *ptr=str+1;char *ptr2;char *out;int len=0;unsigned uc,uc2; + if (*str!='\"') {ep=str;return 0;} /* not a string! */ + + while (*ptr!='\"' && *ptr && ++len) if (*ptr++ == '\\') ptr++; /* Skip escaped quotes. */ + + out=(char*)cJSON_malloc(len+1); /* This is how long we need for the string, roughly. */ + if (!out) return 0; + + ptr=str+1;ptr2=out; + while (*ptr!='\"' && *ptr) + { + if (*ptr!='\\') *ptr2++=*ptr++; + else + { + ptr++; + switch (*ptr) + { + case 'b': *ptr2++='\b'; break; + case 'f': *ptr2++='\f'; break; + case 'n': *ptr2++='\n'; break; + case 'r': *ptr2++='\r'; break; + case 't': *ptr2++='\t'; break; + case 'u': /* transcode utf16 to utf8. */ + if (sscanf(ptr+1,"%4x",&uc) < 1) break; + + ptr+=4; /* get the unicode char. */ + + if ((uc>=0xDC00 && uc<=0xDFFF) || uc==0) break; // check for invalid. + + if (uc>=0xD800 && uc<=0xDBFF) // UTF16 surrogate pairs. + { + if (ptr[1]!='\\' || ptr[2]!='u') break; // missing second-half of surrogate. + if (sscanf(ptr+3,"%4x",&uc2) < 1) break; + ptr+=6; + if (uc2<0xDC00 || uc2>0xDFFF) break; // invalid second-half of surrogate. + uc=0x10000 | ((uc&0x3FF)<<10) | (uc2&0x3FF); + } + + len=4;if (uc<0x80) len=1;else if (uc<0x800) len=2;else if (uc<0x10000) len=3; ptr2+=len; + + switch (len) { + case 4: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6; + case 3: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6; + case 2: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6; + case 1: *--ptr2 =(char)(uc | firstByteMark[len]); + } + ptr2+=len; + break; + default: *ptr2++=*ptr; break; + } + ptr++; + } + } + *ptr2=0; + if (*ptr=='\"') ptr++; + item->valuestring=out; + item->type=cJSON_String; + return ptr; +} + +/* Render the cstring provided to an escaped version that can be printed. */ +static char *print_string_ptr(const char *str) +{ + const char *ptr;char *ptr2,*out;int len=0;unsigned char token; + + if (!str) return cJSON_strdup(""); + ptr=str;while ((token=*ptr) && ++len) {if (strchr("\"\\\b\f\n\r\t",token)) len++; else if (token<32) len+=5;ptr++;} + + out=(char*)cJSON_malloc(len+3); + if (!out) return 0; + + ptr2=out;ptr=str; + *ptr2++='\"'; + while (*ptr) + { + if ((unsigned char)*ptr>31 && *ptr!='\"' && *ptr!='\\') *ptr2++=*ptr++; + else + { + *ptr2++='\\'; + switch (token=*ptr++) + { + case '\\': *ptr2++='\\'; break; + case '\"': *ptr2++='\"'; break; + case '\b': *ptr2++='b'; break; + case '\f': *ptr2++='f'; break; + case '\n': *ptr2++='n'; break; + case '\r': *ptr2++='r'; break; + case '\t': *ptr2++='t'; break; + default: sprintf(ptr2,"u%04x",token);ptr2+=5; break; /* escape and print */ + } + } + } + *ptr2++='\"';*ptr2++=0; + return out; +} +/* Invote print_string_ptr (which is useful) on an item. */ +static char *print_string(cJSON *item) {return print_string_ptr(item->valuestring);} + +/* Predeclare these prototypes. */ +static const char *parse_value(cJSON *item,const char *value); +static char *print_value(cJSON *item,int depth,int fmt); +static const char *parse_array(cJSON *item,const char *value); +static char *print_array(cJSON *item,int depth,int fmt); +static const char *parse_object(cJSON *item,const char *value); +static char *print_object(cJSON *item,int depth,int fmt); + +/* Utility to jump whitespace and cr/lf */ +static const char *skip(const char *in) {while (in && *in && (unsigned char)*in<=32) in++; return in;} + +/* Parse an object - create a new root, and populate. */ +KS_DECLARE(cJSON *)cJSON_Parse(const char *value) +{ + cJSON *c=cJSON_New_Item(); + ep=0; + if (!c) return 0; /* memory fail */ + + if (!parse_value(c,skip(value))) {cJSON_Delete(c);return 0;} + return c; +} + +/* Render a cJSON item/entity/structure to text. */ +KS_DECLARE(char *) cJSON_Print(cJSON *item) {return print_value(item,0,1);} +KS_DECLARE(char *) cJSON_PrintUnformatted(cJSON *item) {return print_value(item,0,0);} + +/* Parser core - when encountering text, process appropriately. */ +static const char *parse_value(cJSON *item,const char *value) +{ + if (!value) return 0; /* Fail on null. */ + if (!strncmp(value,"null",4)) { item->type=cJSON_NULL; return value+4; } + if (!strncmp(value,"false",5)) { item->type=cJSON_False; return value+5; } + if (!strncmp(value,"true",4)) { item->type=cJSON_True; item->valueint=1; return value+4; } + if (*value=='\"') { return parse_string(item,value); } + if (*value=='-' || (*value>='0' && *value<='9')) { return parse_number(item,value); } + if (*value=='[') { return parse_array(item,value); } + if (*value=='{') { return parse_object(item,value); } + + ep=value;return 0; /* failure. */ +} + +/* Render a value to text. */ +static char *print_value(cJSON *item,int depth,int fmt) +{ + char *out=0; + if (!item) return 0; + switch ((item->type)&255) + { + case cJSON_NULL: out=cJSON_strdup("null"); break; + case cJSON_False: out=cJSON_strdup("false");break; + case cJSON_True: out=cJSON_strdup("true"); break; + case cJSON_Number: out=print_number(item);break; + case cJSON_String: out=print_string(item);break; + case cJSON_Array: out=print_array(item,depth,fmt);break; + case cJSON_Object: out=print_object(item,depth,fmt);break; + } + return out; +} + +/* Build an array from input text. */ +static const char *parse_array(cJSON *item,const char *value) +{ + cJSON *child; + if (*value!='[') {ep=value;return 0;} /* not an array! */ + + item->type=cJSON_Array; + value=skip(value+1); + if (*value==']') return value+1; /* empty array. */ + + item->child=child=cJSON_New_Item(); + if (!item->child) return 0; /* memory fail */ + value=skip(parse_value(child,skip(value))); /* skip any spacing, get the value. */ + if (!value) return 0; + + while (*value==',') + { + cJSON *new_item; + if (!(new_item=cJSON_New_Item())) return 0; /* memory fail */ + child->next=new_item;new_item->prev=child;child=new_item; + value=skip(parse_value(child,skip(value+1))); + if (!value) return 0; /* memory fail */ + } + + if (*value==']') return value+1; /* end of array */ + ep=value;return 0; /* malformed. */ +} + +/* Render an array to text */ +static char *print_array(cJSON *item,int depth,int fmt) +{ + char **entries; + char *out=0,*ptr,*ret;int len=5; + cJSON *child=item->child; + int numentries=0,i=0,fail=0; + + /* How many entries in the array? */ + while (child) numentries++,child=child->next; + /* Allocate an array to hold the values for each */ + entries=(char**)cJSON_malloc(numentries*sizeof(char*)); + if (!entries) return 0; + memset(entries,0,numentries*sizeof(char*)); + /* Retrieve all the results: */ + child=item->child; + while (child && !fail) + { + ret=print_value(child,depth+1,fmt); + entries[i++]=ret; + if (ret) len+=strlen(ret)+2+(fmt?1:0); else fail=1; + child=child->next; + } + + /* If we didn't fail, try to malloc the output string */ + if (!fail) out=(char*)cJSON_malloc(len); + /* If that fails, we fail. */ + if (!out) fail=1; + + /* Handle failure. */ + if (fail) + { + for (i=0;itype=cJSON_Object; + value=skip(value+1); + if (*value=='}') return value+1; /* empty array. */ + + item->child=child=cJSON_New_Item(); + if (!item->child) return 0; + value=skip(parse_string(child,skip(value))); + if (!value) return 0; + child->string=child->valuestring;child->valuestring=0; + if (*value!=':') {ep=value;return 0;} /* fail! */ + value=skip(parse_value(child,skip(value+1))); /* skip any spacing, get the value. */ + if (!value) return 0; + + while (*value==',') + { + cJSON *new_item; + if (!(new_item=cJSON_New_Item())) return 0; /* memory fail */ + child->next=new_item;new_item->prev=child;child=new_item; + value=skip(parse_string(child,skip(value+1))); + if (!value) return 0; + child->string=child->valuestring;child->valuestring=0; + if (*value!=':') {ep=value;return 0;} /* fail! */ + value=skip(parse_value(child,skip(value+1))); /* skip any spacing, get the value. */ + if (!value) return 0; + } + + if (*value=='}') return value+1; /* end of array */ + ep=value;return 0; /* malformed. */ +} + +/* Render an object to text. */ +static char *print_object(cJSON *item,int depth,int fmt) +{ + char **entries=0,**names=0; + char *out=0,*ptr,*ret,*str;int len=7,i=0,j; + cJSON *child=item->child; + int numentries=0,fail=0; + /* Count the number of entries. */ + while (child) numentries++,child=child->next; + /* Allocate space for the names and the objects */ + entries=(char**)cJSON_malloc(numentries*sizeof(char*)); + if (!entries) return 0; + names=(char**)cJSON_malloc(numentries*sizeof(char*)); + if (!names) {cJSON_free(entries);return 0;} + memset(entries,0,sizeof(char*)*numentries); + memset(names,0,sizeof(char*)*numentries); + + /* Collect all the results into our arrays: */ + child=item->child;depth++;if (fmt) len+=depth; + while (child) + { + names[i]=str=print_string_ptr(child->string); + entries[i++]=ret=print_value(child,depth,fmt); + if (str && ret) len+=strlen(ret)+strlen(str)+2+(fmt?2+depth:0); else fail=1; + child=child->next; + } + + /* Try to allocate the output string */ + if (!fail) out=(char*)cJSON_malloc(len); + if (!out) fail=1; + + /* Handle failure */ + if (fail) + { + for (i=0;ichild;int i=0;while(c)i++,c=c->next;return i;} +KS_DECLARE(cJSON *)cJSON_GetArrayItem(cJSON *array,int item) {cJSON *c=array->child; while (c && item>0) item--,c=c->next; return c;} +KS_DECLARE(cJSON *)cJSON_GetObjectItem(cJSON *object,const char *string) {cJSON *c=object->child; while (c && cJSON_strcasecmp(c->string,string)) c=c->next; return c;} + +/* Utility for array list handling. */ +static void suffix_object(cJSON *prev,cJSON *item) {prev->next=item;item->prev=prev;} +/* Utility for handling references. */ +static cJSON *create_reference(cJSON *item) {cJSON *ref=cJSON_New_Item();if (!ref) return 0;memcpy(ref,item,sizeof(cJSON));ref->string=0;ref->type|=cJSON_IsReference;ref->next=ref->prev=0;return ref;} + +/* Add item to array/object. */ +KS_DECLARE(void) cJSON_AddItemToArray(cJSON *array, cJSON *item) {cJSON *c=array->child;if (!item) return; if (!c) {array->child=item;} else {while (c && c->next) c=c->next; suffix_object(c,item);}} +KS_DECLARE(void) cJSON_AddItemToObject(cJSON *object,const char *string,cJSON *item) {if (!item) return; if (item->string) cJSON_free(item->string);item->string=cJSON_strdup(string);cJSON_AddItemToArray(object,item);} +KS_DECLARE(void) cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item) {cJSON_AddItemToArray(array,create_reference(item));} +KS_DECLARE(void) cJSON_AddItemReferenceToObject(cJSON *object,const char *string,cJSON *item) {cJSON_AddItemToObject(object,string,create_reference(item));} + +KS_DECLARE(cJSON *)cJSON_DetachItemFromArray(cJSON *array,int which) {cJSON *c=array->child;while (c && which>0) c=c->next,which--;if (!c) return 0; + if (c->prev) c->prev->next=c->next;if (c->next) c->next->prev=c->prev;if (c==array->child) array->child=c->next;c->prev=c->next=0;return c;} +KS_DECLARE(void) cJSON_DeleteItemFromArray(cJSON *array,int which) {cJSON_Delete(cJSON_DetachItemFromArray(array,which));} +KS_DECLARE(cJSON *)cJSON_DetachItemFromObject(cJSON *object,const char *string) {int i=0;cJSON *c=object->child;while (c && cJSON_strcasecmp(c->string,string)) i++,c=c->next;if (c) return cJSON_DetachItemFromArray(object,i);return 0;} +KS_DECLARE(void) cJSON_DeleteItemFromObject(cJSON *object,const char *string) {cJSON_Delete(cJSON_DetachItemFromObject(object,string));} + +/* Replace array/object items with new ones. */ +KS_DECLARE(void) cJSON_ReplaceItemInArray(cJSON *array,int which,cJSON *newitem) {cJSON *c=array->child;while (c && which>0) c=c->next,which--;if (!c) return; + newitem->next=c->next;newitem->prev=c->prev;if (newitem->next) newitem->next->prev=newitem; + if (c==array->child) array->child=newitem; else newitem->prev->next=newitem;c->next=c->prev=0;cJSON_Delete(c);} +KS_DECLARE(void) cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem){int i=0;cJSON *c=object->child;while(c && cJSON_strcasecmp(c->string,string))i++,c=c->next;if(c){newitem->string=cJSON_strdup(string);cJSON_ReplaceItemInArray(object,i,newitem);}} + +/* Create basic types: */ +KS_DECLARE(cJSON *)cJSON_CreateNull() {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_NULL;return item;} +KS_DECLARE(cJSON *)cJSON_CreateTrue() {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_True;return item;} +KS_DECLARE(cJSON *)cJSON_CreateFalse() {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_False;return item;} +KS_DECLARE(cJSON *)cJSON_CreateBool(int b) {cJSON *item=cJSON_New_Item();if(item)item->type=b?cJSON_True:cJSON_False;return item;} +KS_DECLARE(cJSON *)cJSON_CreateNumber(double num) {cJSON *item=cJSON_New_Item();if(item){item->type=cJSON_Number;item->valuedouble=num;item->valueint=(int)num;}return item;} +KS_DECLARE(cJSON *)cJSON_CreateString(const char *string) {cJSON *item=cJSON_New_Item();if(item){item->type=cJSON_String;item->valuestring=cJSON_strdup(string);}return item;} +KS_DECLARE(cJSON *)cJSON_CreateArray() {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_Array;return item;} +KS_DECLARE(cJSON *)cJSON_CreateObject() {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_Object;return item;} + +/* Create Arrays: */ +KS_DECLARE(cJSON *)cJSON_CreateIntArray(int *numbers,int count) {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a!=0 && ichild=n;else suffix_object(p,n);p=n;}return a;} +KS_DECLARE(cJSON *)cJSON_CreateFloatArray(float *numbers,int count) {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a!=0 && ichild=n;else suffix_object(p,n);p=n;}return a;} +KS_DECLARE(cJSON *)cJSON_CreateDoubleArray(double *numbers,int count) {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a!=0 && ichild=n;else suffix_object(p,n);p=n;}return a;} +KS_DECLARE(cJSON *)cJSON_CreateStringArray(const char **strings,int count) {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a!=0 && ichild=n;else suffix_object(p,n);p=n;}return a;} diff --git a/libs/libks/src/ks_threadmutex.c b/libs/libks/src/ks_threadmutex.c new file mode 100644 index 0000000000..a23c02f762 --- /dev/null +++ b/libs/libks/src/ks_threadmutex.c @@ -0,0 +1,239 @@ +/* + * Cross Platform Thread/Mutex abstraction + * Copyright(C) 2007 Michael Jerris + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so. + * + * This work is provided under this license on an "as is" basis, without warranty of any kind, + * either expressed or implied, including, without limitation, warranties that the covered code + * is free of defects, merchantable, fit for a particular purpose or non-infringing. The entire + * risk as to the quality and performance of the covered code is with you. Should any covered + * code prove defective in any respect, you (not the initial developer or any other contributor) + * assume the cost of any necessary servicing, repair or correction. This disclaimer of warranty + * constitutes an essential part of this license. No use of any covered code is authorized hereunder + * except under this disclaimer. + * + */ + +#ifdef WIN32 +/* required for TryEnterCriticalSection definition. Must be defined before windows.h include */ +#define _WIN32_WINNT 0x0400 +#endif + +#include "ks.h" +#include "ks_threadmutex.h" + +#ifdef WIN32 +#include + +#define KS_THREAD_CALLING_CONVENTION __stdcall + +struct ks_mutex { + CRITICAL_SECTION mutex; +}; + +#else + +#include + +#define KS_THREAD_CALLING_CONVENTION + +struct ks_mutex { + pthread_mutex_t mutex; +}; + +#endif + +struct ks_thread { +#ifdef WIN32 + void *handle; +#else + pthread_t handle; +#endif + void *private_data; + ks_thread_function_t function; + size_t stack_size; +#ifndef WIN32 + pthread_attr_t attribute; +#endif +}; + +size_t thread_default_stacksize = 240 * 1024; + +void ks_thread_override_default_stacksize(size_t size) +{ + thread_default_stacksize = size; +} + +static void * KS_THREAD_CALLING_CONVENTION thread_launch(void *args) +{ + void *exit_val; + ks_thread_t *thread = (ks_thread_t *)args; + exit_val = thread->function(thread, thread->private_data); +#ifndef WIN32 + pthread_attr_destroy(&thread->attribute); +#endif + free(thread); + + return exit_val; +} + +KS_DECLARE(ks_status_t) ks_thread_create_detached(ks_thread_function_t func, void *data) +{ + return ks_thread_create_detached_ex(func, data, thread_default_stacksize); +} + +ks_status_t ks_thread_create_detached_ex(ks_thread_function_t func, void *data, size_t stack_size) +{ + ks_thread_t *thread = NULL; + ks_status_t status = KS_FAIL; + + if (!func || !(thread = (ks_thread_t *)malloc(sizeof(ks_thread_t)))) { + goto done; + } + + thread->private_data = data; + thread->function = func; + thread->stack_size = stack_size; + +#if defined(WIN32) + thread->handle = (void *)_beginthreadex(NULL, (unsigned)thread->stack_size, (unsigned int (__stdcall *)(void *))thread_launch, thread, 0, NULL); + if (!thread->handle) { + goto fail; + } + CloseHandle(thread->handle); + + status = KS_SUCCESS; + goto done; +#else + + if (pthread_attr_init(&thread->attribute) != 0) goto fail; + + if (pthread_attr_setdetachstate(&thread->attribute, PTHREAD_CREATE_DETACHED) != 0) goto failpthread; + + if (thread->stack_size && pthread_attr_setstacksize(&thread->attribute, thread->stack_size) != 0) goto failpthread; + + if (pthread_create(&thread->handle, &thread->attribute, thread_launch, thread) != 0) goto failpthread; + + status = KS_SUCCESS; + goto done; + + failpthread: + + pthread_attr_destroy(&thread->attribute); +#endif + + fail: + if (thread) { + free(thread); + } + done: + return status; +} + + +KS_DECLARE(ks_status_t) ks_mutex_create(ks_mutex_t **mutex) +{ + ks_status_t status = KS_FAIL; +#ifndef WIN32 + pthread_mutexattr_t attr; +#endif + ks_mutex_t *check = NULL; + + check = (ks_mutex_t *)malloc(sizeof(**mutex)); + if (!check) + goto done; +#ifdef WIN32 + InitializeCriticalSection(&check->mutex); +#else + if (pthread_mutexattr_init(&attr)) + goto done; + + if (pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE)) + goto fail; + + if (pthread_mutex_init(&check->mutex, &attr)) + goto fail; + + goto success; + + fail: + pthread_mutexattr_destroy(&attr); + goto done; + + success: +#endif + *mutex = check; + status = KS_SUCCESS; + + done: + return status; +} + +KS_DECLARE(ks_status_t) ks_mutex_destroy(ks_mutex_t **mutex) +{ + ks_mutex_t *mp = *mutex; + *mutex = NULL; + if (!mp) { + return KS_FAIL; + } +#ifdef WIN32 + DeleteCriticalSection(&mp->mutex); +#else + if (pthread_mutex_destroy(&mp->mutex)) + return KS_FAIL; +#endif + free(mp); + return KS_SUCCESS; +} + +KS_DECLARE(ks_status_t) ks_mutex_lock(ks_mutex_t *mutex) +{ +#ifdef WIN32 + EnterCriticalSection(&mutex->mutex); +#else + if (pthread_mutex_lock(&mutex->mutex)) + return KS_FAIL; +#endif + return KS_SUCCESS; +} + +KS_DECLARE(ks_status_t) ks_mutex_trylock(ks_mutex_t *mutex) +{ +#ifdef WIN32 + if (!TryEnterCriticalSection(&mutex->mutex)) + return KS_FAIL; +#else + if (pthread_mutex_trylock(&mutex->mutex)) + return KS_FAIL; +#endif + return KS_SUCCESS; +} + +KS_DECLARE(ks_status_t) ks_mutex_unlock(ks_mutex_t *mutex) +{ +#ifdef WIN32 + LeaveCriticalSection(&mutex->mutex); +#else + if (pthread_mutex_unlock(&mutex->mutex)) + return KS_FAIL; +#endif + return KS_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: + */ diff --git a/libs/libks/src/mpool.c b/libs/libks/src/mpool.c new file mode 100644 index 0000000000..72c5b6b108 --- /dev/null +++ b/libs/libks/src/mpool.c @@ -0,0 +1,1768 @@ +/* + * Memory pool routines. + * + * Copyright 1996 by Gray Watson. + * + * This file is part of the mpool package. + * + * Permission to use, copy, modify, and distribute this software for + * any purpose and without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies, and that the name of Gray Watson not be used in advertising + * or publicity pertaining to distribution of the document or software + * without specific, written prior permission. + * + * Gray Watson makes no representations about the suitability of the + * software described herein for any purpose. It is provided "as is" + * without express or implied warranty. + * + * The author may be reached via http://256.com/gray/ + * + * $Id: mpool.c,v 1.5 2006/05/31 20:28:31 gray Exp $ + */ + +/* + * Memory-pool allocation routines. I got sick of the GNU mmalloc + * library which was close to what we needed but did not exactly do + * what I wanted. + * + * The following uses mmap from /dev/zero. It allows a number of + * allocations to be made inside of a memory pool then with a clear or + * close the pool can be reset without any memory fragmentation and + * growth problems. + */ + +#include +#include +#include +#include +#include +#include +#include + +#ifdef DMALLOC +#include "dmalloc.h" +#endif + +#define MPOOL_MAIN + +#include "mpool.h" +#include "mpool_loc.h" + +#ifdef __GNUC__ +#ident "$Id: mpool.c,v 1.5 2006/05/31 20:28:31 gray Exp $" +#else +static char *rcs_id = "$Id: mpool.c,v 1.5 2006/05/31 20:28:31 gray Exp $"; +#endif + +/* version */ +static char *version = "mpool library version 2.1.0"; + +/* local variables */ +static int enabled_b = 0; /* lib initialized? */ +static unsigned int min_bit_free_next = 0; /* min size of next pnt */ +static unsigned int min_bit_free_size = 0; /* min size of next + size */ +static unsigned long bit_array[MAX_BITS + 1]; /* size -> bit */ + +/****************************** local utilities ******************************/ + +/* + * static void startup + * + * DESCRIPTION: + * + * Perform any library level initialization. + * + * RETURNS: + * + * None. + * + * ARGUMENTS: + * + * None. + */ +static void startup(void) +{ + int bit_c; + unsigned long size = 1; + + if (enabled_b) { + return; + } + + /* allocate our free bit array list */ + for (bit_c = 0; bit_c <= MAX_BITS; bit_c++) { + bit_array[bit_c] = size; + + /* + * Note our minimum number of bits that can store a pointer. This + * is smallest address that we can have a linked list for. + */ + if (min_bit_free_next == 0 && size >= sizeof(void *)) { + min_bit_free_next = bit_c; + } + /* + * Note our minimum number of bits that can store a pointer and + * the size of the block. + */ + if (min_bit_free_size == 0 && size >= sizeof(mpool_free_t)) { + min_bit_free_size = bit_c; + } + + size *= 2; + } + + enabled_b = 1; +} + +/* + * static int size_to_bits + * + * DESCRIPTION: + * + * Calculate the number of bits in a size. + * + * RETURNS: + * + * Number of bits. + * + * ARGUMENTS: + * + * size -> Size of memory of which to calculate the number of bits. + */ +static int size_to_bits(const unsigned long size) +{ + int bit_c = 0; + + for (bit_c = 0; bit_c <= MAX_BITS; bit_c++) { + if (size <= bit_array[bit_c]) { + break; + } + } + + return bit_c; +} + +/* + * static int size_to_free_bits + * + * DESCRIPTION: + * + * Calculate the number of bits in a size going on the free list. + * + * RETURNS: + * + * Number of bits. + * + * ARGUMENTS: + * + * size -> Size of memory of which to calculate the number of bits. + */ +static int size_to_free_bits(const unsigned long size) +{ + int bit_c = 0; + + if (size == 0) { + return 0; + } + + for (bit_c = 0; bit_c <= MAX_BITS; bit_c++) { + if (size < bit_array[bit_c]) { + break; + } + } + + return bit_c - 1; +} + +/* + * static int bits_to_size + * + * DESCRIPTION: + * + * Calculate the size represented by a number of bits. + * + * RETURNS: + * + * Number of bits. + * + * ARGUMENTS: + * + * bit_n -> Number of bits + */ +static unsigned long bits_to_size(const int bit_n) +{ + if (bit_n > MAX_BITS) { + return bit_array[MAX_BITS]; + } + else { + return bit_array[bit_n]; + } +} + +/* + * static void *alloc_pages + * + * DESCRIPTION: + * + * Allocate space for a number of memory pages in the memory pool. + * + * RETURNS: + * + * Success - New pages of memory + * + * Failure - NULL + * + * ARGUMENTS: + * + * mp_p <-> Pointer to our memory pool. + * + * page_n -> Number of pages to alloc. + * + * error_p <- Pointer to integer which, if not NULL, will be set with + * a mpool error code. + */ +static void *alloc_pages(mpool_t *mp_p, const unsigned int page_n, + int *error_p) +{ + void *mem, *fill_mem; + unsigned long size, fill; + int state; + + /* are we over our max-pages? */ + if (mp_p->mp_max_pages > 0 && mp_p->mp_page_c >= mp_p->mp_max_pages) { + SET_POINTER(error_p, MPOOL_ERROR_NO_PAGES); + return NULL; + } + + size = SIZE_OF_PAGES(mp_p, page_n); + +#ifdef DEBUG + (void)printf("allocating %u pages or %lu bytes\n", page_n, size); +#endif + + if (BIT_IS_SET(mp_p->mp_flags, MPOOL_FLAG_USE_SBRK)) { + mem = sbrk(size); + if (mem == (void *)-1) { + SET_POINTER(error_p, MPOOL_ERROR_NO_MEM); + return NULL; + } + fill = (unsigned long)mem % mp_p->mp_page_size; + + if (fill > 0) { + fill = mp_p->mp_page_size - fill; + fill_mem = sbrk(fill); + if (fill_mem == (void *)-1) { + SET_POINTER(error_p, MPOOL_ERROR_NO_MEM); + return NULL; + } + if ((char *)fill_mem != (char *)mem + size) { + SET_POINTER(error_p, MPOOL_ERROR_SBRK_CONTIG); + return NULL; + } + mem = (char *)mem + fill; + } + } + else { + state = MAP_PRIVATE; +#ifdef MAP_FILE + state |= MAP_FILE; +#endif +#ifdef MAP_VARIABLE + state |= MAP_VARIABLE; +#endif + + /* mmap from /dev/zero */ + mem = mmap((caddr_t)mp_p->mp_addr, size, PROT_READ | PROT_WRITE, state, + mp_p->mp_fd, mp_p->mp_top); + if (mem == (void *)MAP_FAILED) { + if (errno == ENOMEM) { + SET_POINTER(error_p, MPOOL_ERROR_NO_MEM); + } + else { + SET_POINTER(error_p, MPOOL_ERROR_MMAP); + } + return NULL; + } + mp_p->mp_top += size; + if (mp_p->mp_addr != NULL) { + mp_p->mp_addr = (char *)mp_p->mp_addr + size; + } + } + + mp_p->mp_page_c += page_n; + + SET_POINTER(error_p, MPOOL_ERROR_NONE); + return mem; +} + +/* + * static int free_pages + * + * DESCRIPTION: + * + * Free previously allocated pages of memory. + * + * RETURNS: + * + * Success - MPOOL_ERROR_NONE + * + * Failure - Mpool error code + * + * ARGUMENTS: + * + * pages <-> Pointer to memory pages that we are freeing. + * + * size -> Size of the block that we are freeing. + * + * sbrk_b -> Set to one if the pages were allocated with sbrk else mmap. + */ +static int free_pages(void *pages, const unsigned long size, + const int sbrk_b) +{ + if (! sbrk_b) { + (void)munmap((caddr_t)pages, size); + } + + return MPOOL_ERROR_NONE; +} + +/* + * static int check_magic + * + * DESCRIPTION: + * + * Check for the existance of the magic ID in a memory pointer. + * + * RETURNS: + * + * Success - MPOOL_ERROR_NONE + * + * Failure - Mpool error code + * + * ARGUMENTS: + * + * addr -> Address inside of the block that we are tryign to locate. + * + * size -> Size of the block. + */ +static int check_magic(const void *addr, const unsigned long size) +{ + const unsigned char *mem_p; + + /* set our starting point */ + mem_p = (unsigned char *)addr + size; + + if (*mem_p == FENCE_MAGIC0 && *(mem_p + 1) == FENCE_MAGIC1) { + return MPOOL_ERROR_NONE; + } + else { + return MPOOL_ERROR_PNT_OVER; + } +} + +/* + * static void write_magic + * + * DESCRIPTION: + * + * Write the magic ID to the address. + * + * RETURNS: + * + * None. + * + * ARGUMENTS: + * + * addr -> Address where to write the magic. + */ +static void write_magic(const void *addr) +{ + *(unsigned char *)addr = FENCE_MAGIC0; + *((unsigned char *)addr + 1) = FENCE_MAGIC1; +} + +/* + * static void free_pointer + * + * DESCRIPTION: + * + * Moved a pointer into our free lists. + * + * RETURNS: + * + * Success - MPOOL_ERROR_NONE + * + * Failure - Mpool error code + * + * ARGUMENTS: + * + * mp_p <-> Pointer to the memory pool. + * + * addr <-> Address where to write the magic. We may write a next + * pointer to it. + * + * size -> Size of the address space. + */ +static int free_pointer(mpool_t *mp_p, void *addr, + const unsigned long size) +{ + unsigned int bit_n; + unsigned long real_size; + mpool_free_t free_pnt; + +#ifdef DEBUG + (void)printf("freeing a block at %lx of %lu bytes\n", (long)addr, size); +#endif + + if (size == 0) { + return MPOOL_ERROR_NONE; + } + + /* + * if the user size is larger then can fit in an entire block then + * we change the size + */ + if (size > MAX_BLOCK_USER_MEMORY(mp_p)) { + real_size = SIZE_OF_PAGES(mp_p, PAGES_IN_SIZE(mp_p, size)) - + sizeof(mpool_block_t); + } + else { + real_size = size; + } + + /* + * We use a specific free bits calculation here because if we are + * freeing 10 bytes then we will be putting it into the 8-byte free + * list and not the 16 byte list. size_to_bits(10) will return 4 + * instead of 3. + */ + bit_n = size_to_free_bits(real_size); + + /* + * Minimal error checking. We could go all the way through the + * list however this might be prohibitive. + */ + if (mp_p->mp_free[bit_n] == addr) { + return MPOOL_ERROR_IS_FREE; + } + + /* add the freed pointer to the free list */ + if (bit_n < min_bit_free_next) { + /* + * Yes we know this will lose 99% of the allocations but what else + * can we do? No space for a next pointer. + */ + if (mp_p->mp_free[bit_n] == NULL) { + mp_p->mp_free[bit_n] = addr; + } + } + else if (bit_n < min_bit_free_size) { + /* we copy, not assign, to maintain the free list */ + memcpy(addr, mp_p->mp_free + bit_n, sizeof(void *)); + mp_p->mp_free[bit_n] = addr; + } + else { + + /* setup our free list structure */ + free_pnt.mf_next_p = mp_p->mp_free[bit_n]; + free_pnt.mf_size = real_size; + + /* we copy the structure in since we don't know about alignment */ + memcpy(addr, &free_pnt, sizeof(free_pnt)); + mp_p->mp_free[bit_n] = addr; + } + + return MPOOL_ERROR_NONE; +} + +/* + * static int split_block + * + * DESCRIPTION: + * + * When freeing space in a multi-block chunk we have to create new + * blocks out of the upper areas being freed. + * + * RETURNS: + * + * Success - MPOOL_ERROR_NONE + * + * Failure - Mpool error code + * + * ARGUMENTS: + * + * mp_p <-> Pointer to the memory pool. + * + * free_addr -> Address that we are freeing. + * + * size -> Size of the space that we are taking from address. + */ +static int split_block(mpool_t *mp_p, void *free_addr, + const unsigned long size) +{ + mpool_block_t *block_p, *new_block_p; + int ret, page_n; + void *end_p; + + /* + * 1st we find the block pointer from our free addr. At this point + * the pointer must be the 1st one in the block if it is spans + * multiple blocks. + */ + block_p = (mpool_block_t *)((char *)free_addr - sizeof(mpool_block_t)); + if (block_p->mb_magic != BLOCK_MAGIC + || block_p->mb_magic2 != BLOCK_MAGIC) { + return MPOOL_ERROR_POOL_OVER; + } + + page_n = PAGES_IN_SIZE(mp_p, size); + + /* we are creating a new block structure for the 2nd ... */ + new_block_p = (mpool_block_t *)((char *)block_p + + SIZE_OF_PAGES(mp_p, page_n)); + new_block_p->mb_magic = BLOCK_MAGIC; + /* New bounds is 1st block bounds. The 1st block's is reset below. */ + new_block_p->mb_bounds_p = block_p->mb_bounds_p; + /* Continue the linked list. The 1st block will point to us below. */ + new_block_p->mb_next_p = block_p->mb_next_p; + new_block_p->mb_magic2 = BLOCK_MAGIC; + + /* bounds for the 1st block are reset to the 1st page only */ + block_p->mb_bounds_p = (char *)new_block_p; + /* the next block pointer for the 1st block is now the new one */ + block_p->mb_next_p = new_block_p; + + /* only free the space in the 1st block if it is only 1 block in size */ + if (page_n == 1) { + /* now free the rest of the 1st block block */ + end_p = (char *)free_addr + size; + ret = free_pointer(mp_p, end_p, + (char *)block_p->mb_bounds_p - (char *)end_p); + if (ret != MPOOL_ERROR_NONE) { + return ret; + } + } + + /* now free the rest of the block */ + ret = free_pointer(mp_p, FIRST_ADDR_IN_BLOCK(new_block_p), + MEMORY_IN_BLOCK(new_block_p)); + if (ret != MPOOL_ERROR_NONE) { + return ret; + } + + return MPOOL_ERROR_NONE; +} + +/* + * static void *get_space + * + * DESCRIPTION: + * + * Moved a pointer into our free lists. + * + * RETURNS: + * + * Success - New address that we can use. + * + * Failure - NULL + * + * ARGUMENTS: + * + * mp_p <-> Pointer to the memory pool. + * + * byte_size -> Size of the address space that we need. + * + * error_p <- Pointer to integer which, if not NULL, will be set with + * a mpool error code. + */ +static void *get_space(mpool_t *mp_p, const unsigned long byte_size, + int *error_p) +{ + mpool_block_t *block_p; + mpool_free_t free_pnt; + int ret; + unsigned long size; + unsigned int bit_c, page_n, left; + void *free_addr = NULL, *free_end; + + size = byte_size; + while ((size & (sizeof(void *) - 1)) > 0) { + size++; + } + + /* + * First we check the free lists looking for something with enough + * pages. Maybe we should only look X bits higher in the list. + * + * XXX: this is where we'd do the best fit. We'd look for the + * closest match. We then could put the rest of the allocation that + * we did not use in a lower free list. Have a define which states + * how deep in the free list to go to find the closest match. + */ + for (bit_c = size_to_bits(size); bit_c <= MAX_BITS; bit_c++) { + if (mp_p->mp_free[bit_c] != NULL) { + free_addr = mp_p->mp_free[bit_c]; + break; + } + } + + /* + * If we haven't allocated any blocks or if the last block doesn't + * have enough memory then we need a new block. + */ + if (bit_c > MAX_BITS) { + + /* we need to allocate more space */ + + page_n = PAGES_IN_SIZE(mp_p, size); + + /* now we try and get the pages we need/want */ + block_p = alloc_pages(mp_p, page_n, error_p); + if (block_p == NULL) { + /* error_p set in alloc_pages */ + return NULL; + } + + /* init the block header */ + block_p->mb_magic = BLOCK_MAGIC; + block_p->mb_bounds_p = (char *)block_p + SIZE_OF_PAGES(mp_p, page_n); + block_p->mb_next_p = mp_p->mp_first_p; + block_p->mb_magic2 = BLOCK_MAGIC; + + /* + * We insert it into the front of the queue. We could add it to + * the end but there is not much use. + */ + mp_p->mp_first_p = block_p; + if (mp_p->mp_last_p == NULL) { + mp_p->mp_last_p = block_p; + } + + free_addr = FIRST_ADDR_IN_BLOCK(block_p); + +#ifdef DEBUG + (void)printf("had to allocate space for %lx of %lu bytes\n", + (long)free_addr, size); +#endif + + free_end = (char *)free_addr + size; + left = (char *)block_p->mb_bounds_p - (char *)free_end; + } + else { + + if (bit_c < min_bit_free_next) { + mp_p->mp_free[bit_c] = NULL; + /* calculate the number of left over bytes */ + left = bits_to_size(bit_c) - size; + } + else if (bit_c < min_bit_free_next) { + /* grab the next pointer from the freed address into our list */ + memcpy(mp_p->mp_free + bit_c, free_addr, sizeof(void *)); + /* calculate the number of left over bytes */ + left = bits_to_size(bit_c) - size; + } + else { + /* grab the free structure from the address */ + memcpy(&free_pnt, free_addr, sizeof(free_pnt)); + mp_p->mp_free[bit_c] = free_pnt.mf_next_p; + + /* are we are splitting up a multiblock chunk into fewer blocks? */ + if (PAGES_IN_SIZE(mp_p, free_pnt.mf_size) > PAGES_IN_SIZE(mp_p, size)) { + ret = split_block(mp_p, free_addr, size); + if (ret != MPOOL_ERROR_NONE) { + SET_POINTER(error_p, ret); + return NULL; + } + /* left over memory was taken care of in split_block */ + left = 0; + } + else { + /* calculate the number of left over bytes */ + left = free_pnt.mf_size - size; + } + } + +#ifdef DEBUG + (void)printf("found a free block at %lx of %lu bytes\n", + (long)free_addr, left + size); +#endif + + free_end = (char *)free_addr + size; + } + + /* + * If we have memory left over then we free it so someone else can + * use it. We do not free the space if we just allocated a + * multi-block chunk because we need to have every allocation easily + * find the start of the block. Every user address % page-size + * should take us to the start of the block. + */ + if (left > 0 && size <= MAX_BLOCK_USER_MEMORY(mp_p)) { + /* free the rest of the block */ + ret = free_pointer(mp_p, free_end, left); + if (ret != MPOOL_ERROR_NONE) { + SET_POINTER(error_p, ret); + return NULL; + } + } + + /* update our bounds */ + if (free_addr > mp_p->mp_bounds_p) { + mp_p->mp_bounds_p = free_addr; + } + else if (free_addr < mp_p->mp_min_p) { + mp_p->mp_min_p = free_addr; + } + + return free_addr; +} + +/* + * static void *alloc_mem + * + * DESCRIPTION: + * + * Allocate space for bytes inside of an already open memory pool. + * + * RETURNS: + * + * Success - Pointer to the address to use. + * + * Failure - NULL + * + * ARGUMENTS: + * + * mp_p <-> Pointer to the memory pool. If NULL then it will do a + * normal malloc. + * + * byte_size -> Number of bytes to allocate in the pool. Must be >0. + * + * error_p <- Pointer to integer which, if not NULL, will be set with + * a mpool error code. + */ +static void *alloc_mem(mpool_t *mp_p, const unsigned long byte_size, + int *error_p) +{ + unsigned long size, fence; + void *addr; + + /* make sure we have enough bytes */ + if (byte_size < MIN_ALLOCATION) { + size = MIN_ALLOCATION; + } + else { + size = byte_size; + } + + if (BIT_IS_SET(mp_p->mp_flags, MPOOL_FLAG_NO_FREE)) { + fence = 0; + } + else { + fence = FENCE_SIZE; + } + + /* get our free space + the space for the fence post */ + addr = get_space(mp_p, size + fence, error_p); + if (addr == NULL) { + /* error_p set in get_space */ + return NULL; + } + + if (! BIT_IS_SET(mp_p->mp_flags, MPOOL_FLAG_NO_FREE)) { + write_magic((char *)addr + size); + } + + /* maintain our stats */ + mp_p->mp_alloc_c++; + mp_p->mp_user_alloc += size; + if (mp_p->mp_user_alloc > mp_p->mp_max_alloc) { + mp_p->mp_max_alloc = mp_p->mp_user_alloc; + } + + SET_POINTER(error_p, MPOOL_ERROR_NONE); + return addr; +} + +/* + * static int free_mem + * + * DESCRIPTION: + * + * Free an address from a memory pool. + * + * RETURNS: + * + * Success - MPOOL_ERROR_NONE + * + * Failure - Mpool error code + * + * ARGUMENTS: + * + * mp_p <-> Pointer to the memory pool. If NULL then it will do a + * normal free. + * + * addr <-> Address to free. + * + * size -> Size of the address being freed. + */ +static int free_mem(mpool_t *mp_p, void *addr, const unsigned long size) +{ + unsigned long old_size, fence; + int ret; + mpool_block_t *block_p; + + /* + * If the size is larger than a block then the allocation must be at + * the front of the block. + */ + if (size > MAX_BLOCK_USER_MEMORY(mp_p)) { + block_p = (mpool_block_t *)((char *)addr - sizeof(mpool_block_t)); + if (block_p->mb_magic != BLOCK_MAGIC + || block_p->mb_magic2 != BLOCK_MAGIC) { + return MPOOL_ERROR_POOL_OVER; + } + } + + /* make sure we have enough bytes */ + if (size < MIN_ALLOCATION) { + old_size = MIN_ALLOCATION; + } + else { + old_size = size; + } + + /* if we are packing the pool smaller */ + if (BIT_IS_SET(mp_p->mp_flags, MPOOL_FLAG_NO_FREE)) { + fence = 0; + } + else { + /* find the user's magic numbers if they were written */ + ret = check_magic(addr, old_size); + if (ret != MPOOL_ERROR_NONE) { + return ret; + } + fence = FENCE_SIZE; + } + + /* now we free the pointer */ + ret = free_pointer(mp_p, addr, old_size + fence); + if (ret != MPOOL_ERROR_NONE) { + return ret; + } + mp_p->mp_user_alloc -= old_size; + + /* adjust our stats */ + mp_p->mp_alloc_c--; + + return MPOOL_ERROR_NONE; +} + +/***************************** exported routines *****************************/ + +/* + * mpool_t *mpool_open + * + * DESCRIPTION: + * + * Open/allocate a new memory pool. + * + * RETURNS: + * + * Success - Pool pointer which must be passed to mpool_close to + * deallocate. + * + * Failure - NULL + * + * ARGUMENTS: + * + * flags -> Flags to set attributes of the memory pool. See the top + * of mpool.h. + * + * page_size -> Set the internal memory page-size. This must be a + * multiple of the getpagesize() value. Set to 0 for the default. + * + * start_addr -> Starting address to try and allocate memory pools. + * This is ignored if the MPOOL_FLAG_USE_SBRK is enabled. + * + * error_p <- Pointer to integer which, if not NULL, will be set with + * a mpool error code. + */ +mpool_t *mpool_open(const unsigned int flags, const unsigned int page_size, + void *start_addr, int *error_p) +{ + mpool_block_t *block_p; + int page_n, ret; + mpool_t mp, *mp_p; + void *free_addr; + + if (! enabled_b) { + startup(); + } + + /* zero our temp struct */ + memset(&mp, 0, sizeof(mp)); + + mp.mp_magic = MPOOL_MAGIC; + mp.mp_flags = flags; + mp.mp_alloc_c = 0; + mp.mp_user_alloc = 0; + mp.mp_max_alloc = 0; + mp.mp_page_c = 0; + /* mp.mp_page_size set below */ + /* mp.mp_blocks_bit_n set below */ + /* mp.mp_fd set below */ + /* mp.mp_top set below */ + /* mp.mp_addr set below */ + mp.mp_log_func = NULL; + mp.mp_min_p = NULL; + mp.mp_bounds_p = NULL; + mp.mp_first_p = NULL; + mp.mp_last_p = NULL; + mp.mp_magic2 = MPOOL_MAGIC; + + /* get and sanity check our page size */ + if (page_size > 0) { + mp.mp_page_size = page_size; + if (mp.mp_page_size % getpagesize() != 0) { + SET_POINTER(error_p, MPOOL_ERROR_ARG_INVALID); + return NULL; + } + } + else { + mp.mp_page_size = getpagesize() * DEFAULT_PAGE_MULT; + if (mp.mp_page_size % 1024 != 0) { + SET_POINTER(error_p, MPOOL_ERROR_PAGE_SIZE); + return NULL; + } + } + + if (BIT_IS_SET(flags, MPOOL_FLAG_USE_SBRK)) { + mp.mp_fd = -1; + mp.mp_addr = NULL; + mp.mp_top = 0; + } + else { + /* open dev-zero for our mmaping */ + mp.mp_fd = open("/dev/zero", O_RDWR, 0); + if (mp.mp_fd < 0) { + SET_POINTER(error_p, MPOOL_ERROR_OPEN_ZERO); + return NULL; + } + mp.mp_addr = start_addr; + /* we start at the front of the file */ + mp.mp_top = 0; + } + + /* + * Find out how many pages we need for our mpool structure. + * + * NOTE: this adds possibly unneeded space for mpool_block_t which + * may not be in this block. + */ + page_n = PAGES_IN_SIZE(&mp, sizeof(mpool_t)); + + /* now allocate us space for the actual struct */ + mp_p = alloc_pages(&mp, page_n, error_p); + if (mp_p == NULL) { + if (mp.mp_fd >= 0) { + (void)close(mp.mp_fd); + mp.mp_fd = -1; + } + return NULL; + } + + /* + * NOTE: we do not normally free the rest of the block here because + * we want to lesson the chance of an allocation overwriting the + * main structure. + */ + if (BIT_IS_SET(flags, MPOOL_FLAG_HEAVY_PACKING)) { + + /* we add a block header to the front of the block */ + block_p = (mpool_block_t *)mp_p; + + /* init the block header */ + block_p->mb_magic = BLOCK_MAGIC; + block_p->mb_bounds_p = (char *)block_p + SIZE_OF_PAGES(&mp, page_n); + block_p->mb_next_p = NULL; + block_p->mb_magic2 = BLOCK_MAGIC; + + /* the mpool pointer is then the 2nd thing in the block */ + mp_p = FIRST_ADDR_IN_BLOCK(block_p); + free_addr = (char *)mp_p + sizeof(mpool_t); + + /* free the rest of the block */ + ret = free_pointer(&mp, free_addr, + (char *)block_p->mb_bounds_p - (char *)free_addr); + if (ret != MPOOL_ERROR_NONE) { + if (mp.mp_fd >= 0) { + (void)close(mp.mp_fd); + mp.mp_fd = -1; + } + /* NOTE: after this line mp_p will be invalid */ + (void)free_pages(block_p, SIZE_OF_PAGES(&mp, page_n), + BIT_IS_SET(flags, MPOOL_FLAG_USE_SBRK)); + SET_POINTER(error_p, ret); + return NULL; + } + + /* + * NOTE: if we are HEAVY_PACKING then the 1st block with the mpool + * header is not on the block linked list. + */ + + /* now copy our tmp structure into our new memory area */ + memcpy(mp_p, &mp, sizeof(mpool_t)); + + /* we setup min/max to our current address which is as good as any */ + mp_p->mp_min_p = block_p; + mp_p->mp_bounds_p = block_p->mb_bounds_p; + } + else { + /* now copy our tmp structure into our new memory area */ + memcpy(mp_p, &mp, sizeof(mpool_t)); + + /* we setup min/max to our current address which is as good as any */ + mp_p->mp_min_p = mp_p; + mp_p->mp_bounds_p = (char *)mp_p + SIZE_OF_PAGES(mp_p, page_n); + } + + SET_POINTER(error_p, MPOOL_ERROR_NONE); + return mp_p; +} + +/* + * int mpool_close + * + * DESCRIPTION: + * + * Close/free a memory allocation pool previously opened with + * mpool_open. + * + * RETURNS: + * + * Success - MPOOL_ERROR_NONE + * + * Failure - Mpool error code + * + * ARGUMENTS: + * + * mp_p <-> Pointer to our memory pool. + */ +int mpool_close(mpool_t *mp_p) +{ + mpool_block_t *block_p, *next_p; + void *addr; + unsigned long size; + int ret, final = MPOOL_ERROR_NONE; + + /* special case, just return no-error */ + if (mp_p == NULL) { + return MPOOL_ERROR_ARG_NULL; + } + if (mp_p->mp_magic != MPOOL_MAGIC) { + return MPOOL_ERROR_PNT; + } + if (mp_p->mp_magic2 != MPOOL_MAGIC) { + return MPOOL_ERROR_POOL_OVER; + } + + if (mp_p->mp_log_func != NULL) { + mp_p->mp_log_func(mp_p, MPOOL_FUNC_CLOSE, 0, 0, NULL, NULL, 0); + } + + /* + * NOTE: if we are HEAVY_PACKING then the 1st block with the mpool + * header is not on the linked list. + */ + + /* free/invalidate the blocks */ + for (block_p = mp_p->mp_first_p; block_p != NULL; block_p = next_p) { + if (block_p->mb_magic != BLOCK_MAGIC + || block_p->mb_magic2 != BLOCK_MAGIC) { + final = MPOOL_ERROR_POOL_OVER; + break; + } + block_p->mb_magic = 0; + block_p->mb_magic2 = 0; + /* record the next pointer because it might be invalidated below */ + next_p = block_p->mb_next_p; + ret = free_pages(block_p, (char *)block_p->mb_bounds_p - (char *)block_p, + BIT_IS_SET(mp_p->mp_flags, MPOOL_FLAG_USE_SBRK)); + if (ret != MPOOL_ERROR_NONE) { + final = ret; + } + } + + /* close /dev/zero if necessary */ + if (mp_p->mp_fd >= 0) { + (void)close(mp_p->mp_fd); + mp_p->mp_fd = -1; + } + + /* invalidate the mpool before we ditch it */ + mp_p->mp_magic = 0; + mp_p->mp_magic2 = 0; + + /* last we munmap the mpool pointer itself */ + if (! BIT_IS_SET(mp_p->mp_flags, MPOOL_FLAG_USE_SBRK)) { + + /* if we are heavy packing then we need to free the 1st block later */ + if (BIT_IS_SET(mp_p->mp_flags, MPOOL_FLAG_HEAVY_PACKING)) { + addr = (char *)mp_p - sizeof(mpool_block_t); + } + else { + addr = mp_p; + } + size = SIZE_OF_PAGES(mp_p, PAGES_IN_SIZE(mp_p, sizeof(mpool_t))); + + (void)munmap((caddr_t)addr, size); + } + + return final; +} + +/* + * int mpool_clear + * + * DESCRIPTION: + * + * Wipe an opened memory pool clean so we can start again. + * + * RETURNS: + * + * Success - MPOOL_ERROR_NONE + * + * Failure - Mpool error code + * + * ARGUMENTS: + * + * mp_p <-> Pointer to our memory pool. + */ +int mpool_clear(mpool_t *mp_p) +{ + mpool_block_t *block_p; + int final = MPOOL_ERROR_NONE, bit_n, ret; + void *first_p; + + /* special case, just return no-error */ + if (mp_p == NULL) { + return MPOOL_ERROR_ARG_NULL; + } + if (mp_p->mp_magic != MPOOL_MAGIC) { + return MPOOL_ERROR_PNT; + } + if (mp_p->mp_magic2 != MPOOL_MAGIC) { + return MPOOL_ERROR_POOL_OVER; + } + + if (mp_p->mp_log_func != NULL) { + mp_p->mp_log_func(mp_p, MPOOL_FUNC_CLEAR, 0, 0, NULL, NULL, 0); + } + + /* reset all of our free lists */ + for (bit_n = 0; bit_n <= MAX_BITS; bit_n++) { + mp_p->mp_free[bit_n] = NULL; + } + + /* free the blocks */ + for (block_p = mp_p->mp_first_p; + block_p != NULL; + block_p = block_p->mb_next_p) { + if (block_p->mb_magic != BLOCK_MAGIC + || block_p->mb_magic2 != BLOCK_MAGIC) { + final = MPOOL_ERROR_POOL_OVER; + break; + } + + first_p = FIRST_ADDR_IN_BLOCK(block_p); + + /* free the memory */ + ret = free_pointer(mp_p, first_p, MEMORY_IN_BLOCK(block_p)); + if (ret != MPOOL_ERROR_NONE) { + final = ret; + } + } + + return final; +} + +/* + * void *mpool_alloc + * + * DESCRIPTION: + * + * Allocate space for bytes inside of an already open memory pool. + * + * RETURNS: + * + * Success - Pointer to the address to use. + * + * Failure - NULL + * + * ARGUMENTS: + * + * mp_p <-> Pointer to the memory pool. If NULL then it will do a + * normal malloc. + * + * byte_size -> Number of bytes to allocate in the pool. Must be >0. + * + * error_p <- Pointer to integer which, if not NULL, will be set with + * a mpool error code. + */ +void *mpool_alloc(mpool_t *mp_p, const unsigned long byte_size, + int *error_p) +{ + void *addr; + + if (mp_p == NULL) { + /* special case -- do a normal malloc */ + addr = (void *)malloc(byte_size); + if (addr == NULL) { + SET_POINTER(error_p, MPOOL_ERROR_ALLOC); + return NULL; + } + else { + SET_POINTER(error_p, MPOOL_ERROR_NONE); + return addr; + } + } + + if (mp_p->mp_magic != MPOOL_MAGIC) { + SET_POINTER(error_p, MPOOL_ERROR_PNT); + return NULL; + } + if (mp_p->mp_magic2 != MPOOL_MAGIC) { + SET_POINTER(error_p, MPOOL_ERROR_POOL_OVER); + return NULL; + } + + if (byte_size == 0) { + SET_POINTER(error_p, MPOOL_ERROR_ARG_INVALID); + return NULL; + } + + addr = alloc_mem(mp_p, byte_size, error_p); + + if (mp_p->mp_log_func != NULL) { + mp_p->mp_log_func(mp_p, MPOOL_FUNC_ALLOC, byte_size, 0, addr, NULL, 0); + } + + return addr; +} + +/* + * void *mpool_calloc + * + * DESCRIPTION: + * + * Allocate space for elements of bytes in the memory pool and zero + * the space afterwards. + * + * RETURNS: + * + * Success - Pointer to the address to use. + * + * Failure - NULL + * + * ARGUMENTS: + * + * mp_p <-> Pointer to the memory pool. If NULL then it will do a + * normal calloc. + * + * ele_n -> Number of elements to allocate. + * + * ele_size -> Number of bytes per element being allocated. + * + * error_p <- Pointer to integer which, if not NULL, will be set with + * a mpool error code. + */ +void *mpool_calloc(mpool_t *mp_p, const unsigned long ele_n, + const unsigned long ele_size, int *error_p) +{ + void *addr; + unsigned long byte_size; + + if (mp_p == NULL) { + /* special case -- do a normal calloc */ + addr = (void *)calloc(ele_n, ele_size); + if (addr == NULL) { + SET_POINTER(error_p, MPOOL_ERROR_ALLOC); + return NULL; + } + else { + SET_POINTER(error_p, MPOOL_ERROR_NONE); + return addr; + } + + } + if (mp_p->mp_magic != MPOOL_MAGIC) { + SET_POINTER(error_p, MPOOL_ERROR_PNT); + return NULL; + } + if (mp_p->mp_magic2 != MPOOL_MAGIC) { + SET_POINTER(error_p, MPOOL_ERROR_POOL_OVER); + return NULL; + } + + if (ele_n == 0 || ele_size == 0) { + SET_POINTER(error_p, MPOOL_ERROR_ARG_INVALID); + return NULL; + } + + byte_size = ele_n * ele_size; + addr = alloc_mem(mp_p, byte_size, error_p); + if (addr != NULL) { + memset(addr, 0, byte_size); + } + + if (mp_p->mp_log_func != NULL) { + mp_p->mp_log_func(mp_p, MPOOL_FUNC_CALLOC, ele_size, ele_n, addr, NULL, 0); + } + + /* NOTE: error_p set above */ + return addr; +} + +/* + * int mpool_free + * + * DESCRIPTION: + * + * Free an address from a memory pool. + * + * RETURNS: + * + * Success - MPOOL_ERROR_NONE + * + * Failure - Mpool error code + * + * ARGUMENTS: + * + * mp_p <-> Pointer to the memory pool. If NULL then it will do a + * normal free. + * + * addr <-> Address to free. + * + * size -> Size of the address being freed. + */ +int mpool_free(mpool_t *mp_p, void *addr, const unsigned long size) +{ + if (mp_p == NULL) { + /* special case -- do a normal free */ + free(addr); + return MPOOL_ERROR_NONE; + } + if (mp_p->mp_magic != MPOOL_MAGIC) { + return MPOOL_ERROR_PNT; + } + if (mp_p->mp_magic2 != MPOOL_MAGIC) { + return MPOOL_ERROR_POOL_OVER; + } + + if (mp_p->mp_log_func != NULL) { + mp_p->mp_log_func(mp_p, MPOOL_FUNC_FREE, size, 0, NULL, addr, 0); + } + + if (addr == NULL) { + return MPOOL_ERROR_ARG_NULL; + } + if (size == 0) { + return MPOOL_ERROR_ARG_INVALID; + } + + return free_mem(mp_p, addr, size); +} + +/* + * void *mpool_resize + * + * DESCRIPTION: + * + * Reallocate an address in a mmeory pool to a new size. This is + * different from realloc in that it needs the old address' size. If + * you don't have it then you need to allocate new space, copy the + * data, and free the old pointer yourself. + * + * RETURNS: + * + * Success - Pointer to the address to use. + * + * Failure - NULL + * + * ARGUMENTS: + * + * mp_p <-> Pointer to the memory pool. If NULL then it will do a + * normal realloc. + * + * old_addr -> Previously allocated address. + * + * old_byte_size -> Size of the old address. Must be known, cannot be + * 0. + * + * new_byte_size -> New size of the allocation. + * + * error_p <- Pointer to integer which, if not NULL, will be set with + * a mpool error code. + */ +void *mpool_resize(mpool_t *mp_p, void *old_addr, + const unsigned long old_byte_size, + const unsigned long new_byte_size, + int *error_p) +{ + unsigned long copy_size, new_size, old_size, fence; + void *new_addr; + mpool_block_t *block_p; + int ret; + + if (mp_p == NULL) { + /* special case -- do a normal realloc */ + new_addr = (void *)realloc(old_addr, new_byte_size); + if (new_addr == NULL) { + SET_POINTER(error_p, MPOOL_ERROR_ALLOC); + return NULL; + } + else { + SET_POINTER(error_p, MPOOL_ERROR_NONE); + return new_addr; + } + } + + if (mp_p->mp_magic != MPOOL_MAGIC) { + SET_POINTER(error_p, MPOOL_ERROR_PNT); + return NULL; + } + if (mp_p->mp_magic2 != MPOOL_MAGIC) { + SET_POINTER(error_p, MPOOL_ERROR_POOL_OVER); + return NULL; + } + + if (old_addr == NULL) { + SET_POINTER(error_p, MPOOL_ERROR_ARG_NULL); + return NULL; + } + if (old_byte_size == 0) { + SET_POINTER(error_p, MPOOL_ERROR_ARG_INVALID); + return NULL; + } + + /* + * If the size is larger than a block then the allocation must be at + * the front of the block. + */ + if (old_byte_size > MAX_BLOCK_USER_MEMORY(mp_p)) { + block_p = (mpool_block_t *)((char *)old_addr - sizeof(mpool_block_t)); + if (block_p->mb_magic != BLOCK_MAGIC + || block_p->mb_magic2 != BLOCK_MAGIC) { + SET_POINTER(error_p, MPOOL_ERROR_POOL_OVER); + return NULL; + } + } + + /* make sure we have enough bytes */ + if (old_byte_size < MIN_ALLOCATION) { + old_size = MIN_ALLOCATION; + } + else { + old_size = old_byte_size; + } + + /* verify that the size matches exactly if we can */ + if (BIT_IS_SET(mp_p->mp_flags, MPOOL_FLAG_NO_FREE)) { + fence = 0; + } + else if (old_size > 0) { + ret = check_magic(old_addr, old_size); + if (ret != MPOOL_ERROR_NONE) { + SET_POINTER(error_p, ret); + return NULL; + } + fence = FENCE_SIZE; + } + + /* make sure we have enough bytes */ + if (new_byte_size < MIN_ALLOCATION) { + new_size = MIN_ALLOCATION; + } + else { + new_size = new_byte_size; + } + + /* + * NOTE: we could here see if the size is the same or less and then + * use the current memory and free the space above. This is harder + * than it sounds if we are changing the block size of the + * allocation. + */ + + /* we need to get another address */ + new_addr = alloc_mem(mp_p, new_byte_size, error_p); + if (new_addr == NULL) { + /* error_p set in mpool_alloc */ + return NULL; + } + + if (new_byte_size > old_byte_size) { + copy_size = old_byte_size; + } + else { + copy_size = new_byte_size; + } + memcpy(new_addr, old_addr, copy_size); + + /* free the old address */ + ret = free_mem(mp_p, old_addr, old_byte_size); + if (ret != MPOOL_ERROR_NONE) { + /* if the old free failed, try and free the new address */ + (void)free_mem(mp_p, new_addr, new_byte_size); + SET_POINTER(error_p, ret); + return NULL; + } + + if (mp_p->mp_log_func != NULL) { + mp_p->mp_log_func(mp_p, MPOOL_FUNC_RESIZE, new_byte_size, + 0, new_addr, old_addr, old_byte_size); + } + + SET_POINTER(error_p, MPOOL_ERROR_NONE); + return new_addr; +} + +/* + * int mpool_stats + * + * DESCRIPTION: + * + * Return stats from the memory pool. + * + * RETURNS: + * + * Success - MPOOL_ERROR_NONE + * + * Failure - Mpool error code + * + * ARGUMENTS: + * + * mp_p -> Pointer to the memory pool. + * + * page_size_p <- Pointer to an unsigned integer which, if not NULL, + * will be set to the page-size of the pool. + * + * num_alloced_p <- Pointer to an unsigned long which, if not NULL, + * will be set to the number of pointers currently allocated in pool. + * + * user_alloced_p <- Pointer to an unsigned long which, if not NULL, + * will be set to the number of user bytes allocated in this pool. + * + * max_alloced_p <- Pointer to an unsigned long which, if not NULL, + * will be set to the maximum number of user bytes that have been + * allocated in this pool. + * + * tot_alloced_p <- Pointer to an unsigned long which, if not NULL, + * will be set to the total amount of space (including administrative + * overhead) used by the pool. + */ +int mpool_stats(const mpool_t *mp_p, unsigned int *page_size_p, + unsigned long *num_alloced_p, + unsigned long *user_alloced_p, + unsigned long *max_alloced_p, + unsigned long *tot_alloced_p) +{ + if (mp_p == NULL) { + return MPOOL_ERROR_ARG_NULL; + } + if (mp_p->mp_magic != MPOOL_MAGIC) { + return MPOOL_ERROR_PNT; + } + if (mp_p->mp_magic2 != MPOOL_MAGIC) { + return MPOOL_ERROR_POOL_OVER; + } + + SET_POINTER(page_size_p, mp_p->mp_page_size); + SET_POINTER(num_alloced_p, mp_p->mp_alloc_c); + SET_POINTER(user_alloced_p, mp_p->mp_user_alloc); + SET_POINTER(max_alloced_p, mp_p->mp_max_alloc); + SET_POINTER(tot_alloced_p, SIZE_OF_PAGES(mp_p, mp_p->mp_page_c)); + + return MPOOL_ERROR_NONE; +} + +/* + * int mpool_set_log_func + * + * DESCRIPTION: + * + * Set a logging callback function to be called whenever there was a + * memory transaction. See mpool_log_func_t. + * + * RETURNS: + * + * Success - MPOOL_ERROR_NONE + * + * Failure - Mpool error code + * + * ARGUMENTS: + * + * mp_p <-> Pointer to the memory pool. + * + * log_func -> Log function (defined in mpool.h) which will be called + * with each mpool transaction. + */ +int mpool_set_log_func(mpool_t *mp_p, mpool_log_func_t log_func) +{ + if (mp_p == NULL) { + return MPOOL_ERROR_ARG_NULL; + } + if (mp_p->mp_magic != MPOOL_MAGIC) { + return MPOOL_ERROR_PNT; + } + if (mp_p->mp_magic2 != MPOOL_MAGIC) { + return MPOOL_ERROR_POOL_OVER; + } + + mp_p->mp_log_func = log_func; + + return MPOOL_ERROR_NONE; +} + +/* + * int mpool_set_max_pages + * + * DESCRIPTION: + * + * Set the maximum number of pages that the library will use. Once it + * hits the limit it will return MPOOL_ERROR_NO_PAGES. + * + * NOTE: if the MPOOL_FLAG_HEAVY_PACKING is set then this max-pages + * value will include the page with the mpool header structure in it. + * If the flag is _not_ set then the max-pages will not include this + * first page. + * + * RETURNS: + * + * Success - MPOOL_ERROR_NONE + * + * Failure - Mpool error code + * + * ARGUMENTS: + * + * mp_p <-> Pointer to the memory pool. + * + * max_pages -> Maximum number of pages used by the library. + */ +int mpool_set_max_pages(mpool_t *mp_p, const unsigned int max_pages) +{ + if (mp_p == NULL) { + return MPOOL_ERROR_ARG_NULL; + } + if (mp_p->mp_magic != MPOOL_MAGIC) { + return MPOOL_ERROR_PNT; + } + if (mp_p->mp_magic2 != MPOOL_MAGIC) { + return MPOOL_ERROR_POOL_OVER; + } + + if (BIT_IS_SET(mp_p->mp_flags, MPOOL_FLAG_HEAVY_PACKING)) { + mp_p->mp_max_pages = max_pages; + } + else { + /* + * If we are not heavy-packing the pool then we don't count the + * 1st page allocated which holds the mpool header structure. + */ + mp_p->mp_max_pages = max_pages + 1; + } + + return MPOOL_ERROR_NONE; +} + +/* + * const char *mpool_strerror + * + * DESCRIPTION: + * + * Return the corresponding string for the error number. + * + * RETURNS: + * + * Success - String equivalient of the error. + * + * Failure - String "invalid error code" + * + * ARGUMENTS: + * + * error -> Error number that we are converting. + */ +const char *mpool_strerror(const int error) +{ + switch (error) { + case MPOOL_ERROR_NONE: + return "no error"; + break; + case MPOOL_ERROR_ARG_NULL: + return "function argument is null"; + break; + case MPOOL_ERROR_ARG_INVALID: + return "function argument is invalid"; + break; + case MPOOL_ERROR_PNT: + return "invalid mpool pointer"; + break; + case MPOOL_ERROR_POOL_OVER: + return "mpool structure was overwritten"; + break; + case MPOOL_ERROR_PAGE_SIZE: + return "could not get system page-size"; + break; + case MPOOL_ERROR_OPEN_ZERO: + return "could not open /dev/zero"; + break; + case MPOOL_ERROR_NO_MEM: + return "no memory available"; + break; + case MPOOL_ERROR_MMAP: + return "problems with mmap"; + break; + case MPOOL_ERROR_SIZE: + return "error processing requested size"; + break; + case MPOOL_ERROR_TOO_BIG: + return "allocation exceeds pool max size"; + break; + case MPOOL_ERROR_MEM: + return "invalid memory address"; + break; + case MPOOL_ERROR_MEM_OVER: + return "memory lower bounds overwritten"; + break; + case MPOOL_ERROR_NOT_FOUND: + return "memory block not found in pool"; + break; + case MPOOL_ERROR_IS_FREE: + return "memory address has already been freed"; + break; + case MPOOL_ERROR_BLOCK_STAT: + return "invalid internal block status"; + break; + case MPOOL_ERROR_FREE_ADDR: + return "invalid internal free address"; + break; + case MPOOL_ERROR_SBRK_CONTIG: + return "sbrk did not return contiguous memory"; + break; + case MPOOL_ERROR_NO_PAGES: + return "no available pages left in pool"; + break; + case MPOOL_ERROR_ALLOC: + return "system alloc function failed"; + break; + case MPOOL_ERROR_PNT_OVER: + return "user pointer admin space overwritten"; + break; + default: + break; + } + + return "invalid error code"; +} diff --git a/libs/libks/src/simclist.c b/libs/libks/src/simclist.c new file mode 100755 index 0000000000..c8d36f5ff4 --- /dev/null +++ b/libs/libks/src/simclist.c @@ -0,0 +1,1525 @@ +/* + * Copyright (c) 2007,2008,2009,2010,2011 Mij + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + + +/* + * SimCList library. See http://mij.oltrelinux.com/devel/simclist + */ + +/* SimCList implementation, version 1.6 */ + +#include +#include +#include /* for setting errno */ +#include +#ifndef _WIN32 + /* not in Windows! */ +# include +# include +#endif +#ifndef SIMCLIST_NO_DUMPRESTORE + /* includes for dump/restore */ +# include +# include /* for READ_ERRCHECK() and write() */ +# include /* for open() etc */ +# ifndef _WIN32 +# include /* for htons() on UNIX */ +# else +# include /* for htons() on Windows */ +# endif +#endif + +/* disable asserts */ +#ifndef SIMCLIST_DEBUG +#define NDEBUG +#endif + +#include + + +#include /* for open()'s access modes S_IRUSR etc */ +#include + +#if defined(_MSC_VER) || defined(__MINGW32__) +/* provide gettimeofday() missing in Windows */ +int gettimeofday(struct timeval *tp, void *tzp) { + DWORD t; + + /* XSI says: "If tzp is not a null pointer, the behavior is unspecified" */ + assert(tzp == NULL); + + t = timeGetTime(); + tp->tv_sec = t / 1000; + tp->tv_usec = t % 1000; + return 0; +} +#endif + + +/* work around lack of inttypes.h support in broken Microsoft Visual Studio compilers */ +#if !defined(_WIN32) || !defined(_MSC_VER) +# include /* (u)int*_t */ +#else +# include +typedef UINT8 uint8_t; +typedef UINT16 uint16_t; +typedef ULONG32 uint32_t; +typedef UINT64 uint64_t; +typedef INT8 int8_t; +typedef INT16 int16_t; +typedef LONG32 int32_t; +typedef INT64 int64_t; +#endif + + +/* define some commodity macros for Dump/Restore functionality */ +#ifndef SIMCLIST_NO_DUMPRESTORE +/* write() decorated with error checking logic */ +#define WRITE_ERRCHECK(fd, msgbuf, msglen) do { \ + if (write(fd, msgbuf, msglen) < 0) return -1; \ + } while (0); +/* READ_ERRCHECK() decorated with error checking logic */ +#define READ_ERRCHECK(fd, msgbuf, msglen) do { \ + if (read(fd, msgbuf, msglen) != msglen) { \ + /*errno = EPROTO;*/ \ + return -1; \ + } \ + } while (0); + +/* convert 64bit integers from host to network format */ +#define hton64(x) (\ + htons(1) == 1 ? \ + (uint64_t)x /* big endian */ \ + : /* little endian */ \ + ((uint64_t)((((uint64_t)(x) & 0xff00000000000000ULL) >> 56) | \ + (((uint64_t)(x) & 0x00ff000000000000ULL) >> 40) | \ + (((uint64_t)(x) & 0x0000ff0000000000ULL) >> 24) | \ + (((uint64_t)(x) & 0x000000ff00000000ULL) >> 8) | \ + (((uint64_t)(x) & 0x00000000ff000000ULL) << 8) | \ + (((uint64_t)(x) & 0x0000000000ff0000ULL) << 24) | \ + (((uint64_t)(x) & 0x000000000000ff00ULL) << 40) | \ + (((uint64_t)(x) & 0x00000000000000ffULL) << 56))) \ + ) + +/* convert 64bit integers from network to host format */ +#define ntoh64(x) (hton64(x)) +#endif + +/* some OSes don't have EPROTO (eg OpenBSD) */ +#ifndef EPROTO +#define EPROTO EIO +#endif + +#ifdef SIMCLIST_WITH_THREADS +/* limit (approx) to the number of threads running + * for threaded operations. Only meant when + * SIMCLIST_WITH_THREADS is defined */ +#define SIMCLIST_MAXTHREADS 2 +#endif + +/* + * how many elems to keep as spare. During a deletion, an element + * can be saved in a "free-list", not free()d immediately. When + * latter insertions are performed, spare elems can be used instead + * of malloc()ing new elems. + * + * about this param, some values for appending + * 10 million elems into an empty list: + * (#, time[sec], gain[%], gain/no[%]) + * 0 2,164 0,00 0,00 <-- feature disabled + * 1 1,815 34,9 34,9 + * 2 1,446 71,8 35,9 <-- MAX gain/no + * 3 1,347 81,7 27,23 + * 5 1,213 95,1 19,02 + * 8 1,064 110,0 13,75 + * 10 1,015 114,9 11,49 <-- MAX gain w/ likely sol + * 15 1,019 114,5 7,63 + * 25 0,985 117,9 4,72 + * 50 1,088 107,6 2,15 + * 75 1,016 114,8 1,53 + * 100 0,988 117,6 1,18 + * 150 1,022 114,2 0,76 + * 200 0,939 122,5 0,61 <-- MIN time + */ +#ifndef SIMCLIST_MAX_SPARE_ELEMS +#define SIMCLIST_MAX_SPARE_ELEMS 5 +#endif + + +#ifdef SIMCLIST_WITH_THREADS +#include +#endif + +#include "simclist.h" + + +/* minumum number of elements for sorting with quicksort instead of insertion */ +#define SIMCLIST_MINQUICKSORTELS 24 + + +/* list dump declarations */ +#define SIMCLIST_DUMPFORMAT_VERSION 1 /* (short integer) version of fileformat managed by _dump* and _restore* functions */ + +#define SIMCLIST_DUMPFORMAT_HEADERLEN 30 /* length of the header */ + +/* header for a list dump */ +struct list_dump_header_s { + uint16_t ver; /* version */ + int32_t timestamp_sec; /* dump timestamp, seconds since UNIX Epoch */ + int32_t timestamp_usec; /* dump timestamp, microseconds since timestamp_sec */ + int32_t rndterm; /* random value terminator -- terminates the data sequence */ + + uint32_t totlistlen; /* sum of every element' size, bytes */ + uint32_t numels; /* number of elements */ + uint32_t elemlen; /* bytes length of an element, for constant-size lists, <= 0 otherwise */ + int32_t listhash; /* hash of the list at the time of dumping, or 0 if to be ignored */ +}; + + + +/* deletes tmp from list, with care wrt its position (head, tail, middle) */ +static int list_drop_elem(list_t *restrict l, struct list_entry_s *tmp, unsigned int pos); + +/* set default values for initialized lists */ +static int list_attributes_setdefaults(list_t *restrict l); + +#ifndef NDEBUG +/* check whether the list internal REPresentation is valid -- Costs O(n) */ +static int list_repOk(const list_t *restrict l); + +/* check whether the list attribute set is valid -- Costs O(1) */ +static int list_attrOk(const list_t *restrict l); +#endif + +/* do not inline, this is recursive */ +static void list_sort_quicksort(list_t *restrict l, int versus, + unsigned int first, struct list_entry_s *fel, + unsigned int last, struct list_entry_s *lel); + +static inline void list_sort_selectionsort(list_t *restrict l, int versus, + unsigned int first, struct list_entry_s *fel, + unsigned int last, struct list_entry_s *lel); + +static void *list_get_minmax(const list_t *restrict l, int versus); + +static inline struct list_entry_s *list_findpos(const list_t *restrict l, int posstart); + +/* + * Random Number Generator + * + * The user is expected to seed the RNG (ie call srand()) if + * SIMCLIST_SYSTEM_RNG is defined. + * + * Otherwise, a self-contained RNG based on LCG is used; see + * http://en.wikipedia.org/wiki/Linear_congruential_generator . + * + * Facts pro local RNG: + * 1. no need for the user to call srand() on his own + * 2. very fast, possibly faster than OS + * 3. avoid interference with user's RNG + * + * Facts pro system RNG: + * 1. may be more accurate (irrelevant for SimCList randno purposes) + * 2. why reinvent the wheel + * + * Default to local RNG for user's ease of use. + */ + +#ifdef SIMCLIST_SYSTEM_RNG +/* keep track whether we initialized already (non-0) or not (0) */ +static unsigned random_seed = 0; + +/* use local RNG */ +static inline void seed_random(void) { + if (random_seed == 0) + random_seed = (unsigned)getpid() ^ (unsigned)time(NULL); +} + +static inline long get_random(void) { + random_seed = (1664525 * random_seed + 1013904223); + return random_seed; +} + +#else +/* use OS's random generator */ +# define seed_random() +# define get_random() (rand()) +#endif + + +/* list initialization */ +int list_init(list_t *restrict l) { + if (l == NULL) return -1; + + seed_random(); + + l->numels = 0; + + /* head/tail sentinels and mid pointer */ + l->head_sentinel = (struct list_entry_s *)malloc(sizeof(struct list_entry_s)); + l->tail_sentinel = (struct list_entry_s *)malloc(sizeof(struct list_entry_s)); + l->head_sentinel->next = l->tail_sentinel; + l->tail_sentinel->prev = l->head_sentinel; + l->head_sentinel->prev = l->tail_sentinel->next = l->mid = NULL; + l->head_sentinel->data = l->tail_sentinel->data = NULL; + + /* iteration attributes */ + l->iter_active = 0; + l->iter_pos = 0; + l->iter_curentry = NULL; + + /* free-list attributes */ + l->spareels = (struct list_entry_s **)malloc(SIMCLIST_MAX_SPARE_ELEMS * sizeof(struct list_entry_s *)); + l->spareelsnum = 0; + +#ifdef SIMCLIST_WITH_THREADS + l->threadcount = 0; +#endif + + list_attributes_setdefaults(l); + + assert(list_repOk(l)); + assert(list_attrOk(l)); + + return 0; +} + +void list_destroy(list_t *restrict l) { + unsigned int i; + + list_clear(l); + for (i = 0; i < l->spareelsnum; i++) { + free(l->spareels[i]); + } + free(l->spareels); + free(l->head_sentinel); + free(l->tail_sentinel); +} + +int list_attributes_setdefaults(list_t *restrict l) { + l->attrs.comparator = NULL; + l->attrs.seeker = NULL; + + /* also free() element data when removing and element from the list */ + l->attrs.meter = NULL; + l->attrs.copy_data = 0; + + l->attrs.hasher = NULL; + + /* serializer/unserializer */ + l->attrs.serializer = NULL; + l->attrs.unserializer = NULL; + + assert(list_attrOk(l)); + + return 0; +} + +/* setting list properties */ +int list_attributes_comparator(list_t *restrict l, element_comparator comparator_fun) { + if (l == NULL) return -1; + + l->attrs.comparator = comparator_fun; + + assert(list_attrOk(l)); + + return 0; +} + +int list_attributes_seeker(list_t *restrict l, element_seeker seeker_fun) { + if (l == NULL) return -1; + + l->attrs.seeker = seeker_fun; + assert(list_attrOk(l)); + + return 0; +} + +int list_attributes_copy(list_t *restrict l, element_meter metric_fun, int copy_data) { + if (l == NULL || (metric_fun == NULL && copy_data != 0)) return -1; + + l->attrs.meter = metric_fun; + l->attrs.copy_data = copy_data; + + assert(list_attrOk(l)); + + return 0; +} + +int list_attributes_hash_computer(list_t *restrict l, element_hash_computer hash_computer_fun) { + if (l == NULL) return -1; + + l->attrs.hasher = hash_computer_fun; + assert(list_attrOk(l)); + return 0; +} + +int list_attributes_serializer(list_t *restrict l, element_serializer serializer_fun) { + if (l == NULL) return -1; + + l->attrs.serializer = serializer_fun; + assert(list_attrOk(l)); + return 0; +} + +int list_attributes_unserializer(list_t *restrict l, element_unserializer unserializer_fun) { + if (l == NULL) return -1; + + l->attrs.unserializer = unserializer_fun; + assert(list_attrOk(l)); + return 0; +} + +int list_append(list_t *restrict l, const void *data) { + return list_insert_at(l, data, l->numels); +} + +int list_prepend(list_t *restrict l, const void *data) { + return list_insert_at(l, data, 0); +} + +void *list_fetch(list_t *restrict l) { + return list_extract_at(l, 0); +} + +void *list_get_at(const list_t *restrict l, unsigned int pos) { + struct list_entry_s *tmp; + + tmp = list_findpos(l, pos); + + return (tmp != NULL ? tmp->data : NULL); +} + +void *list_get_max(const list_t *restrict l) { + return list_get_minmax(l, +1); +} + +void *list_get_min(const list_t *restrict l) { + return list_get_minmax(l, -1); +} + +/* REQUIRES {list->numels >= 1} + * return the min (versus < 0) or max value (v > 0) in l */ +static void *list_get_minmax(const list_t *restrict l, int versus) { + void *curminmax; + struct list_entry_s *s; + + if (l->attrs.comparator == NULL || l->numels == 0) + return NULL; + + curminmax = l->head_sentinel->next->data; + for (s = l->head_sentinel->next->next; s != l->tail_sentinel; s = s->next) { + if (l->attrs.comparator(curminmax, s->data) * versus > 0) + curminmax = s->data; + } + + return curminmax; +} + +/* set tmp to point to element at index posstart in l */ +static inline struct list_entry_s *list_findpos(const list_t *restrict l, int posstart) { + struct list_entry_s *ptr; + float x; + int i; + + /* accept 1 slot overflow for fetching head and tail sentinels */ + if (posstart < -1 || posstart > (int)l->numels) return NULL; + + x = (float)(posstart+1) / l->numels; + if (x <= 0.25) { + /* first quarter: get to posstart from head */ + for (i = -1, ptr = l->head_sentinel; i < posstart; ptr = ptr->next, i++); + } else if (x < 0.5) { + /* second quarter: get to posstart from mid */ + for (i = (l->numels-1)/2, ptr = l->mid; i > posstart; ptr = ptr->prev, i--); + } else if (x <= 0.75) { + /* third quarter: get to posstart from mid */ + for (i = (l->numels-1)/2, ptr = l->mid; i < posstart; ptr = ptr->next, i++); + } else { + /* fourth quarter: get to posstart from tail */ + for (i = l->numels, ptr = l->tail_sentinel; i > posstart; ptr = ptr->prev, i--); + } + + return ptr; +} + +void *list_extract_at(list_t *restrict l, unsigned int pos) { + struct list_entry_s *tmp; + void *data; + + if (l->iter_active || pos >= l->numels) return NULL; + + tmp = list_findpos(l, pos); + data = tmp->data; + + tmp->data = NULL; /* save data from list_drop_elem() free() */ + list_drop_elem(l, tmp, pos); + l->numels--; + + assert(list_repOk(l)); + + return data; +} + +int list_insert_at(list_t *restrict l, const void *data, unsigned int pos) { + struct list_entry_s *lent, *succ, *prec; + + if (l->iter_active || pos > l->numels) return -1; + + /* this code optimizes malloc() with a free-list */ + if (l->spareelsnum > 0) { + lent = l->spareels[l->spareelsnum-1]; + l->spareelsnum--; + } else { + lent = (struct list_entry_s *)malloc(sizeof(struct list_entry_s)); + if (lent == NULL) + return -1; + } + + if (l->attrs.copy_data) { + /* make room for user' data (has to be copied) */ + size_t datalen = l->attrs.meter(data); + lent->data = (struct list_entry_s *)malloc(datalen); + memcpy(lent->data, data, datalen); + } else { + lent->data = (void*)data; + } + + /* actually append element */ + prec = list_findpos(l, pos-1); + succ = prec->next; + + prec->next = lent; + lent->prev = prec; + lent->next = succ; + succ->prev = lent; + + l->numels++; + + /* fix mid pointer */ + if (l->numels == 1) { /* first element, set pointer */ + l->mid = lent; + } else if (l->numels % 2) { /* now odd */ + if (pos >= (l->numels-1)/2) l->mid = l->mid->next; + } else { /* now even */ + if (pos <= (l->numels-1)/2) l->mid = l->mid->prev; + } + + assert(list_repOk(l)); + + return 1; +} + +int list_delete(list_t *restrict l, const void *data) { + int pos, r; + + pos = list_locate(l, data); + if (pos < 0) + return -1; + + r = list_delete_at(l, pos); + if (r < 0) + return -1; + + assert(list_repOk(l)); + + return 0; +} + +int list_delete_at(list_t *restrict l, unsigned int pos) { + struct list_entry_s *delendo; + + + if (l->iter_active || pos >= l->numels) return -1; + + delendo = list_findpos(l, pos); + + list_drop_elem(l, delendo, pos); + + l->numels--; + + + assert(list_repOk(l)); + + return 0; +} + +int list_delete_range(list_t *restrict l, unsigned int posstart, unsigned int posend) { + struct list_entry_s *lastvalid, *tmp, *tmp2; + unsigned int numdel, midposafter, i; + int movedx; + + if (l->iter_active || posend < posstart || posend >= l->numels) return -1; + + numdel = posend - posstart + 1; + if (numdel == l->numels) return list_clear(l); + + tmp = list_findpos(l, posstart); /* first el to be deleted */ + lastvalid = tmp->prev; /* last valid element */ + + midposafter = (l->numels-1-numdel)/2; + + midposafter = midposafter < posstart ? midposafter : midposafter+numdel; + movedx = midposafter - (l->numels-1)/2; + + if (movedx > 0) { /* move right */ + for (i = 0; i < (unsigned int)movedx; l->mid = l->mid->next, i++); + } else { /* move left */ + movedx = -movedx; + for (i = 0; i < (unsigned int)movedx; l->mid = l->mid->prev, i++); + } + + assert(posstart == 0 || lastvalid != l->head_sentinel); + i = posstart; + if (l->attrs.copy_data) { + /* also free element data */ + for (; i <= posend; i++) { + tmp2 = tmp; + tmp = tmp->next; + if (tmp2->data != NULL) free(tmp2->data); + if (l->spareelsnum < SIMCLIST_MAX_SPARE_ELEMS) { + l->spareels[l->spareelsnum++] = tmp2; + } else { + free(tmp2); + } + } + } else { + /* only free containers */ + for (; i <= posend; i++) { + tmp2 = tmp; + tmp = tmp->next; + if (l->spareelsnum < SIMCLIST_MAX_SPARE_ELEMS) { + l->spareels[l->spareelsnum++] = tmp2; + } else { + free(tmp2); + } + } + } + assert(i == posend+1 && (posend != l->numels || tmp == l->tail_sentinel)); + + lastvalid->next = tmp; + tmp->prev = lastvalid; + + l->numels -= posend - posstart + 1; + + assert(list_repOk(l)); + + return numdel; +} + +int list_clear(list_t *restrict l) { + struct list_entry_s *s; + unsigned int numels; + + /* will be returned */ + numels = l->numels; + + if (l->iter_active) return -1; + + if (l->attrs.copy_data) { /* also free user data */ + /* spare a loop conditional with two loops: spareing elems and freeing elems */ + for (s = l->head_sentinel->next; l->spareelsnum < SIMCLIST_MAX_SPARE_ELEMS && s != l->tail_sentinel; s = s->next) { + /* move elements as spares as long as there is room */ + if (s->data != NULL) free(s->data); + l->spareels[l->spareelsnum++] = s; + } + while (s != l->tail_sentinel) { + /* free the remaining elems */ + if (s->data != NULL) free(s->data); + s = s->next; + free(s->prev); + } + l->head_sentinel->next = l->tail_sentinel; + l->tail_sentinel->prev = l->head_sentinel; + } else { /* only free element containers */ + /* spare a loop conditional with two loops: spareing elems and freeing elems */ + for (s = l->head_sentinel->next; l->spareelsnum < SIMCLIST_MAX_SPARE_ELEMS && s != l->tail_sentinel; s = s->next) { + /* move elements as spares as long as there is room */ + l->spareels[l->spareelsnum++] = s; + } + while (s != l->tail_sentinel) { + /* free the remaining elems */ + s = s->next; + free(s->prev); + } + l->head_sentinel->next = l->tail_sentinel; + l->tail_sentinel->prev = l->head_sentinel; + } + l->numels = 0; + l->mid = NULL; + + assert(list_repOk(l)); + + return numels; +} + +unsigned int list_size(const list_t *restrict l) { + return l->numels; +} + +int list_empty(const list_t *restrict l) { + return (l->numels == 0); +} + +int list_locate(const list_t *restrict l, const void *data) { + struct list_entry_s *el; + int pos = 0; + + if (l->attrs.comparator != NULL) { + /* use comparator */ + for (el = l->head_sentinel->next; el != l->tail_sentinel; el = el->next, pos++) { + if (l->attrs.comparator(data, el->data) == 0) break; + } + } else { + /* compare references */ + for (el = l->head_sentinel->next; el != l->tail_sentinel; el = el->next, pos++) { + if (el->data == data) break; + } + } + if (el == l->tail_sentinel) return -1; + + return pos; +} + +void *list_seek(list_t *restrict l, const void *indicator) { + const struct list_entry_s *iter; + + if (l->attrs.seeker == NULL) return NULL; + + for (iter = l->head_sentinel->next; iter != l->tail_sentinel; iter = iter->next) { + if (l->attrs.seeker(iter->data, indicator) != 0) return iter->data; + } + + return NULL; +} + +int list_contains(const list_t *restrict l, const void *data) { + return (list_locate(l, data) >= 0); +} + +int list_concat(const list_t *l1, const list_t *l2, list_t *restrict dest) { + struct list_entry_s *el, *srcel; + unsigned int cnt; + int err; + + + if (l1 == NULL || l2 == NULL || dest == NULL || l1 == dest || l2 == dest) + return -1; + + list_init(dest); + + dest->numels = l1->numels + l2->numels; + if (dest->numels == 0) + return 0; + + /* copy list1 */ + srcel = l1->head_sentinel->next; + el = dest->head_sentinel; + while (srcel != l1->tail_sentinel) { + el->next = (struct list_entry_s *)malloc(sizeof(struct list_entry_s)); + el->next->prev = el; + el = el->next; + el->data = srcel->data; + srcel = srcel->next; + } + dest->mid = el; /* approximate position (adjust later) */ + /* copy list 2 */ + srcel = l2->head_sentinel->next; + while (srcel != l2->tail_sentinel) { + el->next = (struct list_entry_s *)malloc(sizeof(struct list_entry_s)); + el->next->prev = el; + el = el->next; + el->data = srcel->data; + srcel = srcel->next; + } + el->next = dest->tail_sentinel; + dest->tail_sentinel->prev = el; + + /* fix mid pointer */ + err = l2->numels - l1->numels; + if ((err+1)/2 > 0) { /* correct pos RIGHT (err-1)/2 moves */ + err = (err+1)/2; + for (cnt = 0; cnt < (unsigned int)err; cnt++) dest->mid = dest->mid->next; + } else if (err/2 < 0) { /* correct pos LEFT (err/2)-1 moves */ + err = -err/2; + for (cnt = 0; cnt < (unsigned int)err; cnt++) dest->mid = dest->mid->prev; + } + + assert(!(list_repOk(l1) && list_repOk(l2)) || list_repOk(dest)); + + return 0; +} + +int list_sort(list_t *restrict l, int versus) { + if (l->iter_active || l->attrs.comparator == NULL) /* cannot modify list in the middle of an iteration */ + return -1; + + if (l->numels <= 1) + return 0; + list_sort_quicksort(l, versus, 0, l->head_sentinel->next, l->numels-1, l->tail_sentinel->prev); + assert(list_repOk(l)); + return 0; +} + +#ifdef SIMCLIST_WITH_THREADS +struct list_sort_wrappedparams { + list_t *restrict l; + int versus; + unsigned int first, last; + struct list_entry_s *fel, *lel; +}; + +static void *list_sort_quicksort_threadwrapper(void *wrapped_params) { + struct list_sort_wrappedparams *wp = (struct list_sort_wrappedparams *)wrapped_params; + list_sort_quicksort(wp->l, wp->versus, wp->first, wp->fel, wp->last, wp->lel); + free(wp); + pthread_exit(NULL); + return NULL; +} +#endif + +static inline void list_sort_selectionsort(list_t *restrict l, int versus, + unsigned int first, struct list_entry_s *fel, + unsigned int last, struct list_entry_s *lel) { + struct list_entry_s *cursor, *toswap, *firstunsorted; + void *tmpdata; + + if (last <= first) /* <= 1-element lists are always sorted */ + return; + + for (firstunsorted = fel; firstunsorted != lel; firstunsorted = firstunsorted->next) { + /* find min or max in the remainder of the list */ + for (toswap = firstunsorted, cursor = firstunsorted->next; cursor != lel->next; cursor = cursor->next) + if (l->attrs.comparator(toswap->data, cursor->data) * -versus > 0) toswap = cursor; + if (toswap != firstunsorted) { /* swap firstunsorted with toswap */ + tmpdata = firstunsorted->data; + firstunsorted->data = toswap->data; + toswap->data = tmpdata; + } + } +} + +static void list_sort_quicksort(list_t *restrict l, int versus, + unsigned int first, struct list_entry_s *fel, + unsigned int last, struct list_entry_s *lel) { + unsigned int pivotid; + unsigned int i; + register struct list_entry_s *pivot; + struct list_entry_s *left, *right; + void *tmpdata; +#ifdef SIMCLIST_WITH_THREADS + pthread_t tid; + int traised; +#endif + + + if (last <= first) /* <= 1-element lists are always sorted */ + return; + + if (last - first+1 <= SIMCLIST_MINQUICKSORTELS) { + list_sort_selectionsort(l, versus, first, fel, last, lel); + return; + } + + /* base of iteration: one element list */ + if (! (last > first)) return; + + pivotid = (get_random() % (last - first + 1)); + /* pivotid = (last - first + 1) / 2; */ + + /* find pivot */ + if (pivotid < (last - first + 1)/2) { + for (i = 0, pivot = fel; i < pivotid; pivot = pivot->next, i++); + } else { + for (i = last - first, pivot = lel; i > pivotid; pivot = pivot->prev, i--); + } + + /* smaller PIVOT bigger */ + left = fel; + right = lel; + /* iterate --- left ---> PIV <--- right --- */ + while (left != pivot && right != pivot) { + for (; left != pivot && (l->attrs.comparator(left->data, pivot->data) * -versus <= 0); left = left->next); + /* left points to a smaller element, or to pivot */ + for (; right != pivot && (l->attrs.comparator(right->data, pivot->data) * -versus >= 0); right = right->prev); + /* right points to a bigger element, or to pivot */ + if (left != pivot && right != pivot) { + /* swap, then move iterators */ + tmpdata = left->data; + left->data = right->data; + right->data = tmpdata; + + left = left->next; + right = right->prev; + } + } + + /* now either left points to pivot (end run), or right */ + if (right == pivot) { /* left part longer */ + while (left != pivot) { + if (l->attrs.comparator(left->data, pivot->data) * -versus > 0) { + tmpdata = left->data; + left->data = pivot->prev->data; + pivot->prev->data = pivot->data; + pivot->data = tmpdata; + pivot = pivot->prev; + pivotid--; + if (pivot == left) break; + } else { + left = left->next; + } + } + } else { /* right part longer */ + while (right != pivot) { + if (l->attrs.comparator(right->data, pivot->data) * -versus < 0) { + /* move current right before pivot */ + tmpdata = right->data; + right->data = pivot->next->data; + pivot->next->data = pivot->data; + pivot->data = tmpdata; + pivot = pivot->next; + pivotid++; + if (pivot == right) break; + } else { + right = right->prev; + } + } + } + + /* sort sublists A and B : |---A---| pivot |---B---| */ + +#ifdef SIMCLIST_WITH_THREADS + traised = 0; + if (pivotid > 0) { + /* prepare wrapped args, then start thread */ + if (l->threadcount < SIMCLIST_MAXTHREADS-1) { + struct list_sort_wrappedparams *wp = (struct list_sort_wrappedparams *)malloc(sizeof(struct list_sort_wrappedparams)); + l->threadcount++; + traised = 1; + wp->l = l; + wp->versus = versus; + wp->first = first; + wp->fel = fel; + wp->last = first+pivotid-1; + wp->lel = pivot->prev; + if (pthread_create(&tid, NULL, list_sort_quicksort_threadwrapper, wp) != 0) { + free(wp); + traised = 0; + list_sort_quicksort(l, versus, first, fel, first+pivotid-1, pivot->prev); + } + } else { + list_sort_quicksort(l, versus, first, fel, first+pivotid-1, pivot->prev); + } + } + if (first + pivotid < last) list_sort_quicksort(l, versus, first+pivotid+1, pivot->next, last, lel); + if (traised) { + pthread_join(tid, (void **)NULL); + l->threadcount--; + } +#else + if (pivotid > 0) list_sort_quicksort(l, versus, first, fel, first+pivotid-1, pivot->prev); + if (first + pivotid < last) list_sort_quicksort(l, versus, first+pivotid+1, pivot->next, last, lel); +#endif +} + +int list_iterator_start(list_t *restrict l) { + if (l->iter_active) return 0; + l->iter_pos = 0; + l->iter_active = 1; + l->iter_curentry = l->head_sentinel->next; + return 1; +} + +void *list_iterator_next(list_t *restrict l) { + void *toret; + + if (! l->iter_active) return NULL; + + toret = l->iter_curentry->data; + l->iter_curentry = l->iter_curentry->next; + l->iter_pos++; + + return toret; +} + +int list_iterator_hasnext(const list_t *restrict l) { + if (! l->iter_active) return 0; + return (l->iter_pos < l->numels); +} + +int list_iterator_stop(list_t *restrict l) { + if (! l->iter_active) return 0; + l->iter_pos = 0; + l->iter_active = 0; + return 1; +} + +int list_hash(const list_t *restrict l, list_hash_t *restrict hash) { + struct list_entry_s *x; + list_hash_t tmphash; + + assert(hash != NULL); + + tmphash = l->numels * 2 + 100; + if (l->attrs.hasher == NULL) { +#ifdef SIMCLIST_ALLOW_LOCATIONBASED_HASHES + /* ENABLE WITH CARE !! */ +#warning "Memlocation-based hash is consistent only for testing modification in the same program run." + int i; + + /* only use element references */ + for (x = l->head_sentinel->next; x != l->tail_sentinel; x = x->next) { + for (i = 0; i < sizeof(x->data); i++) { + tmphash += (tmphash ^ (uintptr_t)x->data); + } + tmphash += tmphash % l->numels; + } +#else + return -1; +#endif + } else { + /* hash each element with the user-given function */ + for (x = l->head_sentinel->next; x != l->tail_sentinel; x = x->next) { + tmphash += tmphash ^ l->attrs.hasher(x->data); + tmphash += tmphash % l->numels; + } + } + + *hash = tmphash; + + return 0; +} + +#ifndef SIMCLIST_NO_DUMPRESTORE +int list_dump_getinfo_filedescriptor(int fd, list_dump_info_t *restrict info) { + int32_t terminator_head, terminator_tail; + uint32_t elemlen; + off_t hop; + + + /* version */ + READ_ERRCHECK(fd, & info->version, sizeof(info->version)); + info->version = ntohs(info->version); + if (info->version > SIMCLIST_DUMPFORMAT_VERSION) { + errno = EILSEQ; + return -1; + } + + /* timestamp.tv_sec and timestamp.tv_usec */ + READ_ERRCHECK(fd, & info->timestamp.tv_sec, sizeof(info->timestamp.tv_sec)); + info->timestamp.tv_sec = ntohl(info->timestamp.tv_sec); + READ_ERRCHECK(fd, & info->timestamp.tv_usec, sizeof(info->timestamp.tv_usec)); + info->timestamp.tv_usec = ntohl(info->timestamp.tv_usec); + + /* list terminator (to check thereafter) */ + READ_ERRCHECK(fd, & terminator_head, sizeof(terminator_head)); + terminator_head = ntohl(terminator_head); + + /* list size */ + READ_ERRCHECK(fd, & info->list_size, sizeof(info->list_size)); + info->list_size = ntohl(info->list_size); + + /* number of elements */ + READ_ERRCHECK(fd, & info->list_numels, sizeof(info->list_numels)); + info->list_numels = ntohl(info->list_numels); + + /* length of each element (for checking for consistency) */ + READ_ERRCHECK(fd, & elemlen, sizeof(elemlen)); + elemlen = ntohl(elemlen); + + /* list hash */ + READ_ERRCHECK(fd, & info->list_hash, sizeof(info->list_hash)); + info->list_hash = ntohl(info->list_hash); + + /* check consistency */ + if (elemlen > 0) { + /* constant length, hop by size only */ + hop = info->list_size; + } else { + /* non-constant length, hop by size + all element length blocks */ + hop = info->list_size + elemlen*info->list_numels; + } + if (lseek(fd, hop, SEEK_CUR) == -1) { + return -1; + } + + /* read the trailing value and compare with terminator_head */ + READ_ERRCHECK(fd, & terminator_tail, sizeof(terminator_tail)); + terminator_tail = ntohl(terminator_tail); + + if (terminator_head == terminator_tail) + info->consistent = 1; + else + info->consistent = 0; + + return 0; +} + +int list_dump_getinfo_file(const char *restrict filename, list_dump_info_t *restrict info) { + int fd, ret; + + fd = open(filename, O_RDONLY, 0); + if (fd < 0) return -1; + + ret = list_dump_getinfo_filedescriptor(fd, info); + close(fd); + + return ret; +} + +int list_dump_filedescriptor(const list_t *restrict l, int fd, size_t *restrict len) { + struct list_entry_s *x; + void *ser_buf; + uint32_t bufsize; + struct timeval timeofday; + struct list_dump_header_s header; + + if (l->attrs.meter == NULL && l->attrs.serializer == NULL) { + errno = ENOTTY; + return -1; + } + + /**** DUMP FORMAT **** + + [ ver timestamp | totlen numels elemlen hash | DATA ] + + where DATA can be: + @ for constant-size list (element size is constant; elemlen > 0) + [ elem elem ... elem ] + @ for other lists (element size dictated by element_meter each time; elemlen <= 0) + [ size elem size elem ... size elem ] + + all integers are encoded in NETWORK BYTE FORMAT + *****/ + + + /* prepare HEADER */ + /* version */ + header.ver = htons( SIMCLIST_DUMPFORMAT_VERSION ); + + /* timestamp */ + gettimeofday(&timeofday, NULL); + header.timestamp_sec = htonl(timeofday.tv_sec); + header.timestamp_usec = htonl(timeofday.tv_usec); + + header.rndterm = htonl((int32_t)get_random()); + + /* total list size is postprocessed afterwards */ + + /* number of elements */ + header.numels = htonl(l->numels); + + /* include an hash, if possible */ + if (l->attrs.hasher != NULL) { + if (htonl(list_hash(l, & header.listhash)) != 0) { + /* could not compute list hash! */ + return -1; + } + } else { + header.listhash = htonl(0); + } + + header.totlistlen = header.elemlen = 0; + + /* leave room for the header at the beginning of the file */ + if (lseek(fd, SIMCLIST_DUMPFORMAT_HEADERLEN, SEEK_SET) < 0) { + /* errno set by lseek() */ + return -1; + } + + /* write CONTENT */ + if (l->numels > 0) { + /* SPECULATE that the list has constant element size */ + + if (l->attrs.serializer != NULL) { /* user user-specified serializer */ + /* get preliminary length of serialized element in header.elemlen */ + ser_buf = l->attrs.serializer(l->head_sentinel->next->data, & header.elemlen); + free(ser_buf); + /* request custom serialization of each element */ + for (x = l->head_sentinel->next; x != l->tail_sentinel; x = x->next) { + ser_buf = l->attrs.serializer(x->data, &bufsize); + header.totlistlen += bufsize; + if (header.elemlen != 0) { /* continue on speculation */ + if (header.elemlen != bufsize) { + free(ser_buf); + /* constant element length speculation broken! */ + header.elemlen = 0; + header.totlistlen = 0; + x = l->head_sentinel; + if (lseek(fd, SIMCLIST_DUMPFORMAT_HEADERLEN, SEEK_SET) < 0) { + /* errno set by lseek() */ + return -1; + } + /* restart from the beginning */ + continue; + } + /* speculation confirmed */ + WRITE_ERRCHECK(fd, ser_buf, bufsize); + } else { /* speculation found broken */ + WRITE_ERRCHECK(fd, & bufsize, sizeof(size_t)); + WRITE_ERRCHECK(fd, ser_buf, bufsize); + } + free(ser_buf); + } + } else if (l->attrs.meter != NULL) { + header.elemlen = (uint32_t)l->attrs.meter(l->head_sentinel->next->data); + + /* serialize the element straight from its data */ + for (x = l->head_sentinel->next; x != l->tail_sentinel; x = x->next) { + bufsize = l->attrs.meter(x->data); + header.totlistlen += bufsize; + if (header.elemlen != 0) { + if (header.elemlen != bufsize) { + /* constant element length speculation broken! */ + header.elemlen = 0; + header.totlistlen = 0; + x = l->head_sentinel; + /* restart from the beginning */ + continue; + } + WRITE_ERRCHECK(fd, x->data, bufsize); + } else { + WRITE_ERRCHECK(fd, &bufsize, sizeof(size_t)); + WRITE_ERRCHECK(fd, x->data, bufsize); + } + } + } + /* adjust endianness */ + header.elemlen = htonl(header.elemlen); + header.totlistlen = htonl(header.totlistlen); + } + + /* write random terminator */ + WRITE_ERRCHECK(fd, & header.rndterm, sizeof(header.rndterm)); /* list terminator */ + + + /* write header */ + lseek(fd, 0, SEEK_SET); + + WRITE_ERRCHECK(fd, & header.ver, sizeof(header.ver)); /* version */ + WRITE_ERRCHECK(fd, & header.timestamp_sec, sizeof(header.timestamp_sec)); /* timestamp seconds */ + WRITE_ERRCHECK(fd, & header.timestamp_usec, sizeof(header.timestamp_usec)); /* timestamp microseconds */ + WRITE_ERRCHECK(fd, & header.rndterm, sizeof(header.rndterm)); /* random terminator */ + + WRITE_ERRCHECK(fd, & header.totlistlen, sizeof(header.totlistlen)); /* total length of elements */ + WRITE_ERRCHECK(fd, & header.numels, sizeof(header.numels)); /* number of elements */ + WRITE_ERRCHECK(fd, & header.elemlen, sizeof(header.elemlen)); /* size of each element, or 0 for independent */ + WRITE_ERRCHECK(fd, & header.listhash, sizeof(header.listhash)); /* list hash, or 0 for "ignore" */ + + + /* possibly store total written length in "len" */ + if (len != NULL) { + *len = sizeof(header) + ntohl(header.totlistlen); + } + + return 0; +} + +int list_restore_filedescriptor(list_t *restrict l, int fd, size_t *restrict len) { + struct list_dump_header_s header; + unsigned long cnt; + void *buf; + uint32_t elsize, totreadlen, totmemorylen; + + memset(& header, 0, sizeof(header)); + + /* read header */ + + /* version */ + READ_ERRCHECK(fd, &header.ver, sizeof(header.ver)); + header.ver = ntohs(header.ver); + if (header.ver != SIMCLIST_DUMPFORMAT_VERSION) { + errno = EILSEQ; + return -1; + } + + /* timestamp */ + READ_ERRCHECK(fd, & header.timestamp_sec, sizeof(header.timestamp_sec)); + header.timestamp_sec = ntohl(header.timestamp_sec); + READ_ERRCHECK(fd, & header.timestamp_usec, sizeof(header.timestamp_usec)); + header.timestamp_usec = ntohl(header.timestamp_usec); + + /* list terminator */ + READ_ERRCHECK(fd, & header.rndterm, sizeof(header.rndterm)); + + header.rndterm = ntohl(header.rndterm); + + /* total list size */ + READ_ERRCHECK(fd, & header.totlistlen, sizeof(header.totlistlen)); + header.totlistlen = ntohl(header.totlistlen); + + /* number of elements */ + READ_ERRCHECK(fd, & header.numels, sizeof(header.numels)); + header.numels = ntohl(header.numels); + + /* length of every element, or '0' = variable */ + READ_ERRCHECK(fd, & header.elemlen, sizeof(header.elemlen)); + header.elemlen = ntohl(header.elemlen); + + /* list hash, or 0 = 'ignore' */ + READ_ERRCHECK(fd, & header.listhash, sizeof(header.listhash)); + header.listhash = ntohl(header.listhash); + + + /* read content */ + totreadlen = totmemorylen = 0; + if (header.elemlen > 0) { + /* elements have constant size = header.elemlen */ + if (l->attrs.unserializer != NULL) { + /* use unserializer */ + buf = malloc(header.elemlen); + for (cnt = 0; cnt < header.numels; cnt++) { + READ_ERRCHECK(fd, buf, header.elemlen); + list_append(l, l->attrs.unserializer(buf, & elsize)); + totmemorylen += elsize; + } + } else { + /* copy verbatim into memory */ + for (cnt = 0; cnt < header.numels; cnt++) { + buf = malloc(header.elemlen); + READ_ERRCHECK(fd, buf, header.elemlen); + list_append(l, buf); + } + totmemorylen = header.numels * header.elemlen; + } + totreadlen = header.numels * header.elemlen; + } else { + /* elements have variable size. Each element is preceded by its size */ + if (l->attrs.unserializer != NULL) { + /* use unserializer */ + for (cnt = 0; cnt < header.numels; cnt++) { + READ_ERRCHECK(fd, & elsize, sizeof(elsize)); + buf = malloc((size_t)elsize); + READ_ERRCHECK(fd, buf, elsize); + totreadlen += elsize; + list_append(l, l->attrs.unserializer(buf, & elsize)); + totmemorylen += elsize; + } + } else { + /* copy verbatim into memory */ + for (cnt = 0; cnt < header.numels; cnt++) { + READ_ERRCHECK(fd, & elsize, sizeof(elsize)); + buf = malloc(elsize); + READ_ERRCHECK(fd, buf, elsize); + totreadlen += elsize; + list_append(l, buf); + } + totmemorylen = totreadlen; + } + } + + READ_ERRCHECK(fd, &elsize, sizeof(elsize)); /* read list terminator */ + elsize = ntohl(elsize); + + /* possibly verify the list consistency */ + /* wrt hash */ + /* don't do that + if (header.listhash != 0 && header.listhash != list_hash(l)) { + errno = ECANCELED; + return -1; + } + */ + + /* wrt header */ + if (totreadlen != header.totlistlen && (int32_t)elsize == header.rndterm) { + errno = EPROTO; + return -1; + } + + /* wrt file */ + if (lseek(fd, 0, SEEK_CUR) != lseek(fd, 0, SEEK_END)) { + errno = EPROTO; + return -1; + } + + if (len != NULL) { + *len = totmemorylen; + } + + return 0; +} + +int list_dump_file(const list_t *restrict l, const char *restrict filename, size_t *restrict len) { + int fd, oflag, mode; + +#ifndef _WIN32 + oflag = O_RDWR | O_CREAT | O_TRUNC; + mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH; +#else + oflag = _O_RDWR | _O_CREAT | _O_TRUNC; + mode = _S_IRUSR | _S_IWUSR | _S_IRGRP | _S_IROTH; +#endif + fd = open(filename, oflag, mode); + if (fd < 0) return -1; + + list_dump_filedescriptor(l, fd, len); + close(fd); + + return 0; +} + +int list_restore_file(list_t *restrict l, const char *restrict filename, size_t *restrict len) { + int fd; + + fd = open(filename, O_RDONLY, 0); + if (fd < 0) return -1; + + list_restore_filedescriptor(l, fd, len); + close(fd); + + return 0; +} +#endif /* ifndef SIMCLIST_NO_DUMPRESTORE */ + + +static int list_drop_elem(list_t *restrict l, struct list_entry_s *tmp, unsigned int pos) { + if (tmp == NULL) return -1; + + /* fix mid pointer. This is wrt the PRE situation */ + if (l->numels % 2) { /* now odd */ + /* sort out the base case by hand */ + if (l->numels == 1) l->mid = NULL; + else if (pos >= l->numels/2) l->mid = l->mid->prev; + } else { /* now even */ + if (pos < l->numels/2) l->mid = l->mid->next; + } + + tmp->prev->next = tmp->next; + tmp->next->prev = tmp->prev; + + /* free what's to be freed */ + if (l->attrs.copy_data && tmp->data != NULL) + free(tmp->data); + + if (l->spareelsnum < SIMCLIST_MAX_SPARE_ELEMS) { + l->spareels[l->spareelsnum++] = tmp; + } else { + free(tmp); + } + + return 0; +} + +/* ready-made comparators and meters */ +#define SIMCLIST_NUMBER_COMPARATOR(type) int list_comparator_##type(const void *a, const void *b) { return( *(type *)a < *(type *)b) - (*(type *)a > *(type *)b); } + +SIMCLIST_NUMBER_COMPARATOR(int8_t) +SIMCLIST_NUMBER_COMPARATOR(int16_t) +SIMCLIST_NUMBER_COMPARATOR(int32_t) +SIMCLIST_NUMBER_COMPARATOR(int64_t) + +SIMCLIST_NUMBER_COMPARATOR(uint8_t) +SIMCLIST_NUMBER_COMPARATOR(uint16_t) +SIMCLIST_NUMBER_COMPARATOR(uint32_t) +SIMCLIST_NUMBER_COMPARATOR(uint64_t) + +SIMCLIST_NUMBER_COMPARATOR(float) +SIMCLIST_NUMBER_COMPARATOR(double) + +int list_comparator_string(const void *a, const void *b) { return strcmp((const char *)b, (const char *)a); } + +/* ready-made metric functions */ +#define SIMCLIST_METER(type) size_t list_meter_##type(const void *el) { if (el) { /* kill compiler whinge */ } return sizeof(type); } + +SIMCLIST_METER(int8_t) +SIMCLIST_METER(int16_t) +SIMCLIST_METER(int32_t) +SIMCLIST_METER(int64_t) + +SIMCLIST_METER(uint8_t) +SIMCLIST_METER(uint16_t) +SIMCLIST_METER(uint32_t) +SIMCLIST_METER(uint64_t) + +SIMCLIST_METER(float) +SIMCLIST_METER(double) + +size_t list_meter_string(const void *el) { return strlen((const char *)el) + 1; } + +/* ready-made hashing functions */ +#define SIMCLIST_HASHCOMPUTER(type) list_hash_t list_hashcomputer_##type(const void *el) { return (list_hash_t)(*(type *)el); } + +SIMCLIST_HASHCOMPUTER(int8_t) +SIMCLIST_HASHCOMPUTER(int16_t) +SIMCLIST_HASHCOMPUTER(int32_t) +SIMCLIST_HASHCOMPUTER(int64_t) + +SIMCLIST_HASHCOMPUTER(uint8_t) +SIMCLIST_HASHCOMPUTER(uint16_t) +SIMCLIST_HASHCOMPUTER(uint32_t) +SIMCLIST_HASHCOMPUTER(uint64_t) + +SIMCLIST_HASHCOMPUTER(float) +SIMCLIST_HASHCOMPUTER(double) + +list_hash_t list_hashcomputer_string(const void *el) { + size_t l; + list_hash_t hash = 123; + const char *str = (const char *)el; + char plus; + + for (l = 0; str[l] != '\0'; l++) { + if (l) plus = hash ^ str[l]; + else plus = hash ^ (str[l] - str[0]); + hash += (plus << (CHAR_BIT * (l % sizeof(list_hash_t)))); + } + + return hash; +} + + +#ifndef NDEBUG +static int list_repOk(const list_t *restrict l) { + int ok, i; + struct list_entry_s *s; + + ok = (l != NULL) && ( + /* head/tail checks */ + (l->head_sentinel != NULL && l->tail_sentinel != NULL) && + (l->head_sentinel != l->tail_sentinel) && (l->head_sentinel->prev == NULL && l->tail_sentinel->next == NULL) && + /* empty list */ + (l->numels > 0 || (l->mid == NULL && l->head_sentinel->next == l->tail_sentinel && l->tail_sentinel->prev == l->head_sentinel)) && + /* spare elements checks */ + l->spareelsnum <= SIMCLIST_MAX_SPARE_ELEMS + ); + + if (!ok) return 0; + + if (l->numels >= 1) { + /* correct referencing */ + for (i = -1, s = l->head_sentinel; i < (int)(l->numels-1)/2 && s->next != NULL; i++, s = s->next) { + if (s->next->prev != s) break; + } + ok = (i == (int)(l->numels-1)/2 && l->mid == s); + if (!ok) return 0; + for (; s->next != NULL; i++, s = s->next) { + if (s->next->prev != s) break; + } + ok = (i == (int)l->numels && s == l->tail_sentinel); + } + + return ok; +} + +static int list_attrOk(const list_t *restrict l) { + int ok; + + ok = (l->attrs.copy_data == 0 || l->attrs.meter != NULL); + return ok; +} + +#endif + diff --git a/libs/libks/src/table.c b/libs/libks/src/table.c new file mode 100644 index 0000000000..4e28556eb9 --- /dev/null +++ b/libs/libks/src/table.c @@ -0,0 +1,4079 @@ +/* + * Generic hash table handler... + * + * Copyright 2000 by Gray Watson. + * + * This file is part of the table package. + * + * Permission to use, copy, modify, and distribute this software for + * any purpose and without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies, and that the name of Gray Watson not be used in advertising + * or publicity pertaining to distribution of the document or software + * without specific, written prior permission. + * + * Gray Watson makes no representations about the suitability of the + * software described herein for any purpose. It is provided "as is" + * without express or implied warranty. + * + * The author may be reached via http://256.com/gray/ + * + * $Id: table.c,v 1.19 2000/03/09 03:30:41 gray Exp $ + */ + +/* + * Handles basic hash-table manipulations. This is an implementation + * of open hashing with an array of buckets holding linked lists of + * elements. Each element has a key and a data. The user indexes on + * the key to find the data. See the typedefs in table_loc.h for more + * information. + */ + +#include +#include +#include +#include + +#ifdef unix + +#include + +#else + +#include +#include +#define NO_MMAP +#define open _open + +#endif + +#ifndef NO_MMAP + +#include +#include + +#ifndef MAP_FAILED +#define MAP_FAILED (caddr_t)0L +#endif + +#endif + +#define TABLE_MAIN + +#include "table.h" +#include "table_loc.h" + +#ifdef DMALLOC +#include "dmalloc.h" +#endif + +static char *rcs_id = + "$Id: table.c,v 1.19 2000/03/09 03:30:41 gray Exp $"; + +/* + * Version id for the library. You also need to add an entry to the + * NEWS and ChangeLog files. + */ +static char *version_id = "$TableVersion: 4.3.0 March 8, 2000 $"; + +/****************************** local functions ******************************/ + +/* + * static table_entry_t *first_entry + * + * DESCRIPTION: + * + * Return the first entry in the table. It will set the linear + * structure counter to the position of the first entry. + * + * RETURNS: + * + * Success: A pointer to the first entry in the table. + * + * Failure: NULL if there is no first entry. + * + * ARGUMENTS: + * + * table_p -> Table whose next entry we are finding. + * + * linear_p <-> Pointer to a linear structure which we will advance + * and then find the corresponding entry. + */ +static table_entry_t *first_entry(const table_t *table_p, + table_linear_t *linear_p) +{ + table_entry_t *entry_p; + unsigned int bucket_c = 0; + + /* look for the first non-empty bucket */ + for (bucket_c = 0; bucket_c < table_p->ta_bucket_n; bucket_c++) { + entry_p = table_p->ta_buckets[bucket_c]; + if (entry_p != NULL) { + if (linear_p != NULL) { + linear_p->tl_bucket_c = bucket_c; + linear_p->tl_entry_c = 0; + } + return TABLE_POINTER(table_p, table_entry_t *, entry_p); + } + } + + return NULL; +} + +/* + * static table_entry_t *next_entry + * + * DESCRIPTION: + * + * Return the next entry in the table which is past the position in + * our linear pointer. It will advance the linear structure counters. + * + * RETURNS: + * + * Success: A pointer to the next entry in the table. + * + * Failure: NULL. + * + * ARGUMENTS: + * + * table_p -> Table whose next entry we are finding. + * + * linear_p <-> Pointer to a linear structure which we will advance + * and then find the corresponding entry. + * + * error_p <- Pointer to an integer which when the routine returns + * will contain a table error code. + */ +static table_entry_t *next_entry(const table_t *table_p, + table_linear_t *linear_p, int *error_p) +{ + table_entry_t *entry_p; + int entry_c; + + /* can't next if we haven't first-ed */ + if (linear_p == NULL) { + SET_POINTER(error_p, TABLE_ERROR_LINEAR); + return NULL; + } + + if (linear_p->tl_bucket_c >= table_p->ta_bucket_n) { + /* + * NOTE: this might happen if we delete an item which shortens the + * table bucket numbers. + */ + SET_POINTER(error_p, TABLE_ERROR_NOT_FOUND); + return NULL; + } + + linear_p->tl_entry_c++; + + /* find the entry which is the nth in the list */ + entry_p = table_p->ta_buckets[linear_p->tl_bucket_c]; + /* NOTE: we swap the order here to be more efficient */ + for (entry_c = linear_p->tl_entry_c; entry_c > 0; entry_c--) { + /* did we reach the end of the list? */ + if (entry_p == NULL) { + break; + } + entry_p = TABLE_POINTER(table_p, table_entry_t *, entry_p)->te_next_p; + } + + /* did we find an entry in the current bucket? */ + if (entry_p != NULL) { + SET_POINTER(error_p, TABLE_ERROR_NONE); + return TABLE_POINTER(table_p, table_entry_t *, entry_p); + } + + /* find the first entry in the next non-empty bucket */ + + linear_p->tl_entry_c = 0; + for (linear_p->tl_bucket_c++; linear_p->tl_bucket_c < table_p->ta_bucket_n; + linear_p->tl_bucket_c++) { + entry_p = table_p->ta_buckets[linear_p->tl_bucket_c]; + if (entry_p != NULL) { + SET_POINTER(error_p, TABLE_ERROR_NONE); + return TABLE_POINTER(table_p, table_entry_t *, entry_p); + } + } + + SET_POINTER(error_p, TABLE_ERROR_NOT_FOUND); + return NULL; +} + +/* + * static table_entry_t *this_entry + * + * DESCRIPTION: + * + * Return the entry pointer in the table which is currently being + * indicated by our linear pointer. + * + * RETURNS: + * + * Success: A pointer to the next entry in the table. + * + * Failure: NULL. + * + * ARGUMENTS: + * + * table_p -> Table whose next entry we are finding. + * + * linear_p -> Pointer to a linear structure which we will find the + * corresponding entry. + * + * error_p <- Pointer to an integer which when the routine returns + * will contain a table error code. + */ +static table_entry_t *this_entry(const table_t *table_p, + const table_linear_t *linear_p, + int *error_p) +{ + table_entry_t *entry_p; + int entry_c; + + /* can't next if we haven't first-ed */ + if (linear_p == NULL) { + SET_POINTER(error_p, TABLE_ERROR_LINEAR); + return NULL; + } + + if (linear_p->tl_bucket_c >= table_p->ta_bucket_n) { + /* + * NOTE: this might happen if we delete an item which shortens the + * table bucket numbers. + */ + SET_POINTER(error_p, TABLE_ERROR_NOT_FOUND); + return NULL; + } + + /* find the entry which is the nth in the list */ + entry_p = table_p->ta_buckets[linear_p->tl_bucket_c]; + + /* NOTE: we swap the order here to be more efficient */ + for (entry_c = linear_p->tl_entry_c; entry_c > 0; entry_c--) { + /* did we reach the end of the list? */ + if (entry_p == NULL) { + break; + } + entry_p = TABLE_POINTER(table_p, table_entry_t *, entry_p)->te_next_p; + } + + /* did we find an entry in the current bucket? */ + if (entry_p == NULL) { + SET_POINTER(error_p, TABLE_ERROR_NOT_FOUND); + return NULL; + } + else { + SET_POINTER(error_p, TABLE_ERROR_NONE); + return TABLE_POINTER(table_p, table_entry_t *, entry_p); + } +} + +/* + * static unsigned int hash + * + * DESCRIPTION: + * + * Hash a variable-length key into a 32-bit value. Every bit of the + * key affects every bit of the return value. Every 1-bit and 2-bit + * delta achieves avalanche. About (6 * len + 35) instructions. The + * best hash table sizes are powers of 2. There is no need to use mod + * (sooo slow!). If you need less than 32 bits, use a bitmask. For + * example, if you need only 10 bits, do h = (h & hashmask(10)); In + * which case, the hash table should have hashsize(10) elements. + * + * By Bob Jenkins, 1996. bob_jenkins@compuserve.com. You may use + * this code any way you wish, private, educational, or commercial. + * It's free. See + * http://ourworld.compuserve.com/homepages/bob_jenkins/evahash.htm + * Use for hash table lookup, or anything where one collision in 2^^32 + * is acceptable. Do NOT use for cryptographic purposes. + * + * RETURNS: + * + * Returns a 32-bit hash value. + * + * ARGUMENTS: + * + * key - Key (the unaligned variable-length array of bytes) that we + * are hashing. + * + * length - Length of the key in bytes. + * + * init_val - Initialization value of the hash if you need to hash a + * number of strings together. For instance, if you are hashing N + * strings (unsigned char **)keys, do it like this: + * + * for (i=0, h=0; i= 12; len -= 12) { + a += (key_p[0] + + ((unsigned int)key_p[1] << 8) + + ((unsigned int)key_p[2] << 16) + + ((unsigned int)key_p[3] << 24)); + b += (key_p[4] + + ((unsigned int)key_p[5] << 8) + + ((unsigned int)key_p[6] << 16) + + ((unsigned int)key_p[7] << 24)); + c += (key_p[8] + + ((unsigned int)key_p[9] << 8) + + ((unsigned int)key_p[10] << 16) + + ((unsigned int)key_p[11] << 24)); + HASH_MIX(a,b,c); + key_p += 12; + } + + c += length; + + /* all the case statements fall through to the next */ + switch(len) { + case 11: + c += ((unsigned int)key_p[10] << 24); + case 10: + c += ((unsigned int)key_p[9] << 16); + case 9: + c += ((unsigned int)key_p[8] << 8); + /* the first byte of c is reserved for the length */ + case 8: + b += ((unsigned int)key_p[7] << 24); + case 7: + b += ((unsigned int)key_p[6] << 16); + case 6: + b += ((unsigned int)key_p[5] << 8); + case 5: + b += key_p[4]; + case 4: + a += ((unsigned int)key_p[3] << 24); + case 3: + a += ((unsigned int)key_p[2] << 16); + case 2: + a += ((unsigned int)key_p[1] << 8); + case 1: + a += key_p[0]; + /* case 0: nothing left to add */ + } + HASH_MIX(a, b, c); + + return c; +} + +/* + * static int entry_size + * + * DESCRIPTION: + * + * Calculates the appropriate size of an entry to include the key and + * data sizes as well as any associated alignment to the data. + * + * RETURNS: + * + * The associated size of the entry. + * + * ARGUMENTS: + * + * table_p - Table associated with the entries whose size we are + * determining. + * + * key_size - Size of the entry key. + * + * data - Size of the entry data. + */ +static int entry_size(const table_t *table_p, const unsigned int key_size, + const unsigned int data_size) +{ + int size, left; + + /* initial size -- key is already aligned if right after struct */ + size = sizeof(struct table_shell_st) + key_size; + + /* if there is no alignment then it is easy */ + if (table_p->ta_data_align == 0) { + return size + data_size; + } + + /* add in our alignement */ + left = size & (table_p->ta_data_align - 1); + if (left > 0) { + size += table_p->ta_data_align - left; + } + + /* we add the data size here after the alignment */ + size += data_size; + + return size; +} + +/* + * static unsigned char *entry_data_buf + * + * DESCRIPTION: + * + * Companion to the ENTRY_DATA_BUF macro but this handles any + * associated alignment to the data in the entry. + * + * NOTE: we assume here that the data-alignment is > 0. + * + * RETURNS: + * + * Pointer to the data segment of the entry. + * + * ARGUMENTS: + * + * table_p - Table associated with the entry. + * + * entry_p - Entry whose data pointer we are determining. + */ +static unsigned char *entry_data_buf(const table_t *table_p, + const table_entry_t *entry_p) +{ + const unsigned char *buf_p; + unsigned int size, pad; + + buf_p = entry_p->te_key_buf + entry_p->te_key_size; + + /* we need the size of the space before the data */ + size = sizeof(struct table_shell_st) + entry_p->te_key_size; + + /* add in our alignment */ + pad = size & (table_p->ta_data_align - 1); + if (pad > 0) { + pad = table_p->ta_data_align - pad; + } + + return (unsigned char *)buf_p + pad; +} + +/******************************* sort routines *******************************/ + +/* + * static int local_compare + * + * DESCRIPTION: + * + * Compare two entries by calling user's compare program or by using + * memcmp. + * + * RETURNS: + * + * < 0, == 0, or > 0 depending on whether p1 is > p2, == p2, < p2. + * + * ARGUMENTS: + * + * p1 - First entry pointer to compare. + * + * p2 - Second entry pointer to compare. + * + * compare - User comparison function. Ignored. + * + * table_p - Associated table being ordered. Ignored. + * + * err_bp - Pointer to an integer which will be set with 1 if an error + * has occurred. It cannot be NULL. + */ +static int local_compare(const void *p1, const void *p2, + table_compare_t compare, const table_t *table_p, + int *err_bp) +{ + const table_entry_t * const *ent1_p = p1, * const *ent2_p = p2; + int cmp; + unsigned int size; + + /* compare as many bytes as we can */ + size = (*ent1_p)->te_key_size; + if ((*ent2_p)->te_key_size < size) { + size = (*ent2_p)->te_key_size; + } + cmp = memcmp(ENTRY_KEY_BUF(*ent1_p), ENTRY_KEY_BUF(*ent2_p), size); + /* if common-size equal, then if next more bytes, it is larger */ + if (cmp == 0) { + cmp = (*ent1_p)->te_key_size - (*ent2_p)->te_key_size; + } + + *err_bp = 0; + return cmp; +} + +/* + * static int local_compare_pos + * + * DESCRIPTION: + * + * Compare two entries by calling user's compare program or by using + * memcmp. + * + * RETURNS: + * + * < 0, == 0, or > 0 depending on whether p1 is > p2, == p2, < p2. + * + * ARGUMENTS: + * + * p1 - First entry pointer to compare. + * + * p2 - Second entry pointer to compare. + * + * compare - User comparison function. Ignored. + * + * table_p - Associated table being ordered. + * + * err_bp - Pointer to an integer which will be set with 1 if an error + * has occurred. It cannot be NULL. + */ +static int local_compare_pos(const void *p1, const void *p2, + table_compare_t compare, + const table_t *table_p, int *err_bp) +{ + const table_linear_t *lin1_p = p1, *lin2_p = p2; + const table_entry_t *ent1_p, *ent2_p; + int cmp, ret; + unsigned int size; + + /* get entry pointers */ + ent1_p = this_entry(table_p, lin1_p, &ret); + ent2_p = this_entry(table_p, lin2_p, &ret); + if (ent1_p == NULL || ent2_p == NULL) { + *err_bp = 1; + return 0; + } + + /* compare as many bytes as we can */ + size = ent1_p->te_key_size; + if (ent2_p->te_key_size < size) { + size = ent2_p->te_key_size; + } + cmp = memcmp(ENTRY_KEY_BUF(ent1_p), ENTRY_KEY_BUF(ent2_p), size); + /* if common-size equal, then if next more bytes, it is larger */ + if (cmp == 0) { + cmp = ent1_p->te_key_size - ent2_p->te_key_size; + } + + *err_bp = 0; + return cmp; +} + +/* + * static int external_compare + * + * DESCRIPTION: + * + * Compare two entries by calling user's compare program or by using + * memcmp. + * + * RETURNS: + * + * < 0, == 0, or > 0 depending on whether p1 is > p2, == p2, < p2. + * + * ARGUMENTS: + * + * p1 - First entry pointer to compare. + * + * p2 - Second entry pointer to compare. + * + * user_compare - User comparison function. + * + * table_p - Associated table being ordered. + * + * err_bp - Pointer to an integer which will be set with 1 if an error + * has occurred. It cannot be NULL. + */ +static int external_compare(const void *p1, const void *p2, + table_compare_t user_compare, + const table_t *table_p, int *err_bp) +{ + const table_entry_t * const *ent1_p = p1, * const *ent2_p = p2; + /* since we know we are not aligned we can use the EXTRY_DATA_BUF macro */ + *err_bp = 0; + return user_compare(ENTRY_KEY_BUF(*ent1_p), (*ent1_p)->te_key_size, + ENTRY_DATA_BUF(table_p, *ent1_p), + (*ent1_p)->te_data_size, + ENTRY_KEY_BUF(*ent2_p), (*ent2_p)->te_key_size, + ENTRY_DATA_BUF(table_p, *ent2_p), + (*ent2_p)->te_data_size); +} + +/* + * static int external_compare_pos + * + * DESCRIPTION: + * + * Compare two entries by calling user's compare program or by using + * memcmp. + * + * RETURNS: + * + * < 0, == 0, or > 0 depending on whether p1 is > p2, == p2, < p2. + * + * ARGUMENTS: + * + * p1 - First entry pointer to compare. + * + * p2 - Second entry pointer to compare. + * + * user_compare - User comparison function. + * + * table_p - Associated table being ordered. + * + * err_bp - Pointer to an integer which will be set with 1 if an error + * has occurred. It cannot be NULL. +*/ +static int external_compare_pos(const void *p1, const void *p2, + table_compare_t user_compare, + const table_t *table_p, int *err_bp) +{ + const table_linear_t *lin1_p = p1, *lin2_p = p2; + const table_entry_t *ent1_p, *ent2_p; + int ret; + + /* get entry pointers */ + ent1_p = this_entry(table_p, lin1_p, &ret); + ent2_p = this_entry(table_p, lin2_p, &ret); + if (ent1_p == NULL || ent2_p == NULL) { + *err_bp = 1; + return 0; + } + + /* since we know we are not aligned we can use the EXTRY_DATA_BUF macro */ + *err_bp = 0; + return user_compare(ENTRY_KEY_BUF(ent1_p), (ent1_p)->te_key_size, + ENTRY_DATA_BUF(table_p, ent1_p), ent1_p->te_data_size, + ENTRY_KEY_BUF(ent2_p), ent2_p->te_key_size, + ENTRY_DATA_BUF(table_p, ent2_p), ent2_p->te_data_size); +} + +/* + * static int external_compare_align + * + * DESCRIPTION: + * + * Compare two entries by calling user's compare program or by using + * memcmp. Alignment information is necessary. + * + * RETURNS: + * + * < 0, == 0, or > 0 depending on whether p1 is > p2, == p2, < p2. + * + * ARGUMENTS: + * + * p1 - First entry pointer to compare. + * + * p2 - Second entry pointer to compare. + * + * user_compare - User comparison function. + * + * table_p - Associated table being ordered. + * + * err_bp - Pointer to an integer which will be set with 1 if an error + * has occurred. It cannot be NULL. + */ +static int external_compare_align(const void *p1, const void *p2, + table_compare_t user_compare, + const table_t *table_p, int *err_bp) +{ + const table_entry_t * const *ent1_p = p1, * const *ent2_p = p2; + /* since we are aligned we have to use the entry_data_buf function */ + *err_bp = 0; + return user_compare(ENTRY_KEY_BUF(*ent1_p), (*ent1_p)->te_key_size, + entry_data_buf(table_p, *ent1_p), + (*ent1_p)->te_data_size, + ENTRY_KEY_BUF(*ent2_p), (*ent2_p)->te_key_size, + entry_data_buf(table_p, *ent2_p), + (*ent2_p)->te_data_size); +} + +/* + * static int external_compare_align_pos + * + * DESCRIPTION: + * + * Compare two entries by calling user's compare program or by using + * memcmp. Alignment information is necessary. + * + * RETURNS: + * + * < 0, == 0, or > 0 depending on whether p1 is > p2, == p2, < p2. + * + * ARGUMENTS: + * + * p1 - First entry pointer to compare. + * + * p2 - Second entry pointer to compare. + * + * user_compare - User comparison function. + * + * table_p - Associated table being ordered. + * + * err_bp - Pointer to an integer which will be set with 1 if an error + * has occurred. It cannot be NULL. + */ +static int external_compare_align_pos(const void *p1, const void *p2, + table_compare_t user_compare, + const table_t *table_p, int *err_bp) +{ + const table_linear_t *lin1_p = p1, *lin2_p = p2; + const table_entry_t *ent1_p, *ent2_p; + int ret; + + /* get entry pointers */ + ent1_p = this_entry(table_p, lin1_p, &ret); + ent2_p = this_entry(table_p, lin2_p, &ret); + if (ent1_p == NULL || ent2_p == NULL) { + *err_bp = 1; + return 0; + } + + /* since we are aligned we have to use the entry_data_buf function */ + *err_bp = 0; + return user_compare(ENTRY_KEY_BUF(ent1_p), ent1_p->te_key_size, + entry_data_buf(table_p, ent1_p), ent1_p->te_data_size, + ENTRY_KEY_BUF(ent2_p), ent2_p->te_key_size, + entry_data_buf(table_p, ent2_p), ent2_p->te_data_size); +} + +/* + * static void swap_bytes + * + * DESCRIPTION: + * + * Swap the values between two items of a specified size. + * + * RETURNS: + * + * None. + * + * ARGUMENTS: + * + * item1_p -> Pointer to the first item. + * + * item2_p -> Pointer to the first item. + * + * ele_size -> Size of the two items. + */ +static void swap_bytes(unsigned char *item1_p, unsigned char *item2_p, + int ele_size) +{ + unsigned char char_temp; + + for (; ele_size > 0; ele_size--) { + char_temp = *item1_p; + *item1_p = *item2_p; + *item2_p = char_temp; + item1_p++; + item2_p++; + } +} + +/* + * static void insert_sort + * + * DESCRIPTION: + * + * Do an insertion sort which is faster for small numbers of items and + * better if the items are already sorted. + * + * RETURNS: + * + * Success - TABLE_ERROR_NONE + * + * Failure - Table error code. + * + * ARGUMENTS: + * + * first_p <-> Start of the list that we are splitting. + * + * last_p <-> Last entry in the list that we are splitting. + * + * holder_p <-> Location of hold area we can store an entry. + * + * ele_size -> Size of the each element in the list. + * + * compare -> Our comparison function. + * + * user_compare -> User comparison function. Could be NULL if we are + * just using a local comparison function. + * + * table_p -> Associated table being sorted. + */ +static int insert_sort(unsigned char *first_p, unsigned char *last_p, + unsigned char *holder_p, + const unsigned int ele_size, compare_t compare, + table_compare_t user_compare, table_t *table_p) +{ + unsigned char *inner_p, *outer_p; + int ret, err_b; + + for (outer_p = first_p + ele_size; outer_p <= last_p; ) { + + /* look for the place to insert the entry */ + for (inner_p = outer_p - ele_size; + inner_p >= first_p; + inner_p -= ele_size) { + ret = compare(outer_p, inner_p, user_compare, table_p, &err_b); + if (err_b) { + return TABLE_ERROR_COMPARE; + } + if (ret >= 0) { + break; + } + } + inner_p += ele_size; + + /* do we need to insert the entry in? */ + if (outer_p != inner_p) { + /* + * Now we shift the entry down into its place in the already + * sorted list. + */ + memcpy(holder_p, outer_p, ele_size); + memmove(inner_p + ele_size, inner_p, outer_p - inner_p); + memcpy(inner_p, holder_p, ele_size); + } + + outer_p += ele_size; + } + + return TABLE_ERROR_NONE; +} + +/* + * static int split + * + * DESCRIPTION: + * + * This sorts an array of longs via the quick sort algorithm (it's + * pretty quick) + * + * RETURNS: + * + * None. + * + * ARGUMENTS: + * + * first_p -> Start of the list that we are splitting. + * + * last_p -> Last entry in the list that we are splitting. + * + * ele_size -> Size of the each element in the list. + * + * compare -> Our comparison function. + * + * user_compare -> User comparison function. Could be NULL if we are + * just using a local comparison function. + * + * table_p -> Associated table being sorted. + */ +static int split(unsigned char *first_p, unsigned char *last_p, + const unsigned int ele_size, compare_t compare, + table_compare_t user_compare, table_t *table_p) +{ + unsigned char *left_p, *right_p, *pivot_p, *left_last_p, *right_first_p; + unsigned char *firsts[MAX_QSORT_SPLITS], *lasts[MAX_QSORT_SPLITS], *pivot; + unsigned int width, split_c = 0; + int size1, size2, min_qsort_size; + int ret, err_b; + + /* + * Allocate some space for our pivot value. We also use this as + * holder space for our insert sort. + */ + pivot = alloca(ele_size); + if (pivot == NULL) { + /* what else can we do? */ + abort(); + } + + min_qsort_size = MAX_QSORT_MANY * ele_size; + + while (1) { + + /* find the left, right, and mid point */ + left_p = first_p; + right_p = last_p; + /* is there a faster way to find this? */ + width = (last_p - first_p) / ele_size; + pivot_p = first_p + ele_size * (width >> 1); + + /* + * Find which of the left, middle, and right elements is the + * median (Knuth vol3 p123). + */ + ret = compare(first_p, pivot_p, user_compare, table_p, &err_b); + if (err_b) { + return TABLE_ERROR_COMPARE; + } + if (ret > 0) { + swap_bytes(first_p, pivot_p, ele_size); + } + ret = compare(pivot_p, last_p, user_compare, table_p, &err_b); + if (err_b) { + return TABLE_ERROR_COMPARE; + } + if (ret > 0) { + swap_bytes(pivot_p, last_p, ele_size); + ret = compare(first_p, pivot_p, user_compare, table_p, &err_b); + if (err_b) { + return TABLE_ERROR_COMPARE; + } + if (ret > 0) { + swap_bytes(first_p, pivot_p, ele_size); + } + } + + /* + * save our pivot so we don't have to worry about hitting and + * swapping it elsewhere while we iterate across the list below. + */ + memcpy(pivot, pivot_p, ele_size); + + do { + + /* shift the left side up until we reach the pivot value */ + while (1) { + ret = compare(left_p, pivot, user_compare, table_p, &err_b); + if (err_b) { + return TABLE_ERROR_COMPARE; + } + if (ret >= 0) { + break; + } + left_p += ele_size; + } + /* shift the right side down until we reach the pivot value */ + while (1) { + ret = compare(pivot, right_p, user_compare, table_p, &err_b); + if (err_b) { + return TABLE_ERROR_COMPARE; + } + if (ret >= 0) { + break; + } + right_p -= ele_size; + } + + /* if we met in the middle then we are done */ + if (left_p == right_p) { + left_p += ele_size; + right_p -= ele_size; + break; + } + else if (left_p < right_p) { + /* + * swap the left and right since they both were on the wrong + * size of the pivot and continue + */ + swap_bytes(left_p, right_p, ele_size); + left_p += ele_size; + right_p -= ele_size; + } + } while (left_p <= right_p); + + /* Rename variables to make more sense. This will get optimized out. */ + right_first_p = left_p; + left_last_p = right_p; + + /* determine the size of the left and right hand parts */ + size1 = left_last_p - first_p; + size2 = last_p - right_first_p; + + /* is the 1st half small enough to just insert-sort? */ + if (size1 < min_qsort_size) { + + /* use the pivot as our temporary space */ + ret = insert_sort(first_p, left_last_p, pivot, ele_size, compare, + user_compare, table_p); + if (ret != TABLE_ERROR_NONE) { + return ret; + } + + /* is the 2nd part small as well? */ + if (size2 < min_qsort_size) { + + /* use the pivot as our temporary space */ + ret = insert_sort(right_first_p, last_p, pivot, ele_size, compare, + user_compare, table_p); + if (ret != TABLE_ERROR_NONE) { + return ret; + } + + /* pop a partition off our stack */ + if (split_c == 0) { + /* we are done */ + return TABLE_ERROR_NONE; + } + split_c--; + first_p = firsts[split_c]; + last_p = lasts[split_c]; + } + else { + /* we can just handle the right side immediately */ + first_p = right_first_p; + /* last_p = last_p */ + } + } + else if (size2 < min_qsort_size) { + + /* use the pivot as our temporary space */ + ret = insert_sort(right_first_p, last_p, pivot, ele_size, compare, + user_compare, table_p); + if (ret != TABLE_ERROR_NONE) { + return ret; + } + + /* we can just handle the left side immediately */ + /* first_p = first_p */ + last_p = left_last_p; + } + else { + /* + * neither partition is small, we'll have to push the larger one + * of them on the stack + */ + if (split_c >= MAX_QSORT_SPLITS) { + /* sanity check here -- we should never get here */ + abort(); + } + if (size1 > size2) { + /* push the left partition on the stack */ + firsts[split_c] = first_p; + lasts[split_c] = left_last_p; + split_c++; + /* continue handling the right side */ + first_p = right_first_p; + /* last_p = last_p */ + } + else { + /* push the right partition on the stack */ + firsts[split_c] = right_first_p; + lasts[split_c] = last_p; + split_c++; + /* continue handling the left side */ + /* first_p = first_p */ + last_p = left_last_p; + } + } + } + + return TABLE_ERROR_NONE; +} + +/*************************** exported routines *******************************/ + +/* + * table_t *table_alloc + * + * DESCRIPTION: + * + * Allocate a new table structure. + * + * RETURNS: + * + * A pointer to the new table structure which must be passed to + * table_free to be deallocated. On error a NULL is returned. + * + * ARGUMENTS: + * + * bucket_n - Number of buckets for the hash table. Our current hash + * value works best with base two numbers. Set to 0 to take the + * library default of 1024. + * + * error_p - Pointer to an integer which, if not NULL, will contain a + * table error code. + */ +table_t *table_alloc(const unsigned int bucket_n, int *error_p) +{ + table_t *table_p = NULL; + unsigned int buck_n; + + /* allocate a table structure */ + table_p = malloc(sizeof(table_t)); + if (table_p == NULL) { + SET_POINTER(error_p, TABLE_ERROR_ALLOC); + return NULL; + } + + if (bucket_n > 0) { + buck_n = bucket_n; + } + else { + buck_n = DEFAULT_SIZE; + } + + /* allocate the buckets which are NULLed */ + table_p->ta_buckets = (table_entry_t **)calloc(buck_n, + sizeof(table_entry_t *)); + if (table_p->ta_buckets == NULL) { + SET_POINTER(error_p, TABLE_ERROR_ALLOC); + free(table_p); + return NULL; + } + + /* initialize structure */ + table_p->ta_magic = TABLE_MAGIC; + table_p->ta_flags = 0; + table_p->ta_bucket_n = buck_n; + table_p->ta_entry_n = 0; + table_p->ta_data_align = 0; + table_p->ta_linear.tl_magic = 0; + table_p->ta_linear.tl_bucket_c = 0; + table_p->ta_linear.tl_entry_c = 0; + table_p->ta_mmap = NULL; + table_p->ta_file_size = 0; + table_p->ta_mem_pool = NULL; + table_p->ta_alloc_func = NULL; + table_p->ta_resize_func = NULL; + table_p->ta_free_func = NULL; + + SET_POINTER(error_p, TABLE_ERROR_NONE); + return table_p; +} + +/* + * table_t *table_alloc_in_pool + * + * DESCRIPTION: + * + * Allocate a new table structure in a memory pool or using + * alternative allocation and free functions. + * + * RETURNS: + * + * A pointer to the new table structure which must be passed to + * table_free to be deallocated. On error a NULL is returned. + * + * ARGUMENTS: + * + * bucket_n - Number of buckets for the hash table. Our current hash + * value works best with base two numbers. Set to 0 to take the + * library default of 1024. + * + * mem_pool <-> Memory pool to associate with the table. Can be NULL. + * + * alloc_func -> Allocate function we are overriding malloc() with. + * + * resize_func -> Resize function we are overriding the standard + * memory resize/realloc with. This can be NULL in which cause the + * library will allocate, copy, and free itself. + * + * free_func -> Free function we are overriding free() with. + * + * error_p - Pointer to an integer which, if not NULL, will contain a + * table error code. + */ +table_t *table_alloc_in_pool(const unsigned int bucket_n, + void *mem_pool, + table_mem_alloc_t alloc_func, + table_mem_resize_t resize_func, + table_mem_free_t free_func, int *error_p) +{ + table_t *table_p = NULL; + unsigned int buck_n, size; + + /* make sure we have real functions, mem_pool and resize_func can be NULL */ + if (alloc_func == NULL || free_func == NULL) { + SET_POINTER(error_p, TABLE_ERROR_ARG_NULL); + return NULL; + } + + /* allocate a table structure */ + table_p = alloc_func(mem_pool, sizeof(table_t)); + if (table_p == NULL) { + SET_POINTER(error_p, TABLE_ERROR_ALLOC); + return NULL; + } + + if (bucket_n > 0) { + buck_n = bucket_n; + } + else { + buck_n = DEFAULT_SIZE; + } + + /* allocate the buckets which are NULLed */ + size = buck_n * sizeof(table_entry_t *); + table_p->ta_buckets = (table_entry_t **)alloc_func(mem_pool, size); + if (table_p->ta_buckets == NULL) { + SET_POINTER(error_p, TABLE_ERROR_ALLOC); + (void)free_func(mem_pool, table_p, sizeof(table_t)); + return NULL; + } + /* + * We zero it ourselves to save the necessity of having a + * table_mem_calloc_t memory override function. + */ + memset(table_p->ta_buckets, 0, size); + + /* initialize structure */ + table_p->ta_magic = TABLE_MAGIC; + table_p->ta_flags = 0; + table_p->ta_bucket_n = buck_n; + table_p->ta_entry_n = 0; + table_p->ta_data_align = 0; + table_p->ta_linear.tl_magic = 0; + table_p->ta_linear.tl_bucket_c = 0; + table_p->ta_linear.tl_entry_c = 0; + table_p->ta_mmap = NULL; + table_p->ta_file_size = 0; + table_p->ta_mem_pool = mem_pool; + table_p->ta_alloc_func = alloc_func; + table_p->ta_resize_func = resize_func; + table_p->ta_free_func = free_func; + + SET_POINTER(error_p, TABLE_ERROR_NONE); + return table_p; +} + +/* + * int table_attr + * + * DESCRIPTION: + * + * Set the attributes for the table. The available attributes are + * specified at the top of table.h. + * + * RETURNS: + * + * Success - TABLE_ERROR_NONE + * + * Failure - Table error code. + * + * ARGUMENTS: + * + * table_p - Pointer to a table structure which we will be altering. + * + * attr - Attribute(s) that we will be applying to the table. + */ +int table_attr(table_t *table_p, const int attr) +{ + if (table_p == NULL) { + return TABLE_ERROR_ARG_NULL; + } + if (table_p->ta_magic != TABLE_MAGIC) { + return TABLE_ERROR_PNT; + } + + table_p->ta_flags = attr; + + return TABLE_ERROR_NONE; +} + +/* + * int table_set_data_alignment + * + * DESCRIPTION: + * + * Set the alignment for the data in the table. This is used when you + * want to store binary data types and refer to them directly out of + * the table storage. For instance if you are storing integers as + * data in the table and want to be able to retrieve the location of + * the interger and then increment it as (*loc_p)++. Otherwise you + * would have to memcpy it out to an integer, increment it, and memcpy + * it back. If you are storing character data, no alignment is + * necessary. + * + * For most data elements, sizeof(long) is recommended unless you use + * smaller data types exclusively. + * + * WARNING: If necessary, you must set the data alignment before any + * data gets put into the table. Otherwise a TABLE_ERROR_NOT_EMPTY + * error will be returned. + * + * NOTE: there is no way to set the key data alignment although it + * should automatically be long aligned. + * + * RETURNS: + * + * Success - TABLE_ERROR_NONE + * + * Failure - Table error code. + * + * ARGUMENTS: + * + * table_p - Pointer to a table structure which we will be altering. + * + * alignment - Alignment requested for the data. Must be a power of + * 2. Set to 0 for none. + */ +int table_set_data_alignment(table_t *table_p, const int alignment) +{ + int val; + + if (table_p == NULL) { + return TABLE_ERROR_ARG_NULL; + } + if (table_p->ta_magic != TABLE_MAGIC) { + return TABLE_ERROR_PNT; + } + if (table_p->ta_entry_n > 0) { + return TABLE_ERROR_NOT_EMPTY; + } + + /* defaults */ + if (alignment < 2) { + table_p->ta_data_align = 0; + } + else { + /* verify we have a base 2 number */ + for (val = 2; val < MAX_ALIGNMENT; val *= 2) { + if (val == alignment) { + break; + } + } + if (val >= MAX_ALIGNMENT) { + return TABLE_ERROR_ALIGNMENT; + } + table_p->ta_data_align = alignment; + } + + return TABLE_ERROR_NONE; +} + +/* + * int table_clear + * + * DESCRIPTION: + * + * Clear out and free all elements in a table structure. + * + * RETURNS: + * + * Success - TABLE_ERROR_NONE + * + * Failure - Table error code. + * + * ARGUMENTS: + * + * table_p - Table structure pointer that we will be clearing. + */ +int table_clear(table_t *table_p) +{ + int final = TABLE_ERROR_NONE; + table_entry_t *entry_p, *next_p; + table_entry_t **bucket_p, **bounds_p; + + if (table_p == NULL) { + return TABLE_ERROR_ARG_NULL; + } + if (table_p->ta_magic != TABLE_MAGIC) { + return TABLE_ERROR_PNT; + } + +#ifndef NO_MMAP + /* no mmap support so immediate error */ + if (table_p->ta_mmap != NULL) { + return TABLE_ERROR_MMAP_OP; + } +#endif + + /* free the table allocation and table structure */ + bounds_p = table_p->ta_buckets + table_p->ta_bucket_n; + for (bucket_p = table_p->ta_buckets; bucket_p < bounds_p; bucket_p++) { + for (entry_p = *bucket_p; entry_p != NULL; entry_p = next_p) { + /* record the next pointer before we free */ + next_p = entry_p->te_next_p; + if (table_p->ta_free_func == NULL) { + free(entry_p); + } + else if (! table_p->ta_free_func(table_p->ta_mem_pool, entry_p, + entry_size(table_p, + entry_p->te_key_size, + entry_p->te_data_size))) { + final = TABLE_ERROR_FREE; + } + } + + /* clear the bucket entry after we free its entries */ + *bucket_p = NULL; + } + + /* reset table state info */ + table_p->ta_entry_n = 0; + table_p->ta_linear.tl_magic = 0; + table_p->ta_linear.tl_bucket_c = 0; + table_p->ta_linear.tl_entry_c = 0; + + return final; +} + +/* + * int table_free + * + * DESCRIPTION: + * + * Deallocates a table structure. + * + * RETURNS: + * + * Success - TABLE_ERROR_NONE + * + * Failure - Table error code. + * + * ARGUMENTS: + * + * table_p - Table structure pointer that we will be freeing. + */ +int table_free(table_t *table_p) +{ + int ret; + + if (table_p == NULL) { + return TABLE_ERROR_ARG_NULL; + } + if (table_p->ta_magic != TABLE_MAGIC) { + return TABLE_ERROR_PNT; + } + +#ifndef NO_MMAP + /* no mmap support so immediate error */ + if (table_p->ta_mmap != NULL) { + return TABLE_ERROR_MMAP_OP; + } +#endif + + ret = table_clear(table_p); + + if (table_p->ta_buckets != NULL) { + if (table_p->ta_free_func == NULL) { + free(table_p->ta_buckets); + } + else if (! table_p->ta_free_func(table_p->ta_mem_pool, + table_p->ta_buckets, + table_p->ta_bucket_n * + sizeof(table_entry_t *))) { + return TABLE_ERROR_FREE; + } + } + table_p->ta_magic = 0; + if (table_p->ta_free_func == NULL) { + free(table_p); + } + else if (! table_p->ta_free_func(table_p->ta_mem_pool, table_p, + sizeof(table_t))) { + if (ret == TABLE_ERROR_NONE) { + ret = TABLE_ERROR_FREE; + } + } + + return ret; +} + +/* + * int table_insert_kd + * + * DESCRIPTION: + * + * Like table_insert except it passes back a pointer to the key and + * the data buffers after they have been inserted into the table + * structure. + * + * This routine adds a key/data pair both of which are made up of a + * buffer of bytes and an associated size. Both the key and the data + * will be copied into buffers allocated inside the table. If the key + * exists already, the associated data will be replaced if the + * overwrite flag is set, otherwise an error is returned. + * + * NOTE: be very careful changing the values since the table library + * provides the pointers to its memory. The key can _never_ be + * changed otherwise you will not find it again. The data can be + * changed but its length can never be altered unless you delete and + * re-insert it into the table. + * + * WARNING: The pointers to the key and data are not in any specific + * alignment. Accessing the key and/or data as an short, integer, or + * long pointer directly can cause problems. + * + * WARNING: Replacing a data cell (not inserting) will cause the table + * linked list to be temporarily invalid. Care must be taken with + * multiple threaded programs which are relying on the first/next + * linked list to be always valid. + * + * RETURNS: + * + * Success - TABLE_ERROR_NONE + * + * Failure - Table error code. + * + * ARGUMENTS: + * + * table_p - Table structure pointer into which we will be inserting a + * new key/data pair. + * + * key_buf - Buffer of bytes of the key that we are inserting. If you + * are storing an (int) as the key (for example) then key_buf should + * be a (int *). + * + * key_size - Size of the key_buf buffer. If set to < 0 then the + * library will do a strlen of key_buf and add 1 for the '\0'. If you + * are storing an (int) as the key (for example) then key_size should + * be sizeof(int). + * + * data_buf - Buffer of bytes of the data that we are inserting. If + * it is NULL then the library will allocate space for the data in the + * table without copying in any information. If data_buf is NULL and + * data_size is 0 then the library will associate a NULL data pointer + * with the key. If you are storing a (long) as the data (for + * example) then data_buf should be a (long *). + * + * data_size - Size of the data_buf buffer. If set to < 0 then the + * library will do a strlen of data_buf and add 1 for the '\0'. If + * you are storing an (long) as the key (for example) then key_size + * should be sizeof(long). + * + * key_buf_p - Pointer which, if not NULL, will be set to the address + * of the key storage that was allocated in the table. If you are + * storing an (int) as the key (for example) then key_buf_p should be + * (int **) i.e. the address of a (int *). + * + * data_buf_p - Pointer which, if not NULL, will be set to the address + * of the data storage that was allocated in the table. If you are + * storing an (long) as the data (for example) then data_buf_p should + * be (long **) i.e. the address of a (long *). + * + * overwrite - Flag which, if set to 1, will allow the overwriting of + * the data in the table with the new data if the key already exists + * in the table. + */ +int table_insert_kd(table_t *table_p, + const void *key_buf, const int key_size, + const void *data_buf, const int data_size, + void **key_buf_p, void **data_buf_p, + const char overwrite_b) +{ + int bucket; + unsigned int ksize, dsize, new_size, old_size, copy_size; + table_entry_t *entry_p, *last_p, *new_entry_p; + void *key_copy_p, *data_copy_p; + + /* check the arguments */ + if (table_p == NULL) { + return TABLE_ERROR_ARG_NULL; + } + if (table_p->ta_magic != TABLE_MAGIC) { + return TABLE_ERROR_PNT; + } + if (key_buf == NULL) { + return TABLE_ERROR_ARG_NULL; + } + /* data_buf can be null but size must be >= 0, if it isn't null size != 0 */ + if ((data_buf == NULL && data_size < 0) + || (data_buf != NULL && data_size == 0)) { + return TABLE_ERROR_SIZE; + } + +#ifndef NO_MMAP + /* no mmap support so immediate error */ + if (table_p->ta_mmap != NULL) { + return TABLE_ERROR_MMAP_OP; + } +#endif + + /* determine sizes of key and data */ + if (key_size < 0) { + ksize = strlen((char *)key_buf) + sizeof(char); + } + else { + ksize = key_size; + } + if (data_size < 0) { + dsize = strlen((char *)data_buf) + sizeof(char); + } + else { + dsize = data_size; + } + + /* get the bucket number via a hash function */ + bucket = hash(key_buf, ksize, 0) % table_p->ta_bucket_n; + + /* look for the entry in this bucket, only check keys of the same size */ + last_p = NULL; + for (entry_p = table_p->ta_buckets[bucket]; + entry_p != NULL; + last_p = entry_p, entry_p = entry_p->te_next_p) { + if (entry_p->te_key_size == ksize + && memcmp(ENTRY_KEY_BUF(entry_p), key_buf, ksize) == 0) { + break; + } + } + + /* did we find it? then we are in replace mode. */ + if (entry_p != NULL) { + + /* can we not overwrite existing data? */ + if (! overwrite_b) { + SET_POINTER(key_buf_p, ENTRY_KEY_BUF(entry_p)); + if (data_buf_p != NULL) { + if (entry_p->te_data_size == 0) { + *data_buf_p = NULL; + } + else { + if (table_p->ta_data_align == 0) { + *data_buf_p = ENTRY_DATA_BUF(table_p, entry_p); + } + else { + *data_buf_p = entry_data_buf(table_p, entry_p); + } + } + } + return TABLE_ERROR_OVERWRITE; + } + + /* re-alloc entry's data if the new size != the old */ + if (dsize != entry_p->te_data_size) { + + /* + * First we delete it from the list to keep the list whole. + * This properly preserves the linked list in case we have a + * thread marching through the linked list while we are + * inserting. Maybe this is an unnecessary protection but it + * should not harm that much. + */ + if (last_p == NULL) { + table_p->ta_buckets[bucket] = entry_p->te_next_p; + } + else { + last_p->te_next_p = entry_p->te_next_p; + } + + /* + * Realloc the structure which may change its pointer. NOTE: + * this may change any previous data_key_p and data_copy_p + * pointers. + */ + new_size = entry_size(table_p, entry_p->te_key_size, dsize); + if (table_p->ta_resize_func == NULL) { + /* if the alloc function has not been overriden do realloc */ + if (table_p->ta_alloc_func == NULL) { + entry_p = (table_entry_t *)realloc(entry_p, new_size); + if (entry_p == NULL) { + return TABLE_ERROR_ALLOC; + } + } + else { + old_size = new_size - dsize + entry_p->te_data_size; + /* + * if the user did override alloc but not resize, assume + * that the user's allocation functions can't grok realloc + * and do it ourselves the hard way. + */ + new_entry_p = + (table_entry_t *)table_p->ta_alloc_func(table_p->ta_mem_pool, + new_size); + if (new_entry_p == NULL) { + return TABLE_ERROR_ALLOC; + } + if (new_size > old_size) { + copy_size = old_size; + } + else { + copy_size = new_size; + } + memcpy(new_entry_p, entry_p, copy_size); + if (! table_p->ta_free_func(table_p->ta_mem_pool, entry_p, + old_size)) { + return TABLE_ERROR_FREE; + } + entry_p = new_entry_p; + } + } + else { + old_size = new_size - dsize + entry_p->te_data_size; + entry_p = (table_entry_t *) + table_p->ta_resize_func(table_p->ta_mem_pool, entry_p, + old_size, new_size); + if (entry_p == NULL) { + return TABLE_ERROR_ALLOC; + } + } + + /* add it back to the front of the list */ + entry_p->te_data_size = dsize; + entry_p->te_next_p = table_p->ta_buckets[bucket]; + table_p->ta_buckets[bucket] = entry_p; + } + + /* copy or replace data in storage */ + if (dsize > 0) { + if (table_p->ta_data_align == 0) { + data_copy_p = ENTRY_DATA_BUF(table_p, entry_p); + } + else { + data_copy_p = entry_data_buf(table_p, entry_p); + } + if (data_buf != NULL) { + memcpy(data_copy_p, data_buf, dsize); + } + } + else { + data_copy_p = NULL; + } + + SET_POINTER(key_buf_p, ENTRY_KEY_BUF(entry_p)); + SET_POINTER(data_buf_p, data_copy_p); + + /* returning from the section where we were overwriting table data */ + return TABLE_ERROR_NONE; + } + + /* + * It is a new entry. + */ + + /* allocate a new entry */ + new_size = entry_size(table_p, ksize, dsize); + if (table_p->ta_alloc_func == NULL) { + entry_p = (table_entry_t *)malloc(new_size); + } + else { + entry_p = + (table_entry_t *)table_p->ta_alloc_func(table_p->ta_mem_pool, new_size); + } + if (entry_p == NULL) { + return TABLE_ERROR_ALLOC; + } + + /* copy key into storage */ + entry_p->te_key_size = ksize; + key_copy_p = ENTRY_KEY_BUF(entry_p); + memcpy(key_copy_p, key_buf, ksize); + + /* copy data in */ + entry_p->te_data_size = dsize; + if (dsize > 0) { + if (table_p->ta_data_align == 0) { + data_copy_p = ENTRY_DATA_BUF(table_p, entry_p); + } + else { + data_copy_p = entry_data_buf(table_p, entry_p); + } + if (data_buf != NULL) { + memcpy(data_copy_p, data_buf, dsize); + } + } + else { + data_copy_p = NULL; + } + + SET_POINTER(key_buf_p, key_copy_p); + SET_POINTER(data_buf_p, data_copy_p); + + /* insert into list, no need to append */ + entry_p->te_next_p = table_p->ta_buckets[bucket]; + table_p->ta_buckets[bucket] = entry_p; + + table_p->ta_entry_n++; + + /* do we need auto-adjust? */ + if ((table_p->ta_flags & TABLE_FLAG_AUTO_ADJUST) + && SHOULD_TABLE_GROW(table_p)) { + return table_adjust(table_p, table_p->ta_entry_n); + } + + return TABLE_ERROR_NONE; +} + +/* + * int table_insert + * + * DESCRIPTION: + * + * Exactly the same as table_insert_kd except it does not pass back a + * pointer to the key after they have been inserted into the table + * structure. This is still here for backwards compatibility. + * + * See table_insert_kd for more information. + * + * RETURNS: + * + * Success - TABLE_ERROR_NONE + * + * Failure - Table error code. + * + * ARGUMENTS: + * + * table_p - Table structure pointer into which we will be inserting a + * new key/data pair. + * + * key_buf - Buffer of bytes of the key that we are inserting. If you + * are storing an (int) as the key (for example) then key_buf should + * be a (int *). + * + * key_size - Size of the key_buf buffer. If set to < 0 then the + * library will do a strlen of key_buf and add 1 for the '\0'. If you + * are storing an (int) as the key (for example) then key_size should + * be sizeof(int). + * + * data_buf - Buffer of bytes of the data that we are inserting. If + * it is NULL then the library will allocate space for the data in the + * table without copying in any information. If data_buf is NULL and + * data_size is 0 then the library will associate a NULL data pointer + * with the key. If you are storing a (long) as the data (for + * example) then data_buf should be a (long *). + * + * data_size - Size of the data_buf buffer. If set to < 0 then the + * library will do a strlen of data_buf and add 1 for the '\0'. If + * you are storing an (long) as the key (for example) then key_size + * should be sizeof(long). + * + * data_buf_p - Pointer which, if not NULL, will be set to the address + * of the data storage that was allocated in the table. If you are + * storing an (long) as the data (for example) then data_buf_p should + * be (long **) i.e. the address of a (long *). + * + * overwrite - Flag which, if set to 1, will allow the overwriting of + * the data in the table with the new data if the key already exists + * in the table. + */ +int table_insert(table_t *table_p, + const void *key_buf, const int key_size, + const void *data_buf, const int data_size, + void **data_buf_p, const char overwrite_b) +{ + return table_insert_kd(table_p, key_buf, key_size, data_buf, data_size, + NULL, data_buf_p, overwrite_b); +} + +/* + * int table_retrieve + * + * DESCRIPTION: + * + * This routine looks up a key made up of a buffer of bytes and an + * associated size in the table. If found then it returns the + * associated data information. + * + * RETURNS: + * + * Success - TABLE_ERROR_NONE + * + * Failure - Table error code. + * + * ARGUMENTS: + * + * table_p - Table structure pointer into which we will be searching + * for the key. + * + * key_buf - Buffer of bytes of the key that we are searching for. If + * you are looking for an (int) as the key (for example) then key_buf + * should be a (int *). + * + * key_size - Size of the key_buf buffer. If set to < 0 then the + * library will do a strlen of key_buf and add 1 for the '\0'. If you + * are looking for an (int) as the key (for example) then key_size + * should be sizeof(int). + * + * data_buf_p - Pointer which, if not NULL, will be set to the address + * of the data storage that was allocated in the table and that is + * associated with the key. If a (long) was stored as the data (for + * example) then data_buf_p should be (long **) i.e. the address of a + * (long *). + * + * data_size_p - Pointer to an integer which, if not NULL, will be set + * to the size of the data stored in the table that is associated with + * the key. + */ +int table_retrieve(table_t *table_p, + const void *key_buf, const int key_size, + void **data_buf_p, int *data_size_p) +{ + int bucket; + unsigned int ksize; + table_entry_t *entry_p, **buckets; + + if (table_p == NULL) { + return TABLE_ERROR_ARG_NULL; + } + if (table_p->ta_magic != TABLE_MAGIC) { + return TABLE_ERROR_PNT; + } + if (key_buf == NULL) { + return TABLE_ERROR_ARG_NULL; + } + + /* find key size */ + if (key_size < 0) { + ksize = strlen((char *)key_buf) + sizeof(char); + } + else { + ksize = key_size; + } + + /* get the bucket number via a has function */ + bucket = hash(key_buf, ksize, 0) % table_p->ta_bucket_n; + + /* look for the entry in this bucket, only check keys of the same size */ + buckets = table_p->ta_buckets; + for (entry_p = buckets[bucket]; + entry_p != NULL; + entry_p = entry_p->te_next_p) { + entry_p = TABLE_POINTER(table_p, table_entry_t *, entry_p); + if (entry_p->te_key_size == ksize + && memcmp(ENTRY_KEY_BUF(entry_p), key_buf, ksize) == 0) { + break; + } + } + + /* not found? */ + if (entry_p == NULL) { + return TABLE_ERROR_NOT_FOUND; + } + + if (data_buf_p != NULL) { + if (entry_p->te_data_size == 0) { + *data_buf_p = NULL; + } + else { + if (table_p->ta_data_align == 0) { + *data_buf_p = ENTRY_DATA_BUF(table_p, entry_p); + } + else { + *data_buf_p = entry_data_buf(table_p, entry_p); + } + } + } + SET_POINTER(data_size_p, entry_p->te_data_size); + + return TABLE_ERROR_NONE; +} + +/* + * int table_delete + * + * DESCRIPTION: + * + * This routine looks up a key made up of a buffer of bytes and an + * associated size in the table. If found then it will be removed + * from the table. The associated data can be passed back to the user + * if requested. + * + * RETURNS: + * + * Success - TABLE_ERROR_NONE + * + * Failure - Table error code. + * + * NOTE: this could be an allocation error if the library is to return + * the data to the user. + * + * ARGUMENTS: + * + * table_p - Table structure pointer from which we will be deleteing + * the key. + * + * key_buf - Buffer of bytes of the key that we are searching for to + * delete. If you are deleting an (int) key (for example) then + * key_buf should be a (int *). + * + * key_size - Size of the key_buf buffer. If set to < 0 then the + * library will do a strlen of key_buf and add 1 for the '\0'. If you + * are deleting an (int) key (for example) then key_size should be + * sizeof(int). + * + * data_buf_p - Pointer which, if not NULL, will be set to the address + * of the data storage that was allocated in the table and that was + * associated with the key. If a (long) was stored as the data (for + * example) then data_buf_p should be (long **) i.e. the address of a + * (long *). If a pointer is passed in, the caller is responsible for + * freeing it after use. If data_buf_p is NULL then the library will + * free up the data allocation itself. + * + * data_size_p - Pointer to an integer which, if not NULL, will be set + * to the size of the data that was stored in the table and that was + * associated with the key. + */ +int table_delete(table_t *table_p, + const void *key_buf, const int key_size, + void **data_buf_p, int *data_size_p) +{ + int bucket; + unsigned int ksize; + unsigned char *data_copy_p; + table_entry_t *entry_p, *last_p; + + if (table_p == NULL) { + return TABLE_ERROR_ARG_NULL; + } + if (table_p->ta_magic != TABLE_MAGIC) { + return TABLE_ERROR_PNT; + } + if (key_buf == NULL) { + return TABLE_ERROR_ARG_NULL; + } + +#ifndef NO_MMAP + /* no mmap support so immediate error */ + if (table_p->ta_mmap != NULL) { + return TABLE_ERROR_MMAP_OP; + } +#endif + + /* get the key size */ + if (key_size < 0) { + ksize = strlen((char *)key_buf) + sizeof(char); + } + else { + ksize = key_size; + } + + /* find our bucket */ + bucket = hash(key_buf, ksize, 0) % table_p->ta_bucket_n; + + /* look for the entry in this bucket, only check keys of the same size */ + for (last_p = NULL, entry_p = table_p->ta_buckets[bucket]; + entry_p != NULL; + last_p = entry_p, entry_p = entry_p->te_next_p) { + if (entry_p->te_key_size == ksize + && memcmp(ENTRY_KEY_BUF(entry_p), key_buf, ksize) == 0) { + break; + } + } + + /* did we find it? */ + if (entry_p == NULL) { + return TABLE_ERROR_NOT_FOUND; + } + + /* + * NOTE: we may want to adjust the linear counters here if the entry + * we are deleting is the one we are pointing on or is ahead of the + * one in the bucket list + */ + + /* remove entry from the linked list */ + if (last_p == NULL) { + table_p->ta_buckets[bucket] = entry_p->te_next_p; + } + else { + last_p->te_next_p = entry_p->te_next_p; + } + + /* free entry */ + if (data_buf_p != NULL) { + if (entry_p->te_data_size == 0) { + *data_buf_p = NULL; + } + else { + /* + * if we were storing it compacted, we now need to malloc some + * space if the user wants the value after the delete. + */ + if (table_p->ta_alloc_func == NULL) { + *data_buf_p = malloc(entry_p->te_data_size); + } + else { + *data_buf_p = table_p->ta_alloc_func(table_p->ta_mem_pool, + entry_p->te_data_size); + } + if (*data_buf_p == NULL) { + return TABLE_ERROR_ALLOC; + } + if (table_p->ta_data_align == 0) { + data_copy_p = ENTRY_DATA_BUF(table_p, entry_p); + } + else { + data_copy_p = entry_data_buf(table_p, entry_p); + } + memcpy(*data_buf_p, data_copy_p, entry_p->te_data_size); + } + } + SET_POINTER(data_size_p, entry_p->te_data_size); + if (table_p->ta_free_func == NULL) { + free(entry_p); + } + else if (! table_p->ta_free_func(table_p->ta_mem_pool, entry_p, + entry_size(table_p, + entry_p->te_key_size, + entry_p->te_data_size))) { + return TABLE_ERROR_FREE; + } + + table_p->ta_entry_n--; + + /* do we need auto-adjust down? */ + if ((table_p->ta_flags & TABLE_FLAG_AUTO_ADJUST) + && (table_p->ta_flags & TABLE_FLAG_ADJUST_DOWN) + && SHOULD_TABLE_SHRINK(table_p)) { + return table_adjust(table_p, table_p->ta_entry_n); + } + + return TABLE_ERROR_NONE; +} + +/* + * int table_delete_first + * + * DESCRIPTION: + * + * This is like the table_delete routines except it deletes the first + * key/data pair in the table instead of an entry corresponding to a + * particular key. The associated key and data information can be + * passed back to the user if requested. This routines is handy to + * clear out a table. + * + * RETURNS: + * + * Success - TABLE_ERROR_NONE + * + * Failure - Table error code. + * + * NOTE: this could be an allocation error if the library is to return + * the data to the user. + * + * ARGUMENTS: + * + * table_p - Table structure pointer from which we will be deleteing + * the first key. + * + * key_buf_p - Pointer which, if not NULL, will be set to the address + * of the storage of the first key that was allocated in the table. + * If an (int) was stored as the first key (for example) then + * key_buf_p should be (int **) i.e. the address of a (int *). If a + * pointer is passed in, the caller is responsible for freeing it + * after use. If key_buf_p is NULL then the library will free up the + * key allocation itself. + * + * key_size_p - Pointer to an integer which, if not NULL, will be set + * to the size of the key that was stored in the table and that was + * associated with the key. + * + * data_buf_p - Pointer which, if not NULL, will be set to the address + * of the data storage that was allocated in the table and that was + * associated with the key. If a (long) was stored as the data (for + * example) then data_buf_p should be (long **) i.e. the address of a + * (long *). If a pointer is passed in, the caller is responsible for + * freeing it after use. If data_buf_p is NULL then the library will + * free up the data allocation itself. + * + * data_size_p - Pointer to an integer which, if not NULL, will be set + * to the size of the data that was stored in the table and that was + * associated with the key. + */ +int table_delete_first(table_t *table_p, + void **key_buf_p, int *key_size_p, + void **data_buf_p, int *data_size_p) +{ + unsigned char *data_copy_p; + table_entry_t *entry_p; + table_linear_t linear; + + if (table_p == NULL) { + return TABLE_ERROR_ARG_NULL; + } + if (table_p->ta_magic != TABLE_MAGIC) { + return TABLE_ERROR_PNT; + } + +#ifndef NO_MMAP + /* no mmap support so immediate error */ + if (table_p->ta_mmap != NULL) { + return TABLE_ERROR_MMAP_OP; + } +#endif + + /* take the first entry */ + entry_p = first_entry(table_p, &linear); + if (entry_p == NULL) { + return TABLE_ERROR_NOT_FOUND; + } + + /* + * NOTE: we may want to adjust the linear counters here if the entry + * we are deleting is the one we are pointing on or is ahead of the + * one in the bucket list + */ + + /* remove entry from the linked list */ + table_p->ta_buckets[linear.tl_bucket_c] = entry_p->te_next_p; + + /* free entry */ + if (key_buf_p != NULL) { + if (entry_p->te_key_size == 0) { + *key_buf_p = NULL; + } + else { + /* + * if we were storing it compacted, we now need to malloc some + * space if the user wants the value after the delete. + */ + if (table_p->ta_alloc_func == NULL) { + *key_buf_p = malloc(entry_p->te_key_size); + } + else { + *key_buf_p = table_p->ta_alloc_func(table_p->ta_mem_pool, + entry_p->te_key_size); + } + if (*key_buf_p == NULL) { + return TABLE_ERROR_ALLOC; + } + memcpy(*key_buf_p, ENTRY_KEY_BUF(entry_p), entry_p->te_key_size); + } + } + SET_POINTER(key_size_p, entry_p->te_key_size); + + if (data_buf_p != NULL) { + if (entry_p->te_data_size == 0) { + *data_buf_p = NULL; + } + else { + /* + * if we were storing it compacted, we now need to malloc some + * space if the user wants the value after the delete. + */ + if (table_p->ta_alloc_func == NULL) { + *data_buf_p = malloc(entry_p->te_data_size); + } + else { + *data_buf_p = table_p->ta_alloc_func(table_p->ta_mem_pool, + entry_p->te_data_size); + } + if (*data_buf_p == NULL) { + return TABLE_ERROR_ALLOC; + } + if (table_p->ta_data_align == 0) { + data_copy_p = ENTRY_DATA_BUF(table_p, entry_p); + } + else { + data_copy_p = entry_data_buf(table_p, entry_p); + } + memcpy(*data_buf_p, data_copy_p, entry_p->te_data_size); + } + } + SET_POINTER(data_size_p, entry_p->te_data_size); + if (table_p->ta_free_func == NULL) { + free(entry_p); + } + else if (! table_p->ta_free_func(table_p->ta_mem_pool, entry_p, + entry_size(table_p, + entry_p->te_key_size, + entry_p->te_data_size))) { + return TABLE_ERROR_FREE; + } + + table_p->ta_entry_n--; + + /* do we need auto-adjust down? */ + if ((table_p->ta_flags & TABLE_FLAG_AUTO_ADJUST) + && (table_p->ta_flags & TABLE_FLAG_ADJUST_DOWN) + && SHOULD_TABLE_SHRINK(table_p)) { + return table_adjust(table_p, table_p->ta_entry_n); + } + + return TABLE_ERROR_NONE; +} + +/* + * int table_info + * + * DESCRIPTION: + * + * Get some information about a table_p structure. + * + * RETURNS: + * + * Success - TABLE_ERROR_NONE + * + * Failure - Table error code. + * + * ARGUMENTS: + * + * table_p - Table structure pointer from which we are getting + * information. + * + * num_buckets_p - Pointer to an integer which, if not NULL, will + * contain the number of buckets in the table. + * + * num_entries_p - Pointer to an integer which, if not NULL, will + * contain the number of entries stored in the table. + */ +int table_info(table_t *table_p, int *num_buckets_p, int *num_entries_p) +{ + if (table_p == NULL) { + return TABLE_ERROR_ARG_NULL; + } + if (table_p->ta_magic != TABLE_MAGIC) { + return TABLE_ERROR_PNT; + } + + SET_POINTER(num_buckets_p, table_p->ta_bucket_n); + SET_POINTER(num_entries_p, table_p->ta_entry_n); + + return TABLE_ERROR_NONE; +} + +/* + * int table_adjust + * + * DESCRIPTION: + * + * Set the number of buckets in a table to a certain value. + * + * RETURNS: + * + * Success - TABLE_ERROR_NONE + * + * Failure - Table error code. + * + * ARGUMENTS: + * + * table_p - Table structure pointer of which we are adjusting. + * + * bucket_n - Number buckets to adjust the table to. Set to 0 to + * adjust the table to its number of entries. + */ +int table_adjust(table_t *table_p, const int bucket_n) +{ + table_entry_t *entry_p, *next_p; + table_entry_t **buckets, **bucket_p, **bounds_p; + int bucket; + unsigned int buck_n, bucket_size; + + if (table_p == NULL) { + return TABLE_ERROR_ARG_NULL; + } + if (table_p->ta_magic != TABLE_MAGIC) { + return TABLE_ERROR_PNT; + } + +#ifndef NO_MMAP + /* no mmap support so immediate error */ + if (table_p->ta_mmap != NULL) { + return TABLE_ERROR_MMAP_OP; + } +#endif + + /* + * NOTE: we walk through the entries and rehash them. If we stored + * the hash value as a full int in the table-entry, all we would + * have to do is remod it. + */ + + /* normalize to the number of entries */ + if (bucket_n == 0) { + buck_n = table_p->ta_entry_n; + } + else { + buck_n = bucket_n; + } + + /* we must have at least 1 bucket */ + if (buck_n == 0) { + buck_n = 1; + } + + (void)printf("growing table to %d\n", buck_n); + + /* make sure we have something to do */ + if (buck_n == table_p->ta_bucket_n) { + return TABLE_ERROR_NONE; + } + + /* allocate a new bucket list */ + bucket_size = buck_n * sizeof(table_entry_t *); + if (table_p->ta_alloc_func == NULL) { + buckets = (table_entry_t **)malloc(bucket_size); + } + else { + buckets = + (table_entry_t **)table_p->ta_alloc_func(table_p->ta_mem_pool, + bucket_size); + } + if (buckets == NULL) { + return TABLE_ERROR_ALLOC; + } + /* + * We zero it ourselves to save the necessity of having a + * table_mem_calloc_t memory override function. + */ + memset(buckets, 0, bucket_size); + + /* + * run through each of the items in the current table and rehash + * them into the newest bucket sizes + */ + bounds_p = table_p->ta_buckets + table_p->ta_bucket_n; + for (bucket_p = table_p->ta_buckets; bucket_p < bounds_p; bucket_p++) { + for (entry_p = *bucket_p; entry_p != NULL; entry_p = next_p) { + + /* hash the old data into the new table size */ + bucket = hash(ENTRY_KEY_BUF(entry_p), entry_p->te_key_size, 0) % buck_n; + + /* record the next one now since we overwrite next below */ + next_p = entry_p->te_next_p; + + /* insert into new list, no need to append */ + entry_p->te_next_p = buckets[bucket]; + buckets[bucket] = entry_p; + + /* + * NOTE: we may want to adjust the bucket_c linear entry here to + * keep it current + */ + } + /* remove the old table pointers as we go by */ + *bucket_p = NULL; + } + + /* replace the table buckets with the new ones */ + if (table_p->ta_free_func == NULL) { + free(table_p->ta_buckets); + } + else if (! table_p->ta_free_func(table_p->ta_mem_pool, + table_p->ta_buckets, + table_p->ta_bucket_n * + sizeof(table_entry_t *))) { + return TABLE_ERROR_FREE; + } + table_p->ta_buckets = buckets; + table_p->ta_bucket_n = buck_n; + + return TABLE_ERROR_NONE; +} + +/* + * int table_type_size + * + * DESCRIPTION: + * + * Return the size of the internal table type. + * + * RETURNS: + * + * The size of the table_t type. + * + * ARGUMENTS: + * + * None. + */ +int table_type_size(void) +{ + return sizeof(table_t); +} + +/************************* linear access routines ****************************/ + +/* + * int table_first + * + * DESCRIPTION: + * + * Find first element in a table and pass back information about the + * key/data pair. If any of the key/data pointers are NULL then they + * are ignored. + * + * NOTE: This function is not reentrant. More than one thread cannot + * be doing a first and next on the same table at the same time. Use + * the table_first_r version below for this. + * + * RETURNS: + * + * Success - TABLE_ERROR_NONE + * + * Failure - Table error code. + * + * ARGUMENTS: + * + * table_p - Table structure pointer from which we are getting the + * first element. + * + * key_buf_p - Pointer which, if not NULL, will be set to the address + * of the storage of the first key that is allocated in the table. If + * an (int) is stored as the first key (for example) then key_buf_p + * should be (int **) i.e. the address of a (int *). + * + * key_size_p - Pointer to an integer which, if not NULL, will be set + * to the size of the key that is stored in the table and that is + * associated with the first key. + * + * data_buf_p - Pointer which, if not NULL, will be set to the address + * of the data storage that is allocated in the table and that is + * associated with the first key. If a (long) is stored as the data + * (for example) then data_buf_p should be (long **) i.e. the address + * of a (long *). + * + * data_size_p - Pointer to an integer which, if not NULL, will be set + * to the size of the data that is stored in the table and that is + * associated with the first key. + */ +int table_first(table_t *table_p, + void **key_buf_p, int *key_size_p, + void **data_buf_p, int *data_size_p) +{ + table_entry_t *entry_p; + + if (table_p == NULL) { + return TABLE_ERROR_ARG_NULL; + } + if (table_p->ta_magic != TABLE_MAGIC) { + return TABLE_ERROR_PNT; + } + + /* initialize our linear magic number */ + table_p->ta_linear.tl_magic = LINEAR_MAGIC; + + entry_p = first_entry(table_p, &table_p->ta_linear); + if (entry_p == NULL) { + return TABLE_ERROR_NOT_FOUND; + } + + SET_POINTER(key_buf_p, ENTRY_KEY_BUF(entry_p)); + SET_POINTER(key_size_p, entry_p->te_key_size); + if (data_buf_p != NULL) { + if (entry_p->te_data_size == 0) { + *data_buf_p = NULL; + } + else { + if (table_p->ta_data_align == 0) { + *data_buf_p = ENTRY_DATA_BUF(table_p, entry_p); + } + else { + *data_buf_p = entry_data_buf(table_p, entry_p); + } + } + } + SET_POINTER(data_size_p, entry_p->te_data_size); + + return TABLE_ERROR_NONE; +} + +/* + * int table_next + * + * DESCRIPTION: + * + * Find the next element in a table and pass back information about + * the key/data pair. If any of the key/data pointers are NULL then + * they are ignored. + * + * NOTE: This function is not reentrant. More than one thread cannot + * be doing a first and next on the same table at the same time. Use + * the table_next_r version below for this. + * + * RETURNS: + * + * Success - TABLE_ERROR_NONE + * + * Failure - Table error code. + * + * ARGUMENTS: + * + * table_p - Table structure pointer from which we are getting the + * next element. + * + * key_buf_p - Pointer which, if not NULL, will be set to the address + * of the storage of the next key that is allocated in the table. If + * an (int) is stored as the next key (for example) then key_buf_p + * should be (int **) i.e. the address of a (int *). + * + * key_size_p - Pointer to an integer which, if not NULL, will be set + * to the size of the key that is stored in the table and that is + * associated with the next key. + * + * data_buf_p - Pointer which, if not NULL, will be set to the address + * of the data storage that is allocated in the table and that is + * associated with the next key. If a (long) is stored as the data + * (for example) then data_buf_p should be (long **) i.e. the address + * of a (long *). + * + * data_size_p - Pointer to an integer which, if not NULL, will be set + * to the size of the data that is stored in the table and that is + * associated with the next key. + */ +int table_next(table_t *table_p, + void **key_buf_p, int *key_size_p, + void **data_buf_p, int *data_size_p) +{ + table_entry_t *entry_p; + int error; + + if (table_p == NULL) { + return TABLE_ERROR_ARG_NULL; + } + if (table_p->ta_magic != TABLE_MAGIC) { + return TABLE_ERROR_PNT; + } + if (table_p->ta_linear.tl_magic != LINEAR_MAGIC) { + return TABLE_ERROR_LINEAR; + } + + /* move to the next entry */ + entry_p = next_entry(table_p, &table_p->ta_linear, &error); + if (entry_p == NULL) { + return error; + } + + SET_POINTER(key_buf_p, ENTRY_KEY_BUF(entry_p)); + SET_POINTER(key_size_p, entry_p->te_key_size); + if (data_buf_p != NULL) { + if (entry_p->te_data_size == 0) { + *data_buf_p = NULL; + } + else { + if (table_p->ta_data_align == 0) { + *data_buf_p = ENTRY_DATA_BUF(table_p, entry_p); + } + else { + *data_buf_p = entry_data_buf(table_p, entry_p); + } + } + } + SET_POINTER(data_size_p, entry_p->te_data_size); + + return TABLE_ERROR_NONE; +} + +/* + * int table_this + * + * DESCRIPTION: + * + * Find the current element in a table and pass back information about + * the key/data pair. If any of the key/data pointers are NULL then + * they are ignored. + * + * NOTE: This function is not reentrant. Use the table_current_r + * version below. + * + * RETURNS: + * + * Success - TABLE_ERROR_NONE + * + * Failure - Table error code. + * + * ARGUMENTS: + * + * table_p - Table structure pointer from which we are getting the + * current element. + * + * key_buf_p - Pointer which, if not NULL, will be set to the address + * of the storage of the current key that is allocated in the table. + * If an (int) is stored as the current key (for example) then + * key_buf_p should be (int **) i.e. the address of a (int *). + * + * key_size_p - Pointer to an integer which, if not NULL, will be set + * to the size of the key that is stored in the table and that is + * associated with the current key. + * + * data_buf_p - Pointer which, if not NULL, will be set to the address + * of the data storage that is allocated in the table and that is + * associated with the current key. If a (long) is stored as the data + * (for example) then data_buf_p should be (long **) i.e. the address + * of a (long *). + * + * data_size_p - Pointer to an integer which, if not NULL, will be set + * to the size of the data that is stored in the table and that is + * associated with the current key. + */ +int table_this(table_t *table_p, + void **key_buf_p, int *key_size_p, + void **data_buf_p, int *data_size_p) +{ + table_entry_t *entry_p = NULL; + int entry_c; + + if (table_p == NULL) { + return TABLE_ERROR_ARG_NULL; + } + if (table_p->ta_magic != TABLE_MAGIC) { + return TABLE_ERROR_PNT; + } + if (table_p->ta_linear.tl_magic != LINEAR_MAGIC) { + return TABLE_ERROR_LINEAR; + } + + /* if we removed an item that shorted the bucket list, we may get this */ + if (table_p->ta_linear.tl_bucket_c >= table_p->ta_bucket_n) { + /* + * NOTE: this might happen if we delete an item which shortens the + * table bucket numbers. + */ + return TABLE_ERROR_NOT_FOUND; + } + + /* find the entry which is the nth in the list */ + entry_p = table_p->ta_buckets[table_p->ta_linear.tl_bucket_c]; + /* NOTE: we swap the order here to be more efficient */ + for (entry_c = table_p->ta_linear.tl_entry_c; entry_c > 0; entry_c--) { + /* did we reach the end of the list? */ + if (entry_p == NULL) { + break; + } + entry_p = TABLE_POINTER(table_p, table_entry_t *, entry_p)->te_next_p; + } + + /* is this a NOT_FOUND or a LINEAR error */ + if (entry_p == NULL) { + return TABLE_ERROR_NOT_FOUND; + } + + SET_POINTER(key_buf_p, ENTRY_KEY_BUF(entry_p)); + SET_POINTER(key_size_p, entry_p->te_key_size); + if (data_buf_p != NULL) { + if (entry_p->te_data_size == 0) { + *data_buf_p = NULL; + } + else { + if (table_p->ta_data_align == 0) { + *data_buf_p = ENTRY_DATA_BUF(table_p, entry_p); + } + else { + *data_buf_p = entry_data_buf(table_p, entry_p); + } + } + } + SET_POINTER(data_size_p, entry_p->te_data_size); + + return TABLE_ERROR_NONE; +} + +/* + * int table_first_r + * + * DESCRIPTION: + * + * Reetrant version of the table_first routine above. Find first + * element in a table and pass back information about the key/data + * pair. If any of the key/data pointers are NULL then they are + * ignored. + * + * RETURNS: + * + * Success - TABLE_ERROR_NONE + * + * Failure - Table error code. + * + * ARGUMENTS: + * + * table_p - Table structure pointer from which we are getting the + * first element. + * + * linear_p - Pointer to a table linear structure which is initialized + * here. The same pointer should then be passed to table_next_r + * below. + * + * key_buf_p - Pointer which, if not NULL, will be set to the address + * of the storage of the first key that is allocated in the table. If + * an (int) is stored as the first key (for example) then key_buf_p + * should be (int **) i.e. the address of a (int *). + * + * key_size_p - Pointer to an integer which, if not NULL, will be set + * to the size of the key that is stored in the table and that is + * associated with the first key. + * + * data_buf_p - Pointer which, if not NULL, will be set to the address + * of the data storage that is allocated in the table and that is + * associated with the first key. If a (long) is stored as the data + * (for example) then data_buf_p should be (long **) i.e. the address + * of a (long *). + * + * data_size_p - Pointer to an integer which, if not NULL, will be set + * to the size of the data that is stored in the table and that is + * associated with the first key. + */ +int table_first_r(table_t *table_p, table_linear_t *linear_p, + void **key_buf_p, int *key_size_p, + void **data_buf_p, int *data_size_p) +{ + table_entry_t *entry_p; + + if (table_p == NULL) { + return TABLE_ERROR_ARG_NULL; + } + if (table_p->ta_magic != TABLE_MAGIC) { + return TABLE_ERROR_PNT; + } + if (linear_p == NULL) { + return TABLE_ERROR_ARG_NULL; + } + + /* initialize our linear magic number */ + linear_p->tl_magic = LINEAR_MAGIC; + + entry_p = first_entry(table_p, linear_p); + if (entry_p == NULL) { + return TABLE_ERROR_NOT_FOUND; + } + + SET_POINTER(key_buf_p, ENTRY_KEY_BUF(entry_p)); + SET_POINTER(key_size_p, entry_p->te_key_size); + if (data_buf_p != NULL) { + if (entry_p->te_data_size == 0) { + *data_buf_p = NULL; + } + else { + if (table_p->ta_data_align == 0) { + *data_buf_p = ENTRY_DATA_BUF(table_p, entry_p); + } + else { + *data_buf_p = entry_data_buf(table_p, entry_p); + } + } + } + SET_POINTER(data_size_p, entry_p->te_data_size); + + return TABLE_ERROR_NONE; +} + +/* + * int table_next_r + * + * DESCRIPTION: + * + * Reetrant version of the table_next routine above. Find next + * element in a table and pass back information about the key/data + * pair. If any of the key/data pointers are NULL then they are + * ignored. + * + * RETURNS: + * + * Success - TABLE_ERROR_NONE + * + * Failure - Table error code. + * + * ARGUMENTS: + * + * table_p - Table structure pointer from which we are getting the + * next element. + * + * linear_p - Pointer to a table linear structure which is incremented + * here. The same pointer must have been passed to table_first_r + * first so that it can be initialized. + * + * key_buf_p - Pointer which, if not NULL, will be set to the address + * of the storage of the next key that is allocated in the table. If + * an (int) is stored as the next key (for example) then key_buf_p + * should be (int **) i.e. the address of a (int *). + * + * key_size_p - Pointer to an integer which, if not NULL will be set + * to the size of the key that is stored in the table and that is + * associated with the next key. + * + * data_buf_p - Pointer which, if not NULL, will be set to the address + * of the data storage that is allocated in the table and that is + * associated with the next key. If a (long) is stored as the data + * (for example) then data_buf_p should be (long **) i.e. the address + * of a (long *). + * + * data_size_p - Pointer to an integer which, if not NULL, will be set + * to the size of the data that is stored in the table and that is + * associated with the next key. + */ +int table_next_r(table_t *table_p, table_linear_t *linear_p, + void **key_buf_p, int *key_size_p, + void **data_buf_p, int *data_size_p) +{ + table_entry_t *entry_p; + int error; + + if (table_p == NULL) { + return TABLE_ERROR_ARG_NULL; + } + if (table_p->ta_magic != TABLE_MAGIC) { + return TABLE_ERROR_PNT; + } + if (linear_p == NULL) { + return TABLE_ERROR_ARG_NULL; + } + if (linear_p->tl_magic != LINEAR_MAGIC) { + return TABLE_ERROR_LINEAR; + } + + /* move to the next entry */ + entry_p = next_entry(table_p, linear_p, &error); + if (entry_p == NULL) { + return error; + } + + SET_POINTER(key_buf_p, ENTRY_KEY_BUF(entry_p)); + SET_POINTER(key_size_p, entry_p->te_key_size); + if (data_buf_p != NULL) { + if (entry_p->te_data_size == 0) { + *data_buf_p = NULL; + } + else { + if (table_p->ta_data_align == 0) { + *data_buf_p = ENTRY_DATA_BUF(table_p, entry_p); + } + else { + *data_buf_p = entry_data_buf(table_p, entry_p); + } + } + } + SET_POINTER(data_size_p, entry_p->te_data_size); + + return TABLE_ERROR_NONE; +} + +/* + * int table_this_r + * + * DESCRIPTION: + * + * Reetrant version of the table_this routine above. Find current + * element in a table and pass back information about the key/data + * pair. If any of the key/data pointers are NULL then they are + * ignored. + * + * RETURNS: + * + * Success - TABLE_ERROR_NONE + * + * Failure - Table error code. + * + * ARGUMENTS: + * + * table_p - Table structure pointer from which we are getting the + * current element. + * + * linear_p - Pointer to a table linear structure which is accessed + * here. The same pointer must have been passed to table_first_r + * first so that it can be initialized. + * + * key_buf_p - Pointer which, if not NULL, will be set to the address + * of the storage of the current key that is allocated in the table. + * If an (int) is stored as the current key (for example) then + * key_buf_p should be (int **) i.e. the address of a (int *). + * + * key_size_p - Pointer to an integer which, if not NULL, will be set + * to the size of the key that is stored in the table and that is + * associated with the current key. + * + * data_buf_p - Pointer which, if not NULL, will be set to the address + * of the data storage that is allocated in the table and that is + * associated with the current key. If a (long) is stored as the data + * (for example) then data_buf_p should be (long **) i.e. the address + * of a (long *). + * + * data_size_p - Pointer to an integer which, if not NULL, will be set + * to the size of the data that is stored in the table and that is + * associated with the current key. + */ +int table_this_r(table_t *table_p, table_linear_t *linear_p, + void **key_buf_p, int *key_size_p, + void **data_buf_p, int *data_size_p) +{ + table_entry_t *entry_p; + int entry_c; + + if (table_p == NULL) { + return TABLE_ERROR_ARG_NULL; + } + if (table_p->ta_magic != TABLE_MAGIC) { + return TABLE_ERROR_PNT; + } + if (linear_p->tl_magic != LINEAR_MAGIC) { + return TABLE_ERROR_LINEAR; + } + + /* if we removed an item that shorted the bucket list, we may get this */ + if (linear_p->tl_bucket_c >= table_p->ta_bucket_n) { + /* + * NOTE: this might happen if we delete an item which shortens the + * table bucket numbers. + */ + return TABLE_ERROR_NOT_FOUND; + } + + /* find the entry which is the nth in the list */ + for (entry_c = linear_p->tl_entry_c, + entry_p = table_p->ta_buckets[linear_p->tl_bucket_c]; + entry_p != NULL && entry_c > 0; + entry_c--, entry_p = TABLE_POINTER(table_p, table_entry_t *, + entry_p)->te_next_p) { + } + + if (entry_p == NULL) { + return TABLE_ERROR_NOT_FOUND; + } + + SET_POINTER(key_buf_p, ENTRY_KEY_BUF(entry_p)); + SET_POINTER(key_size_p, entry_p->te_key_size); + if (data_buf_p != NULL) { + if (entry_p->te_data_size == 0) { + *data_buf_p = NULL; + } + else { + if (table_p->ta_data_align == 0) { + *data_buf_p = ENTRY_DATA_BUF(table_p, entry_p); + } + else { + *data_buf_p = entry_data_buf(table_p, entry_p); + } + } + } + SET_POINTER(data_size_p, entry_p->te_data_size); + + return TABLE_ERROR_NONE; +} + +/******************************* mmap routines *******************************/ + +/* + * table_t *table_mmap + * + * DESCRIPTION: + * + * Mmap a table from a file that had been written to disk earlier via + * table_write. + * + * RETURNS: + * + * A pointer to the new table structure which must be passed to + * table_munmap to be deallocated. On error a NULL is returned. + * + * ARGUMENTS: + * + * path - Table file to mmap in. + * + * error_p - Pointer to an integer which, if not NULL, will contain a + * table error code. + */ +table_t *table_mmap(const char *path, int *error_p) +{ +#ifdef NO_MMAP + + /* no mmap support so immediate error */ + SET_POINTER(error_p, TABLE_ERROR_MMAP_NONE); + return NULL; + +#else + + table_t *table_p; + struct stat sbuf; + int fd, state; + + table_p = (table_t *)malloc(sizeof(table_t)); + if (table_p == NULL) { + SET_POINTER(error_p, TABLE_ERROR_ALLOC); + return NULL; + } + + /* open the mmap file */ + fd = open(path, O_RDONLY, 0); + if (fd < 0) { + free(table_p); + SET_POINTER(error_p, TABLE_ERROR_OPEN); + return NULL; + } + + /* get the file size */ + if (fstat(fd, &sbuf) != 0) { + free(table_p); + SET_POINTER(error_p, TABLE_ERROR_OPEN); + return NULL; + } + + /* mmap the space and close the file */ +#ifdef __alpha + state = (MAP_SHARED | MAP_FILE | MAP_VARIABLE); +#else + state = MAP_SHARED; +#endif + + table_p->ta_mmap = (table_t *)mmap((caddr_t)0, sbuf.st_size, PROT_READ, + state, fd, 0); + (void)close(fd); + + if (table_p->ta_mmap == (table_t *)MAP_FAILED) { + SET_POINTER(error_p, TABLE_ERROR_MMAP); + return NULL; + } + + /* is the mmap file contain bad info or maybe another system type? */ + if (table_p->ta_mmap->ta_magic != TABLE_MAGIC) { + SET_POINTER(error_p, TABLE_ERROR_PNT); + return NULL; + } + + /* sanity check on the file size */ + if (table_p->ta_mmap->ta_file_size != sbuf.st_size) { + SET_POINTER(error_p, TABLE_ERROR_SIZE); + return NULL; + } + + /* copy the fields out of the mmap file into our memory version */ + table_p->ta_magic = TABLE_MAGIC; + table_p->ta_flags = table_p->ta_mmap->ta_flags; + table_p->ta_bucket_n = table_p->ta_mmap->ta_bucket_n; + table_p->ta_entry_n = table_p->ta_mmap->ta_entry_n; + table_p->ta_data_align = table_p->ta_mmap->ta_data_align; + table_p->ta_buckets = TABLE_POINTER(table_p, table_entry_t **, + table_p->ta_mmap->ta_buckets); + table_p->ta_linear.tl_magic = 0; + table_p->ta_linear.tl_bucket_c = 0; + table_p->ta_linear.tl_entry_c = 0; + /* mmap is already set */ + table_p->ta_file_size = table_p->ta_mmap->ta_file_size; + + SET_POINTER(error_p, TABLE_ERROR_NONE); + return table_p; + +#endif +} + +/* + * int table_munmap + * + * DESCRIPTION: + * + * Unmmap a table that was previously mmapped using table_mmap. + * + * RETURNS: + * + * Returns table error codes. + * + * ARGUMENTS: + * + * table_p - Mmaped table pointer to unmap. + */ +int table_munmap(table_t *table_p) +{ +#ifdef NO_MMAP + + /* no mmap support so immediate error */ + return TABLE_ERROR_MMAP_NONE; + +#else + + if (table_p == NULL) { + return TABLE_ERROR_ARG_NULL; + } + if (table_p->ta_magic != TABLE_MAGIC) { + return TABLE_ERROR_PNT; + } + if (table_p->ta_mmap == NULL) { + return TABLE_ERROR_PNT; + } + + (void)munmap((caddr_t)table_p->ta_mmap, table_p->ta_file_size); + table_p->ta_magic = 0; + free(table_p); + return TABLE_ERROR_NONE; + +#endif +} + +/******************************* file routines *******************************/ + +/* + * int table_read + * + * DESCRIPTION: + * + * Read in a table from a file that had been written to disk earlier + * via table_write. + * + * RETURNS: + * + * Success - Pointer to the new table structure which must be passed + * to table_free to be deallocated. + * + * Failure - NULL + * + * ARGUMENTS: + * + * path - Table file to read in. + * + * error_p - Pointer to an integer which, if not NULL, will contain a + * table error code. + */ +table_t *table_read(const char *path, int *error_p) +{ + unsigned int size; + int fd, ent_size; + FILE *infile; + table_entry_t entry, **bucket_p, *entry_p = NULL, *last_p; + unsigned long pos; + table_t *table_p; + + /* open the file */ + fd = open(path, O_RDONLY, 0); + if (fd < 0) { + SET_POINTER(error_p, TABLE_ERROR_OPEN); + return NULL; + } + + /* allocate a table structure */ + table_p = malloc(sizeof(table_t)); + if (table_p == NULL) { + SET_POINTER(error_p, TABLE_ERROR_ALLOC); + return NULL; + } + + /* now open the fd to get buffered i/o */ + infile = fdopen(fd, "r"); + if (infile == NULL) { + SET_POINTER(error_p, TABLE_ERROR_OPEN); + return NULL; + } + + /* read the main table struct */ + if (fread(table_p, sizeof(table_t), 1, infile) != 1) { + SET_POINTER(error_p, TABLE_ERROR_READ); + free(table_p); + return NULL; + } + table_p->ta_file_size = 0; + + /* is the mmap file contain bad info or maybe another system type? */ + if (table_p->ta_magic != TABLE_MAGIC) { + SET_POINTER(error_p, TABLE_ERROR_PNT); + return NULL; + } + + /* allocate the buckets */ + table_p->ta_buckets = (table_entry_t **)calloc(table_p->ta_bucket_n, + sizeof(table_entry_t *)); + if (table_p->ta_buckets == NULL) { + SET_POINTER(error_p, TABLE_ERROR_ALLOC); + free(table_p); + return NULL; + } + + if (fread(table_p->ta_buckets, sizeof(table_entry_t *), table_p->ta_bucket_n, + infile) != (size_t)table_p->ta_bucket_n) { + SET_POINTER(error_p, TABLE_ERROR_READ); + free(table_p->ta_buckets); + free(table_p); + return NULL; + } + + /* read in the entries */ + for (bucket_p = table_p->ta_buckets; + bucket_p < table_p->ta_buckets + table_p->ta_bucket_n; + bucket_p++) { + + /* skip null buckets */ + if (*bucket_p == NULL) { + continue; + } + + /* run through the entry list */ + last_p = NULL; + for (pos = *(unsigned long *)bucket_p;; + pos = (unsigned long)entry_p->te_next_p) { + + /* read in the entry */ + if (fseek(infile, pos, SEEK_SET) != 0) { + SET_POINTER(error_p, TABLE_ERROR_SEEK); + free(table_p->ta_buckets); + free(table_p); + if (entry_p != NULL) { + free(entry_p); + } + /* the other table elements will not be freed */ + return NULL; + } + if (fread(&entry, sizeof(struct table_shell_st), 1, infile) != 1) { + SET_POINTER(error_p, TABLE_ERROR_READ); + free(table_p->ta_buckets); + free(table_p); + if (entry_p != NULL) { + free(entry_p); + } + /* the other table elements will not be freed */ + return NULL; + } + + /* make a new entry */ + ent_size = entry_size(table_p, entry.te_key_size, entry.te_data_size); + entry_p = (table_entry_t *)malloc(ent_size); + if (entry_p == NULL) { + SET_POINTER(error_p, TABLE_ERROR_ALLOC); + free(table_p->ta_buckets); + free(table_p); + /* the other table elements will not be freed */ + return NULL; + } + entry_p->te_key_size = entry.te_key_size; + entry_p->te_data_size = entry.te_data_size; + entry_p->te_next_p = entry.te_next_p; + + if (last_p == NULL) { + *bucket_p = entry_p; + } + else { + last_p->te_next_p = entry_p; + } + + /* determine how much more we have to read */ + size = ent_size - sizeof(struct table_shell_st); + if (fread(ENTRY_KEY_BUF(entry_p), sizeof(char), size, infile) != size) { + SET_POINTER(error_p, TABLE_ERROR_READ); + free(table_p->ta_buckets); + free(table_p); + free(entry_p); + /* the other table elements will not be freed */ + return NULL; + } + + /* we are done if the next pointer is null */ + if (entry_p->te_next_p == (unsigned long)0) { + break; + } + last_p = entry_p; + } + } + + (void)fclose(infile); + + SET_POINTER(error_p, TABLE_ERROR_NONE); + return table_p; +} + +/* + * int table_write + * + * DESCRIPTION: + * + * Write a table from memory to file. + * + * RETURNS: + * + * Success - TABLE_ERROR_NONE + * + * Failure - Table error code. + * + * ARGUMENTS: + * + * table_p - Pointer to the table that we are writing to the file. + * + * path - Table file to write out to. + * + * mode - Mode of the file. This argument is passed on to open when + * the file is created. + */ +int table_write(const table_t *table_p, const char *path, const int mode) +{ + int fd, rem, ent_size; + unsigned int bucket_c, bucket_size; + unsigned long size; + table_entry_t *entry_p, **buckets, **bucket_p, *next_p; + table_t main_tab; + FILE *outfile; + + if (table_p == NULL) { + return TABLE_ERROR_ARG_NULL; + } + if (table_p->ta_magic != TABLE_MAGIC) { + return TABLE_ERROR_PNT; + } + + fd = open(path, O_WRONLY | O_CREAT, mode); + if (fd < 0) { + return TABLE_ERROR_OPEN; + } + + outfile = fdopen(fd, "w"); + if (outfile == NULL) { + return TABLE_ERROR_OPEN; + } + + /* allocate a block of sizes for each bucket */ + bucket_size = sizeof(table_entry_t *) * table_p->ta_bucket_n; + if (table_p->ta_alloc_func == NULL) { + buckets = (table_entry_t **)malloc(bucket_size); + } + else { + buckets = + (table_entry_t **)table_p->ta_alloc_func(table_p->ta_mem_pool, + bucket_size); + } + if (buckets == NULL) { + return TABLE_ERROR_ALLOC; + } + + /* make a copy of the main struct */ + main_tab = *table_p; + + /* start counting the bytes */ + size = 0; + size += sizeof(table_t); + + /* buckets go right after main struct */ + main_tab.ta_buckets = (table_entry_t **)size; + size += sizeof(table_entry_t *) * table_p->ta_bucket_n; + + /* run through and count the buckets */ + for (bucket_c = 0; bucket_c < table_p->ta_bucket_n; bucket_c++) { + bucket_p = table_p->ta_buckets + bucket_c; + if (*bucket_p == NULL) { + buckets[bucket_c] = NULL; + continue; + } + buckets[bucket_c] = (table_entry_t *)size; + for (entry_p = *bucket_p; entry_p != NULL; entry_p = entry_p->te_next_p) { + size += entry_size(table_p, entry_p->te_key_size, entry_p->te_data_size); + /* + * We now have to round the file to the nearest long so the + * mmaping of the longs in the entry structs will work. + */ + rem = size & (sizeof(long) - 1); + if (rem > 0) { + size += sizeof(long) - rem; + } + } + } + /* add a \0 at the end to fill the last section */ + size++; + + /* set the main fields */ + main_tab.ta_linear.tl_magic = 0; + main_tab.ta_linear.tl_bucket_c = 0; + main_tab.ta_linear.tl_entry_c = 0; + main_tab.ta_mmap = NULL; + main_tab.ta_file_size = size; + + /* + * Now we can start the writing because we got the bucket offsets. + */ + + /* write the main table struct */ + size = 0; + if (fwrite(&main_tab, sizeof(table_t), 1, outfile) != 1) { + if (table_p->ta_free_func == NULL) { + free(buckets); + } + else { + (void)table_p->ta_free_func(table_p->ta_mem_pool, buckets, bucket_size); + } + return TABLE_ERROR_WRITE; + } + size += sizeof(table_t); + if (fwrite(buckets, sizeof(table_entry_t *), table_p->ta_bucket_n, + outfile) != (size_t)table_p->ta_bucket_n) { + if (table_p->ta_free_func == NULL) { + free(buckets); + } + else { + (void)table_p->ta_free_func(table_p->ta_mem_pool, buckets, bucket_size); + } + return TABLE_ERROR_WRITE; + } + size += sizeof(table_entry_t *) * table_p->ta_bucket_n; + + /* write out the entries */ + for (bucket_p = table_p->ta_buckets; + bucket_p < table_p->ta_buckets + table_p->ta_bucket_n; + bucket_p++) { + for (entry_p = *bucket_p; entry_p != NULL; entry_p = entry_p->te_next_p) { + + ent_size = entry_size(table_p, entry_p->te_key_size, + entry_p->te_data_size); + size += ent_size; + /* round to nearest long here so we can write copy */ + rem = size & (sizeof(long) - 1); + if (rem > 0) { + size += sizeof(long) - rem; + } + next_p = entry_p->te_next_p; + if (next_p != NULL) { + entry_p->te_next_p = (table_entry_t *)size; + } + + /* now write to disk */ + if (fwrite(entry_p, ent_size, 1, outfile) != 1) { + if (table_p->ta_free_func == NULL) { + free(buckets); + } + else { + (void)table_p->ta_free_func(table_p->ta_mem_pool, buckets, + bucket_size); + } + return TABLE_ERROR_WRITE; + } + + /* restore the next pointer */ + if (next_p != NULL) { + entry_p->te_next_p = next_p; + } + + /* now write the padding information */ + if (rem > 0) { + rem = sizeof(long) - rem; + /* + * NOTE: this won't leave fseek'd space at the end but we + * don't care there because there is no accessed memory + * afterwards. We write 1 \0 at the end to make sure. + */ + if (fseek(outfile, rem, SEEK_CUR) != 0) { + if (table_p->ta_free_func == NULL) { + free(buckets); + } + else { + (void)table_p->ta_free_func(table_p->ta_mem_pool, buckets, + bucket_size); + } + return TABLE_ERROR_SEEK; + } + } + } + } + /* + * Write a \0 at the end of the file to make sure that the last + * fseek filled with nulls. + */ + (void)fputc('\0', outfile); + + (void)fclose(outfile); + if (table_p->ta_free_func == NULL) { + free(buckets); + } + else if (! table_p->ta_free_func(table_p->ta_mem_pool, buckets, + bucket_size)) { + return TABLE_ERROR_FREE; + } + + return TABLE_ERROR_NONE; +} + +/******************************** table order ********************************/ + +/* + * table_entry_t *table_order + * + * DESCRIPTION: + * + * Order a table by building an array of table entry pointers and then + * sorting this array using the qsort function. To retrieve the + * sorted entries, you can then use the table_entry routine to access + * each entry in order. + * + * NOTE: This routine is thread safe and makes use of an internal + * status qsort function. + * + * RETURNS: + * + * Success - An allocated list of table-linear structures which must + * be freed by table_order_free later. + * + * Failure - NULL + * + * ARGUMENTS: + * + * table_p - Pointer to the table that we are ordering. + * + * compare - Comparison function defined by the user. Its definition + * is at the top of the table.h file. If this is NULL then it will + * order the table my memcmp-ing the keys. + * + * num_entries_p - Pointer to an integer which, if not NULL, will + * contain the number of entries in the returned entry pointer array. + * + * error_p - Pointer to an integer which, if not NULL, will contain a + * table error code. + */ +table_entry_t **table_order(table_t *table_p, table_compare_t compare, + int *num_entries_p, int *error_p) +{ + table_entry_t *entry_p, **entries, **entries_p; + table_linear_t linear; + compare_t comp_func; + unsigned int entries_size; + int ret; + + if (table_p == NULL) { + SET_POINTER(error_p, TABLE_ERROR_ARG_NULL); + return NULL; + } + if (table_p->ta_magic != TABLE_MAGIC) { + SET_POINTER(error_p, TABLE_ERROR_PNT); + return NULL; + } + + /* there must be at least 1 element in the table for this to work */ + if (table_p->ta_entry_n == 0) { + SET_POINTER(error_p, TABLE_ERROR_EMPTY); + return NULL; + } + + entries_size = table_p->ta_entry_n * sizeof(table_entry_t *); + if (table_p->ta_alloc_func == NULL) { + entries = (table_entry_t **)malloc(entries_size); + } + else { + entries = + (table_entry_t **)table_p->ta_alloc_func(table_p->ta_mem_pool, + entries_size); + } + if (entries == NULL) { + SET_POINTER(error_p, TABLE_ERROR_ALLOC); + return NULL; + } + + /* get a pointer to all entries */ + entry_p = first_entry(table_p, &linear); + if (entry_p == NULL) { + if (table_p->ta_free_func == NULL) { + free(entries); + } + else { + (void)table_p->ta_free_func(table_p->ta_mem_pool, entries, entries_size); + } + SET_POINTER(error_p, TABLE_ERROR_NOT_FOUND); + return NULL; + } + + /* add all of the entries to the array */ + for (entries_p = entries; + entry_p != NULL; + entry_p = next_entry(table_p, &linear, &ret)) { + *entries_p++ = entry_p; + } + + if (ret != TABLE_ERROR_NOT_FOUND) { + if (table_p->ta_free_func == NULL) { + free(entries); + } + else { + (void)table_p->ta_free_func(table_p->ta_mem_pool, entries, entries_size); + } + SET_POINTER(error_p, ret); + return NULL; + } + + if (compare == NULL) { + /* this is regardless of the alignment */ + comp_func = local_compare; + } + else if (table_p->ta_data_align == 0) { + comp_func = external_compare; + } + else { + comp_func = external_compare_align; + } + + /* now qsort the entire entries array from first to last element */ + ret = split((unsigned char *)entries, + (unsigned char *)(entries + table_p->ta_entry_n - 1), + sizeof(table_entry_t *), comp_func, compare, table_p); + if (ret != TABLE_ERROR_NONE) { + if (table_p->ta_free_func == NULL) { + free(entries); + } + else { + (void)table_p->ta_free_func(table_p->ta_mem_pool, entries, entries_size); + } + SET_POINTER(error_p, ret); + return NULL; + } + + SET_POINTER(num_entries_p, table_p->ta_entry_n); + + SET_POINTER(error_p, TABLE_ERROR_NONE); + return entries; +} + +/* + * int table_order_free + * + * DESCRIPTION: + * + * Free the pointer returned by the table_order or table_order_pos + * routines. + * + * RETURNS: + * + * Success - TABLE_ERROR_NONE + * + * Failure - Table error code. + * + * ARGUMENTS: + * + * table_p - Pointer to the table. + * + * table_entries - Allocated list of entry pointers returned by + * table_order. + * + * entry_n - Number of entries in the array as passed back by + * table_order or table_order_pos in num_entries_p. + */ +int table_order_free(table_t *table_p, table_entry_t **table_entries, + const int entry_n) +{ + int ret, final = TABLE_ERROR_NONE; + + if (table_p == NULL) { + return TABLE_ERROR_ARG_NULL; + } + if (table_p->ta_magic != TABLE_MAGIC) { + return TABLE_ERROR_PNT; + } + + if (table_p->ta_free_func == NULL) { + free(table_entries); + } + else { + ret = table_p->ta_free_func(table_p->ta_mem_pool, table_entries, + sizeof(table_entry_t *) * entry_n); + if (ret != 1) { + final = TABLE_ERROR_FREE; + } + } + + return final; +} + +/* + * int table_entry + * + * DESCRIPTION: + * + * Get information about an element. The element is one from the + * array returned by the table_order function. If any of the key/data + * pointers are NULL then they are ignored. + * + * RETURNS: + * + * Success - TABLE_ERROR_NONE + * + * Failure - Table error code. + * + * ARGUMENTS: + * + * table_p - Table structure pointer from which we are getting the + * element. + * + * entry_p - Pointer to a table entry from the array returned by the + * table_order function. + * + * key_buf_p - Pointer which, if not NULL, will be set to the address + * of the storage of this entry that is allocated in the table. If an + * (int) is stored as this entry (for example) then key_buf_p should + * be (int **) i.e. the address of a (int *). + * + * key_size_p - Pointer to an integer which, if not NULL, will be set + * to the size of the key that is stored in the table. + * + * data_buf_p - Pointer which, if not NULL, will be set to the address + * of the data storage of this entry that is allocated in the table. + * If a (long) is stored as this entry data (for example) then + * data_buf_p should be (long **) i.e. the address of a (long *). + * + * data_size_p - Pointer to an integer which, if not NULL, will be set + * to the size of the data that is stored in the table. + */ +int table_entry(table_t *table_p, table_entry_t *entry_p, + void **key_buf_p, int *key_size_p, + void **data_buf_p, int *data_size_p) +{ + if (table_p == NULL) { + return TABLE_ERROR_ARG_NULL; + } + if (table_p->ta_magic != TABLE_MAGIC) { + return TABLE_ERROR_PNT; + } + if (entry_p == NULL) { + return TABLE_ERROR_ARG_NULL; + } + + SET_POINTER(key_buf_p, ENTRY_KEY_BUF(entry_p)); + SET_POINTER(key_size_p, entry_p->te_key_size); + if (data_buf_p != NULL) { + if (entry_p->te_data_size == 0) { + *data_buf_p = NULL; + } + else { + if (table_p->ta_data_align == 0) { + *data_buf_p = ENTRY_DATA_BUF(table_p, entry_p); + } + else { + *data_buf_p = entry_data_buf(table_p, entry_p); + } + } + } + SET_POINTER(data_size_p, entry_p->te_data_size); + + return TABLE_ERROR_NONE; +} + +/* + * table_linear_t *table_order_pos + * + * DESCRIPTION: + * + * Order a table by building an array of table linear structures and + * then sorting this array using the qsort function. To retrieve the + * sorted entries, you can then use the table_entry_pos routine to + * access each entry in order. + * + * NOTE: This routine is thread safe and makes use of an internal + * status qsort function. + * + * RETURNS: + * + * Success - An allocated list of table-linear structures which must + * be freed by table_order_pos_free later. + * + * Failure - NULL + * + * ARGUMENTS: + * + * table_p - Pointer to the table that we are ordering. + * + * compare - Comparison function defined by the user. Its definition + * is at the top of the table.h file. If this is NULL then it will + * order the table my memcmp-ing the keys. + * + * num_entries_p - Pointer to an integer which, if not NULL, will + * contain the number of entries in the returned entry pointer array. + * + * error_p - Pointer to an integer which, if not NULL, will contain a + * table error code. + */ +table_linear_t *table_order_pos(table_t *table_p, table_compare_t compare, + int *num_entries_p, int *error_p) +{ + table_entry_t *entry_p; + table_linear_t linear, *linears, *linears_p; + compare_t comp_func; + int ret; + + if (table_p == NULL) { + SET_POINTER(error_p, TABLE_ERROR_ARG_NULL); + return NULL; + } + if (table_p->ta_magic != TABLE_MAGIC) { + SET_POINTER(error_p, TABLE_ERROR_PNT); + return NULL; + } + + /* there must be at least 1 element in the table for this to work */ + if (table_p->ta_entry_n == 0) { + SET_POINTER(error_p, TABLE_ERROR_EMPTY); + return NULL; + } + + if (table_p->ta_alloc_func == NULL) { + linears = (table_linear_t *)malloc(table_p->ta_entry_n * + sizeof(table_linear_t)); + } + else { + linears = + (table_linear_t *)table_p->ta_alloc_func(table_p->ta_mem_pool, + table_p->ta_entry_n * + sizeof(table_linear_t)); + } + if (linears == NULL) { + SET_POINTER(error_p, TABLE_ERROR_ALLOC); + return NULL; + } + + /* get a pointer to all entries */ + entry_p = first_entry(table_p, &linear); + if (entry_p == NULL) { + SET_POINTER(error_p, TABLE_ERROR_NOT_FOUND); + return NULL; + } + + /* add all of the entries to the array */ + for (linears_p = linears; + entry_p != NULL; + entry_p = next_entry(table_p, &linear, &ret)) { + *linears_p++ = linear; + } + + if (ret != TABLE_ERROR_NOT_FOUND) { + SET_POINTER(error_p, ret); + return NULL; + } + + if (compare == NULL) { + /* this is regardless of the alignment */ + comp_func = local_compare_pos; + } + else if (table_p->ta_data_align == 0) { + comp_func = external_compare_pos; + } + else { + comp_func = external_compare_align_pos; + } + + /* now qsort the entire entries array from first to last element */ + split((unsigned char *)linears, + (unsigned char *)(linears + table_p->ta_entry_n - 1), + sizeof(table_linear_t), comp_func, compare, table_p); + + if (num_entries_p != NULL) { + *num_entries_p = table_p->ta_entry_n; + } + + SET_POINTER(error_p, TABLE_ERROR_NONE); + return linears; +} + +/* + * int table_order_pos_free + * + * DESCRIPTION: + * + * Free the pointer returned by the table_order or table_order_pos + * routines. + * + * RETURNS: + * + * Success - TABLE_ERROR_NONE + * + * Failure - Table error code. + * + * ARGUMENTS: + * + * table_p - Pointer to the table. + * + * table_entries - Allocated list of entry pointers returned by + * table_order_pos. + * + * entry_n - Number of entries in the array as passed back by + * table_order or table_order_pos in num_entries_p. + */ +int table_order_pos_free(table_t *table_p, table_linear_t *table_entries, + const int entry_n) +{ + int ret, final = TABLE_ERROR_NONE; + + if (table_p == NULL) { + return TABLE_ERROR_ARG_NULL; + } + if (table_p->ta_magic != TABLE_MAGIC) { + return TABLE_ERROR_PNT; + } + + if (table_p->ta_free_func == NULL) { + free(table_entries); + } + else { + ret = table_p->ta_free_func(table_p->ta_mem_pool, table_entries, + sizeof(table_linear_t) * entry_n); + if (ret != 1) { + final = TABLE_ERROR_FREE; + } + } + + return final; +} + +/* + * int table_entry_pos + * + * DESCRIPTION: + * + * Get information about an element. The element is one from the + * array returned by the table_order function. If any of the key/data + * pointers are NULL then they are ignored. + * + * RETURNS: + * + * Success - TABLE_ERROR_NONE + * + * Failure - Table error code. + * + * ARGUMENTS: + * + * table_p - Table structure pointer from which we are getting the + * element. + * + * linear_p - Pointer to a table linear structure from the array + * returned by the table_order function. + * + * key_buf_p - Pointer which, if not NULL, will be set to the address + * of the storage of this entry that is allocated in the table. If an + * (int) is stored as this entry (for example) then key_buf_p should + * be (int **) i.e. the address of a (int *). + * + * key_size_p - Pointer to an integer which, if not NULL, will be set + * to the size of the key that is stored in the table. + * + * data_buf_p - Pointer which, if not NULL, will be set to the address + * of the data storage of this entry that is allocated in the table. + * If a (long) is stored as this entry data (for example) then + * data_buf_p should be (long **) i.e. the address of a (long *). + * + * data_size_p - Pointer to an integer which, if not NULL, will be set + * to the size of the data that is stored in the table. + */ +int table_entry_pos(table_t *table_p, table_linear_t *linear_p, + void **key_buf_p, int *key_size_p, + void **data_buf_p, int *data_size_p) +{ + table_entry_t *entry_p; + int ret; + + if (table_p == NULL) { + return TABLE_ERROR_ARG_NULL; + } + if (table_p->ta_magic != TABLE_MAGIC) { + return TABLE_ERROR_PNT; + } + if (linear_p == NULL) { + return TABLE_ERROR_ARG_NULL; + } + + /* find the associated entry */ + entry_p = this_entry(table_p, linear_p, &ret); + if (entry_p == NULL) { + return ret; + } + + if (key_buf_p != NULL) { + *key_buf_p = ENTRY_KEY_BUF(entry_p); + } + if (key_size_p != NULL) { + *key_size_p = entry_p->te_key_size; + } + if (data_buf_p != NULL) { + if (entry_p->te_data_size == 0) { + *data_buf_p = NULL; + } + else { + if (table_p->ta_data_align == 0) { + *data_buf_p = ENTRY_DATA_BUF(table_p, entry_p); + } + else { + *data_buf_p = entry_data_buf(table_p, entry_p); + } + } + } + if (data_size_p != NULL) { + *data_size_p = entry_p->te_data_size; + } + + return TABLE_ERROR_NONE; +} + +/* + * const char *table_strerror + * + * DESCRIPTION: + * + * Return the corresponding string for the error number. + * + * RETURNS: + * + * Success - String equivalient of the error. + * + * Failure - String "invalid error code" + * + * ARGUMENTS: + * + * error - Error number that we are converting. + */ +const char *table_strerror(const int error) +{ + error_str_t *err_p; + + for (err_p = errors; err_p->es_error != 0; err_p++) { + if (err_p->es_error == error) { + return err_p->es_string; + } + } + + return INVALID_ERROR; +} diff --git a/libs/libks/src/table_util.c b/libs/libks/src/table_util.c new file mode 100644 index 0000000000..2fcfda3778 --- /dev/null +++ b/libs/libks/src/table_util.c @@ -0,0 +1,295 @@ +/* + * Hash table utility program. + * + * Copyright 2000 by Gray Watson + * + * This file is part of the table package. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose and without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies, + * and that the name of Gray Watson not be used in advertising or + * publicity pertaining to distribution of the document or software + * without specific, written prior permission. + * + * Gray Watson makes no representations about the suitability of the + * software described herein for any purpose. It is provided "as is" + * without express or implied warranty. + * + * The author may be reached via http://256.com/gray/ + * + * $Id: table_util.c,v 1.5 2000/03/09 03:30:42 gray Exp $ + */ + +#include +#include +#include + +#include "table.h" + +static char *rcs_id = + "$Id: table_util.c,v 1.5 2000/03/09 03:30:42 gray Exp $"; + +#define WRITE_MODE 0640 /* mode to write out table */ +#define SPECIAL_CHARS "e\033^^\"\"''\\\\n\nr\rt\tb\bf\fa\007" + +/* + * expand_chars + * + * DESCRIPTION: + * + * Copies a buffer into a output buffer while translates + * non-printables into %03o octal values. If it can, it will also + * translate certain \ characters (\r, \n, etc.) into \\%c. The + * routine is useful for printing out binary values. + * + * NOTE: It does _not_ add a \0 at the end of the output buffer. + * + * RETURNS: + * + * Returns the number of characters added to the output buffer. + * + * ARGUMENTS: + * + * buf - the buffer to convert. + * + * buf_size - size of the buffer. If < 0 then it will expand till it + * sees a \0 character. + * + * out - destination buffer for the convertion. + * + * out_size - size of the output buffer. + */ +int expand_chars(const void *buf, const int buf_size, + char *out, const int out_size) +{ + int buf_c; + const unsigned char *buf_p, *spec_p; + char *max_p, *out_p = out; + + /* setup our max pointer */ + max_p = out + out_size; + + /* run through the input buffer, counting the characters as we go */ + for (buf_c = 0, buf_p = (const unsigned char *)buf;; buf_c++, buf_p++) { + + /* did we reach the end of the buffer? */ + if (buf_size < 0) { + if (*buf_p == '\0') { + break; + } + } + else { + if (buf_c >= buf_size) { + break; + } + } + + /* search for special characters */ + for (spec_p = (unsigned char *)SPECIAL_CHARS + 1; + *(spec_p - 1) != '\0'; + spec_p += 2) { + if (*spec_p == *buf_p) { + break; + } + } + + /* did we find one? */ + if (*(spec_p - 1) != '\0') { + if (out_p + 2 >= max_p) { + break; + } + (void)sprintf(out_p, "\\%c", *(spec_p - 1)); + out_p += 2; + continue; + } + + /* print out any 7-bit printable characters */ + if (*buf_p < 128 && isprint(*buf_p)) { + if (out_p + 1 >= max_p) { + break; + } + *out_p = *(char *)buf_p; + out_p += 1; + } + else { + if (out_p + 4 >= max_p) { + break; + } + (void)sprintf(out_p, "\\%03o", *buf_p); + out_p += 4; + } + } + + return out_p - out; +} + +/* + * dump_table + * + * DESCRIPTION: + * + * Dump a table file to the screen. + * + * RETURNS: + * + * None. + * + * ARGUMENTS: + * + * tab_p - a table pointer that we are dumping. + */ +static void dump_table(table_t *tab_p) +{ + char buf[10240]; + void *key_p, *data_p; + int ret, key_size, data_size, len, entry_c; + + for (ret = table_first(tab_p, (void **)&key_p, &key_size, + (void **)&data_p, &data_size), entry_c = 0; + ret == TABLE_ERROR_NONE; + ret = table_next(tab_p, (void **)&key_p, &key_size, + (void **)&data_p, &data_size), entry_c++) { + /* expand the key */ + len = expand_chars(key_p, key_size, buf, sizeof(buf)); + (void)printf("%d: key '%.*s' (%d), ", entry_c, len, buf, len); + /* now dump the data */ + len = expand_chars(data_p, data_size, buf, sizeof(buf)); + (void)printf("data '%.*s' (%d)\n", len, buf, len); + } +} + +/* + * usage + * + * DESCRIPTION: + * + * Print the usage message to stderr. + * + * RETURNS: + * + * None. + * + * ARGUMENTS: + * + * tab_p - a table pointer that we are dumping. + */ +static void usage(void) +{ + (void)fprintf(stderr, + "Usage: table_util\n" + " [-b number] or --buckets num buckets to adjust table\n" + " [-o file] or --out-file output filename\n" + " [-v] or --verbose verbose messages\n" + " file input table filename\n"); + exit(1); +} + +int main(int argc, char **argv) +{ + table_t *tab_p; + char do_write = 0, verbose = 0; + char *out_file = NULL, *in_file; + int ret, entry_n, bucket_n, num_buckets = 0; + + /* process the args */ + for (argc--, argv++; argc > 0 && **argv == '-'; argc--, argv++) { + + switch (*(*argv + 1)) { + + case 'b': + argc--, argv++; + if (argc == 0) { + usage(); + } + num_buckets = atoi(*argv); + break; + + case 'o': + argc--, argv++; + if (argc == 0) { + usage(); + } + out_file = *argv; + break; + + case 'v': + verbose = 1; + break; + + default: + usage(); + break; + } + } + + if (argc != 1) { + usage(); + } + + /* take the last argument as the input file */ + in_file = *argv; + + /* read in the table from disk */ + tab_p = table_read(in_file, &ret); + if (tab_p == NULL) { + (void)fprintf(stderr, "table_util: unable to table_read from '%s': %s\n", + in_file, table_strerror(ret)); + exit(1); + } + + /* get info about the table */ + ret = table_info(tab_p, &bucket_n, &entry_n); + if (ret != TABLE_ERROR_NONE) { + (void)fprintf(stderr, + "table_util: unable to get info on table in '%s': %s\n", + in_file, table_strerror(ret)); + exit(1); + } + + (void)printf("Read table of %d buckets and %d entries from '%s'\n", + bucket_n, entry_n, in_file); + + if (verbose) { + dump_table(tab_p); + } + + if (num_buckets > 0) { + /* adjust the table's buckets */ + ret = table_adjust(tab_p, num_buckets); + if (ret != TABLE_ERROR_NONE) { + (void)fprintf(stderr, + "table_util: unable to adjust table to %d buckets: %s\n", + num_buckets, table_strerror(ret)); + exit(1); + } + do_write = 1; + } + + /* did we modify the table at all */ + if (do_write) { + if (out_file == NULL) { + out_file = in_file; + } + + /* write out our table */ + ret = table_write(tab_p, out_file, WRITE_MODE); + if (ret != TABLE_ERROR_NONE) { + (void)fprintf(stderr, "table_util: unable to write table to '%s': %s\n", + out_file, table_strerror(ret)); + exit(1); + } + + (void)printf("Wrote table to '%s'\n", out_file); + } + + /* free the table */ + ret = table_free(tab_p); + if (ret != TABLE_ERROR_NONE) { + (void)fprintf(stderr, "table_util: unable to free table: %s\n", + table_strerror(ret)); + /* NOTE: not a critical error */ + } + + exit(0); +} From d22e0caf15d1132e88bc1af43d97e422503d7521 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Wed, 19 Sep 2012 13:06:33 -0500 Subject: [PATCH 007/252] trigger update on sofia lib for new patch --- libs/sofia-sip/.update | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/sofia-sip/.update b/libs/sofia-sip/.update index 142a1e1a97..f85cfc8001 100644 --- a/libs/sofia-sip/.update +++ b/libs/sofia-sip/.update @@ -1 +1 @@ -Wed Aug 15 22:51:21 CDT 2012 +Wed Sep 19 13:06:07 CDT 2012 From 7018a15bf19b2ff10cade312843e1f114a4e33e4 Mon Sep 17 00:00:00 2001 From: David Yat Sin Date: Wed, 19 Sep 2012 15:25:38 -0400 Subject: [PATCH 008/252] fix for compile warning --- .../src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_cfg.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_cfg.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_cfg.c index 801febda14..7fb2f119a0 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_cfg.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_cfg.c @@ -273,7 +273,7 @@ static ftdm_status_t parse_trunkgroup(const char *_trunkgroup) { int i; char *p, *name, *dchan_span, *backup_span, *trunkgroup; - uint8_t num_spans; + uint8_t num_spans = 0; ftdm_status_t ret = FTDM_SUCCESS; trunkgroup = ftdm_strdup(_trunkgroup); From 08e95e6ee134ecef4774d0eb20653720db992bf9 Mon Sep 17 00:00:00 2001 From: Brian West Date: Wed, 19 Sep 2012 14:44:42 -0500 Subject: [PATCH 009/252] fix 7960/40 reboot --- src/mod/endpoints/mod_sofia/sofia_reg.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/mod/endpoints/mod_sofia/sofia_reg.c b/src/mod/endpoints/mod_sofia/sofia_reg.c index d710602107..1142534401 100644 --- a/src/mod/endpoints/mod_sofia/sofia_reg.c +++ b/src/mod/endpoints/mod_sofia/sofia_reg.c @@ -588,6 +588,8 @@ void sofia_reg_send_reboot(sofia_profile_t *profile, const char *callid, const c event = "reboot_now"; } else if (switch_stristr("spa", user_agent)) { event = "reboot"; + } else if (switch_stristr("Cisco-CP7960G", user_agent) || switch_stristr("Cisco-CP7940G", user_agent)) { + event = "check-sync"; } else if (switch_stristr("cisco", user_agent)) { event = "service-control"; contenttype = "text/plain"; From 98063854c6181837b5af34f939356e03ab52f27f Mon Sep 17 00:00:00 2001 From: Brian West Date: Wed, 19 Sep 2012 15:54:38 -0500 Subject: [PATCH 010/252] This already has a new line in it --- .../src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_rcv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_rcv.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_rcv.c index 34b4150ac0..da9a3024eb 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_rcv.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_rcv.c @@ -1091,7 +1091,7 @@ void sngisdn_rcv_sng_log(uint8_t level, char *fmt,...) switch (level) { case SNG_LOGLEVEL_DEBUG: - ftdm_log(FTDM_LOG_DEBUG, "sng_isdn->%s\n", data); + ftdm_log(FTDM_LOG_DEBUG, "sng_isdn->%s", data); break; case SNG_LOGLEVEL_WARN: if ( strncmp(data, "Invalid Q.921/Q.931 frame", 25) ) { From 72f0cf476d55f08f49c85af192792f6b67624fdb Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Wed, 19 Sep 2012 16:34:22 -0500 Subject: [PATCH 011/252] add conference-create and conference-destroy action events --- .../applications/mod_conference/mod_conference.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/mod/applications/mod_conference/mod_conference.c b/src/mod/applications/mod_conference/mod_conference.c index 0b1adcab57..0bdf28822b 100644 --- a/src/mod/applications/mod_conference/mod_conference.c +++ b/src/mod/applications/mod_conference/mod_conference.c @@ -1910,7 +1910,7 @@ static void *SWITCH_THREAD_FUNC conference_thread_run(switch_thread_t *thread, v int32_t z = 0; int member_score_sum = 0; int divisor = 0; - + if (!(divisor = conference->rate / 8000)) { divisor = 1; } @@ -1932,6 +1932,13 @@ static void *SWITCH_THREAD_FUNC conference_thread_run(switch_thread_t *thread, v conference->is_recording = 0; conference->record_count = 0; + + + switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, CONF_EVENT_MAINT); + conference_add_event_data(conference, event); + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Action", "conference-create"); + switch_event_fire(&event); + while (globals.running && !switch_test_flag(conference, CFLAG_DESTRUCT)) { switch_size_t file_sample_len = samples; switch_size_t file_data_len = samples * 2; @@ -2448,6 +2455,11 @@ static void *SWITCH_THREAD_FUNC conference_thread_run(switch_thread_t *thread, v } } + + switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, CONF_EVENT_MAINT); + conference_add_event_data(conference, event); + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Action", "conference-destroy"); + switch_event_fire(&event); switch_core_timer_destroy(&timer); switch_mutex_lock(globals.hash_mutex); From fff6e50a9bd76676ea23a49e0102cda77bdabeca Mon Sep 17 00:00:00 2001 From: Moises Silva Date: Wed, 19 Sep 2012 20:02:30 -0400 Subject: [PATCH 012/252] freetdm: Fix E&M answer procedure for DAHDI --- libs/freetdm/mod_freetdm/mod_freetdm.c | 1 + libs/freetdm/src/ftmod/ftmod_zt/ftmod_zt.c | 7 ++++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/libs/freetdm/mod_freetdm/mod_freetdm.c b/libs/freetdm/mod_freetdm/mod_freetdm.c index 271f532a70..06dc587a4b 100755 --- a/libs/freetdm/mod_freetdm/mod_freetdm.c +++ b/libs/freetdm/mod_freetdm/mod_freetdm.c @@ -2285,6 +2285,7 @@ static FIO_SIGNAL_CB_FUNCTION(on_fxo_signal) } break; case FTDM_SIGEVENT_SIGSTATUS_CHANGED: + case FTDM_SIGEVENT_COLLECTED_DIGIT: /* Analog E&M */ break; default: { diff --git a/libs/freetdm/src/ftmod/ftmod_zt/ftmod_zt.c b/libs/freetdm/src/ftmod/ftmod_zt/ftmod_zt.c index 2569ea49fd..363dcee7c5 100644 --- a/libs/freetdm/src/ftmod/ftmod_zt/ftmod_zt.c +++ b/libs/freetdm/src/ftmod/ftmod_zt/ftmod_zt.c @@ -737,6 +737,7 @@ static FIO_COMMAND_FUNCTION(zt_command) ftdm_log_chan_msg(ftdmchan, FTDM_LOG_ERROR, "OFFHOOK Failed"); return FTDM_FAIL; } + ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Channel is now offhook\n"); ftdm_set_flag_locked(ftdmchan, FTDM_CHANNEL_OFFHOOK); } break; @@ -747,6 +748,7 @@ static FIO_COMMAND_FUNCTION(zt_command) ftdm_log_chan_msg(ftdmchan, FTDM_LOG_ERROR, "ONHOOK Failed"); return FTDM_FAIL; } + ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Channel is now onhook\n"); ftdm_clear_flag_locked(ftdmchan, FTDM_CHANNEL_OFFHOOK); } break; @@ -1084,7 +1086,10 @@ static __inline__ ftdm_status_t zt_channel_process_event(ftdm_channel_t *fchan, case ZT_EVENT_RINGOFFHOOK: { if (fchan->type == FTDM_CHAN_TYPE_FXS || (fchan->type == FTDM_CHAN_TYPE_EM && fchan->state != FTDM_CHANNEL_STATE_UP)) { - ftdm_set_flag_locked(fchan, FTDM_CHANNEL_OFFHOOK); + if (fchan->type != FTDM_CHAN_TYPE_EM) { + /* In E&M we're supposed to set this flag when the tx side goes offhook, not the rx */ + ftdm_set_flag_locked(fchan, FTDM_CHANNEL_OFFHOOK); + } *event_id = FTDM_OOB_OFFHOOK; } else if (fchan->type == FTDM_CHAN_TYPE_FXO) { *event_id = FTDM_OOB_RING_START; From 45bda533616d6b2ea866b1cbb3707851fe876627 Mon Sep 17 00:00:00 2001 From: Travis Cross Date: Thu, 20 Sep 2012 06:43:54 +0000 Subject: [PATCH 013/252] Add new modules to debian packaging --- debian/control-modules | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/debian/control-modules b/debian/control-modules index 5b76bd5d26..a41e858513 100644 --- a/debian/control-modules +++ b/debian/control-modules @@ -147,6 +147,11 @@ 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). @@ -192,6 +197,11 @@ Module: applications/mod_snom Description: SNOM specific features This module implements features specific to SNOM phones. +Module: applications/mod_sonar +Description: Sonar ping timer + This module measures the latency on an audio link by sending audible + audio sonar pings. + Module: applications/mod_soundtouch Description: Soundtouch This module implements example media bugs. @@ -335,6 +345,10 @@ Module: codecs/mod_voipcodecs Description: mod_voipcodecs Adds mod_voipcodecs. +Module: codecs/mod_vp8 +Description: VP8 video codec + This module adds the VP8 video codec, also known as WebM. + ## mod/dialplans Module: dialplans/mod_dialplan_asterisk @@ -376,6 +390,10 @@ Description: mod_h323 Adds mod_h323. Build-Depends: libopenh323-dev, libpt-dev +Module: endpoints/mod_html5 +Description: HTML5 endpoint module + This module adds support for HTML5 technologies such as WebRTC. + Module: endpoints/mod_khomp Description: mod_khomp Adds mod_khomp. @@ -651,6 +669,10 @@ Description: mod_xml_ldap Adds mod_xml_ldap. Build-Depends: libsasl2-dev +Module: xml_int/mod_xml_radius +Description: mod_xml_radius + Adds mod_xml_radius + Module: xml_int/mod_xml_rpc Description: mod_xml_rpc Adds mod_xml_rpc. From 1dd2e0f6b0294019f0a62ce3b0e7c658c9e2de66 Mon Sep 17 00:00:00 2001 From: Travis Cross Date: Thu, 20 Sep 2012 06:48:07 +0000 Subject: [PATCH 014/252] Avoid new modules in debian except mod_vp8 --- debian/bootstrap.sh | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/debian/bootstrap.sh b/debian/bootstrap.sh index a724948577..5ba909b851 100755 --- a/debian/bootstrap.sh +++ b/debian/bootstrap.sh @@ -12,9 +12,11 @@ avoid_mods=( applications/mod_limit applications/mod_mongo applications/mod_mp4 + applications/mod_oreka applications/mod_osp applications/mod_rad_auth applications/mod_skel + applications/mod_sonar applications/mod_soundtouch asr_tts/mod_cepstral asr_tts/mod_flite @@ -26,6 +28,7 @@ avoid_mods=( codecs/mod_voipcodecs endpoints/mod_gsmopen endpoints/mod_h323 + endpoints/mod_html5 endpoints/mod_khomp endpoints/mod_opal endpoints/mod_reference @@ -35,6 +38,7 @@ avoid_mods=( languages/mod_spidermonkey sdk/autotools xml_int/mod_xml_ldap + xml_int/mod_xml_radius ) avoid_mods_sid=( endpoints/mod_portaudio From eca14d46011a416db288a8e87d00dee47be70002 Mon Sep 17 00:00:00 2001 From: Travis Cross Date: Thu, 20 Sep 2012 07:03:30 +0000 Subject: [PATCH 015/252] Fix format string for actual type of apr_time_t This was causing the build to fail if mod_sonar was configured to build. --- src/mod/applications/mod_sonar/mod_sonar.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mod/applications/mod_sonar/mod_sonar.c b/src/mod/applications/mod_sonar/mod_sonar.c index 5cdcd35188..8f6e424eb3 100644 --- a/src/mod/applications/mod_sonar/mod_sonar.c +++ b/src/mod/applications/mod_sonar/mod_sonar.c @@ -61,7 +61,7 @@ switch_bool_t sonar_ping_callback(switch_core_session_t *session, const char *ap end = switch_time_now(); diff = end - start; start = 0; - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Sonar ping took %lu milliseconds\n", diff / 1000); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Sonar ping took %ld milliseconds\n", (long)diff / 1000); return SWITCH_TRUE; } From c6e75490552a500fb8dddc6889e14b6229489c0f Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Thu, 20 Sep 2012 09:48:47 -0500 Subject: [PATCH 016/252] FS-4634 --resolve --- src/switch_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/switch_core.c b/src/switch_core.c index 30f1ef3bae..2a9bec7dee 100644 --- a/src/switch_core.c +++ b/src/switch_core.c @@ -1692,7 +1692,7 @@ static void switch_load_core_config(const char *file) switch_core_session_ctl(SCSC_LOGLEVEL, &level); } #ifdef HAVE_SETRLIMIT - } else if (!strcasecmp(var, "dump-cores")) { + } else if (!strcasecmp(var, "dump-cores") && switch_true(val)) { struct rlimit rlp; memset(&rlp, 0, sizeof(rlp)); rlp.rlim_cur = RLIM_INFINITY; From 0dac49008655ea222318ab056ea5a82548bb6d73 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Thu, 20 Sep 2012 09:53:53 -0500 Subject: [PATCH 017/252] FS-4315 --resolve --- src/mod/applications/mod_spy/mod_spy.c | 113 ++++++++++++++++--------- 1 file changed, 71 insertions(+), 42 deletions(-) diff --git a/src/mod/applications/mod_spy/mod_spy.c b/src/mod/applications/mod_spy/mod_spy.c index 12c42ba15c..a5cb3c92c0 100644 --- a/src/mod/applications/mod_spy/mod_spy.c +++ b/src/mod/applications/mod_spy/mod_spy.c @@ -46,22 +46,39 @@ struct mod_spy_globals { uint32_t spy_count; } globals; +typedef struct spy { + const char *uuid; + struct spy *next; +} spy_t; + + static switch_status_t spy_on_hangup(switch_core_session_t *session) { switch_channel_t *channel = switch_core_session_get_channel(session); + const char *data = switch_channel_get_private(channel, "_userspy_"); + const char *uuid = switch_core_session_get_uuid(session); + spy_t *spy = NULL, *p = NULL, *prev = NULL; - char *data = switch_channel_get_private(channel, "_userspy_"); switch_thread_rwlock_wrlock(globals.spy_hash_lock); - if ((switch_core_hash_delete(globals.spy_hash, data) != SWITCH_STATUS_SUCCESS)) { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "No such key in userspy: %s \n", data); - - } else { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Userspy deactivated on %s\n", data); - globals.spy_count--; + spy = switch_core_hash_find(globals.spy_hash, data); + for (p = spy; p; p = p->next) { + if (p->uuid == uuid) { + if (prev) { + prev->next = p->next; + } else { + spy = p->next; + } + globals.spy_count--; + break; + } + prev = p; } + switch_core_hash_insert(globals.spy_hash, data, spy); + switch_thread_rwlock_unlock(globals.spy_hash_lock); + return SWITCH_STATUS_SUCCESS; } @@ -115,12 +132,20 @@ SWITCH_STANDARD_API(dump_hash) switch_hash_index_t *hi; const void *key; void *val; + spy_t *spy; switch_thread_rwlock_rdlock(globals.spy_hash_lock); for (hi = switch_hash_first(NULL, globals.spy_hash); hi; hi = switch_hash_next(hi)) { switch_hash_this(hi, &key, NULL, &val); - stream->write_function(stream, "%s : %s\n", (char *) key, (const char *) val); + spy = (spy_t *) val; + + stream->write_function(stream, "%s :"); + while (spy) { + stream->write_function(stream, " %s", spy->uuid); + spy = spy->next; + } + stream->write_function(stream, "\n"); } stream->write_function(stream, "\n%d total spy\n", globals.spy_count); @@ -130,9 +155,10 @@ SWITCH_STANDARD_API(dump_hash) static switch_status_t process_event(switch_event_t *event) { + switch_status_t status = SWITCH_STATUS_SUCCESS; switch_core_session_t *session = NULL; - char *username[3] = { 0 }; - char *domain[3] = { 0 }; + char *username[3] = { NULL }; + char *domain[3] = { NULL }; char key[512]; char *uuid = NULL, *my_uuid = NULL; int i; @@ -147,8 +173,8 @@ static switch_status_t process_event(switch_event_t *event) username[0] = switch_event_get_header(event, "Caller-Username"); domain[0] = switch_event_get_header(event, "variable_domain_name"); - domain[1] = switch_event_get_header(event, "variable_dialed_domain"); username[1] = switch_event_get_header(event, "variable_dialed_user"); + domain[1] = switch_event_get_header(event, "variable_dialed_domain"); username[2] = switch_event_get_header(event, "variable_user_name"); domain[2] = switch_event_get_header(event, "variable_domain_name"); @@ -156,35 +182,39 @@ static switch_status_t process_event(switch_event_t *event) for (i = 0; i < 3; i++) { if (username[i] && domain[i]) { + spy_t *spy = NULL; switch_snprintf(key, sizeof(key), "%s@%s", username[i], domain[i]); - if ((uuid = switch_core_hash_find(globals.spy_hash, key))) { + if ((spy = switch_core_hash_find(globals.spy_hash, key))) { + while (spy) { + if ((session = switch_core_session_locate(spy->uuid))) { + switch_channel_t *channel = switch_core_session_get_channel(session); + + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "UserSpy retrieved uuid %s for key %s, activating eavesdrop\n", uuid, key); + my_uuid = switch_event_get_header(event, "Unique-ID"); + + switch_channel_set_variable(channel, "spy_uuid", my_uuid); + + switch_channel_set_state(channel, CS_EXCHANGE_MEDIA); + switch_channel_set_flag(channel, CF_BREAK); + + switch_core_session_rwunlock(session); + } + spy = spy->next; + } break; + } else { + /* not found */ + status = SWITCH_STATUS_FALSE; } } } - + + done: switch_thread_rwlock_unlock(globals.spy_hash_lock); + return status; - if (!uuid) { - return SWITCH_STATUS_FALSE; - } - - if ((session = switch_core_session_locate(uuid))) { - switch_channel_t *channel = switch_core_session_get_channel(session); - - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "UserSpy retrieved uuid %s for key %s, activating eavesdrop \n", uuid, key); - my_uuid = switch_event_get_header(event, "Unique-ID"); - - switch_channel_set_variable(channel, "spy_uuid", my_uuid); - - switch_channel_set_state(channel, CS_EXCHANGE_MEDIA); - switch_channel_set_flag(channel, CF_BREAK); - - switch_core_session_rwunlock(session); - } - return SWITCH_STATUS_SUCCESS; } @@ -233,20 +263,20 @@ SWITCH_STANDARD_APP(userspy_function) if (!zstr(data) && (params = switch_core_session_strdup(session, data))) { if ((argc = switch_separate_string(params, ' ', argv, (sizeof(argv) / sizeof(argv[0])))) >= 1) { - switch_channel_t *channel = switch_core_session_get_channel(session); char *uuid = switch_core_session_get_uuid(session); switch_status_t status; + spy_t *spy = NULL; + + spy = switch_core_session_alloc(session, sizeof(spy_t)); + switch_assert(spy != NULL); + spy->uuid = uuid; switch_thread_rwlock_wrlock(globals.spy_hash_lock); - if (switch_core_hash_find(globals.spy_hash, argv[0])) { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Spy already exists for %s\n", argv[0]); - switch_channel_hangup(channel, SWITCH_CAUSE_NORMAL_CLEARING); - switch_thread_rwlock_unlock(globals.spy_hash_lock); - return; - } - status = switch_core_hash_insert(globals.spy_hash, argv[0], (void *) uuid); + spy->next = (spy_t *) switch_core_hash_find(globals.spy_hash, argv[0]); + + status = switch_core_hash_insert(globals.spy_hash, argv[0], (void *) spy); if ((status != SWITCH_STATUS_SUCCESS)) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Can't insert to spy hash\n"); @@ -270,11 +300,10 @@ SWITCH_STANDARD_APP(userspy_function) } switch_channel_set_state(channel, CS_PARK); - return; } - return; + } else { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Usage: %s\n", USERSPY_SYNTAX); } - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Usage: %s\n", USERSPY_SYNTAX); } SWITCH_MODULE_LOAD_FUNCTION(mod_spy_load) From a39ba84f5e5cf1c318bd57a41bfc649c0a79776b Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Thu, 20 Sep 2012 09:55:47 -0500 Subject: [PATCH 018/252] FS-4458 --resolve --- .../mod_erlang_event/mod_erlang_event.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/mod/event_handlers/mod_erlang_event/mod_erlang_event.c b/src/mod/event_handlers/mod_erlang_event/mod_erlang_event.c index 0aeaece8dd..9b34bfa8fc 100644 --- a/src/mod/event_handlers/mod_erlang_event/mod_erlang_event.c +++ b/src/mod/event_handlers/mod_erlang_event/mod_erlang_event.c @@ -812,7 +812,6 @@ static void handle_exit(listener_t *listener, erlang_pid * pid) } - if (listener->log_process.type == ERLANG_PID && !ei_compare_pids(&listener->log_process.pid, pid)) { void *pop; @@ -1477,15 +1476,14 @@ SWITCH_STANDARD_APP(erlang_outbound_function) int argc = 0, argc2 = 0; char *argv[80] = { 0 }, *argv2[80] = { 0 }; char *mydata, *myarg; - char uuid[SWITCH_UUID_FORMATTED_LENGTH + 1]; session_elem_t *session_element = NULL; + switch_channel_t *channel = switch_core_session_get_channel(session); /* process app arguments */ if (data && (mydata = switch_core_session_strdup(session, data))) { argc = switch_separate_string(mydata, ' ', argv, (sizeof(argv) / sizeof(argv[0]))); } /* XXX else? */ - memcpy(uuid, switch_core_session_get_uuid(session), SWITCH_UUID_FORMATTED_LENGTH); if (argc < 2) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Parse Error - need registered name and node!\n"); @@ -1518,6 +1516,13 @@ SWITCH_STANDARD_APP(erlang_outbound_function) switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "enter erlang_outbound_function %s %s\n", argv[0], node); + + if (switch_channel_test_flag(channel, CF_CONTROLLED)) { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Channel is already under control\n"); + return; + } + + /* first work out if there is a listener already talking to the node we want to talk to */ listener = find_listener(node); /* if there is no listener, then create one */ @@ -1551,7 +1556,7 @@ SWITCH_STANDARD_APP(erlang_outbound_function) switch_thread_rwlock_unlock(globals.listener_rwlock); } - switch_log_printf(SWITCH_CHANNEL_UUID_LOG(uuid), SWITCH_LOG_DEBUG, "exit erlang_outbound_function\n"); + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "exit erlang_outbound_function\n"); } From 07ed03c45845901c997c3d999d5603c85e44cc9d Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Thu, 20 Sep 2012 09:57:58 -0500 Subject: [PATCH 019/252] FS-4625 --resolve --- src/mod/applications/mod_dptools/mod_dptools.c | 17 +++++++++++++++++ src/switch_channel.c | 2 +- src/switch_ivr_async.c | 11 +---------- 3 files changed, 19 insertions(+), 11 deletions(-) diff --git a/src/mod/applications/mod_dptools/mod_dptools.c b/src/mod/applications/mod_dptools/mod_dptools.c index b481ca9f05..4fec5c3269 100755 --- a/src/mod/applications/mod_dptools/mod_dptools.c +++ b/src/mod/applications/mod_dptools/mod_dptools.c @@ -567,6 +567,22 @@ SWITCH_STANDARD_APP(mkdir_function) switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s MKDIR: %s\n", switch_channel_get_name(switch_core_session_get_channel(session)), data); } +#define RENAME_SYNTAX " " +SWITCH_STANDARD_APP(rename_function) +{ + char *argv[2] = { 0 }; + char *lbuf = NULL; + + if (!zstr(data) && (lbuf = switch_core_session_strdup(session, data)) + && switch_split(lbuf, ' ', argv) == 2) { + switch_file_rename(argv[0], argv[1], switch_core_session_get_pool(session)); + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s RENAME: %s %s\n", + switch_channel_get_name(switch_core_session_get_channel(session)), argv[0], argv[1]); + + } else { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Usage: %s\n", RENAME_SYNTAX); + } +} #define SOFT_HOLD_SYNTAX " [] []" SWITCH_STANDARD_APP(soft_hold_function) @@ -5103,6 +5119,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_dptools_load) SWITCH_ADD_APP(app_interface, "enable_heartbeat", "Enable Media Heartbeat", "Enable Media Heartbeat", heartbeat_function, HEARTBEAT_SYNTAX, SAF_SUPPORT_NOMEDIA); SWITCH_ADD_APP(app_interface, "mkdir", "Create a directory", "Create a directory", mkdir_function, MKDIR_SYNTAX, SAF_SUPPORT_NOMEDIA); + SWITCH_ADD_APP(app_interface, "rename", "Rename file", "Rename file", rename_function, RENAME_SYNTAX, SAF_SUPPORT_NOMEDIA | SAF_ZOMBIE_EXEC); SWITCH_ADD_APP(app_interface, "soft_hold", "Put a bridged channel on hold", "Put a bridged channel on hold", soft_hold_function, SOFT_HOLD_SYNTAX, SAF_NONE); SWITCH_ADD_APP(app_interface, "bind_meta_app", "Bind a key to an application", "Bind a key to an application", dtmf_bind_function, BIND_SYNTAX, diff --git a/src/switch_channel.c b/src/switch_channel.c index f823b22e49..5606d81fe0 100644 --- a/src/switch_channel.c +++ b/src/switch_channel.c @@ -3274,7 +3274,7 @@ static void do_execute_on(switch_channel_t *channel, const char *variable) app = switch_core_session_strdup(channel->session, variable); for(p = app; p && *p; p++) { - if (*p == ' ') { + if (*p == ' ' || (*p == ':' && (*(p+1) != ':'))) { *p++ = '\0'; arg = p; break; diff --git a/src/switch_ivr_async.c b/src/switch_ivr_async.c index 03f9839f78..314b41a5ed 100644 --- a/src/switch_ivr_async.c +++ b/src/switch_ivr_async.c @@ -1083,16 +1083,7 @@ static switch_bool_t record_callback(switch_media_bug_t *bug, void *user_data, s 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; - - if ((data = strchr(app, ':'))) { - *data++ = '\0'; - } - - switch_core_session_execute_application(session, app, data); - } + switch_channel_execute_on(channel, "record_post_process_exec_app"); if ((var = switch_channel_get_variable(channel, "record_post_process_exec_api"))) { char *cmd = switch_core_session_strdup(session, var); From dfa83799d0921b0b2486267c9634d17130ad337e Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Thu, 20 Sep 2012 09:59:50 -0500 Subject: [PATCH 020/252] FS-4624 --resolve --- .../applications/mod_dptools/mod_dptools.c | 58 ++++++++++++++----- src/switch_ivr_async.c | 2 +- 2 files changed, 45 insertions(+), 15 deletions(-) diff --git a/src/mod/applications/mod_dptools/mod_dptools.c b/src/mod/applications/mod_dptools/mod_dptools.c index 4fec5c3269..fae029bc61 100755 --- a/src/mod/applications/mod_dptools/mod_dptools.c +++ b/src/mod/applications/mod_dptools/mod_dptools.c @@ -4419,7 +4419,7 @@ struct file_string_context { typedef struct file_string_context file_string_context_t; -static int next_file(switch_file_handle_t *handle) +static switch_status_t next_file(switch_file_handle_t *handle) { file_string_context_t *context = handle->private_info; char *file; @@ -4434,7 +4434,7 @@ static int next_file(switch_file_handle_t *handle) } if (context->index >= context->argc) { - return 0; + return SWITCH_STATUS_FALSE; } @@ -4450,8 +4450,23 @@ static int next_file(switch_file_handle_t *handle) file = switch_core_sprintf(handle->memory_pool, "%s%s%s", prefix, SWITCH_PATH_SEPARATOR, context->argv[context->index]); } - if (switch_core_file_open(&context->fh, - file, handle->channels, handle->samplerate, SWITCH_FILE_FLAG_READ | SWITCH_FILE_DATA_SHORT, NULL) != SWITCH_STATUS_SUCCESS) { + if (switch_test_flag(handle, SWITCH_FILE_FLAG_WRITE)) { + char *path = switch_core_strdup(handle->memory_pool, file); + char *p; + + if ((p = strrchr(path, *SWITCH_PATH_SEPARATOR))) { + *p = '\0'; + if (switch_dir_make_recursive(path, SWITCH_DEFAULT_DIR_PERMS, handle->memory_pool) != SWITCH_STATUS_SUCCESS) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error creating %s\n", path); + return SWITCH_STATUS_FALSE; + } + + } else { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error finding the folder path section in '%s'\n", path); + } + + } + if (switch_core_file_open(&context->fh, file, handle->channels, handle->samplerate, handle->flags, NULL) != SWITCH_STATUS_SUCCESS) { goto top; } @@ -4477,7 +4492,7 @@ static int next_file(switch_file_handle_t *handle) } } - return 1; + return SWITCH_STATUS_SUCCESS; } @@ -4503,11 +4518,6 @@ static switch_status_t file_string_file_open(switch_file_handle_t *handle, const file_string_context_t *context; char *file_dup; - if (switch_test_flag(handle, SWITCH_FILE_FLAG_WRITE)) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "This format does not support writing!\n"); - return SWITCH_STATUS_FALSE; - } - context = switch_core_alloc(handle->memory_pool, sizeof(*context)); file_dup = switch_core_strdup(handle->memory_pool, path); @@ -4516,7 +4526,7 @@ static switch_status_t file_string_file_open(switch_file_handle_t *handle, const handle->private_info = context; - return next_file(handle) ? SWITCH_STATUS_SUCCESS : SWITCH_STATUS_FALSE; + return next_file(handle); } static switch_status_t file_string_file_close(switch_file_handle_t *handle) @@ -4549,16 +4559,35 @@ static switch_status_t file_string_file_read(switch_file_handle_t *handle, void } if (status != SWITCH_STATUS_SUCCESS) { - if (!next_file(handle)) { - return SWITCH_STATUS_FALSE; + if ((status = next_file(handle)) != SWITCH_STATUS_SUCCESS) { + return status; } *len = llen; status = switch_core_file_read(&context->fh, data, len); } - return SWITCH_STATUS_SUCCESS; + return status; } +static switch_status_t file_string_file_write(switch_file_handle_t *handle, void *data, size_t *len) +{ + file_string_context_t *context = handle->private_info; + switch_status_t status; + size_t llen = *len; + + status = switch_core_file_write(&context->fh, data, len); + + if (status != SWITCH_STATUS_SUCCESS) { + if ((status = next_file(handle)) != SWITCH_STATUS_SUCCESS) { + return status; + } + *len = llen; + status = switch_core_file_write(&context->fh, data, len); + } + return status; +} + + /* Registration */ static char *file_string_supported_formats[SWITCH_MAX_CODECS] = { 0 }; @@ -4979,6 +5008,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_dptools_load) file_interface->file_open = file_string_file_open; file_interface->file_close = file_string_file_close; file_interface->file_read = file_string_file_read; + file_interface->file_write = file_string_file_write; file_interface->file_seek = file_string_file_seek; diff --git a/src/switch_ivr_async.c b/src/switch_ivr_async.c index 314b41a5ed..a9ebc4b352 100644 --- a/src/switch_ivr_async.c +++ b/src/switch_ivr_async.c @@ -1825,7 +1825,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_record_session(switch_core_session_t file_path = switch_core_session_strdup(session, file); } - if (file_path) { + if (file_path && !strstr(file_path, SWITCH_URL_SEPARATOR)) { char *p; char *path = switch_core_session_strdup(session, file_path); From 54289f2a6596db634c17ca2f0620273255cec4ef Mon Sep 17 00:00:00 2001 From: Michael S Collins Date: Thu, 20 Sep 2012 08:46:01 -0700 Subject: [PATCH 021/252] FreeSWITCH ChangeLog for 1.2.1 and 1.2.2 --- docs/ChangeLog | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/docs/ChangeLog b/docs/ChangeLog index e0de248e87..562fe03d5f 100644 --- a/docs/ChangeLog +++ b/docs/ChangeLog @@ -1,3 +1,25 @@ +freeswitch (1.2.2) + configuration: Add language config files for es-ES,es-MX,pt-BR,pt-PT (Thanks Francois Delawarde) (r:9cde99b4/FS-3003) + core: move recovery engine up into the core (r:66677c94) + core: add ignore_early_media=consume to ivr_originate (r:13dab11c) + core: add timestamps for on and off hold times to put in xml cdrs (r:b0e49d3e) + libtiff: update to 4.0.2 (r:a2b5af56) + mod_commands: add uuid_answer and uuid_pre_answer (r:ce88d572) + mod_commands: add uuid_early_ok (r:35f0e2ff) + mod_commands: add uuid_media_reneg api command to tell a channel to send a re-invite with optional list of new codecs (r:bfc46567) + mod_dptools: mutex app (r:212953bc) + mod_httapi: add cache param (r:a8b89bcc) + mod_shout: add mp3 codec for mp4 (r:084dac25) + mod_sofia: change mod_sofia to use new core based recovery engine (r:2a8841ab) + mod_sofia: fire-message-events profile param (r:9c06cb34) + mod_spidermonkey: add email function to js (r:37b36aea) + +freeswitch (1.2.1) + libapr: Updating in tree apr for 1.4.6 (r:4029614e) + libwebsockets: Initial commit (r:6fa2fd36) + mod_sofia: add rtp endpoint contributed by sangoma (r:ef5c1256) + mod_spidermonkey: add javascript chatplan app (r:61839229) + freeswitch (1.2.0) build: Automated builds for CI testing/Jenkins (r:2aff535a) build: add debian source package building script (r:c164aae9) From caaa5726b07e717ed02229993b520e5e6fa2f42f Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Thu, 20 Sep 2012 10:49:39 -0500 Subject: [PATCH 022/252] fold over use-server to be alias for nameserver param and support back compat with legacy configs --- src/mod/applications/mod_enum/mod_enum.c | 68 ++++++++++++------------ 1 file changed, 34 insertions(+), 34 deletions(-) diff --git a/src/mod/applications/mod_enum/mod_enum.c b/src/mod/applications/mod_enum/mod_enum.c index c40e6443f0..ae19bdb791 100644 --- a/src/mod/applications/mod_enum/mod_enum.c +++ b/src/mod/applications/mod_enum/mod_enum.c @@ -67,7 +67,6 @@ static switch_event_node_t *NODE = NULL; static struct { char *root; - char *server; char *isn_root; enum_route_t *route_order; switch_memory_pool_t *pool; @@ -79,7 +78,6 @@ static struct { } globals; SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_root, globals.root); -SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_server, globals.server); SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_isn_root, globals.isn_root); static void add_route(char *service, char *regex, char *replace) @@ -126,8 +124,6 @@ static switch_status_t load_config(void) const char *val = switch_xml_attr_soft(param, "value"); if (!strcasecmp(var, "default-root")) { set_global_root(val); - } else if (!strcasecmp(var, "use-server")) { - set_global_server(val); } else if (!strcasecmp(var, "auto-reload")) { globals.auto_reload = switch_true(val); } else if (!strcasecmp(var, "query-timeout")) { @@ -140,7 +136,7 @@ static switch_status_t load_config(void) globals.random = switch_true(val); } else if (!strcasecmp(var, "default-isn-root")) { set_global_isn_root(val); - } else if (!strcasecmp(var, "nameserver")) { + } else if (!strcasecmp(var, "nameserver") || !strcasecmp(var, "use-server")) { if ( inameserver < ENUM_MAXNAMESERVERS ) { globals.nameserver[inameserver] = (char *) val; inameserver++; @@ -560,6 +556,7 @@ static switch_status_t enum_lookup(char *root, char *in, enum_record_t **results int argc; int x = 0; char *enum_nameserver_dup; + const char *enum_nameserver = NULL; *results = NULL; @@ -577,41 +574,45 @@ static switch_status_t enum_lookup(char *root, char *in, enum_record_t **results /* Empty the server array */ for(inameserver=0; inameserver Date: Thu, 20 Sep 2012 09:53:34 -0700 Subject: [PATCH 023/252] FreeSWITCH ChangeLog for 1.2.3 --- docs/ChangeLog | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/docs/ChangeLog b/docs/ChangeLog index 562fe03d5f..ae69a26e4c 100644 --- a/docs/ChangeLog +++ b/docs/ChangeLog @@ -1,3 +1,12 @@ +freeswitch (1.2.3) + core: add hold_events variable with start and stop times for each hold (r:9a193a9c) + core: update json lib in core and ESL and re-apply old patches (r:5a956890) + core: add skip_cdr_causes variable to list call hangup causes that should not trigger cdr processing (r:3cf238fc) + formats: add mod_mp4v2 for mp4 recording, most things are hardcodec, but it should work with 8000hz audio and H264 video (r:7e01bd10) + libsofia: Fix DoS vulnerability in processing Route Header (r:016550f2/FS-4627) + libtpl: add tpl to tree (r:4985a41f) + mod_sofia: add transfer_to variable for call processing (r:1b2b4565) + freeswitch (1.2.2) configuration: Add language config files for es-ES,es-MX,pt-BR,pt-PT (Thanks Francois Delawarde) (r:9cde99b4/FS-3003) core: move recovery engine up into the core (r:66677c94) @@ -12,6 +21,7 @@ freeswitch (1.2.2) mod_shout: add mp3 codec for mp4 (r:084dac25) mod_sofia: change mod_sofia to use new core based recovery engine (r:2a8841ab) mod_sofia: fire-message-events profile param (r:9c06cb34) + mod_sofia: add send-display-update profile param to disable the update method (r:8f0c726b) mod_spidermonkey: add email function to js (r:37b36aea) freeswitch (1.2.1) From 363749c0dd7456b292be59b4ed0cfe810d730423 Mon Sep 17 00:00:00 2001 From: Michael S Collins Date: Thu, 20 Sep 2012 11:47:39 -0700 Subject: [PATCH 024/252] Additional 1.2.3 ChangeLog entries (Thanks Moy) --- docs/ChangeLog | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/docs/ChangeLog b/docs/ChangeLog index ae69a26e4c..9e03975eb9 100644 --- a/docs/ChangeLog +++ b/docs/ChangeLog @@ -3,10 +3,14 @@ freeswitch (1.2.3) core: update json lib in core and ESL and re-apply old patches (r:5a956890) core: add skip_cdr_causes variable to list call hangup causes that should not trigger cdr processing (r:3cf238fc) formats: add mod_mp4v2 for mp4 recording, most things are hardcodec, but it should work with 8000hz audio and H264 video (r:7e01bd10) + freetdm: M2UA Signaling gateway support (SIGTRAN) + freetdm: New TDM endpoint for raw IO access to boards (controllable channel) + freetdm: New dialplan paramters and SIP X headers to set ISUP message information elements + freetdm: Misc ISUP bug fixes libsofia: Fix DoS vulnerability in processing Route Header (r:016550f2/FS-4627) libtpl: add tpl to tree (r:4985a41f) mod_sofia: add transfer_to variable for call processing (r:1b2b4565) - + freeswitch (1.2.2) configuration: Add language config files for es-ES,es-MX,pt-BR,pt-PT (Thanks Francois Delawarde) (r:9cde99b4/FS-3003) core: move recovery engine up into the core (r:66677c94) From 5ecccf539da049a785808096a0641160555246a6 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Thu, 20 Sep 2012 15:57:08 -0500 Subject: [PATCH 025/252] FS-4637 please test and repost log --- src/mod/endpoints/mod_sofia/sofia.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/mod/endpoints/mod_sofia/sofia.c b/src/mod/endpoints/mod_sofia/sofia.c index 304ac668dd..f7f7bddead 100644 --- a/src/mod/endpoints/mod_sofia/sofia.c +++ b/src/mod/endpoints/mod_sofia/sofia.c @@ -5845,9 +5845,9 @@ static void sofia_handle_sip_r_invite(switch_core_session_t *session, int status sofia_clear_flag(tech_pvt, TFLAG_T38_PASSTHRU); } - if (switch_channel_test_flag(channel, CF_PROXY_MODE) || - switch_channel_test_flag(channel, CF_PROXY_MEDIA) || - (sofia_test_flag(tech_pvt, TFLAG_T38_PASSTHRU) && (has_t38 || status > 299))) { + if (status > 199 && (switch_channel_test_flag(channel, CF_PROXY_MODE) || + switch_channel_test_flag(channel, CF_PROXY_MEDIA) || + (sofia_test_flag(tech_pvt, TFLAG_T38_PASSTHRU) && (has_t38 || status > 299)))) { if (sofia_test_flag(tech_pvt, TFLAG_SENT_UPDATE)) { sofia_clear_flag_locked(tech_pvt, TFLAG_SENT_UPDATE); From 1a586474502925d4938fe7be3348b814adae38df Mon Sep 17 00:00:00 2001 From: Michael S Collins Date: Thu, 20 Sep 2012 16:24:26 -0700 Subject: [PATCH 026/252] ChangeLog update (thanks Seven Du\!) --- docs/ChangeLog | 1 - 1 file changed, 1 deletion(-) diff --git a/docs/ChangeLog b/docs/ChangeLog index 9e03975eb9..d73e3630af 100644 --- a/docs/ChangeLog +++ b/docs/ChangeLog @@ -22,7 +22,6 @@ freeswitch (1.2.2) mod_commands: add uuid_media_reneg api command to tell a channel to send a re-invite with optional list of new codecs (r:bfc46567) mod_dptools: mutex app (r:212953bc) mod_httapi: add cache param (r:a8b89bcc) - mod_shout: add mp3 codec for mp4 (r:084dac25) mod_sofia: change mod_sofia to use new core based recovery engine (r:2a8841ab) mod_sofia: fire-message-events profile param (r:9c06cb34) mod_sofia: add send-display-update profile param to disable the update method (r:8f0c726b) From 142374eaabcf5c7e88234c3cad5d5b5ebcdb4c93 Mon Sep 17 00:00:00 2001 From: Jeff Lenk Date: Thu, 20 Sep 2012 21:04:39 -0500 Subject: [PATCH 027/252] mod_enum windows fix for last commit --- src/mod/applications/mod_enum/mod_enum.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/mod/applications/mod_enum/mod_enum.c b/src/mod/applications/mod_enum/mod_enum.c index ae19bdb791..9835fda46d 100644 --- a/src/mod/applications/mod_enum/mod_enum.c +++ b/src/mod/applications/mod_enum/mod_enum.c @@ -163,7 +163,7 @@ static switch_status_t load_config(void) done: #ifdef _MSC_VER - if (!globals.server) { + if (!globals.nameserver[0]) { HKEY hKey; DWORD data_sz; char* buf; @@ -183,7 +183,7 @@ static switch_status_t load_config(void) buf[data_sz] = 0; } switch_replace_char(buf, ' ', 0, SWITCH_FALSE); /* only use the first entry ex "192.168.1.1 192.168.1.2" */ - globals.server = buf; + globals.nameserver[0] = buf; } } } From 1050d443a65ba4db724e5a934f0d2a1971c720a9 Mon Sep 17 00:00:00 2001 From: Giovanni Maruzzelli Date: Fri, 21 Sep 2012 10:37:26 +0200 Subject: [PATCH 028/252] test, please ignore --- src/mod/endpoints/mod_skypopen/README | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mod/endpoints/mod_skypopen/README b/src/mod/endpoints/mod_skypopen/README index ba5b0d9271..90314cda68 100644 --- a/src/mod/endpoints/mod_skypopen/README +++ b/src/mod/endpoints/mod_skypopen/README @@ -5,4 +5,4 @@ tricks and tweaks, possible problems at: http://wiki.freeswitch.org/wiki/Mod_skypopen_Skype_Endpoint_and_Trunk -< gmaruzz at gmail dot com > +mail to: < gmaruzz at gmail dot com > From ef9af7dc94b562901e138adf92fbd2f8f4701194 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Fri, 21 Sep 2012 10:15:45 -0500 Subject: [PATCH 029/252] FS-4636 --resolve I think this is an ok change so we'll push it. --- src/switch_ivr_originate.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/switch_ivr_originate.c b/src/switch_ivr_originate.c index 0b02d2ba2c..7cb296b1c6 100644 --- a/src/switch_ivr_originate.c +++ b/src/switch_ivr_originate.c @@ -1216,24 +1216,28 @@ static switch_status_t setup_ringback(originate_global_t *oglobals, originate_st } if (!ringback->asis) { + switch_codec_implementation_t peer_read_impl = { 0 }; + if (switch_test_flag(read_codec, SWITCH_CODEC_FLAG_PASSTHROUGH)) { switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(caller_channel), SWITCH_LOG_WARNING, "%s Ringback not supported in passthrough codec mode.\n", switch_channel_get_name(caller_channel)); switch_goto_status(SWITCH_STATUS_GENERR, end); } + switch_core_session_get_read_impl(originate_status[0].peer_session, &peer_read_impl); + if (switch_core_codec_init(write_codec, "L16", NULL, - read_codec->implementation->actual_samples_per_second, - read_codec->implementation->microseconds_per_packet / 1000, + peer_read_impl.actual_samples_per_second, + peer_read_impl.microseconds_per_packet / 1000, 1, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE, NULL, switch_core_session_get_pool(oglobals->session)) == SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(oglobals->session), SWITCH_LOG_DEBUG, "Raw Codec Activation Success L16@%uhz 1 channel %dms\n", - read_codec->implementation->actual_samples_per_second, read_codec->implementation->microseconds_per_packet / 1000); + peer_read_impl.actual_samples_per_second, peer_read_impl.microseconds_per_packet / 1000); write_frame->codec = write_codec; write_frame->datalen = read_codec->implementation->decoded_bytes_per_packet; write_frame->samples = write_frame->datalen / 2; From 9c97ae3cccf96fcfb302c520afad7eb1f607d536 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Fri, 21 Sep 2012 14:45:30 -0500 Subject: [PATCH 030/252] FS-4640 please test --- src/mod/endpoints/mod_sofia/mod_sofia.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mod/endpoints/mod_sofia/mod_sofia.c b/src/mod/endpoints/mod_sofia/mod_sofia.c index aa3f3207d5..b7450e4e47 100644 --- a/src/mod/endpoints/mod_sofia/mod_sofia.c +++ b/src/mod/endpoints/mod_sofia/mod_sofia.c @@ -2600,7 +2600,7 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi switch_core_session_pass_indication(session, SWITCH_MESSAGE_INDICATE_ANSWER); } } else { - if (msg->numeric_arg) { + if (msg->numeric_arg && !(switch_channel_test_flag(channel, CF_ANSWERED) && code == 488)) { if (code > 399) { switch_call_cause_t cause = sofia_glue_sip_cause_to_freeswitch(code); if (code == 401 || cause == 407) cause = SWITCH_CAUSE_USER_CHALLENGE; From 3439d1b3b4f4b561f45eed1d67fc709ced1c107b Mon Sep 17 00:00:00 2001 From: William King Date: Sat, 22 Sep 2012 18:53:27 -0700 Subject: [PATCH 031/252] FS-4305: --resolve When libvlc is unable to decode the audio fast enough for the local stream player, use multiple very quick 1 sample chunks of silence to fill in while libvlc catches up. --- src/mod/formats/mod_vlc/mod_vlc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/mod/formats/mod_vlc/mod_vlc.c b/src/mod/formats/mod_vlc/mod_vlc.c index 592acb1ff0..d5b5ec336d 100644 --- a/src/mod/formats/mod_vlc/mod_vlc.c +++ b/src/mod/formats/mod_vlc/mod_vlc.c @@ -275,8 +275,8 @@ static switch_status_t vlc_file_read(switch_file_handle_t *handle, void *data, s if (!read && (status == 5 || status == 6)) { return SWITCH_STATUS_FALSE; } else if (!read) { - read = 2000; - memset(data, 255, read); + read = 2; + memset(data, 0, read); } if (read) From 72baa97369618698ec649fece8629d12afae46de Mon Sep 17 00:00:00 2001 From: Travis Cross Date: Fri, 21 Sep 2012 18:04:41 +0000 Subject: [PATCH 032/252] Condense the humanized FS version string Old: FreeSWITCH Version 1.3.0+git~20120916T192130Z~3b5aa066c7 (1.3.0; git at commit 3b5aa066c7 on Sun, 16 Sep 2012 19:21:30 Z) New: FreeSWITCH Version 1.3.0+git~20120916T192130Z~3b5aa066c7 (git 3b5aa06 2012-09-16 19:21:30Z) --- build/print_git_revision.c | 10 +++++----- src/include/switch_version.h.cmake | 2 +- src/include/switch_version.h.template | 2 +- src/mod/applications/mod_commands/mod_commands.c | 2 +- src/switch.c | 2 +- src/switch_core.c | 2 +- 6 files changed, 10 insertions(+), 10 deletions(-) diff --git a/build/print_git_revision.c b/build/print_git_revision.c index 0f8e680b37..974ba6ca3a 100644 --- a/build/print_git_revision.c +++ b/build/print_git_revision.c @@ -69,15 +69,15 @@ static int print_human_version(void) { if ((sys1(xdate,sizeof(xdate),"git log -n1 --format='%ct' HEAD"))) return 1; xdate_t=(time_t)atoi(xdate); if (!(xdate_tm=gmtime(&xdate_t))) return 1; - strftime(xfdate,sizeof(xfdate),"%a, %d %b %Y %H:%M:%S Z",xdate_tm); - if ((sys1(xcommit,sizeof(xcommit),"git rev-list -n1 --abbrev=10 --abbrev-commit HEAD"))) + strftime(xfdate,sizeof(xfdate),"%Y-%m-%d %H:%M:%SZ",xdate_tm); + if ((sys1(xcommit,sizeof(xcommit),"git rev-list -n1 --abbrev=7 --abbrev-commit HEAD"))) return 1; - snprintf(xver,sizeof(xver),"; git at commit %s on %s",xcommit,xfdate); + snprintf(xver,sizeof(xver),"git %s %s",xcommit,xfdate); if (show_unclean && (sys(NULL,0,"git diff-index --quiet HEAD"))) { char buf[256], now[256]; time_t now_t=time(NULL); struct tm *now_tm; if (!(now_tm=gmtime(&now_t))) return 1; - strftime(now,sizeof(now),"%a, %d %b %Y %H:%M:%S Z",now_tm); - snprintf(buf,sizeof(buf),"%s; unclean git build on %s",xver,now); + strftime(now,sizeof(now),"%Y-%m-%d %H:%M:%SZ",now_tm); + snprintf(buf,sizeof(buf),"%s unclean %s",xver,now); strncpy(xver,buf,sizeof(xver)); } printf("%s\n",xver); diff --git a/src/include/switch_version.h.cmake b/src/include/switch_version.h.cmake index c722c2221d..6e7f2036e6 100644 --- a/src/include/switch_version.h.cmake +++ b/src/include/switch_version.h.cmake @@ -43,7 +43,7 @@ extern "C" { #define SWITCH_VERSION_REVISION "@Project_WC_REVISION@" #define SWITCH_VERSION_REVISION_HUMAN "@Project_WC_REVISION@" #define SWITCH_VERSION_FULL SWITCH_VERSION_MAJOR "." SWITCH_VERSION_MINOR "." SWITCH_VERSION_MICRO SWITCH_VERSION_REVISION -#define SWITCH_VERSION_FULL_HUMAN SWITCH_VERSION_MAJOR "." SWITCH_VERSION_MINOR "." SWITCH_VERSION_MICRO SWITCH_VERSION_REVISION_HUMAN +#define SWITCH_VERSION_FULL_HUMAN SWITCH_VERSION_MAJOR "." SWITCH_VERSION_MINOR "." SWITCH_VERSION_MICRO " " SWITCH_VERSION_REVISION_HUMAN #ifdef __cplusplus } diff --git a/src/include/switch_version.h.template b/src/include/switch_version.h.template index dfec6e091e..2e253dc69f 100644 --- a/src/include/switch_version.h.template +++ b/src/include/switch_version.h.template @@ -43,7 +43,7 @@ extern "C" { #define SWITCH_VERSION_REVISION "@SWITCH_VERSION_REVISION@" #define SWITCH_VERSION_REVISION_HUMAN "@SWITCH_VERSION_REVISION_HUMAN@" #define SWITCH_VERSION_FULL SWITCH_VERSION_MAJOR "." SWITCH_VERSION_MINOR "." SWITCH_VERSION_MICRO SWITCH_VERSION_REVISION -#define SWITCH_VERSION_FULL_HUMAN SWITCH_VERSION_MAJOR "." SWITCH_VERSION_MINOR "." SWITCH_VERSION_MICRO SWITCH_VERSION_REVISION_HUMAN +#define SWITCH_VERSION_FULL_HUMAN SWITCH_VERSION_MAJOR "." SWITCH_VERSION_MINOR "." SWITCH_VERSION_MICRO " " SWITCH_VERSION_REVISION_HUMAN #ifdef __cplusplus } diff --git a/src/mod/applications/mod_commands/mod_commands.c b/src/mod/applications/mod_commands/mod_commands.c index 0a6c1d08ce..d823af7194 100644 --- a/src/mod/applications/mod_commands/mod_commands.c +++ b/src/mod/applications/mod_commands/mod_commands.c @@ -286,7 +286,7 @@ SWITCH_STANDARD_API(shutdown_function) SWITCH_STANDARD_API(version_function) { - stream->write_function(stream, "FreeSWITCH Version %s (%s)\n", SWITCH_VERSION_FULL, SWITCH_VERSION_FULL_HUMAN); + stream->write_function(stream, "FreeSWITCH Version %s (%s)\n", SWITCH_VERSION_FULL, SWITCH_VERSION_REVISION_HUMAN); return SWITCH_STATUS_SUCCESS; } diff --git a/src/switch.c b/src/switch.c index e1b602356e..4f8678a97f 100644 --- a/src/switch.c +++ b/src/switch.c @@ -577,7 +577,7 @@ int main(int argc, char *argv[]) } else if (!strcmp(local_argv[x], "-version")) { - fprintf(stdout, "FreeSWITCH version: %s (%s)\n", SWITCH_VERSION_FULL, SWITCH_VERSION_FULL_HUMAN); + fprintf(stdout, "FreeSWITCH version: %s (%s)\n", SWITCH_VERSION_FULL, SWITCH_VERSION_REVISION_HUMAN); exit(EXIT_SUCCESS); } #endif diff --git a/src/switch_core.c b/src/switch_core.c index 2a9bec7dee..ec313ea2fb 100644 --- a/src/switch_core.c +++ b/src/switch_core.c @@ -2013,7 +2013,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_init_and_modload(switch_core_flag_t switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "\nFreeSWITCH Version %s (%s) Started.\nMax Sessions[%u]\nSession Rate[%d]\nSQL [%s]\n", - SWITCH_VERSION_FULL, SWITCH_VERSION_FULL_HUMAN, + SWITCH_VERSION_FULL, SWITCH_VERSION_REVISION_HUMAN, switch_core_session_limit(0), switch_core_sessions_per_second(0), switch_test_flag((&runtime), SCF_USE_SQL) ? "Enabled" : "Disabled"); From d98bb16b3dbcd30a8cb22806ec43ef4dbee2794f Mon Sep 17 00:00:00 2001 From: Travis Cross Date: Fri, 21 Sep 2012 18:22:48 +0000 Subject: [PATCH 033/252] debian: Ensure date is calculated in UTC --- debian/util.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/debian/util.sh b/debian/util.sh index b270dbd2f8..b15d918378 100755 --- a/debian/util.sh +++ b/debian/util.sh @@ -140,7 +140,7 @@ get_last_release_ver () { get_nightly_version () { local commit="$(git rev-list -n1 --abbrev=10 --abbrev-commit HEAD)" - echo "$(get_last_release_ver)+git~$(date +%Y%m%dT%H%M%SZ)~$commit" + echo "$(get_last_release_ver)+git~$(date -u +%Y%m%dT%H%M%SZ)~$commit" } create_orig () { From 5fd7643ab125d20b2268371373cf2444deb8a712 Mon Sep 17 00:00:00 2001 From: Travis Cross Date: Sun, 23 Sep 2012 07:47:57 +0000 Subject: [PATCH 034/252] debian: style --- debian/util.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/debian/util.sh b/debian/util.sh index b15d918378..717a78364e 100755 --- a/debian/util.sh +++ b/debian/util.sh @@ -140,7 +140,7 @@ get_last_release_ver () { get_nightly_version () { local commit="$(git rev-list -n1 --abbrev=10 --abbrev-commit HEAD)" - echo "$(get_last_release_ver)+git~$(date -u +%Y%m%dT%H%M%SZ)~$commit" + echo "$(get_last_release_ver)+git~$(date -u '+%Y%m%dT%H%M%SZ')~$commit" } create_orig () { From 53c24a93e08ab9db9b7514c6a0bb17cc4e8e32d5 Mon Sep 17 00:00:00 2001 From: Travis Cross Date: Fri, 21 Sep 2012 18:27:13 +0000 Subject: [PATCH 035/252] debian: Add support for humanized version string --- build/set-fs-version.sh | 3 ++- debian/util.sh | 14 ++++++++++---- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/build/set-fs-version.sh b/build/set-fs-version.sh index 6743b58b5f..acac71db60 100755 --- a/build/set-fs-version.sh +++ b/build/set-fs-version.sh @@ -8,9 +8,10 @@ sdir="." check_pwd check_input_ver_build $@ in_ver="$1" +in_hrev="$2" if [ "$in_ver" = "auto" ]; then in_ver="$(cat build/next-release.txt)" fi eval $(parse_version "$in_ver") -set_fs_ver "$gver" "$gmajor" "$gminor" "$gmicro" "$grev" +set_fs_ver "$gver" "$gmajor" "$gminor" "$gmicro" "$grev" "$in_hrev" diff --git a/debian/util.sh b/debian/util.sh index 717a78364e..43278c2920 100755 --- a/debian/util.sh +++ b/debian/util.sh @@ -143,11 +143,15 @@ get_nightly_version () { echo "$(get_last_release_ver)+git~$(date -u '+%Y%m%dT%H%M%SZ')~$commit" } +get_nightly_revision_human () { + echo "git $(git rev-list -n1 --abbrev=7 --abbrev-commit HEAD) $(date -u '+%Y-%m-%d %H:%M:%SZ')" +} + create_orig () { { set -e local OPTIND OPTARG - local uver="" bundle_deps=false zl=9e + local uver="" hrev="" bundle_deps=false zl=9e while getopts 'bnv:z:' o "$@"; do case "$o" in b) bundle_deps=true;; @@ -157,8 +161,10 @@ create_orig () { esac done shift $(($OPTIND-1)) - [ -z "$uver" ] || [ "$uver" = "nightly" ] \ - && uver="$(get_nightly_version)" + if [ -z "$uver" ] || [ "$uver" = "nightly" ]; then + uver="$(get_nightly_version)" + hrev="$(get_nightly_revision_human)" + fi local treeish="$1" dver="$(mk_dver "$uver")" local orig="../freeswitch_$dver.orig.tar.xz" [ -n "$treeish" ] || treeish="HEAD" @@ -175,7 +181,7 @@ create_orig () { (cd libs && getlibs) git add -f libs fi - ./build/set-fs-version.sh "$uver" && git add configure.in + ./build/set-fs-version.sh "$uver" "$hrev" && git add configure.in echo "$uver" > .version && git add -f .version git commit --allow-empty -m "nightly v$uver" git archive -v \ From fb2ffbafe29beaf5c2b148e0131307e8569886ef Mon Sep 17 00:00:00 2001 From: Travis Cross Date: Sat, 22 Sep 2012 19:05:18 +0000 Subject: [PATCH 036/252] Add configure flags to moderate the ClueCon nags The default remains the same: we show the huge ClueCon nag banner on startup and in fs_cli. However, if you pass --disable-huge-cluecon-nag, no banner will be shown. If you pass --enable-modest-cluecon-nag, a modest text-based ClueCon reminder will be shown instead. --- Makefile.am | 18 ++++++++++-------- build/Makefile.am | 4 ++-- configure.in | 22 +++++++++++++++++++++- libs/esl/fs_cli.c | 10 +++++----- libs/esl/src/include/cc.h | 6 ++++++ src/include/cc.h | 6 ++++++ src/switch_core.c | 6 +++++- 7 files changed, 55 insertions(+), 17 deletions(-) diff --git a/Makefile.am b/Makefile.am index e7f1f799a5..cdf20f55c0 100644 --- a/Makefile.am +++ b/Makefile.am @@ -311,7 +311,7 @@ bin_PROGRAMS = freeswitch fs_cli fs_ivrd tone2wav fs_encode ## fs_cli_SOURCES = libs/esl/src/esl.c libs/esl/src/esl_config.c libs/esl/src/esl_event.c \ libs/esl/src/esl_threadmutex.c libs/esl/fs_cli.c libs/esl/src/esl_json.c libs/esl/src/esl_buffer.c -fs_cli_CFLAGS = $(AM_CFLAGS) -I$(switch_srcdir)/libs/esl/src/include +fs_cli_CFLAGS = $(AM_CFLAGS) -I$(switch_srcdir)/libs/esl/src/include -include src/include/switch_private.h fs_cli_LDFLAGS = $(AM_LDFLAGS) -lpthread $(ESL_LDFLAGS) -lm if HAVE_LIBEDIT @@ -660,13 +660,15 @@ sofia-reconf: cd libs/sofia-sip && ./configure --prefix=$(prefix) --with-pic --with-glib=no --disable-shared cluecon: - @clear - @echo Thank you for updating. This is going to take a while so relax. - @echo Now would be a good time to register for ClueCon! - @cat cluecon2.tmpl - @echo - @echo http://www.cluecon.com - @sleep 5 + @if $(ENABLE_CLUECON_NAG); then \ + clear; \ + echo "Thank you for updating. This is going to take a while so relax."; \ + echo "Now would be a good time to register for ClueCon!"; \ + cat cluecon2.tmpl; \ + echo; \ + echo "http://www.cluecon.com"; \ + sleep 5; \ + fi current: cluecon update-clean is-scm $(MAKE) update $(MAKE) all diff --git a/build/Makefile.am b/build/Makefile.am index 3feb22157d..fa5a257a5f 100644 --- a/build/Makefile.am +++ b/build/Makefile.am @@ -11,7 +11,7 @@ all: @echo " + http://www.cluecon.com +" @echo " + +" @echo " +-----------------------------------------------+" - @cat ../cluecon2.tmpl + @-$(ENABLE_CLUECON_NAG) && cat ../cluecon2.tmpl install: @echo " +---------- FreeSWITCH install Complete ----------+" @@ -69,7 +69,7 @@ install: @echo " + http://www.cluecon.com +" @echo " + +" @echo " +-------------------------------------------------+" - @cat ../cluecon2.tmpl + @-$(ENABLE_CLUECON_NAG) && cat ../cluecon2.tmpl .PHONY: check dvi html info install-data \ diff --git a/configure.in b/configure.in index 5a97b86ace..926706ed78 100644 --- a/configure.in +++ b/configure.in @@ -330,6 +330,26 @@ if test "x${enable_visibility}" != "xno" ; then fi fi +# Enable ClueCon nag banner (default: on) +AC_ARG_ENABLE(huge-cluecon-nag, +[AC_HELP_STRING([--disable-huge-cluecon-nag],[build without huge ClueCon banners])], +[enable_huge_cluecon_nag="$enableval"],[enable_huge_cluecon_nag="yes"]) + +AC_ARG_ENABLE(modest-cluecon-nag, +[AC_HELP_STRING([--enable-modest-cluecon-nag],[build with modest ClueCon announcements])], +[enable_modest_cluecon_nag="$enableval"],[enable_modest_cluecon_nag="no"]) + +if test "${enable_modest_cluecon_nag}" = "yes"; then + enable_huge_cluecon_nag="no" + AC_DEFINE([SHOW_MODEST_CLUECON_NAG],[1],[Show modest ClueCon nag messages.]) + AC_SUBST([ENABLE_CLUECON_NAG],[false]) +elif test "${enable_huge_cluecon_nag}" = "yes"; then + AC_DEFINE([SHOW_HUGE_CLUECON_NAG],[1],[Show huge ClueCon nag messages.]) + AC_SUBST([ENABLE_CLUECON_NAG],[true]) +else + AC_SUBST([ENABLE_CLUECON_NAG],[false]) +fi + # Enable debugging (default: on) # (rename option if the default is changed) AC_ARG_ENABLE(debug, @@ -1115,7 +1135,7 @@ AC_OUTPUT ## ## Registering for ClueCon ## -if ! test -f noreg ; then +if ! test -f noreg && test "${enable_huge_cluecon_nag}" = "yes" ; then echo "" echo "" echo $ECHO_N "Registering you for ClueCon http://www.cluecon.com $ECHO_C" 1>&6 diff --git a/libs/esl/fs_cli.c b/libs/esl/fs_cli.c index 95629da76e..03d8e351d1 100644 --- a/libs/esl/fs_cli.c +++ b/libs/esl/fs_cli.c @@ -931,17 +931,17 @@ static void print_banner(FILE *stream) WriteFile(hStdout, banner, (DWORD) strlen(banner), NULL, NULL); WriteFile(hStdout, cc, (DWORD) strlen(cc), NULL, NULL); SetConsoleTextAttribute(hStdout, wOldColorAttrs); - /* Print the rest info in default colors */ fprintf(stream, "\n%s\n", inf); -#else - fprintf(stream, - "%s%s%s%s%s%s\n%s\n", +#elif SHOW_HUGE_CLUECON_NAG + fprintf(stream, "%s%s%s%s%s%s\n%s\n", ESL_SEQ_DEFAULT_COLOR, ESL_SEQ_FYELLOW, ESL_SEQ_BBLUE, banner, cc, ESL_SEQ_DEFAULT_COLOR, inf); - + fprintf(stream, "%s", output_text_color); +#else + fprintf(stream, "%s%s%s\n%s\n", ESL_SEQ_DEFAULT_COLOR, banner, cc, inf); fprintf(stream, "%s", output_text_color); #endif } diff --git a/libs/esl/src/include/cc.h b/libs/esl/src/include/cc.h index 44666193c6..6387209c6b 100644 --- a/libs/esl/src/include/cc.h +++ b/libs/esl/src/include/cc.h @@ -1,2 +1,8 @@ +#ifdef SHOW_HUGE_CLUECON_NAG const char *cc = ".========================================================================================================.\n| ____ _____ ____ _ ____ _ _ _____ |\n| / ___|___ _ __ ___ ___ |_ _|__ / ___| |_ _ ___ / ___|___ _ __ ( ) |___ / |\n| | | / _ \\| '_ ` _ \\ / _ \\ | |/ _ \\ | | | | | | |/ _ \\ | / _ \\| '_ \\ |/| | |_ \\ |\n| | |__| (_) | | | | | | __/ | | (_) | | |___| | |_| | __/ |__| (_) | | | | | |___) | |\n| \\____\\___/|_| |_| |_|\\___| |_|\\___/ \\____|_|\\__,_|\\___|\\____\\___/|_| |_| |_|____/ |\n| |\n| ____ _ _ _ _ ____ _ |\n| / ___| |__ (_) ___ __ _ __ _ ___ | | | / ___| / \\ |\n| | | | '_ \\| |/ __/ _` |/ _` |/ _ \\ | | | \\___ \\ / _ \\ |\n| | |___| | | | | (_| (_| | (_| | (_) | | |_| |___) / ___ \\ |\n| \\____|_| |_|_|\\___\\__,_|\\__, |\\___( ) \\___/|____/_/ \\_\\ |\n| |___/ |/ |\n| _ _ __ _ _ ___ _ _ ____ ___ _ _____ |\n| / \\ _ _ __ _ _ _ ___| |_ / /_ | |_| |__ ( _ )| |_| |__ |___ \\ / _ \\/ |___ / |\n| / _ \\| | | |/ _` | | | / __| __| | '_ \\| __| '_ \\ _____ / _ \\| __| '_ \\ __) | | | | | |_ \\ |\n| / ___ \\ |_| | (_| | |_| \\__ \\ |_ | (_) | |_| | | | |_____| | (_) | |_| | | | / __/| |_| | |___) | |\n| /_/ \\_\\__,_|\\__, |\\__,_|___/\\__| \\___/ \\__|_| |_| \\___/ \\__|_| |_| |_____|\\___/|_|____/ |\n| |___/ |\n| _ |\n| __ ____ ____ __ ___| |_ _ ___ ___ ___ _ __ ___ ___ _ __ ___ |\n| \\ \\ /\\ / /\\ \\ /\\ / /\\ \\ /\\ / / / __| | | | |/ _ \\/ __/ _ \\| '_ \\ / __/ _ \\| '_ ` _ \\ |\n| \\ V V / \\ V V / \\ V V / _ | (__| | |_| | __/ (_| (_) | | | | _ | (_| (_) | | | | | | |\n| \\_/\\_/ \\_/\\_/ \\_/\\_/ (_) \\___|_|\\__,_|\\___|\\___\\___/|_| |_| (_) \\___\\___/|_| |_| |_| |\n| |\n.========================================================================================================.\n"; +#elif SHOW_MODEST_CLUECON_NAG +const char *cc = "Come to ClueCon '13 August 6-8th, 2013, Chicago, USA\nwww.cluecon.com\n"; +#else +const char *cc = ""; +#endif diff --git a/src/include/cc.h b/src/include/cc.h index 44666193c6..6387209c6b 100644 --- a/src/include/cc.h +++ b/src/include/cc.h @@ -1,2 +1,8 @@ +#ifdef SHOW_HUGE_CLUECON_NAG const char *cc = ".========================================================================================================.\n| ____ _____ ____ _ ____ _ _ _____ |\n| / ___|___ _ __ ___ ___ |_ _|__ / ___| |_ _ ___ / ___|___ _ __ ( ) |___ / |\n| | | / _ \\| '_ ` _ \\ / _ \\ | |/ _ \\ | | | | | | |/ _ \\ | / _ \\| '_ \\ |/| | |_ \\ |\n| | |__| (_) | | | | | | __/ | | (_) | | |___| | |_| | __/ |__| (_) | | | | | |___) | |\n| \\____\\___/|_| |_| |_|\\___| |_|\\___/ \\____|_|\\__,_|\\___|\\____\\___/|_| |_| |_|____/ |\n| |\n| ____ _ _ _ _ ____ _ |\n| / ___| |__ (_) ___ __ _ __ _ ___ | | | / ___| / \\ |\n| | | | '_ \\| |/ __/ _` |/ _` |/ _ \\ | | | \\___ \\ / _ \\ |\n| | |___| | | | | (_| (_| | (_| | (_) | | |_| |___) / ___ \\ |\n| \\____|_| |_|_|\\___\\__,_|\\__, |\\___( ) \\___/|____/_/ \\_\\ |\n| |___/ |/ |\n| _ _ __ _ _ ___ _ _ ____ ___ _ _____ |\n| / \\ _ _ __ _ _ _ ___| |_ / /_ | |_| |__ ( _ )| |_| |__ |___ \\ / _ \\/ |___ / |\n| / _ \\| | | |/ _` | | | / __| __| | '_ \\| __| '_ \\ _____ / _ \\| __| '_ \\ __) | | | | | |_ \\ |\n| / ___ \\ |_| | (_| | |_| \\__ \\ |_ | (_) | |_| | | | |_____| | (_) | |_| | | | / __/| |_| | |___) | |\n| /_/ \\_\\__,_|\\__, |\\__,_|___/\\__| \\___/ \\__|_| |_| \\___/ \\__|_| |_| |_____|\\___/|_|____/ |\n| |___/ |\n| _ |\n| __ ____ ____ __ ___| |_ _ ___ ___ ___ _ __ ___ ___ _ __ ___ |\n| \\ \\ /\\ / /\\ \\ /\\ / /\\ \\ /\\ / / / __| | | | |/ _ \\/ __/ _ \\| '_ \\ / __/ _ \\| '_ ` _ \\ |\n| \\ V V / \\ V V / \\ V V / _ | (__| | |_| | __/ (_| (_) | | | | _ | (_| (_) | | | | | | |\n| \\_/\\_/ \\_/\\_/ \\_/\\_/ (_) \\___|_|\\__,_|\\___|\\___\\___/|_| |_| (_) \\___\\___/|_| |_| |_| |\n| |\n.========================================================================================================.\n"; +#elif SHOW_MODEST_CLUECON_NAG +const char *cc = "Come to ClueCon '13 August 6-8th, 2013, Chicago, USA\nwww.cluecon.com\n"; +#else +const char *cc = ""; +#endif diff --git a/src/switch_core.c b/src/switch_core.c index ec313ea2fb..27e1717916 100644 --- a/src/switch_core.c +++ b/src/switch_core.c @@ -2002,12 +2002,16 @@ SWITCH_DECLARE(switch_status_t) switch_core_init_and_modload(switch_core_flag_t #ifdef WIN32 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "%s%s\n\n", switch_core_banner(), cc); -#else +#elif SHOW_HUGE_CLUECON_NAG switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "%s%s%s%s%s%s\n\n", SWITCH_SEQ_DEFAULT_COLOR, SWITCH_SEQ_FYELLOW, SWITCH_SEQ_BBLUE, switch_core_banner(), cc, SWITCH_SEQ_DEFAULT_COLOR); +#else + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "%s%s%s\n\n", + SWITCH_SEQ_DEFAULT_COLOR, + switch_core_banner(), cc); #endif From 6f9467992ac8d8435d312a3d78091e66578ab6a6 Mon Sep 17 00:00:00 2001 From: Travis Cross Date: Sat, 22 Sep 2012 19:07:30 +0000 Subject: [PATCH 037/252] Use the modest ClueCon nag for Debian builds --- debian/rules | 1 + 1 file changed, 1 insertion(+) diff --git a/debian/rules b/debian/rules index cd7934e439..8c9f284341 100755 --- a/debian/rules +++ b/debian/rules @@ -64,6 +64,7 @@ override_dh_auto_clean: --host=$(DEB_HOST_GNU_TYPE) --build=$(DEB_BUILD_GNU_TYPE) \ --with-gnu-ld --with-python --with-erlang --with-openssl \ --enable-core-odbc-support --enable-zrtp \ + --enable-modest-cluecon-nag \ --prefix=/usr --localstatedir=/var \ --sysconfdir=/etc/freeswitch \ --with-modinstdir=/usr/lib/freeswitch/mod \ From 59d3823ed25c0173665aff871cfe20f02fcefbf1 Mon Sep 17 00:00:00 2001 From: Travis Cross Date: Sat, 22 Sep 2012 22:46:36 +0000 Subject: [PATCH 038/252] Update .gitignore --- libs/.gitignore | 16 ++++++++++++++++ src/mod/.gitignore | 4 ++++ 2 files changed, 20 insertions(+) diff --git a/libs/.gitignore b/libs/.gitignore index 5b0f00bde8..1bc99bcab9 100644 --- a/libs/.gitignore +++ b/libs/.gitignore @@ -341,6 +341,19 @@ opal /libsndfile/tests/test_wrapper.sh /libsndfile/Win32/Makefile /libsndfile/Win32/Makefile.in +/libwebsockets/Makefile +/libwebsockets/Makefile.in +/libwebsockets/config.h +/libwebsockets/lib/Makefile +/libwebsockets/lib/Makefile.in +/libwebsockets/m4/libtool.m4 +/libwebsockets/m4/ltoptions.m4 +/libwebsockets/m4/ltsugar.m4 +/libwebsockets/m4/ltversion.m4 +/libwebsockets/m4/lt~obsolete.m4 +/libwebsockets/stamp-h1 +/libwebsockets/test-server/Makefile +/libwebsockets/test-server/Makefile.in /mongo-cxx-driver-v*/ /mpg123/ /openldap-*/ @@ -678,6 +691,9 @@ opal /srtp/Makefile.in /srtp/test/Makefile /srtp/test/Makefile.in +/tiff-*/build/Makefile +/tiff-*/build/Makefile.in +/tiff-*/tools/tiffcrop /tiff-*/contrib/acorn/Makefile /tiff-*/contrib/acorn/Makefile.in /tiff-*/contrib/addtiffo/addtiffo diff --git a/src/mod/.gitignore b/src/mod/.gitignore index af97a2c162..1aa253520e 100644 --- a/src/mod/.gitignore +++ b/src/mod/.gitignore @@ -16,6 +16,7 @@ /applications/mod_fsv/Makefile /applications/mod_httapi/Makefile /applications/mod_limit/Makefile +/applications/mod_random/Makefile /applications/mod_sms/Makefile /applications/mod_spandsp/Makefile /applications/mod_spandsp/Makefile.in @@ -29,6 +30,8 @@ /asr_tts/mod_unimrcp/Makefile.in /asr_tts/mod_unimrcp/mod_unimrcp.log /asr_tts/mod_flite/*/*/mod_flite_manifest.rc +/codecs/mod_skel_codec/Makefile +/codecs/mod_vp8/Makefile /dialplans/mod_dialplan_asterisk/Makefile /dialplans/mod_dialplan_xml/Makefile /endpoints/mod_portaudio/Makefile @@ -66,6 +69,7 @@ /loggers/mod_logfile/Makefile /loggers/mod_syslog/Makefile /say/mod_say_en/Makefile +/say/mod_say_fa/Makefile /say/mod_say_ja/Makefile /say/mod_say_ru/Makefile /timers/mod_posix_timer/Makefile From 2dc709981b3084a071cc22cd3b56c0ec61296080 Mon Sep 17 00:00:00 2001 From: Travis Cross Date: Sun, 23 Sep 2012 00:01:29 +0000 Subject: [PATCH 039/252] Add configure option to skip subdirectories If you pass --enable-skip-subdirectories then configure will skip configuring or reconfiguring libraries and simply configure the FS core itself. --- configure.in | 68 ++++++++++++++++++++++++++++------------------------ 1 file changed, 37 insertions(+), 31 deletions(-) diff --git a/configure.in b/configure.in index 926706ed78..fdef3735ca 100644 --- a/configure.in +++ b/configure.in @@ -330,6 +330,11 @@ if test "x${enable_visibility}" != "xno" ; then fi fi +# Option to skip configuration of subdirectories +AC_ARG_ENABLE(skip-subdirectories, +[AC_HELP_STRING([--enable-skip-subdirectories],[skip configuration of subdirectories])], +[enable_skip_subdirectories="$enableval"],[enable_skip_subdirectories="no"]) + # Enable ClueCon nag banner (default: on) AC_ARG_ENABLE(huge-cluecon-nag, [AC_HELP_STRING([--disable-huge-cluecon-nag],[build without huge ClueCon banners])], @@ -1089,39 +1094,40 @@ ac_configure_args="$ac_configure_args CONFIGURE_CFLAGS='$CFLAGS' CONFIGURE_CXXFL # --localstatedir='$localstatedir' --datadir='$datadir'" # Run configure in all the subdirs -AC_CONFIG_SUBDIRS([libs/srtp]) -AC_CONFIG_SUBDIRS([libs/sqlite]) -if test "$enable_core_libedit_support" = "yes" ; then - AC_CONFIG_SUBDIRS([libs/libedit]) +if ! test "${enable_skip_subdirectories}" = "yes"; then + AC_CONFIG_SUBDIRS([libs/srtp]) + AC_CONFIG_SUBDIRS([libs/sqlite]) + if test "$enable_core_libedit_support" = "yes" ; then + AC_CONFIG_SUBDIRS([libs/libedit]) + fi + AC_CONFIG_SUBDIRS([libs/pcre]) + AC_CONFIG_SUBDIRS([libs/apr]) + AC_CONFIG_SUBDIRS([libs/apr-util]) + AC_CONFIG_SUBDIRS([libs/ilbc]) + AC_CONFIG_SUBDIRS([libs/curl]) + AC_CONFIG_SUBDIRS([libs/iksemel]) + AC_CONFIG_SUBDIRS([libs/js/nsprpub]) + AC_CONFIG_SUBDIRS([libs/js]) + AC_CONFIG_SUBDIRS([libs/libdingaling]) + AC_CONFIG_SUBDIRS([libs/libsndfile]) + AC_CONFIG_SUBDIRS([libs/sofia-sip]) + AC_CONFIG_SUBDIRS([libs/speex]) + AC_CONFIG_SUBDIRS([libs/portaudio]) + AC_CONFIG_SUBDIRS([libs/openzap]) + AC_CONFIG_SUBDIRS([libs/freetdm]) + AC_CONFIG_SUBDIRS([libs/unimrcp]) + AC_CONFIG_SUBDIRS([libs/tiff-4.0.2]) + AC_CONFIG_SUBDIRS([libs/spandsp]) + AC_CONFIG_SUBDIRS([libs/broadvoice]) + AC_CONFIG_SUBDIRS([libs/libg722_1]) + AC_CONFIG_SUBDIRS([libs/silk]) + AC_CONFIG_SUBDIRS([libs/libcodec2]) + if test "x${enable_zrtp}" = "xyes"; then + AC_CONFIG_SUBDIRS([libs/libzrtp/projects/gnu]) + fi + AC_CONFIG_SUBDIRS([libs/libwebsockets]) fi -AC_CONFIG_SUBDIRS([libs/pcre]) -AC_CONFIG_SUBDIRS([libs/apr]) -AC_CONFIG_SUBDIRS([libs/apr-util]) -AC_CONFIG_SUBDIRS([libs/ilbc]) -AC_CONFIG_SUBDIRS([libs/curl]) -AC_CONFIG_SUBDIRS([libs/iksemel]) -AC_CONFIG_SUBDIRS([libs/js/nsprpub]) -AC_CONFIG_SUBDIRS([libs/js]) -AC_CONFIG_SUBDIRS([libs/libdingaling]) -AC_CONFIG_SUBDIRS([libs/libsndfile]) -AC_CONFIG_SUBDIRS([libs/sofia-sip]) -AC_CONFIG_SUBDIRS([libs/speex]) -AC_CONFIG_SUBDIRS([libs/portaudio]) -AC_CONFIG_SUBDIRS([libs/openzap]) -AC_CONFIG_SUBDIRS([libs/freetdm]) -AC_CONFIG_SUBDIRS([libs/unimrcp]) -AC_CONFIG_SUBDIRS([libs/tiff-4.0.2]) -AC_CONFIG_SUBDIRS([libs/spandsp]) -AC_CONFIG_SUBDIRS([libs/broadvoice]) -AC_CONFIG_SUBDIRS([libs/libg722_1]) -AC_CONFIG_SUBDIRS([libs/silk]) -AC_CONFIG_SUBDIRS([libs/libcodec2]) -if test "x${enable_zrtp}" = "xyes"; then - AC_CONFIG_SUBDIRS([libs/libzrtp/projects/gnu]) -fi -AC_CONFIG_SUBDIRS([libs/libwebsockets]) - case $host in *-openbsd*) # libtool won't link static libs against shared ones on OpenBSD unless we tell it not to be stupid From da5b0b38872bd7478ba919957ed061489398fcf0 Mon Sep 17 00:00:00 2001 From: Travis Cross Date: Sun, 23 Sep 2012 00:33:52 +0000 Subject: [PATCH 040/252] debian: Remove config for mod_fax --- debian/bootstrap.sh | 1 - debian/control-modules | 4 ---- 2 files changed, 5 deletions(-) diff --git a/debian/bootstrap.sh b/debian/bootstrap.sh index 5ba909b851..736d7a4895 100755 --- a/debian/bootstrap.sh +++ b/debian/bootstrap.sh @@ -8,7 +8,6 @@ fs_description="FreeSWITCH is a scalable open source cross-platform telephony pl mod_build_depends="." supported_distros="squeeze wheezy sid" avoid_mods=( - applications/mod_fax applications/mod_limit applications/mod_mongo applications/mod_mp4 diff --git a/debian/control-modules b/debian/control-modules index a41e858513..b2d15db8b5 100644 --- a/debian/control-modules +++ b/debian/control-modules @@ -79,10 +79,6 @@ Module: applications/mod_expr Description: Expr This module adds expr support for expression evaluation. -Module: applications/mod_fax -Description: Fax - This module adds fax support provided by Steve Underwood's SpanDSP. - Module: applications/mod_fifo Description: FIFO This module adds a first-in first-out queue system. From 6f056ef7673bd71636e4cdf0dd727ddba70aeeee Mon Sep 17 00:00:00 2001 From: Travis Cross Date: Sun, 23 Sep 2012 03:49:40 +0000 Subject: [PATCH 041/252] debian: Enable mod_oreka --- debian/bootstrap.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/debian/bootstrap.sh b/debian/bootstrap.sh index 736d7a4895..41c0897f3a 100755 --- a/debian/bootstrap.sh +++ b/debian/bootstrap.sh @@ -11,7 +11,6 @@ avoid_mods=( applications/mod_limit applications/mod_mongo applications/mod_mp4 - applications/mod_oreka applications/mod_osp applications/mod_rad_auth applications/mod_skel From 0b0a916fdead12768c0c574ff66932fcb8450753 Mon Sep 17 00:00:00 2001 From: Travis Cross Date: Sun, 23 Sep 2012 03:50:09 +0000 Subject: [PATCH 042/252] debian: Enable mod_sonar --- debian/bootstrap.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/debian/bootstrap.sh b/debian/bootstrap.sh index 41c0897f3a..e91a7609b8 100755 --- a/debian/bootstrap.sh +++ b/debian/bootstrap.sh @@ -14,7 +14,6 @@ avoid_mods=( applications/mod_osp applications/mod_rad_auth applications/mod_skel - applications/mod_sonar applications/mod_soundtouch asr_tts/mod_cepstral asr_tts/mod_flite From 2a665f409477eaa02384bfc05350fe663e0a3e5b Mon Sep 17 00:00:00 2001 From: Travis Cross Date: Sun, 23 Sep 2012 03:51:15 +0000 Subject: [PATCH 043/252] debian: Enable mod_html5 --- debian/bootstrap.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/debian/bootstrap.sh b/debian/bootstrap.sh index e91a7609b8..a4164082a9 100755 --- a/debian/bootstrap.sh +++ b/debian/bootstrap.sh @@ -25,7 +25,6 @@ avoid_mods=( codecs/mod_voipcodecs endpoints/mod_gsmopen endpoints/mod_h323 - endpoints/mod_html5 endpoints/mod_khomp endpoints/mod_opal endpoints/mod_reference From df04ec4b12407cf37ab4920cf1ff3ef0d5e12a5f Mon Sep 17 00:00:00 2001 From: Travis Cross Date: Sun, 23 Sep 2012 03:56:19 +0000 Subject: [PATCH 044/252] debian: Enable mod_soundtouch --- debian/bootstrap.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/debian/bootstrap.sh b/debian/bootstrap.sh index a4164082a9..69068334c9 100755 --- a/debian/bootstrap.sh +++ b/debian/bootstrap.sh @@ -14,7 +14,6 @@ avoid_mods=( applications/mod_osp applications/mod_rad_auth applications/mod_skel - applications/mod_soundtouch asr_tts/mod_cepstral asr_tts/mod_flite codecs/mod_com_g729 From 882e184a89ac7aa77bee9368dce25b12a3390eab Mon Sep 17 00:00:00 2001 From: Travis Cross Date: Sun, 23 Sep 2012 04:34:52 +0000 Subject: [PATCH 045/252] debian: Provide system FLAC/Ogg/Vorbis for mod_sndfile --- debian/control-modules | 1 + 1 file changed, 1 insertion(+) diff --git a/debian/control-modules b/debian/control-modules index b2d15db8b5..b9f0a5772a 100644 --- a/debian/control-modules +++ b/debian/control-modules @@ -511,6 +511,7 @@ Build-Depends: libogg-dev, libvorbis-dev Module: formats/mod_sndfile Description: mod_sndfile Adds mod_sndfile. +Build-Depends: libflac-dev, libogg-dev, libvorbis-dev Module: formats/mod_tone_stream Description: mod_tone_stream From 447a2c6279a64d435412a651e17d884d6d277c02 Mon Sep 17 00:00:00 2001 From: Travis Cross Date: Sun, 23 Sep 2012 05:25:40 +0000 Subject: [PATCH 046/252] Improve startup cosmetics --- src/switch_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/switch_core.c b/src/switch_core.c index 27e1717916..a82df1a0e6 100644 --- a/src/switch_core.c +++ b/src/switch_core.c @@ -2016,7 +2016,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_init_and_modload(switch_core_flag_t switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, - "\nFreeSWITCH Version %s (%s) Started.\nMax Sessions[%u]\nSession Rate[%d]\nSQL [%s]\n", + "\nFreeSWITCH Version %s (%s)\n\nFreeSWITCH Started\nMax Sessions [%u]\nSession Rate [%d]\nSQL [%s]\n", SWITCH_VERSION_FULL, SWITCH_VERSION_REVISION_HUMAN, switch_core_session_limit(0), switch_core_sessions_per_second(0), switch_test_flag((&runtime), SCF_USE_SQL) ? "Enabled" : "Disabled"); From 91a8356d4d38d345c3e45201e0d92b0c5364b896 Mon Sep 17 00:00:00 2001 From: Travis Cross Date: Sun, 23 Sep 2012 06:38:34 +0000 Subject: [PATCH 047/252] debian: Add isac and vp8 to meta-codecs --- debian/bootstrap.sh | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/debian/bootstrap.sh b/debian/bootstrap.sh index 69068334c9..6b0dc67614 100755 --- a/debian/bootstrap.sh +++ b/debian/bootstrap.sh @@ -332,12 +332,14 @@ Depends: \${misc:Depends}, freeswitch (= \${binary:Version}), freeswitch-mod-g723-1 (= \${binary:Version}), freeswitch-mod-g729 (= \${binary:Version}), freeswitch-mod-h26x (= \${binary:Version}), + freeswitch-mod-isac (= \${binary:Version}), freeswitch-mod-mp4v (= \${binary:Version}), freeswitch-mod-opus (= \${binary:Version}), freeswitch-mod-silk (= \${binary:Version}), freeswitch-mod-spandsp (= \${binary:Version}), freeswitch-mod-speex (= \${binary:Version}), - freeswitch-mod-theora (= \${binary:Version}) + freeswitch-mod-theora (= \${binary:Version}), + freeswitch-mod-vp8 (= \${binary:Version}) Suggests: freeswitch-mod-ilbc (= \${binary:Version}), freeswitch-mod-siren (= \${binary:Version}) From b8e3c1d524a4c1eca9830b2067af2fef811e6a36 Mon Sep 17 00:00:00 2001 From: Travis Cross Date: Sun, 23 Sep 2012 07:33:51 +0000 Subject: [PATCH 048/252] debian: Add meta-sorbet and meta-all --- debian/bootstrap.sh | 201 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 201 insertions(+) diff --git a/debian/bootstrap.sh b/debian/bootstrap.sh index 6b0dc67614..9b3e9687fd 100755 --- a/debian/bootstrap.sh +++ b/debian/bootstrap.sh @@ -321,6 +321,207 @@ Description: Cross-Platform Scalable Multi-Protocol Soft Switch This is a metapackage which depends on the packages needed for running the FreeSWITCH vanilla example configuration. +Package: freeswitch-meta-sorbet +Architecture: any +Depends: \${misc:Depends}, freeswitch (= \${binary:Version}), +Recommends: + freeswitch-init (= \${binary:Version}), + freeswitch-meta-codecs (= \${binary:Version}), + freeswitch-music (= \${binary:Version}), + freeswitch-sounds (= \${binary:Version}), + freeswitch-mod-abstraction (= \${binary:Version}), + freeswitch-mod-avmd (= \${binary:Version}), + freeswitch-mod-blacklist (= \${binary:Version}), + freeswitch-mod-callcenter (= \${binary:Version}), + freeswitch-mod-cidlookup (= \${binary:Version}), + freeswitch-mod-commands (= \${binary:Version}), + freeswitch-mod-conference (= \${binary:Version}), + freeswitch-mod-curl (= \${binary:Version}), + freeswitch-mod-db (= \${binary:Version}), + freeswitch-mod-directory (= \${binary:Version}), + freeswitch-mod-distributor (= \${binary:Version}), + freeswitch-mod-dptools (= \${binary:Version}), + freeswitch-mod-easyroute (= \${binary:Version}), + freeswitch-mod-enum (= \${binary:Version}), + freeswitch-mod-esf (= \${binary:Version}), + freeswitch-mod-esl (= \${binary:Version}), + freeswitch-mod-expr (= \${binary:Version}), + freeswitch-mod-fifo (= \${binary:Version}), + freeswitch-mod-fsk (= \${binary:Version}), + freeswitch-mod-fsv (= \${binary:Version}), + freeswitch-mod-hash (= \${binary:Version}), + freeswitch-mod-httapi (= \${binary:Version}), + freeswitch-mod-http-cache (= \${binary:Version}), + freeswitch-mod-lcr (= \${binary:Version}), + freeswitch-mod-nibblebill (= \${binary:Version}), + freeswitch-mod-oreka (= \${binary:Version}), + freeswitch-mod-random (= \${binary:Version}), + freeswitch-mod-redis (= \${binary:Version}), + freeswitch-mod-rss (= \${binary:Version}), + freeswitch-mod-sms (= \${binary:Version}), + freeswitch-mod-snapshot (= \${binary:Version}), + freeswitch-mod-snom (= \${binary:Version}), + freeswitch-mod-sonar (= \${binary:Version}), + freeswitch-mod-soundtouch (= \${binary:Version}), + freeswitch-mod-spandsp (= \${binary:Version}), + freeswitch-mod-spy (= \${binary:Version}), + freeswitch-mod-stress (= \${binary:Version}), + freeswitch-mod-valet-parking (= \${binary:Version}), + freeswitch-mod-vmd (= \${binary:Version}), + freeswitch-mod-voicemail (= \${binary:Version}), + freeswitch-mod-voicemail-ivr (= \${binary:Version}), + freeswitch-mod-pocketsphinx (= \${binary:Version}), + freeswitch-mod-tts-commandline (= \${binary:Version}), + freeswitch-mod-dialplan-xml (= \${binary:Version}), + freeswitch-mod-html5 (= \${binary:Version}), + freeswitch-mod-loopback (= \${binary:Version}), + freeswitch-mod-rtmp (= \${binary:Version}), + freeswitch-mod-skinny (= \${binary:Version}), + freeswitch-mod-sofia (= \${binary:Version}), + freeswitch-mod-cdr-csv (= \${binary:Version}), + freeswitch-mod-cdr-sqlite (= \${binary:Version}), + freeswitch-mod-event-socket (= \${binary:Version}), + freeswitch-mod-json-cdr (= \${binary:Version}), + freeswitch-mod-local-stream (= \${binary:Version}), + freeswitch-mod-native-file (= \${binary:Version}), + freeswitch-mod-shell-stream (= \${binary:Version}), + freeswitch-mod-sndfile (= \${binary:Version}), + freeswitch-mod-tone-stream (= \${binary:Version}), + freeswitch-mod-lua (= \${binary:Version}), + freeswitch-mod-console (= \${binary:Version}), + freeswitch-mod-logfile (= \${binary:Version}), + freeswitch-mod-syslog (= \${binary:Version}), + freeswitch-mod-say-en (= \${binary:Version}), + freeswitch-mod-posix-timer (= \${binary:Version}), + freeswitch-mod-timerfd (= \${binary:Version}), + freeswitch-mod-xml-cdr (= \${binary:Version}), + freeswitch-mod-xml-curl (= \${binary:Version}), +Description: Cross-Platform Scalable Multi-Protocol Soft Switch + $(debian_wrap "${fs_description}") + . + This is a metapackage which recommends most packaged FreeSWITCH + modules except a few which aren't recommended. + +Package: freeswitch-meta-all +Architecture: any +Depends: \${misc:Depends}, freeswitch (= \${binary:Version}), +Recommends: + freeswitch-init (= \${binary:Version}), + freeswitch-meta-codecs (= \${binary:Version}), + freeswitch-music (= \${binary:Version}), + freeswitch-sounds (= \${binary:Version}), + freeswitch-mod-abstraction (= \${binary:Version}), + freeswitch-mod-avmd (= \${binary:Version}), + freeswitch-mod-blacklist (= \${binary:Version}), + freeswitch-mod-callcenter (= \${binary:Version}), + freeswitch-mod-cidlookup (= \${binary:Version}), + freeswitch-mod-cluechoo (= \${binary:Version}), + freeswitch-mod-commands (= \${binary:Version}), + freeswitch-mod-conference (= \${binary:Version}), + freeswitch-mod-curl (= \${binary:Version}), + freeswitch-mod-db (= \${binary:Version}), + freeswitch-mod-directory (= \${binary:Version}), + freeswitch-mod-distributor (= \${binary:Version}), + freeswitch-mod-dptools (= \${binary:Version}), + freeswitch-mod-easyroute (= \${binary:Version}), + freeswitch-mod-enum (= \${binary:Version}), + freeswitch-mod-esf (= \${binary:Version}), + freeswitch-mod-esl (= \${binary:Version}), + freeswitch-mod-expr (= \${binary:Version}), + freeswitch-mod-fifo (= \${binary:Version}), + freeswitch-mod-fsk (= \${binary:Version}), + freeswitch-mod-fsv (= \${binary:Version}), + freeswitch-mod-hash (= \${binary:Version}), + freeswitch-mod-httapi (= \${binary:Version}), + freeswitch-mod-http-cache (= \${binary:Version}), + freeswitch-mod-ladspa (= \${binary:Version}), + freeswitch-mod-lcr (= \${binary:Version}), + freeswitch-mod-memcache (= \${binary:Version}), + freeswitch-mod-nibblebill (= \${binary:Version}), + freeswitch-mod-oreka (= \${binary:Version}), + freeswitch-mod-random (= \${binary:Version}), + freeswitch-mod-redis (= \${binary:Version}), + freeswitch-mod-rss (= \${binary:Version}), + freeswitch-mod-sms (= \${binary:Version}), + freeswitch-mod-snapshot (= \${binary:Version}), + freeswitch-mod-snipe-hunt (= \${binary:Version}), + freeswitch-mod-snom (= \${binary:Version}), + freeswitch-mod-sonar (= \${binary:Version}), + freeswitch-mod-soundtouch (= \${binary:Version}), + freeswitch-mod-spandsp (= \${binary:Version}), + freeswitch-mod-spy (= \${binary:Version}), + freeswitch-mod-stress (= \${binary:Version}), + freeswitch-mod-valet-parking (= \${binary:Version}), + freeswitch-mod-vmd (= \${binary:Version}), + freeswitch-mod-voicemail (= \${binary:Version}), + freeswitch-mod-voicemail-ivr (= \${binary:Version}), + freeswitch-mod-pocketsphinx (= \${binary:Version}), + freeswitch-mod-tts-commandline (= \${binary:Version}), + freeswitch-mod-dialplan-asterisk (= \${binary:Version}), + freeswitch-mod-dialplan-directory (= \${binary:Version}), + freeswitch-mod-dialplan-xml (= \${binary:Version}), + freeswitch-mod-ldap (= \${binary:Version}), + freeswitch-mod-alsa (= \${binary:Version}), + freeswitch-mod-dingaling (= \${binary:Version}), + freeswitch-mod-html5 (= \${binary:Version}), + freeswitch-mod-loopback (= \${binary:Version}), + freeswitch-mod-rtmp (= \${binary:Version}), + freeswitch-mod-skinny (= \${binary:Version}), + freeswitch-mod-sofia (= \${binary:Version}), + freeswitch-mod-cdr-csv (= \${binary:Version}), + freeswitch-mod-cdr-mongodb (= \${binary:Version}), + freeswitch-mod-cdr-pg-csv (= \${binary:Version}), + freeswitch-mod-cdr-sqlite (= \${binary:Version}), + freeswitch-mod-erlang-event (= \${binary:Version}), + freeswitch-mod-event-multicast (= \${binary:Version}), + freeswitch-mod-event-socket (= \${binary:Version}), + freeswitch-mod-event-test (= \${binary:Version}), + freeswitch-mod-event-zmq (= \${binary:Version}), + freeswitch-mod-json-cdr (= \${binary:Version}), + freeswitch-mod-radius-cdr (= \${binary:Version}), + freeswitch-mod-snmp (= \${binary:Version}), + freeswitch-mod-local-stream (= \${binary:Version}), + freeswitch-mod-native-file (= \${binary:Version}), + freeswitch-mod-shell-stream (= \${binary:Version}), + freeswitch-mod-sndfile (= \${binary:Version}), + freeswitch-mod-tone-stream (= \${binary:Version}), + freeswitch-mod-java (= \${binary:Version}), + freeswitch-mod-lua (= \${binary:Version}), + freeswitch-mod-perl (= \${binary:Version}), + freeswitch-mod-python (= \${binary:Version}), + freeswitch-mod-yaml (= \${binary:Version}), + freeswitch-mod-console (= \${binary:Version}), + freeswitch-mod-logfile (= \${binary:Version}), + freeswitch-mod-syslog (= \${binary:Version}), + freeswitch-mod-say-en (= \${binary:Version}), + freeswitch-mod-posix-timer (= \${binary:Version}), + freeswitch-mod-timerfd (= \${binary:Version}), + freeswitch-mod-xml-cdr (= \${binary:Version}), + freeswitch-mod-xml-curl (= \${binary:Version}), + freeswitch-mod-xml-rpc (= \${binary:Version}), + freeswitch-mod-xml-scgi (= \${binary:Version}), +Suggests: + freeswitch-mod-vlc (= \${binary:Version}), + freeswitch-mod-say-de (= \${binary:Version}), + freeswitch-mod-say-es (= \${binary:Version}), + freeswitch-mod-say-fa (= \${binary:Version}), + freeswitch-mod-say-fr (= \${binary:Version}), + freeswitch-mod-say-he (= \${binary:Version}), + freeswitch-mod-say-hr (= \${binary:Version}), + freeswitch-mod-say-hu (= \${binary:Version}), + freeswitch-mod-say-it (= \${binary:Version}), + freeswitch-mod-say-ja (= \${binary:Version}), + freeswitch-mod-say-nl (= \${binary:Version}), + freeswitch-mod-say-pt (= \${binary:Version}), + freeswitch-mod-say-ru (= \${binary:Version}), + freeswitch-mod-say-th (= \${binary:Version}), + freeswitch-mod-say-zh (= \${binary:Version}), +Description: Cross-Platform Scalable Multi-Protocol Soft Switch + $(debian_wrap "${fs_description}") + . + This is a metapackage which recommends or suggests all packaged + FreeSWITCH modules. + Package: freeswitch-meta-codecs Architecture: any Depends: \${misc:Depends}, freeswitch (= \${binary:Version}), From d565fdece5152a252252d4d95813ab0040004907 Mon Sep 17 00:00:00 2001 From: Michael Jerris Date: Mon, 24 Sep 2012 15:35:35 -0400 Subject: [PATCH 049/252] revert 6f9467992ac8d8435d312a3d78091e66578ab6a6 --- debian/rules | 1 - 1 file changed, 1 deletion(-) diff --git a/debian/rules b/debian/rules index 8c9f284341..cd7934e439 100755 --- a/debian/rules +++ b/debian/rules @@ -64,7 +64,6 @@ override_dh_auto_clean: --host=$(DEB_HOST_GNU_TYPE) --build=$(DEB_BUILD_GNU_TYPE) \ --with-gnu-ld --with-python --with-erlang --with-openssl \ --enable-core-odbc-support --enable-zrtp \ - --enable-modest-cluecon-nag \ --prefix=/usr --localstatedir=/var \ --sysconfdir=/etc/freeswitch \ --with-modinstdir=/usr/lib/freeswitch/mod \ From 4ff9b2f102ab000f8d04aae01ad108bc7ea600fd Mon Sep 17 00:00:00 2001 From: Michael Jerris Date: Mon, 24 Sep 2012 15:38:06 -0400 Subject: [PATCH 050/252] revert fb2ffbafe29beaf5c2b148e0131307e8569886ef --- Makefile.am | 18 ++++++++---------- build/Makefile.am | 4 ++-- configure.in | 22 +--------------------- libs/esl/fs_cli.c | 10 +++++----- libs/esl/src/include/cc.h | 6 ------ src/include/cc.h | 6 ------ src/switch_core.c | 6 +----- 7 files changed, 17 insertions(+), 55 deletions(-) diff --git a/Makefile.am b/Makefile.am index cdf20f55c0..e7f1f799a5 100644 --- a/Makefile.am +++ b/Makefile.am @@ -311,7 +311,7 @@ bin_PROGRAMS = freeswitch fs_cli fs_ivrd tone2wav fs_encode ## fs_cli_SOURCES = libs/esl/src/esl.c libs/esl/src/esl_config.c libs/esl/src/esl_event.c \ libs/esl/src/esl_threadmutex.c libs/esl/fs_cli.c libs/esl/src/esl_json.c libs/esl/src/esl_buffer.c -fs_cli_CFLAGS = $(AM_CFLAGS) -I$(switch_srcdir)/libs/esl/src/include -include src/include/switch_private.h +fs_cli_CFLAGS = $(AM_CFLAGS) -I$(switch_srcdir)/libs/esl/src/include fs_cli_LDFLAGS = $(AM_LDFLAGS) -lpthread $(ESL_LDFLAGS) -lm if HAVE_LIBEDIT @@ -660,15 +660,13 @@ sofia-reconf: cd libs/sofia-sip && ./configure --prefix=$(prefix) --with-pic --with-glib=no --disable-shared cluecon: - @if $(ENABLE_CLUECON_NAG); then \ - clear; \ - echo "Thank you for updating. This is going to take a while so relax."; \ - echo "Now would be a good time to register for ClueCon!"; \ - cat cluecon2.tmpl; \ - echo; \ - echo "http://www.cluecon.com"; \ - sleep 5; \ - fi + @clear + @echo Thank you for updating. This is going to take a while so relax. + @echo Now would be a good time to register for ClueCon! + @cat cluecon2.tmpl + @echo + @echo http://www.cluecon.com + @sleep 5 current: cluecon update-clean is-scm $(MAKE) update $(MAKE) all diff --git a/build/Makefile.am b/build/Makefile.am index fa5a257a5f..3feb22157d 100644 --- a/build/Makefile.am +++ b/build/Makefile.am @@ -11,7 +11,7 @@ all: @echo " + http://www.cluecon.com +" @echo " + +" @echo " +-----------------------------------------------+" - @-$(ENABLE_CLUECON_NAG) && cat ../cluecon2.tmpl + @cat ../cluecon2.tmpl install: @echo " +---------- FreeSWITCH install Complete ----------+" @@ -69,7 +69,7 @@ install: @echo " + http://www.cluecon.com +" @echo " + +" @echo " +-------------------------------------------------+" - @-$(ENABLE_CLUECON_NAG) && cat ../cluecon2.tmpl + @cat ../cluecon2.tmpl .PHONY: check dvi html info install-data \ diff --git a/configure.in b/configure.in index fdef3735ca..9fa01e4aba 100644 --- a/configure.in +++ b/configure.in @@ -335,26 +335,6 @@ AC_ARG_ENABLE(skip-subdirectories, [AC_HELP_STRING([--enable-skip-subdirectories],[skip configuration of subdirectories])], [enable_skip_subdirectories="$enableval"],[enable_skip_subdirectories="no"]) -# Enable ClueCon nag banner (default: on) -AC_ARG_ENABLE(huge-cluecon-nag, -[AC_HELP_STRING([--disable-huge-cluecon-nag],[build without huge ClueCon banners])], -[enable_huge_cluecon_nag="$enableval"],[enable_huge_cluecon_nag="yes"]) - -AC_ARG_ENABLE(modest-cluecon-nag, -[AC_HELP_STRING([--enable-modest-cluecon-nag],[build with modest ClueCon announcements])], -[enable_modest_cluecon_nag="$enableval"],[enable_modest_cluecon_nag="no"]) - -if test "${enable_modest_cluecon_nag}" = "yes"; then - enable_huge_cluecon_nag="no" - AC_DEFINE([SHOW_MODEST_CLUECON_NAG],[1],[Show modest ClueCon nag messages.]) - AC_SUBST([ENABLE_CLUECON_NAG],[false]) -elif test "${enable_huge_cluecon_nag}" = "yes"; then - AC_DEFINE([SHOW_HUGE_CLUECON_NAG],[1],[Show huge ClueCon nag messages.]) - AC_SUBST([ENABLE_CLUECON_NAG],[true]) -else - AC_SUBST([ENABLE_CLUECON_NAG],[false]) -fi - # Enable debugging (default: on) # (rename option if the default is changed) AC_ARG_ENABLE(debug, @@ -1141,7 +1121,7 @@ AC_OUTPUT ## ## Registering for ClueCon ## -if ! test -f noreg && test "${enable_huge_cluecon_nag}" = "yes" ; then +if ! test -f noreg ; then echo "" echo "" echo $ECHO_N "Registering you for ClueCon http://www.cluecon.com $ECHO_C" 1>&6 diff --git a/libs/esl/fs_cli.c b/libs/esl/fs_cli.c index 03d8e351d1..95629da76e 100644 --- a/libs/esl/fs_cli.c +++ b/libs/esl/fs_cli.c @@ -931,17 +931,17 @@ static void print_banner(FILE *stream) WriteFile(hStdout, banner, (DWORD) strlen(banner), NULL, NULL); WriteFile(hStdout, cc, (DWORD) strlen(cc), NULL, NULL); SetConsoleTextAttribute(hStdout, wOldColorAttrs); + /* Print the rest info in default colors */ fprintf(stream, "\n%s\n", inf); -#elif SHOW_HUGE_CLUECON_NAG - fprintf(stream, "%s%s%s%s%s%s\n%s\n", +#else + fprintf(stream, + "%s%s%s%s%s%s\n%s\n", ESL_SEQ_DEFAULT_COLOR, ESL_SEQ_FYELLOW, ESL_SEQ_BBLUE, banner, cc, ESL_SEQ_DEFAULT_COLOR, inf); - fprintf(stream, "%s", output_text_color); -#else - fprintf(stream, "%s%s%s\n%s\n", ESL_SEQ_DEFAULT_COLOR, banner, cc, inf); + fprintf(stream, "%s", output_text_color); #endif } diff --git a/libs/esl/src/include/cc.h b/libs/esl/src/include/cc.h index 6387209c6b..44666193c6 100644 --- a/libs/esl/src/include/cc.h +++ b/libs/esl/src/include/cc.h @@ -1,8 +1,2 @@ -#ifdef SHOW_HUGE_CLUECON_NAG const char *cc = ".========================================================================================================.\n| ____ _____ ____ _ ____ _ _ _____ |\n| / ___|___ _ __ ___ ___ |_ _|__ / ___| |_ _ ___ / ___|___ _ __ ( ) |___ / |\n| | | / _ \\| '_ ` _ \\ / _ \\ | |/ _ \\ | | | | | | |/ _ \\ | / _ \\| '_ \\ |/| | |_ \\ |\n| | |__| (_) | | | | | | __/ | | (_) | | |___| | |_| | __/ |__| (_) | | | | | |___) | |\n| \\____\\___/|_| |_| |_|\\___| |_|\\___/ \\____|_|\\__,_|\\___|\\____\\___/|_| |_| |_|____/ |\n| |\n| ____ _ _ _ _ ____ _ |\n| / ___| |__ (_) ___ __ _ __ _ ___ | | | / ___| / \\ |\n| | | | '_ \\| |/ __/ _` |/ _` |/ _ \\ | | | \\___ \\ / _ \\ |\n| | |___| | | | | (_| (_| | (_| | (_) | | |_| |___) / ___ \\ |\n| \\____|_| |_|_|\\___\\__,_|\\__, |\\___( ) \\___/|____/_/ \\_\\ |\n| |___/ |/ |\n| _ _ __ _ _ ___ _ _ ____ ___ _ _____ |\n| / \\ _ _ __ _ _ _ ___| |_ / /_ | |_| |__ ( _ )| |_| |__ |___ \\ / _ \\/ |___ / |\n| / _ \\| | | |/ _` | | | / __| __| | '_ \\| __| '_ \\ _____ / _ \\| __| '_ \\ __) | | | | | |_ \\ |\n| / ___ \\ |_| | (_| | |_| \\__ \\ |_ | (_) | |_| | | | |_____| | (_) | |_| | | | / __/| |_| | |___) | |\n| /_/ \\_\\__,_|\\__, |\\__,_|___/\\__| \\___/ \\__|_| |_| \\___/ \\__|_| |_| |_____|\\___/|_|____/ |\n| |___/ |\n| _ |\n| __ ____ ____ __ ___| |_ _ ___ ___ ___ _ __ ___ ___ _ __ ___ |\n| \\ \\ /\\ / /\\ \\ /\\ / /\\ \\ /\\ / / / __| | | | |/ _ \\/ __/ _ \\| '_ \\ / __/ _ \\| '_ ` _ \\ |\n| \\ V V / \\ V V / \\ V V / _ | (__| | |_| | __/ (_| (_) | | | | _ | (_| (_) | | | | | | |\n| \\_/\\_/ \\_/\\_/ \\_/\\_/ (_) \\___|_|\\__,_|\\___|\\___\\___/|_| |_| (_) \\___\\___/|_| |_| |_| |\n| |\n.========================================================================================================.\n"; -#elif SHOW_MODEST_CLUECON_NAG -const char *cc = "Come to ClueCon '13 August 6-8th, 2013, Chicago, USA\nwww.cluecon.com\n"; -#else -const char *cc = ""; -#endif diff --git a/src/include/cc.h b/src/include/cc.h index 6387209c6b..44666193c6 100644 --- a/src/include/cc.h +++ b/src/include/cc.h @@ -1,8 +1,2 @@ -#ifdef SHOW_HUGE_CLUECON_NAG const char *cc = ".========================================================================================================.\n| ____ _____ ____ _ ____ _ _ _____ |\n| / ___|___ _ __ ___ ___ |_ _|__ / ___| |_ _ ___ / ___|___ _ __ ( ) |___ / |\n| | | / _ \\| '_ ` _ \\ / _ \\ | |/ _ \\ | | | | | | |/ _ \\ | / _ \\| '_ \\ |/| | |_ \\ |\n| | |__| (_) | | | | | | __/ | | (_) | | |___| | |_| | __/ |__| (_) | | | | | |___) | |\n| \\____\\___/|_| |_| |_|\\___| |_|\\___/ \\____|_|\\__,_|\\___|\\____\\___/|_| |_| |_|____/ |\n| |\n| ____ _ _ _ _ ____ _ |\n| / ___| |__ (_) ___ __ _ __ _ ___ | | | / ___| / \\ |\n| | | | '_ \\| |/ __/ _` |/ _` |/ _ \\ | | | \\___ \\ / _ \\ |\n| | |___| | | | | (_| (_| | (_| | (_) | | |_| |___) / ___ \\ |\n| \\____|_| |_|_|\\___\\__,_|\\__, |\\___( ) \\___/|____/_/ \\_\\ |\n| |___/ |/ |\n| _ _ __ _ _ ___ _ _ ____ ___ _ _____ |\n| / \\ _ _ __ _ _ _ ___| |_ / /_ | |_| |__ ( _ )| |_| |__ |___ \\ / _ \\/ |___ / |\n| / _ \\| | | |/ _` | | | / __| __| | '_ \\| __| '_ \\ _____ / _ \\| __| '_ \\ __) | | | | | |_ \\ |\n| / ___ \\ |_| | (_| | |_| \\__ \\ |_ | (_) | |_| | | | |_____| | (_) | |_| | | | / __/| |_| | |___) | |\n| /_/ \\_\\__,_|\\__, |\\__,_|___/\\__| \\___/ \\__|_| |_| \\___/ \\__|_| |_| |_____|\\___/|_|____/ |\n| |___/ |\n| _ |\n| __ ____ ____ __ ___| |_ _ ___ ___ ___ _ __ ___ ___ _ __ ___ |\n| \\ \\ /\\ / /\\ \\ /\\ / /\\ \\ /\\ / / / __| | | | |/ _ \\/ __/ _ \\| '_ \\ / __/ _ \\| '_ ` _ \\ |\n| \\ V V / \\ V V / \\ V V / _ | (__| | |_| | __/ (_| (_) | | | | _ | (_| (_) | | | | | | |\n| \\_/\\_/ \\_/\\_/ \\_/\\_/ (_) \\___|_|\\__,_|\\___|\\___\\___/|_| |_| (_) \\___\\___/|_| |_| |_| |\n| |\n.========================================================================================================.\n"; -#elif SHOW_MODEST_CLUECON_NAG -const char *cc = "Come to ClueCon '13 August 6-8th, 2013, Chicago, USA\nwww.cluecon.com\n"; -#else -const char *cc = ""; -#endif diff --git a/src/switch_core.c b/src/switch_core.c index a82df1a0e6..30b94232c4 100644 --- a/src/switch_core.c +++ b/src/switch_core.c @@ -2002,16 +2002,12 @@ SWITCH_DECLARE(switch_status_t) switch_core_init_and_modload(switch_core_flag_t #ifdef WIN32 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "%s%s\n\n", switch_core_banner(), cc); -#elif SHOW_HUGE_CLUECON_NAG +#else switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "%s%s%s%s%s%s\n\n", SWITCH_SEQ_DEFAULT_COLOR, SWITCH_SEQ_FYELLOW, SWITCH_SEQ_BBLUE, switch_core_banner(), cc, SWITCH_SEQ_DEFAULT_COLOR); -#else - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "%s%s%s\n\n", - SWITCH_SEQ_DEFAULT_COLOR, - switch_core_banner(), cc); #endif From 236bfeeaa3440e157fe7f4a07a16264441ad1f0b Mon Sep 17 00:00:00 2001 From: Michael Jerris Date: Mon, 24 Sep 2012 15:39:52 -0400 Subject: [PATCH 051/252] revert 2dc709981b3084a071cc22cd3b56c0ec61296080 --- configure.in | 68 ++++++++++++++++++++++++---------------------------- 1 file changed, 31 insertions(+), 37 deletions(-) diff --git a/configure.in b/configure.in index 9fa01e4aba..5a97b86ace 100644 --- a/configure.in +++ b/configure.in @@ -330,11 +330,6 @@ if test "x${enable_visibility}" != "xno" ; then fi fi -# Option to skip configuration of subdirectories -AC_ARG_ENABLE(skip-subdirectories, -[AC_HELP_STRING([--enable-skip-subdirectories],[skip configuration of subdirectories])], -[enable_skip_subdirectories="$enableval"],[enable_skip_subdirectories="no"]) - # Enable debugging (default: on) # (rename option if the default is changed) AC_ARG_ENABLE(debug, @@ -1074,40 +1069,39 @@ ac_configure_args="$ac_configure_args CONFIGURE_CFLAGS='$CFLAGS' CONFIGURE_CXXFL # --localstatedir='$localstatedir' --datadir='$datadir'" # Run configure in all the subdirs -if ! test "${enable_skip_subdirectories}" = "yes"; then - AC_CONFIG_SUBDIRS([libs/srtp]) - AC_CONFIG_SUBDIRS([libs/sqlite]) - if test "$enable_core_libedit_support" = "yes" ; then - AC_CONFIG_SUBDIRS([libs/libedit]) - fi - AC_CONFIG_SUBDIRS([libs/pcre]) - AC_CONFIG_SUBDIRS([libs/apr]) - AC_CONFIG_SUBDIRS([libs/apr-util]) - AC_CONFIG_SUBDIRS([libs/ilbc]) - AC_CONFIG_SUBDIRS([libs/curl]) - AC_CONFIG_SUBDIRS([libs/iksemel]) - AC_CONFIG_SUBDIRS([libs/js/nsprpub]) - AC_CONFIG_SUBDIRS([libs/js]) - AC_CONFIG_SUBDIRS([libs/libdingaling]) - AC_CONFIG_SUBDIRS([libs/libsndfile]) - AC_CONFIG_SUBDIRS([libs/sofia-sip]) - AC_CONFIG_SUBDIRS([libs/speex]) - AC_CONFIG_SUBDIRS([libs/portaudio]) - AC_CONFIG_SUBDIRS([libs/openzap]) - AC_CONFIG_SUBDIRS([libs/freetdm]) - AC_CONFIG_SUBDIRS([libs/unimrcp]) - AC_CONFIG_SUBDIRS([libs/tiff-4.0.2]) - AC_CONFIG_SUBDIRS([libs/spandsp]) - AC_CONFIG_SUBDIRS([libs/broadvoice]) - AC_CONFIG_SUBDIRS([libs/libg722_1]) - AC_CONFIG_SUBDIRS([libs/silk]) - AC_CONFIG_SUBDIRS([libs/libcodec2]) - if test "x${enable_zrtp}" = "xyes"; then - AC_CONFIG_SUBDIRS([libs/libzrtp/projects/gnu]) - fi - AC_CONFIG_SUBDIRS([libs/libwebsockets]) +AC_CONFIG_SUBDIRS([libs/srtp]) +AC_CONFIG_SUBDIRS([libs/sqlite]) +if test "$enable_core_libedit_support" = "yes" ; then + AC_CONFIG_SUBDIRS([libs/libedit]) fi +AC_CONFIG_SUBDIRS([libs/pcre]) +AC_CONFIG_SUBDIRS([libs/apr]) +AC_CONFIG_SUBDIRS([libs/apr-util]) +AC_CONFIG_SUBDIRS([libs/ilbc]) +AC_CONFIG_SUBDIRS([libs/curl]) +AC_CONFIG_SUBDIRS([libs/iksemel]) +AC_CONFIG_SUBDIRS([libs/js/nsprpub]) +AC_CONFIG_SUBDIRS([libs/js]) +AC_CONFIG_SUBDIRS([libs/libdingaling]) +AC_CONFIG_SUBDIRS([libs/libsndfile]) +AC_CONFIG_SUBDIRS([libs/sofia-sip]) +AC_CONFIG_SUBDIRS([libs/speex]) +AC_CONFIG_SUBDIRS([libs/portaudio]) +AC_CONFIG_SUBDIRS([libs/openzap]) +AC_CONFIG_SUBDIRS([libs/freetdm]) +AC_CONFIG_SUBDIRS([libs/unimrcp]) +AC_CONFIG_SUBDIRS([libs/tiff-4.0.2]) +AC_CONFIG_SUBDIRS([libs/spandsp]) +AC_CONFIG_SUBDIRS([libs/broadvoice]) +AC_CONFIG_SUBDIRS([libs/libg722_1]) +AC_CONFIG_SUBDIRS([libs/silk]) +AC_CONFIG_SUBDIRS([libs/libcodec2]) +if test "x${enable_zrtp}" = "xyes"; then + AC_CONFIG_SUBDIRS([libs/libzrtp/projects/gnu]) +fi +AC_CONFIG_SUBDIRS([libs/libwebsockets]) + case $host in *-openbsd*) # libtool won't link static libs against shared ones on OpenBSD unless we tell it not to be stupid From daa97613a710c69be11f6ee22864631a69f61946 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Mon, 24 Sep 2012 12:28:11 -0500 Subject: [PATCH 052/252] FS-4641 --resolve --- src/mod/event_handlers/mod_json_cdr/mod_json_cdr.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/mod/event_handlers/mod_json_cdr/mod_json_cdr.c b/src/mod/event_handlers/mod_json_cdr/mod_json_cdr.c index 7b1cf2a6a9..a50616f708 100644 --- a/src/mod/event_handlers/mod_json_cdr/mod_json_cdr.c +++ b/src/mod/event_handlers/mod_json_cdr/mod_json_cdr.c @@ -560,15 +560,15 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_json_cdr_load) } else if (!strcasecmp(var, "enable-cacert-check") && switch_true(val)) { globals.enable_cacert_check = 1; } else if (!strcasecmp(var, "ssl-cert-path")) { - globals.ssl_cert_file = val; + globals.ssl_cert_file = switch_core_strdup(globals.pool, val); } else if (!strcasecmp(var, "ssl-key-path")) { - globals.ssl_key_file = val; + globals.ssl_key_file = switch_core_strdup(globals.pool, val); } else if (!strcasecmp(var, "ssl-key-password")) { - globals.ssl_key_password = val; + globals.ssl_key_password = switch_core_strdup(globals.pool, val); } else if (!strcasecmp(var, "ssl-version")) { - globals.ssl_version = val; + globals.ssl_version = switch_core_strdup(globals.pool, val); } else if (!strcasecmp(var, "ssl-cacert-file")) { - globals.ssl_cacert_file = val; + globals.ssl_cacert_file = switch_core_strdup(globals.pool, val); } else if (!strcasecmp(var, "enable-ssl-verifyhost") && switch_true(val)) { globals.enable_ssl_verifyhost = 1; } else if (!strcasecmp(var, "auth-scheme")) { From f8760a1fa890352452439d428602caac4849b0cb Mon Sep 17 00:00:00 2001 From: Jeff Lenk Date: Mon, 24 Sep 2012 16:58:31 -0500 Subject: [PATCH 053/252] FS-4641 apply same fix to mod_xml_cdr --- src/mod/xml_int/mod_xml_cdr/mod_xml_cdr.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/mod/xml_int/mod_xml_cdr/mod_xml_cdr.c b/src/mod/xml_int/mod_xml_cdr/mod_xml_cdr.c index 28f4ae2e44..8779caa6f3 100644 --- a/src/mod/xml_int/mod_xml_cdr/mod_xml_cdr.c +++ b/src/mod/xml_int/mod_xml_cdr/mod_xml_cdr.c @@ -548,15 +548,15 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_xml_cdr_load) } else if (!strcasecmp(var, "enable-cacert-check") && switch_true(val)) { globals.enable_cacert_check = 1; } else if (!strcasecmp(var, "ssl-cert-path")) { - globals.ssl_cert_file = val; + globals.ssl_cert_file = switch_core_strdup(globals.pool, val); } else if (!strcasecmp(var, "ssl-key-path")) { - globals.ssl_key_file = val; + globals.ssl_key_file = switch_core_strdup(globals.pool, val); } else if (!strcasecmp(var, "ssl-key-password")) { - globals.ssl_key_password = val; + globals.ssl_key_password = switch_core_strdup(globals.pool, val); } else if (!strcasecmp(var, "ssl-version")) { - globals.ssl_version = val; + globals.ssl_version = switch_core_strdup(globals.pool, val); } else if (!strcasecmp(var, "ssl-cacert-file")) { - globals.ssl_cacert_file = val; + globals.ssl_cacert_file = switch_core_strdup(globals.pool, val); } else if (!strcasecmp(var, "enable-ssl-verifyhost") && switch_true(val)) { globals.enable_ssl_verifyhost = 1; } else if (!strcasecmp(var, "auth-scheme")) { From 03c981bf72ffc17f310220547d4652fd60199426 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Mon, 24 Sep 2012 14:59:02 -0500 Subject: [PATCH 054/252] add smaller banner for teeny tiny terminals --- build/cc.sh | 10 ++++++++++ cc.sh | 2 ++ cluecon2_small.tmpl | 10 ++++++++++ cluecon_small.tmpl | 8 ++++++++ libs/esl/fs_cli.c | 39 +++++++++++++++++++++++++++++++++++-- libs/esl/src/include/cc.h | 4 +++- src/include/cc.h | 4 +++- src/switch_core.c | 41 +++++++++++++++++++++++++++++++++++++-- 8 files changed, 112 insertions(+), 6 deletions(-) create mode 100644 build/cc.sh create mode 100644 cluecon2_small.tmpl create mode 100644 cluecon_small.tmpl diff --git a/build/cc.sh b/build/cc.sh new file mode 100644 index 0000000000..2eb7634b13 --- /dev/null +++ b/build/cc.sh @@ -0,0 +1,10 @@ +#!/bin/sh +s=(`stty size`) +c=${s[1]} + + +if [ $c -gt 99 ] ; then + cat ../cluecon2.tmpl +else + cat ../cluecon2_small.tmpl +fi diff --git a/cc.sh b/cc.sh index 85ab418e26..323b877db8 100755 --- a/cc.sh +++ b/cc.sh @@ -1,8 +1,10 @@ cc=`cat cluecon.tmpl | sed 's/\\\\/\\\\\\\\/g' | awk '{printf "%s\\\\n", $0}' ` +cc_s=`cat cluecon_small.tmpl | sed 's/\\\\/\\\\\\\\/g' | awk '{printf "%s\\\\n", $0}' ` cat < src/include/cc.h const char *cc = "$cc"; +const char *cc_s = "$cc_s"; EOF diff --git a/cluecon2_small.tmpl b/cluecon2_small.tmpl new file mode 100644 index 0000000000..7e81f074dc --- /dev/null +++ b/cluecon2_small.tmpl @@ -0,0 +1,10 @@ + +.===============================================================. +| _ | +| ___| |_ _ ___ ___ ___ _ __ ___ ___ _ __ ___ | +| / __| | | | |/ _ \/ __/ _ \| '_ \ / __/ _ \| '_ ` _ \ | +| | (__| | |_| | __/ (_| (_) | | | | _ | (_| (_) | | | | | | | +| \___|_|\__,_|\___|\___\___/|_| |_| (_) \___\___/|_| |_| |_| | +| | +.===============================================================. + diff --git a/cluecon_small.tmpl b/cluecon_small.tmpl new file mode 100644 index 0000000000..e6ceb6d837 --- /dev/null +++ b/cluecon_small.tmpl @@ -0,0 +1,8 @@ +.===============================================================. +| _ | +| ___| |_ _ ___ ___ ___ _ __ ___ ___ _ __ ___ | +| / __| | | | |/ _ \/ __/ _ \| '_ \ / __/ _ \| '_ ` _ \ | +| | (__| | |_| | __/ (_| (_) | | | | _ | (_| (_) | | | | | | | +| \___|_|\__,_|\___|\___\___/|_| |_| (_) \___\___/|_| |_| |_| | +| | +.===============================================================. diff --git a/libs/esl/fs_cli.c b/libs/esl/fs_cli.c index 95629da76e..bde78f183b 100644 --- a/libs/esl/fs_cli.c +++ b/libs/esl/fs_cli.c @@ -116,6 +116,31 @@ static void clear_cli(void) { fflush(stdout); } +static void screen_size(int *x, int *y) +{ + +#ifdef WIN32 + CONSOLE_SCREEN_BUFFER_INFO csbi; + int ret; + + if ((ret = GetConsoleScreenBufferInfo(GetStdHandle( STD_OUTPUT_HANDLE ), &csbi))) { + if (x) *x = csbi.dwSize.X; + if (y) *y = csbi.dwSize.Y; + } + +#elif TIOCGWINSZ + struct winsize w; + ioctl(0, TIOCGWINSZ, &w); + + if (x) *x = w.ws_col; + if (y) *y = w.ws_row; +#else + if (x) *x = 24; + if (x) *x = 80; +#endif + +} + /* If a fnkey is configured then process the command */ static unsigned char console_fnkey_pressed(int i) { @@ -923,13 +948,19 @@ static const char *inf = "Type /help to see a list of commands\n\n\n"; static void print_banner(FILE *stream) { + int x; + const char *use = NULL; #include + screen_size(&x, NULL); + + use = (x > 100) ? cc : cc_s; + #ifdef WIN32 /* Print banner in yellow with blue background */ SetConsoleTextAttribute(hStdout, ESL_SEQ_FYELLOW | BACKGROUND_BLUE); WriteFile(hStdout, banner, (DWORD) strlen(banner), NULL, NULL); - WriteFile(hStdout, cc, (DWORD) strlen(cc), NULL, NULL); + WriteFile(hStdout, use, (DWORD) strlen(use), NULL, NULL); SetConsoleTextAttribute(hStdout, wOldColorAttrs); /* Print the rest info in default colors */ @@ -940,10 +971,14 @@ static void print_banner(FILE *stream) ESL_SEQ_DEFAULT_COLOR, ESL_SEQ_FYELLOW, ESL_SEQ_BBLUE, banner, - cc, ESL_SEQ_DEFAULT_COLOR, inf); + use, ESL_SEQ_DEFAULT_COLOR, inf); fprintf(stream, "%s", output_text_color); #endif + + if (x < 160) { + fprintf(stream, "\n[This app Best viewed at 160x60 or more..]\n"); + } } static void set_fn_keys(cli_profile_t *profile) diff --git a/libs/esl/src/include/cc.h b/libs/esl/src/include/cc.h index 44666193c6..965aa9cbac 100644 --- a/libs/esl/src/include/cc.h +++ b/libs/esl/src/include/cc.h @@ -1,2 +1,4 @@ -const char *cc = ".========================================================================================================.\n| ____ _____ ____ _ ____ _ _ _____ |\n| / ___|___ _ __ ___ ___ |_ _|__ / ___| |_ _ ___ / ___|___ _ __ ( ) |___ / |\n| | | / _ \\| '_ ` _ \\ / _ \\ | |/ _ \\ | | | | | | |/ _ \\ | / _ \\| '_ \\ |/| | |_ \\ |\n| | |__| (_) | | | | | | __/ | | (_) | | |___| | |_| | __/ |__| (_) | | | | | |___) | |\n| \\____\\___/|_| |_| |_|\\___| |_|\\___/ \\____|_|\\__,_|\\___|\\____\\___/|_| |_| |_|____/ |\n| |\n| ____ _ _ _ _ ____ _ |\n| / ___| |__ (_) ___ __ _ __ _ ___ | | | / ___| / \\ |\n| | | | '_ \\| |/ __/ _` |/ _` |/ _ \\ | | | \\___ \\ / _ \\ |\n| | |___| | | | | (_| (_| | (_| | (_) | | |_| |___) / ___ \\ |\n| \\____|_| |_|_|\\___\\__,_|\\__, |\\___( ) \\___/|____/_/ \\_\\ |\n| |___/ |/ |\n| _ _ __ _ _ ___ _ _ ____ ___ _ _____ |\n| / \\ _ _ __ _ _ _ ___| |_ / /_ | |_| |__ ( _ )| |_| |__ |___ \\ / _ \\/ |___ / |\n| / _ \\| | | |/ _` | | | / __| __| | '_ \\| __| '_ \\ _____ / _ \\| __| '_ \\ __) | | | | | |_ \\ |\n| / ___ \\ |_| | (_| | |_| \\__ \\ |_ | (_) | |_| | | | |_____| | (_) | |_| | | | / __/| |_| | |___) | |\n| /_/ \\_\\__,_|\\__, |\\__,_|___/\\__| \\___/ \\__|_| |_| \\___/ \\__|_| |_| |_____|\\___/|_|____/ |\n| |___/ |\n| _ |\n| __ ____ ____ __ ___| |_ _ ___ ___ ___ _ __ ___ ___ _ __ ___ |\n| \\ \\ /\\ / /\\ \\ /\\ / /\\ \\ /\\ / / / __| | | | |/ _ \\/ __/ _ \\| '_ \\ / __/ _ \\| '_ ` _ \\ |\n| \\ V V / \\ V V / \\ V V / _ | (__| | |_| | __/ (_| (_) | | | | _ | (_| (_) | | | | | | |\n| \\_/\\_/ \\_/\\_/ \\_/\\_/ (_) \\___|_|\\__,_|\\___|\\___\\___/|_| |_| (_) \\___\\___/|_| |_| |_| |\n| |\n.========================================================================================================.\n"; + +const char *cc = ".========================================================================================================.\n| ____ _____ ____ _ ____ _ _ _____ |\n| / ___|___ _ __ ___ ___ |_ _|__ / ___| |_ _ ___ / ___|___ _ __ ( ) |___ / |\n| | | / _ \\| '_ ` _ \\ / _ \\ | |/ _ \\ | | | | | | |/ _ \\ | / _ \\| '_ \\ |/| | |_ \\ |\n| | |__| (_) | | | | | | __/ | | (_) | | |___| | |_| | __/ |__| (_) | | | | | |___) | |\n| \\____\\___/|_| |_| |_|\\___| |_|\\___/ \\____|_|\\__,_|\\___|\\____\\___/|_| |_| |_|____/ |\n| |\n| ____ _ _ _ _ ____ _ |\n| / ___| |__ (_) ___ __ _ __ _ ___ | | | / ___| / \\ |\n| | | | '_ \\| |/ __/ _` |/ _` |/ _ \\ | | | \\___ \\ / _ \\ |\n| | |___| | | | | (_| (_| | (_| | (_) | | |_| |___) / ___ \\ |\n| \\____|_| |_|_|\\___\\__,_|\\__, |\\___( ) \\___/|____/_/ \\_\\ |\n| |___/ |/ |\n| _ _ __ _ _ ___ _ _ ____ ___ _ _____ |\n| / \\ _ _ __ _ _ _ ___| |_ / /_ | |_| |__ ( _ )| |_| |__ |___ \\ / _ \\/ |___ / |\n| / _ \\| | | |/ _` | | | / __| __| | '_ \\| __| '_ \\ _____ / _ \\| __| '_ \\ __) | | | | | |_ \\ |\n| / ___ \\ |_| | (_| | |_| \\__ \\ |_ | (_) | |_| | | | |_____| | (_) | |_| | | | / __/| |_| | |___) | |\n| /_/ \\_\\__,_|\\__, |\\__,_|___/\\__| \\___/ \\__|_| |_| \\___/ \\__|_| |_| |_____|\\___/|_|____/ |\n| |___/ |\n| _ |\n| __ ____ ____ __ ___| |_ _ ___ ___ ___ _ __ ___ ___ _ __ ___ |\n| \\ \\ /\\ / /\\ \\ /\\ / /\\ \\ /\\ / / / __| | | | |/ _ \\/ __/ _ \\| '_ \\ / __/ _ \\| '_ ` _ \\ |\n| \\ V V / \\ V V / \\ V V / _ | (__| | |_| | __/ (_| (_) | | | | _ | (_| (_) | | | | | | |\n| \\_/\\_/ \\_/\\_/ \\_/\\_/ (_) \\___|_|\\__,_|\\___|\\___\\___/|_| |_| (_) \\___\\___/|_| |_| |_| |\n| |\n.========================================================================================================.\n"; +const char *cc_s = ".===============================================================.\n| _ |\n| ___| |_ _ ___ ___ ___ _ __ ___ ___ _ __ ___ |\n| / __| | | | |/ _ \\/ __/ _ \\| '_ \\ / __/ _ \\| '_ ` _ \\ |\n| | (__| | |_| | __/ (_| (_) | | | | _ | (_| (_) | | | | | | |\n| \\___|_|\\__,_|\\___|\\___\\___/|_| |_| (_) \\___\\___/|_| |_| |_| |\n| |\n.===============================================================.\n"; diff --git a/src/include/cc.h b/src/include/cc.h index 44666193c6..965aa9cbac 100644 --- a/src/include/cc.h +++ b/src/include/cc.h @@ -1,2 +1,4 @@ -const char *cc = ".========================================================================================================.\n| ____ _____ ____ _ ____ _ _ _____ |\n| / ___|___ _ __ ___ ___ |_ _|__ / ___| |_ _ ___ / ___|___ _ __ ( ) |___ / |\n| | | / _ \\| '_ ` _ \\ / _ \\ | |/ _ \\ | | | | | | |/ _ \\ | / _ \\| '_ \\ |/| | |_ \\ |\n| | |__| (_) | | | | | | __/ | | (_) | | |___| | |_| | __/ |__| (_) | | | | | |___) | |\n| \\____\\___/|_| |_| |_|\\___| |_|\\___/ \\____|_|\\__,_|\\___|\\____\\___/|_| |_| |_|____/ |\n| |\n| ____ _ _ _ _ ____ _ |\n| / ___| |__ (_) ___ __ _ __ _ ___ | | | / ___| / \\ |\n| | | | '_ \\| |/ __/ _` |/ _` |/ _ \\ | | | \\___ \\ / _ \\ |\n| | |___| | | | | (_| (_| | (_| | (_) | | |_| |___) / ___ \\ |\n| \\____|_| |_|_|\\___\\__,_|\\__, |\\___( ) \\___/|____/_/ \\_\\ |\n| |___/ |/ |\n| _ _ __ _ _ ___ _ _ ____ ___ _ _____ |\n| / \\ _ _ __ _ _ _ ___| |_ / /_ | |_| |__ ( _ )| |_| |__ |___ \\ / _ \\/ |___ / |\n| / _ \\| | | |/ _` | | | / __| __| | '_ \\| __| '_ \\ _____ / _ \\| __| '_ \\ __) | | | | | |_ \\ |\n| / ___ \\ |_| | (_| | |_| \\__ \\ |_ | (_) | |_| | | | |_____| | (_) | |_| | | | / __/| |_| | |___) | |\n| /_/ \\_\\__,_|\\__, |\\__,_|___/\\__| \\___/ \\__|_| |_| \\___/ \\__|_| |_| |_____|\\___/|_|____/ |\n| |___/ |\n| _ |\n| __ ____ ____ __ ___| |_ _ ___ ___ ___ _ __ ___ ___ _ __ ___ |\n| \\ \\ /\\ / /\\ \\ /\\ / /\\ \\ /\\ / / / __| | | | |/ _ \\/ __/ _ \\| '_ \\ / __/ _ \\| '_ ` _ \\ |\n| \\ V V / \\ V V / \\ V V / _ | (__| | |_| | __/ (_| (_) | | | | _ | (_| (_) | | | | | | |\n| \\_/\\_/ \\_/\\_/ \\_/\\_/ (_) \\___|_|\\__,_|\\___|\\___\\___/|_| |_| (_) \\___\\___/|_| |_| |_| |\n| |\n.========================================================================================================.\n"; + +const char *cc = ".========================================================================================================.\n| ____ _____ ____ _ ____ _ _ _____ |\n| / ___|___ _ __ ___ ___ |_ _|__ / ___| |_ _ ___ / ___|___ _ __ ( ) |___ / |\n| | | / _ \\| '_ ` _ \\ / _ \\ | |/ _ \\ | | | | | | |/ _ \\ | / _ \\| '_ \\ |/| | |_ \\ |\n| | |__| (_) | | | | | | __/ | | (_) | | |___| | |_| | __/ |__| (_) | | | | | |___) | |\n| \\____\\___/|_| |_| |_|\\___| |_|\\___/ \\____|_|\\__,_|\\___|\\____\\___/|_| |_| |_|____/ |\n| |\n| ____ _ _ _ _ ____ _ |\n| / ___| |__ (_) ___ __ _ __ _ ___ | | | / ___| / \\ |\n| | | | '_ \\| |/ __/ _` |/ _` |/ _ \\ | | | \\___ \\ / _ \\ |\n| | |___| | | | | (_| (_| | (_| | (_) | | |_| |___) / ___ \\ |\n| \\____|_| |_|_|\\___\\__,_|\\__, |\\___( ) \\___/|____/_/ \\_\\ |\n| |___/ |/ |\n| _ _ __ _ _ ___ _ _ ____ ___ _ _____ |\n| / \\ _ _ __ _ _ _ ___| |_ / /_ | |_| |__ ( _ )| |_| |__ |___ \\ / _ \\/ |___ / |\n| / _ \\| | | |/ _` | | | / __| __| | '_ \\| __| '_ \\ _____ / _ \\| __| '_ \\ __) | | | | | |_ \\ |\n| / ___ \\ |_| | (_| | |_| \\__ \\ |_ | (_) | |_| | | | |_____| | (_) | |_| | | | / __/| |_| | |___) | |\n| /_/ \\_\\__,_|\\__, |\\__,_|___/\\__| \\___/ \\__|_| |_| \\___/ \\__|_| |_| |_____|\\___/|_|____/ |\n| |___/ |\n| _ |\n| __ ____ ____ __ ___| |_ _ ___ ___ ___ _ __ ___ ___ _ __ ___ |\n| \\ \\ /\\ / /\\ \\ /\\ / /\\ \\ /\\ / / / __| | | | |/ _ \\/ __/ _ \\| '_ \\ / __/ _ \\| '_ ` _ \\ |\n| \\ V V / \\ V V / \\ V V / _ | (__| | |_| | __/ (_| (_) | | | | _ | (_| (_) | | | | | | |\n| \\_/\\_/ \\_/\\_/ \\_/\\_/ (_) \\___|_|\\__,_|\\___|\\___\\___/|_| |_| (_) \\___\\___/|_| |_| |_| |\n| |\n.========================================================================================================.\n"; +const char *cc_s = ".===============================================================.\n| _ |\n| ___| |_ _ ___ ___ ___ _ __ ___ ___ _ __ ___ |\n| / __| | | | |/ _ \\/ __/ _ \\| '_ \\ / __/ _ \\| '_ ` _ \\ |\n| | (__| | |_| | __/ (_| (_) | | | | _ | (_| (_) | | | | | | |\n| \\___|_|\\__,_|\\___|\\___\\___/|_| |_| (_) \\___\\___/|_| |_| |_| |\n| |\n.===============================================================.\n"; diff --git a/src/switch_core.c b/src/switch_core.c index 30b94232c4..a747a9dc27 100644 --- a/src/switch_core.c +++ b/src/switch_core.c @@ -186,6 +186,31 @@ SWITCH_DECLARE(FILE *) switch_core_get_console(void) return runtime.console; } +SWITCH_DECLARE(void) switch_core_screen_size(int *x, int *y) +{ + +#ifdef WIN32 + CONSOLE_SCREEN_BUFFER_INFO csbi; + int ret; + + if ((ret = GetConsoleScreenBufferInfo(GetStdHandle( STD_OUTPUT_HANDLE ), &csbi))) { + if (x) *x = csbi.dwSize.X; + if (y) *y = csbi.dwSize.Y; + } + +#elif TIOCGWINSZ + struct winsize w; + ioctl(0, TIOCGWINSZ, &w); + + if (x) *x = w.ws_col; + if (y) *y = w.ws_row; +#else + if (x) *x = 24; + if (x) *x = 80; +#endif + +} + SWITCH_DECLARE(FILE *) switch_core_data_channel(switch_text_channel_t channel) { FILE *handle = stdout; @@ -1964,6 +1989,8 @@ SWITCH_DECLARE(switch_status_t) switch_core_init_and_modload(switch_core_flag_t { switch_event_t *event; char *cmd; + int x = 0; + const char *use = NULL; #include "cc.h" @@ -2000,14 +2027,19 @@ SWITCH_DECLARE(switch_status_t) switch_core_init_and_modload(switch_core_flag_t switch_event_fire(&event); } + switch_core_screen_size(&x, NULL); + + use = (x > 100) ? cc : cc_s; + #ifdef WIN32 - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "%s%s\n\n", switch_core_banner(), cc); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "%s%s\n\n", switch_core_banner(), use); #else switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "%s%s%s%s%s%s\n\n", SWITCH_SEQ_DEFAULT_COLOR, SWITCH_SEQ_FYELLOW, SWITCH_SEQ_BBLUE, switch_core_banner(), - cc, SWITCH_SEQ_DEFAULT_COLOR); + use, SWITCH_SEQ_DEFAULT_COLOR); + #endif @@ -2017,6 +2049,11 @@ SWITCH_DECLARE(switch_status_t) switch_core_init_and_modload(switch_core_flag_t switch_core_session_limit(0), switch_core_sessions_per_second(0), switch_test_flag((&runtime), SCF_USE_SQL) ? "Enabled" : "Disabled"); + + if (x < 160) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "\n[This app Best viewed at 160x60 or more..]\n"); + } + switch_clear_flag((&runtime), SCF_NO_NEW_SESSIONS); if ((cmd = switch_core_get_variable_dup("api_on_startup"))) { From b9897750854d1ddc68bd256b938078629a5dd178 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Mon, 24 Sep 2012 17:07:55 -0500 Subject: [PATCH 055/252] followup for cent5 --- src/switch_core.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/switch_core.c b/src/switch_core.c index a747a9dc27..7bd11609d3 100644 --- a/src/switch_core.c +++ b/src/switch_core.c @@ -186,6 +186,9 @@ SWITCH_DECLARE(FILE *) switch_core_get_console(void) return runtime.console; } +#ifdef HAVE_SYS_IOCTL_H +#include +#endif SWITCH_DECLARE(void) switch_core_screen_size(int *x, int *y) { From 614ba049b182dc753b2d0543075da6128e481c99 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Mon, 24 Sep 2012 17:53:23 -0500 Subject: [PATCH 056/252] add proto --- src/include/switch_core.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/include/switch_core.h b/src/include/switch_core.h index b340078f41..4f26719d32 100644 --- a/src/include/switch_core.h +++ b/src/include/switch_core.h @@ -139,6 +139,7 @@ struct switch_core_port_allocator; ///\{ +SWITCH_DECLARE(void) switch_core_screen_size(int *x, int *y); SWITCH_DECLARE(void) switch_core_session_sched_heartbeat(switch_core_session_t *session, uint32_t seconds); SWITCH_DECLARE(void) switch_core_session_unsched_heartbeat(switch_core_session_t *session); From f997cc25d1bb2d370f119213acb2f710fed17281 Mon Sep 17 00:00:00 2001 From: Jeff Lenk Date: Mon, 24 Sep 2012 22:35:08 -0500 Subject: [PATCH 057/252] remove trailing backlash from windows temp paths - mostly cosmetic --- src/switch_core.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/switch_core.c b/src/switch_core.c index 7bd11609d3..20dfd9b411 100644 --- a/src/switch_core.c +++ b/src/switch_core.c @@ -661,6 +661,7 @@ SWITCH_DECLARE(void) switch_core_set_globals(void) #else #ifdef WIN32 GetTempPath(dwBufSize, lpPathBuffer); + lpPathBuffer[strlen(lpPathBuffer)-1] = 0; switch_snprintf(SWITCH_GLOBAL_dirs.temp_dir, BUFSIZE, "%s", lpPathBuffer); #else switch_snprintf(SWITCH_GLOBAL_dirs.temp_dir, BUFSIZE, "%s", "/tmp"); From 176d60beb337d91618942ee45afef8f1538e92fa Mon Sep 17 00:00:00 2001 From: Jeff Lenk Date: Tue, 25 Sep 2012 08:55:44 -0500 Subject: [PATCH 058/252] FS-4645 does this help --- src/switch_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/switch_core.c b/src/switch_core.c index 20dfd9b411..86804f09b7 100644 --- a/src/switch_core.c +++ b/src/switch_core.c @@ -201,7 +201,7 @@ SWITCH_DECLARE(void) switch_core_screen_size(int *x, int *y) if (y) *y = csbi.dwSize.Y; } -#elif TIOCGWINSZ +#elif defined(TIOCGWINSZ) struct winsize w; ioctl(0, TIOCGWINSZ, &w); From ee50ed23ab213b24946ecf1ae87ba79a767f0487 Mon Sep 17 00:00:00 2001 From: Michael Jerris Date: Tue, 25 Sep 2012 14:19:00 -0400 Subject: [PATCH 059/252] FS-4645: --resolve fix build error in fs_cli --- libs/esl/fs_cli.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/esl/fs_cli.c b/libs/esl/fs_cli.c index bde78f183b..8b9a065a60 100644 --- a/libs/esl/fs_cli.c +++ b/libs/esl/fs_cli.c @@ -128,7 +128,7 @@ static void screen_size(int *x, int *y) if (y) *y = csbi.dwSize.Y; } -#elif TIOCGWINSZ +#elif defined(TIOCGWINSZ) struct winsize w; ioctl(0, TIOCGWINSZ, &w); From 0fe6aa4d0a1c8ab58430c7b4c2530fe80c9bb69b Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Tue, 25 Sep 2012 16:08:45 -0500 Subject: [PATCH 060/252] switch another file parsing function to use buffered read --- src/switch_console.c | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/src/switch_console.c b/src/switch_console.c index 41d308e339..3945baec7c 100644 --- a/src/switch_console.c +++ b/src/switch_console.c @@ -203,7 +203,7 @@ SWITCH_DECLARE_NONSTD(switch_status_t) switch_console_stream_write(switch_stream SWITCH_DECLARE(switch_status_t) switch_stream_write_file_contents(switch_stream_handle_t *stream, const char *path) { char *dpath = NULL; - int fd; + FILE *fd = NULL; switch_status_t status = SWITCH_STATUS_FALSE; if (!switch_is_file_path(path)) { @@ -211,12 +211,14 @@ SWITCH_DECLARE(switch_status_t) switch_stream_write_file_contents(switch_stream_ path = dpath; } - if ((fd = open(path, O_RDONLY)) > -1) { - char buf[2048] = { 0 }; - while (switch_fd_read_line(fd, buf, sizeof(buf))) { - stream->write_function(stream, "%s", buf); + if ((fd = fopen(path, "r"))) { + char *line_buf = NULL; + switch_size_t llen = 0; + + while (switch_fp_read_dline(fd, &line_buf, &llen)) { + stream->write_function(stream, "%s", line_buf); } - close(fd); + fclose(fd); status = SWITCH_STATUS_SUCCESS; } @@ -246,7 +248,7 @@ SWITCH_DECLARE(char *) switch_console_expand_alias(char *cmd, char *arg) return NULL; } - if (switch_core_db_handle(&db) != SWITCH_STATUS_SUCCESS) { + if (switch_core_persist_db_handle(&db) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Database Error\n"); return NULL; } @@ -682,7 +684,7 @@ SWITCH_DECLARE(unsigned char) switch_console_complete(const char *line, const ch #endif #endif - if (switch_core_db_handle(&db) != SWITCH_STATUS_SUCCESS) { + if (switch_core_persist_db_handle(&db) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Database Error\n"); return CC_ERROR; } @@ -1774,7 +1776,7 @@ SWITCH_DECLARE(switch_status_t) switch_console_set_complete(const char *string) SWITCH_STANDARD_STREAM(mystream); - if (switch_core_db_handle(&db) != SWITCH_STATUS_SUCCESS) { + if (switch_core_persist_db_handle(&db) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Database Error\n"); free(mystream.data); free(mydata); @@ -1857,7 +1859,7 @@ SWITCH_DECLARE(switch_status_t) switch_console_set_alias(const char *string) switch_cache_db_handle_t *db = NULL; char *sql = NULL; - if (switch_core_db_handle(&db) != SWITCH_STATUS_SUCCESS) { + if (switch_core_persist_db_handle(&db) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Database Error\n"); free(mydata); return SWITCH_STATUS_FALSE; From dbf5153fb7d1b4d5a09f8c139b3d288c17656e74 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Tue, 25 Sep 2012 16:12:23 -0500 Subject: [PATCH 061/252] speed improvements: change scheduler to SCHED_FIFO, Disable realtime throttling, use in-memory db for sqlite core channels table (set core-db-name to 'core' in switch.conf.xml for previous behaviour of using the core sqlite file, now only aliases will be in the persistant db) --- src/include/switch_core.h | 3 +++ src/switch_core.c | 22 ++++++++++++++++++- src/switch_core_sqldb.c | 45 ++++++++++++++++++++++++++++++++++++++- 3 files changed, 68 insertions(+), 2 deletions(-) diff --git a/src/include/switch_core.h b/src/include/switch_core.h index 4f26719d32..507f18a166 100644 --- a/src/include/switch_core.h +++ b/src/include/switch_core.h @@ -2303,6 +2303,9 @@ SWITCH_DECLARE(switch_status_t) _switch_core_db_handle(switch_cache_db_handle_t SWITCH_DECLARE(switch_status_t) _switch_core_recovery_db_handle(switch_cache_db_handle_t ** dbh, const char *file, const char *func, int line); #define switch_core_recovery_db_handle(_a) _switch_core_recovery_db_handle(_a, __FILE__, __SWITCH_FUNC__, __LINE__) +SWITCH_DECLARE(switch_status_t) _switch_core_persist_db_handle(switch_cache_db_handle_t ** dbh, const char *file, const char *func, int line); +#define switch_core_persist_db_handle(_a) _switch_core_persist_db_handle(_a, __FILE__, __SWITCH_FUNC__, __LINE__) + SWITCH_DECLARE(switch_bool_t) switch_cache_db_test_reactive(switch_cache_db_handle_t *db, const char *test_sql, const char *drop_sql, const char *reactive_sql); SWITCH_DECLARE(switch_status_t) switch_cache_db_persistant_execute(switch_cache_db_handle_t *dbh, const char *sql, uint32_t retries); diff --git a/src/switch_core.c b/src/switch_core.c index 86804f09b7..257c37a646 100644 --- a/src/switch_core.c +++ b/src/switch_core.c @@ -731,16 +731,36 @@ SWITCH_DECLARE(int32_t) set_realtime_priority(void) * Try to use a round-robin scheduler * with a fallback if that does not work */ + int fd; + const char *rt = "/proc/sys/kernel/sched_rt_runtime_us"; + char data[] = "-1\n"; struct sched_param sched = { 0 }; sched.sched_priority = 1; - if (sched_setscheduler(0, SCHED_RR, &sched)) { + if (sched_setscheduler(0, SCHED_FIFO, &sched)) { sched.sched_priority = 0; if (sched_setscheduler(0, SCHED_OTHER, &sched)) { return -1; } } + + if ((fd = open(rt, O_WRONLY)) > 0) { + int r; + + if (!(r = write(fd, data, sizeof(data)))) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Error Disablling RT limits [%s][%d]\n", rt, r); + } else { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Disabling RT throttling.\n"); + } + close(fd); + } else { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Error opening %s\n", rt); + } + + #endif + + #ifdef HAVE_SETPRIORITY /* * setpriority() works on FreeBSD (6.2), nice() doesn't diff --git a/src/switch_core_sqldb.c b/src/switch_core_sqldb.c index 200ed3507e..b0f52b6150 100644 --- a/src/switch_core_sqldb.c +++ b/src/switch_core_sqldb.c @@ -176,7 +176,7 @@ static switch_cache_db_handle_t *get_handle(const char *db_str, const char *user } -#define SWITCH_CORE_DB "core" +#define SWITCH_CORE_DB "file:scoreboard?mode=memory&cache=shared" /*! \brief Open the default system database */ @@ -218,6 +218,49 @@ SWITCH_DECLARE(switch_status_t) _switch_core_db_handle(switch_cache_db_handle_t return r; } +#define SWITCH_CORE_PERSIST_DB "core" +/*! + \brief Open the default system database +*/ +SWITCH_DECLARE(switch_status_t) _switch_core_persist_db_handle(switch_cache_db_handle_t **dbh, const char *file, const char *func, int line) +{ + switch_cache_db_connection_options_t options = { {0} }; + switch_status_t r; + + if (!sql_manager.manage) { + return SWITCH_STATUS_FALSE; + } + + if (zstr(runtime.odbc_dsn)) { + if (switch_test_flag((&runtime), SCF_CORE_ODBC_REQ)) { + return SWITCH_STATUS_FALSE; + } + + if (runtime.dbname) { + options.core_db_options.db_path = runtime.dbname; + } else { + options.core_db_options.db_path = SWITCH_CORE_PERSIST_DB; + } + r = _switch_cache_db_get_db_handle(dbh, SCDB_TYPE_CORE_DB, &options, file, func, line); + + } else { + options.odbc_options.dsn = runtime.odbc_dsn; + options.odbc_options.user = runtime.odbc_user; + options.odbc_options.pass = runtime.odbc_pass; + + r = _switch_cache_db_get_db_handle(dbh, SCDB_TYPE_ODBC, &options, file, func, line); + } + + /* I *think* we can do without this now, if not let me know + if (r == SWITCH_STATUS_SUCCESS && !(*dbh)->io_mutex) { + (*dbh)->io_mutex = sql_manager.io_mutex; + } + */ + + return r; +} + + #define SWITCH_CORE_RECOVERY_DB "core_recovery" SWITCH_DECLARE(switch_status_t) _switch_core_recovery_db_handle(switch_cache_db_handle_t **dbh, const char *file, const char *func, int line) { From 817439d76a5fc268a71efc32d0b6607f8bcd610d Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Tue, 25 Sep 2012 16:12:51 -0500 Subject: [PATCH 062/252] check for SCHED_FIFO in configure --- configure.in | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/configure.in b/configure.in index 5a97b86ace..92a88048fd 100644 --- a/configure.in +++ b/configure.in @@ -532,6 +532,12 @@ AC_CHECK_DECL([SCHED_RR], #include #endif]) +AC_CHECK_DECL([SCHED_FIFO], + [AC_DEFINE([HAVE_SCHED_FIFO],[1],[SCHED_FIFO constant for sched_setscheduler])],, + [#ifdef HAVE_SCHED_H + #include + #endif]) + # # use mlockall only on linux (for now; if available) # @@ -572,7 +578,6 @@ if test "x${ac_cv_func_sched_setscheduler}" = "xyes" -a \ then AC_DEFINE([USE_SCHED_SETSCHEDULER],[1],[Enable round-robin scheduler using sched_setscheduler]) fi - # # xmlrpc-c checks # From b15468d1aaf74fa80573354f2d47a522faa7a08e Mon Sep 17 00:00:00 2001 From: Jeff Lenk Date: Wed, 26 Sep 2012 08:11:08 -0500 Subject: [PATCH 063/252] OPENZAP-192 --resolve --- libs/freetdm/src/ftdm_io.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libs/freetdm/src/ftdm_io.c b/libs/freetdm/src/ftdm_io.c index d99561566c..932ce30aa7 100644 --- a/libs/freetdm/src/ftdm_io.c +++ b/libs/freetdm/src/ftdm_io.c @@ -4735,7 +4735,7 @@ static void print_core_usage(ftdm_stream_handle_t *stream) static unsigned long long ftdm_str2val(const char *str, val_str_t *val_str_table, ftdm_size_t array_size, unsigned long long default_val) { - int i; + ftdm_size_t i; for (i = 0; i < array_size; i++) { if (!strcasecmp(val_str_table[i].str, str)) { return val_str_table[i].val; @@ -4746,7 +4746,7 @@ static unsigned long long ftdm_str2val(const char *str, val_str_t *val_str_table static const char *ftdm_val2str(unsigned long long val, val_str_t *val_str_table, ftdm_size_t array_size, const char *default_str) { - int i; + ftdm_size_t i; for (i = 0; i < array_size; i++) { if (val_str_table[i].val == val) { return val_str_table[i].str; From d77dfdbbf2c963125f21d087b764112ac7b7c7a0 Mon Sep 17 00:00:00 2001 From: Jeff Lenk Date: Wed, 26 Sep 2012 08:16:28 -0500 Subject: [PATCH 064/252] FS-4219 --resolve windows revision display human thanks Peter --- libs/win32/util.vbs | 35 ++++++----------------------------- 1 file changed, 6 insertions(+), 29 deletions(-) diff --git a/libs/win32/util.vbs b/libs/win32/util.vbs index 2c35dfdcb7..0ce107c4c4 100644 --- a/libs/win32/util.vbs +++ b/libs/win32/util.vbs @@ -314,31 +314,6 @@ Function GetTimeUTC() End Function -Function GetWeekDay(DateTime) - - DayOfWeek = DatePart("w", DateTime) - - Select Case DayOfWeek - Case 1 GetWeekDay = "Sun" - Case 2 GetWeekDay = "Mon" - Case 3 GetWeekDay = "Tue" - Case 4 GetWeekDay = "Wed" - Case 5 GetWeekDay = "Thu" - Case 6 GetWeekDay = "Fri" - Case 7 GetWeekDay = "Sat" - End Select - -End Function - -Function GetMonthName(DateTime) - - Val = MonthName(Month(DateTime), True) - Val = UCase(Left(Val, 1)) & Mid(Val, 2, 4) - - GetMonthName = Val - -End Function - Sub CreateVersion(tmpFolder, VersionDir, includebase, includedest) Dim oExec @@ -364,7 +339,7 @@ Sub CreateVersion(tmpFolder, VersionDir, includebase, includedest) If IsNumeric(strFromProc) Then lastChangedDateTime = DateAdd("s", strFromProc, "01/01/1970 00:00:00") strLastCommit = YEAR(lastChangedDateTime) & Pd(Month(lastChangedDateTime), 2) & Pd(DAY(lastChangedDateTime), 2) & "T" & Pd(Hour(lastChangedDateTime), 2) & Pd(Minute(lastChangedDateTime), 2) & Pd(Second(lastChangedDateTime), 2) & "Z" - strLastCommitHuman = GetWeekDay(lastChangedDateTime) & ", " & Pd(DAY(lastChangedDateTime), 2) & " " & GetMonthName(lastChangedDateTime) & " " & YEAR(lastChangedDateTime) & " " & Pd(Hour(lastChangedDateTime), 2) & ":" & Pd(Minute(lastChangedDateTime), 2) & ":" & Pd(Second(lastChangedDateTime), 2) & " Z" + strLastCommitHuman = YEAR(lastChangedDateTime) & "-" & Pd(Month(lastChangedDateTime), 2) & "-" & Pd(DAY(lastChangedDateTime), 2) & " " & Pd(Hour(lastChangedDateTime), 2) & ":" & Pd(Minute(lastChangedDateTime), 2) & ":" & Pd(Second(lastChangedDateTime), 2) & "Z" Else strLastCommit = "" strLastCommitHuman = "" @@ -372,17 +347,19 @@ Sub CreateVersion(tmpFolder, VersionDir, includebase, includedest) 'Get revision hash strRevision = ExecAndGetResult(tmpFolder, VersionDir, "git rev-list -n1 --abbrev=10 --abbrev-commit HEAD") + strRevisionHuman = ExecAndGetResult(tmpFolder, VersionDir, "git rev-list -n1 --abbrev=7 --abbrev-commit HEAD") - If strLastCommit <> "" And strLastCommitHuman <> "" And strRevision <> "" Then + If strLastCommit <> "" And strLastCommitHuman <> "" And strRevision <> "" And strRevisionHuman <> "" Then 'Bild version string strGitVer = "+git~" & strLastCommit & "~" & strRevision - strVerHuman = strVerRev & "; git at commit " & strRevision & " on " & strLastCommitHuman + strVerHuman = "git " & strRevisionHuman & " " & strLastCommitHuman 'Check for local changes, if found, append to git revision string If ShowUnclean Then If ExecAndGetExitCode(tmpFolder, VersionDir, "git diff-index --quiet HEAD") <> 0 Then lastChangedDateTime = GetTimeUTC() strGitVer = strGitVer & "+unclean~" & YEAR(lastChangedDateTime) & Pd(Month(lastChangedDateTime), 2) & Pd(DAY(lastChangedDateTime), 2) & "T" & Pd(Hour(lastChangedDateTime), 2) & Pd(Minute(lastChangedDateTime), 2) & Pd(Second(lastChangedDateTime), 2) & "Z" + strVerHuman = strVerHuman & " unclean " & YEAR(lastChangedDateTime) & "-" & Pd(Month(lastChangedDateTime), 2) & "-" & Pd(DAY(lastChangedDateTime), 2) & " " & Pd(Hour(lastChangedDateTime), 2) & ":" & Pd(Minute(lastChangedDateTime), 2) & ":" & Pd(Second(lastChangedDateTime), 2) & "Z" End If End If Else @@ -393,7 +370,7 @@ Sub CreateVersion(tmpFolder, VersionDir, includebase, includedest) VERSION=VERSION & strGitVer sLastVersion = "" - Set sLastFile = FSO.OpenTextFile(tmpFolder & "lastversion", ForReading, true, OpenAsASCII) + Set sLastFile = FSO.OpenTextFile(tmpFolder & "lastversion", ForReading, True, OpenAsASCII) If Not sLastFile.atEndOfStream Then sLastVersion = sLastFile.ReadLine() End If From e50f7a92e9a9c215022ca747747c56201c105e2e Mon Sep 17 00:00:00 2001 From: Giovanni Maruzzelli Date: Wed, 26 Sep 2012 16:53:07 +0200 Subject: [PATCH 065/252] gsmopen: FS-4652 , compilation failed with Mobigator --- .../mod_gsmopen/gsmopen_protocol.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/mod/endpoints/mod_gsmopen/alsa_nogsmlib_nocplusplus/mod_gsmopen/gsmopen_protocol.c b/src/mod/endpoints/mod_gsmopen/alsa_nogsmlib_nocplusplus/mod_gsmopen/gsmopen_protocol.c index 6834a1d880..00c83d0640 100644 --- a/src/mod/endpoints/mod_gsmopen/alsa_nogsmlib_nocplusplus/mod_gsmopen/gsmopen_protocol.c +++ b/src/mod/endpoints/mod_gsmopen/alsa_nogsmlib_nocplusplus/mod_gsmopen/gsmopen_protocol.c @@ -1961,7 +1961,7 @@ int gsmopen_serial_read_AT(private_t * tech_pvt, int look_for_ack, int timeout_u if (tech_pvt->reading_sms_msg > 1 && at_ack == -1) { int c; char sms_body[16000]; - int err = 0; + //int err = 0; memset(sms_body, '\0', sizeof(sms_body)); if (strncmp(tech_pvt->line_array.result[i], "+CMGR", 5) == 0) { /* we are reading the "header" of an SMS */ @@ -2005,10 +2005,10 @@ int gsmopen_serial_read_AT(private_t * tech_pvt, int look_for_ack, int timeout_u if (which_field == 1) { //FIXME why this? err = ucs2_to_utf8(tech_pvt, content, content2, sizeof(content2)); //err = ucs2_to_utf8(tech_pvt, content, content2, sizeof(content2)); - err = 0; + //err = 0; strncpy(content2, content, sizeof(content2)); } else { - err = 0; + //err = 0; strncpy(content2, content, sizeof(content2)); } DEBUGA_GSMOPEN("%d content2=%s\n", GSMOPEN_P_LOG, which_field, content2); @@ -3287,7 +3287,7 @@ int alsa_write(private_t * tech_pvt, short *data, int datalen) static char silencebuf[8000]; static int sizpos = 0; int len = sizpos; - int pos; + //int pos; int res = 0; time_t now_timestamp; /* size_t frames = 0; */ @@ -3313,7 +3313,7 @@ int alsa_write(private_t * tech_pvt, short *data, int datalen) memcpy(sizbuf + sizpos, data, datalen); memset(data, 255, datalen); len += datalen; - pos = 0; + //pos = 0; #ifdef ALSA_MONITOR From 0fc0b999505d1a4664ee566cf28696f597a20f79 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Wed, 26 Sep 2012 08:01:25 -0500 Subject: [PATCH 066/252] FS-4654 --resolve --- src/switch_console.c | 4 ++-- src/switch_core_sqldb.c | 7 ++++++- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/switch_console.c b/src/switch_console.c index 3945baec7c..d461333860 100644 --- a/src/switch_console.c +++ b/src/switch_console.c @@ -684,7 +684,7 @@ SWITCH_DECLARE(unsigned char) switch_console_complete(const char *line, const ch #endif #endif - if (switch_core_persist_db_handle(&db) != SWITCH_STATUS_SUCCESS) { + if (switch_core_db_handle(&db) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Database Error\n"); return CC_ERROR; } @@ -1776,7 +1776,7 @@ SWITCH_DECLARE(switch_status_t) switch_console_set_complete(const char *string) SWITCH_STANDARD_STREAM(mystream); - if (switch_core_persist_db_handle(&db) != SWITCH_STATUS_SUCCESS) { + if (switch_core_db_handle(&db) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Database Error\n"); free(mystream.data); free(mydata); diff --git a/src/switch_core_sqldb.c b/src/switch_core_sqldb.c index b0f52b6150..5a76d0e1ae 100644 --- a/src/switch_core_sqldb.c +++ b/src/switch_core_sqldb.c @@ -2409,9 +2409,14 @@ switch_status_t switch_core_sqldb_start(switch_memory_pool_t *pool, switch_bool_ break; } + { + switch_cache_db_handle_t *db = NULL; + switch_core_persist_db_handle(&db) + switch_cache_db_test_reactive(db, "select hostname from aliases", "DROP TABLE aliases", create_alias_sql); + switch_cache_db_release_db_handle(&db); + } switch_cache_db_test_reactive(sql_manager.dbh, "select hostname from complete", "DROP TABLE complete", create_complete_sql); - switch_cache_db_test_reactive(sql_manager.dbh, "select hostname from aliases", "DROP TABLE aliases", create_alias_sql); switch_cache_db_test_reactive(sql_manager.dbh, "select hostname from nat", "DROP TABLE nat", create_nat_sql); switch_cache_db_test_reactive(sql_manager.dbh, "delete from registrations where reg_user='' or network_proto='tcp' or network_proto='tls'", "DROP TABLE registrations", create_registrations_sql); From 8075b01569e402ec9eb8d5c7df4214f012ce0a8a Mon Sep 17 00:00:00 2001 From: Stefan Knoblich Date: Wed, 26 Sep 2012 17:19:15 +0200 Subject: [PATCH 067/252] Fix error in switch_core_screen_size() and screen_size() fallback code. Signed-off-by: Stefan Knoblich --- libs/esl/fs_cli.c | 2 +- src/switch_core.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libs/esl/fs_cli.c b/libs/esl/fs_cli.c index 8b9a065a60..80388db3a4 100644 --- a/libs/esl/fs_cli.c +++ b/libs/esl/fs_cli.c @@ -135,8 +135,8 @@ static void screen_size(int *x, int *y) if (x) *x = w.ws_col; if (y) *y = w.ws_row; #else - if (x) *x = 24; if (x) *x = 80; + if (y) *y = 24; #endif } diff --git a/src/switch_core.c b/src/switch_core.c index 257c37a646..6cce356061 100644 --- a/src/switch_core.c +++ b/src/switch_core.c @@ -208,8 +208,8 @@ SWITCH_DECLARE(void) switch_core_screen_size(int *x, int *y) if (x) *x = w.ws_col; if (y) *y = w.ws_row; #else - if (x) *x = 24; if (x) *x = 80; + if (y) *y = 24; #endif } From 507de0a7e514cee62c21526e89dfd2b70a7e228c Mon Sep 17 00:00:00 2001 From: Giovanni Maruzzelli Date: Wed, 26 Sep 2012 17:23:43 +0200 Subject: [PATCH 068/252] gsmopen: FS-4652 , compilation failed with Mobigator --- .../mod_gsmopen/mod_gsmopen.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/mod/endpoints/mod_gsmopen/alsa_nogsmlib_nocplusplus/mod_gsmopen/mod_gsmopen.c b/src/mod/endpoints/mod_gsmopen/alsa_nogsmlib_nocplusplus/mod_gsmopen/mod_gsmopen.c index fdfbca74b8..40c6f51801 100644 --- a/src/mod/endpoints/mod_gsmopen/alsa_nogsmlib_nocplusplus/mod_gsmopen/mod_gsmopen.c +++ b/src/mod/endpoints/mod_gsmopen/alsa_nogsmlib_nocplusplus/mod_gsmopen/mod_gsmopen.c @@ -1392,9 +1392,9 @@ static switch_status_t load_config(int reload_type) const char *dialplan = "XML"; const char *destination = "5000"; const char *controldevice_name = "/dev/ttyACM0"; - char *digit_timeout = NULL; - char *max_digits = NULL; - char *hotline = NULL; + char *digit_timeout; + char *max_digits; + char *hotline; char *dial_regex = NULL; char *hold_music = NULL; char *fail_dial_regex = NULL; @@ -1469,10 +1469,10 @@ static switch_status_t load_config(int reload_type) #else const char *no_sound = "1"; #endif // defined(GSMOPEN_ALSA) || defined(GSMOPEN_PORTAUDIO) - const char *portaudiocindex = "1"; - const char *portaudiopindex = "1"; - const char *speexecho = "1"; - const char *speexpreprocess = "1"; + const char *portaudiocindex; + const char *portaudiopindex; + const char *speexecho; + const char *speexpreprocess; uint32_t interface_id = 0; #ifdef WIN32 @@ -2869,7 +2869,7 @@ SWITCH_STANDARD_API(gsmopen_boost_audio_function) { char *mycmd = NULL, *argv[10] = { 0 }; int argc = 0; - private_t *tech_pvt = NULL; + private_t *tech_pvt; if (!zstr(cmd) && (mycmd = strdup(cmd))) { argc = switch_separate_string(mycmd, ' ', argv, (sizeof(argv) / sizeof(argv[0]))); From 3df5c5f2f4efa253067946f62e26c46dff596574 Mon Sep 17 00:00:00 2001 From: Stefan Knoblich Date: Wed, 26 Sep 2012 17:44:39 +0200 Subject: [PATCH 069/252] FreeSWITCH: Add missing semicolon Signed-off-by: Stefan Knoblich --- src/switch_core_sqldb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/switch_core_sqldb.c b/src/switch_core_sqldb.c index 5a76d0e1ae..d77b432c90 100644 --- a/src/switch_core_sqldb.c +++ b/src/switch_core_sqldb.c @@ -2411,7 +2411,7 @@ switch_status_t switch_core_sqldb_start(switch_memory_pool_t *pool, switch_bool_ { switch_cache_db_handle_t *db = NULL; - switch_core_persist_db_handle(&db) + switch_core_persist_db_handle(&db); switch_cache_db_test_reactive(db, "select hostname from aliases", "DROP TABLE aliases", create_alias_sql); switch_cache_db_release_db_handle(&db); } From f102f7b4c4d3f8e86be80ca7acd8b017a2636f46 Mon Sep 17 00:00:00 2001 From: Giovanni Maruzzelli Date: Wed, 26 Sep 2012 18:55:54 +0200 Subject: [PATCH 070/252] gsmopen: FS-4652 , compilation failed with Mobigator --- .../alsa_nogsmlib_nocplusplus/mod_gsmopen/mod_gsmopen.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/mod/endpoints/mod_gsmopen/alsa_nogsmlib_nocplusplus/mod_gsmopen/mod_gsmopen.c b/src/mod/endpoints/mod_gsmopen/alsa_nogsmlib_nocplusplus/mod_gsmopen/mod_gsmopen.c index 40c6f51801..2841d2146a 100644 --- a/src/mod/endpoints/mod_gsmopen/alsa_nogsmlib_nocplusplus/mod_gsmopen/mod_gsmopen.c +++ b/src/mod/endpoints/mod_gsmopen/alsa_nogsmlib_nocplusplus/mod_gsmopen/mod_gsmopen.c @@ -1469,10 +1469,12 @@ static switch_status_t load_config(int reload_type) #else const char *no_sound = "1"; #endif // defined(GSMOPEN_ALSA) || defined(GSMOPEN_PORTAUDIO) +#ifdef GSMOPEN_PORTAUDIO const char *portaudiocindex; const char *portaudiopindex; const char *speexecho; const char *speexpreprocess; +#endif// GSMOPEN_PORTAUDIO uint32_t interface_id = 0; #ifdef WIN32 @@ -1620,6 +1622,7 @@ static switch_status_t load_config(int reload_type) alsacname = val; } else if (!strcasecmp(var, "alsapname")) { alsapname = val; +#ifdef GSMOPEN_PORTAUDIO } else if (!strcasecmp(var, "portaudiocindex")) { portaudiocindex = val; } else if (!strcasecmp(var, "portaudiopindex")) { @@ -1628,6 +1631,7 @@ static switch_status_t load_config(int reload_type) speexecho = val; } else if (!strcasecmp(var, "speexpreprocess")) { speexpreprocess = val; +#endif// GSMOPEN_PORTAUDIO } else if (!strcasecmp(var, "at_early_audio")) { at_early_audio = val; } else if (!strcasecmp(var, "at_after_preinit_pause")) { From ed6f040e702844abf0d2db7bde4fc70143e26a9a Mon Sep 17 00:00:00 2001 From: Giovanni Maruzzelli Date: Wed, 26 Sep 2012 19:01:08 +0200 Subject: [PATCH 071/252] gsmopen: FS-4652 , compilation failed with Mobigator --- .../alsa_nogsmlib_nocplusplus/mod_gsmopen/mod_gsmopen.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/mod/endpoints/mod_gsmopen/alsa_nogsmlib_nocplusplus/mod_gsmopen/mod_gsmopen.c b/src/mod/endpoints/mod_gsmopen/alsa_nogsmlib_nocplusplus/mod_gsmopen/mod_gsmopen.c index 2841d2146a..17a34e5c6d 100644 --- a/src/mod/endpoints/mod_gsmopen/alsa_nogsmlib_nocplusplus/mod_gsmopen/mod_gsmopen.c +++ b/src/mod/endpoints/mod_gsmopen/alsa_nogsmlib_nocplusplus/mod_gsmopen/mod_gsmopen.c @@ -2873,7 +2873,7 @@ SWITCH_STANDARD_API(gsmopen_boost_audio_function) { char *mycmd = NULL, *argv[10] = { 0 }; int argc = 0; - private_t *tech_pvt; + //private_t *tech_pvt; if (!zstr(cmd) && (mycmd = strdup(cmd))) { argc = switch_separate_string(mycmd, ' ', argv, (sizeof(argv) / sizeof(argv[0]))); @@ -2887,7 +2887,7 @@ SWITCH_STANDARD_API(gsmopen_boost_audio_function) /* we've been asked for a normal interface name, or we have not found idle interfaces to serve as the "ANY" interface */ if (strlen(globals.GSMOPEN_INTERFACES[i].name) && (strncmp(globals.GSMOPEN_INTERFACES[i].name, argv[0], strlen(argv[0])) == 0)) { - tech_pvt = &globals.GSMOPEN_INTERFACES[i]; + //tech_pvt = &globals.GSMOPEN_INTERFACES[i]; stream->write_function(stream, "Using interface: globals.GSMOPEN_INTERFACES[%d].name=|||%s|||\n", i, globals.GSMOPEN_INTERFACES[i].name); found = 1; break; From d0ddd77cdcf26f6388bdd1631b18cb682fb01504 Mon Sep 17 00:00:00 2001 From: Giovanni Maruzzelli Date: Wed, 26 Sep 2012 19:15:42 +0200 Subject: [PATCH 072/252] gsmopen: FS-4652 , compilation failed with Mobigator --- .../mod_gsmopen/mod_gsmopen.c | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/mod/endpoints/mod_gsmopen/alsa_nogsmlib_nocplusplus/mod_gsmopen/mod_gsmopen.c b/src/mod/endpoints/mod_gsmopen/alsa_nogsmlib_nocplusplus/mod_gsmopen/mod_gsmopen.c index 17a34e5c6d..5e31e76857 100644 --- a/src/mod/endpoints/mod_gsmopen/alsa_nogsmlib_nocplusplus/mod_gsmopen/mod_gsmopen.c +++ b/src/mod/endpoints/mod_gsmopen/alsa_nogsmlib_nocplusplus/mod_gsmopen/mod_gsmopen.c @@ -1392,13 +1392,13 @@ static switch_status_t load_config(int reload_type) const char *dialplan = "XML"; const char *destination = "5000"; const char *controldevice_name = "/dev/ttyACM0"; - char *digit_timeout; - char *max_digits; - char *hotline; + //char *digit_timeout; + //char *max_digits; + //char *hotline; char *dial_regex = NULL; char *hold_music = NULL; char *fail_dial_regex = NULL; - const char *enable_callerid = "true"; + const char *enable_callerid ; const char *at_dial_pre_number = "ATD"; @@ -1506,12 +1506,12 @@ static switch_status_t load_config(int reload_type) destination = val; } else if (!strcasecmp(var, "controldevice_name")) { controldevice_name = val; - } else if (!strcasecmp(var, "digit_timeout")) { - digit_timeout = val; - } else if (!strcasecmp(var, "max_digits")) { - max_digits = val; - } else if (!strcasecmp(var, "hotline")) { - hotline = val; + //} else if (!strcasecmp(var, "digit_timeout")) { + //digit_timeout = val; + //} else if (!strcasecmp(var, "max_digits")) { + //max_digits = val; + //} else if (!strcasecmp(var, "hotline")) { + //hotline = val; } else if (!strcasecmp(var, "dial_regex")) { dial_regex = val; } else if (!strcasecmp(var, SWITCH_HOLD_MUSIC_VARIABLE)) { From a1d727cab65b779ec5f9df8c8eec6cdf8ac04c64 Mon Sep 17 00:00:00 2001 From: Giovanni Maruzzelli Date: Wed, 26 Sep 2012 19:20:27 +0200 Subject: [PATCH 073/252] gsmopen: FS-4652 , compilation failed with Mobigator --- .../alsa_nogsmlib_nocplusplus/mod_gsmopen/mod_gsmopen.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/mod/endpoints/mod_gsmopen/alsa_nogsmlib_nocplusplus/mod_gsmopen/mod_gsmopen.c b/src/mod/endpoints/mod_gsmopen/alsa_nogsmlib_nocplusplus/mod_gsmopen/mod_gsmopen.c index 5e31e76857..fc41a4a1b3 100644 --- a/src/mod/endpoints/mod_gsmopen/alsa_nogsmlib_nocplusplus/mod_gsmopen/mod_gsmopen.c +++ b/src/mod/endpoints/mod_gsmopen/alsa_nogsmlib_nocplusplus/mod_gsmopen/mod_gsmopen.c @@ -1398,7 +1398,7 @@ static switch_status_t load_config(int reload_type) char *dial_regex = NULL; char *hold_music = NULL; char *fail_dial_regex = NULL; - const char *enable_callerid ; + //const char *enable_callerid ; const char *at_dial_pre_number = "ATD"; @@ -1518,8 +1518,8 @@ static switch_status_t load_config(int reload_type) hold_music = val; } else if (!strcasecmp(var, "fail_dial_regex")) { fail_dial_regex = val; - } else if (!strcasecmp(var, "enable_callerid")) { - enable_callerid = val; + //} else if (!strcasecmp(var, "enable_callerid")) { + //enable_callerid = val; } else if (!strcasecmp(var, "at_dial_pre_number")) { at_dial_pre_number = val; } else if (!strcasecmp(var, "at_dial_post_number")) { From 155ecd96506f8d6d33da45ced1ed8856aa50ec29 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Wed, 26 Sep 2012 11:25:42 -0500 Subject: [PATCH 074/252] FS-4636 fix regression --- src/switch_ivr_originate.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/switch_ivr_originate.c b/src/switch_ivr_originate.c index 7cb296b1c6..0efa8e238e 100644 --- a/src/switch_ivr_originate.c +++ b/src/switch_ivr_originate.c @@ -1224,7 +1224,11 @@ static switch_status_t setup_ringback(originate_global_t *oglobals, originate_st switch_goto_status(SWITCH_STATUS_GENERR, end); } - switch_core_session_get_read_impl(originate_status[0].peer_session, &peer_read_impl); + if (oglobals->bridge_early_media > -1 && zstr(ringback_data) && len == 1 && originate_status[0].peer_session) { + switch_core_session_get_read_impl(originate_status[0].peer_session, &peer_read_impl); + } else { + switch_core_session_get_read_impl(oglobals->session, &peer_read_impl); + } if (switch_core_codec_init(write_codec, "L16", From 4bb5c93e4ad2ae2ee98126254be4d6c8538267b0 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Wed, 26 Sep 2012 12:10:37 -0500 Subject: [PATCH 075/252] use a lower level write func for cng packets --- src/switch_rtp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/switch_rtp.c b/src/switch_rtp.c index 0b966d8ba2..de842c5db7 100644 --- a/src/switch_rtp.c +++ b/src/switch_rtp.c @@ -977,7 +977,7 @@ static int check_srtp_and_ice(switch_rtp_t *rtp_session) switch_frame_flag_t frame_flags = SFF_NONE; data[0] = 65; rtp_session->cn++; - rtp_common_write(rtp_session, NULL, (void *) data, 2, rtp_session->cng_pt, 0, &frame_flags); + switch_rtp_write_manual(rtp_session, (void *) data, 2, 0, rtp_session->cng_pt, ntohl(rtp_session->send_msg.header.ts), &frame_flags); } From 9d2aa0cd4cc18d553e1781e9e63b6977227089c3 Mon Sep 17 00:00:00 2001 From: Robert Jongbloed Date: Tue, 25 Sep 2012 12:55:41 +1000 Subject: [PATCH 076/252] Fixed failure to close FS call when H.323 call is closed from remote in early phase. --- src/mod/endpoints/mod_opal/mod_opal.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mod/endpoints/mod_opal/mod_opal.cpp b/src/mod/endpoints/mod_opal/mod_opal.cpp index 53c504b059..ba0b5c364d 100644 --- a/src/mod/endpoints/mod_opal/mod_opal.cpp +++ b/src/mod/endpoints/mod_opal/mod_opal.cpp @@ -644,7 +644,7 @@ void FSConnection::OnReleased() m_rxAudioOpened.Signal(); // Just in case m_txAudioOpened.Signal(); - if (m_fsChannel == NULL) { + if (m_fsChannel != NULL) { PTRACE(3, "mod_opal\tHanging up FS side"); switch_channel_hangup(m_fsChannel, (switch_call_cause_t)callEndReason.q931); } From cf0f483aabb3a6697011066de7b52ef50c6871de Mon Sep 17 00:00:00 2001 From: Robert Jongbloed Date: Thu, 27 Sep 2012 10:15:24 +1000 Subject: [PATCH 077/252] Assuming, just because it is MSVC, that the standard integers are not defined, is not correct. Need to test for define _STDINT as well as later versions of MSVC (>= VS2010) do have stdint.h --- libs/esl/src/include/esl.h | 2 ++ libs/libdingaling/src/ldl_compat.h | 2 +- libs/libteletone/src/libteletone_generate.h | 2 ++ libs/stfu/stfu.h | 2 +- libs/unimrcp/libs/mpf/codecs/g711/g711.h | 2 ++ src/include/g711.h | 2 ++ src/include/switch_platform.h | 2 +- src/mod/endpoints/mod_opal/mod_opal.h | 24 --------------------- 8 files changed, 11 insertions(+), 27 deletions(-) diff --git a/libs/esl/src/include/esl.h b/libs/esl/src/include/esl.h index 4296175f3a..5e66fe437a 100644 --- a/libs/esl/src/include/esl.h +++ b/libs/esl/src/include/esl.h @@ -221,6 +221,7 @@ typedef enum { #include #include typedef SOCKET esl_socket_t; +#if !defined(_STDINT) && !defined(uint32_t) typedef unsigned __int64 uint64_t; typedef unsigned __int32 uint32_t; typedef unsigned __int16 uint16_t; @@ -229,6 +230,7 @@ typedef __int64 int64_t; typedef __int32 int32_t; typedef __int16 int16_t; typedef __int8 int8_t; +#endif typedef intptr_t esl_ssize_t; typedef int esl_filehandle_t; #define ESL_SOCK_INVALID INVALID_SOCKET diff --git a/libs/libdingaling/src/ldl_compat.h b/libs/libdingaling/src/ldl_compat.h index 2507cd5957..280bf20dc8 100644 --- a/libs/libdingaling/src/ldl_compat.h +++ b/libs/libdingaling/src/ldl_compat.h @@ -42,7 +42,7 @@ extern "C" { #ifdef _MSC_VER -#ifndef uint32_t +#if !defined(_STDINT) && !defined(uint32_t) typedef unsigned __int8 uint8_t; typedef unsigned __int16 uint16_t; typedef unsigned __int32 uint32_t; diff --git a/libs/libteletone/src/libteletone_generate.h b/libs/libteletone/src/libteletone_generate.h index a49e45a658..25d5bf79d7 100644 --- a/libs/libteletone/src/libteletone_generate.h +++ b/libs/libteletone/src/libteletone_generate.h @@ -91,6 +91,7 @@ extern "C" { #define __inline__ __inline #endif +#if !defined(_STDINT) && !defined(uint32_t) typedef unsigned __int64 uint64_t; typedef unsigned __int32 uint32_t; typedef unsigned __int16 uint16_t; @@ -99,6 +100,7 @@ typedef __int64 int64_t; typedef __int32 int32_t; typedef __int16 int16_t; typedef __int8 int8_t; +#endif #else #include #endif diff --git a/libs/stfu/stfu.h b/libs/stfu/stfu.h index 2b21419118..045b644009 100644 --- a/libs/stfu/stfu.h +++ b/libs/stfu/stfu.h @@ -49,7 +49,7 @@ extern "C" { #endif #ifdef _MSC_VER -#ifndef uint32_t +#if !defined(_STDINT) && !defined(uint32_t) typedef unsigned __int8 uint8_t; typedef unsigned __int16 uint16_t; typedef unsigned __int32 uint32_t; diff --git a/libs/unimrcp/libs/mpf/codecs/g711/g711.h b/libs/unimrcp/libs/mpf/codecs/g711/g711.h index a8a0e92150..ae7e0e44aa 100644 --- a/libs/unimrcp/libs/mpf/codecs/g711/g711.h +++ b/libs/unimrcp/libs/mpf/codecs/g711/g711.h @@ -49,11 +49,13 @@ extern "C" { #ifndef __inline__ #define __inline__ __inline #endif +#if !defined(_STDINT) && !defined(uint32_t) typedef unsigned __int8 uint8_t; typedef __int16 int16_t; typedef __int32 int32_t; typedef unsigned __int16 uint16_t; #endif +#endif #if defined(__i386__) /*! \brief Find the bit position of the highest set bit in a word diff --git a/src/include/g711.h b/src/include/g711.h index 53f3afc87e..aac82a15ac 100644 --- a/src/include/g711.h +++ b/src/include/g711.h @@ -50,11 +50,13 @@ extern "C" { #ifndef __inline__ #define __inline__ __inline #endif +#if !defined(_STDINT) && !defined(uint32_t) typedef unsigned __int8 uint8_t; typedef __int16 int16_t; typedef __int32 int32_t; typedef unsigned __int16 uint16_t; #endif +#endif #if defined(__i386__) /*! \brief Find the bit position of the highest set bit in a word diff --git a/src/include/switch_platform.h b/src/include/switch_platform.h index a011850748..1140aac8ba 100644 --- a/src/include/switch_platform.h +++ b/src/include/switch_platform.h @@ -88,7 +88,7 @@ SWITCH_BEGIN_EXTERN_C #endif #undef inline #define inline __inline -#ifndef uint32_t +#if !defined(_STDINT) && !defined(uint32_t) typedef unsigned __int8 uint8_t; typedef unsigned __int16 uint16_t; typedef unsigned __int32 uint32_t; diff --git a/src/mod/endpoints/mod_opal/mod_opal.h b/src/mod/endpoints/mod_opal/mod_opal.h index da2ea1fa5b..56ac9b3671 100644 --- a/src/mod/endpoints/mod_opal/mod_opal.h +++ b/src/mod/endpoints/mod_opal/mod_opal.h @@ -49,31 +49,7 @@ #undef strcasecmp #undef strncasecmp - -#ifdef _MSC_VER -/*The following insanity is because libteletone_generate.h defines int8_t in - a slightly different manner to most other cases (SDL, PCAP, Java V8, - VS2010's own stdint.h, etc) and does not provide a mechanism to prevent it's - inclusion. Then, to cap it off, MSVC barfs on the difference. - - Sigh. - */ -#pragma include_alias(, <../../libs/libteletone/src/libteletone.h>) -#pragma include_alias(, <../../libs/libteletone/src/libteletone_generate.h>) -#pragma include_alias(, <../../libs/libteletone/src/libteletone_detect.h>) -#define int8_t signed int8_t -#include -#undef int8_t -#endif // End of insanity - - -#define HAVE_APR -#define uint32_t uint32_t // Avoid conflict in stdint definitions #include -#undef uint32_t - -#include - #define MODNAME "mod_opal" From 5b0115676c5c6cb0762187bdd999fb115aaa2eb9 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Thu, 27 Sep 2012 09:19:51 -0500 Subject: [PATCH 078/252] add void to declarations --- libs/esl/src/esl_json.c | 14 +++++++------- libs/esl/src/include/esl_json.h | 12 ++++++------ 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/libs/esl/src/esl_json.c b/libs/esl/src/esl_json.c index 5e7157cfe4..cd0706d6cb 100644 --- a/libs/esl/src/esl_json.c +++ b/libs/esl/src/esl_json.c @@ -35,7 +35,7 @@ static const char *ep; -ESL_DECLARE(const char *)cJSON_GetErrorPtr() {return ep;} +ESL_DECLARE(const char *)cJSON_GetErrorPtr(void) {return ep;} static int cJSON_strcasecmp(const char *s1,const char *s2) { @@ -82,7 +82,7 @@ ESL_DECLARE(void)cJSON_InitHooks(cJSON_Hooks* hooks) } /* Internal constructor. */ -static cJSON *cJSON_New_Item() +static cJSON *cJSON_New_Item(void) { cJSON* node = (cJSON*)cJSON_malloc(sizeof(cJSON)); if (node) memset(node,0,sizeof(cJSON)); @@ -513,14 +513,14 @@ ESL_DECLARE(void) cJSON_ReplaceItemInArray(cJSON *array,int which,cJSON *newite ESL_DECLARE(void) cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem){int i=0;cJSON *c=object->child;while(c && cJSON_strcasecmp(c->string,string))i++,c=c->next;if(c){newitem->string=cJSON_strdup(string);cJSON_ReplaceItemInArray(object,i,newitem);}} /* Create basic types: */ -ESL_DECLARE(cJSON *)cJSON_CreateNull() {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_NULL;return item;} -ESL_DECLARE(cJSON *)cJSON_CreateTrue() {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_True;return item;} -ESL_DECLARE(cJSON *)cJSON_CreateFalse() {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_False;return item;} +ESL_DECLARE(cJSON *)cJSON_CreateNull(void) {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_NULL;return item;} +ESL_DECLARE(cJSON *)cJSON_CreateTrue(void) {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_True;return item;} +ESL_DECLARE(cJSON *)cJSON_CreateFalse(void) {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_False;return item;} ESL_DECLARE(cJSON *)cJSON_CreateBool(int b) {cJSON *item=cJSON_New_Item();if(item)item->type=b?cJSON_True:cJSON_False;return item;} ESL_DECLARE(cJSON *)cJSON_CreateNumber(double num) {cJSON *item=cJSON_New_Item();if(item){item->type=cJSON_Number;item->valuedouble=num;item->valueint=(int)num;}return item;} ESL_DECLARE(cJSON *)cJSON_CreateString(const char *string) {cJSON *item=cJSON_New_Item();if(item){item->type=cJSON_String;item->valuestring=cJSON_strdup(string);}return item;} -ESL_DECLARE(cJSON *)cJSON_CreateArray() {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_Array;return item;} -ESL_DECLARE(cJSON *)cJSON_CreateObject() {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_Object;return item;} +ESL_DECLARE(cJSON *)cJSON_CreateArray(void) {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_Array;return item;} +ESL_DECLARE(cJSON *)cJSON_CreateObject(void) {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_Object;return item;} /* Create Arrays: */ ESL_DECLARE(cJSON *)cJSON_CreateIntArray(int *numbers,int count) {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a!=0 && ichild=n;else suffix_object(p,n);p=n;}return a;} diff --git a/libs/esl/src/include/esl_json.h b/libs/esl/src/include/esl_json.h index 615645597a..d3605cd8c7 100755 --- a/libs/esl/src/include/esl_json.h +++ b/libs/esl/src/include/esl_json.h @@ -79,17 +79,17 @@ ESL_DECLARE(cJSON *)cJSON_GetArrayItem(cJSON *array,int item); ESL_DECLARE(cJSON *)cJSON_GetObjectItem(cJSON *object,const char *string); /* For analysing failed parses. This returns a pointer to the parse error. You'll probably need to look a few chars back to make sense of it. Defined when cJSON_Parse() returns 0. 0 when cJSON_Parse() succeeds. */ -ESL_DECLARE(const char *)cJSON_GetErrorPtr(); +ESL_DECLARE(const char *)cJSON_GetErrorPtr(void); /* These calls create a cJSON item of the appropriate type. */ -ESL_DECLARE(cJSON *)cJSON_CreateNull(); -ESL_DECLARE(cJSON *)cJSON_CreateTrue(); -ESL_DECLARE(cJSON *)cJSON_CreateFalse(); +ESL_DECLARE(cJSON *)cJSON_CreateNull(void); +ESL_DECLARE(cJSON *)cJSON_CreateTrue(void); +ESL_DECLARE(cJSON *)cJSON_CreateFalse(void); ESL_DECLARE(cJSON *)cJSON_CreateBool(int b); ESL_DECLARE(cJSON *)cJSON_CreateNumber(double num); ESL_DECLARE(cJSON *)cJSON_CreateString(const char *string); -ESL_DECLARE(cJSON *)cJSON_CreateArray(); -ESL_DECLARE(cJSON *)cJSON_CreateObject(); +ESL_DECLARE(cJSON *)cJSON_CreateArray(void); +ESL_DECLARE(cJSON *)cJSON_CreateObject(void); /* These utilities create an Array of count items. */ ESL_DECLARE(cJSON *)cJSON_CreateIntArray(int *numbers,int count); From 7a69d7d47cbb4db5b5ea100e8d9555b701f62b90 Mon Sep 17 00:00:00 2001 From: Jeff Lenk Date: Thu, 27 Sep 2012 12:10:13 -0500 Subject: [PATCH 079/252] FS-4638 --resolve add error log for bad codec string --- src/switch_loadable_module.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/switch_loadable_module.c b/src/switch_loadable_module.c index 15c4739775..d253a75bea 100644 --- a/src/switch_loadable_module.c +++ b/src/switch_loadable_module.c @@ -2108,6 +2108,8 @@ SWITCH_DECLARE(char *) switch_parse_codec_buf(char *buf, uint32_t *interval, uin *rate = atoi(cur); } else if (strchr(cur, 'b')) { *bit = atoi(cur); + } else { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Bad syntax for codec string. Missing qualifier [h|k|i|b] for part [%s]!\n", cur); } } cur = next; From c7283aaa1a3f9032c9498b575231c986cc0885fd Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Thu, 27 Sep 2012 13:37:15 -0500 Subject: [PATCH 080/252] force core rebuild when apr and other core libs change --- Makefile.am | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Makefile.am b/Makefile.am index e7f1f799a5..adf412b205 100644 --- a/Makefile.am +++ b/Makefile.am @@ -449,26 +449,32 @@ libs/curl/lib/libcurl.la: libs/curl libs/curl/Makefile @$(TOUCH_TARGET) libs/apr/libapr-1.la: libs/apr libs/apr/.update + touch src/include/switch.h @cd libs/apr && $(MAKE) @$(TOUCH_TARGET) libs/apr-util/libaprutil-1.la: libs/apr-util libs/apr-util/.update libs/apr/libapr-1.la + touch src/include/switch.h @cd libs/apr-util && $(MAKE) @$(TOUCH_TARGET) libs/speex/libspeex/libspeexdsp.la: libs/speex/.update + touch src/include/switch.h @cd libs/speex && $(MAKE) @$(TOUCH_TARGET) libs/sqlite/libsqlite3.la: libs/sqlite libs/sqlite/.update + touch src/include/switch.h @cd libs/sqlite && $(MAKE) CFLAGS="$(SWITCH_AM_CFLAGS)" @$(TOUCH_TARGET) libs/pcre/libpcre.la: libs/pcre libs/pcre/.update + touch src/include/switch.h @cd libs/pcre && $(MAKE) @$(TOUCH_TARGET) libs/srtp/libsrtp.la: libs/srtp libs/srtp/.update + touch src/include/switch.h @cd libs/srtp && $(MAKE) @$(TOUCH_TARGET) From 90f3ab40998de46a0ec962e0e4f707dfa688e157 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Thu, 27 Sep 2012 13:37:54 -0500 Subject: [PATCH 081/252] fix thread priority code, this has never worked until today --- libs/apr/.update | 2 +- libs/apr/include/arch/unix/apr_arch_threadproc.h | 1 + libs/apr/threadproc/unix/thread.c | 5 +++++ src/switch_apr.c | 15 +++------------ 4 files changed, 10 insertions(+), 13 deletions(-) diff --git a/libs/apr/.update b/libs/apr/.update index d5bc43d9d4..4452df8ef3 100644 --- a/libs/apr/.update +++ b/libs/apr/.update @@ -1 +1 @@ -Mon Sep 27 13:15:54 CDT 2010 +Thu Sep 27 13:36:14 CDT 2012 diff --git a/libs/apr/include/arch/unix/apr_arch_threadproc.h b/libs/apr/include/arch/unix/apr_arch_threadproc.h index 6b0180234d..bd9359a49f 100644 --- a/libs/apr/include/arch/unix/apr_arch_threadproc.h +++ b/libs/apr/include/arch/unix/apr_arch_threadproc.h @@ -60,6 +60,7 @@ struct apr_thread_t { struct apr_threadattr_t { apr_pool_t *pool; pthread_attr_t attr; + int priority; }; struct apr_threadkey_t { diff --git a/libs/apr/threadproc/unix/thread.c b/libs/apr/threadproc/unix/thread.c index 28fcef0aef..9a56e55405 100644 --- a/libs/apr/threadproc/unix/thread.c +++ b/libs/apr/threadproc/unix/thread.c @@ -174,6 +174,11 @@ APR_DECLARE(apr_status_t) apr_thread_create(apr_thread_t **new, } if ((stat = pthread_create((*new)->td, temp, dummy_worker, (*new))) == 0) { + if (attr->priority) { + pthread_t *thread = (*new)->td; + pthread_setschedprio(*thread, attr->priority); + } + return APR_SUCCESS; } else { diff --git a/src/switch_apr.c b/src/switch_apr.c index c854c97617..dfb56d5390 100644 --- a/src/switch_apr.c +++ b/src/switch_apr.c @@ -633,25 +633,16 @@ SWITCH_DECLARE(switch_status_t) switch_threadattr_stacksize_set(switch_threadatt struct apr_threadattr_t { apr_pool_t *pool; pthread_attr_t attr; + int priority; }; #endif SWITCH_DECLARE(switch_status_t) switch_threadattr_priority_increase(switch_threadattr_t *attr) { - int stat = 0; #ifndef WIN32 - struct sched_param param; - struct apr_threadattr_t *myattr = attr; - - pthread_attr_getschedparam(&myattr->attr, ¶m); - param.sched_priority = 1; - stat = pthread_attr_setschedparam(&myattr->attr, ¶m); - - if (stat == 0) { - return SWITCH_STATUS_SUCCESS; - } + attr->priority = 10; #endif - return stat; + return SWITCH_STATUS_SUCCESS; } static char TT_KEY[] = "1"; From 7c840030247382912a87a3362a4497a9e4dda9b1 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Thu, 27 Sep 2012 11:42:19 -0500 Subject: [PATCH 082/252] bump important threads to realtime priority --- src/switch_apr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/switch_apr.c b/src/switch_apr.c index dfb56d5390..49b7a9b5c5 100644 --- a/src/switch_apr.c +++ b/src/switch_apr.c @@ -640,7 +640,7 @@ struct apr_threadattr_t { SWITCH_DECLARE(switch_status_t) switch_threadattr_priority_increase(switch_threadattr_t *attr) { #ifndef WIN32 - attr->priority = 10; + attr->priority = 99; #endif return SWITCH_STATUS_SUCCESS; } From 06a3266360c2cec7e4b3a450ee6693430a0d0451 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Thu, 27 Sep 2012 14:27:28 -0500 Subject: [PATCH 083/252] FS-4655 its not a bug its a behaviour request, try this patch --- src/mod/endpoints/mod_alsa/mod_alsa.c | 2 +- src/mod/endpoints/mod_portaudio/mod_portaudio.c | 2 +- src/mod/endpoints/mod_rtmp/mod_rtmp.c | 2 +- src/mod/endpoints/mod_skypopen/mod_skypopen.c | 2 +- src/mod/endpoints/mod_sofia/mod_sofia.c | 3 ++- src/mod/endpoints/mod_unicall/mod_unicall.c | 2 +- src/switch_core_session.c | 5 +++++ 7 files changed, 12 insertions(+), 6 deletions(-) diff --git a/src/mod/endpoints/mod_alsa/mod_alsa.c b/src/mod/endpoints/mod_alsa/mod_alsa.c index bafe8bdcc1..13e36ea53d 100644 --- a/src/mod/endpoints/mod_alsa/mod_alsa.c +++ b/src/mod/endpoints/mod_alsa/mod_alsa.c @@ -758,7 +758,7 @@ static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *sessi switch_call_cause_t *cancel_cause) { - if ((*new_session = switch_core_session_request(alsa_endpoint_interface, SWITCH_CALL_DIRECTION_OUTBOUND, flags, pool)) != 0) { + if ((*new_session = switch_core_session_request_uuid(alsa_endpoint_interface, SWITCH_CALL_DIRECTION_OUTBOUND, flags, pool, switch_event_get_header(var_event, "origination_uuid"))) != 0) { private_t *tech_pvt; switch_channel_t *channel; switch_caller_profile_t *caller_profile; diff --git a/src/mod/endpoints/mod_portaudio/mod_portaudio.c b/src/mod/endpoints/mod_portaudio/mod_portaudio.c index abc36620dd..f5487486ce 100644 --- a/src/mod/endpoints/mod_portaudio/mod_portaudio.c +++ b/src/mod/endpoints/mod_portaudio/mod_portaudio.c @@ -1157,7 +1157,7 @@ static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *sessi return retcause; } - if (!(*new_session = switch_core_session_request(portaudio_endpoint_interface, SWITCH_CALL_DIRECTION_OUTBOUND, flags, pool))) { + if (!(*new_session = switch_core_session_request_uuid(portaudio_endpoint_interface, SWITCH_CALL_DIRECTION_OUTBOUND, flags, pool, switch_event_get_header(var_event, "origination_uuid")))) { return retcause; } diff --git a/src/mod/endpoints/mod_rtmp/mod_rtmp.c b/src/mod/endpoints/mod_rtmp/mod_rtmp.c index 0bdc4531de..844b1483d0 100644 --- a/src/mod/endpoints/mod_rtmp/mod_rtmp.c +++ b/src/mod/endpoints/mod_rtmp/mod_rtmp.c @@ -590,7 +590,7 @@ switch_call_cause_t rtmp_outgoing_channel(switch_core_session_t *session, switch goto fail; } - if (!(*newsession = switch_core_session_request(rtmp_globals.rtmp_endpoint_interface, flags, SWITCH_CALL_DIRECTION_OUTBOUND, inpool))) { + if (!(*newsession = switch_core_session_request_uuid(rtmp_globals.rtmp_endpoint_interface, flags, SWITCH_CALL_DIRECTION_OUTBOUND, inpool, switch_event_get_header(var_event, "origination_uuid")))) { goto fail; } diff --git a/src/mod/endpoints/mod_skypopen/mod_skypopen.c b/src/mod/endpoints/mod_skypopen/mod_skypopen.c index 21dea92d4f..43253a71e9 100644 --- a/src/mod/endpoints/mod_skypopen/mod_skypopen.c +++ b/src/mod/endpoints/mod_skypopen/mod_skypopen.c @@ -1261,7 +1261,7 @@ static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *sessi switch_call_cause_t *cancel_cause) { private_t *tech_pvt = NULL; - if ((*new_session = switch_core_session_request(skypopen_endpoint_interface, SWITCH_CALL_DIRECTION_OUTBOUND, flags, pool)) != 0) { + if ((*new_session = switch_core_session_request_uuid(skypopen_endpoint_interface, SWITCH_CALL_DIRECTION_OUTBOUND, flags, pool, switch_event_get_header(var_event, "origination_uuid"))) != 0) { switch_channel_t *channel = NULL; switch_caller_profile_t *caller_profile; char *rdest; diff --git a/src/mod/endpoints/mod_sofia/mod_sofia.c b/src/mod/endpoints/mod_sofia/mod_sofia.c index b7450e4e47..a9721b4c49 100644 --- a/src/mod/endpoints/mod_sofia/mod_sofia.c +++ b/src/mod/endpoints/mod_sofia/mod_sofia.c @@ -4538,7 +4538,8 @@ static switch_call_cause_t sofia_outgoing_channel(switch_core_session_t *session goto error; } - if (!(nsession = switch_core_session_request(sofia_endpoint_interface, SWITCH_CALL_DIRECTION_OUTBOUND, flags, pool))) { + if (!(nsession = switch_core_session_request_uuid(sofia_endpoint_interface, SWITCH_CALL_DIRECTION_OUTBOUND, + flags, pool, switch_event_get_header(var_event, "origination_uuid")))) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Error Creating Session\n"); goto error; } diff --git a/src/mod/endpoints/mod_unicall/mod_unicall.c b/src/mod/endpoints/mod_unicall/mod_unicall.c index 75680bd243..18cd5d11d5 100644 --- a/src/mod/endpoints/mod_unicall/mod_unicall.c +++ b/src/mod/endpoints/mod_unicall/mod_unicall.c @@ -197,7 +197,7 @@ static switch_call_cause_t unicall_incoming_channel(zap_sigmsg_t *sigmsg, switch *sp = NULL; - if (!(session = switch_core_session_request(openzap_endpoint_interface, SWITCH_CALL_DIRECTION_INBOUND, SOF_NONE, NULL))) { + if (!(session = switch_core_session_request_uuid(openzap_endpoint_interface, SWITCH_CALL_DIRECTION_INBOUND, SOF_NONE, NULL, switch_event_get_header(var_event, "origination_uuid")))) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Initialization Error!\n"); return ZAP_FAIL; } diff --git a/src/switch_core_session.c b/src/switch_core_session.c index 94edc35488..eb60968f5d 100644 --- a/src/switch_core_session.c +++ b/src/switch_core_session.c @@ -1682,6 +1682,11 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_set_uuid(switch_core_session switch_assert(use_uuid); + if (!strcmp(use_uuid, session->uuid_str)) { + return SWITCH_STATUS_SUCCESS; + } + + switch_mutex_lock(runtime.session_hash_mutex); if (switch_core_hash_find(session_manager.session_table, use_uuid)) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_CRIT, "Duplicate UUID!\n"); From 15ef8925c31e100e2656408aea2fa7495ebd4b91 Mon Sep 17 00:00:00 2001 From: David Yat Sin Date: Thu, 27 Sep 2012 23:48:18 -0400 Subject: [PATCH 084/252] Fix for Q.921 not always recovering --- .../ftmod_sangoma_isdn_stack_out.c | 16 +++++++++++++--- .../ftmod_sangoma_isdn_support.c | 11 ++++++++++- 2 files changed, 23 insertions(+), 4 deletions(-) diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_out.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_out.c index 02b1ce0be8..f6e0d70b41 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_out.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_out.c @@ -475,8 +475,16 @@ void sngisdn_snd_restart(ftdm_channel_t *ftdmchan) void sngisdn_snd_data(ftdm_channel_t *dchan, uint8_t *data, ftdm_size_t len) { sng_l1_frame_t l1_frame; + ftdm_alarm_flag_t alarmbits = 0; sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) dchan->span->signal_data; + ftdm_channel_get_alarms(dchan, &alarmbits); + + if (alarmbits) { + ftdm_log_chan_msg(dchan, FTDM_LOG_WARNING, "Dropping incoming data due to L1 alarm\n"); + return; + } + if (len > sizeof(l1_frame.data)) { ftdm_log_chan(dchan, FTDM_LOG_ERROR, "Received frame of %"FTDM_SIZE_FMT" bytes, exceeding max size of %"FTDM_SIZE_FMT" bytes\n", len, sizeof(l1_frame.data)); @@ -548,9 +556,11 @@ void sngisdn_snd_event(sngisdn_span_data_t *signal_data, ftdm_oob_event_t event) case FTDM_OOB_ALARM_CLEAR: l1_event.type = SNG_L1EVENT_ALARM_OFF; sng_isdn_event_ind(signal_data->link_id, &l1_event); - - ftdm_sched_timer(signal_data->sched, "delayed_dl_req", 8000, sngisdn_delayed_dl_req, (void*) signal_data, NULL); - signal_data->dl_request_pending = 1; + + if (!signal_data->dl_request_pending) { + signal_data->dl_request_pending = 1; + ftdm_sched_timer(signal_data->sched, "delayed_dl_req", 8000, sngisdn_delayed_dl_req, (void*) signal_data, NULL); + } break; case FTDM_OOB_ALARM_TRAP: l1_event.type = SNG_L1EVENT_ALARM_ON; diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_support.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_support.c index 246c3190ee..cabf68be77 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_support.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_support.c @@ -1214,14 +1214,23 @@ void sngisdn_t3_timeout(void *p_sngisdn_info) void sngisdn_delayed_dl_req(void *p_signal_data) { + ftdm_signaling_status_t sigstatus = FTDM_SIG_STATE_DOWN; sngisdn_span_data_t *signal_data = (sngisdn_span_data_t *)p_signal_data; ftdm_span_t *span = signal_data->ftdm_span; if (!signal_data->dl_request_pending) { return; } - signal_data->dl_request_pending = 0; + + ftdm_span_get_sig_status(span, &sigstatus); + if (sigstatus == FTDM_SIG_STATE_UP) { + signal_data->dl_request_pending = 0; + return; + } + sngisdn_snd_dl_req(span->channels[1]); + ftdm_sched_timer(signal_data->sched, "delayed_dl_req", 4000, sngisdn_delayed_dl_req, (void*) signal_data, NULL); + return; } From 0cb64960f1378be6883f0c35e2aae5b7a227c6cb Mon Sep 17 00:00:00 2001 From: Michael S Collins Date: Fri, 28 Sep 2012 09:45:42 -0700 Subject: [PATCH 085/252] config: improve default directory's dialstring param to handle registrations from any SIP profile --- conf/vanilla/directory/default.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/conf/vanilla/directory/default.xml b/conf/vanilla/directory/default.xml index 8af7aea135..0dc67412de 100644 --- a/conf/vanilla/directory/default.xml +++ b/conf/vanilla/directory/default.xml @@ -21,7 +21,7 @@ - + From 5259814aee16ede974456490a79e8a98de1d6d2e Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Fri, 28 Sep 2012 14:05:58 -0500 Subject: [PATCH 086/252] number not true --- src/switch_rtp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/switch_rtp.c b/src/switch_rtp.c index de842c5db7..b3b396e619 100644 --- a/src/switch_rtp.c +++ b/src/switch_rtp.c @@ -1688,7 +1688,7 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_add_crypto_key(switch_rtp_t *rtp_sess memset(policy, 0, sizeof(*policy)); - switch_channel_set_variable(channel, "send_silence_when_idle", "true"); + switch_channel_set_variable(channel, "send_silence_when_idle", "400"); switch (crypto_key->type) { case AES_CM_128_HMAC_SHA1_80: From 8d614040168083f0dad5ca4a45bae7c06ed3de7c Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Fri, 28 Sep 2012 16:17:20 -0500 Subject: [PATCH 087/252] fix issue where dtmf was not being sent on an outbound leg when there was no inbound audio --- src/switch_rtp.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/switch_rtp.c b/src/switch_rtp.c index b3b396e619..14fbe1a849 100644 --- a/src/switch_rtp.c +++ b/src/switch_rtp.c @@ -3492,7 +3492,6 @@ static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_ if (!switch_test_flag(rtp_session, SWITCH_RTP_FLAG_NOBLOCK) || !switch_test_flag(rtp_session, SWITCH_RTP_FLAG_USE_TIMER) || switch_test_flag(rtp_session, SWITCH_RTP_FLAG_PROXY_MEDIA) || switch_test_flag(rtp_session, SWITCH_RTP_FLAG_UDPTL) || (bytes && bytes < 5) || (!bytes && poll_loop)) { - do_2833(rtp_session, session); bytes = 0; return_cng_frame(); } @@ -3692,6 +3691,8 @@ static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_ if (do_cng) { uint8_t *data = (uint8_t *) rtp_session->recv_msg.body; + do_2833(rtp_session, session); + if (rtp_session->last_cng_ts == rtp_session->last_read_ts + rtp_session->samples_per_interval) { rtp_session->last_cng_ts = 0; } else { From 677d16cfd5b16c0fac4f6f432db027faf068a95f Mon Sep 17 00:00:00 2001 From: Giovanni Maruzzelli Date: Mon, 1 Oct 2012 01:26:20 +0200 Subject: [PATCH 088/252] scripts/trace/sipgrep: correctly interpret option -C (print ANSI colors in debug file only when option -C is defined) --- scripts/trace/sipgrep | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/trace/sipgrep b/scripts/trace/sipgrep index 474a2d5c7b..3b3796925e 100755 --- a/scripts/trace/sipgrep +++ b/scripts/trace/sipgrep @@ -286,8 +286,8 @@ sub print_out if(defined $filedebug) { open(DBG, ">>$filedebug"); - $lcolor = 'reset' if(!(defined $debugfilecolors)); - print DBG color $lcolor if(!(defined $debugfilecolors)); + $lcolor = 'reset' if((defined $debugfilecolors)); + print DBG color $lcolor if((defined $debugfilecolors)); print DBG $ltext; close(DBG); } From bf060c6396c8b45b4dff154b00395744fceee2ea Mon Sep 17 00:00:00 2001 From: Jeff Lenk Date: Mon, 1 Oct 2012 08:56:51 -0500 Subject: [PATCH 089/252] FS-4664 --resolve --- src/mod/endpoints/mod_skinny/skinny_server.c | 24 ++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/src/mod/endpoints/mod_skinny/skinny_server.c b/src/mod/endpoints/mod_skinny/skinny_server.c index 6c0e01f8a0..652b7954c6 100644 --- a/src/mod/endpoints/mod_skinny/skinny_server.c +++ b/src/mod/endpoints/mod_skinny/skinny_server.c @@ -1198,10 +1198,11 @@ switch_status_t skinny_handle_enbloc_call_message(listener_t *listener, skinny_m switch_status_t skinny_handle_stimulus_message(listener_t *listener, skinny_message_t *request) { switch_status_t status = SWITCH_STATUS_SUCCESS; - struct speed_dial_stat_res_message *button = NULL; uint32_t line_instance = 0; uint32_t call_id = 0; switch_core_session_t *session = NULL; + struct speed_dial_stat_res_message *button_speed_dial = NULL; + struct line_stat_res_message *button_line = NULL; skinny_check_data_length(request, sizeof(request->data.stimulus)-sizeof(request->data.stimulus.call_id)); @@ -1215,10 +1216,10 @@ switch_status_t skinny_handle_stimulus_message(listener_t *listener, skinny_mess skinny_session_process_dest(session, listener, line_instance, "redial", '\0', 0); break; case SKINNY_BUTTON_SPEED_DIAL: - skinny_speed_dial_get(listener, request->data.stimulus.instance, &button); - if(strlen(button->line) > 0) { + skinny_speed_dial_get(listener, request->data.stimulus.instance, &button_speed_dial); + if(strlen(button_speed_dial->line) > 0) { skinny_create_incoming_session(listener, &line_instance, &session); - skinny_session_process_dest(session, listener, line_instance, button->line, '\0', 0); + skinny_session_process_dest(session, listener, line_instance, button_speed_dial->line, '\0', 0); } break; case SKINNY_BUTTON_HOLD: @@ -1239,6 +1240,21 @@ switch_status_t skinny_handle_stimulus_message(listener_t *listener, skinny_mess skinny_create_incoming_session(listener, &line_instance, &session); skinny_session_process_dest(session, listener, line_instance, "vmain", '\0', 0); break; + + case SKINNY_BUTTON_LINE: + // Get the button data + skinny_line_get(listener, request->data.stimulus.instance, &button_line); + + // Set the button and try to open the incoming session with this + line_instance = button_line->number; + session = skinny_profile_find_session(listener->profile, listener, &line_instance, call_id); + + // If session and line match, answer the call + if ( session && line_instance == button_line->number ) { + status = skinny_session_answer(session, listener, line_instance); + } + break; + default: switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Unknown Stimulus Type Received [%d]\n", request->data.stimulus.instance_type); } From 8733a2c8950f552de5d239974ca6d6d09d529228 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Mon, 1 Oct 2012 11:47:26 -0500 Subject: [PATCH 090/252] some priority queuing tweaks for performance --- src/mod/applications/mod_conference/mod_conference.c | 1 + src/mod/endpoints/mod_sofia/sofia.c | 7 +++++-- src/switch_core.c | 2 +- src/switch_core_io.c | 2 ++ src/switch_core_sqldb.c | 3 ++- src/switch_event.c | 1 + src/switch_time.c | 5 ++++- 7 files changed, 16 insertions(+), 5 deletions(-) diff --git a/src/mod/applications/mod_conference/mod_conference.c b/src/mod/applications/mod_conference/mod_conference.c index 0bdf28822b..d84f3b6f7d 100644 --- a/src/mod/applications/mod_conference/mod_conference.c +++ b/src/mod/applications/mod_conference/mod_conference.c @@ -7748,6 +7748,7 @@ static void launch_conference_thread(conference_obj_t *conference) switch_set_flag_locked(conference, CFLAG_RUNNING); switch_threadattr_create(&thd_attr, conference->pool); switch_threadattr_detach_set(thd_attr, 1); + switch_threadattr_priority_increase(thd_attr); switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE); switch_mutex_lock(globals.hash_mutex); switch_mutex_unlock(globals.hash_mutex); diff --git a/src/mod/endpoints/mod_sofia/sofia.c b/src/mod/endpoints/mod_sofia/sofia.c index f7f7bddead..2793cd7354 100644 --- a/src/mod/endpoints/mod_sofia/sofia.c +++ b/src/mod/endpoints/mod_sofia/sofia.c @@ -1599,7 +1599,7 @@ void *SWITCH_THREAD_FUNC sofia_msg_thread_run(switch_thread_t *thread, void *obj msg_queue_threads++; switch_mutex_unlock(mod_sofia_globals.mutex); - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "MSG Thread %d Started\n", my_id); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "MSG Thread %d Started\n", my_id); for(;;) { @@ -1612,12 +1612,13 @@ void *SWITCH_THREAD_FUNC sofia_msg_thread_run(switch_thread_t *thread, void *obj if (pop) { sofia_dispatch_event_t *de = (sofia_dispatch_event_t *) pop; sofia_process_dispatch_event(&de); + switch_os_yield(); } else { break; } } - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "MSG Thread Ended\n"); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "MSG Thread Ended\n"); switch_mutex_lock(mod_sofia_globals.mutex); msg_queue_threads--; @@ -1934,6 +1935,8 @@ void sofia_event_callback(nua_event_t event, if (profile->pres_type) { switch_cond_next(); + } else { + switch_os_yield(); } diff --git a/src/switch_core.c b/src/switch_core.c index 6cce356061..488b755232 100644 --- a/src/switch_core.c +++ b/src/switch_core.c @@ -736,7 +736,7 @@ SWITCH_DECLARE(int32_t) set_realtime_priority(void) char data[] = "-1\n"; struct sched_param sched = { 0 }; sched.sched_priority = 1; - if (sched_setscheduler(0, SCHED_FIFO, &sched)) { + if (sched_setscheduler(0, SCHED_RR, &sched)) { sched.sched_priority = 0; if (sched_setscheduler(0, SCHED_OTHER, &sched)) { return -1; diff --git a/src/switch_core_io.c b/src/switch_core_io.c index 8978306adb..7b9580c0bb 100644 --- a/src/switch_core_io.c +++ b/src/switch_core_io.c @@ -112,6 +112,8 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_read_frame(switch_core_sessi switch_assert(session != NULL); + switch_os_yield(); + if (switch_mutex_trylock(session->codec_read_mutex) == SWITCH_STATUS_SUCCESS) { switch_mutex_unlock(session->codec_read_mutex); } else { diff --git a/src/switch_core_sqldb.c b/src/switch_core_sqldb.c index d77b432c90..2e3e71f204 100644 --- a/src/switch_core_sqldb.c +++ b/src/switch_core_sqldb.c @@ -2539,7 +2539,7 @@ switch_status_t switch_core_sqldb_start(switch_memory_pool_t *pool, switch_bool_ switch_threadattr_create(&thd_attr, sql_manager.memory_pool); switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE); - + switch_threadattr_priority_increase(thd_attr); switch_core_sqldb_start_thread(); switch_thread_create(&sql_manager.db_thread, thd_attr, switch_core_sql_db_thread, NULL, sql_manager.memory_pool); @@ -2641,6 +2641,7 @@ SWITCH_DECLARE(void) switch_core_sqldb_start_thread(void) switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Starting SQL thread.\n"); switch_threadattr_create(&thd_attr, sql_manager.memory_pool); switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE); + switch_threadattr_priority_increase(thd_attr); switch_thread_create(&sql_manager.thread, thd_attr, switch_core_sql_thread, NULL, sql_manager.memory_pool); } else { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "SQL thread is already running\n"); diff --git a/src/switch_event.c b/src/switch_event.c index 3a02e3a449..175dadf5cf 100644 --- a/src/switch_event.c +++ b/src/switch_event.c @@ -276,6 +276,7 @@ static void *SWITCH_THREAD_FUNC switch_event_dispatch_thread(switch_thread_t *th event = (switch_event_t *) pop; switch_event_deliver(&event); + switch_os_yield(); } diff --git a/src/switch_time.c b/src/switch_time.c index fb9fea1de0..54bf9338ef 100644 --- a/src/switch_time.c +++ b/src/switch_time.c @@ -150,6 +150,7 @@ SWITCH_DECLARE(void) switch_os_yield(void) #if defined(WIN32) SwitchToThread(); #else + usleep(1); sched_yield(); #endif } @@ -672,8 +673,10 @@ static switch_status_t timer_next(switch_timer_t *timer) while (globals.RUNNING == 1 && private_info->ready && TIMER_MATRIX[timer->interval].tick < private_info->reference) { check_roll(); + switch_os_yield(); + + if (runtime.tipping_point && globals.timer_count >= runtime.tipping_point) { - switch_os_yield(); globals.use_cond_yield = 0; } else { if (globals.use_cond_yield == 1) { From 464155c5cd1c3c8e050e9c59d3990d382cf12658 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Mon, 1 Oct 2012 10:20:48 -0500 Subject: [PATCH 091/252] more priority tweaks --- src/include/switch_apr.h | 2 +- src/include/switch_types.h | 7 +++++ .../mod_callcenter/mod_callcenter.c | 2 +- .../mod_conference/mod_conference.c | 2 +- .../mod_voicemail/mod_voicemail.c | 2 +- .../commons/base/system/freeswitch/thread.hpp | 5 +++- src/mod/endpoints/mod_skypopen/mod_skypopen.c | 8 ++--- src/mod/endpoints/mod_sofia/sofia.c | 8 ++--- src/mod/endpoints/mod_sofia/sofia_presence.c | 2 +- src/mod/xml_int/mod_xml_scgi/mod_xml_scgi.c | 2 +- src/switch_apr.c | 29 ++++++++++++------- src/switch_core.c | 4 +-- src/switch_core_session.c | 1 + src/switch_core_sqldb.c | 4 +-- src/switch_event.c | 4 +-- src/switch_loadable_module.c | 1 - 16 files changed, 49 insertions(+), 34 deletions(-) diff --git a/src/include/switch_apr.h b/src/include/switch_apr.h index bd19353991..671052ab30 100644 --- a/src/include/switch_apr.h +++ b/src/include/switch_apr.h @@ -989,7 +989,7 @@ SWITCH_DECLARE(const char *) switch_dir_next_file(switch_dir_t *thedir, char *bu //APR_DECLARE(apr_status_t) apr_threadattr_stacksize_set(apr_threadattr_t *attr, switch_size_t stacksize) SWITCH_DECLARE(switch_status_t) switch_threadattr_stacksize_set(switch_threadattr_t *attr, switch_size_t stacksize); -SWITCH_DECLARE(switch_status_t) switch_threadattr_priority_increase(switch_threadattr_t *attr); +SWITCH_DECLARE(switch_status_t) switch_threadattr_priority_set(switch_threadattr_t *attr, switch_thread_priority_t priority); /** diff --git a/src/include/switch_types.h b/src/include/switch_types.h index 5f3a4fa258..f9d8476454 100644 --- a/src/include/switch_types.h +++ b/src/include/switch_types.h @@ -2016,6 +2016,13 @@ typedef switch_status_t (*switch_module_shutdown_t) SWITCH_MODULE_SHUTDOWN_ARGS; #define SWITCH_MODULE_RUNTIME_FUNCTION(name) switch_status_t name SWITCH_MODULE_RUNTIME_ARGS #define SWITCH_MODULE_SHUTDOWN_FUNCTION(name) switch_status_t name SWITCH_MODULE_SHUTDOWN_ARGS +typedef enum { + SWITCH_PRI_LOW = 1, + SWITCH_PRI_NORMAL = 10, + SWITCH_PRI_IMPORTANT = 50, + SWITCH_PRI_REALTIME = 99, +} switch_thread_priority_t; + typedef enum { SMODF_NONE = 0, SMODF_GLOBAL_SYMBOLS = (1 << 0) diff --git a/src/mod/applications/mod_callcenter/mod_callcenter.c b/src/mod/applications/mod_callcenter/mod_callcenter.c index df8670f2ee..e6f7ea7945 100644 --- a/src/mod/applications/mod_callcenter/mod_callcenter.c +++ b/src/mod/applications/mod_callcenter/mod_callcenter.c @@ -2272,7 +2272,7 @@ void cc_agent_dispatch_thread_start(void) switch_threadattr_create(&thd_attr, globals.pool); switch_threadattr_detach_set(thd_attr, 1); switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE); - switch_threadattr_priority_increase(thd_attr); + switch_threadattr_priority_set(thd_attr, SWITCH_PRI_REALTIME); switch_thread_create(&thread, thd_attr, cc_agent_dispatch_thread_run, NULL, globals.pool); } diff --git a/src/mod/applications/mod_conference/mod_conference.c b/src/mod/applications/mod_conference/mod_conference.c index d84f3b6f7d..3acb7d6c55 100644 --- a/src/mod/applications/mod_conference/mod_conference.c +++ b/src/mod/applications/mod_conference/mod_conference.c @@ -7748,7 +7748,7 @@ static void launch_conference_thread(conference_obj_t *conference) switch_set_flag_locked(conference, CFLAG_RUNNING); switch_threadattr_create(&thd_attr, conference->pool); switch_threadattr_detach_set(thd_attr, 1); - switch_threadattr_priority_increase(thd_attr); + switch_threadattr_priority_set(thd_attr, SWITCH_PRI_REALTIME); switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE); switch_mutex_lock(globals.hash_mutex); switch_mutex_unlock(globals.hash_mutex); diff --git a/src/mod/applications/mod_voicemail/mod_voicemail.c b/src/mod/applications/mod_voicemail/mod_voicemail.c index 51677c5b3f..78eb57a20a 100644 --- a/src/mod/applications/mod_voicemail/mod_voicemail.c +++ b/src/mod/applications/mod_voicemail/mod_voicemail.c @@ -3930,7 +3930,7 @@ void vm_event_thread_start(void) switch_threadattr_create(&thd_attr, globals.pool); switch_threadattr_detach_set(thd_attr, 1); switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE); - switch_threadattr_priority_increase(thd_attr); + switch_threadattr_priority_set(thd_attr, SWITCH_PRI_IMPORTANT); switch_thread_create(&thread, thd_attr, vm_event_thread_run, NULL, globals.pool); } diff --git a/src/mod/endpoints/mod_khomp/commons/base/system/freeswitch/thread.hpp b/src/mod/endpoints/mod_khomp/commons/base/system/freeswitch/thread.hpp index 9e5abc4372..3c61b6a6ec 100644 --- a/src/mod/endpoints/mod_khomp/commons/base/system/freeswitch/thread.hpp +++ b/src/mod/endpoints/mod_khomp/commons/base/system/freeswitch/thread.hpp @@ -288,7 +288,10 @@ private: return true; /* - //BUG in Freeswitch + //BUG in Freeswitch + +THANKS FOR NOT REPORTING IT SO WE MUST LIVE WITH A PROBLEM YOU KNOW ABOUT ..... + if(switch_threadattr_priority_increase( (switch_threadattr_t *)_thread_info->_attribute) != 0) return false; diff --git a/src/mod/endpoints/mod_skypopen/mod_skypopen.c b/src/mod/endpoints/mod_skypopen/mod_skypopen.c index 43253a71e9..c3b5d81681 100644 --- a/src/mod/endpoints/mod_skypopen/mod_skypopen.c +++ b/src/mod/endpoints/mod_skypopen/mod_skypopen.c @@ -1741,7 +1741,7 @@ static switch_status_t load_config(int reload_type) switch_threadattr_create(&skypopen_api_thread_attr, skypopen_module_pool); switch_threadattr_detach_set(skypopen_api_thread_attr, 0); switch_threadattr_stacksize_set(skypopen_api_thread_attr, SWITCH_THREAD_STACKSIZE); - //switch_threadattr_priority_increase(skypopen_api_thread_attr); + switch_thread_create(&globals.SKYPOPEN_INTERFACES[interface_id].skypopen_api_thread, skypopen_api_thread_attr, skypopen_do_skypeapi_thread, &globals.SKYPOPEN_INTERFACES[interface_id], skypopen_module_pool); @@ -1751,7 +1751,7 @@ static switch_status_t load_config(int reload_type) switch_threadattr_create(&skypopen_signaling_thread_attr, skypopen_module_pool); switch_threadattr_detach_set(skypopen_signaling_thread_attr, 0); switch_threadattr_stacksize_set(skypopen_signaling_thread_attr, SWITCH_THREAD_STACKSIZE); - //switch_threadattr_priority_increase(skypopen_signaling_thread_attr); + switch_thread_create(&globals.SKYPOPEN_INTERFACES[interface_id].skypopen_signaling_thread, skypopen_signaling_thread_attr, skypopen_signaling_thread_func, &globals.SKYPOPEN_INTERFACES[interface_id], skypopen_module_pool); @@ -2272,7 +2272,7 @@ int start_audio_threads(private_t *tech_pvt) switch_threadattr_create(&tcp_srv_thread_thd_attr, skypopen_module_pool); switch_threadattr_detach_set(tcp_srv_thread_thd_attr, 0); switch_threadattr_stacksize_set(tcp_srv_thread_thd_attr, SWITCH_THREAD_STACKSIZE); - switch_threadattr_priority_increase(tcp_srv_thread_thd_attr); + switch_threadattr_priority_set(tcp_srv_thread_thd_attr, SWITCH_PRI_REALTIME); switch_mutex_lock(tech_pvt->mutex_thread_audio_srv); //DEBUGA_SKYPE("debugging_hangup srv lock\n", SKYPOPEN_P_LOG); if (switch_thread_create(&tech_pvt->tcp_srv_thread, tcp_srv_thread_thd_attr, skypopen_do_tcp_srv_thread, tech_pvt, skypopen_module_pool) == @@ -2290,7 +2290,7 @@ int start_audio_threads(private_t *tech_pvt) switch_threadattr_create(&tcp_cli_thread_thd_attr, skypopen_module_pool); switch_threadattr_detach_set(tcp_cli_thread_thd_attr, 0); switch_threadattr_stacksize_set(tcp_cli_thread_thd_attr, SWITCH_THREAD_STACKSIZE); - switch_threadattr_priority_increase(tcp_cli_thread_thd_attr); + switch_threadattr_priority_set(tcp_cli_thread_thd_attr, SWITCH_PRI_REALTIME); switch_mutex_lock(tech_pvt->mutex_thread_audio_cli); //DEBUGA_SKYPE("debugging_hangup cli lock\n", SKYPOPEN_P_LOG); if (switch_thread_create(&tech_pvt->tcp_cli_thread, tcp_cli_thread_thd_attr, skypopen_do_tcp_cli_thread, tech_pvt, skypopen_module_pool) == diff --git a/src/mod/endpoints/mod_sofia/sofia.c b/src/mod/endpoints/mod_sofia/sofia.c index 2793cd7354..3b5277647f 100644 --- a/src/mod/endpoints/mod_sofia/sofia.c +++ b/src/mod/endpoints/mod_sofia/sofia.c @@ -1647,7 +1647,7 @@ void sofia_msg_thread_start(int idx) switch_threadattr_create(&thd_attr, mod_sofia_globals.pool); switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE); - switch_threadattr_priority_increase(thd_attr); + switch_threadattr_priority_set(thd_attr, SWITCH_PRI_REALTIME); switch_thread_create(&mod_sofia_globals.msg_queue_thread[i], thd_attr, sofia_msg_thread_run, @@ -2373,7 +2373,7 @@ switch_thread_t *launch_sofia_worker_thread(sofia_profile_t *profile) switch_threadattr_create(&thd_attr, profile->pool); switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE); - switch_threadattr_priority_increase(thd_attr); + switch_threadattr_priority_set(thd_attr, SWITCH_PRI_REALTIME); switch_thread_create(&thread, thd_attr, sofia_profile_worker_thread_run, profile, profile->pool); while (!sofia_test_pflag(profile, PFLAG_WORKER_RUNNING)) { @@ -2753,7 +2753,7 @@ void launch_sofia_profile_thread(sofia_profile_t *profile) switch_threadattr_create(&thd_attr, profile->pool); switch_threadattr_detach_set(thd_attr, 1); switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE); - switch_threadattr_priority_increase(thd_attr); + switch_threadattr_priority_set(thd_attr, SWITCH_PRI_REALTIME); switch_thread_create(&thread, thd_attr, sofia_profile_thread_run, profile, profile->pool); } @@ -6114,7 +6114,6 @@ static void launch_media_on_hold(switch_core_session_t *session) switch_threadattr_create(&thd_attr, switch_core_session_get_pool(session)); switch_threadattr_detach_set(thd_attr, 1); switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE); - switch_threadattr_priority_increase(thd_attr); switch_thread_create(&thread, thd_attr, media_on_hold_thread_run, session, switch_core_session_get_pool(session)); } @@ -7198,7 +7197,6 @@ static void launch_nightmare_xfer(nightmare_xfer_helper_t *nhelper) switch_threadattr_create(&thd_attr, nhelper->pool); switch_threadattr_detach_set(thd_attr, 1); switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE); - switch_threadattr_priority_increase(thd_attr); switch_thread_create(&thread, thd_attr, nightmare_xfer_thread_run, nhelper, nhelper->pool); } diff --git a/src/mod/endpoints/mod_sofia/sofia_presence.c b/src/mod/endpoints/mod_sofia/sofia_presence.c index 045ea7a827..10d741bca4 100644 --- a/src/mod/endpoints/mod_sofia/sofia_presence.c +++ b/src/mod/endpoints/mod_sofia/sofia_presence.c @@ -1577,7 +1577,7 @@ void sofia_presence_event_thread_start(void) switch_threadattr_create(&thd_attr, mod_sofia_globals.pool); switch_threadattr_detach_set(thd_attr, 1); switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE); - switch_threadattr_priority_increase(thd_attr); + switch_threadattr_priority_set(thd_attr, SWITCH_PRI_IMPORTANT); switch_thread_create(&thread, thd_attr, sofia_presence_event_thread_run, NULL, mod_sofia_globals.pool); } diff --git a/src/mod/xml_int/mod_xml_scgi/mod_xml_scgi.c b/src/mod/xml_int/mod_xml_scgi/mod_xml_scgi.c index 3e39e65407..81b0ef240f 100644 --- a/src/mod/xml_int/mod_xml_scgi/mod_xml_scgi.c +++ b/src/mod/xml_int/mod_xml_scgi/mod_xml_scgi.c @@ -126,7 +126,7 @@ static void launch_monitor_thread(xml_binding_t *binding) switch_threadattr_create(&thd_attr, globals.pool); switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE); - switch_threadattr_priority_increase(thd_attr); + switch_threadattr_priority_set(thd_attr, SWITCH_PRI_IMPORTANT); switch_thread_create(&binding->thread, thd_attr, monitor_thread_run, binding, globals.pool); } diff --git a/src/switch_apr.c b/src/switch_apr.c index 49b7a9b5c5..64e066853e 100644 --- a/src/switch_apr.c +++ b/src/switch_apr.c @@ -614,9 +614,24 @@ SWITCH_DECLARE(const char *) switch_dir_next_file(switch_dir_t *thedir, char *bu /* thread stubs */ +#ifndef WIN32 +struct apr_threadattr_t { + apr_pool_t *pool; + pthread_attr_t attr; + int priority; +}; +#endif + + SWITCH_DECLARE(switch_status_t) switch_threadattr_create(switch_threadattr_t ** new_attr, switch_memory_pool_t *pool) { - return apr_threadattr_create(new_attr, pool); + switch_status_t status; + + if ((status = apr_threadattr_create(new_attr, pool)) == SWITCH_STATUS_SUCCESS) { + (*new_attr)->priority = SWITCH_PRI_NORMAL; + } + + return status; } SWITCH_DECLARE(switch_status_t) switch_threadattr_detach_set(switch_threadattr_t *attr, int32_t on) @@ -629,18 +644,10 @@ SWITCH_DECLARE(switch_status_t) switch_threadattr_stacksize_set(switch_threadatt return apr_threadattr_stacksize_set(attr, stacksize); } -#ifndef WIN32 -struct apr_threadattr_t { - apr_pool_t *pool; - pthread_attr_t attr; - int priority; -}; -#endif - -SWITCH_DECLARE(switch_status_t) switch_threadattr_priority_increase(switch_threadattr_t *attr) +SWITCH_DECLARE(switch_status_t) switch_threadattr_priority_set(switch_threadattr_t *attr, switch_thread_priority_t priority) { #ifndef WIN32 - attr->priority = 99; + attr->priority = priority; #endif return SWITCH_STATUS_SUCCESS; } diff --git a/src/switch_core.c b/src/switch_core.c index 488b755232..1d87d9ce2e 100644 --- a/src/switch_core.c +++ b/src/switch_core.c @@ -533,7 +533,7 @@ SWITCH_DECLARE(switch_thread_t *) switch_core_launch_thread(switch_thread_start_ ts->objs[0] = obj; ts->objs[1] = thread; switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE); - switch_threadattr_priority_increase(thd_attr); + switch_threadattr_priority_set(thd_attr, SWITCH_PRI_REALTIME); switch_thread_create(&thread, thd_attr, func, ts, pool); } @@ -735,7 +735,7 @@ SWITCH_DECLARE(int32_t) set_realtime_priority(void) const char *rt = "/proc/sys/kernel/sched_rt_runtime_us"; char data[] = "-1\n"; struct sched_param sched = { 0 }; - sched.sched_priority = 1; + sched.sched_priority = SWITCH_PRI_REALTIME; if (sched_setscheduler(0, SCHED_RR, &sched)) { sched.sched_priority = 0; if (sched_setscheduler(0, SCHED_OTHER, &sched)) { diff --git a/src/switch_core_session.c b/src/switch_core_session.c index eb60968f5d..6e565dca06 100644 --- a/src/switch_core_session.c +++ b/src/switch_core_session.c @@ -1554,6 +1554,7 @@ static switch_status_t check_queue(void) switch_threadattr_create(&thd_attr, node->pool); switch_threadattr_detach_set(thd_attr, 1); switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE); + switch_threadattr_priority_set(thd_attr, SWITCH_PRI_LOW); if (switch_thread_create(&thread, thd_attr, switch_core_session_thread_pool_worker, node, node->pool) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Thread Failure!\n"); diff --git a/src/switch_core_sqldb.c b/src/switch_core_sqldb.c index 2e3e71f204..556e3abab2 100644 --- a/src/switch_core_sqldb.c +++ b/src/switch_core_sqldb.c @@ -2539,7 +2539,7 @@ switch_status_t switch_core_sqldb_start(switch_memory_pool_t *pool, switch_bool_ switch_threadattr_create(&thd_attr, sql_manager.memory_pool); switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE); - switch_threadattr_priority_increase(thd_attr); + switch_threadattr_priority_set(thd_attr, SWITCH_PRI_REALTIME); switch_core_sqldb_start_thread(); switch_thread_create(&sql_manager.db_thread, thd_attr, switch_core_sql_db_thread, NULL, sql_manager.memory_pool); @@ -2641,7 +2641,7 @@ SWITCH_DECLARE(void) switch_core_sqldb_start_thread(void) switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Starting SQL thread.\n"); switch_threadattr_create(&thd_attr, sql_manager.memory_pool); switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE); - switch_threadattr_priority_increase(thd_attr); + switch_threadattr_priority_set(thd_attr, SWITCH_PRI_REALTIME); switch_thread_create(&sql_manager.thread, thd_attr, switch_core_sql_thread, NULL, sql_manager.memory_pool); } else { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "SQL thread is already running\n"); diff --git a/src/switch_event.c b/src/switch_event.c index 175dadf5cf..02d23ee8f7 100644 --- a/src/switch_event.c +++ b/src/switch_event.c @@ -545,7 +545,7 @@ SWITCH_DECLARE(void) switch_event_launch_dispatch_threads(uint32_t max) switch_threadattr_create(&thd_attr, pool); switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE); - switch_threadattr_priority_increase(thd_attr); + switch_threadattr_priority_set(thd_attr, SWITCH_PRI_REALTIME); switch_thread_create(&EVENT_DISPATCH_QUEUE_THREADS[index], thd_attr, switch_event_dispatch_thread, EVENT_DISPATCH_QUEUE, pool); while(--sanity && !EVENT_DISPATCH_QUEUE_RUNNING[index]) switch_yield(10000); @@ -603,7 +603,7 @@ SWITCH_DECLARE(switch_status_t) switch_event_init(switch_memory_pool_t *pool) #endif //switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE); - //switch_threadattr_priority_increase(thd_attr); + switch_queue_create(&EVENT_DISPATCH_QUEUE, DISPATCH_QUEUE_LEN * MAX_DISPATCH, pool); switch_event_launch_dispatch_threads(1); diff --git a/src/switch_loadable_module.c b/src/switch_loadable_module.c index d253a75bea..718572612e 100644 --- a/src/switch_loadable_module.c +++ b/src/switch_loadable_module.c @@ -656,7 +656,6 @@ static void chat_thread_start(int idx) switch_threadattr_create(&thd_attr, chat_globals.pool); switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE); - //switch_threadattr_priority_increase(thd_attr); switch_thread_create(&chat_globals.msg_queue_thread[i], thd_attr, chat_thread_run, From 0f477d1586a6b31a345ba71b19fe1d7143aa3773 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Mon, 1 Oct 2012 12:24:33 -0500 Subject: [PATCH 092/252] increase pri in sofia --- libs/sofia-sip/libsofia-sip-ua/su/su_pthread_port.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libs/sofia-sip/libsofia-sip-ua/su/su_pthread_port.c b/libs/sofia-sip/libsofia-sip-ua/su/su_pthread_port.c index dfcd9ac901..9899da6f47 100644 --- a/libs/sofia-sip/libsofia-sip-ua/su/su_pthread_port.c +++ b/libs/sofia-sip/libsofia-sip-ua/su/su_pthread_port.c @@ -263,11 +263,12 @@ int su_pthreaded_port_start(su_port_create_f *create, pthread_attr_init(&attr); pthread_attr_setstacksize(&attr, 244); pthread_attr_getschedparam(&attr, ¶m); - param.sched_priority = 1; + param.sched_priority = 99; pthread_attr_setschedparam(&attr, ¶m); pthread_mutex_lock(arg.mutex); if (pthread_create(&tid, &attr, su_pthread_port_clone_main, &arg) == 0) { + pthread_setschedprio(tid, 99); pthread_cond_wait(arg.cv, arg.mutex); thread_created = 1; } From ece61bb7d33b18afb9a81bdb3f3086613bcd7bd8 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Mon, 1 Oct 2012 12:25:03 -0500 Subject: [PATCH 093/252] bump date to trigger build --- libs/sofia-sip/.update | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/sofia-sip/.update b/libs/sofia-sip/.update index f85cfc8001..ecae8fc840 100644 --- a/libs/sofia-sip/.update +++ b/libs/sofia-sip/.update @@ -1 +1 @@ -Wed Sep 19 13:06:07 CDT 2012 +Mon Oct 1 12:24:45 CDT 2012 From 0995d133a6a2dadf1d4696567581e107e1d0406d Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Mon, 1 Oct 2012 12:39:16 -0500 Subject: [PATCH 094/252] remove stray goto --- src/mod/languages/mod_spidermonkey/mod_spidermonkey.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/mod/languages/mod_spidermonkey/mod_spidermonkey.c b/src/mod/languages/mod_spidermonkey/mod_spidermonkey.c index d50030c218..1fa7b4ad5c 100644 --- a/src/mod/languages/mod_spidermonkey/mod_spidermonkey.c +++ b/src/mod/languages/mod_spidermonkey/mod_spidermonkey.c @@ -702,8 +702,6 @@ static JSBool event_chat_execute(JSContext * cx, JSObject * obj, uintN argc, jsv arg = JS_GetStringBytes(JS_ValueToString(cx, argv[1])); } - goto end; - switch_core_execute_chat_app(eo->event, app, arg); *rval = BOOLEAN_TO_JSVAL(JS_TRUE); @@ -711,8 +709,6 @@ static JSBool event_chat_execute(JSContext * cx, JSObject * obj, uintN argc, jsv } } - end: - *rval = BOOLEAN_TO_JSVAL(JS_FALSE); return JS_FALSE; } From 52eff9451c171e4300fefef334d6d2964dee35f0 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Mon, 1 Oct 2012 12:14:30 -0500 Subject: [PATCH 095/252] wrap fork so we can drop priority in child processes --- src/include/switch_core.h | 3 +++ .../mod_gsmopen/asterisk/celliax_additional.c | 4 +-- .../mod_gsmopen/gsmopen_protocol.cpp | 2 +- .../mod_shell_stream/mod_shell_stream.c | 2 +- .../xml_int/mod_xml_scgi/xml_scgi_server.pl | 2 +- src/switch.c | 2 +- src/switch_core.c | 25 ++++++++++++++++--- src/switch_xml.c | 2 +- 8 files changed, 31 insertions(+), 11 deletions(-) diff --git a/src/include/switch_core.h b/src/include/switch_core.h index 507f18a166..efd983ded8 100644 --- a/src/include/switch_core.h +++ b/src/include/switch_core.h @@ -2368,6 +2368,9 @@ SWITCH_DECLARE(void) switch_core_recovery_untrack(switch_core_session_t *session SWITCH_DECLARE(void) switch_core_recovery_track(switch_core_session_t *session); SWITCH_DECLARE(void) switch_core_recovery_flush(const char *technology, const char *profile_name); + +SWITCH_DECLARE(pid_t) switch_fork(void); + SWITCH_END_EXTERN_C #endif /* For Emacs: diff --git a/src/mod/endpoints/mod_gsmopen/asterisk/celliax_additional.c b/src/mod/endpoints/mod_gsmopen/asterisk/celliax_additional.c index f72c8d8552..efae699ab7 100644 --- a/src/mod/endpoints/mod_gsmopen/asterisk/celliax_additional.c +++ b/src/mod/endpoints/mod_gsmopen/asterisk/celliax_additional.c @@ -1185,7 +1185,7 @@ int celliax_serial_getstatus_AT(struct celliax_pvt *p) NOTICA("incoming SMS message:>>>%s<<<\n", CELLIAX_P_LOG, p->sms_message); pipe(fd1); - pid1 = fork(); + pid1 = switch_fork(); if (pid1 == 0) { //child int err; @@ -1735,7 +1735,7 @@ int celliax_serial_read_AT(struct celliax_pvt *p, int look_for_ack, int timeout_ NOTICA("incoming SMS message:>>>%s<<<\n", CELLIAX_P_LOG, p->sms_message); pipe(fd1); - pid1 = fork(); + pid1 = switch_fork(); if (pid1 == 0) { //child int err; diff --git a/src/mod/endpoints/mod_gsmopen/gsmopen_protocol.cpp b/src/mod/endpoints/mod_gsmopen/gsmopen_protocol.cpp index ffa4e3d014..5bdda08f81 100644 --- a/src/mod/endpoints/mod_gsmopen/gsmopen_protocol.cpp +++ b/src/mod/endpoints/mod_gsmopen/gsmopen_protocol.cpp @@ -3101,7 +3101,7 @@ int gsmopen_serial_getstatus_AT(private_t *tech_pvt) DEBUGA_AT("incoming SMS message:---%s---\n", GSMOPEN_P_LOG, p->sms_message); pipe(fd1); - pid1 = fork(); + pid1 = switch_fork(); if (pid1 == 0) { //child int err; diff --git a/src/mod/formats/mod_shell_stream/mod_shell_stream.c b/src/mod/formats/mod_shell_stream/mod_shell_stream.c index 38969c84f6..a682eb424d 100644 --- a/src/mod/formats/mod_shell_stream/mod_shell_stream.c +++ b/src/mod/formats/mod_shell_stream/mod_shell_stream.c @@ -108,7 +108,7 @@ static switch_status_t shell_stream_file_open(switch_file_handle_t *handle, cons if (pipe(context->fds)) { goto error; } else { /* good to go */ - context->pid = fork(); + context->pid = switch_fork(); if (context->pid < 0) { /* ok maybe not */ goto error; diff --git a/src/mod/xml_int/mod_xml_scgi/xml_scgi_server.pl b/src/mod/xml_int/mod_xml_scgi/xml_scgi_server.pl index 0f4af275bc..c10fd515ee 100644 --- a/src/mod/xml_int/mod_xml_scgi/xml_scgi_server.pl +++ b/src/mod/xml_int/mod_xml_scgi/xml_scgi_server.pl @@ -65,7 +65,7 @@ $SIG{CHLD} = "IGNORE"; while (my $request = $scgi->accept) { # fork every new req into its own process (optional) - my $pid = fork(); + my $pid = switch_fork(); if ($pid) { $request->close(); diff --git a/src/switch.c b/src/switch.c index 4f8678a97f..0ddefbc5da 100644 --- a/src/switch.c +++ b/src/switch.c @@ -262,7 +262,7 @@ static void daemonize(int do_wait) } } - pid = fork(); + pid = switch_fork(); switch (pid) { case 0: /* child process */ diff --git a/src/switch_core.c b/src/switch_core.c index 1d87d9ce2e..70d4cd5d0f 100644 --- a/src/switch_core.c +++ b/src/switch_core.c @@ -2731,15 +2731,33 @@ SWITCH_DECLARE(void) switch_close_extra_files(int *keep, int keep_ttl) } - #ifdef WIN32 static int switch_system_fork(const char *cmd, switch_bool_t wait) { return switch_system_thread(cmd, wait); } +SWITCH_DECLARE(pid_t) switch_fork(void) +{ + return -1; +} + + #else +SWITCH_DECLARE(pid_t) switch_fork(void) +{ + int i = fork(); + + if (!i) { + set_low_priority(); + } + + return i; +} + + + static int switch_system_fork(const char *cmd, switch_bool_t wait) { int pid; @@ -2747,7 +2765,7 @@ static int switch_system_fork(const char *cmd, switch_bool_t wait) switch_core_set_signal_handlers(); - pid = fork(); + pid = switch_fork(); if (pid) { if (wait) { @@ -2757,7 +2775,6 @@ static int switch_system_fork(const char *cmd, switch_bool_t wait) } else { switch_close_extra_files(NULL, 0); - set_low_priority(); if (system(dcmd) == -1) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to execute because of a command error : %s\n", dcmd); } @@ -2793,7 +2810,7 @@ SWITCH_DECLARE(int) switch_stream_system_fork(const char *cmd, switch_stream_han if (pipe(fds)) { goto end; } else { /* good to go */ - pid = fork(); + pid = switch_fork(); if (pid < 0) { /* ok maybe not */ close(fds[0]); diff --git a/src/switch_xml.c b/src/switch_xml.c index a4da3ca6cf..f441567cac 100644 --- a/src/switch_xml.c +++ b/src/switch_xml.c @@ -1238,7 +1238,7 @@ static FILE *preprocess_exec(const char *cwd, const char *command, FILE *write_f if (pipe(fds)) { goto end; } else { /* good to go */ - pid = fork(); + pid = switch_fork(); if (pid < 0) { /* ok maybe not */ close(fds[0]); From 5620d6d063b104502208a46e0c3170de5f74237c Mon Sep 17 00:00:00 2001 From: Jeff Lenk Date: Mon, 1 Oct 2012 20:34:15 -0500 Subject: [PATCH 096/252] windows fixes for priority - needs to be revisited when apr and pthread versions support calls. --- libs/sofia-sip/libsofia-sip-ua/su/su_pthread_port.c | 3 +++ src/switch_apr.c | 10 ++++++++++ 2 files changed, 13 insertions(+) diff --git a/libs/sofia-sip/libsofia-sip-ua/su/su_pthread_port.c b/libs/sofia-sip/libsofia-sip-ua/su/su_pthread_port.c index 9899da6f47..90b335d491 100644 --- a/libs/sofia-sip/libsofia-sip-ua/su/su_pthread_port.c +++ b/libs/sofia-sip/libsofia-sip-ua/su/su_pthread_port.c @@ -268,7 +268,10 @@ int su_pthreaded_port_start(su_port_create_f *create, pthread_mutex_lock(arg.mutex); if (pthread_create(&tid, &attr, su_pthread_port_clone_main, &arg) == 0) { +#ifndef WIN32 + /* this needs to be revisited when pthread for windows supports thread priority settings */ pthread_setschedprio(tid, 99); +#endif pthread_cond_wait(arg.cv, arg.mutex); thread_created = 1; } diff --git a/src/switch_apr.c b/src/switch_apr.c index 64e066853e..2fcb2cd81e 100644 --- a/src/switch_apr.c +++ b/src/switch_apr.c @@ -620,6 +620,14 @@ struct apr_threadattr_t { pthread_attr_t attr; int priority; }; +#else +/* this needs to be revisited when apr for windows supports thread priority settings */ +/* search for WIN32 in this file */ +struct apr_threadattr_t { + apr_pool_t *pool; + apr_int32_t detach; + apr_size_t stacksize; +}; #endif @@ -628,7 +636,9 @@ SWITCH_DECLARE(switch_status_t) switch_threadattr_create(switch_threadattr_t ** switch_status_t status; if ((status = apr_threadattr_create(new_attr, pool)) == SWITCH_STATUS_SUCCESS) { +#ifndef WIN32 (*new_attr)->priority = SWITCH_PRI_NORMAL; +#endif } return status; From bc06155740c409f23527ef1602b36a0426c097c5 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Tue, 2 Oct 2012 07:39:21 -0500 Subject: [PATCH 097/252] more priority tweaks --- src/switch_apr.c | 2 +- src/switch_core.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/switch_apr.c b/src/switch_apr.c index 2fcb2cd81e..aeb10185a9 100644 --- a/src/switch_apr.c +++ b/src/switch_apr.c @@ -637,7 +637,7 @@ SWITCH_DECLARE(switch_status_t) switch_threadattr_create(switch_threadattr_t ** if ((status = apr_threadattr_create(new_attr, pool)) == SWITCH_STATUS_SUCCESS) { #ifndef WIN32 - (*new_attr)->priority = SWITCH_PRI_NORMAL; + (*new_attr)->priority = SWITCH_PRI_LOW; #endif } diff --git a/src/switch_core.c b/src/switch_core.c index 70d4cd5d0f..4912f0abd8 100644 --- a/src/switch_core.c +++ b/src/switch_core.c @@ -735,7 +735,7 @@ SWITCH_DECLARE(int32_t) set_realtime_priority(void) const char *rt = "/proc/sys/kernel/sched_rt_runtime_us"; char data[] = "-1\n"; struct sched_param sched = { 0 }; - sched.sched_priority = SWITCH_PRI_REALTIME; + sched.sched_priority = SWITCH_PRI_LOW; if (sched_setscheduler(0, SCHED_RR, &sched)) { sched.sched_priority = 0; if (sched_setscheduler(0, SCHED_OTHER, &sched)) { From b97e0cef29aa44ea22687250e306ede822c98a8e Mon Sep 17 00:00:00 2001 From: Raymond Chandler Date: Tue, 2 Oct 2012 11:54:19 -0400 Subject: [PATCH 098/252] don't disable dial if previously allowed --- src/mod/applications/mod_httapi/mod_httapi.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/mod/applications/mod_httapi/mod_httapi.c b/src/mod/applications/mod_httapi/mod_httapi.c index 887dae3891..35427c7b79 100644 --- a/src/mod/applications/mod_httapi/mod_httapi.c +++ b/src/mod/applications/mod_httapi/mod_httapi.c @@ -1970,19 +1970,19 @@ static switch_status_t do_config(void) } else if (!strcasecmp(var, "dial")) { profile->perms.dial.enabled = switch_true(val); } else if (!strcasecmp(var, "dial-set-context")) { - profile->perms.dial.enabled = switch_true(val); + if (switch_true(val)) profile->perms.dial.enabled = SWITCH_TRUE; profile->perms.dial.set_context = switch_true(val); } else if (!strcasecmp(var, "dial-set-dialplan")) { - profile->perms.dial.enabled = switch_true(val); + if (switch_true(val)) profile->perms.dial.enabled = SWITCH_TRUE; profile->perms.dial.set_dp = switch_true(val); } else if (!strcasecmp(var, "dial-set-cid-name")) { - profile->perms.dial.enabled = switch_true(val); + if (switch_true(val)) profile->perms.dial.enabled = SWITCH_TRUE; profile->perms.dial.set_cid_name = switch_true(val); } else if (!strcasecmp(var, "dial-set-cid-number")) { - profile->perms.dial.enabled = switch_true(val); + if (switch_true(val)) profile->perms.dial.enabled = SWITCH_TRUE; profile->perms.dial.set_cid_number = switch_true(val); } else if (!strcasecmp(var, "dial-full-originate")) { - profile->perms.dial.enabled = switch_true(val); + if (switch_true(val)) profile->perms.dial.enabled = SWITCH_TRUE; profile->perms.dial.full_originate = switch_true(val); } else if (!strcasecmp(var, "conference")) { profile->perms.conference.enabled = switch_true(val); From ff3c0139fc9ab48b71b5a2723f6db06c0fd0f054 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Tue, 2 Oct 2012 09:29:25 -0500 Subject: [PATCH 099/252] auto-answer A leg when B leg is already answered in all conditions not just when A leg is both unanswered and has no media --- src/switch_ivr_bridge.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/switch_ivr_bridge.c b/src/switch_ivr_bridge.c index 590ebcea34..990b121f00 100644 --- a/src/switch_ivr_bridge.c +++ b/src/switch_ivr_bridge.c @@ -1304,10 +1304,10 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_multi_threaded_bridge(switch_core_ses switch_core_session_rwunlock(peer_session); goto done; } + } - if (switch_channel_test_flag(peer_channel, CF_ANSWERED) && !switch_channel_test_flag(caller_channel, CF_ANSWERED)) { - switch_channel_answer(caller_channel); - } + if (switch_channel_test_flag(peer_channel, CF_ANSWERED) && !switch_channel_test_flag(caller_channel, CF_ANSWERED)) { + switch_channel_answer(caller_channel); } switch_channel_wait_for_flag(peer_channel, CF_BROADCAST, SWITCH_FALSE, 10000, caller_channel); From 10657f3f5c1fb00d6b8e85d3956c170695b169bd Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Tue, 2 Oct 2012 11:56:21 -0500 Subject: [PATCH 100/252] FS-4675 --resolve --- .../applications/mod_commands/mod_commands.c | 20 +++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/src/mod/applications/mod_commands/mod_commands.c b/src/mod/applications/mod_commands/mod_commands.c index d823af7194..892d6e7479 100644 --- a/src/mod/applications/mod_commands/mod_commands.c +++ b/src/mod/applications/mod_commands/mod_commands.c @@ -1563,15 +1563,19 @@ SWITCH_STANDARD_API(regex_function) proceed = switch_regex_perform(argv[0], argv[1], &re, ovector, sizeof(ovector) / sizeof(ovector[0])); if (argc > 2) { - len = (strlen(argv[0]) + strlen(argv[2]) + 10) * proceed; - substituted = malloc(len); - switch_assert(substituted); - memset(substituted, 0, len); - switch_replace_char(argv[2], '%', '$', SWITCH_FALSE); - switch_perform_substitution(re, proceed, argv[2], argv[0], substituted, len, ovector); + if (proceed) { + len = (strlen(argv[0]) + strlen(argv[2]) + 10) * proceed; + substituted = malloc(len); + switch_assert(substituted); + memset(substituted, 0, len); + switch_replace_char(argv[2], '%', '$', SWITCH_FALSE); + switch_perform_substitution(re, proceed, argv[2], argv[0], substituted, len, ovector); - stream->write_function(stream, "%s", substituted); - free(substituted); + stream->write_function(stream, "%s", substituted); + free(substituted); + } else { + stream->write_function(stream, "%s", argv[0]); + } } else { stream->write_function(stream, proceed ? "true" : "false"); } From 80c2bd786a6b1f20dd577b6d9d810f7a0cf02d3e Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Tue, 2 Oct 2012 10:30:51 -0500 Subject: [PATCH 101/252] FS-4669 --resolve --- src/mod/endpoints/mod_sofia/sofia.c | 22 ++++++++++++++++++++-- src/switch_rtp.c | 2 +- 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/src/mod/endpoints/mod_sofia/sofia.c b/src/mod/endpoints/mod_sofia/sofia.c index 3b5277647f..2a6dc4cc5f 100644 --- a/src/mod/endpoints/mod_sofia/sofia.c +++ b/src/mod/endpoints/mod_sofia/sofia.c @@ -5839,13 +5839,31 @@ static void sofia_handle_sip_r_invite(switch_core_session_t *session, int status } - if (!switch_channel_test_flag(channel, CF_PROXY_MODE) && - sip->sip_payload && sip->sip_payload->pl_data && switch_stristr("m=image", sip->sip_payload->pl_data)) { + if (sip->sip_payload && sip->sip_payload->pl_data && switch_stristr("m=image", sip->sip_payload->pl_data)) { has_t38 = 1; } if (switch_channel_test_flag(channel, CF_PROXY_MODE)) { sofia_clear_flag(tech_pvt, TFLAG_T38_PASSTHRU); + has_t38 = 0; + } + + if (switch_channel_test_flag(channel, CF_PROXY_MEDIA) && has_t38) { + if (switch_rtp_ready(tech_pvt->rtp_session)) { + switch_rtp_udptl_mode(tech_pvt->rtp_session); + + if ((uuid = switch_channel_get_partner_uuid(channel)) && (other_session = switch_core_session_locate(uuid))) { + if (switch_core_session_compare(session, other_session)) { + private_object_t *other_tech_pvt = switch_core_session_get_private(other_session); + if (switch_rtp_ready(other_tech_pvt->rtp_session)) { + switch_rtp_udptl_mode(other_tech_pvt->rtp_session); + } + } + switch_core_session_rwunlock(other_session); + } + } + + has_t38 = 0; } if (status > 199 && (switch_channel_test_flag(channel, CF_PROXY_MODE) || diff --git a/src/switch_rtp.c b/src/switch_rtp.c index 14fbe1a849..0acae50c19 100644 --- a/src/switch_rtp.c +++ b/src/switch_rtp.c @@ -4520,7 +4520,7 @@ SWITCH_DECLARE(int) switch_rtp_write_frame(switch_rtp_t *rtp_session, switch_fra send_msg = frame->packet; - if (!switch_test_flag(rtp_session, SWITCH_RTP_FLAG_UDPTL)) { + if (!switch_test_flag(rtp_session, SWITCH_RTP_FLAG_UDPTL) && !switch_test_flag(frame, SFF_UDPTL_PACKET)) { if (switch_test_flag(rtp_session, SWITCH_RTP_FLAG_VIDEO)) { send_msg->header.pt = rtp_session->payload; } From 2722f4da194b98de8cb5415c6d1af651b9d5af90 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Tue, 2 Oct 2012 11:02:42 -0500 Subject: [PATCH 102/252] FS-4674 add loopback_export for a list of channel vars to pass from loopback-a to loopback-b --- src/mod/endpoints/mod_loopback/mod_loopback.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/mod/endpoints/mod_loopback/mod_loopback.c b/src/mod/endpoints/mod_loopback/mod_loopback.c index e2a2c3daab..e8a8ab8c18 100644 --- a/src/mod/endpoints/mod_loopback/mod_loopback.c +++ b/src/mod/endpoints/mod_loopback/mod_loopback.c @@ -992,6 +992,24 @@ static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *sessi } if (switch_event_dup(&clone, var_event) == SWITCH_STATUS_SUCCESS) { + const char *var; + + if ((var = switch_channel_get_variable(channel, "loopback_export"))) { + int argc = 0; + char *argv[128] = { 0 }; + char *dup = switch_core_session_strdup(session, var); + + if ((argc = switch_split(dup, ',', argv))) { + int i; + for (i = 0; i < argc; i++) { + if (!zstr(argv[i])) { + const char *val = switch_channel_get_variable(channel, argv[i]); + switch_event_add_header_string(clone, SWITCH_STACK_BOTTOM, argv[i], val); + } + } + } + } + switch_channel_set_private(channel, "__loopback_vars__", clone); } From 51bdf8522a1a17fc4d09ba78473772cb2c7071e1 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Tue, 2 Oct 2012 12:22:03 -0500 Subject: [PATCH 103/252] FS-4677 --resolve --- .../applications/mod_conference/mod_conference.c | 13 +++++++++---- src/mod/endpoints/mod_sofia/sofia.c | 5 ++++- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/src/mod/applications/mod_conference/mod_conference.c b/src/mod/applications/mod_conference/mod_conference.c index 3acb7d6c55..ada1d84877 100644 --- a/src/mod/applications/mod_conference/mod_conference.c +++ b/src/mod/applications/mod_conference/mod_conference.c @@ -1325,7 +1325,7 @@ static void send_rfc_event(conference_obj_t *conference) -static void send_conference_notify(conference_obj_t *conference, const char *status, switch_bool_t final) +static void send_conference_notify(conference_obj_t *conference, const char *status, const char *call_id, switch_bool_t final) { switch_event_t *event; char *name = NULL, *domain = NULL, *dup_domain = NULL; @@ -1352,6 +1352,7 @@ static void send_conference_notify(conference_obj_t *conference, const char *sta switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "conference-name", name); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "conference-domain", domain); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "conference-event", "refer"); + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "call_id", call_id); if (final) { switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "final", "true"); @@ -6566,9 +6567,11 @@ static switch_status_t conference_outcall(conference_obj_t *conference, switch_bool_t have_flags = SWITCH_FALSE; const char *outcall_flags; int track = 0; + const char *call_id; if (var_event && switch_true(switch_event_get_header(var_event, "conference_track_status"))) { track++; + call_id = switch_event_get_header(var_event, "conference_track_call_id"); } *cause = SWITCH_CAUSE_NORMAL_CLEARING; @@ -6613,7 +6616,7 @@ static switch_status_t conference_outcall(conference_obj_t *conference, switch_mutex_unlock(conference->mutex); if (track) { - send_conference_notify(conference, "SIP/2.0 100 Trying\r\n", SWITCH_FALSE); + send_conference_notify(conference, "SIP/2.0 100 Trying\r\n", call_id, SWITCH_FALSE); } @@ -6630,14 +6633,14 @@ static switch_status_t conference_outcall(conference_obj_t *conference, } if (track) { - send_conference_notify(conference, "SIP/2.0 481 Failure\r\n", SWITCH_TRUE); + send_conference_notify(conference, "SIP/2.0 481 Failure\r\n", call_id, SWITCH_TRUE); } goto done; } if (track) { - send_conference_notify(conference, "SIP/2.0 200 OK\r\n", SWITCH_TRUE); + send_conference_notify(conference, "SIP/2.0 200 OK\r\n", call_id, SWITCH_TRUE); } rdlock = 1; @@ -8571,6 +8574,7 @@ static void call_setup_event_handler(switch_event_t *event) char *action = switch_event_get_header(event, "Request-Action"); char *ext = switch_event_get_header(event, "Request-Target-Extension"); char *full_url = switch_event_get_header(event, "full_url"); + char *call_id = switch_event_get_header(event, "Request-Call-ID"); if (!ext) ext = dial_str; @@ -8600,6 +8604,7 @@ static void call_setup_event_handler(switch_event_t *event) switch_event_add_header_string(var_event, SWITCH_STACK_BOTTOM, "conference_invite_uri", dial_uri); switch_event_add_header_string(var_event, SWITCH_STACK_BOTTOM, "conference_track_status", "true"); + switch_event_add_header_string(var_event, SWITCH_STACK_BOTTOM, "conference_track_call_id", call_id); if (!strncasecmp(ostr, "url+", 4)) { ostr += 4; diff --git a/src/mod/endpoints/mod_sofia/sofia.c b/src/mod/endpoints/mod_sofia/sofia.c index 2a6dc4cc5f..a74a490da8 100644 --- a/src/mod/endpoints/mod_sofia/sofia.c +++ b/src/mod/endpoints/mod_sofia/sofia.c @@ -1326,7 +1326,10 @@ static void our_sofia_event_callback(nua_event_t event, switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "full-url", "true"); } - + if (sip->sip_call_id && sip->sip_call_id->i_id) { + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Request-Call-ID", sip->sip_call_id->i_id); + } + if (!zstr(referred_by)) { switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Request-Sender", "sofia/%s/%s", profile->name, referred_by); } From d84df73aaa87b46b781c53e8388bae83b33b88dc Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Tue, 2 Oct 2012 17:03:22 -0500 Subject: [PATCH 104/252] FS-4677 oops --- src/mod/applications/mod_conference/mod_conference.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mod/applications/mod_conference/mod_conference.c b/src/mod/applications/mod_conference/mod_conference.c index ada1d84877..089879ad40 100644 --- a/src/mod/applications/mod_conference/mod_conference.c +++ b/src/mod/applications/mod_conference/mod_conference.c @@ -6567,7 +6567,7 @@ static switch_status_t conference_outcall(conference_obj_t *conference, switch_bool_t have_flags = SWITCH_FALSE; const char *outcall_flags; int track = 0; - const char *call_id; + const char *call_id = NULL; if (var_event && switch_true(switch_event_get_header(var_event, "conference_track_status"))) { track++; From 686a89a7984b05a7ee2a7b68619d7a14d0a83366 Mon Sep 17 00:00:00 2001 From: Travis Cross Date: Wed, 3 Oct 2012 02:15:51 +0000 Subject: [PATCH 105/252] debian: Formatting fix --- debian/README.Debian | 4 ++-- debian/README.source | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/debian/README.Debian b/debian/README.Debian index 72be2ce528..99bf84c567 100644 --- a/debian/README.Debian +++ b/debian/README.Debian @@ -1,5 +1,5 @@ FreeSWITCH for Debian --------------- +--------------------- This debian packaging breaks out every module of freeswitch into a separate package, so be sure to verify that you are actually @@ -23,4 +23,4 @@ recommend doing the following: /etc/init.d/freeswitch start fs_cli - -- Travis Cross , Sat, 5 May 2012 23:41:29 +0000 + -- Travis Cross , Wed, 3 Oct 2012 02:15:32 +0000 diff --git a/debian/README.source b/debian/README.source index f432311158..1f1f054f8e 100644 --- a/debian/README.source +++ b/debian/README.source @@ -1,5 +1,5 @@ FreeSWITCH for Debian --------------- +--------------------- You may be reading this because you're wondering where all the files are in debian/, such as control. You may also be here looking for the @@ -94,4 +94,4 @@ freeswitch-music-*: git clone https://github.com/traviscross/freeswitch-sounds.git cd freeswitch-sounds && cat debian/README.source - -- Travis Cross , Tue, 4 Sep 2012 14:56:52 +0000 + -- Travis Cross , Wed, 3 Oct 2012 02:15:24 +0000 From 03fce657e8ed7ccf2d38b2014dd595d7901d0756 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Wed, 3 Oct 2012 07:09:59 -0500 Subject: [PATCH 106/252] FS-4549 --resolve --- .../applications/mod_commands/mod_commands.c | 25 +++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/src/mod/applications/mod_commands/mod_commands.c b/src/mod/applications/mod_commands/mod_commands.c index 892d6e7479..38e85a47c2 100644 --- a/src/mod/applications/mod_commands/mod_commands.c +++ b/src/mod/applications/mod_commands/mod_commands.c @@ -286,7 +286,28 @@ SWITCH_STANDARD_API(shutdown_function) SWITCH_STANDARD_API(version_function) { - stream->write_function(stream, "FreeSWITCH Version %s (%s)\n", SWITCH_VERSION_FULL, SWITCH_VERSION_REVISION_HUMAN); + int argc; + char *mydata = NULL, *argv[2]; + + if (zstr(cmd)) { + stream->write_function(stream, "FreeSWITCH Version %s (%s)\n", SWITCH_VERSION_FULL, SWITCH_VERSION_REVISION_HUMAN); + goto end; + } + + mydata = strdup(cmd); + switch_assert(mydata); + + argc = switch_separate_string(mydata, ' ', argv, (sizeof(argv) / sizeof(argv[0]))); + + if (argv[0] && switch_stristr("short", argv[0])) { + stream->write_function(stream, "%s.%s.%s\n", SWITCH_VERSION_MAJOR,SWITCH_VERSION_MINOR,SWITCH_VERSION_MICRO); + } else { + stream->write_function(stream, "FreeSWITCH Version %s (%s)\n", SWITCH_VERSION_FULL, SWITCH_VERSION_FULL_HUMAN); + } + + switch_safe_free(mydata); + +end: return SWITCH_STATUS_SUCCESS; } @@ -5658,7 +5679,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_commands_load) SWITCH_ADD_API(commands_api_interface, "fsctl", "control messages", ctl_function, CTL_SYNTAX); SWITCH_ADD_API(commands_api_interface, "...", "shutdown", shutdown_function, ""); SWITCH_ADD_API(commands_api_interface, "shutdown", "shutdown", shutdown_function, ""); - SWITCH_ADD_API(commands_api_interface, "version", "version", version_function, ""); + SWITCH_ADD_API(commands_api_interface, "version", "version", version_function, "[short]"); SWITCH_ADD_API(commands_api_interface, "global_getvar", "global_getvar", global_getvar_function, GLOBAL_GETVAR_SYNTAX); SWITCH_ADD_API(commands_api_interface, "global_setvar", "global_setvar", global_setvar_function, GLOBAL_SETVAR_SYNTAX); SWITCH_ADD_API(commands_api_interface, "group_call", "Generate a dial string to call a group", group_call_function, "[@]"); From ea599992e1fc150f63bc3fa96bcc34d1d570c1ad Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Wed, 3 Oct 2012 07:42:05 -0500 Subject: [PATCH 107/252] FS-4656 --resolve with this patch the bug is fixed but also the old behaviour of setting this variable on the A leg expecting it to auto-set it on the B leg is no longer supported. It must be exported or put in the dialstring with {} to put it on the B leg going forward --- src/mod/endpoints/mod_sofia/mod_sofia.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/mod/endpoints/mod_sofia/mod_sofia.c b/src/mod/endpoints/mod_sofia/mod_sofia.c index a9721b4c49..d3a8b8a104 100644 --- a/src/mod/endpoints/mod_sofia/mod_sofia.c +++ b/src/mod/endpoints/mod_sofia/mod_sofia.c @@ -4909,13 +4909,8 @@ static switch_call_cause_t sofia_outgoing_channel(switch_core_session_t *session if (session) { const char *vval = NULL; - if ((vval = switch_channel_get_variable(o_channel, "sip_auto_answer")) && switch_true(vval)) { - switch_channel_set_variable_printf(nchannel, "sip_h_Call-Info", ";answer-after=0", profile->sipip); - switch_channel_set_variable(nchannel, "sip_invite_params", "intercom=true"); - } - switch_ivr_transfer_variable(session, nsession, SOFIA_REPLACES_HEADER); - switch_ivr_transfer_variable(session, nsession, "sip_auto_answer"); + if (!(vval = switch_channel_get_variable(o_channel, "sip_copy_custom_headers")) || switch_true(vval)) { switch_ivr_transfer_variable(session, nsession, SOFIA_SIP_HEADER_PREFIX_T); } From 7329787b9a536d0dc9304677ea8980882e2cfe05 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Wed, 3 Oct 2012 07:45:39 -0500 Subject: [PATCH 108/252] fix warning --- src/mod/applications/mod_commands/mod_commands.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mod/applications/mod_commands/mod_commands.c b/src/mod/applications/mod_commands/mod_commands.c index 38e85a47c2..f1a9953fde 100644 --- a/src/mod/applications/mod_commands/mod_commands.c +++ b/src/mod/applications/mod_commands/mod_commands.c @@ -299,7 +299,7 @@ SWITCH_STANDARD_API(version_function) argc = switch_separate_string(mydata, ' ', argv, (sizeof(argv) / sizeof(argv[0]))); - if (argv[0] && switch_stristr("short", argv[0])) { + if (argc > 0 && switch_stristr("short", argv[0])) { stream->write_function(stream, "%s.%s.%s\n", SWITCH_VERSION_MAJOR,SWITCH_VERSION_MINOR,SWITCH_VERSION_MICRO); } else { stream->write_function(stream, "FreeSWITCH Version %s (%s)\n", SWITCH_VERSION_FULL, SWITCH_VERSION_FULL_HUMAN); From cefeaee88c0a2127a670a3e5f66c44d4fa856fc3 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Wed, 3 Oct 2012 07:46:37 -0500 Subject: [PATCH 109/252] FS-4650 --resolve --- .../applications/mod_commands/mod_commands.c | 136 ++++++++++++++++++ 1 file changed, 136 insertions(+) diff --git a/src/mod/applications/mod_commands/mod_commands.c b/src/mod/applications/mod_commands/mod_commands.c index f1a9953fde..a4554a7925 100644 --- a/src/mod/applications/mod_commands/mod_commands.c +++ b/src/mod/applications/mod_commands/mod_commands.c @@ -181,6 +181,141 @@ SWITCH_STANDARD_API(say_string_function) } +static void dump_user(const char *dname, const char* gname, switch_xml_t x_user_tag, switch_stream_handle_t *stream, const char *_context) +{ + switch_xml_t x_vars, x_var; + switch_status_t status; + switch_stream_handle_t apistream = { 0 }; + char *user_context = NULL; + char *effective_caller_id_name = NULL; + char *effective_caller_id_number = NULL; + char *callgroup = NULL; + + if (!x_user_tag) { + return; + } + + if ((x_vars = switch_xml_child(x_user_tag, "variables"))) { + for (x_var = switch_xml_child(x_vars, "variable"); x_var; x_var = x_var->next) { + const char *key = switch_xml_attr_soft(x_var, "name"); + const char *val = switch_xml_attr_soft(x_var, "value"); + + if (!strcasecmp(key, "user_context")) { + user_context = (char*) val; + } else if (!strcasecmp(key, "effective_caller_id_name")) { + effective_caller_id_name = (char*) val; + } else if (!strcasecmp(key, "effective_caller_id_number")) { + effective_caller_id_number = (char*) val; + } else if (!strcasecmp(key, "callgroup")) { + callgroup = (char*) val; + } else { + continue; + } + } + } + + if (_context) { + if (zstr(user_context) || strcasecmp(_context, user_context)) { + return; + } + } + + SWITCH_STANDARD_STREAM(apistream); + if ((status = switch_api_execute("sofia_contact", switch_xml_attr_soft(x_user_tag, "id"), NULL, &apistream)) != SWITCH_STATUS_SUCCESS) { + switch_safe_free(apistream.data); + return; + } + stream->write_function(stream, "%s|%s|%s|%s|%s|%s|%s|%s\n", switch_xml_attr_soft(x_user_tag, "id"), user_context, dname, gname, apistream.data, callgroup, effective_caller_id_name, effective_caller_id_number); + switch_safe_free(apistream.data); + + return; +} + +#define LIST_USERS_SYNTAX "[group ] [domain ] [user ] [context ]" +SWITCH_STANDARD_API(list_users_function) +{ + int argc; + char *pdata, *argv[8]; + int32_t arg = 0; + switch_xml_t xml_root, x_domains, x_domain_tag; + switch_xml_t gts, gt, uts, ut; + char *_user = NULL, *_domain = NULL, *_context = NULL, *_group = NULL; + + + if ((pdata = strdup(cmd))) { + argc = switch_separate_string(pdata, ' ', argv, (sizeof(argv) / sizeof(argv[0]))); + + if (argc >= 8) { + stream->write_function(stream, "-USAGE: %s\n", LIST_USERS_SYNTAX); + goto done; + } + + for (arg = 0; arg < argc; arg++) { + if (!strcasecmp(argv[arg], "user")) { + _user = argv[arg + 1]; + } + if (!strcasecmp(argv[arg], "domain")) { + _domain = argv[arg + 1]; + } + if (!strcasecmp(argv[arg], "context")) { + _context = argv[arg + 1]; + } + if (!strcasecmp(argv[arg], "group")) { + _group = argv[arg + 1]; + } + } + } + + stream->write_function(stream, "userid|context|domain|group|contact|callgroup|effective_caller_id_name|effective_caller_id_number\n"); + + if (switch_xml_locate("directory", NULL, NULL, NULL, &xml_root, &x_domains, NULL, SWITCH_FALSE) == SWITCH_STATUS_SUCCESS) { + const char *dname = NULL; + const char *gname = NULL; + + for (x_domain_tag = switch_xml_child(x_domains, "domain"); x_domain_tag; x_domain_tag = x_domain_tag->next) { + dname = switch_xml_attr_soft(x_domain_tag, "name"); + + if (_domain && strcasecmp(_domain, dname)) { + continue; + } + + if ((gts = switch_xml_child(x_domain_tag, "groups"))) { + for (gt = switch_xml_child(gts, "group"); gt; gt = gt->next) { + gname = switch_xml_attr_soft(gt, "name"); + + if (_group && strcasecmp(_group, gname)) { + continue; + } + + for (uts = switch_xml_child(gt, "users"); uts; uts = uts->next) { + for (ut = switch_xml_child(uts, "user"); ut; ut = ut->next) { + if (_user && strcasecmp(_user, switch_xml_attr_soft(ut, "id"))) { + continue; + } + dump_user(dname, gname, ut, stream, _context); + } + } + } + } else { + for (uts = switch_xml_child(x_domain_tag, "users"); uts; uts = uts->next) { + for (ut = switch_xml_child(uts, "user"); ut; ut = ut->next) { + if (_user && strcasecmp(_user, switch_xml_attr_soft(ut, "id"))) { + continue; + } + dump_user(dname, gname, ut, stream, _context); + } + } + } + } + switch_xml_free(xml_root); + } + + stream->write_function(stream, "\n+OK\n"); + +done: + switch_safe_free(pdata); + return SWITCH_STATUS_SUCCESS; +} SWITCH_STANDARD_API(reg_url_function) { @@ -5695,6 +5830,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_commands_load) SWITCH_ADD_API(commands_api_interface, "limit_status", "Gets the status of a limit backend", limit_status_function, ""); SWITCH_ADD_API(commands_api_interface, "limit_reset", "Reset the counters of a limit backend", limit_reset_function, ""); SWITCH_ADD_API(commands_api_interface, "limit_interval_reset", "Reset the interval counter for a limited resource", limit_interval_reset_function, LIMIT_INTERVAL_RESET_SYNTAX); + SWITCH_ADD_API(commands_api_interface, "list_users", "List Users configured in Directory", list_users_function, LIST_USERS_SYNTAX); SWITCH_ADD_API(commands_api_interface, "load", "Load Module", load_function, LOAD_SYNTAX); SWITCH_ADD_API(commands_api_interface, "log", "Log", log_function, LOG_SYNTAX); SWITCH_ADD_API(commands_api_interface, "md5", "md5", md5_function, ""); From fd177cdf332a02d84e7ff514afe3883cc5371548 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Wed, 3 Oct 2012 09:29:50 -0500 Subject: [PATCH 110/252] FS-4676 going over the traces the only thing I can guess is that you may have some race condition on the speed of your box or something regarding the db, Try this patch that may help --- src/mod/endpoints/mod_sofia/sofia_presence.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/mod/endpoints/mod_sofia/sofia_presence.c b/src/mod/endpoints/mod_sofia/sofia_presence.c index 10d741bca4..d7d7a49cf7 100644 --- a/src/mod/endpoints/mod_sofia/sofia_presence.c +++ b/src/mod/endpoints/mod_sofia/sofia_presence.c @@ -3138,9 +3138,6 @@ static int broadsoft_sla_notify_callback(void *pArg, int argc, char **argv, char switch_snprintf(key, sizeof(key), "%s%s", user, host); data = switch_core_hash_find(sh->hash, key); - - data = switch_core_hash_find(sh->hash, key); - if (data) { tmp = switch_core_sprintf(sh->pool, "%s,;appearance-index=*;appearance-state=idle", data, host); } else { @@ -3354,7 +3351,7 @@ static int sync_sla(sofia_profile_t *profile, const char *to_user, const char *t switch_core_hash_init(&sh->hash, sh->pool); sql = switch_mprintf("select sip_from_user,sip_from_host,call_info,call_info_state,uuid from sip_dialogs " - "where call_info_state is not null and call_info_state != '' and hostname='%q' and profile_name='%q' " + "where call_info_state is not null and call_info_state != '' and call_info_state != 'idle' and hostname='%q' and profile_name='%q' " "and ((sip_from_user='%q' and sip_from_host='%q') or presence_id='%q@%q') " "and profile_name='%q'", mod_sofia_globals.hostname, profile->name, to_user, to_host, to_user, to_host, profile->name); From 6d01ad5e38ebc536ad3f7166a024db48b71123ef Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Wed, 3 Oct 2012 14:10:22 -0500 Subject: [PATCH 111/252] some more priority tweaks --- src/mod/endpoints/mod_sofia/sofia.c | 4 ++-- src/switch_core.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/mod/endpoints/mod_sofia/sofia.c b/src/mod/endpoints/mod_sofia/sofia.c index a74a490da8..26ff378ee4 100644 --- a/src/mod/endpoints/mod_sofia/sofia.c +++ b/src/mod/endpoints/mod_sofia/sofia.c @@ -1650,7 +1650,7 @@ void sofia_msg_thread_start(int idx) switch_threadattr_create(&thd_attr, mod_sofia_globals.pool); switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE); - switch_threadattr_priority_set(thd_attr, SWITCH_PRI_REALTIME); + //switch_threadattr_priority_set(thd_attr, SWITCH_PRI_REALTIME); switch_thread_create(&mod_sofia_globals.msg_queue_thread[i], thd_attr, sofia_msg_thread_run, @@ -2376,7 +2376,7 @@ switch_thread_t *launch_sofia_worker_thread(sofia_profile_t *profile) switch_threadattr_create(&thd_attr, profile->pool); switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE); - switch_threadattr_priority_set(thd_attr, SWITCH_PRI_REALTIME); + //switch_threadattr_priority_set(thd_attr, SWITCH_PRI_REALTIME); switch_thread_create(&thread, thd_attr, sofia_profile_worker_thread_run, profile, profile->pool); while (!sofia_test_pflag(profile, PFLAG_WORKER_RUNNING)) { diff --git a/src/switch_core.c b/src/switch_core.c index 4912f0abd8..4e47519757 100644 --- a/src/switch_core.c +++ b/src/switch_core.c @@ -736,7 +736,7 @@ SWITCH_DECLARE(int32_t) set_realtime_priority(void) char data[] = "-1\n"; struct sched_param sched = { 0 }; sched.sched_priority = SWITCH_PRI_LOW; - if (sched_setscheduler(0, SCHED_RR, &sched)) { + if (sched_setscheduler(0, SCHED_FIFO, &sched)) { sched.sched_priority = 0; if (sched_setscheduler(0, SCHED_OTHER, &sched)) { return -1; From 61033f420bd0a4a11061b705a415b6007c96be99 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Wed, 3 Oct 2012 14:19:34 -0500 Subject: [PATCH 112/252] revert --- src/include/switch_core.h | 3 --- src/switch_console.c | 4 +-- src/switch_core_sqldb.c | 53 ++------------------------------------- 3 files changed, 4 insertions(+), 56 deletions(-) diff --git a/src/include/switch_core.h b/src/include/switch_core.h index efd983ded8..540de6e537 100644 --- a/src/include/switch_core.h +++ b/src/include/switch_core.h @@ -2303,9 +2303,6 @@ SWITCH_DECLARE(switch_status_t) _switch_core_db_handle(switch_cache_db_handle_t SWITCH_DECLARE(switch_status_t) _switch_core_recovery_db_handle(switch_cache_db_handle_t ** dbh, const char *file, const char *func, int line); #define switch_core_recovery_db_handle(_a) _switch_core_recovery_db_handle(_a, __FILE__, __SWITCH_FUNC__, __LINE__) -SWITCH_DECLARE(switch_status_t) _switch_core_persist_db_handle(switch_cache_db_handle_t ** dbh, const char *file, const char *func, int line); -#define switch_core_persist_db_handle(_a) _switch_core_persist_db_handle(_a, __FILE__, __SWITCH_FUNC__, __LINE__) - SWITCH_DECLARE(switch_bool_t) switch_cache_db_test_reactive(switch_cache_db_handle_t *db, const char *test_sql, const char *drop_sql, const char *reactive_sql); SWITCH_DECLARE(switch_status_t) switch_cache_db_persistant_execute(switch_cache_db_handle_t *dbh, const char *sql, uint32_t retries); diff --git a/src/switch_console.c b/src/switch_console.c index d461333860..059ff79d59 100644 --- a/src/switch_console.c +++ b/src/switch_console.c @@ -248,7 +248,7 @@ SWITCH_DECLARE(char *) switch_console_expand_alias(char *cmd, char *arg) return NULL; } - if (switch_core_persist_db_handle(&db) != SWITCH_STATUS_SUCCESS) { + if (switch_core_db_handle(&db) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Database Error\n"); return NULL; } @@ -1859,7 +1859,7 @@ SWITCH_DECLARE(switch_status_t) switch_console_set_alias(const char *string) switch_cache_db_handle_t *db = NULL; char *sql = NULL; - if (switch_core_persist_db_handle(&db) != SWITCH_STATUS_SUCCESS) { + if (switch_core_db_handle(&db) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Database Error\n"); free(mydata); return SWITCH_STATUS_FALSE; diff --git a/src/switch_core_sqldb.c b/src/switch_core_sqldb.c index 556e3abab2..b4a58bbd9d 100644 --- a/src/switch_core_sqldb.c +++ b/src/switch_core_sqldb.c @@ -176,7 +176,7 @@ static switch_cache_db_handle_t *get_handle(const char *db_str, const char *user } -#define SWITCH_CORE_DB "file:scoreboard?mode=memory&cache=shared" +#define SWITCH_CORE_DB "core" /*! \brief Open the default system database */ @@ -218,49 +218,6 @@ SWITCH_DECLARE(switch_status_t) _switch_core_db_handle(switch_cache_db_handle_t return r; } -#define SWITCH_CORE_PERSIST_DB "core" -/*! - \brief Open the default system database -*/ -SWITCH_DECLARE(switch_status_t) _switch_core_persist_db_handle(switch_cache_db_handle_t **dbh, const char *file, const char *func, int line) -{ - switch_cache_db_connection_options_t options = { {0} }; - switch_status_t r; - - if (!sql_manager.manage) { - return SWITCH_STATUS_FALSE; - } - - if (zstr(runtime.odbc_dsn)) { - if (switch_test_flag((&runtime), SCF_CORE_ODBC_REQ)) { - return SWITCH_STATUS_FALSE; - } - - if (runtime.dbname) { - options.core_db_options.db_path = runtime.dbname; - } else { - options.core_db_options.db_path = SWITCH_CORE_PERSIST_DB; - } - r = _switch_cache_db_get_db_handle(dbh, SCDB_TYPE_CORE_DB, &options, file, func, line); - - } else { - options.odbc_options.dsn = runtime.odbc_dsn; - options.odbc_options.user = runtime.odbc_user; - options.odbc_options.pass = runtime.odbc_pass; - - r = _switch_cache_db_get_db_handle(dbh, SCDB_TYPE_ODBC, &options, file, func, line); - } - - /* I *think* we can do without this now, if not let me know - if (r == SWITCH_STATUS_SUCCESS && !(*dbh)->io_mutex) { - (*dbh)->io_mutex = sql_manager.io_mutex; - } - */ - - return r; -} - - #define SWITCH_CORE_RECOVERY_DB "core_recovery" SWITCH_DECLARE(switch_status_t) _switch_core_recovery_db_handle(switch_cache_db_handle_t **dbh, const char *file, const char *func, int line) { @@ -2409,13 +2366,7 @@ switch_status_t switch_core_sqldb_start(switch_memory_pool_t *pool, switch_bool_ break; } - { - switch_cache_db_handle_t *db = NULL; - switch_core_persist_db_handle(&db); - switch_cache_db_test_reactive(db, "select hostname from aliases", "DROP TABLE aliases", create_alias_sql); - switch_cache_db_release_db_handle(&db); - } - + switch_cache_db_test_reactive(sql_manager.dbh, "select hostname from aliases", "DROP TABLE aliases", create_alias_sql); switch_cache_db_test_reactive(sql_manager.dbh, "select hostname from complete", "DROP TABLE complete", create_complete_sql); switch_cache_db_test_reactive(sql_manager.dbh, "select hostname from nat", "DROP TABLE nat", create_nat_sql); switch_cache_db_test_reactive(sql_manager.dbh, "delete from registrations where reg_user='' or network_proto='tcp' or network_proto='tls'", From 7afd4cae6708fb68accb663c56a639daef8d8178 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Thu, 4 Oct 2012 08:02:32 -0500 Subject: [PATCH 113/252] FS-4677 --- src/mod/endpoints/mod_sofia/sofia_presence.c | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/src/mod/endpoints/mod_sofia/sofia_presence.c b/src/mod/endpoints/mod_sofia/sofia_presence.c index d7d7a49cf7..eea01d50a5 100644 --- a/src/mod/endpoints/mod_sofia/sofia_presence.c +++ b/src/mod/endpoints/mod_sofia/sofia_presence.c @@ -934,7 +934,7 @@ static void send_conference_data(sofia_profile_t *profile, switch_event_t *event sql = switch_mprintf("select full_to, full_from, contact %q ';_;isfocus', expires, call_id, event, network_ip, network_port, " "'%q' as ct,'%q' as pt " " from sip_subscriptions where " - "hostname='%q' and profile_name='%q' and sub_to_user='%q' and sub_to_host='%q' and event='%q'" + "hostname='%q' and profile_name='%q' and sub_to_user='%q' and sub_to_host='%q' and event='%q' " "and call_id = '%q' ", switch_sql_concat(), type, @@ -956,10 +956,19 @@ static void send_conference_data(sofia_profile_t *profile, switch_event_t *event sofia_glue_execute_sql_callback(profile, profile->ireg_mutex, sql, sofia_presence_send_sql, &cb); if (switch_true(final)) { - sql = switch_mprintf("delete from sip_subscriptions where " - "hostname='%q' and profile_name='%q' and sub_to_user='%q' and sub_to_host='%q' and event='%q'", - mod_sofia_globals.hostname, profile->name, - from_user, from_host, event_str); + if (call_id) { + sql = switch_mprintf("delete from sip_subscriptions where " + "hostname='%q' and profile_name='%q' and sub_to_user='%q' and sub_to_host='%q' and event='%q' " + "and call_id = '%q' ", + mod_sofia_globals.hostname, profile->name, + from_user, from_host, event_str, call_id); + + } else { + sql = switch_mprintf("delete from sip_subscriptions where " + "hostname='%q' and profile_name='%q' and sub_to_user='%q' and sub_to_host='%q' and event='%q'", + mod_sofia_globals.hostname, profile->name, + from_user, from_host, event_str); + } sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE); } From 3d57cbda984ebad46fa6c1a94dfd8109b130a2b9 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Thu, 4 Oct 2012 08:29:26 -0500 Subject: [PATCH 114/252] pull this code echo -1 > /proc/sys/kernel/sched_rt_runtime_us yourself if you want to enable this --- src/switch_core.c | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/src/switch_core.c b/src/switch_core.c index 4e47519757..95a7b4dbed 100644 --- a/src/switch_core.c +++ b/src/switch_core.c @@ -731,9 +731,6 @@ SWITCH_DECLARE(int32_t) set_realtime_priority(void) * Try to use a round-robin scheduler * with a fallback if that does not work */ - int fd; - const char *rt = "/proc/sys/kernel/sched_rt_runtime_us"; - char data[] = "-1\n"; struct sched_param sched = { 0 }; sched.sched_priority = SWITCH_PRI_LOW; if (sched_setscheduler(0, SCHED_FIFO, &sched)) { @@ -742,21 +739,6 @@ SWITCH_DECLARE(int32_t) set_realtime_priority(void) return -1; } } - - if ((fd = open(rt, O_WRONLY)) > 0) { - int r; - - if (!(r = write(fd, data, sizeof(data)))) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Error Disablling RT limits [%s][%d]\n", rt, r); - } else { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Disabling RT throttling.\n"); - } - close(fd); - } else { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Error opening %s\n", rt); - } - - #endif From 391e7c365b02d9b822bfeb0daa1fd6e9788c6ba1 Mon Sep 17 00:00:00 2001 From: Eliot Gable Date: Fri, 5 Oct 2012 16:11:12 +0000 Subject: [PATCH 115/252] Rename switch_hash_first() and switch_hash_next() to switch_core_hash_first() and switch_core_hash_next() and deprecate the older versions. --- src/include/switch_core.h | 29 +++++++++++++++++++++++++++-- src/switch_core_hash.c | 25 ++++++++++++++++++++++--- 2 files changed, 49 insertions(+), 5 deletions(-) diff --git a/src/include/switch_core.h b/src/include/switch_core.h index efd983ded8..a7c4122759 100644 --- a/src/include/switch_core.h +++ b/src/include/switch_core.h @@ -1332,14 +1332,14 @@ SWITCH_DECLARE(void *) switch_core_hash_find_rdlock(_In_ switch_hash_t *hash, _I \param hash the hashtable to use \return The element, or NULL if it wasn't found */ -SWITCH_DECLARE(switch_hash_index_t *) switch_hash_first(char *deprecate_me, _In_ switch_hash_t *hash); +SWITCH_DECLARE(switch_hash_index_t *) switch_core_hash_first(_In_ switch_hash_t *hash); /*! \brief Gets the next element of a hashtable \param hi The current element \return The next element, or NULL if there are no more */ -SWITCH_DECLARE(switch_hash_index_t *) switch_hash_next(_In_ switch_hash_index_t *hi); +SWITCH_DECLARE(switch_hash_index_t *) switch_core_hash_next(_In_ switch_hash_index_t *hi); /*! \brief Gets the key and value of the current hash element @@ -1348,6 +1348,31 @@ SWITCH_DECLARE(switch_hash_index_t *) switch_hash_next(_In_ switch_hash_index_t \param klen [out] the key's size \param val [out] the value */ +SWITCH_DECLARE(void) switch_core_hash_this(_In_ switch_hash_index_t *hi, _Out_opt_ptrdiff_cap_(klen) + const void **key, _Out_opt_ switch_ssize_t *klen, _Out_ void **val); + +/*! + \brief DEPRECATED in favor of switch_core_hash_first(). Gets the first element of a hashtable. + \param deprecate_me [deprecated] NULL + \param hash the hashtable to use + \return The element, or NULL if it wasn't found +*/ +SWITCH_DECLARE(switch_hash_index_t *) switch_hash_first(char *deprecate_me, _In_ switch_hash_t *hash); + +/*! + \brief DEPRECATED in favor of switch_core_hash_next(). Gets the next element of a hashtable. + \param hi The current element + \return The next element, or NULL if there are no more +*/ +SWITCH_DECLARE(switch_hash_index_t *) switch_hash_next(_In_ switch_hash_index_t *hi); + +/*! + \brief DEPRECATED in favor of switch_core_hash_this(). Gets the key and value of the current hash element. + \param hi The current element + \param key [out] the key + \param klen [out] the key's size + \param val [out] the value +*/ SWITCH_DECLARE(void) switch_hash_this(_In_ switch_hash_index_t *hi, _Out_opt_ptrdiff_cap_(klen) const void **key, _Out_opt_ switch_ssize_t *klen, _Out_ void **val); diff --git a/src/switch_core_hash.c b/src/switch_core_hash.c index c31a31fa9c..fd9494374a 100644 --- a/src/switch_core_hash.c +++ b/src/switch_core_hash.c @@ -222,17 +222,17 @@ SWITCH_DECLARE(void *) switch_core_hash_find_rdlock(switch_hash_t *hash, const c return val; } -SWITCH_DECLARE(switch_hash_index_t *) switch_hash_first(char *deprecate_me, switch_hash_t *hash) +SWITCH_DECLARE(switch_hash_index_t *) switch_core_hash_first(switch_hash_t *hash) { return (switch_hash_index_t *) sqliteHashFirst(&hash->table); } -SWITCH_DECLARE(switch_hash_index_t *) switch_hash_next(switch_hash_index_t *hi) +SWITCH_DECLARE(switch_hash_index_t *) switch_core_hash_next(switch_hash_index_t *hi) { return (switch_hash_index_t *) sqliteHashNext((HashElem *) hi); } -SWITCH_DECLARE(void) switch_hash_this(switch_hash_index_t *hi, const void **key, switch_ssize_t *klen, void **val) +SWITCH_DECLARE(void) switch_core_hash_this(switch_hash_index_t *hi, const void **key, switch_ssize_t *klen, void **val) { if (key) { *key = sqliteHashKey((HashElem *) hi); @@ -245,6 +245,25 @@ SWITCH_DECLARE(void) switch_hash_this(switch_hash_index_t *hi, const void **key, } } +/* Deprecated */ +SWITCH_DECLARE(switch_hash_index_t *) switch_hash_first(char *deprecate_me, switch_hash_t *hash) +{ + (void*)(deprecate_me); + return switch_core_hash_first(hash); +} + +/* Deprecated */ +SWITCH_DECLARE(switch_hash_index_t *) switch_hash_next(switch_hash_index_t *hi) +{ + return switch_core_hash_next(hi); +} + +/* Deprecated */ +SWITCH_DECLARE(void) switch_hash_this(switch_hash_index_t *hi, const void **key, switch_ssize_t *klen, void **val) +{ + return switch_core_hash_this(hi, key, klen, val); +} + /* For Emacs: * Local Variables: * mode:c From 5bc1f537bc35287ababb1530df9e1ac37a92bf19 Mon Sep 17 00:00:00 2001 From: Eliot Gable Date: Fri, 5 Oct 2012 16:48:03 +0000 Subject: [PATCH 116/252] Fix compiler warnings. --- src/switch_core_hash.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/switch_core_hash.c b/src/switch_core_hash.c index fd9494374a..4159d8b5fa 100644 --- a/src/switch_core_hash.c +++ b/src/switch_core_hash.c @@ -248,7 +248,6 @@ SWITCH_DECLARE(void) switch_core_hash_this(switch_hash_index_t *hi, const void * /* Deprecated */ SWITCH_DECLARE(switch_hash_index_t *) switch_hash_first(char *deprecate_me, switch_hash_t *hash) { - (void*)(deprecate_me); return switch_core_hash_first(hash); } @@ -261,7 +260,7 @@ SWITCH_DECLARE(switch_hash_index_t *) switch_hash_next(switch_hash_index_t *hi) /* Deprecated */ SWITCH_DECLARE(void) switch_hash_this(switch_hash_index_t *hi, const void **key, switch_ssize_t *klen, void **val) { - return switch_core_hash_this(hi, key, klen, val); + switch_core_hash_this(hi, key, klen, val); } /* For Emacs: From a6602206deca73496d031efaefa5b6b5ec4610d3 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Fri, 5 Oct 2012 09:00:30 -0500 Subject: [PATCH 117/252] FS-4684 try this, this behaviour is not supported in proxy mode --- src/mod/endpoints/mod_sofia/sofia_glue.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/mod/endpoints/mod_sofia/sofia_glue.c b/src/mod/endpoints/mod_sofia/sofia_glue.c index 4c0ae8de1f..a67bc97b36 100644 --- a/src/mod/endpoints/mod_sofia/sofia_glue.c +++ b/src/mod/endpoints/mod_sofia/sofia_glue.c @@ -1830,6 +1830,9 @@ void sofia_glue_tech_patch_sdp(private_object_t *tech_pvt) tech_pvt->video_rm_rate = 90000; tech_pvt->video_codec_ms = 0; switch_snprintf(vport_buf, sizeof(vport_buf), "%u", tech_pvt->adv_sdp_video_port); + if (switch_channel_media_ready(tech_pvt->channel) && !switch_rtp_ready(tech_pvt->video_rtp_session)) { + sofia_glue_activate_rtp(tech_pvt, 0); + } } strncpy(q, p, 8); From 44f78e9e76c4db689a39888bf72b31aaf58b5568 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Fri, 5 Oct 2012 09:43:00 -0500 Subject: [PATCH 118/252] FS-4650 --resolve --- .../applications/mod_commands/mod_commands.c | 123 +++++++++++++++--- 1 file changed, 103 insertions(+), 20 deletions(-) diff --git a/src/mod/applications/mod_commands/mod_commands.c b/src/mod/applications/mod_commands/mod_commands.c index a4554a7925..f3fad29e43 100644 --- a/src/mod/applications/mod_commands/mod_commands.c +++ b/src/mod/applications/mod_commands/mod_commands.c @@ -181,20 +181,57 @@ SWITCH_STANDARD_API(say_string_function) } -static void dump_user(const char *dname, const char* gname, switch_xml_t x_user_tag, switch_stream_handle_t *stream, const char *_context) +struct user_struct { + char *dname; + char *gname; + char *effective_caller_id_name; + char *effective_caller_id_number; + char *callgroup; + switch_xml_t x_user_tag; + switch_stream_handle_t *stream; + char *search_context; + char *context; + switch_xml_t x_domain_tag; +}; + +static void dump_user(struct user_struct *us) { - switch_xml_t x_vars, x_var; + switch_xml_t x_vars, x_var, ux, x_user_tag, x_domain_tag; switch_status_t status; - switch_stream_handle_t apistream = { 0 }; - char *user_context = NULL; + switch_stream_handle_t apistream = { 0 }, *stream; + char *user_context = NULL, *search_context = NULL, *context = NULL; char *effective_caller_id_name = NULL; char *effective_caller_id_number = NULL; - char *callgroup = NULL; + char *dname = NULL, *gname = NULL, *callgroup = NULL; + char *utype = NULL, *uname = NULL; + char *apip = NULL; + + x_user_tag = us->x_user_tag; + x_domain_tag = us->x_domain_tag; + effective_caller_id_name = us->effective_caller_id_name; + effective_caller_id_number = us->effective_caller_id_number; + callgroup = us->callgroup; + dname = us->dname; + gname = us->gname; + stream = us->stream; + context = us->context; + search_context = us->search_context; if (!x_user_tag) { return; } + utype = (char *)switch_xml_attr_soft(us->x_user_tag, "type"); + uname = (char *)switch_xml_attr_soft(us->x_user_tag, "id"); + + if (!strcasecmp(utype, "pointer")) { + if (switch_xml_locate_user_in_domain(uname, x_domain_tag, &ux, NULL) == SWITCH_STATUS_SUCCESS) { + x_user_tag = ux; + } + } + + user_context = (char *)context; + if ((x_vars = switch_xml_child(x_user_tag, "variables"))) { for (x_var = switch_xml_child(x_vars, "variable"); x_var; x_var = x_var->next) { const char *key = switch_xml_attr_soft(x_var, "name"); @@ -214,19 +251,28 @@ static void dump_user(const char *dname, const char* gname, switch_xml_t x_user_ } } - if (_context) { - if (zstr(user_context) || strcasecmp(_context, user_context)) { + if (search_context) { + if (zstr(user_context) || strcasecmp(search_context, user_context)) { return; } } + if(zstr(dname)) { + apip = switch_mprintf("%s",switch_xml_attr_soft(x_user_tag, "id")); + } else { + apip = switch_mprintf("%s@%s",switch_xml_attr_soft(x_user_tag, "id"), dname); + } + SWITCH_STANDARD_STREAM(apistream); - if ((status = switch_api_execute("sofia_contact", switch_xml_attr_soft(x_user_tag, "id"), NULL, &apistream)) != SWITCH_STATUS_SUCCESS) { - switch_safe_free(apistream.data); - return; + if ((status = switch_api_execute("sofia_contact", apip, NULL, &apistream)) != SWITCH_STATUS_SUCCESS) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "sofia_contact '%s' failed. status: %d \n", apip, status ); + goto end; } stream->write_function(stream, "%s|%s|%s|%s|%s|%s|%s|%s\n", switch_xml_attr_soft(x_user_tag, "id"), user_context, dname, gname, apistream.data, callgroup, effective_caller_id_name, effective_caller_id_number); + +end: switch_safe_free(apistream.data); + switch_safe_free(apip); return; } @@ -239,7 +285,7 @@ SWITCH_STANDARD_API(list_users_function) int32_t arg = 0; switch_xml_t xml_root, x_domains, x_domain_tag; switch_xml_t gts, gt, uts, ut; - char *_user = NULL, *_domain = NULL, *_context = NULL, *_group = NULL; + char *_user = NULL, *_domain = NULL, *_search_context = NULL, *_group = NULL; if ((pdata = strdup(cmd))) { @@ -258,7 +304,7 @@ SWITCH_STANDARD_API(list_users_function) _domain = argv[arg + 1]; } if (!strcasecmp(argv[arg], "context")) { - _context = argv[arg + 1]; + _search_context = argv[arg + 1]; } if (!strcasecmp(argv[arg], "group")) { _group = argv[arg + 1]; @@ -269,30 +315,64 @@ SWITCH_STANDARD_API(list_users_function) stream->write_function(stream, "userid|context|domain|group|contact|callgroup|effective_caller_id_name|effective_caller_id_number\n"); if (switch_xml_locate("directory", NULL, NULL, NULL, &xml_root, &x_domains, NULL, SWITCH_FALSE) == SWITCH_STATUS_SUCCESS) { - const char *dname = NULL; - const char *gname = NULL; + struct user_struct us = { 0 }; for (x_domain_tag = switch_xml_child(x_domains, "domain"); x_domain_tag; x_domain_tag = x_domain_tag->next) { - dname = switch_xml_attr_soft(x_domain_tag, "name"); + switch_xml_t x_vars, x_var; - if (_domain && strcasecmp(_domain, dname)) { + us.dname = (char*)switch_xml_attr_soft(x_domain_tag, "name"); + + if (_domain && strcasecmp(_domain, us.dname)) { continue; } + if ((x_vars = switch_xml_child(x_domain_tag, "variables"))) { + if ((x_var = switch_xml_find_child_multi(x_vars, "variable", "name", "user_context", NULL))) { + us.context = (char*)switch_xml_attr_soft(x_var, "value"); + } + if ((x_var = switch_xml_find_child_multi(x_vars, "variable", "name", "callgroup", NULL))) { + us.callgroup = (char*)switch_xml_attr_soft(x_var, "value"); + } + if ((x_var = switch_xml_find_child_multi(x_vars, "variable", "name", "effective_caller_id_name", NULL))) { + us.effective_caller_id_name = (char*)switch_xml_attr_soft(x_var, "value"); + } + if ((x_var = switch_xml_find_child_multi(x_vars, "variable", "name", "effective_caller_id_number", NULL))) { + us.effective_caller_id_number = (char*)switch_xml_attr_soft(x_var, "value"); + } + } + if ((gts = switch_xml_child(x_domain_tag, "groups"))) { for (gt = switch_xml_child(gts, "group"); gt; gt = gt->next) { - gname = switch_xml_attr_soft(gt, "name"); + us.gname = (char*)switch_xml_attr_soft(gt, "name"); - if (_group && strcasecmp(_group, gname)) { + if (_group && strcasecmp(_group, us.gname)) { continue; } + if ((x_vars = switch_xml_child(gt, "variables"))) { + if ((x_var = switch_xml_find_child_multi(x_vars, "variable", "name", "user_context", NULL))) { + us.context = (char*)switch_xml_attr_soft(x_var, "value"); + } + if ((x_var = switch_xml_find_child_multi(x_vars, "variable", "name", "callgroup", NULL))) { + us.callgroup = (char*)switch_xml_attr_soft(x_var, "value"); + } + if ((x_var = switch_xml_find_child_multi(x_vars, "variable", "name", "effective_caller_id_name", NULL))) { + us.effective_caller_id_name = (char*)switch_xml_attr_soft(x_var, "value"); + } + if ((x_var = switch_xml_find_child_multi(x_vars, "variable", "name", "effective_caller_id_number", NULL))) { + us.effective_caller_id_number = (char*)switch_xml_attr_soft(x_var, "value"); + } + } + for (uts = switch_xml_child(gt, "users"); uts; uts = uts->next) { for (ut = switch_xml_child(uts, "user"); ut; ut = ut->next) { if (_user && strcasecmp(_user, switch_xml_attr_soft(ut, "id"))) { continue; } - dump_user(dname, gname, ut, stream, _context); + us.x_user_tag = ut; + us.x_domain_tag = x_domain_tag; + us.stream = stream; + dump_user(&us); } } } @@ -302,7 +382,10 @@ SWITCH_STANDARD_API(list_users_function) if (_user && strcasecmp(_user, switch_xml_attr_soft(ut, "id"))) { continue; } - dump_user(dname, gname, ut, stream, _context); + us.x_user_tag = ut; + us.x_domain_tag = x_domain_tag; + us.stream = stream; + dump_user(&us); } } } From 09b1b8bc7fad6183c844972dbf8d9af3cb0ff62e Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Fri, 5 Oct 2012 10:14:22 -0500 Subject: [PATCH 119/252] add nohead param to skip over the cache check with HEAD method --- src/mod/applications/mod_httapi/mod_httapi.c | 54 +++++++++++--------- 1 file changed, 29 insertions(+), 25 deletions(-) diff --git a/src/mod/applications/mod_httapi/mod_httapi.c b/src/mod/applications/mod_httapi/mod_httapi.c index 35427c7b79..845c342f63 100644 --- a/src/mod/applications/mod_httapi/mod_httapi.c +++ b/src/mod/applications/mod_httapi/mod_httapi.c @@ -2530,37 +2530,41 @@ static switch_status_t locate_url_file(http_file_context_t *context, const char lock_file(context, SWITCH_TRUE); - if ((status = fetch_cache_data(context, url, &headers, NULL)) != SWITCH_STATUS_SUCCESS) { - if (status == SWITCH_STATUS_NOTFOUND) { - unreachable = 2; - if (now - context->expires < globals.not_found_expires) { + if (!context->url_params || !switch_true(switch_event_get_header(context->url_params, "nohead"))) { + if ((status = fetch_cache_data(context, url, &headers, NULL)) != SWITCH_STATUS_SUCCESS) { + if (status == SWITCH_STATUS_NOTFOUND) { + unreachable = 2; + if (now - context->expires < globals.not_found_expires) { + switch_goto_status(SWITCH_STATUS_SUCCESS, end); + } + } else { + unreachable = 1; + } + } + + if (switch_file_exists(context->cache_file, context->pool) != SWITCH_STATUS_SUCCESS && unreachable) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "File at url [%s] is unreachable!\n", url); + goto end; + } + + if (!unreachable && !zstr(context->metadata)) { + metadata = switch_core_sprintf(context->pool, "%s:%s:%s:%s", + url, + switch_event_get_header_nil(headers, "last-modified"), + switch_event_get_header_nil(headers, "etag"), + switch_event_get_header_nil(headers, "content-length") + ); + + if (!strcmp(metadata, context->metadata)) { + write_meta_file(context, metadata, headers); switch_goto_status(SWITCH_STATUS_SUCCESS, end); } - } else { - unreachable = 1; } + + switch_event_destroy(&headers); } - if (switch_file_exists(context->cache_file, context->pool) != SWITCH_STATUS_SUCCESS && unreachable) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "File at url [%s] is unreachable!\n", url); - goto end; - } - if (!unreachable && !zstr(context->metadata)) { - metadata = switch_core_sprintf(context->pool, "%s:%s:%s:%s", - url, - switch_event_get_header_nil(headers, "last-modified"), - switch_event_get_header_nil(headers, "etag"), - switch_event_get_header_nil(headers, "content-length") - ); - - if (!strcmp(metadata, context->metadata)) { - write_meta_file(context, metadata, headers); - switch_goto_status(SWITCH_STATUS_SUCCESS, end); - } - } - - switch_event_destroy(&headers); fetch_cache_data(context, url, &headers, context->cache_file); metadata = switch_core_sprintf(context->pool, "%s:%s:%s:%s", url, From 4dd1591945e4ff8d4ee587796cd0103dc89df407 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Fri, 5 Oct 2012 11:49:29 -0500 Subject: [PATCH 120/252] FS-4684 this should help the proxy situation --- src/switch_rtp.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/switch_rtp.c b/src/switch_rtp.c index 0acae50c19..ab7bc29eb1 100644 --- a/src/switch_rtp.c +++ b/src/switch_rtp.c @@ -4521,7 +4521,8 @@ SWITCH_DECLARE(int) switch_rtp_write_frame(switch_rtp_t *rtp_session, switch_fra send_msg = frame->packet; if (!switch_test_flag(rtp_session, SWITCH_RTP_FLAG_UDPTL) && !switch_test_flag(frame, SFF_UDPTL_PACKET)) { - if (switch_test_flag(rtp_session, SWITCH_RTP_FLAG_VIDEO)) { + + if (switch_test_flag(rtp_session, SWITCH_RTP_FLAG_VIDEO) && rtp_session->payload > 0) { send_msg->header.pt = rtp_session->payload; } From 57e9912f8bf82a22828e858747a231b5a19ec9eb Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Fri, 5 Oct 2012 13:46:57 -0500 Subject: [PATCH 121/252] FS-4650 please try to use an up to date gcc when doing new dev to catch build errs. This is what I get for the one time I did not compile test --- src/mod/applications/mod_commands/mod_commands.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/mod/applications/mod_commands/mod_commands.c b/src/mod/applications/mod_commands/mod_commands.c index f3fad29e43..5923860507 100644 --- a/src/mod/applications/mod_commands/mod_commands.c +++ b/src/mod/applications/mod_commands/mod_commands.c @@ -285,7 +285,7 @@ SWITCH_STANDARD_API(list_users_function) int32_t arg = 0; switch_xml_t xml_root, x_domains, x_domain_tag; switch_xml_t gts, gt, uts, ut; - char *_user = NULL, *_domain = NULL, *_search_context = NULL, *_group = NULL; + char *_user = NULL, *_domain = NULL, *_group = NULL; if ((pdata = strdup(cmd))) { @@ -303,9 +303,7 @@ SWITCH_STANDARD_API(list_users_function) if (!strcasecmp(argv[arg], "domain")) { _domain = argv[arg + 1]; } - if (!strcasecmp(argv[arg], "context")) { - _search_context = argv[arg + 1]; - } + if (!strcasecmp(argv[arg], "group")) { _group = argv[arg + 1]; } From bed72bff7aae829f42a3ce2c954e985624024a78 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Fri, 5 Oct 2012 16:43:39 -0500 Subject: [PATCH 122/252] update vid code in dingaling --- .../endpoints/mod_dingaling/mod_dingaling.c | 29 ++++++++++--------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/src/mod/endpoints/mod_dingaling/mod_dingaling.c b/src/mod/endpoints/mod_dingaling/mod_dingaling.c index e6c2864617..9dd89b0e59 100644 --- a/src/mod/endpoints/mod_dingaling/mod_dingaling.c +++ b/src/mod/endpoints/mod_dingaling/mod_dingaling.c @@ -1098,9 +1098,9 @@ static int activate_audio_rtp(struct private_object *tech_pvt) int r = 1; - if (switch_rtp_ready(tech_pvt->transports[LDL_TPORT_RTP].rtp_session)) { - return 1; - } + //if (switch_rtp_ready(tech_pvt->transports[LDL_TPORT_RTP].rtp_session)) { + // return 1; + //} if (!(tech_pvt->transports[LDL_TPORT_RTP].remote_ip && tech_pvt->transports[LDL_TPORT_RTP].remote_port)) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG, "No valid rtp candidates received!\n"); @@ -1415,9 +1415,10 @@ static int activate_video_rtp(struct private_object *tech_pvt) switch_rtp_activate_ice(tech_pvt->transports[LDL_TPORT_VIDEO_RTP].rtp_session, tech_pvt->transports[LDL_TPORT_VIDEO_RTP].remote_user, tech_pvt->transports[LDL_TPORT_VIDEO_RTP].local_user, - tech_pvt->transports[LDL_TPORT_VIDEO_RTP].remote_pass); + NULL);//tech_pvt->transports[LDL_TPORT_VIDEO_RTP].remote_pass); switch_channel_set_flag(channel, CF_VIDEO); - //switch_rtp_set_default_payload(tech_pvt->transports[LDL_TPORT_VIDEO_RTP].rtp_session, tech_pvt->transports[LDL_TPORT_VIDEO_RTP].r_codec_num); + //switch_rtp_set_default_payload(tech_pvt->transports[LDL_TPORT_VIDEO_RTP].rtp_session, tech_pvt->transports[LDL_TPORT_VIDEO_RTP].codec_num); + //switch_rtp_set_recv_pt(tech_pvt->transports[LDL_TPORT_VIDEO_RTP].rtp_session, tech_pvt->transports[LDL_TPORT_VIDEO_RTP].codec_num); if (tech_pvt->transports[LDL_TPORT_VIDEO_RTCP].remote_port) { @@ -1425,7 +1426,7 @@ static int activate_video_rtp(struct private_object *tech_pvt) switch_rtp_activate_rtcp_ice(tech_pvt->transports[LDL_TPORT_VIDEO_RTP].rtp_session, tech_pvt->transports[LDL_TPORT_VIDEO_RTCP].remote_user, tech_pvt->transports[LDL_TPORT_VIDEO_RTCP].local_user, - tech_pvt->transports[LDL_TPORT_VIDEO_RTCP].remote_pass); + NULL);//tech_pvt->transports[LDL_TPORT_VIDEO_RTCP].remote_pass); } @@ -2236,7 +2237,6 @@ static switch_status_t channel_read_video_frame(switch_core_session_t *session, switch_rtp_zerocopy_read_frame(tech_pvt->transports[LDL_TPORT_VIDEO_RTP].rtp_session, &tech_pvt->transports[LDL_TPORT_VIDEO_RTP].read_frame, flags); } - if (tech_pvt->transports[LDL_TPORT_VIDEO_RTP].read_frame.datalen == 0) { switch_set_flag((&tech_pvt->transports[LDL_TPORT_RTP].read_frame), SFF_CNG); tech_pvt->transports[LDL_TPORT_VIDEO_RTP].read_frame.datalen = 2; @@ -3599,13 +3599,13 @@ static switch_status_t parse_candidates(ldl_session_t *dlsession, switch_core_se if (tech_pvt->transports[ttype].accepted) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Already Accepted [%s:%d]\n", tech_pvt->transports[ttype].remote_ip, tech_pvt->transports[ttype].remote_port); - goto end; + //goto end; } if (tech_pvt->transports[ttype].remote_ip) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Already picked an IP [%s]\n", tech_pvt->transports[ttype].remote_ip); - goto end; + //goto end; } @@ -3663,17 +3663,20 @@ static switch_status_t parse_candidates(ldl_session_t *dlsession, switch_core_se } } - if (!switch_test_flag(tech_pvt, TFLAG_OUTBOUND) && (ttype == LDL_TPORT_VIDEO_RTP || ttype == LDL_TPORT_VIDEO_RTP) && - tech_pvt->transports[ttype].accepted == 1 && (1||switch_test_flag(tech_pvt, TFLAG_RTP_READY))) { + if (!switch_test_flag(tech_pvt, TFLAG_OUTBOUND)) { - if (ttype == LDL_TPORT_VIDEO_RTP) { + if (tech_pvt->transports[LDL_TPORT_VIDEO_RTP].accepted && + tech_pvt->transports[LDL_TPORT_VIDEO_RTCP].accepted) { activate_video_rtp(tech_pvt); } - if (ttype == LDL_TPORT_VIDEO_RTP) { + + if (tech_pvt->transports[LDL_TPORT_RTP].accepted && + tech_pvt->transports[LDL_TPORT_RTCP].accepted) { activate_audio_rtp(tech_pvt); } + tech_pvt->transports[ttype].restart_rtp++; } From 90691b36c4f9feaba9d167b2b3efc9786cd50824 Mon Sep 17 00:00:00 2001 From: Stefan Knoblich Date: Sat, 22 Sep 2012 01:05:51 +0200 Subject: [PATCH 123/252] FreeTDM: Remove trailing whitespace at end of ftdm_{copy,set}_string() Signed-off-by: Stefan Knoblich --- libs/freetdm/src/include/ftdm_os.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libs/freetdm/src/include/ftdm_os.h b/libs/freetdm/src/include/ftdm_os.h index 39afec94be..d9d2b23205 100644 --- a/libs/freetdm/src/include/ftdm_os.h +++ b/libs/freetdm/src/include/ftdm_os.h @@ -64,10 +64,10 @@ typedef uint64_t ftdm_time_t; #endif /*! \brief strncpy replacement */ -#define ftdm_copy_string(x,y,z) strncpy(x, y, z - 1) +#define ftdm_copy_string(x,y,z) strncpy(x, y, z - 1) /*! \brief strncpy into a fixed-length buffer */ -#define ftdm_set_string(x,y) strncpy(x, y, sizeof(x)-1) +#define ftdm_set_string(x,y) strncpy(x, y, sizeof(x)-1) /*! \brief check for null or zero length string buffer */ #define ftdm_strlen_zero(s) (!s || *s == '\0') From 1d605ef47b77c5dc13de130ebbc8766fd456f68f Mon Sep 17 00:00:00 2001 From: Stefan Knoblich Date: Sat, 22 Sep 2012 01:06:34 +0200 Subject: [PATCH 124/252] FreeTDM: Add ftdm_clamp_safe() "Safer" version of ftdm_clamp(), that swaps min/max parameters if vmin happens to be larger than vmax, making sure the output will always satisfy vmin <= x <= vmax. Signed-off-by: Stefan Knoblich --- libs/freetdm/src/include/ftdm_os.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libs/freetdm/src/include/ftdm_os.h b/libs/freetdm/src/include/ftdm_os.h index d9d2b23205..c34810d241 100644 --- a/libs/freetdm/src/include/ftdm_os.h +++ b/libs/freetdm/src/include/ftdm_os.h @@ -87,6 +87,10 @@ typedef uint64_t ftdm_time_t; /*! \brief Get value that is in range [vmin,vmax] */ #define ftdm_clamp(val,vmin,vmax) ftdm_max(vmin,ftdm_min(val,vmax)) +/*!< \brief Safer version of ftdm_clamp(), that swaps vmin/vmax parameters if vmin > vmax */ +#define ftdm_clamp_safe(val,vmin,vmax) \ + ftdm_clamp(val, ftdm_min(vmin,vmax), ftdm_max(vmin,vmax)) + /*! * \brief Get offset of member in structure * \param[in] type Type of struct From da0ff2d615af009d1e4505b957e39b3dc8ab21da Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Sun, 7 Oct 2012 09:40:24 -0500 Subject: [PATCH 125/252] FS-4697 --resolve --- src/switch_core_session.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/switch_core_session.c b/src/switch_core_session.c index 6e565dca06..ab8f31059d 100644 --- a/src/switch_core_session.c +++ b/src/switch_core_session.c @@ -1466,21 +1466,23 @@ static void *SWITCH_THREAD_FUNC switch_core_session_thread_pool_worker(switch_th if (check_status == SWITCH_STATUS_SUCCESS) { switch_core_session_t *session = (switch_core_session_t *) pop; - + switch_size_t id; + if (!session) break; + id = session->id; switch_mutex_lock(session_manager.mutex); session_manager.busy++; switch_mutex_unlock(session_manager.mutex); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG10, "Worker Thread %ld Processing session %"SWITCH_SIZE_T_FMT" %s\n", - (long) thread, session->id, switch_core_session_get_name(session)); + (long) thread, id, switch_core_session_get_name(session)); switch_core_session_thread(thread, (void *) session); - - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG10, "Worker Thread %ld Done Processing session %"SWITCH_SIZE_T_FMT" %s\n", - (long) thread, session->id, switch_core_session_get_name(session)); + + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG10, "Worker Thread %ld Done Processing session %"SWITCH_SIZE_T_FMT"\n", + (long) thread, id); switch_mutex_lock(session_manager.mutex); session_manager.busy--; From 0263ce92478ef65ee976d063167db057943088c1 Mon Sep 17 00:00:00 2001 From: Seven Du Date: Mon, 8 Oct 2012 09:03:24 +0800 Subject: [PATCH 126/252] FS-4695 fix apple build, seems there's no pthread_setschedprio on Mac, not sure if windows has the same problem in apr/threadproc/unix/thread.c --- libs/apr/threadproc/unix/thread.c | 2 ++ libs/sofia-sip/libsofia-sip-ua/su/su_pthread_port.c | 8 ++++++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/libs/apr/threadproc/unix/thread.c b/libs/apr/threadproc/unix/thread.c index 9a56e55405..6c6ff8b842 100644 --- a/libs/apr/threadproc/unix/thread.c +++ b/libs/apr/threadproc/unix/thread.c @@ -174,10 +174,12 @@ APR_DECLARE(apr_status_t) apr_thread_create(apr_thread_t **new, } if ((stat = pthread_create((*new)->td, temp, dummy_worker, (*new))) == 0) { +#ifndef __APPLE__ if (attr->priority) { pthread_t *thread = (*new)->td; pthread_setschedprio(*thread, attr->priority); } +#endif return APR_SUCCESS; } diff --git a/libs/sofia-sip/libsofia-sip-ua/su/su_pthread_port.c b/libs/sofia-sip/libsofia-sip-ua/su/su_pthread_port.c index 90b335d491..db314b28dd 100644 --- a/libs/sofia-sip/libsofia-sip-ua/su/su_pthread_port.c +++ b/libs/sofia-sip/libsofia-sip-ua/su/su_pthread_port.c @@ -268,8 +268,12 @@ int su_pthreaded_port_start(su_port_create_f *create, pthread_mutex_lock(arg.mutex); if (pthread_create(&tid, &attr, su_pthread_port_clone_main, &arg) == 0) { -#ifndef WIN32 - /* this needs to be revisited when pthread for windows supports thread priority settings */ + +#if defined (WIN32) + /* this needs to be revisited when pthread for Windows supports thread priority settings */ +#elif defined (__APPLE__) + /* no such function on Apple */ +#else pthread_setschedprio(tid, 99); #endif pthread_cond_wait(arg.cv, arg.mutex); From 5cb354dddc142a3e8abf0b0a3cdeac28745238fd Mon Sep 17 00:00:00 2001 From: Eliot Gable Date: Sun, 30 Sep 2012 01:48:48 +0000 Subject: [PATCH 127/252] Initial core-pgsql support based on native libpq; FS starts and stops without errors using core-pgsql. --- Makefile.am | 4 +- conf/vanilla/autoload_configs/switch.conf.xml | 2 + conf/vanilla/sip_profiles/internal.xml | 3 + configure.in | 23 + src/include/switch.h | 1 + src/include/switch_core.h | 14 +- src/include/switch_pgsql.h | 162 ++++ src/include/switch_types.h | 4 +- .../mod_cidlookup/mod_cidlookup.c | 32 +- src/mod/applications/mod_db/mod_db.c | 20 +- src/mod/applications/mod_fifo/mod_fifo.c | 20 +- .../mod_voicemail/mod_voicemail.c | 18 +- src/mod/endpoints/mod_sofia/sofia.c | 2 +- src/mod/endpoints/mod_sofia/sofia_glue.c | 18 +- src/switch_core.c | 12 +- src/switch_core_sqldb.c | 268 ++++-- src/switch_pgsql.c | 770 ++++++++++++++++++ 17 files changed, 1283 insertions(+), 90 deletions(-) create mode 100644 src/include/switch_pgsql.h create mode 100644 src/switch_pgsql.c diff --git a/Makefile.am b/Makefile.am index adf412b205..f11f891aac 100644 --- a/Makefile.am +++ b/Makefile.am @@ -207,7 +207,8 @@ library_include_HEADERS = \ libs/libteletone/src/libteletone.h \ libs/libtpl-1.5/src/tpl.h \ src/include/switch_limit.h \ - src/include/switch_odbc.h + src/include/switch_odbc.h \ + src/include/switch_pgsql.h nodist_libfreeswitch_la_SOURCES = \ src/include/switch_frame.h \ @@ -262,6 +263,7 @@ libfreeswitch_la_SOURCES = \ src/switch_config.c \ src/switch_time.c \ src/switch_odbc.c \ + src/switch_pgsql.c \ src/switch_limit.c \ src/g711.c \ src/switch_pcm.c \ diff --git a/conf/vanilla/autoload_configs/switch.conf.xml b/conf/vanilla/autoload_configs/switch.conf.xml index 64f3d6fa71..34bdedcda9 100644 --- a/conf/vanilla/autoload_configs/switch.conf.xml +++ b/conf/vanilla/autoload_configs/switch.conf.xml @@ -144,6 +144,8 @@ + + + + + diff --git a/configure.in b/configure.in index 92a88048fd..4e036b0d81 100644 --- a/configure.in +++ b/configure.in @@ -395,7 +395,30 @@ if test "x$enable_core_odbc_support" != "xno"; then AC_CHECK_LIB([odbc], [SQLDisconnect],, AC_MSG_ERROR([no usable libodbc; please install unixodbc devel package or equivalent])) fi +AC_ARG_ENABLE(core-pgsql-support, + [AS_HELP_STRING([--enable-core-pgsql-support], [Compile with PGSQL Support])],,[enable_core_pgsql_support="no"]) +if test x"$enable_core_pgsql_support" = x"yes" ; then + +AC_PATH_PROG([PG_CONFIG], [pg_config], [no]) +if test "$PG_CONFIG" != "no"; then + AC_MSG_CHECKING([for PostgreSQL libraries]) + POSTGRESQL_CFLAGS="`$PG_CONFIG --cflags` -I`$PG_CONFIG --includedir`" + POSTGRESQL_CXXFLAGS="`$PG_CONFIG --cppflags` -I`$PG_CONFIG --includedir`" + POSTGRESQL_LDFLAGS="`$PG_CONFIG --ldflags` -L`$PG_CONFIG --libdir` -lpq" + POSTGRESQL_VERSION=`$PG_CONFIG --version | sed -e 's#PostgreSQL ##'` + AC_DEFINE([SWITCH_HAVE_PGSQL], [1], [Define to 1 if PostgreSQL libraries are available]) + AC_CHECK_LIB([pq], [PQgetvalue],, AC_MSG_ERROR([no usable libpq; please install PostgreSQL devel package or equivalent])) + AC_MSG_RESULT([yes]) + SWITCH_AM_CFLAGS="$POSTGRESQL_CFLAGS $SWITCH_AM_CFLAGS" + SWITCH_AM_CXXFLAGS="$POSTGRESQL_CXXFLAGS $SWITCH_AM_CXXFLAGS" + SWITCH_AM_LDFLAGS="$POSTGRESQL_LDFLAGS $SWITCH_AM_LDFLAGS" +else + AC_MSG_RESULT([no]) + AC_MSG_FAILURE([Unabled to find pg_config in PATH. Is PostgreSQL installed?]) +fi + +fi AC_ARG_ENABLE(timerfd-wrapper, [AC_HELP_STRING([--enable-timerfd-wrapper],[timerfd is in the kernel but not in your libc])],[enable_timer_fd_wrapper="$enableval"],[enable_timer_fd_wrapper="no"]) diff --git a/src/include/switch.h b/src/include/switch.h index 3e1bfbb77f..1eb45ae48a 100644 --- a/src/include/switch.h +++ b/src/include/switch.h @@ -135,6 +135,7 @@ #include "switch_config.h" #include "switch_nat.h" #include "switch_odbc.h" +#include "switch_pgsql.h" #include "switch_json.h" #include "switch_limit.h" diff --git a/src/include/switch_core.h b/src/include/switch_core.h index fa703eafc0..73607926fa 100644 --- a/src/include/switch_core.h +++ b/src/include/switch_core.h @@ -2210,12 +2210,14 @@ typedef enum { typedef enum { SCDB_TYPE_CORE_DB, - SCDB_TYPE_ODBC + SCDB_TYPE_ODBC, + SCDB_TYPE_PGSQL } switch_cache_db_handle_type_t; typedef union { switch_core_db_t *core_db_dbh; switch_odbc_handle_t *odbc_dbh; + switch_pgsql_handle_t *pgsql_dbh; } switch_cache_db_native_handle_t; typedef struct { @@ -2228,9 +2230,14 @@ typedef struct { char *pass; } switch_cache_db_odbc_options_t; +typedef struct { + char *dsn; +} switch_cache_db_pgsql_options_t; + typedef union { switch_cache_db_core_db_options_t core_db_options; switch_cache_db_odbc_options_t odbc_options; + switch_cache_db_pgsql_options_t pgsql_options; } switch_cache_db_connection_options_t; struct switch_cache_db_handle; @@ -2241,6 +2248,11 @@ static inline const char *switch_cache_db_type_name(switch_cache_db_handle_type_ const char *type_str = "INVALID"; switch (type) { + case SCDB_TYPE_PGSQL: + { + type_str = "PGSQL"; + } + break; case SCDB_TYPE_ODBC: { type_str = "ODBC"; diff --git a/src/include/switch_pgsql.h b/src/include/switch_pgsql.h new file mode 100644 index 0000000000..282172e646 --- /dev/null +++ b/src/include/switch_pgsql.h @@ -0,0 +1,162 @@ +/* + * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application + * Copyright (C) 2005-2012, Anthony Minessale II + * + * 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 + * Portions created by the Initial Developer are Copyright (C) + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Anthony Minessale II + * Eliot Gable + * + * switch_pgsql.h -- PGSQL Driver + * + */ + +#ifndef SWITCH_PGSQL_H +#define SWITCH_PGSQL_H + +#include + +#define DEFAULT_PGSQL_RETRIES 120 + +SWITCH_BEGIN_EXTERN_C + +struct switch_pgsql_handle; +struct switch_pgsql_result; + + +typedef enum { + SWITCH_PGSQL_STATE_INIT, + SWITCH_PGSQL_STATE_DOWN, + SWITCH_PGSQL_STATE_CONNECTED, + SWITCH_PGSQL_STATE_ERROR +} switch_pgsql_state_t; + +typedef enum { + SWITCH_PGSQL_SUCCESS = 0, + SWITCH_PGSQL_FAIL = -1 +} switch_pgsql_status_t; + +/*! + \brief Create a new handle for the PGSQL connection. + \param dsn The DSN of the database to connect to. See documentation for PQconnectdb() at + http://www.postgresql.org/docs/9.0/static/libpq-connect.html. The DSN *MUST* be + prefixed with 'pgsql;' to use the switch_cache_db* functionality. However, the DSN + passed to this function directly *MUST NOT* be prefixed with 'pgsql;'. + \return Returns a pointer to a newly allocated switch_pgsql_handle_t type or NULL on failure. + */ +SWITCH_DECLARE(switch_pgsql_handle_t *) switch_pgsql_handle_new(const char *dsn); + +/*! + \brief Sets the number of retries if the PGSQL connection fails. + \param handle A fully allocated switch_pgsql_handle_t returned from a call to switch_pgsql_handle_new(). + \param num_retries How many times to retry connecting to the database if this connection fails. + */ +SWITCH_DECLARE(void) switch_pgsql_set_num_retries(switch_pgsql_handle_t *handle, int num_retries); + +/*! + \brief Disconnects a PGSQL connection from the database. + \param handle The PGSQL database handle to disconnect. + \return Returns SWITCH_PGSQL_SUCCESS or SWITCH_PGSQL_FAIL. + */ +SWITCH_DECLARE(switch_pgsql_status_t ) switch_pgsql_handle_disconnect(switch_pgsql_handle_t *handle); +#if 0 + ) /* Emacs formatting issue */ +#endif +/*! + \brief Connect to the database specified by the DSN passed to the switch_pgsql_handle_new() call which + initialized this handle. + \param The database handle to connect to the database. + \return Returns SWITCH_PGSQL_SUCCESS or SWITCH_PGSQL_FAIL. + */ +SWITCH_DECLARE(switch_pgsql_status_t) switch_pgsql_handle_connect(switch_pgsql_handle_t *handle); + +/*! + */ +SWITCH_DECLARE(void) switch_pgsql_handle_destroy(switch_pgsql_handle_t **handlep); + +SWITCH_DECLARE(switch_pgsql_status_t) switch_pgsql_send_query(switch_pgsql_handle_t *handle, const char* sql); + +SWITCH_DECLARE(switch_pgsql_status_t) switch_pgsql_cancel_real(const char *file, const char *func, int line, switch_pgsql_handle_t *handle); +#define switch_pgsql_cancel(handle) switch_pgsql_cancel_real(__FILE__, (char * )__SWITCH_FUNC__, __LINE__, handle) + +SWITCH_DECLARE(switch_pgsql_status_t) switch_pgsql_next_result_timed(switch_pgsql_handle_t *handle, switch_pgsql_result_t **result_out, int seconds); +#define switch_pgsql_next_result(h, r) switch_pgsql_next_result_timed(h, r, 10000) + +SWITCH_DECLARE(void) switch_pgsql_free_result(switch_pgsql_result_t **result); + +SWITCH_DECLARE(switch_pgsql_status_t) switch_pgsql_finish_results_real(const char* file, const char *func, int line, switch_pgsql_handle_t *handle); +#define switch_pgsql_finish_results(handle) switch_pgsql_finish_results_real(__FILE__, (char * )__SWITCH_FUNC__, __LINE__, handle) + +SWITCH_DECLARE(switch_pgsql_status_t) switch_pgsql_handle_exec_base(switch_pgsql_handle_t *handle, const char *sql, char **err); + +SWITCH_DECLARE(switch_pgsql_state_t) switch_pgsql_handle_get_state(switch_pgsql_handle_t *handle); +SWITCH_DECLARE(switch_pgsql_status_t) switch_pgsql_handle_exec(switch_pgsql_handle_t *handle, const char *sql, char **err); +SWITCH_DECLARE(switch_pgsql_status_t) switch_pgsql_handle_exec_string(switch_pgsql_handle_t *handle, const char *sql, char *resbuf, size_t len, char **err); +SWITCH_DECLARE(switch_bool_t) switch_pgsql_available(void); +SWITCH_DECLARE(switch_pgsql_status_t) switch_pgsql_SQLSetAutoCommitAttr(switch_pgsql_handle_t *handle, switch_bool_t on); +SWITCH_DECLARE(switch_pgsql_status_t) switch_pgsql_SQLEndTran(switch_pgsql_handle_t *handle, switch_bool_t commit); + +/*! + \brief Execute the sql query and issue a callback for each row returned + \param file the file from which this function is called + \param func the function from which this function is called + \param line the line from which this function is called + \param handle the PGSQL handle + \param sql the sql string to execute + \param callback the callback function to execute + \param pdata the state data passed on each callback invocation + \return SWITCH_STATUS_SUCCESS if the operation was successful + \note none +*/ +SWITCH_DECLARE(switch_pgsql_status_t) switch_pgsql_handle_callback_exec_detailed(const char *file, const char *func, int line, switch_pgsql_handle_t *handle, + const char *sql, switch_core_db_callback_func_t callback, void *pdata, + char **err); +/*! + \brief Execute the sql query and issue a callback for each row returned + \param handle the PGSQL handle + \param sql the sql string to execute + \param callback the callback function to execute + \param pdata the state data passed on each callback invocation + \return SWITCH_STATUS_SUCCESS if the operation was successful + \note none +*/ +#define switch_pgsql_handle_callback_exec(handle, sql, callback, pdata, err) \ + switch_pgsql_handle_callback_exec_detailed(__FILE__, (char * )__SWITCH_FUNC__, __LINE__, \ + handle, sql, callback, pdata, err) + + +SWITCH_DECLARE(char *) switch_pgsql_handle_get_error(switch_pgsql_handle_t *handle); + +SWITCH_DECLARE(int) switch_pgsql_handle_affected_rows(switch_pgsql_handle_t *handle); + +SWITCH_END_EXTERN_C +#endif +/* 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: + */ diff --git a/src/include/switch_types.h b/src/include/switch_types.h index f9d8476454..6f77f32ef4 100644 --- a/src/include/switch_types.h +++ b/src/include/switch_types.h @@ -324,7 +324,7 @@ typedef enum { SCF_CLEAR_SQL = (1 << 17), SCF_THREADED_SYSTEM_EXEC = (1 << 18), SCF_SYNC_CLOCK_REQUESTED = (1 << 19), - SCF_CORE_ODBC_REQ = (1 << 20), + SCF_CORE_NON_SQLITE_DB_REQ = (1 << 20), SCF_DEBUG_SQL = (1 << 21), SCF_API_EXPANSION = (1 << 22), SCF_SESSION_THREAD_POOL = (1 << 23) @@ -1833,6 +1833,8 @@ typedef struct switch_buffer switch_buffer_t; typedef struct switch_codec_settings switch_codec_settings_t; typedef struct switch_codec_fmtp switch_codec_fmtp_t; typedef struct switch_odbc_handle switch_odbc_handle_t; +typedef struct switch_pgsql_handle switch_pgsql_handle_t; +typedef struct switch_pgsql_result switch_pgsql_result_t; typedef struct switch_io_routines switch_io_routines_t; typedef struct switch_speech_handle switch_speech_handle_t; diff --git a/src/mod/applications/mod_cidlookup/mod_cidlookup.c b/src/mod/applications/mod_cidlookup/mod_cidlookup.c index 562cea7f5f..d71278dd2f 100755 --- a/src/mod/applications/mod_cidlookup/mod_cidlookup.c +++ b/src/mod/applications/mod_cidlookup/mod_cidlookup.c @@ -94,12 +94,20 @@ static switch_cache_db_handle_t *cidlookup_get_db_handle(void) switch_cache_db_handle_t *dbh = NULL; if (!zstr(globals.odbc_dsn)) { - options.odbc_options.dsn = globals.odbc_dsn; - options.odbc_options.user = globals.odbc_user; - options.odbc_options.pass = globals.odbc_pass; + char *dsn; + if ((dsn = strstr(globals.odbc_dsn, "pgsql;")) != NULL) { + options.pgsql_options.dsn = (char*)(dsn + 6); - if (switch_cache_db_get_db_handle(&dbh, SCDB_TYPE_ODBC, &options) != SWITCH_STATUS_SUCCESS) - dbh = NULL; + if (switch_cache_db_get_db_handle(&dbh, SCDB_TYPE_PGSQL, &options) != SWITCH_STATUS_SUCCESS) + dbh = NULL; + } else { + options.odbc_options.dsn = globals.odbc_dsn; + options.odbc_options.user = globals.odbc_user; + options.odbc_options.pass = globals.odbc_pass; + + if (switch_cache_db_get_db_handle(&dbh, SCDB_TYPE_ODBC, &options) != SWITCH_STATUS_SUCCESS) + dbh = NULL; + } } return dbh; } @@ -112,8 +120,8 @@ static switch_status_t config_callback_dsn(switch_xml_config_item_t *data, const switch_cache_db_handle_t *dbh = NULL; - if (!switch_odbc_available()) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "ODBC is not compiled in. Do not configure odbc-dsn parameter!\n"); + if (!switch_odbc_available() && !switch_pgsql_available()) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "ODBC and PGSQL are not compiled in. Do not configure odbc-dsn parameter!\n"); return SWITCH_STATUS_FALSE; } @@ -134,7 +142,7 @@ static switch_status_t config_callback_dsn(switch_xml_config_item_t *data, const switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Connecting to dsn: %s\n", globals.odbc_dsn); if (!(dbh = cidlookup_get_db_handle())) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Cannot Open ODBC Database!\n"); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Cannot Open Database!\n"); switch_goto_status(SWITCH_STATUS_FALSE, done); } } @@ -195,7 +203,7 @@ static switch_bool_t cidlookup_execute_sql_callback(char *sql, switch_core_db_ca retval = SWITCH_TRUE; } } else { - *err = switch_core_sprintf(cbt->pool, "Unable to get ODBC handle. dsn: %s, dbh is %s\n", globals.odbc_dsn, dbh ? "not null" : "null"); + *err = switch_core_sprintf(cbt->pool, "Unable to get database handle. dsn: %s, dbh is %s\n", globals.odbc_dsn, dbh ? "not null" : "null"); } switch_cache_db_release_db_handle(&dbh); @@ -564,7 +572,7 @@ static cid_data_t *do_lookup(switch_memory_pool_t *pool, switch_event_t *event, switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "caller_id_number", number); /* database always wins */ - if (switch_odbc_available() && globals.odbc_dsn && globals.sql) { + if ((switch_odbc_available() || switch_pgsql_available()) && globals.odbc_dsn && globals.sql) { name = do_db_lookup(pool, event, number, globals.sql); if (name) { cid->name = name; @@ -610,7 +618,7 @@ static cid_data_t *do_lookup(switch_memory_pool_t *pool, switch_event_t *event, switch_assert(cid); } /* append area if we can */ - if (!cid->area && !skipcitystate && strlen(number) == 11 && number[0] == '1' && switch_odbc_available() && globals.odbc_dsn && globals.citystate_sql) { + if (!cid->area && !skipcitystate && strlen(number) == 11 && number[0] == '1' && (switch_odbc_available() || switch_pgsql_available()) && globals.odbc_dsn && globals.citystate_sql) { /* yes, this is really area */ name = do_db_lookup(pool, event, number, globals.citystate_sql); @@ -768,7 +776,7 @@ SWITCH_STANDARD_API(cidlookup_function) stream->write_function(stream, " odbc-dsn: %s\n sql: %s\n citystate-sql: %s\n", globals.odbc_dsn ? globals.odbc_dsn : "(null)", globals.sql ? globals.sql : "(null)", globals.citystate_sql ? globals.citystate_sql : "(null)"); - stream->write_function(stream, " ODBC Compiled: %s\n", switch_odbc_available()? "true" : "false"); + stream->write_function(stream, " ODBC Compiled: %s; PGSQL Compiled: %s\n", switch_odbc_available() ? "true" : "false", switch_pgsql_available() ? "true" : "false"); switch_goto_status(SWITCH_STATUS_SUCCESS, done); } diff --git a/src/mod/applications/mod_db/mod_db.c b/src/mod/applications/mod_db/mod_db.c index 5c64b20c95..69e0522be7 100644 --- a/src/mod/applications/mod_db/mod_db.c +++ b/src/mod/applications/mod_db/mod_db.c @@ -92,12 +92,20 @@ switch_cache_db_handle_t *limit_get_db_handle(void) switch_cache_db_handle_t *dbh = NULL; if (!zstr(globals.odbc_dsn)) { - options.odbc_options.dsn = globals.odbc_dsn; - options.odbc_options.user = globals.odbc_user; - options.odbc_options.pass = globals.odbc_pass; + char *dsn; + if ((dsn = strstr(globals.odbc_dsn, "pgsql;")) != NULL) { + options.pgsql_options.dsn = (char*)(dsn + 6); - if (switch_cache_db_get_db_handle(&dbh, SCDB_TYPE_ODBC, &options) != SWITCH_STATUS_SUCCESS) - dbh = NULL; + if (switch_cache_db_get_db_handle(&dbh, SCDB_TYPE_PGSQL, &options) != SWITCH_STATUS_SUCCESS) + dbh = NULL; + } else { + options.odbc_options.dsn = globals.odbc_dsn; + options.odbc_options.user = globals.odbc_user; + options.odbc_options.pass = globals.odbc_pass; + + if (switch_cache_db_get_db_handle(&dbh, SCDB_TYPE_ODBC, &options) != SWITCH_STATUS_SUCCESS) + dbh = NULL; + } return dbh; } else { options.core_db_options.db_path = globals.dbname; @@ -275,7 +283,7 @@ SWITCH_LIMIT_STATUS(limit_status_db) /* INIT / Config */ -static switch_xml_config_string_options_t limit_config_dsn = { NULL, 0, "[^:]+:[^:]+:.+" }; +static switch_xml_config_string_options_t limit_config_dsn = { NULL, 0, "^pgsql;|[^:]+:[^:]+:.+" }; static switch_xml_config_item_t config_settings[] = { SWITCH_CONFIG_ITEM("odbc-dsn", SWITCH_CONFIG_STRING, 0, &globals.odbc_dsn, NULL, &limit_config_dsn, diff --git a/src/mod/applications/mod_fifo/mod_fifo.c b/src/mod/applications/mod_fifo/mod_fifo.c index f500c4683a..56383a2973 100644 --- a/src/mod/applications/mod_fifo/mod_fifo.c +++ b/src/mod/applications/mod_fifo/mod_fifo.c @@ -731,12 +731,20 @@ switch_cache_db_handle_t *fifo_get_db_handle(void) switch_cache_db_handle_t *dbh = NULL; if (!zstr(globals.odbc_dsn)) { - options.odbc_options.dsn = globals.odbc_dsn; - options.odbc_options.user = globals.odbc_user; - options.odbc_options.pass = globals.odbc_pass; + char *dsn; + if ((dsn = strstr(globals.odbc_dsn, "pgsql;")) != NULL) { + options.pgsql_options.dsn = (char*)(dsn + 6); - if (switch_cache_db_get_db_handle(&dbh, SCDB_TYPE_ODBC, &options) != SWITCH_STATUS_SUCCESS) { - dbh = NULL; + if (switch_cache_db_get_db_handle(&dbh, SCDB_TYPE_PGSQL, &options) != SWITCH_STATUS_SUCCESS) + dbh = NULL; + } else { + options.odbc_options.dsn = globals.odbc_dsn; + options.odbc_options.user = globals.odbc_user; + options.odbc_options.pass = globals.odbc_pass; + + if (switch_cache_db_get_db_handle(&dbh, SCDB_TYPE_ODBC, &options) != SWITCH_STATUS_SUCCESS) { + dbh = NULL; + } } return dbh; } else { @@ -4010,7 +4018,7 @@ static switch_status_t load_config(int reload, int del_all) } if (!strcasecmp(var, "odbc-dsn") && !zstr(val)) { - if (switch_odbc_available()) { + if (switch_odbc_available() || switch_pgsql_available()) { switch_set_string(globals.odbc_dsn, val); if ((globals.odbc_user = strchr(globals.odbc_dsn, ':'))) { *globals.odbc_user++ = '\0'; diff --git a/src/mod/applications/mod_voicemail/mod_voicemail.c b/src/mod/applications/mod_voicemail/mod_voicemail.c index 78eb57a20a..2e17e5dbf6 100644 --- a/src/mod/applications/mod_voicemail/mod_voicemail.c +++ b/src/mod/applications/mod_voicemail/mod_voicemail.c @@ -167,12 +167,20 @@ switch_cache_db_handle_t *vm_get_db_handle(vm_profile_t *profile) switch_cache_db_handle_t *dbh = NULL; if (!zstr(profile->odbc_dsn)) { - options.odbc_options.dsn = profile->odbc_dsn; - options.odbc_options.user = profile->odbc_user; - options.odbc_options.pass = profile->odbc_pass; + char *dsn; + if ((dsn = strstr(profile->odbc_dsn, "pgsql;")) != NULL) { + options.pgsql_options.dsn = (char*)(dsn + 6); - if (switch_cache_db_get_db_handle(&dbh, SCDB_TYPE_ODBC, &options) != SWITCH_STATUS_SUCCESS) - dbh = NULL; + if (switch_cache_db_get_db_handle(&dbh, SCDB_TYPE_PGSQL, &options) != SWITCH_STATUS_SUCCESS) + dbh = NULL; + } else { + options.odbc_options.dsn = profile->odbc_dsn; + options.odbc_options.user = profile->odbc_user; + options.odbc_options.pass = profile->odbc_pass; + + if (switch_cache_db_get_db_handle(&dbh, SCDB_TYPE_ODBC, &options) != SWITCH_STATUS_SUCCESS) + dbh = NULL; + } return dbh; } else { options.core_db_options.db_path = profile->dbname; diff --git a/src/mod/endpoints/mod_sofia/sofia.c b/src/mod/endpoints/mod_sofia/sofia.c index 26ff378ee4..e738cf2fb0 100644 --- a/src/mod/endpoints/mod_sofia/sofia.c +++ b/src/mod/endpoints/mod_sofia/sofia.c @@ -4414,7 +4414,7 @@ switch_status_t config_sofia(int reload, char *profile_name) sofia_set_flag(profile, TFLAG_CAPTURE); nua_set_params(profile->nua, TPTAG_CAPT(mod_sofia_globals.capture_server), TAG_END()); } else if (!strcasecmp(var, "odbc-dsn") && !zstr(val)) { - if (switch_odbc_available()) { + if (switch_odbc_available() || switch_pgsql_available()) { profile->odbc_dsn = switch_core_strdup(profile->pool, val); if ((profile->odbc_user = strchr(profile->odbc_dsn, ':'))) { *profile->odbc_user++ = '\0'; diff --git a/src/mod/endpoints/mod_sofia/sofia_glue.c b/src/mod/endpoints/mod_sofia/sofia_glue.c index a67bc97b36..a39a8e9e71 100644 --- a/src/mod/endpoints/mod_sofia/sofia_glue.c +++ b/src/mod/endpoints/mod_sofia/sofia_glue.c @@ -6367,12 +6367,20 @@ switch_cache_db_handle_t *sofia_glue_get_db_handle(sofia_profile_t *profile) switch_cache_db_handle_t *dbh = NULL; if (!zstr(profile->odbc_dsn)) { - options.odbc_options.dsn = profile->odbc_dsn; - options.odbc_options.user = profile->odbc_user; - options.odbc_options.pass = profile->odbc_pass; + char *dsn; + if ((dsn = strstr(profile->odbc_dsn, "pgsql;")) != NULL) { + options.pgsql_options.dsn = (char*)(dsn + 6); - if (switch_cache_db_get_db_handle(&dbh, SCDB_TYPE_ODBC, &options) != SWITCH_STATUS_SUCCESS) - dbh = NULL; + if (switch_cache_db_get_db_handle(&dbh, SCDB_TYPE_PGSQL, &options) != SWITCH_STATUS_SUCCESS) + dbh = NULL; + } else { + options.odbc_options.dsn = profile->odbc_dsn; + options.odbc_options.user = profile->odbc_user; + options.odbc_options.pass = profile->odbc_pass; + + if (switch_cache_db_get_db_handle(&dbh, SCDB_TYPE_ODBC, &options) != SWITCH_STATUS_SUCCESS) + dbh = NULL; + } return dbh; } else { options.core_db_options.db_path = profile->dbname; diff --git a/src/switch_core.c b/src/switch_core.c index 95a7b4dbed..8e1a6567d7 100644 --- a/src/switch_core.c +++ b/src/switch_core.c @@ -1910,7 +1910,7 @@ static void switch_load_core_config(const char *file) } else if (!strcasecmp(var, "core-db-name") && !zstr(val)) { runtime.dbname = switch_core_strdup(runtime.memory_pool, val); } else if (!strcasecmp(var, "core-db-dsn") && !zstr(val)) { - if (switch_odbc_available()) { + if (switch_odbc_available() || switch_pgsql_available()) { runtime.odbc_dsn = switch_core_strdup(runtime.memory_pool, val); if ((runtime.odbc_user = strchr(runtime.odbc_dsn, ':'))) { *runtime.odbc_user++ = '\0'; @@ -1919,10 +1919,10 @@ static void switch_load_core_config(const char *file) } } } else { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "ODBC IS NOT AVAILABLE!\n"); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "ODBC AND PGSQL ARE NOT AVAILABLE!\n"); } } else if (!strcasecmp(var, "core-recovery-db-dsn") && !zstr(val)) { - if (switch_odbc_available()) { + if (switch_odbc_available() || switch_pgsql_available()) { runtime.recovery_odbc_dsn = switch_core_strdup(runtime.memory_pool, val); if ((runtime.recovery_odbc_user = strchr(runtime.recovery_odbc_dsn, ':'))) { *runtime.recovery_odbc_user++ = '\0'; @@ -1931,10 +1931,10 @@ static void switch_load_core_config(const char *file) } } } else { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "ODBC IS NOT AVAILABLE!\n"); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "ODBC AND PGSQL ARE NOT AVAILABLE!\n"); } - } else if (!strcasecmp(var, "core-odbc-required") && !zstr(val)) { - switch_set_flag((&runtime), SCF_CORE_ODBC_REQ); + } else if (!strcasecmp(var, "core-non-sqlite-db-required") && !zstr(val)) { + switch_set_flag((&runtime), SCF_CORE_NON_SQLITE_DB_REQ); } else if (!strcasecmp(var, "core-dbtype") && !zstr(val)) { if (!strcasecmp(val, "MSSQL")) { runtime.odbc_dbtype = DBTYPE_MSSQL; diff --git a/src/switch_core_sqldb.c b/src/switch_core_sqldb.c index b4a58bbd9d..cbc7a611e3 100644 --- a/src/switch_core_sqldb.c +++ b/src/switch_core_sqldb.c @@ -190,7 +190,7 @@ SWITCH_DECLARE(switch_status_t) _switch_core_db_handle(switch_cache_db_handle_t } if (zstr(runtime.odbc_dsn)) { - if (switch_test_flag((&runtime), SCF_CORE_ODBC_REQ)) { + if (switch_test_flag((&runtime), SCF_CORE_NON_SQLITE_DB_REQ)) { return SWITCH_STATUS_FALSE; } @@ -202,11 +202,18 @@ SWITCH_DECLARE(switch_status_t) _switch_core_db_handle(switch_cache_db_handle_t r = _switch_cache_db_get_db_handle(dbh, SCDB_TYPE_CORE_DB, &options, file, func, line); } else { - options.odbc_options.dsn = runtime.odbc_dsn; - options.odbc_options.user = runtime.odbc_user; - options.odbc_options.pass = runtime.odbc_pass; + char *dsn; + if ((dsn = strstr(runtime.odbc_dsn, "pgsql;")) != NULL) { + options.pgsql_options.dsn = (char*)(dsn + 6); - r = _switch_cache_db_get_db_handle(dbh, SCDB_TYPE_ODBC, &options, file, func, line); + r = _switch_cache_db_get_db_handle(dbh, SCDB_TYPE_PGSQL, &options, file, func, line); + } else { + options.odbc_options.dsn = runtime.odbc_dsn; + options.odbc_options.user = runtime.odbc_user; + options.odbc_options.pass = runtime.odbc_pass; + + r = _switch_cache_db_get_db_handle(dbh, SCDB_TYPE_ODBC, &options, file, func, line); + } } /* I *think* we can do without this now, if not let me know @@ -218,6 +225,56 @@ SWITCH_DECLARE(switch_status_t) _switch_core_db_handle(switch_cache_db_handle_t return r; } +#define SWITCH_CORE_PERSIST_DB "core" +/*! + \brief Open the default system database +*/ +SWITCH_DECLARE(switch_status_t) _switch_core_persist_db_handle(switch_cache_db_handle_t **dbh, const char *file, const char *func, int line) +{ + switch_cache_db_connection_options_t options = { {0} }; + switch_status_t r; + + if (!sql_manager.manage) { + return SWITCH_STATUS_FALSE; + } + + if (zstr(runtime.odbc_dsn)) { + if (switch_test_flag((&runtime), SCF_CORE_NON_SQLITE_DB_REQ)) { + return SWITCH_STATUS_FALSE; + } + + if (runtime.dbname) { + options.core_db_options.db_path = runtime.dbname; + } else { + options.core_db_options.db_path = SWITCH_CORE_PERSIST_DB; + } + r = _switch_cache_db_get_db_handle(dbh, SCDB_TYPE_CORE_DB, &options, file, func, line); + + } else { + char *dsn; + if ((dsn = strstr(runtime.odbc_dsn, "pgsql;")) != NULL) { + options.pgsql_options.dsn = (char*)(dsn + 6); + + r = _switch_cache_db_get_db_handle(dbh, SCDB_TYPE_PGSQL, &options, file, func, line); + } else { + options.odbc_options.dsn = runtime.odbc_dsn; + options.odbc_options.user = runtime.odbc_user; + options.odbc_options.pass = runtime.odbc_pass; + + r = _switch_cache_db_get_db_handle(dbh, SCDB_TYPE_ODBC, &options, file, func, line); + } + } + + /* I *think* we can do without this now, if not let me know + if (r == SWITCH_STATUS_SUCCESS && !(*dbh)->io_mutex) { + (*dbh)->io_mutex = sql_manager.io_mutex; + } + */ + + return r; +} + + #define SWITCH_CORE_RECOVERY_DB "core_recovery" SWITCH_DECLARE(switch_status_t) _switch_core_recovery_db_handle(switch_cache_db_handle_t **dbh, const char *file, const char *func, int line) { @@ -229,7 +286,7 @@ SWITCH_DECLARE(switch_status_t) _switch_core_recovery_db_handle(switch_cache_db_ } if (zstr(runtime.recovery_odbc_dsn)) { - if (switch_test_flag((&runtime), SCF_CORE_ODBC_REQ)) { + if (switch_test_flag((&runtime), SCF_CORE_NON_SQLITE_DB_REQ)) { return SWITCH_STATUS_FALSE; } @@ -241,11 +298,18 @@ SWITCH_DECLARE(switch_status_t) _switch_core_recovery_db_handle(switch_cache_db_ r = _switch_cache_db_get_db_handle(dbh, SCDB_TYPE_CORE_DB, &options, file, func, line); } else { - options.odbc_options.dsn = runtime.recovery_odbc_dsn; - options.odbc_options.user = runtime.recovery_odbc_user; - options.odbc_options.pass = runtime.recovery_odbc_pass; + char *dsn; + if ((dsn = strstr(runtime.recovery_odbc_dsn, "pgsql;")) != NULL) { + options.pgsql_options.dsn = (char*)(dsn + 6); - r = _switch_cache_db_get_db_handle(dbh, SCDB_TYPE_ODBC, &options, file, func, line); + r = _switch_cache_db_get_db_handle(dbh, SCDB_TYPE_PGSQL, &options, file, func, line); + } else { + options.odbc_options.dsn = runtime.recovery_odbc_dsn; + options.odbc_options.user = runtime.recovery_odbc_user; + options.odbc_options.pass = runtime.recovery_odbc_pass; + + r = _switch_cache_db_get_db_handle(dbh, SCDB_TYPE_ODBC, &options, file, func, line); + } } /* I *think* we can do without this now, if not let me know @@ -286,6 +350,11 @@ static void sql_close(time_t prune) switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG10, "Dropping idle DB connection %s\n", dbh->name); switch (dbh->type) { + case SCDB_TYPE_PGSQL: + { + switch_pgsql_handle_destroy(&dbh->native_handle.pgsql_dbh); + } + break; case SCDB_TYPE_ODBC: { switch_odbc_handle_destroy(&dbh->native_handle.odbc_dbh); @@ -373,8 +442,8 @@ SWITCH_DECLARE(switch_status_t) _switch_cache_db_get_db_handle(switch_cache_db_h uint32_t yield_len = 100000, total_yield = 0; const char *db_name = NULL; - const char *db_user = NULL; - const char *db_pass = NULL; + const char *odbc_user = NULL; + const char *odbc_pass = NULL; while(runtime.max_db_handles && sql_manager.total_handles >= runtime.max_db_handles && sql_manager.total_used_handles >= sql_manager.total_handles) { if (!waiting++) { @@ -393,18 +462,24 @@ SWITCH_DECLARE(switch_status_t) _switch_cache_db_get_db_handle(switch_cache_db_h } switch (type) { + case SCDB_TYPE_PGSQL: + { + db_name = connection_options->odbc_options.dsn; + odbc_user = NULL; + odbc_pass = NULL; + } case SCDB_TYPE_ODBC: { db_name = connection_options->odbc_options.dsn; - db_user = connection_options->odbc_options.user; - db_pass = connection_options->odbc_options.pass; + odbc_user = connection_options->odbc_options.user; + odbc_pass = connection_options->odbc_options.pass; } break; case SCDB_TYPE_CORE_DB: { db_name = connection_options->core_db_options.db_path; - db_user = ""; - db_pass = ""; + odbc_user = NULL; + odbc_pass = NULL; } break; } @@ -413,8 +488,11 @@ SWITCH_DECLARE(switch_status_t) _switch_cache_db_get_db_handle(switch_cache_db_h return SWITCH_STATUS_FALSE; } - - snprintf(db_str, sizeof(db_str) - 1, "db=\"%s\";user=\"%s\";pass=\"%s\"", db_name, db_user, db_pass); + if (odbc_user || odbc_pass) { + snprintf(db_str, sizeof(db_str) - 1, "db=\"%s\";user=\"%s\";pass=\"%s\"", db_name, odbc_user, odbc_pass); + } else { + snprintf(db_str, sizeof(db_str) - 1, "db=\"%s\"", db_name); + } snprintf(db_callsite_str, sizeof(db_callsite_str) - 1, "%s:%d", file, line); snprintf(thread_str, sizeof(thread_str) - 1, "thread=\"%lu\"", (unsigned long) (intptr_t) self); @@ -424,8 +502,23 @@ SWITCH_DECLARE(switch_status_t) _switch_cache_db_get_db_handle(switch_cache_db_h } else { switch_core_db_t *db = NULL; switch_odbc_handle_t *odbc_dbh = NULL; + switch_pgsql_handle_t *pgsql_dbh = NULL; switch (type) { + case SCDB_TYPE_PGSQL: + { + if (!switch_pgsql_available()) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Failure! PGSQL NOT AVAILABLE! Can't connect to DSN %s\n", connection_options->pgsql_options.dsn); + goto end; + } + + if ((pgsql_dbh = switch_pgsql_handle_new(connection_options->pgsql_options.dsn))) { + if (switch_pgsql_handle_connect(pgsql_dbh) != SWITCH_PGSQL_SUCCESS) { + switch_pgsql_handle_destroy(&pgsql_dbh); + } + } + } + break; case SCDB_TYPE_ODBC: { @@ -454,8 +547,8 @@ SWITCH_DECLARE(switch_status_t) _switch_cache_db_get_db_handle(switch_cache_db_h goto end; } - if (!db && !odbc_dbh) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Failure to connect to %s %s!\n", db?"SQLITE":"ODBC", db?connection_options->core_db_options.db_path:connection_options->odbc_options.dsn); + if (!db && !odbc_dbh && !pgsql_dbh) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Failure to connect to %s %s!\n", (db ? "SQLITE" : (odbc_dbh ? "ODBC" : "PGSQL")), (db ? connection_options->core_db_options.db_path : (odbc_dbh ? connection_options->odbc_options.dsn : connection_options->pgsql_options.dsn))); goto end; } @@ -466,8 +559,10 @@ SWITCH_DECLARE(switch_status_t) _switch_cache_db_get_db_handle(switch_cache_db_h if (db) { new_dbh->native_handle.core_db_dbh = db; - } else { + } else if (odbc_dbh) { new_dbh->native_handle.odbc_dbh = odbc_dbh; + } else { + new_dbh->native_handle.pgsql_dbh = pgsql_dbh; } add_handle(new_dbh, db_str, db_callsite_str, thread_str); @@ -499,6 +594,11 @@ static switch_status_t switch_cache_db_execute_sql_real(switch_cache_db_handle_t } switch (dbh->type) { + case SCDB_TYPE_PGSQL: + { + status = switch_pgsql_handle_exec(dbh->native_handle.pgsql_dbh, sql, &errmsg); + } + break; case SCDB_TYPE_ODBC: { status = switch_odbc_handle_exec(dbh->native_handle.odbc_dbh, sql, NULL, &errmsg); @@ -650,6 +750,11 @@ SWITCH_DECLARE(int) switch_cache_db_affected_rows(switch_cache_db_handle_t *dbh) return switch_odbc_handle_affected_rows(dbh->native_handle.odbc_dbh); } break; + case SCDB_TYPE_PGSQL: + { + return switch_pgsql_handle_affected_rows(dbh->native_handle.pgsql_dbh); + } + break; } return 0; } @@ -707,6 +812,11 @@ SWITCH_DECLARE(char *) switch_cache_db_execute_sql2str(switch_cache_db_handle_t status = switch_odbc_handle_exec_string(dbh->native_handle.odbc_dbh, sql, str, len, err); } break; + case SCDB_TYPE_PGSQL: + { + status = switch_pgsql_handle_exec_string(dbh->native_handle.pgsql_dbh, sql, str, len, err); + } + break; } end: @@ -784,16 +894,34 @@ SWITCH_DECLARE(switch_status_t) switch_cache_db_persistant_execute_trans(switch_ while (begin_retries > 0) { again = 0; - if (runtime.odbc_dbtype == DBTYPE_DEFAULT) { - switch_cache_db_execute_sql_real(dbh, "BEGIN", &errmsg); - } else { - switch_odbc_status_t result; - - if ((result = switch_odbc_SQLSetAutoCommitAttr(dbh->native_handle.odbc_dbh, 0)) != SWITCH_ODBC_SUCCESS) { - char tmp[100]; - switch_snprintfv(tmp, sizeof(tmp), "%q-%i", "Unable to Set AutoCommit Off", result); - errmsg = strdup(tmp); + switch(dbh->type) { + case SCDB_TYPE_CORE_DB: + { + switch_cache_db_execute_sql_real(dbh, "BEGIN", &errmsg); } + break; + case SCDB_TYPE_ODBC: + { + switch_odbc_status_t result; + + if ((result = switch_odbc_SQLSetAutoCommitAttr(dbh->native_handle.odbc_dbh, 0)) != SWITCH_ODBC_SUCCESS) { + char tmp[100]; + switch_snprintfv(tmp, sizeof(tmp), "%q-%i", "Unable to Set AutoCommit Off", result); + errmsg = strdup(tmp); + } + } + break; + case SCDB_TYPE_PGSQL: + { + switch_pgsql_status_t result; + + if ((result = switch_pgsql_SQLSetAutoCommitAttr(dbh->native_handle.pgsql_dbh, 0)) != SWITCH_PGSQL_SUCCESS) { + char tmp[100]; + switch_snprintfv(tmp, sizeof(tmp), "%q-%i", "Unable to Set AutoCommit Off", result); + errmsg = strdup(tmp); + } + } + break; } if (errmsg) { @@ -807,11 +935,25 @@ SWITCH_DECLARE(switch_status_t) switch_cache_db_persistant_execute_trans(switch_ errmsg = NULL; if (again) { - if (runtime.odbc_dbtype == DBTYPE_DEFAULT) { - switch_cache_db_execute_sql_real(dbh, "COMMIT", NULL); - } else { - switch_odbc_SQLEndTran(dbh->native_handle.odbc_dbh, 1); - switch_odbc_SQLSetAutoCommitAttr(dbh->native_handle.odbc_dbh, 1); + switch(dbh->type) { + case SCDB_TYPE_CORE_DB: + { + switch_cache_db_execute_sql_real(dbh, "COMMIT", NULL); + } + break; + case SCDB_TYPE_ODBC: + { + switch_odbc_SQLEndTran(dbh->native_handle.odbc_dbh, 1); + switch_odbc_SQLSetAutoCommitAttr(dbh->native_handle.odbc_dbh, 1); + } + break; + case SCDB_TYPE_PGSQL: + { + switch_pgsql_SQLEndTran(dbh->native_handle.pgsql_dbh, 1); + switch_pgsql_SQLSetAutoCommitAttr(dbh->native_handle.pgsql_dbh, 1); + switch_pgsql_finish_results(dbh->native_handle.pgsql_dbh); + } + break; } goto again; @@ -868,11 +1010,25 @@ SWITCH_DECLARE(switch_status_t) switch_cache_db_persistant_execute_trans(switch_ done: - if (runtime.odbc_dbtype == DBTYPE_DEFAULT) { - switch_cache_db_execute_sql_real(dbh, "COMMIT", NULL); - } else { - switch_odbc_SQLEndTran(dbh->native_handle.odbc_dbh, 1); - switch_odbc_SQLSetAutoCommitAttr(dbh->native_handle.odbc_dbh, 1); + switch(dbh->type) { + case SCDB_TYPE_CORE_DB: + { + switch_cache_db_execute_sql_real(dbh, "COMMIT", NULL); + } + break; + case SCDB_TYPE_ODBC: + { + switch_odbc_SQLEndTran(dbh->native_handle.odbc_dbh, 1); + switch_odbc_SQLSetAutoCommitAttr(dbh->native_handle.odbc_dbh, 1); + } + break; + case SCDB_TYPE_PGSQL: + { + switch_pgsql_SQLEndTran(dbh->native_handle.pgsql_dbh, 1); + switch_pgsql_SQLSetAutoCommitAttr(dbh->native_handle.pgsql_dbh, 1); + switch_pgsql_finish_results(dbh->native_handle.pgsql_dbh); + } + break; } if (!zstr(runtime.core_db_post_trans_execute)) { @@ -903,6 +1059,11 @@ SWITCH_DECLARE(switch_status_t) switch_cache_db_execute_sql_callback(switch_cach switch (dbh->type) { + case SCDB_TYPE_PGSQL: + { + status = switch_pgsql_handle_callback_exec(dbh->native_handle.pgsql_dbh, sql, callback, pdata, err); + } + break; case SCDB_TYPE_ODBC: { status = switch_odbc_handle_callback_exec(dbh->native_handle.odbc_dbh, sql, callback, pdata, err); @@ -951,6 +1112,17 @@ SWITCH_DECLARE(switch_bool_t) switch_cache_db_test_reactive(switch_cache_db_hand if (io_mutex) switch_mutex_lock(io_mutex); switch (dbh->type) { + case SCDB_TYPE_PGSQL: + { + if (switch_pgsql_handle_exec(dbh->native_handle.pgsql_dbh, test_sql, NULL) != SWITCH_PGSQL_SUCCESS) { + r = SWITCH_FALSE; + if (drop_sql) { + switch_pgsql_handle_exec(dbh->native_handle.pgsql_dbh, drop_sql, NULL); + } + switch_pgsql_handle_exec(dbh->native_handle.pgsql_dbh, reactive_sql, NULL); + } + } + break; case SCDB_TYPE_ODBC: { if (switch_odbc_handle_exec(dbh->native_handle.odbc_dbh, test_sql, NULL, NULL) != SWITCH_ODBC_SUCCESS) { @@ -1057,6 +1229,8 @@ static void *SWITCH_THREAD_FUNC switch_core_sql_thread(switch_thread_t *thread, switch_mutex_lock(sql_manager.cond_mutex); switch (sql_manager.event_db->type) { + case SCDB_TYPE_PGSQL: + break; case SCDB_TYPE_ODBC: break; case SCDB_TYPE_CORE_DB: @@ -2313,7 +2487,7 @@ switch_status_t switch_core_sqldb_start(switch_memory_pool_t *pool, switch_bool_ if (switch_core_db_handle(&sql_manager.dbh) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error Opening DB!\n"); - if (switch_test_flag((&runtime), SCF_CORE_ODBC_REQ)) { + if (switch_test_flag((&runtime), SCF_CORE_NON_SQLITE_DB_REQ)) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Failure! ODBC IS REQUIRED!\n"); return SWITCH_STATUS_FALSE; } @@ -2336,6 +2510,7 @@ switch_status_t switch_core_sqldb_start(switch_memory_pool_t *pool, switch_bool_ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Opening DB\n"); switch (sql_manager.dbh->type) { + case SCDB_TYPE_PGSQL: case SCDB_TYPE_ODBC: if (switch_test_flag((&runtime), SCF_CLEAR_SQL)) { char sql[512] = ""; @@ -2376,6 +2551,7 @@ switch_status_t switch_core_sqldb_start(switch_memory_pool_t *pool, switch_bool_ switch (sql_manager.dbh->type) { + case SCDB_TYPE_PGSQL: case SCDB_TYPE_ODBC: { char *err; @@ -2405,7 +2581,7 @@ switch_status_t switch_core_sqldb_start(switch_memory_pool_t *pool, switch_bool_ runtime.odbc_dsn = NULL; runtime.odbc_user = NULL; runtime.odbc_pass = NULL; - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Transactions not supported on your DB, disabling ODBC\n"); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Transactions not supported on your DB, disabling non-SQLite support; using SQLite\n"); switch_cache_db_release_db_handle(&sql_manager.dbh); free(err); goto top; @@ -2536,9 +2712,9 @@ SWITCH_DECLARE(void) switch_core_sqldb_start_thread(void) if (switch_core_recovery_db_handle(&dbh) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error Opening DB!\n"); - if (switch_test_flag((&runtime), SCF_CORE_ODBC_REQ)) { + if (switch_test_flag((&runtime), SCF_CORE_NON_SQLITE_DB_REQ)) { int arg = 1; - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Failure! ODBC IS REQUIRED!\n"); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Failure! ODBC OR PGSQL IS REQUIRED!\n"); switch_core_session_ctl(SCSC_SHUTDOWN_NOW, &arg); } @@ -2562,8 +2738,8 @@ SWITCH_DECLARE(void) switch_core_sqldb_start_thread(void) if (switch_core_db_handle(&sql_manager.dbh) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error Opening DB!\n"); - if (switch_test_flag((&runtime), SCF_CORE_ODBC_REQ)) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Failure! ODBC IS REQUIRED!\n"); + if (switch_test_flag((&runtime), SCF_CORE_NON_SQLITE_DB_REQ)) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Failure! ODBC OR PGSQL IS REQUIRED!\n"); goto end; } diff --git a/src/switch_pgsql.c b/src/switch_pgsql.c new file mode 100644 index 0000000000..ead39a7e9f --- /dev/null +++ b/src/switch_pgsql.c @@ -0,0 +1,770 @@ +/* + * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application + * Copyright (C) 2005-2012, Anthony Minessale II + * + * 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 + * Portions created by the Initial Developer are Copyright (C) + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Anthony Minessale II + * Eliot Gable + * + * switch_pgsql.c -- PGSQL Driver + * + */ + +#include +#include + +#ifdef SWITCH_HAVE_PGSQL +#include + + +struct switch_pgsql_handle { + char *dsn; + const char *sql; + PGconn* con; + int sock; + switch_pgsql_state_t state; + int affected_rows; + int num_retries; + switch_bool_t auto_commit; + switch_bool_t in_txn; +}; + +struct switch_pgsql_result { + PGresult *result; + ExecStatusType status; + char *err; + int rows; + int cols; +}; +#endif + +SWITCH_DECLARE(switch_pgsql_handle_t *) switch_pgsql_handle_new(const char *dsn) +{ +#ifdef SWITCH_HAVE_PGSQL + switch_pgsql_handle_t *new_handle; + + if (!(new_handle = malloc(sizeof(*new_handle)))) { + goto err; + } + + memset(new_handle, 0, sizeof(*new_handle)); + + if (!(new_handle->dsn = strdup(dsn))) { + goto err; + } + + new_handle->sock = 0; + new_handle->state = SWITCH_PGSQL_STATE_INIT; + new_handle->con = NULL; + new_handle->affected_rows = 0; + new_handle->num_retries = DEFAULT_PGSQL_RETRIES; + new_handle->auto_commit = SWITCH_TRUE; + new_handle->in_txn = SWITCH_FALSE; + + return new_handle; + + err: + if (new_handle) { + switch_safe_free(new_handle->dsn); + switch_safe_free(new_handle); + } +#endif + return NULL; +} + +SWITCH_DECLARE(void) switch_pgsql_set_num_retries(switch_pgsql_handle_t *handle, int num_retries) +{ +#ifdef SWITCH_HAVE_PGSQL + if (handle) { + handle->num_retries = num_retries; + } +#endif +} + +SWITCH_DECLARE(switch_pgsql_status_t) switch_pgsql_handle_disconnect(switch_pgsql_handle_t *handle) +{ +#ifdef SWITCH_HAVE_PGSQL + + if (!handle) { + return SWITCH_PGSQL_FAIL; + } + + if (handle->state == SWITCH_PGSQL_STATE_CONNECTED) { + PQfinish(handle->con); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG10, "Disconnected from [%s]\n", handle->dsn); + } + + handle->state = SWITCH_PGSQL_STATE_DOWN; + + return SWITCH_PGSQL_SUCCESS; +#else + return SWITCH_PGSQL_FAIL; +#endif +} + + +#ifdef SWITCH_HAVE_PGSQL + +SWITCH_DECLARE(switch_pgsql_status_t) switch_pgsql_send_query(switch_pgsql_handle_t *handle, const char* sql) +{ + char *err_str; + + if (!PQsendQuery(handle->con, sql)) { + err_str = switch_pgsql_handle_get_error(handle); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Failed to send query (%s) to database: %s\n", sql, err_str); + switch_pgsql_finish_results(handle); + goto error; + } + handle->sql = sql; + + return SWITCH_PGSQL_SUCCESS; + error: + return SWITCH_PGSQL_FAIL; +} + +SWITCH_DECLARE(switch_pgsql_status_t) switch_pgsql_cancel_real(const char *file, const char *func, int line, switch_pgsql_handle_t *handle) +{ + char err_buf[256]; + PGcancel *cancel = NULL; + switch_pgsql_status_t ret = SWITCH_PGSQL_SUCCESS; + + memset(err_buf, 0, 256); + cancel = PQgetCancel(handle->con); + if(!PQcancel(cancel, err_buf, 256)) { + switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, func, line, NULL, SWITCH_LOG_CRIT, "Failed to cancel long-running query (%s): %s\n", handle->sql, err_buf); + ret = SWITCH_PGSQL_FAIL; + } + PQfreeCancel(cancel); + return ret; +} + + +SWITCH_DECLARE(switch_pgsql_status_t) switch_pgsql_next_result_timed(switch_pgsql_handle_t *handle, switch_pgsql_result_t **result_out, int msec) +{ + switch_pgsql_result_t *res; + switch_time_t start; + switch_time_t ctime; + unsigned int usec = msec * 1000; + char *err_str; + fd_set pgset; + struct timeval timeout; + + if(!handle) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "**BUG** Null handle passed to switch_pgsql_next_result.\n"); + return SWITCH_PGSQL_FAIL; + } + + /* Try to consume input that might be waiting right away */ + if (PQconsumeInput(handle->con)) { + /* And check to see if we have a full result ready for reading */ + if (PQisBusy(handle->con)) { + + /* Wait for a result to become available, up to msec milliseconds */ + start = switch_time_now(); + while((ctime = switch_time_now()) - start <= usec) { + FD_ZERO(&pgset); + FD_SET(handle->sock, &pgset); + + timeout.tv_sec = 0; + timeout.tv_usec = 500; + + /* Wait for the PostgreSQL socket to be ready for data reads. */ + if (select(FD_SETSIZE, &pgset, NULL, NULL, &timeout) > 0) { + /* Then try to consume any input waiting. */ + if (PQconsumeInput(handle->con)) { + /* And check to see if we have a full result ready for reading */ + if (!PQisBusy(handle->con)) { + /* If we can pull a full result without blocking, then break this loop */ + break; + } + } else { + /* If we had an error trying to consume input, report it and cancel the query. */ + err_str = switch_pgsql_handle_get_error(handle); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "An error occurred trying to consume input for query (%s): %s\n", handle->sql, err_str); + switch_safe_free(err_str); + switch_pgsql_cancel(handle); + goto error; + } + } + } + + /* If we broke the loop above because of a timeout, report that and cancel the query. */ + if (ctime - start > usec) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Query (%s) took too long to complete or database not responding.\n", handle->sql); + switch_pgsql_cancel(handle); + goto error; + } + + + + } + } else { + /* If we had an error trying to consume input, report it and cancel the query. */ + err_str = switch_pgsql_handle_get_error(handle); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "An error occurred trying to consume input for query (%s): %s\n", handle->sql, err_str); + switch_safe_free(err_str); + switch_pgsql_cancel(handle); + goto error; + } + + + /* At this point, we know we can read a full result without blocking. */ + if(!(res = malloc(sizeof(switch_pgsql_result_t)))) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Malloc failed!\n"); + goto error; + } + memset(res, 0, sizeof(switch_pgsql_result_t)); + + + res->result = PQgetResult(handle->con); + if (res->result) { + *result_out = res; + res->status = PQresultStatus(res->result); + switch(res->status) { + case PGRES_TUPLES_OK: + { + res->rows = PQntuples(res->result); + handle->affected_rows = res->rows; + res->cols = PQnfields(res->result); + } + break; + case PGRES_COPY_OUT: + case PGRES_COPY_IN: + case PGRES_COMMAND_OK: + break; + case PGRES_EMPTY_QUERY: + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Query (%s) returned PGRES_EMPTY_QUERY\n", handle->sql); + case PGRES_BAD_RESPONSE: + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Query (%s) returned PGRES_BAD_RESPONSE\n", handle->sql); + case PGRES_NONFATAL_ERROR: + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Query (%s) returned PGRES_NONFATAL_ERROR\n", handle->sql); + case PGRES_FATAL_ERROR: + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Query (%s) returned PGRES_FATAL_ERROR\n", handle->sql); + res->err = PQresultErrorMessage(res->result); + goto error; + break; + } + } else { + free(res); + res = NULL; + *result_out = NULL; + goto error; + } + + return SWITCH_PGSQL_SUCCESS; + error: + return SWITCH_PGSQL_FAIL; +} + +SWITCH_DECLARE(void) switch_pgsql_free_result(switch_pgsql_result_t **result) +{ + if (!*result) { + return; + } + + if ((*result)->result) { + PQclear((*result)->result); + } + free(*result); + *result = NULL; +} + +SWITCH_DECLARE(switch_pgsql_status_t) switch_pgsql_finish_results_real(const char* file, const char* func, int line, switch_pgsql_handle_t *handle) +{ + switch_pgsql_result_t *res = NULL; + switch_pgsql_status_t final_status = SWITCH_PGSQL_SUCCESS; + int done = 0; + do { + switch_pgsql_next_result(handle, &res); + if (res && res->err) { + switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, func, line, NULL, SWITCH_LOG_ERROR, "Error executing query:\n%s\n", res->err); + final_status = SWITCH_PGSQL_FAIL; + } + if (!res) done = 1; + switch_pgsql_free_result(&res); + } while (!done); + return final_status; +} + +static int db_is_up(switch_pgsql_handle_t *handle) +{ + int ret = 0; + switch_event_t *event; + char *err_str = NULL; + int max_tries = DEFAULT_PGSQL_RETRIES; + int code = 0, recon = 0; + + if (handle) { + max_tries = handle->num_retries; + if (max_tries < 1) + max_tries = DEFAULT_PGSQL_RETRIES; + } + + top: + + if (!handle) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "No DB Handle\n"); + goto done; + } + if (!handle->con) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "No DB Connection\n"); + goto done; + } + + if (PQstatus(handle->con) == CONNECTION_BAD) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "PQstatus returned bad connection; reconnecting...\n"); + handle->state = SWITCH_PGSQL_STATE_ERROR; + PQreset(handle->con); + if (PQstatus(handle->con) == CONNECTION_BAD) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "PQstatus returned bad connection -- reconnection failed!\n"); + goto error; + } + handle->state = SWITCH_PGSQL_STATE_CONNECTED; + } + +/* if (!PQsendQuery(handle->con, "SELECT 1")) { + code = __LINE__; + goto error; + } + + if(switch_pgsql_next_result(handle, &result) == SWITCH_PGSQL_FAIL) { + code = __LINE__; + goto error; + } + + if (!result || result->status != PGRES_COMMAND_OK) { + code = __LINE__; + goto error; + } + + switch_pgsql_free_result(&result); + switch_pgsql_finish_results(handle); +*/ + ret = 1; + goto done; + + error: + err_str = switch_pgsql_handle_get_error(handle); + + if (PQstatus(handle->con) == CONNECTION_BAD) { + handle->state = SWITCH_PGSQL_STATE_ERROR; + PQreset(handle->con); + if (PQstatus(handle->con) == CONNECTION_OK) { + handle->state = SWITCH_PGSQL_STATE_CONNECTED; + recon = SWITCH_PGSQL_SUCCESS; + } + } + + max_tries--; + + if (switch_event_create(&event, SWITCH_EVENT_TRAP) == SWITCH_STATUS_SUCCESS) { + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Failure-Message", "The sql server is not responding for DSN %s [%s][%d]", + switch_str_nil(handle->dsn), switch_str_nil(err_str), code); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "The sql server is not responding for DSN %s [%s][%d]\n", + switch_str_nil(handle->dsn), switch_str_nil(err_str), code); + + if (recon == SWITCH_PGSQL_SUCCESS) { + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Additional-Info", "The connection has been re-established"); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "The connection has been re-established\n"); + } else { + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Additional-Info", "The connection could not be re-established"); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "The connection could not be re-established\n"); + } + if (!max_tries) { + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Additional-Info", "Giving up!"); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Giving up!\n"); + } + + switch_event_fire(&event); + } + + if (!max_tries) { + goto done; + } + + switch_safe_free(err_str); + switch_yield(1000000); + goto top; + + done: + + switch_safe_free(err_str); + + return ret; +} +#endif + + +SWITCH_DECLARE(switch_pgsql_status_t) switch_pgsql_handle_connect(switch_pgsql_handle_t *handle) +{ +#ifdef SWITCH_HAVE_PGSQL + if (handle->state == SWITCH_PGSQL_STATE_CONNECTED) { + switch_pgsql_handle_disconnect(handle); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "Re-connecting %s\n", handle->dsn); + } + + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "Connecting %s\n", handle->dsn); + + handle->con = PQconnectdb(handle->dsn); + if (PQstatus(handle->con) != CONNECTION_OK) { + char *err_str; + if ((err_str = switch_pgsql_handle_get_error(handle))) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "%s\n", err_str); + switch_safe_free(err_str); + } else { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to connect to the database [%s]\n", handle->dsn); + switch_pgsql_handle_disconnect(handle); + } + return SWITCH_PGSQL_FAIL; + } + + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "Connected to [%s]\n", handle->dsn); + handle->state = SWITCH_PGSQL_STATE_CONNECTED; + handle->sock = PQsocket(handle->con); + return SWITCH_PGSQL_SUCCESS; +#else + return SWITCH_PGSQL_FAIL; +#endif +} + +SWITCH_DECLARE(switch_pgsql_status_t) switch_pgsql_handle_exec_string(switch_pgsql_handle_t *handle, const char *sql, char *resbuf, size_t len, char **err) +{ +#ifdef SWITCH_HAVE_PGSQL + switch_pgsql_status_t sstatus = SWITCH_PGSQL_SUCCESS; + char *val = NULL; + switch_pgsql_result_t *result = NULL; + + handle->affected_rows = 0; + + if (switch_pgsql_handle_exec_base(handle, sql, err) == SWITCH_PGSQL_FAIL) { + goto error; + } + + if(switch_pgsql_next_result(handle, &result) == SWITCH_PGSQL_FAIL) { + goto error; + } + + if (!result || result->status != PGRES_COMMAND_OK) { + sstatus = SWITCH_PGSQL_FAIL; + goto done; + } + + if (handle->affected_rows <= 0) { + goto done; + } + + val = PQgetvalue(result->result, 0, 0); + strncpy(resbuf, val, len); + + done: + + switch_pgsql_free_result(&result); + if (switch_pgsql_finish_results(handle) != SWITCH_PGSQL_SUCCESS) { + sstatus = SWITCH_PGSQL_FAIL; + } + + return sstatus; + error: + return SWITCH_PGSQL_FAIL; +#else + return SWITCH_PGSQL_FAIL; +#endif +} + +SWITCH_DECLARE(switch_pgsql_status_t) switch_pgsql_handle_exec_base(switch_pgsql_handle_t *handle, const char *sql, char **err) +{ +#ifdef SWITCH_HAVE_PGSQL + char *err_str = NULL; + + handle->affected_rows = 0; + + if (!db_is_up(handle)) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Database is not up!\n"); + goto error; + } + + if (handle->auto_commit == SWITCH_FALSE && handle->in_txn == SWITCH_FALSE) { + if (switch_pgsql_send_query(handle, "BEGIN") != SWITCH_PGSQL_SUCCESS) { + switch_pgsql_finish_results(handle); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error sending BEGIN!\n"); + goto error; + } + + if (switch_pgsql_finish_results(handle) != SWITCH_PGSQL_SUCCESS) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error sending BEGIN!\n"); + goto error; + } + handle->in_txn = SWITCH_TRUE; + } + + if (switch_pgsql_send_query(handle, sql) != SWITCH_PGSQL_SUCCESS) { + switch_pgsql_finish_results(handle); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error sending query!\n"); + goto error; + } + + return SWITCH_PGSQL_SUCCESS; + + error: + err_str = switch_pgsql_handle_get_error(handle); + + if (zstr(err_str)) { + err_str = strdup((char *)"SQL ERROR!"); + } + + if (err_str) { + if (!switch_stristr("already exists", err_str) && !switch_stristr("duplicate key name", err_str)) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "ERR: [%s]\n[%s]\n", sql, switch_str_nil(err_str)); + } + if (err) { + *err = err_str; + } else { + free(err_str); + } + } +#endif + return SWITCH_PGSQL_FAIL; +} + +SWITCH_DECLARE(switch_pgsql_status_t) switch_pgsql_handle_exec(switch_pgsql_handle_t *handle, const char *sql, char **err) +{ +#ifdef SWITCH_HAVE_PGSQL + if (switch_pgsql_handle_exec_base(handle, sql, err) == SWITCH_PGSQL_FAIL) { + goto error; + } + + return switch_pgsql_finish_results(handle); + error: +#endif + return SWITCH_PGSQL_FAIL; +} + +SWITCH_DECLARE(switch_pgsql_status_t) switch_pgsql_handle_callback_exec_detailed(const char *file, const char *func, int line, + switch_pgsql_handle_t *handle, + const char *sql, switch_core_db_callback_func_t callback, void *pdata, + char **err) +{ +#ifdef SWITCH_HAVE_PGSQL + char *err_str = NULL; + int row = 0, col = 0, err_cnt = 0; + switch_pgsql_result_t *result = NULL; + + handle->affected_rows = 0; + + switch_assert(callback != NULL); + + if (switch_pgsql_handle_exec_base(handle, sql, err) == SWITCH_PGSQL_FAIL) { + goto error; + } + + if (switch_pgsql_next_result(handle, &result) == SWITCH_PGSQL_FAIL) { + err_cnt++; + err_str = switch_pgsql_handle_get_error(handle); + if (result && !zstr(result->err)) { + switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, func, line, NULL, SWITCH_LOG_ERROR, "ERR: [%s]\n[%s]\n", sql, switch_str_nil(result->err)); + } + if (!zstr(err_str)) { + switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, func, line, NULL, SWITCH_LOG_ERROR, "ERR: [%s]\n[%s]\n", sql, switch_str_nil(err_str)); + } + switch_safe_free(err_str); + err_str = NULL; + } + + while (result != NULL) { + for (row = 0; row < result->rows; ++row) { + char **names; + char **vals; + + names = calloc(result->cols, sizeof(*names)); + vals = calloc(result->cols, sizeof(*vals)); + + switch_assert(names && vals); + + for (col = 0; col < result->cols; ++col) { + char * tmp; + int len; + + tmp = PQfname(result->result, col); + if (tmp) { + len = strlen(tmp); + names[col] = malloc(len+1); + strncpy(names[col], tmp, len); + + len = PQgetlength(result->result, row, col); + vals[col] = malloc(len+1); + tmp = PQgetvalue(result->result, row, col); + strncpy(vals[col], tmp, len); + } else { + switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, func, line, NULL, SWITCH_LOG_ERROR, "ERR: Column number %d out of range\n", col); + } + } + + if (callback(pdata, row, vals, names)) { + break; + } + + for (col = 0; col < result->cols; ++col) { + free(names[col]); + free(vals[col]); + } + free(names); + free(vals); + } + if (switch_pgsql_next_result(handle, &result) == SWITCH_PGSQL_FAIL) { + err_cnt++; + err_str = switch_pgsql_handle_get_error(handle); + if (result && !zstr(result->err)) { + switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, func, line, NULL, SWITCH_LOG_ERROR, "ERR: [%s]\n[%s]\n", sql, switch_str_nil(result->err)); + } + if (!zstr(err_str)) { + switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, func, line, NULL, SWITCH_LOG_ERROR, "ERR: [%s]\n[%s]\n", sql, switch_str_nil(err_str)); + } + switch_safe_free(err_str); + err_str = NULL; + } + } + if (err_cnt) { + goto error; + } + + return SWITCH_PGSQL_SUCCESS; + error: +#endif + return SWITCH_PGSQL_FAIL; +} + +SWITCH_DECLARE(void) switch_pgsql_handle_destroy(switch_pgsql_handle_t **handlep) +{ +#ifdef SWITCH_HAVE_PGSQL + + switch_pgsql_handle_t *handle = NULL; + + if (!handlep) { + return; + } + handle = *handlep; + + if (handle) { + switch_pgsql_handle_disconnect(handle); + + switch_safe_free(handle->dsn); + free(handle); + } + *handlep = NULL; +#else + return; +#endif +} + +SWITCH_DECLARE(switch_pgsql_state_t) switch_pgsql_handle_get_state(switch_pgsql_handle_t *handle) +{ +#ifdef SWITCH_HAVE_PGSQL + return handle ? handle->state : SWITCH_PGSQL_STATE_INIT; +#else + return SWITCH_PGSQL_STATE_ERROR; +#endif +} + +SWITCH_DECLARE(char *) switch_pgsql_handle_get_error(switch_pgsql_handle_t *handle) +{ +#ifdef SWITCH_HAVE_PGSQL + char * err_str; + if (!handle) { + return NULL; + }; + switch_strdup(err_str, PQerrorMessage(handle->con)); + return err_str; +#else + return NULL; +#endif +} + +SWITCH_DECLARE(int) switch_pgsql_handle_affected_rows(switch_pgsql_handle_t *handle) +{ +#ifdef SWITCH_HAVE_PGSQL + return handle->affected_rows; +#else + return 0; +#endif +} + +SWITCH_DECLARE(switch_bool_t) switch_pgsql_available(void) +{ +#ifdef SWITCH_HAVE_PGSQL + return SWITCH_TRUE; +#else + return SWITCH_FALSE; +#endif +} + +SWITCH_DECLARE(switch_pgsql_status_t) switch_pgsql_SQLSetAutoCommitAttr(switch_pgsql_handle_t *handle, switch_bool_t on) +{ +#ifdef SWITCH_HAVE_PGSQL + if (on) { + handle->auto_commit = SWITCH_TRUE; + } else { + handle->auto_commit = SWITCH_FALSE; + } + return SWITCH_PGSQL_SUCCESS; +#else + return (switch_pgsql_status_t) SWITCH_FALSE; +#endif +} + +SWITCH_DECLARE(switch_pgsql_status_t) switch_pgsql_SQLEndTran(switch_pgsql_handle_t *handle, switch_bool_t commit) +{ +#ifdef SWITCH_HAVE_PGSQL + char * err_str = NULL; + if (commit) { + if(!PQsendQuery(handle->con, "COMMIT")) { + err_str = switch_pgsql_handle_get_error(handle); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Could not commit transaction: %s\n", err_str); + switch_safe_free(err_str); + return SWITCH_PGSQL_FAIL; + } + } else { + if(!PQsendQuery(handle->con, "ROLLBACK")) { + err_str = switch_pgsql_handle_get_error(handle); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Could not rollback transaction: %s\n", err_str); + switch_safe_free(err_str); + return SWITCH_PGSQL_FAIL; + } + } + handle->in_txn = SWITCH_FALSE; + return SWITCH_PGSQL_SUCCESS; +#else + return (switch_pgsql_status_t) SWITCH_FALSE; +#endif +} + + +/* 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: + */ From e08f9ada73cb7a39477c4fe255fe28af7c6bfa92 Mon Sep 17 00:00:00 2001 From: Eliot Gable Date: Thu, 4 Oct 2012 20:19:38 +0000 Subject: [PATCH 128/252] Abstract the sql_manager and cache_db stuff so that modules can utilize the core functionality to run their own instance of a cached SQL connection. Includes patch to fix some segs in case ODBC does not have password set or if using PGSQL support. --- src/include/switch_core.h | 31 ++- src/include/switch_types.h | 5 + src/switch_core.c | 2 +- src/switch_core_sqldb.c | 543 ++++++++++++++++++++++--------------- 4 files changed, 351 insertions(+), 230 deletions(-) diff --git a/src/include/switch_core.h b/src/include/switch_core.h index 73607926fa..d6da431dfc 100644 --- a/src/include/switch_core.h +++ b/src/include/switch_core.h @@ -2193,7 +2193,11 @@ SWITCH_DECLARE(switch_status_t) switch_core_chat_send(const char *dest_proto, sw SWITCH_DECLARE(switch_status_t) switch_core_chat_deliver(const char *dest_proto, switch_event_t **message_event); SWITCH_DECLARE(switch_status_t) switch_ivr_preprocess_session(switch_core_session_t *session, const char *cmds); -SWITCH_DECLARE(void) switch_core_sqldb_stop_thread(void); +SWITCH_DECLARE(void) switch_sqldb_stop_thread(switch_sql_manager_t *sql_manager); +#define switch_core_sqldb_stop_thread() switch_sqldb_stop_thread(&switch_cache_db_sql_manager) + +SWITCH_DECLARE(void) switch_sqldb_start_thread(switch_sql_manager_t *sql_manager, void *(SWITCH_THREAD_FUNC * func) (switch_thread_t *, void *), + char **post_connect_sql, int argc); SWITCH_DECLARE(void) switch_core_sqldb_start_thread(void); ///\} @@ -2240,8 +2244,6 @@ typedef union { switch_cache_db_pgsql_options_t pgsql_options; } switch_cache_db_connection_options_t; -struct switch_cache_db_handle; -typedef struct switch_cache_db_handle switch_cache_db_handle_t; static inline const char *switch_cache_db_type_name(switch_cache_db_handle_type_t type) { @@ -2281,7 +2283,9 @@ SWITCH_DECLARE(void) switch_cache_db_dismiss_db_handle(switch_cache_db_handle_t other threads until the allocating thread actually terminates. \param [in] The handle */ +SWITCH_DECLARE(void) _switch_cache_db_release_db_handle(switch_sql_manager_t *sql_manager, switch_cache_db_handle_t ** dbh); SWITCH_DECLARE(void) switch_cache_db_release_db_handle(switch_cache_db_handle_t ** dbh); + /*! \brief Gets a new cached handle from the pool, potentially creating a new connection. The connection is bound to the thread until it (the thread) terminates unless @@ -2290,12 +2294,19 @@ SWITCH_DECLARE(void) switch_cache_db_release_db_handle(switch_cache_db_handle_t \param [in] type - ODBC or SQLLITE \param [in] connection_options (userid, password, etc) */ +SWITCH_DECLARE(switch_status_t) __switch_cache_db_get_db_handle(switch_sql_manager_t *sql_manager, + switch_cache_db_handle_t ** dbh, + switch_cache_db_handle_type_t type, + switch_cache_db_connection_options_t *connection_options, + const char *file, const char *func, int line); SWITCH_DECLARE(switch_status_t) _switch_cache_db_get_db_handle(switch_cache_db_handle_t ** dbh, switch_cache_db_handle_type_t type, switch_cache_db_connection_options_t *connection_options, const char *file, const char *func, int line); #define switch_cache_db_get_db_handle(_a, _b, _c) _switch_cache_db_get_db_handle(_a, _b, _c, __FILE__, __SWITCH_FUNC__, __LINE__) + + /*! \brief Executes the sql and returns the result as a string \param [in] dbh The handle @@ -2330,15 +2341,21 @@ SWITCH_DECLARE(switch_status_t) switch_cache_db_execute_sql_callback(switch_cach */ SWITCH_DECLARE(int) switch_cache_db_affected_rows(switch_cache_db_handle_t *dbh); +extern switch_sql_manager_t switch_cache_db_sql_manager; /*! \brief Provides some feedback as to the status of the db connection pool \param [in] stream stream for status */ +SWITCH_DECLARE(void) _switch_cache_db_status(switch_sql_manager_t *sql_manager, switch_stream_handle_t *stream); SWITCH_DECLARE(void) switch_cache_db_status(switch_stream_handle_t *stream); +SWITCH_DECLARE(switch_status_t) __switch_core_db_handle(switch_sql_manager_t *sql_manager, switch_cache_db_handle_t ** dbh, const char *file, const char *func, int line); SWITCH_DECLARE(switch_status_t) _switch_core_db_handle(switch_cache_db_handle_t ** dbh, const char *file, const char *func, int line); #define switch_core_db_handle(_a) _switch_core_db_handle(_a, __FILE__, __SWITCH_FUNC__, __LINE__) -SWITCH_DECLARE(switch_status_t) _switch_core_recovery_db_handle(switch_cache_db_handle_t ** dbh, const char *file, const char *func, int line); -#define switch_core_recovery_db_handle(_a) _switch_core_recovery_db_handle(_a, __FILE__, __SWITCH_FUNC__, __LINE__) +SWITCH_DECLARE(switch_status_t) _switch_core_recovery_db_handle(switch_sql_manager_t *sql_manager, switch_cache_db_handle_t ** dbh, const char *file, const char *func, int line); +#define switch_core_recovery_db_handle(_a) _switch_core_recovery_db_handle(&switch_cache_db_sql_manager, _a, __FILE__, __SWITCH_FUNC__, __LINE__) + +SWITCH_DECLARE(switch_status_t) _switch_core_persist_db_handle(switch_sql_manager_t *sql_manager, switch_cache_db_handle_t ** dbh, const char *file, const char *func, int line); +#define switch_core_persist_db_handle(_a) _switch_core_persist_db_handle(&switch_cache_db_sql_manager, _a, __FILE__, __SWITCH_FUNC__, __LINE__) SWITCH_DECLARE(switch_bool_t) switch_cache_db_test_reactive(switch_cache_db_handle_t *db, const char *test_sql, const char *drop_sql, const char *reactive_sql); @@ -2347,7 +2364,9 @@ SWITCH_DECLARE(switch_status_t) switch_cache_db_persistant_execute_trans(switch_ SWITCH_DECLARE(void) switch_core_set_signal_handlers(void); SWITCH_DECLARE(uint32_t) switch_core_debug_level(void); -SWITCH_DECLARE(void) switch_cache_db_flush_handles(void); +SWITCH_DECLARE(void) switch_cache_db_flush_handles(switch_sql_manager_t *sql_manager); +#define switch_core_cache_db_flush_handles() switch_cache_db_flush_handles(&switch_cache_db_sql_manager) + SWITCH_DECLARE(const char *) switch_core_banner(void); SWITCH_DECLARE(switch_bool_t) switch_core_session_in_thread(switch_core_session_t *session); SWITCH_DECLARE(uint32_t) switch_default_ptime(const char *name, uint32_t number); diff --git a/src/include/switch_types.h b/src/include/switch_types.h index 6f77f32ef4..ddd66a0a4e 100644 --- a/src/include/switch_types.h +++ b/src/include/switch_types.h @@ -1836,6 +1836,11 @@ typedef struct switch_odbc_handle switch_odbc_handle_t; typedef struct switch_pgsql_handle switch_pgsql_handle_t; typedef struct switch_pgsql_result switch_pgsql_result_t; +struct switch_cache_db_handle; +typedef struct switch_cache_db_handle switch_cache_db_handle_t; +struct switch_sql_manager; +typedef struct switch_sql_manager switch_sql_manager_t; + typedef struct switch_io_routines switch_io_routines_t; typedef struct switch_speech_handle switch_speech_handle_t; typedef struct switch_asr_handle switch_asr_handle_t; diff --git a/src/switch_core.c b/src/switch_core.c index 8e1a6567d7..9c525a6c1e 100644 --- a/src/switch_core.c +++ b/src/switch_core.c @@ -2260,7 +2260,7 @@ SWITCH_DECLARE(int32_t) switch_core_session_ctl(switch_session_ctl_t cmd, void * switch_time_calibrate_clock(); break; case SCSC_FLUSH_DB_HANDLES: - switch_cache_db_flush_handles(); + switch_core_cache_db_flush_handles(); break; case SCSC_SEND_SIGHUP: handle_SIGHUP(1); diff --git a/src/switch_core_sqldb.c b/src/switch_core_sqldb.c index cbc7a611e3..23b08ace75 100644 --- a/src/switch_core_sqldb.c +++ b/src/switch_core_sqldb.c @@ -26,6 +26,7 @@ * Anthony Minessale II * Michael Jerris * Paul D. Tinsley + * Eliot Gable * * * switch_core_sqldb.c -- Main Core Library (statistics tracker) @@ -55,7 +56,7 @@ struct switch_cache_db_handle { struct switch_cache_db_handle *next; }; -static struct { +struct switch_sql_manager { switch_cache_db_handle_t *event_db; switch_queue_t *sql_queue[2]; switch_memory_pool_t *memory_pool; @@ -73,7 +74,9 @@ static struct { uint32_t total_handles; uint32_t total_used_handles; switch_cache_db_handle_t *dbh; -} sql_manager; +}; + +switch_sql_manager_t switch_cache_db_sql_manager; static switch_cache_db_handle_t *create_handle(switch_cache_db_handle_type_t type) @@ -90,11 +93,11 @@ static switch_cache_db_handle_t *create_handle(switch_cache_db_handle_type_t typ return new_dbh; } -static void add_handle(switch_cache_db_handle_t *dbh, const char *db_str, const char *db_callsite_str, const char *thread_str) +static void add_handle(switch_sql_manager_t *sql_manager, switch_cache_db_handle_t *dbh, const char *db_str, const char *db_callsite_str, const char *thread_str) { switch_ssize_t hlen = -1; - switch_mutex_lock(sql_manager.dbh_mutex); + switch_mutex_lock(sql_manager->dbh_mutex); switch_set_string(dbh->creator, db_callsite_str); @@ -103,37 +106,37 @@ static void add_handle(switch_cache_db_handle_t *dbh, const char *db_str, const dbh->thread_hash = switch_ci_hashfunc_default(thread_str, &hlen); dbh->use_count++; - sql_manager.total_used_handles++; - dbh->next = sql_manager.handle_pool; + sql_manager->total_used_handles++; + dbh->next = sql_manager->handle_pool; - sql_manager.handle_pool = dbh; - sql_manager.total_handles++; + sql_manager->handle_pool = dbh; + sql_manager->total_handles++; switch_mutex_lock(dbh->mutex); - switch_mutex_unlock(sql_manager.dbh_mutex); + switch_mutex_unlock(sql_manager->dbh_mutex); } -static void del_handle(switch_cache_db_handle_t *dbh) +static void del_handle(switch_sql_manager_t *sql_manager, switch_cache_db_handle_t *dbh) { switch_cache_db_handle_t *dbh_ptr, *last = NULL; - switch_mutex_lock(sql_manager.dbh_mutex); - for (dbh_ptr = sql_manager.handle_pool; dbh_ptr; dbh_ptr = dbh_ptr->next) { + switch_mutex_lock(sql_manager->dbh_mutex); + for (dbh_ptr = sql_manager->handle_pool; dbh_ptr; dbh_ptr = dbh_ptr->next) { if (dbh_ptr == dbh) { if (last) { last->next = dbh_ptr->next; } else { - sql_manager.handle_pool = dbh_ptr->next; + sql_manager->handle_pool = dbh_ptr->next; } - sql_manager.total_handles--; + sql_manager->total_handles--; break; } last = dbh_ptr; } - switch_mutex_unlock(sql_manager.dbh_mutex); + switch_mutex_unlock(sql_manager->dbh_mutex); } -static switch_cache_db_handle_t *get_handle(const char *db_str, const char *user_str, const char *thread_str) +static switch_cache_db_handle_t *get_handle(switch_sql_manager_t *sql_manager, const char *db_str, const char *user_str, const char *thread_str) { switch_ssize_t hlen = -1; unsigned long hash = 0, thread_hash = 0; @@ -142,9 +145,9 @@ static switch_cache_db_handle_t *get_handle(const char *db_str, const char *user hash = switch_ci_hashfunc_default(db_str, &hlen); thread_hash = switch_ci_hashfunc_default(thread_str, &hlen); - switch_mutex_lock(sql_manager.dbh_mutex); + switch_mutex_lock(sql_manager->dbh_mutex); - for (dbh_ptr = sql_manager.handle_pool; dbh_ptr; dbh_ptr = dbh_ptr->next) { + for (dbh_ptr = sql_manager->handle_pool; dbh_ptr; dbh_ptr = dbh_ptr->next) { if (dbh_ptr->thread_hash == thread_hash && dbh_ptr->hash == hash && !switch_test_flag(dbh_ptr, CDF_PRUNE) && switch_mutex_trylock(dbh_ptr->mutex) == SWITCH_STATUS_SUCCESS) { r = dbh_ptr; @@ -152,7 +155,7 @@ static switch_cache_db_handle_t *get_handle(const char *db_str, const char *user } if (!r) { - for (dbh_ptr = sql_manager.handle_pool; dbh_ptr; dbh_ptr = dbh_ptr->next) { + for (dbh_ptr = sql_manager->handle_pool; dbh_ptr; dbh_ptr = dbh_ptr->next) { if (dbh_ptr->hash == hash && !dbh_ptr->use_count && !switch_test_flag(dbh_ptr, CDF_PRUNE) && switch_mutex_trylock(dbh_ptr->mutex) == SWITCH_STATUS_SUCCESS) { r = dbh_ptr; @@ -163,13 +166,13 @@ static switch_cache_db_handle_t *get_handle(const char *db_str, const char *user if (r) { r->use_count++; - sql_manager.total_used_handles++; + sql_manager->total_used_handles++; r->hash = switch_ci_hashfunc_default(db_str, &hlen); r->thread_hash = thread_hash; switch_set_string(r->last_user, user_str); } - switch_mutex_unlock(sql_manager.dbh_mutex); + switch_mutex_unlock(sql_manager->dbh_mutex); return r; @@ -181,11 +184,16 @@ static switch_cache_db_handle_t *get_handle(const char *db_str, const char *user \brief Open the default system database */ SWITCH_DECLARE(switch_status_t) _switch_core_db_handle(switch_cache_db_handle_t **dbh, const char *file, const char *func, int line) +{ + return __switch_core_db_handle(&switch_cache_db_sql_manager, dbh, file, func, line); +} + +SWITCH_DECLARE(switch_status_t) __switch_core_db_handle(switch_sql_manager_t *sql_manager, switch_cache_db_handle_t **dbh, const char *file, const char *func, int line) { switch_cache_db_connection_options_t options = { {0} }; switch_status_t r; - if (!sql_manager.manage) { + if (!sql_manager->manage) { return SWITCH_STATUS_FALSE; } @@ -199,26 +207,26 @@ SWITCH_DECLARE(switch_status_t) _switch_core_db_handle(switch_cache_db_handle_t } else { options.core_db_options.db_path = SWITCH_CORE_DB; } - r = _switch_cache_db_get_db_handle(dbh, SCDB_TYPE_CORE_DB, &options, file, func, line); + r = __switch_cache_db_get_db_handle(sql_manager, dbh, SCDB_TYPE_CORE_DB, &options, file, func, line); } else { char *dsn; if ((dsn = strstr(runtime.odbc_dsn, "pgsql;")) != NULL) { options.pgsql_options.dsn = (char*)(dsn + 6); - r = _switch_cache_db_get_db_handle(dbh, SCDB_TYPE_PGSQL, &options, file, func, line); + r = __switch_cache_db_get_db_handle(sql_manager, dbh, SCDB_TYPE_PGSQL, &options, file, func, line); } else { options.odbc_options.dsn = runtime.odbc_dsn; options.odbc_options.user = runtime.odbc_user; options.odbc_options.pass = runtime.odbc_pass; - r = _switch_cache_db_get_db_handle(dbh, SCDB_TYPE_ODBC, &options, file, func, line); + r = __switch_cache_db_get_db_handle(sql_manager, dbh, SCDB_TYPE_ODBC, &options, file, func, line); } } /* I *think* we can do without this now, if not let me know if (r == SWITCH_STATUS_SUCCESS && !(*dbh)->io_mutex) { - (*dbh)->io_mutex = sql_manager.io_mutex; + (*dbh)->io_mutex = sql_manager->io_mutex; } */ @@ -229,12 +237,12 @@ SWITCH_DECLARE(switch_status_t) _switch_core_db_handle(switch_cache_db_handle_t /*! \brief Open the default system database */ -SWITCH_DECLARE(switch_status_t) _switch_core_persist_db_handle(switch_cache_db_handle_t **dbh, const char *file, const char *func, int line) +SWITCH_DECLARE(switch_status_t) _switch_core_persist_db_handle(switch_sql_manager_t *sql_manager, switch_cache_db_handle_t **dbh, const char *file, const char *func, int line) { switch_cache_db_connection_options_t options = { {0} }; switch_status_t r; - if (!sql_manager.manage) { + if (!sql_manager->manage) { return SWITCH_STATUS_FALSE; } @@ -248,26 +256,26 @@ SWITCH_DECLARE(switch_status_t) _switch_core_persist_db_handle(switch_cache_db_h } else { options.core_db_options.db_path = SWITCH_CORE_PERSIST_DB; } - r = _switch_cache_db_get_db_handle(dbh, SCDB_TYPE_CORE_DB, &options, file, func, line); + r = __switch_cache_db_get_db_handle(sql_manager, dbh, SCDB_TYPE_CORE_DB, &options, file, func, line); } else { char *dsn; if ((dsn = strstr(runtime.odbc_dsn, "pgsql;")) != NULL) { options.pgsql_options.dsn = (char*)(dsn + 6); - r = _switch_cache_db_get_db_handle(dbh, SCDB_TYPE_PGSQL, &options, file, func, line); + r = __switch_cache_db_get_db_handle(sql_manager, dbh, SCDB_TYPE_PGSQL, &options, file, func, line); } else { options.odbc_options.dsn = runtime.odbc_dsn; options.odbc_options.user = runtime.odbc_user; options.odbc_options.pass = runtime.odbc_pass; - r = _switch_cache_db_get_db_handle(dbh, SCDB_TYPE_ODBC, &options, file, func, line); + r = __switch_cache_db_get_db_handle(sql_manager, dbh, SCDB_TYPE_ODBC, &options, file, func, line); } } /* I *think* we can do without this now, if not let me know if (r == SWITCH_STATUS_SUCCESS && !(*dbh)->io_mutex) { - (*dbh)->io_mutex = sql_manager.io_mutex; + (*dbh)->io_mutex = sql_manager->io_mutex; } */ @@ -276,12 +284,12 @@ SWITCH_DECLARE(switch_status_t) _switch_core_persist_db_handle(switch_cache_db_h #define SWITCH_CORE_RECOVERY_DB "core_recovery" -SWITCH_DECLARE(switch_status_t) _switch_core_recovery_db_handle(switch_cache_db_handle_t **dbh, const char *file, const char *func, int line) +SWITCH_DECLARE(switch_status_t) _switch_core_recovery_db_handle(switch_sql_manager_t *sql_manager, switch_cache_db_handle_t **dbh, const char *file, const char *func, int line) { switch_cache_db_connection_options_t options = { {0} }; switch_status_t r; - if (!sql_manager.manage) { + if (!sql_manager->manage) { return SWITCH_STATUS_FALSE; } @@ -295,26 +303,26 @@ SWITCH_DECLARE(switch_status_t) _switch_core_recovery_db_handle(switch_cache_db_ } else { options.core_db_options.db_path = SWITCH_CORE_RECOVERY_DB; } - r = _switch_cache_db_get_db_handle(dbh, SCDB_TYPE_CORE_DB, &options, file, func, line); + r = __switch_cache_db_get_db_handle(sql_manager, dbh, SCDB_TYPE_CORE_DB, &options, file, func, line); } else { char *dsn; if ((dsn = strstr(runtime.recovery_odbc_dsn, "pgsql;")) != NULL) { options.pgsql_options.dsn = (char*)(dsn + 6); - r = _switch_cache_db_get_db_handle(dbh, SCDB_TYPE_PGSQL, &options, file, func, line); + r = __switch_cache_db_get_db_handle(sql_manager, dbh, SCDB_TYPE_PGSQL, &options, file, func, line); } else { options.odbc_options.dsn = runtime.recovery_odbc_dsn; options.odbc_options.user = runtime.recovery_odbc_user; options.odbc_options.pass = runtime.recovery_odbc_pass; - r = _switch_cache_db_get_db_handle(dbh, SCDB_TYPE_ODBC, &options, file, func, line); + r = __switch_cache_db_get_db_handle(sql_manager, dbh, SCDB_TYPE_ODBC, &options, file, func, line); } } /* I *think* we can do without this now, if not let me know if (r == SWITCH_STATUS_SUCCESS && !(*dbh)->io_mutex) { - (*dbh)->io_mutex = sql_manager.io_mutex; + (*dbh)->io_mutex = sql_manager->io_mutex; } */ @@ -326,16 +334,16 @@ SWITCH_DECLARE(switch_status_t) _switch_core_recovery_db_handle(switch_cache_db_ #define SQL_REG_TIMEOUT 15 -static void sql_close(time_t prune) +static void sql_close(switch_sql_manager_t *sql_manager, time_t prune) { switch_cache_db_handle_t *dbh = NULL; int locked = 0; - switch_mutex_lock(sql_manager.dbh_mutex); + switch_mutex_lock(sql_manager->dbh_mutex); top: locked = 0; - for (dbh = sql_manager.handle_pool; dbh; dbh = dbh->next) { + for (dbh = sql_manager->handle_pool; dbh; dbh = dbh->next) { time_t diff = 0; if (prune > 0 && prune > dbh->last_used) { @@ -368,7 +376,7 @@ static void sql_close(time_t prune) break; } - del_handle(dbh); + del_handle(sql_manager, dbh); switch_mutex_unlock(dbh->mutex); switch_core_destroy_memory_pool(&dbh->pool); goto top; @@ -386,7 +394,7 @@ static void sql_close(time_t prune) goto top; } - switch_mutex_unlock(sql_manager.dbh_mutex); + switch_mutex_unlock(sql_manager->dbh_mutex); } @@ -395,16 +403,20 @@ SWITCH_DECLARE(switch_cache_db_handle_type_t) switch_cache_db_get_type(switch_ca return dbh->type; } -SWITCH_DECLARE(void) switch_cache_db_flush_handles(void) +SWITCH_DECLARE(void) switch_cache_db_flush_handles(switch_sql_manager_t *sql_manager) { - sql_close(switch_epoch_time_now(NULL) + SQL_CACHE_TIMEOUT + 1); + sql_close(sql_manager, switch_epoch_time_now(NULL) + SQL_CACHE_TIMEOUT + 1); } - SWITCH_DECLARE(void) switch_cache_db_release_db_handle(switch_cache_db_handle_t **dbh) +{ + _switch_cache_db_release_db_handle(&switch_cache_db_sql_manager, dbh); +} + +SWITCH_DECLARE(void) _switch_cache_db_release_db_handle(switch_sql_manager_t *sql_manager, switch_cache_db_handle_t **dbh) { if (dbh && *dbh) { - switch_mutex_lock(sql_manager.dbh_mutex); + switch_mutex_lock(sql_manager->dbh_mutex); (*dbh)->last_used = switch_epoch_time_now(NULL); (*dbh)->io_mutex = NULL; @@ -415,9 +427,9 @@ SWITCH_DECLARE(void) switch_cache_db_release_db_handle(switch_cache_db_handle_t } } switch_mutex_unlock((*dbh)->mutex); - sql_manager.total_used_handles--; + sql_manager->total_used_handles--; *dbh = NULL; - switch_mutex_unlock(sql_manager.dbh_mutex); + switch_mutex_unlock(sql_manager->dbh_mutex); } } @@ -428,7 +440,16 @@ SWITCH_DECLARE(void) switch_cache_db_dismiss_db_handle(switch_cache_db_handle_t } -SWITCH_DECLARE(switch_status_t) _switch_cache_db_get_db_handle(switch_cache_db_handle_t **dbh, +SWITCH_DECLARE(switch_status_t) _switch_cache_db_get_db_handle(switch_cache_db_handle_t ** dbh, + switch_cache_db_handle_type_t type, + switch_cache_db_connection_options_t *connection_options, + const char *file, const char *func, int line) +{ + return __switch_cache_db_get_db_handle(&switch_cache_db_sql_manager, dbh, type, connection_options, file, func, line); +} + +SWITCH_DECLARE(switch_status_t) __switch_cache_db_get_db_handle(switch_sql_manager_t *sql_manager, + switch_cache_db_handle_t **dbh, switch_cache_db_handle_type_t type, switch_cache_db_connection_options_t *connection_options, const char *file, const char *func, int line) @@ -445,7 +466,7 @@ SWITCH_DECLARE(switch_status_t) _switch_cache_db_get_db_handle(switch_cache_db_h const char *odbc_user = NULL; const char *odbc_pass = NULL; - while(runtime.max_db_handles && sql_manager.total_handles >= runtime.max_db_handles && sql_manager.total_used_handles >= sql_manager.total_handles) { + while(runtime.max_db_handles && sql_manager->total_handles >= runtime.max_db_handles && sql_manager->total_used_handles >= sql_manager->total_handles) { if (!waiting++) { switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, func, line, NULL, SWITCH_LOG_WARNING, "Max handles %u exceeded, blocking....\n", runtime.max_db_handles); @@ -496,7 +517,7 @@ SWITCH_DECLARE(switch_status_t) _switch_cache_db_get_db_handle(switch_cache_db_h snprintf(db_callsite_str, sizeof(db_callsite_str) - 1, "%s:%d", file, line); snprintf(thread_str, sizeof(thread_str) - 1, "thread=\"%lu\"", (unsigned long) (intptr_t) self); - if ((new_dbh = get_handle(db_str, db_callsite_str, thread_str))) { + if ((new_dbh = get_handle(sql_manager, db_str, db_callsite_str, thread_str))) { switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, func, line, NULL, SWITCH_LOG_DEBUG10, "Reuse Unused Cached DB handle %s [%s]\n", new_dbh->name, switch_cache_db_type_name(new_dbh->type)); } else { @@ -552,9 +573,6 @@ SWITCH_DECLARE(switch_status_t) _switch_cache_db_get_db_handle(switch_cache_db_h goto end; } - switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, func, line, NULL, SWITCH_LOG_DEBUG10, - "Create Cached DB handle %s [%s] %s:%d\n", new_dbh->name, switch_cache_db_type_name(type), file, line); - new_dbh = create_handle(type); if (db) { @@ -565,7 +583,11 @@ SWITCH_DECLARE(switch_status_t) _switch_cache_db_get_db_handle(switch_cache_db_h new_dbh->native_handle.pgsql_dbh = pgsql_dbh; } - add_handle(new_dbh, db_str, db_callsite_str, thread_str); + add_handle(sql_manager, new_dbh, db_str, db_callsite_str, thread_str); + + switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, func, line, NULL, SWITCH_LOG_DEBUG10, + "Create Cached DB handle %s [%s] %s:%d\n", new_dbh->name, switch_cache_db_type_name(type), file, line); + } end: @@ -638,18 +660,20 @@ static switch_status_t switch_cache_db_execute_sql_real(switch_cache_db_handle_t return status; } -static void wake_thread(int force) +static void _wake_thread(switch_sql_manager_t *sql_manager, int force) { if (force) { - switch_thread_cond_signal(sql_manager.cond); + switch_thread_cond_signal(sql_manager->cond); return; } - if (switch_mutex_trylock(sql_manager.cond_mutex) == SWITCH_STATUS_SUCCESS) { - switch_thread_cond_signal(sql_manager.cond); - switch_mutex_unlock(sql_manager.cond_mutex); + if (switch_mutex_trylock(sql_manager->cond_mutex) == SWITCH_STATUS_SUCCESS) { + switch_thread_cond_signal(sql_manager->cond); + switch_mutex_unlock(sql_manager->cond_mutex); } } +#define wake_thread(f) _wake_thread(&switch_cache_db_sql_manager, f) + /** OMFG you cruel bastards. Who chooses 64k as a max buffer len for a sql statement, have you ever heard of transactions? @@ -1173,13 +1197,16 @@ SWITCH_DECLARE(switch_bool_t) switch_cache_db_test_reactive(switch_cache_db_hand static void *SWITCH_THREAD_FUNC switch_core_sql_db_thread(switch_thread_t *thread, void *obj) { - int sec = 0, reg_sec = 0;; + int sec = 0, reg_sec = 0; + switch_sql_manager_t *sql_manager; - sql_manager.db_thread_running = 1; + sql_manager = (switch_sql_manager_t*)obj; - while (sql_manager.db_thread_running == 1) { + sql_manager->db_thread_running = 1; + + while (sql_manager->db_thread_running == 1) { if (++sec == SQL_CACHE_TIMEOUT) { - sql_close(switch_epoch_time_now(NULL)); + sql_close(sql_manager, switch_epoch_time_now(NULL)); wake_thread(0); sec = 0; } @@ -1208,44 +1235,47 @@ static void *SWITCH_THREAD_FUNC switch_core_sql_thread(switch_thread_t *thread, int lc = 0, wrote = 0, do_sleep = 1; uint32_t sanity = 120; int auto_pause = 0; + switch_sql_manager_t *sql_manager; + + sql_manager = (switch_sql_manager_t*)obj; switch_assert(sqlbuf); - while (!sql_manager.event_db) { - if (switch_core_db_handle(&sql_manager.event_db) == SWITCH_STATUS_SUCCESS && sql_manager.event_db) + while (!sql_manager->event_db) { + if (switch_core_db_handle(&sql_manager->event_db) == SWITCH_STATUS_SUCCESS && sql_manager->event_db) break; switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Error getting core db, Retrying\n"); switch_yield(500000); sanity--; } - if (!sql_manager.event_db) { + if (!sql_manager->event_db) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Error getting core db Disabling core sql functionality\n"); return NULL; } - sql_manager.thread_running = 1; + sql_manager->thread_running = 1; - switch_mutex_lock(sql_manager.cond_mutex); + switch_mutex_lock(sql_manager->cond_mutex); - switch (sql_manager.event_db->type) { + switch (switch_cache_db_sql_manager.event_db->type) { case SCDB_TYPE_PGSQL: break; case SCDB_TYPE_ODBC: break; case SCDB_TYPE_CORE_DB: { - switch_cache_db_execute_sql(sql_manager.event_db, "PRAGMA synchronous=OFF;", NULL); - switch_cache_db_execute_sql(sql_manager.event_db, "PRAGMA count_changes=OFF;", NULL); - switch_cache_db_execute_sql(sql_manager.event_db, "PRAGMA temp_store=MEMORY;", NULL); - switch_cache_db_execute_sql(sql_manager.event_db, "PRAGMA journal_mode=OFF;", NULL); + switch_cache_db_execute_sql(sql_manager->event_db, "PRAGMA synchronous=OFF;", NULL); + switch_cache_db_execute_sql(sql_manager->event_db, "PRAGMA count_changes=OFF;", NULL); + switch_cache_db_execute_sql(sql_manager->event_db, "PRAGMA temp_store=MEMORY;", NULL); + switch_cache_db_execute_sql(sql_manager->event_db, "PRAGMA journal_mode=OFF;", NULL); } break; } - while (sql_manager.thread_running == 1) { - if (save_sql || switch_queue_trypop(sql_manager.sql_queue[0], &pop) == SWITCH_STATUS_SUCCESS || - switch_queue_trypop(sql_manager.sql_queue[1], &pop) == SWITCH_STATUS_SUCCESS) { + while (sql_manager->thread_running == 1) { + if (save_sql || switch_queue_trypop(sql_manager->sql_queue[0], &pop) == SWITCH_STATUS_SUCCESS || + switch_queue_trypop(sql_manager->sql_queue[1], &pop) == SWITCH_STATUS_SUCCESS) { if (save_sql) { sql = save_sql; @@ -1268,8 +1298,8 @@ static void *SWITCH_THREAD_FUNC switch_core_sql_thread(switch_thread_t *thread, sql_len = new_mlen; if (switch_test_flag((&runtime), SCF_DEBUG_SQL)) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, - "REALLOC %ld %d %d\n", (long int)sql_len, switch_queue_size(sql_manager.sql_queue[0]), - switch_queue_size(sql_manager.sql_queue[1])); + "REALLOC %ld %d %d\n", (long int)sql_len, switch_queue_size(sql_manager->sql_queue[0]), + switch_queue_size(sql_manager->sql_queue[1])); } if (!(tmp = realloc(sqlbuf, sql_len))) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "SQL thread ending on mem err\n"); @@ -1280,7 +1310,7 @@ static void *SWITCH_THREAD_FUNC switch_core_sql_thread(switch_thread_t *thread, } else { if (switch_test_flag((&runtime), SCF_DEBUG_SQL)) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, - "SAVE %d %d\n", switch_queue_size(sql_manager.sql_queue[0]), switch_queue_size(sql_manager.sql_queue[1])); + "SAVE %d %d\n", switch_queue_size(sql_manager->sql_queue[0]), switch_queue_size(sql_manager->sql_queue[1])); } save_sql = sql; sql = NULL; @@ -1289,7 +1319,7 @@ static void *SWITCH_THREAD_FUNC switch_core_sql_thread(switch_thread_t *thread, } } - iterations++; + iterations++; sprintf(sqlbuf + len, "%s;\n", sql); len += newlen; free(sql); @@ -1300,7 +1330,7 @@ static void *SWITCH_THREAD_FUNC switch_core_sql_thread(switch_thread_t *thread, } } - lc = switch_queue_size(sql_manager.sql_queue[0]) + switch_queue_size(sql_manager.sql_queue[1]); + lc = switch_queue_size(sql_manager->sql_queue[0]) + switch_queue_size(sql_manager->sql_queue[1]); if (lc > SWITCH_SQL_QUEUE_PAUSE_LEN) { @@ -1326,9 +1356,9 @@ static void *SWITCH_THREAD_FUNC switch_core_sql_thread(switch_thread_t *thread, if (trans && iterations && (iterations > target || !lc)) { if (switch_test_flag((&runtime), SCF_DEBUG_SQL)) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, - "RUN %d %d %d\n", switch_queue_size(sql_manager.sql_queue[0]), switch_queue_size(sql_manager.sql_queue[1]), iterations); + "RUN %d %d %d\n", switch_queue_size(sql_manager->sql_queue[0]), switch_queue_size(sql_manager->sql_queue[1]), iterations); } - if (switch_cache_db_persistant_execute_trans(sql_manager.event_db, sqlbuf, 1) != SWITCH_STATUS_SUCCESS) { + if (switch_cache_db_persistant_execute_trans(sql_manager->event_db, sqlbuf, 1) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "SQL thread unable to commit transaction, records lost!\n"); } if (switch_test_flag((&runtime), SCF_DEBUG_SQL)) { @@ -1349,10 +1379,10 @@ static void *SWITCH_THREAD_FUNC switch_core_sql_thread(switch_thread_t *thread, wrote = 1; } - lc = switch_queue_size(sql_manager.sql_queue[0]) + switch_queue_size(sql_manager.sql_queue[1]); + lc = switch_queue_size(sql_manager->sql_queue[0]) + switch_queue_size(sql_manager->sql_queue[1]); if (!lc) { - switch_thread_cond_wait(sql_manager.cond, sql_manager.cond_mutex); + switch_thread_cond_wait(sql_manager->cond, sql_manager->cond_mutex); } else if (wrote) { if (lc > 2000) { do_sleep = 0; @@ -1364,21 +1394,21 @@ static void *SWITCH_THREAD_FUNC switch_core_sql_thread(switch_thread_t *thread, } - switch_mutex_unlock(sql_manager.cond_mutex); + switch_mutex_unlock(sql_manager->cond_mutex); - while (switch_queue_trypop(sql_manager.sql_queue[0], &pop) == SWITCH_STATUS_SUCCESS) { + while (switch_queue_trypop(sql_manager->sql_queue[0], &pop) == SWITCH_STATUS_SUCCESS) { free(pop); } - while (switch_queue_trypop(sql_manager.sql_queue[1], &pop) == SWITCH_STATUS_SUCCESS) { + while (switch_queue_trypop(sql_manager->sql_queue[1], &pop) == SWITCH_STATUS_SUCCESS) { free(pop); } free(sqlbuf); - sql_manager.thread_running = 0; + sql_manager->thread_running = 0; - switch_cache_db_release_db_handle(&sql_manager.event_db); + switch_cache_db_release_db_handle(&sql_manager->event_db); return NULL; } @@ -1820,9 +1850,9 @@ static void core_event_handler(switch_event_t *event) for (i = 0; i < sql_idx; i++) { if (switch_stristr("update channels", sql[i]) || switch_stristr("delete from channels", sql[i])) { - switch_queue_push(sql_manager.sql_queue[1], sql[i]); + switch_queue_push(switch_cache_db_sql_manager.sql_queue[1], sql[i]); } else { - switch_queue_push(sql_manager.sql_queue[0], sql[i]); + switch_queue_push(switch_cache_db_sql_manager.sql_queue[0], sql[i]); } sql[i] = NULL; wake_thread(0); @@ -2381,7 +2411,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_add_registration(const char *user, c user, realm, switch_core_get_switchname()); } - switch_queue_push(sql_manager.sql_queue[0], sql); + switch_queue_push(switch_cache_db_sql_manager.sql_queue[0], sql); if ( !zstr(metadata) ) { sql = switch_mprintf("insert into registrations (reg_user,realm,token,url,expires,network_ip,network_port,network_proto,hostname,metadata) " @@ -2413,7 +2443,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_add_registration(const char *user, c } - switch_queue_push(sql_manager.sql_queue[0], sql); + switch_queue_push(switch_cache_db_sql_manager.sql_queue[0], sql); return SWITCH_STATUS_SUCCESS; } @@ -2433,7 +2463,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_del_registration(const char *user, c sql = switch_mprintf("delete from registrations where reg_user='%q' and realm='%q' and hostname='%q'", user, realm, switch_core_get_switchname()); } - switch_queue_push(sql_manager.sql_queue[0], sql); + switch_queue_push(switch_cache_db_sql_manager.sql_queue[0], sql); return SWITCH_STATUS_SUCCESS; } @@ -2456,35 +2486,33 @@ SWITCH_DECLARE(switch_status_t) switch_core_expire_registration(int force) sql = switch_mprintf("delete from registrations where expires > 0 and expires <= %ld and hostname='%q'", now, switch_core_get_switchname()); } - switch_queue_push(sql_manager.sql_queue[0], sql); + switch_queue_push(switch_cache_db_sql_manager.sql_queue[0], sql); return SWITCH_STATUS_SUCCESS; } -switch_status_t switch_core_sqldb_start(switch_memory_pool_t *pool, switch_bool_t manage) +void switch_sqldb_init_sql_manager(switch_sql_manager_t *sql_manager, switch_memory_pool_t *pool, switch_bool_t manage) { - switch_threadattr_t *thd_attr; - uint32_t sanity = 400; - sql_manager.memory_pool = pool; - sql_manager.manage = manage; + sql_manager->memory_pool = pool; + sql_manager->manage = manage; - switch_mutex_init(&sql_manager.dbh_mutex, SWITCH_MUTEX_NESTED, sql_manager.memory_pool); - switch_mutex_init(&sql_manager.io_mutex, SWITCH_MUTEX_NESTED, sql_manager.memory_pool); - switch_mutex_init(&sql_manager.cond_mutex, SWITCH_MUTEX_NESTED, sql_manager.memory_pool); - switch_mutex_init(&sql_manager.ctl_mutex, SWITCH_MUTEX_NESTED, sql_manager.memory_pool); + switch_mutex_init(&sql_manager->dbh_mutex, SWITCH_MUTEX_NESTED, sql_manager->memory_pool); + switch_mutex_init(&sql_manager->io_mutex, SWITCH_MUTEX_NESTED, sql_manager->memory_pool); + switch_mutex_init(&sql_manager->cond_mutex, SWITCH_MUTEX_NESTED, sql_manager->memory_pool); + switch_mutex_init(&sql_manager->ctl_mutex, SWITCH_MUTEX_NESTED, sql_manager->memory_pool); - switch_thread_cond_create(&sql_manager.cond, sql_manager.memory_pool); + switch_thread_cond_create(&sql_manager->cond, sql_manager->memory_pool); +} +switch_status_t switch_sqldb_connect(switch_sql_manager_t *sql_manager, switch_memory_pool_t *pool) +{ - - if (!sql_manager.manage) goto skip; - - top: + top: /* Activate SQL database */ - if (switch_core_db_handle(&sql_manager.dbh) != SWITCH_STATUS_SUCCESS) { + if (switch_core_db_handle(&sql_manager->dbh) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error Opening DB!\n"); if (switch_test_flag((&runtime), SCF_CORE_NON_SQLITE_DB_REQ)) { @@ -2508,8 +2536,25 @@ switch_status_t switch_core_sqldb_start(switch_memory_pool_t *pool, switch_bool_ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Opening DB\n"); + return SWITCH_STATUS_SUCCESS; +} - switch (sql_manager.dbh->type) { +switch_status_t switch_core_sqldb_start(switch_memory_pool_t *pool, switch_bool_t manage) +{ + switch_threadattr_t *thd_attr; + uint32_t sanity = 400; + switch_sql_manager_t *sql_manager = &switch_cache_db_sql_manager; + + switch_sqldb_init_sql_manager(sql_manager, pool, manage); + + if (manage == SWITCH_FALSE) goto skip; + + top: + if (switch_sqldb_connect(sql_manager, pool) == SWITCH_STATUS_FALSE) { + return SWITCH_STATUS_FALSE; + } + + switch (sql_manager->dbh->type) { case SCDB_TYPE_PGSQL: case SCDB_TYPE_ODBC: if (switch_test_flag((&runtime), SCF_CLEAR_SQL)) { @@ -2520,61 +2565,61 @@ switch_status_t switch_core_sqldb_start(switch_memory_pool_t *pool, switch_bool_ for (i = 0; tables[i]; i++) { switch_snprintfv(sql, sizeof(sql), "delete from %q where hostname='%q'", tables[i], hostname); - switch_cache_db_execute_sql(sql_manager.dbh, sql, NULL); + switch_cache_db_execute_sql(sql_manager->dbh, sql, NULL); } } break; case SCDB_TYPE_CORE_DB: { - switch_cache_db_execute_sql(sql_manager.dbh, "drop table channels", NULL); - switch_cache_db_execute_sql(sql_manager.dbh, "drop table calls", NULL); - switch_cache_db_execute_sql(sql_manager.dbh, "drop view detailed_calls", NULL); - switch_cache_db_execute_sql(sql_manager.dbh, "drop view basic_calls", NULL); - switch_cache_db_execute_sql(sql_manager.dbh, "drop table interfaces", NULL); - switch_cache_db_execute_sql(sql_manager.dbh, "drop table tasks", NULL); - switch_cache_db_execute_sql(sql_manager.dbh, "PRAGMA synchronous=OFF;", NULL); - switch_cache_db_execute_sql(sql_manager.dbh, "PRAGMA count_changes=OFF;", NULL); - switch_cache_db_execute_sql(sql_manager.dbh, "PRAGMA default_cache_size=8000", NULL); - switch_cache_db_execute_sql(sql_manager.dbh, "PRAGMA temp_store=MEMORY;", NULL); - switch_cache_db_execute_sql(sql_manager.dbh, "PRAGMA journal_mode=OFF;", NULL); + switch_cache_db_execute_sql(sql_manager->dbh, "drop table channels", NULL); + switch_cache_db_execute_sql(sql_manager->dbh, "drop table calls", NULL); + switch_cache_db_execute_sql(sql_manager->dbh, "drop view detailed_calls", NULL); + switch_cache_db_execute_sql(sql_manager->dbh, "drop view basic_calls", NULL); + switch_cache_db_execute_sql(sql_manager->dbh, "drop table interfaces", NULL); + switch_cache_db_execute_sql(sql_manager->dbh, "drop table tasks", NULL); + switch_cache_db_execute_sql(sql_manager->dbh, "PRAGMA synchronous=OFF;", NULL); + switch_cache_db_execute_sql(sql_manager->dbh, "PRAGMA count_changes=OFF;", NULL); + switch_cache_db_execute_sql(sql_manager->dbh, "PRAGMA default_cache_size=8000", NULL); + switch_cache_db_execute_sql(sql_manager->dbh, "PRAGMA temp_store=MEMORY;", NULL); + switch_cache_db_execute_sql(sql_manager->dbh, "PRAGMA journal_mode=OFF;", NULL); } break; } - switch_cache_db_test_reactive(sql_manager.dbh, "select hostname from aliases", "DROP TABLE aliases", create_alias_sql); - switch_cache_db_test_reactive(sql_manager.dbh, "select hostname from complete", "DROP TABLE complete", create_complete_sql); - switch_cache_db_test_reactive(sql_manager.dbh, "select hostname from nat", "DROP TABLE nat", create_nat_sql); - switch_cache_db_test_reactive(sql_manager.dbh, "delete from registrations where reg_user='' or network_proto='tcp' or network_proto='tls'", + switch_cache_db_test_reactive(sql_manager->dbh, "select hostname from aliases", "DROP TABLE aliases", create_alias_sql); + switch_cache_db_test_reactive(sql_manager->dbh, "select hostname from complete", "DROP TABLE complete", create_complete_sql); + switch_cache_db_test_reactive(sql_manager->dbh, "select hostname from nat", "DROP TABLE nat", create_nat_sql); + switch_cache_db_test_reactive(sql_manager->dbh, "delete from registrations where reg_user='' or network_proto='tcp' or network_proto='tls'", "DROP TABLE registrations", create_registrations_sql); - switch_cache_db_test_reactive(sql_manager.dbh, "select metadata from registrations", NULL, "ALTER TABLE registrations ADD COLUMN metadata VARCHAR(256)"); + switch_cache_db_test_reactive(sql_manager->dbh, "select metadata from registrations", NULL, "ALTER TABLE registrations ADD COLUMN metadata VARCHAR(256)"); - switch (sql_manager.dbh->type) { + switch (sql_manager->dbh->type) { case SCDB_TYPE_PGSQL: case SCDB_TYPE_ODBC: { char *err; - switch_cache_db_test_reactive(sql_manager.dbh, "select call_uuid, read_bit_rate, sent_callee_name from channels", "DROP TABLE channels", create_channels_sql); - switch_cache_db_test_reactive(sql_manager.dbh, "select * from detailed_calls where sent_callee_name=''", "DROP VIEW detailed_calls", detailed_calls_sql); - switch_cache_db_test_reactive(sql_manager.dbh, "select * from basic_calls where sent_callee_name=''", "DROP VIEW basic_calls", basic_calls_sql); - switch_cache_db_test_reactive(sql_manager.dbh, "select call_uuid from calls", "DROP TABLE calls", create_calls_sql); + switch_cache_db_test_reactive(sql_manager->dbh, "select call_uuid, read_bit_rate, sent_callee_name from channels", "DROP TABLE channels", create_channels_sql); + switch_cache_db_test_reactive(sql_manager->dbh, "select * from detailed_calls where sent_callee_name=''", "DROP VIEW detailed_calls", detailed_calls_sql); + switch_cache_db_test_reactive(sql_manager->dbh, "select * from basic_calls where sent_callee_name=''", "DROP VIEW basic_calls", basic_calls_sql); + switch_cache_db_test_reactive(sql_manager->dbh, "select call_uuid from calls", "DROP TABLE calls", create_calls_sql); if (runtime.odbc_dbtype == DBTYPE_DEFAULT) { - switch_cache_db_test_reactive(sql_manager.dbh, "delete from registrations where reg_user='' or network_proto='tcp' or network_proto='tls'", + switch_cache_db_test_reactive(sql_manager->dbh, "delete from registrations where reg_user='' or network_proto='tcp' or network_proto='tls'", "DROP TABLE registrations", create_registrations_sql); } else { char *tmp = switch_string_replace(create_registrations_sql, "url TEXT", "url VARCHAR(max)"); - switch_cache_db_test_reactive(sql_manager.dbh, "delete from registrations where reg_user='' or network_proto='tcp' or network_proto='tls'", + switch_cache_db_test_reactive(sql_manager->dbh, "delete from registrations where reg_user='' or network_proto='tcp' or network_proto='tls'", "DROP TABLE registrations", tmp); free(tmp); } - switch_cache_db_test_reactive(sql_manager.dbh, "select ikey from interfaces", "DROP TABLE interfaces", create_interfaces_sql); - switch_cache_db_test_reactive(sql_manager.dbh, "select hostname from tasks", "DROP TABLE tasks", create_tasks_sql); + switch_cache_db_test_reactive(sql_manager->dbh, "select ikey from interfaces", "DROP TABLE interfaces", create_interfaces_sql); + switch_cache_db_test_reactive(sql_manager->dbh, "select hostname from tasks", "DROP TABLE tasks", create_tasks_sql); if (runtime.odbc_dbtype == DBTYPE_DEFAULT) { - switch_cache_db_execute_sql(sql_manager.dbh, "begin;delete from channels where hostname='';delete from channels where hostname='';commit;", &err); + switch_cache_db_execute_sql(sql_manager->dbh, "begin;delete from channels where hostname='';delete from channels where hostname='';commit;", &err); } else { - switch_cache_db_execute_sql(sql_manager.dbh, "delete from channels where hostname='';delete from channels where hostname='';", &err); + switch_cache_db_execute_sql(sql_manager->dbh, "delete from channels where hostname='';delete from channels where hostname='';", &err); } if (err) { @@ -2582,7 +2627,7 @@ switch_status_t switch_core_sqldb_start(switch_memory_pool_t *pool, switch_bool_ runtime.odbc_user = NULL; runtime.odbc_pass = NULL; switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Transactions not supported on your DB, disabling non-SQLite support; using SQLite\n"); - switch_cache_db_release_db_handle(&sql_manager.dbh); + switch_cache_db_release_db_handle(&sql_manager->dbh); free(err); goto top; } @@ -2590,49 +2635,49 @@ switch_status_t switch_core_sqldb_start(switch_memory_pool_t *pool, switch_bool_ break; case SCDB_TYPE_CORE_DB: { - switch_cache_db_execute_sql(sql_manager.dbh, create_channels_sql, NULL); - switch_cache_db_execute_sql(sql_manager.dbh, create_calls_sql, NULL); - switch_cache_db_execute_sql(sql_manager.dbh, create_interfaces_sql, NULL); - switch_cache_db_execute_sql(sql_manager.dbh, create_tasks_sql, NULL); - switch_cache_db_execute_sql(sql_manager.dbh, detailed_calls_sql, NULL); - switch_cache_db_execute_sql(sql_manager.dbh, basic_calls_sql, NULL); + switch_cache_db_execute_sql(sql_manager->dbh, create_channels_sql, NULL); + switch_cache_db_execute_sql(sql_manager->dbh, create_calls_sql, NULL); + switch_cache_db_execute_sql(sql_manager->dbh, create_interfaces_sql, NULL); + switch_cache_db_execute_sql(sql_manager->dbh, create_tasks_sql, NULL); + switch_cache_db_execute_sql(sql_manager->dbh, detailed_calls_sql, NULL); + switch_cache_db_execute_sql(sql_manager->dbh, basic_calls_sql, NULL); } break; } - switch_cache_db_execute_sql(sql_manager.dbh, "delete from complete where sticky=0", NULL); - switch_cache_db_execute_sql(sql_manager.dbh, "delete from aliases where sticky=0", NULL); - switch_cache_db_execute_sql(sql_manager.dbh, "delete from nat where sticky=0", NULL); - switch_cache_db_execute_sql(sql_manager.dbh, "create index alias1 on aliases (alias)", NULL); - switch_cache_db_execute_sql(sql_manager.dbh, "create index tasks1 on tasks (hostname,task_id)", NULL); - switch_cache_db_execute_sql(sql_manager.dbh, "create index complete1 on complete (a1,hostname)", NULL); - switch_cache_db_execute_sql(sql_manager.dbh, "create index complete2 on complete (a2,hostname)", NULL); - switch_cache_db_execute_sql(sql_manager.dbh, "create index complete3 on complete (a3,hostname)", NULL); - switch_cache_db_execute_sql(sql_manager.dbh, "create index complete4 on complete (a4,hostname)", NULL); - switch_cache_db_execute_sql(sql_manager.dbh, "create index complete5 on complete (a5,hostname)", NULL); - switch_cache_db_execute_sql(sql_manager.dbh, "create index complete6 on complete (a6,hostname)", NULL); - switch_cache_db_execute_sql(sql_manager.dbh, "create index complete7 on complete (a7,hostname)", NULL); - switch_cache_db_execute_sql(sql_manager.dbh, "create index complete8 on complete (a8,hostname)", NULL); - switch_cache_db_execute_sql(sql_manager.dbh, "create index complete9 on complete (a9,hostname)", NULL); - switch_cache_db_execute_sql(sql_manager.dbh, "create index complete10 on complete (a10,hostname)", NULL); - switch_cache_db_execute_sql(sql_manager.dbh, "create index complete11 on complete (a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,hostname)", NULL); - switch_cache_db_execute_sql(sql_manager.dbh, "create index nat_map_port_proto on nat (port,proto,hostname)", NULL); - switch_cache_db_execute_sql(sql_manager.dbh, "create index channels1 on channels(hostname)", NULL); - switch_cache_db_execute_sql(sql_manager.dbh, "create index calls1 on calls(hostname)", NULL); - switch_cache_db_execute_sql(sql_manager.dbh, "create index chidx1 on channels (hostname)", NULL); - switch_cache_db_execute_sql(sql_manager.dbh, "create index uuindex on channels (uuid)", NULL); - switch_cache_db_execute_sql(sql_manager.dbh, "create index uuindex2 on channels (call_uuid)", NULL); - switch_cache_db_execute_sql(sql_manager.dbh, "create index callsidx1 on calls (hostname)", NULL); - switch_cache_db_execute_sql(sql_manager.dbh, "create index eruuindex on calls (caller_uuid)", NULL); - switch_cache_db_execute_sql(sql_manager.dbh, "create index eeuuindex on calls (callee_uuid)", NULL); - switch_cache_db_execute_sql(sql_manager.dbh, "create index eeuuindex2 on calls (call_uuid)", NULL); - switch_cache_db_execute_sql(sql_manager.dbh, "create index regindex1 on registrations (reg_user,realm,hostname)", NULL); + switch_cache_db_execute_sql(sql_manager->dbh, "delete from complete where sticky=0", NULL); + switch_cache_db_execute_sql(sql_manager->dbh, "delete from aliases where sticky=0", NULL); + switch_cache_db_execute_sql(sql_manager->dbh, "delete from nat where sticky=0", NULL); + switch_cache_db_execute_sql(sql_manager->dbh, "create index alias1 on aliases (alias)", NULL); + switch_cache_db_execute_sql(sql_manager->dbh, "create index tasks1 on tasks (hostname,task_id)", NULL); + switch_cache_db_execute_sql(sql_manager->dbh, "create index complete1 on complete (a1,hostname)", NULL); + switch_cache_db_execute_sql(sql_manager->dbh, "create index complete2 on complete (a2,hostname)", NULL); + switch_cache_db_execute_sql(sql_manager->dbh, "create index complete3 on complete (a3,hostname)", NULL); + switch_cache_db_execute_sql(sql_manager->dbh, "create index complete4 on complete (a4,hostname)", NULL); + switch_cache_db_execute_sql(sql_manager->dbh, "create index complete5 on complete (a5,hostname)", NULL); + switch_cache_db_execute_sql(sql_manager->dbh, "create index complete6 on complete (a6,hostname)", NULL); + switch_cache_db_execute_sql(sql_manager->dbh, "create index complete7 on complete (a7,hostname)", NULL); + switch_cache_db_execute_sql(sql_manager->dbh, "create index complete8 on complete (a8,hostname)", NULL); + switch_cache_db_execute_sql(sql_manager->dbh, "create index complete9 on complete (a9,hostname)", NULL); + switch_cache_db_execute_sql(sql_manager->dbh, "create index complete10 on complete (a10,hostname)", NULL); + switch_cache_db_execute_sql(sql_manager->dbh, "create index complete11 on complete (a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,hostname)", NULL); + switch_cache_db_execute_sql(sql_manager->dbh, "create index nat_map_port_proto on nat (port,proto,hostname)", NULL); + switch_cache_db_execute_sql(sql_manager->dbh, "create index channels1 on channels(hostname)", NULL); + switch_cache_db_execute_sql(sql_manager->dbh, "create index calls1 on calls(hostname)", NULL); + switch_cache_db_execute_sql(sql_manager->dbh, "create index chidx1 on channels (hostname)", NULL); + switch_cache_db_execute_sql(sql_manager->dbh, "create index uuindex on channels (uuid)", NULL); + switch_cache_db_execute_sql(sql_manager->dbh, "create index uuindex2 on channels (call_uuid)", NULL); + switch_cache_db_execute_sql(sql_manager->dbh, "create index callsidx1 on calls (hostname)", NULL); + switch_cache_db_execute_sql(sql_manager->dbh, "create index eruuindex on calls (caller_uuid)", NULL); + switch_cache_db_execute_sql(sql_manager->dbh, "create index eeuuindex on calls (callee_uuid)", NULL); + switch_cache_db_execute_sql(sql_manager->dbh, "create index eeuuindex2 on calls (call_uuid)", NULL); + switch_cache_db_execute_sql(sql_manager->dbh, "create index regindex1 on registrations (reg_user,realm,hostname)", NULL); skip: - if (sql_manager.manage) { + if (sql_manager->manage) { #ifdef SWITCH_SQL_BIND_EVERY_EVENT switch_event_bind("core_db", SWITCH_EVENT_ALL, SWITCH_EVENT_SUBCLASS_ANY, core_event_handler, NULL); #else @@ -2661,16 +2706,16 @@ switch_status_t switch_core_sqldb_start(switch_memory_pool_t *pool, switch_bool_ switch_event_bind("core_db", SWITCH_EVENT_NAT, SWITCH_EVENT_SUBCLASS_ANY, core_event_handler, NULL); #endif - switch_queue_create(&sql_manager.sql_queue[0], SWITCH_SQL_QUEUE_LEN, sql_manager.memory_pool); - switch_queue_create(&sql_manager.sql_queue[1], SWITCH_SQL_QUEUE_LEN, sql_manager.memory_pool); + switch_queue_create(&sql_manager->sql_queue[0], SWITCH_SQL_QUEUE_LEN, sql_manager->memory_pool); + switch_queue_create(&sql_manager->sql_queue[1], SWITCH_SQL_QUEUE_LEN, sql_manager->memory_pool); - switch_threadattr_create(&thd_attr, sql_manager.memory_pool); + switch_threadattr_create(&thd_attr, sql_manager->memory_pool); switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE); switch_threadattr_priority_set(thd_attr, SWITCH_PRI_REALTIME); switch_core_sqldb_start_thread(); - switch_thread_create(&sql_manager.db_thread, thd_attr, switch_core_sql_db_thread, NULL, sql_manager.memory_pool); + switch_thread_create(&sql_manager->db_thread, thd_attr, switch_core_sql_db_thread, sql_manager, sql_manager->memory_pool); - while (sql_manager.manage && !sql_manager.thread_running && --sanity) { + while (sql_manager->manage && !sql_manager->thread_running && --sanity) { switch_yield(10000); } } @@ -2678,37 +2723,36 @@ switch_status_t switch_core_sqldb_start(switch_memory_pool_t *pool, switch_bool_ } -SWITCH_DECLARE(void) switch_core_sqldb_stop_thread(void) +SWITCH_DECLARE(void) switch_sqldb_stop_thread(switch_sql_manager_t *sql_manager) { - switch_mutex_lock(sql_manager.ctl_mutex); - if (sql_manager.thread && sql_manager.thread_running) { + switch_mutex_lock(sql_manager->ctl_mutex); + if (sql_manager->thread && sql_manager->thread_running) { switch_status_t st; - if (sql_manager.manage) { - switch_queue_push(sql_manager.sql_queue[0], NULL); - switch_queue_push(sql_manager.sql_queue[1], NULL); + if (sql_manager->manage) { + switch_queue_push(sql_manager->sql_queue[0], NULL); + switch_queue_push(sql_manager->sql_queue[1], NULL); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Waiting for unfinished SQL transactions\n"); wake_thread(0); - sql_manager.thread_running = -1; - switch_thread_join(&st, sql_manager.thread); - sql_manager.thread = NULL; - switch_cache_db_release_db_handle(&sql_manager.dbh); - sql_manager.dbh = NULL; + sql_manager->thread_running = -1; + switch_thread_join(&st, sql_manager->thread); + sql_manager->thread = NULL; + switch_cache_db_release_db_handle(&sql_manager->dbh); + sql_manager->dbh = NULL; } else { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "SQL is not enabled\n"); } } else { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "SQL thread is not running\n"); } - switch_mutex_unlock(sql_manager.ctl_mutex); + switch_mutex_unlock(sql_manager->ctl_mutex); } -SWITCH_DECLARE(void) switch_core_sqldb_start_thread(void) + +void switch_core_recovery_create_indices(void) { switch_cache_db_handle_t *dbh; - switch_mutex_lock(sql_manager.ctl_mutex); - if (switch_core_recovery_db_handle(&dbh) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error Opening DB!\n"); @@ -2728,14 +2772,34 @@ SWITCH_DECLARE(void) switch_core_sqldb_start_thread(void) switch_cache_db_release_db_handle(&dbh); } +} - if (sql_manager.manage) { + +SWITCH_DECLARE(void) switch_core_sqldb_start_thread(void) +{ + char *post_connect_sql[2]; + post_connect_sql[0] = "delete from channels"; + post_connect_sql[1] = "delete from calls"; + + switch_core_recovery_create_indices(); + switch_sqldb_start_thread(&switch_cache_db_sql_manager, switch_core_sql_thread, post_connect_sql, 2); + +} + +SWITCH_DECLARE(void) switch_sqldb_start_thread(switch_sql_manager_t *sql_manager, void *(SWITCH_THREAD_FUNC * func) (switch_thread_t *, void *), + char *post_connect_sql[], int argc) +{ + int i = 0; + + switch_mutex_lock(sql_manager->ctl_mutex); + + if (sql_manager->manage) { top: - if (!sql_manager.dbh) { + if (!sql_manager->dbh) { /* Activate SQL database */ - if (switch_core_db_handle(&sql_manager.dbh) != SWITCH_STATUS_SUCCESS) { + if (switch_core_db_handle(&sql_manager->dbh) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error Opening DB!\n"); if (switch_test_flag((&runtime), SCF_CORE_NON_SQLITE_DB_REQ)) { @@ -2749,7 +2813,7 @@ SWITCH_DECLARE(void) switch_core_sqldb_start_thread(void) runtime.odbc_pass = NULL; runtime.odbc_dbtype = DBTYPE_DEFAULT; switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Falling back to core_db.\n"); - sql_manager.dbh = NULL; + sql_manager->dbh = NULL; goto top; } @@ -2758,18 +2822,21 @@ SWITCH_DECLARE(void) switch_core_sqldb_start_thread(void) goto end; } - switch_cache_db_execute_sql(sql_manager.dbh, "delete from channels", NULL); - switch_cache_db_execute_sql(sql_manager.dbh, "delete from calls", NULL); + if (argc && post_connect_sql) { + for ( i = 0; i < argc; i++) { + switch_cache_db_execute_sql(sql_manager->dbh, post_connect_sql[i], NULL); + } + } } - if (!sql_manager.thread) { + if (!sql_manager->thread) { switch_threadattr_t *thd_attr; switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Starting SQL thread.\n"); - switch_threadattr_create(&thd_attr, sql_manager.memory_pool); + switch_threadattr_create(&thd_attr, sql_manager->memory_pool); switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE); switch_threadattr_priority_set(thd_attr, SWITCH_PRI_REALTIME); - switch_thread_create(&sql_manager.thread, thd_attr, switch_core_sql_thread, NULL, sql_manager.memory_pool); + switch_thread_create(&sql_manager->thread, thd_attr, func, sql_manager, sql_manager->memory_pool); } else { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "SQL thread is already running\n"); } @@ -2779,28 +2846,38 @@ SWITCH_DECLARE(void) switch_core_sqldb_start_thread(void) end: - switch_mutex_unlock(sql_manager.ctl_mutex); + switch_mutex_unlock(sql_manager->ctl_mutex); } -void switch_core_sqldb_stop(void) +void switch_sqldb_stop(switch_sql_manager_t *sql_manager) { switch_status_t st; switch_event_unbind_callback(core_event_handler); - switch_core_sqldb_stop_thread(); + switch_sqldb_stop_thread(sql_manager); - if (sql_manager.db_thread && sql_manager.db_thread_running) { - sql_manager.db_thread_running = -1; - switch_thread_join(&st, sql_manager.db_thread); + if (sql_manager->db_thread && sql_manager->db_thread_running) { + sql_manager->db_thread_running = -1; + switch_thread_join(&st, sql_manager->db_thread); } - switch_cache_db_flush_handles(); - sql_close(0); + switch_cache_db_flush_handles(sql_manager); + sql_close(sql_manager, 0); +} + +void switch_core_sqldb_stop() +{ + switch_sqldb_stop(&switch_cache_db_sql_manager); } SWITCH_DECLARE(void) switch_cache_db_status(switch_stream_handle_t *stream) +{ + _switch_cache_db_status(&switch_cache_db_sql_manager, stream); +} + +SWITCH_DECLARE(void) _switch_cache_db_status(switch_sql_manager_t *sql_manager, switch_stream_handle_t *stream) { /* return some status info suitable for the cli */ switch_cache_db_handle_t *dbh = NULL; @@ -2811,11 +2888,16 @@ SWITCH_DECLARE(void) switch_cache_db_status(switch_stream_handle_t *stream) char *pos2 = NULL; int count = 0, used = 0; - switch_mutex_lock(sql_manager.dbh_mutex); + switch_mutex_lock(sql_manager->dbh_mutex); - for (dbh = sql_manager.handle_pool; dbh; dbh = dbh->next) { - char *needle = "pass=\""; + for (dbh = sql_manager->handle_pool; dbh; dbh = dbh->next) { + char *needles[3]; time_t diff = 0; + int i = 0; + + needles[0] = "pass=\""; + needles[1] = "password="; + needles[2] = "password='"; diff = now - dbh->last_used; @@ -2828,11 +2910,26 @@ SWITCH_DECLARE(void) switch_cache_db_status(switch_stream_handle_t *stream) /* sanitize password */ memset(cleankey_str, 0, sizeof(cleankey_str)); - pos1 = strstr(dbh->name, needle) + strlen(needle); - pos2 = strstr(pos1, "\""); - strncpy(cleankey_str, dbh->name, pos1 - dbh->name); - strcpy(&cleankey_str[pos1 - dbh->name], pos2); - + for (i = 0; i < 3; i++) { + if((pos1 = strstr(dbh->name, needles[i]))) { + pos1 += strlen(needles[i]); + + if (!(pos2 = strstr(pos1, "\""))) { + if (!(pos2 = strstr(pos1, "'"))) { + if (!(pos2 = strstr(pos1, " "))) { + pos2 = pos1 + strlen(pos1); + } + } + } + strncpy(cleankey_str, dbh->name, pos1 - dbh->name); + strcpy(&cleankey_str[pos1 - dbh->name], pos2); + break; + } + } + if (i == 3) { + strncpy(cleankey_str, dbh->name, strlen(dbh->name)); + } + count++; if (dbh->use_count) { @@ -2850,7 +2947,7 @@ SWITCH_DECLARE(void) switch_cache_db_status(switch_stream_handle_t *stream) stream->write_function(stream, "%d total. %d in use.\n", count, used); - switch_mutex_unlock(sql_manager.dbh_mutex); + switch_mutex_unlock(sql_manager->dbh_mutex); } SWITCH_DECLARE(char*)switch_sql_concat(void) From 3dec8fb447973bff9bce020ac2a71a9c277a4569 Mon Sep 17 00:00:00 2001 From: Eliot Gable Date: Mon, 8 Oct 2012 20:39:09 +0000 Subject: [PATCH 129/252] we don't need to use pg's cflags --- configure.in | 2 -- 1 file changed, 2 deletions(-) diff --git a/configure.in b/configure.in index 4e036b0d81..e8ab623d7f 100644 --- a/configure.in +++ b/configure.in @@ -403,14 +403,12 @@ if test x"$enable_core_pgsql_support" = x"yes" ; then AC_PATH_PROG([PG_CONFIG], [pg_config], [no]) if test "$PG_CONFIG" != "no"; then AC_MSG_CHECKING([for PostgreSQL libraries]) - POSTGRESQL_CFLAGS="`$PG_CONFIG --cflags` -I`$PG_CONFIG --includedir`" POSTGRESQL_CXXFLAGS="`$PG_CONFIG --cppflags` -I`$PG_CONFIG --includedir`" POSTGRESQL_LDFLAGS="`$PG_CONFIG --ldflags` -L`$PG_CONFIG --libdir` -lpq" POSTGRESQL_VERSION=`$PG_CONFIG --version | sed -e 's#PostgreSQL ##'` AC_DEFINE([SWITCH_HAVE_PGSQL], [1], [Define to 1 if PostgreSQL libraries are available]) AC_CHECK_LIB([pq], [PQgetvalue],, AC_MSG_ERROR([no usable libpq; please install PostgreSQL devel package or equivalent])) AC_MSG_RESULT([yes]) - SWITCH_AM_CFLAGS="$POSTGRESQL_CFLAGS $SWITCH_AM_CFLAGS" SWITCH_AM_CXXFLAGS="$POSTGRESQL_CXXFLAGS $SWITCH_AM_CXXFLAGS" SWITCH_AM_LDFLAGS="$POSTGRESQL_LDFLAGS $SWITCH_AM_LDFLAGS" else From 7e28946ba436c3bdf9eede37365fe8f255826a16 Mon Sep 17 00:00:00 2001 From: Eliot Gable Date: Mon, 8 Oct 2012 20:56:05 +0000 Subject: [PATCH 130/252] Make error message slightly more verbose. --- src/switch_core_sqldb.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/switch_core_sqldb.c b/src/switch_core_sqldb.c index 23b08ace75..2888131698 100644 --- a/src/switch_core_sqldb.c +++ b/src/switch_core_sqldb.c @@ -607,6 +607,7 @@ static switch_status_t switch_cache_db_execute_sql_real(switch_cache_db_handle_t switch_status_t status = SWITCH_STATUS_FALSE; char *errmsg = NULL; char *tmp = NULL; + char *type = NULL; switch_mutex_t *io_mutex = dbh->io_mutex; if (io_mutex) switch_mutex_lock(io_mutex); @@ -618,17 +619,20 @@ static switch_status_t switch_cache_db_execute_sql_real(switch_cache_db_handle_t switch (dbh->type) { case SCDB_TYPE_PGSQL: { + type = "PGSQL"; status = switch_pgsql_handle_exec(dbh->native_handle.pgsql_dbh, sql, &errmsg); } break; case SCDB_TYPE_ODBC: { + type = "ODBC"; status = switch_odbc_handle_exec(dbh->native_handle.odbc_dbh, sql, NULL, &errmsg); } break; case SCDB_TYPE_CORE_DB: { int ret = switch_core_db_exec(dbh->native_handle.core_db_dbh, sql, NULL, NULL, &errmsg); + type = "NATIVE"; if (ret == SWITCH_CORE_DB_OK) { status = SWITCH_STATUS_SUCCESS; @@ -645,7 +649,7 @@ static switch_status_t switch_cache_db_execute_sql_real(switch_cache_db_handle_t if (errmsg) { if (!switch_stristr("already exists", errmsg) && !switch_stristr("duplicate key name", errmsg)) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "SQL ERR [%s]\n%s\n", errmsg, sql); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "%s SQL ERR [%s]\n%s\n", (type ? type : "Unknown"), errmsg, sql); } if (err) { *err = errmsg; From dc1477e5750f897047005008b624903f5cf0c37f Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Mon, 8 Oct 2012 13:08:05 -0500 Subject: [PATCH 131/252] fix build without pgsql --- src/switch_pgsql.c | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/src/switch_pgsql.c b/src/switch_pgsql.c index ead39a7e9f..1094aee20b 100644 --- a/src/switch_pgsql.c +++ b/src/switch_pgsql.c @@ -122,11 +122,9 @@ SWITCH_DECLARE(switch_pgsql_status_t) switch_pgsql_handle_disconnect(switch_pgsq #endif } - -#ifdef SWITCH_HAVE_PGSQL - SWITCH_DECLARE(switch_pgsql_status_t) switch_pgsql_send_query(switch_pgsql_handle_t *handle, const char* sql) { +#ifdef SWITCH_HAVE_PGSQL char *err_str; if (!PQsendQuery(handle->con, sql)) { @@ -139,14 +137,16 @@ SWITCH_DECLARE(switch_pgsql_status_t) switch_pgsql_send_query(switch_pgsql_handl return SWITCH_PGSQL_SUCCESS; error: +#endif return SWITCH_PGSQL_FAIL; } SWITCH_DECLARE(switch_pgsql_status_t) switch_pgsql_cancel_real(const char *file, const char *func, int line, switch_pgsql_handle_t *handle) { + switch_pgsql_status_t ret = SWITCH_PGSQL_SUCCESS; +#ifdef SWITCH_HAVE_PGSQL char err_buf[256]; PGcancel *cancel = NULL; - switch_pgsql_status_t ret = SWITCH_PGSQL_SUCCESS; memset(err_buf, 0, 256); cancel = PQgetCancel(handle->con); @@ -155,12 +155,14 @@ SWITCH_DECLARE(switch_pgsql_status_t) switch_pgsql_cancel_real(const char *file, ret = SWITCH_PGSQL_FAIL; } PQfreeCancel(cancel); +#endif return ret; } SWITCH_DECLARE(switch_pgsql_status_t) switch_pgsql_next_result_timed(switch_pgsql_handle_t *handle, switch_pgsql_result_t **result_out, int msec) { +#ifdef SWITCH_HAVE_PGSQL switch_pgsql_result_t *res; switch_time_t start; switch_time_t ctime; @@ -273,11 +275,14 @@ SWITCH_DECLARE(switch_pgsql_status_t) switch_pgsql_next_result_timed(switch_pgsq return SWITCH_PGSQL_SUCCESS; error: +#endif return SWITCH_PGSQL_FAIL; } SWITCH_DECLARE(void) switch_pgsql_free_result(switch_pgsql_result_t **result) { +#ifdef SWITCH_HAVE_PGSQL + if (!*result) { return; } @@ -287,10 +292,14 @@ SWITCH_DECLARE(void) switch_pgsql_free_result(switch_pgsql_result_t **result) } free(*result); *result = NULL; +#else + return; +#endif } SWITCH_DECLARE(switch_pgsql_status_t) switch_pgsql_finish_results_real(const char* file, const char* func, int line, switch_pgsql_handle_t *handle) { +#ifdef SWITCH_HAVE_PGSQL switch_pgsql_result_t *res = NULL; switch_pgsql_status_t final_status = SWITCH_PGSQL_SUCCESS; int done = 0; @@ -304,8 +313,12 @@ SWITCH_DECLARE(switch_pgsql_status_t) switch_pgsql_finish_results_real(const cha switch_pgsql_free_result(&res); } while (!done); return final_status; +#else + return SWITCH_PGSQL_FAIL; +#endif } +#ifdef SWITCH_HAVE_PG static int db_is_up(switch_pgsql_handle_t *handle) { int ret = 0; From 93f4c0f69844b5d3718b40c41aa6f3cb6f5e0492 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Mon, 8 Oct 2012 13:28:01 -0500 Subject: [PATCH 132/252] move sofia locking contention outside of cache_db handle management --- src/mod/endpoints/mod_sofia/sofia_glue.c | 60 +++++++++++------------- src/mod/endpoints/mod_sofia/sofia_reg.c | 54 ++++++++++----------- 2 files changed, 51 insertions(+), 63 deletions(-) diff --git a/src/mod/endpoints/mod_sofia/sofia_glue.c b/src/mod/endpoints/mod_sofia/sofia_glue.c index a39a8e9e71..0e7ed4db0a 100644 --- a/src/mod/endpoints/mod_sofia/sofia_glue.c +++ b/src/mod/endpoints/mod_sofia/sofia_glue.c @@ -6394,19 +6394,17 @@ void sofia_glue_actually_execute_sql_trans(sofia_profile_t *profile, char *sql, { switch_cache_db_handle_t *dbh = NULL; + if (!(dbh = sofia_glue_get_db_handle(profile))) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error Opening DB\n"); + return; + } + if (mutex) { switch_mutex_lock(mutex); } - if (!(dbh = sofia_glue_get_db_handle(profile))) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error Opening DB\n"); - goto end; - } - switch_cache_db_persistant_execute_trans(dbh, sql, 1); - end: - switch_cache_db_release_db_handle(&dbh); if (mutex) { @@ -6419,29 +6417,27 @@ void sofia_glue_actually_execute_sql(sofia_profile_t *profile, char *sql, switch switch_cache_db_handle_t *dbh = NULL; char *err = NULL; + if (!(dbh = sofia_glue_get_db_handle(profile))) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error Opening DB\n"); + return; + } + if (mutex) { switch_mutex_lock(mutex); } - if (!(dbh = sofia_glue_get_db_handle(profile))) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error Opening DB\n"); - goto end; - } - switch_cache_db_execute_sql(dbh, sql, &err); + if (mutex) { + switch_mutex_unlock(mutex); + } + if (err) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "SQL ERR: [%s]\n%s\n", err, sql); free(err); } - end: - switch_cache_db_release_db_handle(&dbh); - - if (mutex) { - switch_mutex_unlock(mutex); - } } switch_bool_t sofia_glue_execute_sql_callback(sofia_profile_t *profile, @@ -6451,30 +6447,28 @@ switch_bool_t sofia_glue_execute_sql_callback(sofia_profile_t *profile, char *errmsg = NULL; switch_cache_db_handle_t *dbh = NULL; + if (!(dbh = sofia_glue_get_db_handle(profile))) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error Opening DB\n"); + return ret; + } + if (mutex) { switch_mutex_lock(mutex); } - if (!(dbh = sofia_glue_get_db_handle(profile))) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error Opening DB\n"); - goto end; - } - switch_cache_db_execute_sql_callback(dbh, sql, callback, pdata, &errmsg); + if (mutex) { + switch_mutex_unlock(mutex); + } + if (errmsg) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "SQL ERR: [%s] %s\n", sql, errmsg); free(errmsg); } - end: - switch_cache_db_release_db_handle(&dbh); - if (mutex) { - switch_mutex_unlock(mutex); - } - return ret; } @@ -6495,15 +6489,15 @@ char *sofia_glue_execute_sql2str(sofia_profile_t *profile, switch_mutex_t *mutex ret = switch_cache_db_execute_sql2str(dbh, sql, resbuf, len, &err); + if (mutex) { + switch_mutex_unlock(mutex); + } + if (err) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "SQL ERR: [%s]\n%s\n", err, sql); free(err); } - if (mutex) { - switch_mutex_unlock(mutex); - } - switch_cache_db_release_db_handle(&dbh); return ret; diff --git a/src/mod/endpoints/mod_sofia/sofia_reg.c b/src/mod/endpoints/mod_sofia/sofia_reg.c index 1142534401..98299a784b 100644 --- a/src/mod/endpoints/mod_sofia/sofia_reg.c +++ b/src/mod/endpoints/mod_sofia/sofia_reg.c @@ -690,9 +690,8 @@ void sofia_reg_expire_call_id(sofia_profile_t *profile, const char *call_id, int ",user_agent,server_user,server_host,profile_name,network_ip" ",%d from sip_registrations where call_id='%q' %s", reboot, call_id, sqlextra); - switch_mutex_lock(profile->ireg_mutex); - sofia_glue_execute_sql_callback(profile, NULL, sql, sofia_reg_del_callback, profile); - switch_mutex_unlock(profile->ireg_mutex); + + sofia_glue_execute_sql_callback(profile, profile->ireg_mutex, sql, sofia_reg_del_callback, profile); switch_safe_free(sql); sql = switch_mprintf("delete from sip_registrations where call_id='%q' %s", call_id, sqlextra); @@ -708,7 +707,7 @@ void sofia_reg_check_expire(sofia_profile_t *profile, time_t now, int reboot) { char sql[1024]; - switch_mutex_lock(profile->ireg_mutex); + if (now) { switch_snprintf(sql, sizeof(sql), "select call_id,sip_user,sip_host,contact,status,rpid,expires" @@ -719,7 +718,7 @@ void sofia_reg_check_expire(sofia_profile_t *profile, time_t now, int reboot) ",user_agent,server_user,server_host,profile_name,network_ip" ",%d from sip_registrations where expires > 0", reboot); } - sofia_glue_execute_sql_callback(profile, NULL, sql, sofia_reg_del_callback, profile); + sofia_glue_execute_sql_callback(profile, profile->ireg_mutex, sql, sofia_reg_del_callback, profile); if (now) { switch_snprintfv(sql, sizeof(sql), "delete from sip_registrations where expires > 0 and expires <= %ld and hostname='%q'", (long) now, mod_sofia_globals.hostname); @@ -727,7 +726,7 @@ void sofia_reg_check_expire(sofia_profile_t *profile, time_t now, int reboot) switch_snprintfv(sql, sizeof(sql), "delete from sip_registrations where expires > 0 and hostname='%q'", mod_sofia_globals.hostname); } - sofia_glue_actually_execute_sql(profile, sql, NULL); + sofia_glue_actually_execute_sql(profile, sql, profile->ireg_mutex); @@ -735,12 +734,12 @@ void sofia_reg_check_expire(sofia_profile_t *profile, time_t now, int reboot) switch_snprintfv(sql, sizeof(sql), "select call_id from sip_shared_appearance_dialogs where hostname='%q' " "and profile_name='%s' and expires <= %ld", mod_sofia_globals.hostname, profile->name, (long) now); - sofia_glue_execute_sql_callback(profile, NULL, sql, sofia_sla_dialog_del_callback, profile); + sofia_glue_execute_sql_callback(profile, profile->ireg_mutex, sql, sofia_sla_dialog_del_callback, profile); switch_snprintfv(sql, sizeof(sql), "delete from sip_shared_appearance_dialogs where expires > 0 and hostname='%q' and expires <= %ld", mod_sofia_globals.hostname, (long) now); - sofia_glue_actually_execute_sql(profile, sql, NULL); + sofia_glue_actually_execute_sql(profile, sql, profile->ireg_mutex); } @@ -751,7 +750,7 @@ void sofia_reg_check_expire(sofia_profile_t *profile, time_t now, int reboot) switch_snprintfv(sql, sizeof(sql), "delete from sip_presence where expires > 0 and hostname='%q'", mod_sofia_globals.hostname); } - sofia_glue_actually_execute_sql(profile, sql, NULL); + sofia_glue_actually_execute_sql(profile, sql, profile->ireg_mutex); if (now) { switch_snprintfv(sql, sizeof(sql), "delete from sip_authentication where expires > 0 and expires <= %ld and hostname='%q'", @@ -760,7 +759,7 @@ void sofia_reg_check_expire(sofia_profile_t *profile, time_t now, int reboot) switch_snprintfv(sql, sizeof(sql), "delete from sip_authentication where expires > 0 and hostname='%q'", mod_sofia_globals.hostname); } - sofia_glue_actually_execute_sql(profile, sql, NULL); + sofia_glue_actually_execute_sql(profile, sql, profile->ireg_mutex); sofia_presence_check_subscriptions(profile, now); @@ -771,7 +770,7 @@ void sofia_reg_check_expire(sofia_profile_t *profile, time_t now, int reboot) switch_snprintfv(sql, sizeof(sql), "delete from sip_dialogs where expires >= -1 and hostname='%q'", mod_sofia_globals.hostname); } - sofia_glue_actually_execute_sql(profile, sql, NULL); + sofia_glue_actually_execute_sql(profile, sql, profile->ireg_mutex); if (now) { @@ -781,7 +780,7 @@ void sofia_reg_check_expire(sofia_profile_t *profile, time_t now, int reboot) " from sip_registrations where hostname='%s' and " "profile_name='%s'", mod_sofia_globals.hostname, profile->name); - sofia_glue_execute_sql_callback(profile, NULL, sql, sofia_reg_nat_callback, profile); + sofia_glue_execute_sql_callback(profile, profile->ireg_mutex, sql, sofia_reg_nat_callback, profile); } else if (sofia_test_pflag(profile, PFLAG_NAT_OPTIONS_PING)) { switch_snprintf(sql, sizeof(sql), "select call_id,sip_user,sip_host,contact,status,rpid," "expires,user_agent,server_user,server_host,profile_name" @@ -789,12 +788,10 @@ void sofia_reg_check_expire(sofia_profile_t *profile, time_t now, int reboot) "or contact like '%%fs_nat=yes%%') and hostname='%s' " "and profile_name='%s'", mod_sofia_globals.hostname, profile->name); - sofia_glue_execute_sql_callback(profile, NULL, sql, sofia_reg_nat_callback, profile); + sofia_glue_execute_sql_callback(profile, profile->ireg_mutex, sql, sofia_reg_nat_callback, profile); } } - switch_mutex_unlock(profile->ireg_mutex); - } @@ -837,9 +834,9 @@ void sofia_reg_check_call_id(sofia_profile_t *profile, const char *call_id) ",user_agent,server_user,server_host,profile_name,network_ip" " from sip_registrations where call_id='%q' %s", call_id, sqlextra); - switch_mutex_lock(profile->ireg_mutex); - sofia_glue_execute_sql_callback(profile, NULL, sql, sofia_reg_check_callback, profile); - switch_mutex_unlock(profile->ireg_mutex); + + sofia_glue_execute_sql_callback(profile, profile->ireg_mutex, sql, sofia_reg_check_callback, profile); + switch_safe_free(sql); switch_safe_free(sqlextra); @@ -851,31 +848,28 @@ void sofia_reg_check_sync(sofia_profile_t *profile) { char sql[1024]; - switch_mutex_lock(profile->ireg_mutex); switch_snprintf(sql, sizeof(sql), "select call_id,sip_user,sip_host,contact,status,rpid,expires" ",user_agent,server_user,server_host,profile_name,network_ip" " from sip_registrations where expires > 0"); - sofia_glue_execute_sql_callback(profile, NULL, sql, sofia_reg_del_callback, profile); + sofia_glue_execute_sql_callback(profile, profile->ireg_mutex, sql, sofia_reg_del_callback, profile); switch_snprintfv(sql, sizeof(sql), "delete from sip_registrations where expires > 0 and hostname='%q'", mod_sofia_globals.hostname); - sofia_glue_actually_execute_sql(profile, sql, NULL); + sofia_glue_actually_execute_sql(profile, sql, profile->ireg_mutex); switch_snprintfv(sql, sizeof(sql), "delete from sip_presence where expires > 0 and hostname='%q'", mod_sofia_globals.hostname); - sofia_glue_actually_execute_sql(profile, sql, NULL); + sofia_glue_actually_execute_sql(profile, sql, profile->ireg_mutex); switch_snprintfv(sql, sizeof(sql), "delete from sip_authentication where expires > 0 and hostname='%q'", mod_sofia_globals.hostname); - sofia_glue_actually_execute_sql(profile, sql, NULL); + sofia_glue_actually_execute_sql(profile, sql, profile->ireg_mutex); switch_snprintfv(sql, sizeof(sql), "delete from sip_subscriptions where expires >= -1 and hostname='%q'", mod_sofia_globals.hostname); - sofia_glue_actually_execute_sql(profile, sql, NULL); + sofia_glue_actually_execute_sql(profile, sql, profile->ireg_mutex); switch_snprintfv(sql, sizeof(sql), "delete from sip_dialogs where expires >= -1 and hostname='%q'", mod_sofia_globals.hostname); - sofia_glue_actually_execute_sql(profile, sql, NULL); - - switch_mutex_unlock(profile->ireg_mutex); + sofia_glue_actually_execute_sql(profile, sql, profile->ireg_mutex); } @@ -1558,13 +1552,13 @@ uint8_t sofia_reg_handle_register(nua_t *nua, sofia_profile_t *profile, nua_hand } else { sql = switch_mprintf("delete from sip_registrations where sip_user='%q' and sip_host='%q'", to_user, reg_host); } - switch_mutex_lock(profile->ireg_mutex); + sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE); } else { char buf[32] = ""; sql = switch_mprintf("select count(*) from sip_registrations where sip_user='%q' and sip_host='%q' and contact='%q'", to_user, reg_host, contact_str); - switch_mutex_lock(profile->ireg_mutex); + sofia_glue_execute_sql2str(profile, profile->ireg_mutex, sql, buf, sizeof(buf)); switch_safe_free(sql); @@ -1616,7 +1610,7 @@ uint8_t sofia_reg_handle_register(nua_t *nua, sofia_profile_t *profile, nua_hand sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE); } - switch_mutex_unlock(profile->ireg_mutex); + if (switch_event_create_subclass(&s_event, SWITCH_EVENT_CUSTOM, MY_EVENT_REGISTER) == SWITCH_STATUS_SUCCESS) { switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "profile-name", profile->name); From 1215ee4fe1533f4fe0f4c885297e3f8bc6652e39 Mon Sep 17 00:00:00 2001 From: Brian West Date: Mon, 8 Oct 2012 17:19:17 -0500 Subject: [PATCH 133/252] FS-4699 --resolve --- conf/vanilla/vars.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/conf/vanilla/vars.xml b/conf/vanilla/vars.xml index 907c6f1015..f6b3431e9c 100644 --- a/conf/vanilla/vars.xml +++ b/conf/vanilla/vars.xml @@ -212,6 +212,7 @@ + From 4ddc2f96d4a59c469e90aa72f1f6c4fb15af7b2e Mon Sep 17 00:00:00 2001 From: Michael Jerris Date: Mon, 8 Oct 2012 18:59:14 -0400 Subject: [PATCH 134/252] add new files --- w32/Library/FreeSwitchCore.2008.vcproj | 8 ++++++++ w32/Library/FreeSwitchCore.2010.vcxproj | 4 +++- w32/Library/FreeSwitchCore.2010.vcxproj.filters | 8 +++++++- w32/Library/FreeSwitchCore.vcproj | 8 ++++++++ 4 files changed, 26 insertions(+), 2 deletions(-) diff --git a/w32/Library/FreeSwitchCore.2008.vcproj b/w32/Library/FreeSwitchCore.2008.vcproj index e4303b904d..624e125542 100644 --- a/w32/Library/FreeSwitchCore.2008.vcproj +++ b/w32/Library/FreeSwitchCore.2008.vcproj @@ -854,6 +854,10 @@ RelativePath="..\..\src\switch_odbc.c" > + + @@ -1592,6 +1596,10 @@ RelativePath="..\..\src\include\switch_odbc.h" > + + diff --git a/w32/Library/FreeSwitchCore.2010.vcxproj b/w32/Library/FreeSwitchCore.2010.vcxproj index 5e466c3f10..89d3ed68f0 100644 --- a/w32/Library/FreeSwitchCore.2010.vcxproj +++ b/w32/Library/FreeSwitchCore.2010.vcxproj @@ -419,6 +419,7 @@ if not exist "$(OutDir)htdocs" xcopy "$(SolutionDir)htdocs\*.*" "$(OutDir)htdocs 4389;4127;%(DisableSpecificWarnings) + @@ -738,6 +739,7 @@ if not exist "$(OutDir)htdocs" xcopy "$(SolutionDir)htdocs\*.*" "$(OutDir)htdocs + @@ -834,4 +836,4 @@ if not exist "$(OutDir)htdocs" xcopy "$(SolutionDir)htdocs\*.*" "$(OutDir)htdocs - \ No newline at end of file + diff --git a/w32/Library/FreeSwitchCore.2010.vcxproj.filters b/w32/Library/FreeSwitchCore.2010.vcxproj.filters index 9766295d13..7283c0b6ad 100644 --- a/w32/Library/FreeSwitchCore.2010.vcxproj.filters +++ b/w32/Library/FreeSwitchCore.2010.vcxproj.filters @@ -160,6 +160,9 @@ Source Files + + Source Files + Source Files @@ -285,6 +288,9 @@ Header Files + + Header Files + Header Files @@ -342,4 +348,4 @@ {a1474195-5783-4c77-977f-59657b38fd01} - \ No newline at end of file + diff --git a/w32/Library/FreeSwitchCore.vcproj b/w32/Library/FreeSwitchCore.vcproj index 52e5406457..137c455d49 100644 --- a/w32/Library/FreeSwitchCore.vcproj +++ b/w32/Library/FreeSwitchCore.vcproj @@ -534,6 +534,10 @@ RelativePath="..\..\src\switch_odbc.c" > + + @@ -1032,6 +1036,10 @@ RelativePath="..\..\src\include\switch_odbc.h" > + + From 21d240b28cea006cff95ecb1bee1d6d6e6142334 Mon Sep 17 00:00:00 2001 From: Michael Jerris Date: Mon, 8 Oct 2012 19:05:12 -0400 Subject: [PATCH 135/252] windows build --- src/switch_pgsql.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/switch_pgsql.c b/src/switch_pgsql.c index fc02ab73d5..27550afe67 100644 --- a/src/switch_pgsql.c +++ b/src/switch_pgsql.c @@ -31,9 +31,9 @@ */ #include -#include #ifdef SWITCH_HAVE_PGSQL +#include #include #include From 1ad45f70091b3e0762b14328dd590869bad3a153 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Mon, 8 Oct 2012 15:57:44 -0500 Subject: [PATCH 136/252] revert e08f9ada73cb7a39477c4fe255fe28af7c6bfa92 --- src/include/switch_core.h | 31 +-- src/include/switch_types.h | 5 - src/switch_core.c | 2 +- src/switch_core_sqldb.c | 543 +++++++++++++++---------------------- 4 files changed, 230 insertions(+), 351 deletions(-) diff --git a/src/include/switch_core.h b/src/include/switch_core.h index d6da431dfc..73607926fa 100644 --- a/src/include/switch_core.h +++ b/src/include/switch_core.h @@ -2193,11 +2193,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_chat_send(const char *dest_proto, sw SWITCH_DECLARE(switch_status_t) switch_core_chat_deliver(const char *dest_proto, switch_event_t **message_event); SWITCH_DECLARE(switch_status_t) switch_ivr_preprocess_session(switch_core_session_t *session, const char *cmds); -SWITCH_DECLARE(void) switch_sqldb_stop_thread(switch_sql_manager_t *sql_manager); -#define switch_core_sqldb_stop_thread() switch_sqldb_stop_thread(&switch_cache_db_sql_manager) - -SWITCH_DECLARE(void) switch_sqldb_start_thread(switch_sql_manager_t *sql_manager, void *(SWITCH_THREAD_FUNC * func) (switch_thread_t *, void *), - char **post_connect_sql, int argc); +SWITCH_DECLARE(void) switch_core_sqldb_stop_thread(void); SWITCH_DECLARE(void) switch_core_sqldb_start_thread(void); ///\} @@ -2244,6 +2240,8 @@ typedef union { switch_cache_db_pgsql_options_t pgsql_options; } switch_cache_db_connection_options_t; +struct switch_cache_db_handle; +typedef struct switch_cache_db_handle switch_cache_db_handle_t; static inline const char *switch_cache_db_type_name(switch_cache_db_handle_type_t type) { @@ -2283,9 +2281,7 @@ SWITCH_DECLARE(void) switch_cache_db_dismiss_db_handle(switch_cache_db_handle_t other threads until the allocating thread actually terminates. \param [in] The handle */ -SWITCH_DECLARE(void) _switch_cache_db_release_db_handle(switch_sql_manager_t *sql_manager, switch_cache_db_handle_t ** dbh); SWITCH_DECLARE(void) switch_cache_db_release_db_handle(switch_cache_db_handle_t ** dbh); - /*! \brief Gets a new cached handle from the pool, potentially creating a new connection. The connection is bound to the thread until it (the thread) terminates unless @@ -2294,19 +2290,12 @@ SWITCH_DECLARE(void) switch_cache_db_release_db_handle(switch_cache_db_handle_t \param [in] type - ODBC or SQLLITE \param [in] connection_options (userid, password, etc) */ -SWITCH_DECLARE(switch_status_t) __switch_cache_db_get_db_handle(switch_sql_manager_t *sql_manager, - switch_cache_db_handle_t ** dbh, - switch_cache_db_handle_type_t type, - switch_cache_db_connection_options_t *connection_options, - const char *file, const char *func, int line); SWITCH_DECLARE(switch_status_t) _switch_cache_db_get_db_handle(switch_cache_db_handle_t ** dbh, switch_cache_db_handle_type_t type, switch_cache_db_connection_options_t *connection_options, const char *file, const char *func, int line); #define switch_cache_db_get_db_handle(_a, _b, _c) _switch_cache_db_get_db_handle(_a, _b, _c, __FILE__, __SWITCH_FUNC__, __LINE__) - - /*! \brief Executes the sql and returns the result as a string \param [in] dbh The handle @@ -2341,21 +2330,15 @@ SWITCH_DECLARE(switch_status_t) switch_cache_db_execute_sql_callback(switch_cach */ SWITCH_DECLARE(int) switch_cache_db_affected_rows(switch_cache_db_handle_t *dbh); -extern switch_sql_manager_t switch_cache_db_sql_manager; /*! \brief Provides some feedback as to the status of the db connection pool \param [in] stream stream for status */ -SWITCH_DECLARE(void) _switch_cache_db_status(switch_sql_manager_t *sql_manager, switch_stream_handle_t *stream); SWITCH_DECLARE(void) switch_cache_db_status(switch_stream_handle_t *stream); -SWITCH_DECLARE(switch_status_t) __switch_core_db_handle(switch_sql_manager_t *sql_manager, switch_cache_db_handle_t ** dbh, const char *file, const char *func, int line); SWITCH_DECLARE(switch_status_t) _switch_core_db_handle(switch_cache_db_handle_t ** dbh, const char *file, const char *func, int line); #define switch_core_db_handle(_a) _switch_core_db_handle(_a, __FILE__, __SWITCH_FUNC__, __LINE__) -SWITCH_DECLARE(switch_status_t) _switch_core_recovery_db_handle(switch_sql_manager_t *sql_manager, switch_cache_db_handle_t ** dbh, const char *file, const char *func, int line); -#define switch_core_recovery_db_handle(_a) _switch_core_recovery_db_handle(&switch_cache_db_sql_manager, _a, __FILE__, __SWITCH_FUNC__, __LINE__) - -SWITCH_DECLARE(switch_status_t) _switch_core_persist_db_handle(switch_sql_manager_t *sql_manager, switch_cache_db_handle_t ** dbh, const char *file, const char *func, int line); -#define switch_core_persist_db_handle(_a) _switch_core_persist_db_handle(&switch_cache_db_sql_manager, _a, __FILE__, __SWITCH_FUNC__, __LINE__) +SWITCH_DECLARE(switch_status_t) _switch_core_recovery_db_handle(switch_cache_db_handle_t ** dbh, const char *file, const char *func, int line); +#define switch_core_recovery_db_handle(_a) _switch_core_recovery_db_handle(_a, __FILE__, __SWITCH_FUNC__, __LINE__) SWITCH_DECLARE(switch_bool_t) switch_cache_db_test_reactive(switch_cache_db_handle_t *db, const char *test_sql, const char *drop_sql, const char *reactive_sql); @@ -2364,9 +2347,7 @@ SWITCH_DECLARE(switch_status_t) switch_cache_db_persistant_execute_trans(switch_ SWITCH_DECLARE(void) switch_core_set_signal_handlers(void); SWITCH_DECLARE(uint32_t) switch_core_debug_level(void); -SWITCH_DECLARE(void) switch_cache_db_flush_handles(switch_sql_manager_t *sql_manager); -#define switch_core_cache_db_flush_handles() switch_cache_db_flush_handles(&switch_cache_db_sql_manager) - +SWITCH_DECLARE(void) switch_cache_db_flush_handles(void); SWITCH_DECLARE(const char *) switch_core_banner(void); SWITCH_DECLARE(switch_bool_t) switch_core_session_in_thread(switch_core_session_t *session); SWITCH_DECLARE(uint32_t) switch_default_ptime(const char *name, uint32_t number); diff --git a/src/include/switch_types.h b/src/include/switch_types.h index ddd66a0a4e..6f77f32ef4 100644 --- a/src/include/switch_types.h +++ b/src/include/switch_types.h @@ -1836,11 +1836,6 @@ typedef struct switch_odbc_handle switch_odbc_handle_t; typedef struct switch_pgsql_handle switch_pgsql_handle_t; typedef struct switch_pgsql_result switch_pgsql_result_t; -struct switch_cache_db_handle; -typedef struct switch_cache_db_handle switch_cache_db_handle_t; -struct switch_sql_manager; -typedef struct switch_sql_manager switch_sql_manager_t; - typedef struct switch_io_routines switch_io_routines_t; typedef struct switch_speech_handle switch_speech_handle_t; typedef struct switch_asr_handle switch_asr_handle_t; diff --git a/src/switch_core.c b/src/switch_core.c index 9c525a6c1e..8e1a6567d7 100644 --- a/src/switch_core.c +++ b/src/switch_core.c @@ -2260,7 +2260,7 @@ SWITCH_DECLARE(int32_t) switch_core_session_ctl(switch_session_ctl_t cmd, void * switch_time_calibrate_clock(); break; case SCSC_FLUSH_DB_HANDLES: - switch_core_cache_db_flush_handles(); + switch_cache_db_flush_handles(); break; case SCSC_SEND_SIGHUP: handle_SIGHUP(1); diff --git a/src/switch_core_sqldb.c b/src/switch_core_sqldb.c index 2888131698..b679baab0c 100644 --- a/src/switch_core_sqldb.c +++ b/src/switch_core_sqldb.c @@ -26,7 +26,6 @@ * Anthony Minessale II * Michael Jerris * Paul D. Tinsley - * Eliot Gable * * * switch_core_sqldb.c -- Main Core Library (statistics tracker) @@ -56,7 +55,7 @@ struct switch_cache_db_handle { struct switch_cache_db_handle *next; }; -struct switch_sql_manager { +static struct { switch_cache_db_handle_t *event_db; switch_queue_t *sql_queue[2]; switch_memory_pool_t *memory_pool; @@ -74,9 +73,7 @@ struct switch_sql_manager { uint32_t total_handles; uint32_t total_used_handles; switch_cache_db_handle_t *dbh; -}; - -switch_sql_manager_t switch_cache_db_sql_manager; +} sql_manager; static switch_cache_db_handle_t *create_handle(switch_cache_db_handle_type_t type) @@ -93,11 +90,11 @@ static switch_cache_db_handle_t *create_handle(switch_cache_db_handle_type_t typ return new_dbh; } -static void add_handle(switch_sql_manager_t *sql_manager, switch_cache_db_handle_t *dbh, const char *db_str, const char *db_callsite_str, const char *thread_str) +static void add_handle(switch_cache_db_handle_t *dbh, const char *db_str, const char *db_callsite_str, const char *thread_str) { switch_ssize_t hlen = -1; - switch_mutex_lock(sql_manager->dbh_mutex); + switch_mutex_lock(sql_manager.dbh_mutex); switch_set_string(dbh->creator, db_callsite_str); @@ -106,37 +103,37 @@ static void add_handle(switch_sql_manager_t *sql_manager, switch_cache_db_handle dbh->thread_hash = switch_ci_hashfunc_default(thread_str, &hlen); dbh->use_count++; - sql_manager->total_used_handles++; - dbh->next = sql_manager->handle_pool; + sql_manager.total_used_handles++; + dbh->next = sql_manager.handle_pool; - sql_manager->handle_pool = dbh; - sql_manager->total_handles++; + sql_manager.handle_pool = dbh; + sql_manager.total_handles++; switch_mutex_lock(dbh->mutex); - switch_mutex_unlock(sql_manager->dbh_mutex); + switch_mutex_unlock(sql_manager.dbh_mutex); } -static void del_handle(switch_sql_manager_t *sql_manager, switch_cache_db_handle_t *dbh) +static void del_handle(switch_cache_db_handle_t *dbh) { switch_cache_db_handle_t *dbh_ptr, *last = NULL; - switch_mutex_lock(sql_manager->dbh_mutex); - for (dbh_ptr = sql_manager->handle_pool; dbh_ptr; dbh_ptr = dbh_ptr->next) { + switch_mutex_lock(sql_manager.dbh_mutex); + for (dbh_ptr = sql_manager.handle_pool; dbh_ptr; dbh_ptr = dbh_ptr->next) { if (dbh_ptr == dbh) { if (last) { last->next = dbh_ptr->next; } else { - sql_manager->handle_pool = dbh_ptr->next; + sql_manager.handle_pool = dbh_ptr->next; } - sql_manager->total_handles--; + sql_manager.total_handles--; break; } last = dbh_ptr; } - switch_mutex_unlock(sql_manager->dbh_mutex); + switch_mutex_unlock(sql_manager.dbh_mutex); } -static switch_cache_db_handle_t *get_handle(switch_sql_manager_t *sql_manager, const char *db_str, const char *user_str, const char *thread_str) +static switch_cache_db_handle_t *get_handle(const char *db_str, const char *user_str, const char *thread_str) { switch_ssize_t hlen = -1; unsigned long hash = 0, thread_hash = 0; @@ -145,9 +142,9 @@ static switch_cache_db_handle_t *get_handle(switch_sql_manager_t *sql_manager, c hash = switch_ci_hashfunc_default(db_str, &hlen); thread_hash = switch_ci_hashfunc_default(thread_str, &hlen); - switch_mutex_lock(sql_manager->dbh_mutex); + switch_mutex_lock(sql_manager.dbh_mutex); - for (dbh_ptr = sql_manager->handle_pool; dbh_ptr; dbh_ptr = dbh_ptr->next) { + for (dbh_ptr = sql_manager.handle_pool; dbh_ptr; dbh_ptr = dbh_ptr->next) { if (dbh_ptr->thread_hash == thread_hash && dbh_ptr->hash == hash && !switch_test_flag(dbh_ptr, CDF_PRUNE) && switch_mutex_trylock(dbh_ptr->mutex) == SWITCH_STATUS_SUCCESS) { r = dbh_ptr; @@ -155,7 +152,7 @@ static switch_cache_db_handle_t *get_handle(switch_sql_manager_t *sql_manager, c } if (!r) { - for (dbh_ptr = sql_manager->handle_pool; dbh_ptr; dbh_ptr = dbh_ptr->next) { + for (dbh_ptr = sql_manager.handle_pool; dbh_ptr; dbh_ptr = dbh_ptr->next) { if (dbh_ptr->hash == hash && !dbh_ptr->use_count && !switch_test_flag(dbh_ptr, CDF_PRUNE) && switch_mutex_trylock(dbh_ptr->mutex) == SWITCH_STATUS_SUCCESS) { r = dbh_ptr; @@ -166,13 +163,13 @@ static switch_cache_db_handle_t *get_handle(switch_sql_manager_t *sql_manager, c if (r) { r->use_count++; - sql_manager->total_used_handles++; + sql_manager.total_used_handles++; r->hash = switch_ci_hashfunc_default(db_str, &hlen); r->thread_hash = thread_hash; switch_set_string(r->last_user, user_str); } - switch_mutex_unlock(sql_manager->dbh_mutex); + switch_mutex_unlock(sql_manager.dbh_mutex); return r; @@ -184,16 +181,11 @@ static switch_cache_db_handle_t *get_handle(switch_sql_manager_t *sql_manager, c \brief Open the default system database */ SWITCH_DECLARE(switch_status_t) _switch_core_db_handle(switch_cache_db_handle_t **dbh, const char *file, const char *func, int line) -{ - return __switch_core_db_handle(&switch_cache_db_sql_manager, dbh, file, func, line); -} - -SWITCH_DECLARE(switch_status_t) __switch_core_db_handle(switch_sql_manager_t *sql_manager, switch_cache_db_handle_t **dbh, const char *file, const char *func, int line) { switch_cache_db_connection_options_t options = { {0} }; switch_status_t r; - if (!sql_manager->manage) { + if (!sql_manager.manage) { return SWITCH_STATUS_FALSE; } @@ -207,26 +199,26 @@ SWITCH_DECLARE(switch_status_t) __switch_core_db_handle(switch_sql_manager_t *sq } else { options.core_db_options.db_path = SWITCH_CORE_DB; } - r = __switch_cache_db_get_db_handle(sql_manager, dbh, SCDB_TYPE_CORE_DB, &options, file, func, line); + r = _switch_cache_db_get_db_handle(dbh, SCDB_TYPE_CORE_DB, &options, file, func, line); } else { char *dsn; if ((dsn = strstr(runtime.odbc_dsn, "pgsql;")) != NULL) { options.pgsql_options.dsn = (char*)(dsn + 6); - r = __switch_cache_db_get_db_handle(sql_manager, dbh, SCDB_TYPE_PGSQL, &options, file, func, line); + r = _switch_cache_db_get_db_handle(dbh, SCDB_TYPE_PGSQL, &options, file, func, line); } else { options.odbc_options.dsn = runtime.odbc_dsn; options.odbc_options.user = runtime.odbc_user; options.odbc_options.pass = runtime.odbc_pass; - r = __switch_cache_db_get_db_handle(sql_manager, dbh, SCDB_TYPE_ODBC, &options, file, func, line); + r = _switch_cache_db_get_db_handle(dbh, SCDB_TYPE_ODBC, &options, file, func, line); } } /* I *think* we can do without this now, if not let me know if (r == SWITCH_STATUS_SUCCESS && !(*dbh)->io_mutex) { - (*dbh)->io_mutex = sql_manager->io_mutex; + (*dbh)->io_mutex = sql_manager.io_mutex; } */ @@ -237,12 +229,12 @@ SWITCH_DECLARE(switch_status_t) __switch_core_db_handle(switch_sql_manager_t *sq /*! \brief Open the default system database */ -SWITCH_DECLARE(switch_status_t) _switch_core_persist_db_handle(switch_sql_manager_t *sql_manager, switch_cache_db_handle_t **dbh, const char *file, const char *func, int line) +SWITCH_DECLARE(switch_status_t) _switch_core_persist_db_handle(switch_cache_db_handle_t **dbh, const char *file, const char *func, int line) { switch_cache_db_connection_options_t options = { {0} }; switch_status_t r; - if (!sql_manager->manage) { + if (!sql_manager.manage) { return SWITCH_STATUS_FALSE; } @@ -256,26 +248,26 @@ SWITCH_DECLARE(switch_status_t) _switch_core_persist_db_handle(switch_sql_manage } else { options.core_db_options.db_path = SWITCH_CORE_PERSIST_DB; } - r = __switch_cache_db_get_db_handle(sql_manager, dbh, SCDB_TYPE_CORE_DB, &options, file, func, line); + r = _switch_cache_db_get_db_handle(dbh, SCDB_TYPE_CORE_DB, &options, file, func, line); } else { char *dsn; if ((dsn = strstr(runtime.odbc_dsn, "pgsql;")) != NULL) { options.pgsql_options.dsn = (char*)(dsn + 6); - r = __switch_cache_db_get_db_handle(sql_manager, dbh, SCDB_TYPE_PGSQL, &options, file, func, line); + r = _switch_cache_db_get_db_handle(dbh, SCDB_TYPE_PGSQL, &options, file, func, line); } else { options.odbc_options.dsn = runtime.odbc_dsn; options.odbc_options.user = runtime.odbc_user; options.odbc_options.pass = runtime.odbc_pass; - r = __switch_cache_db_get_db_handle(sql_manager, dbh, SCDB_TYPE_ODBC, &options, file, func, line); + r = _switch_cache_db_get_db_handle(dbh, SCDB_TYPE_ODBC, &options, file, func, line); } } /* I *think* we can do without this now, if not let me know if (r == SWITCH_STATUS_SUCCESS && !(*dbh)->io_mutex) { - (*dbh)->io_mutex = sql_manager->io_mutex; + (*dbh)->io_mutex = sql_manager.io_mutex; } */ @@ -284,12 +276,12 @@ SWITCH_DECLARE(switch_status_t) _switch_core_persist_db_handle(switch_sql_manage #define SWITCH_CORE_RECOVERY_DB "core_recovery" -SWITCH_DECLARE(switch_status_t) _switch_core_recovery_db_handle(switch_sql_manager_t *sql_manager, switch_cache_db_handle_t **dbh, const char *file, const char *func, int line) +SWITCH_DECLARE(switch_status_t) _switch_core_recovery_db_handle(switch_cache_db_handle_t **dbh, const char *file, const char *func, int line) { switch_cache_db_connection_options_t options = { {0} }; switch_status_t r; - if (!sql_manager->manage) { + if (!sql_manager.manage) { return SWITCH_STATUS_FALSE; } @@ -303,26 +295,26 @@ SWITCH_DECLARE(switch_status_t) _switch_core_recovery_db_handle(switch_sql_manag } else { options.core_db_options.db_path = SWITCH_CORE_RECOVERY_DB; } - r = __switch_cache_db_get_db_handle(sql_manager, dbh, SCDB_TYPE_CORE_DB, &options, file, func, line); + r = _switch_cache_db_get_db_handle(dbh, SCDB_TYPE_CORE_DB, &options, file, func, line); } else { char *dsn; if ((dsn = strstr(runtime.recovery_odbc_dsn, "pgsql;")) != NULL) { options.pgsql_options.dsn = (char*)(dsn + 6); - r = __switch_cache_db_get_db_handle(sql_manager, dbh, SCDB_TYPE_PGSQL, &options, file, func, line); + r = _switch_cache_db_get_db_handle(dbh, SCDB_TYPE_PGSQL, &options, file, func, line); } else { options.odbc_options.dsn = runtime.recovery_odbc_dsn; options.odbc_options.user = runtime.recovery_odbc_user; options.odbc_options.pass = runtime.recovery_odbc_pass; - r = __switch_cache_db_get_db_handle(sql_manager, dbh, SCDB_TYPE_ODBC, &options, file, func, line); + r = _switch_cache_db_get_db_handle(dbh, SCDB_TYPE_ODBC, &options, file, func, line); } } /* I *think* we can do without this now, if not let me know if (r == SWITCH_STATUS_SUCCESS && !(*dbh)->io_mutex) { - (*dbh)->io_mutex = sql_manager->io_mutex; + (*dbh)->io_mutex = sql_manager.io_mutex; } */ @@ -334,16 +326,16 @@ SWITCH_DECLARE(switch_status_t) _switch_core_recovery_db_handle(switch_sql_manag #define SQL_REG_TIMEOUT 15 -static void sql_close(switch_sql_manager_t *sql_manager, time_t prune) +static void sql_close(time_t prune) { switch_cache_db_handle_t *dbh = NULL; int locked = 0; - switch_mutex_lock(sql_manager->dbh_mutex); + switch_mutex_lock(sql_manager.dbh_mutex); top: locked = 0; - for (dbh = sql_manager->handle_pool; dbh; dbh = dbh->next) { + for (dbh = sql_manager.handle_pool; dbh; dbh = dbh->next) { time_t diff = 0; if (prune > 0 && prune > dbh->last_used) { @@ -376,7 +368,7 @@ static void sql_close(switch_sql_manager_t *sql_manager, time_t prune) break; } - del_handle(sql_manager, dbh); + del_handle(dbh); switch_mutex_unlock(dbh->mutex); switch_core_destroy_memory_pool(&dbh->pool); goto top; @@ -394,7 +386,7 @@ static void sql_close(switch_sql_manager_t *sql_manager, time_t prune) goto top; } - switch_mutex_unlock(sql_manager->dbh_mutex); + switch_mutex_unlock(sql_manager.dbh_mutex); } @@ -403,20 +395,16 @@ SWITCH_DECLARE(switch_cache_db_handle_type_t) switch_cache_db_get_type(switch_ca return dbh->type; } -SWITCH_DECLARE(void) switch_cache_db_flush_handles(switch_sql_manager_t *sql_manager) +SWITCH_DECLARE(void) switch_cache_db_flush_handles(void) { - sql_close(sql_manager, switch_epoch_time_now(NULL) + SQL_CACHE_TIMEOUT + 1); + sql_close(switch_epoch_time_now(NULL) + SQL_CACHE_TIMEOUT + 1); } + SWITCH_DECLARE(void) switch_cache_db_release_db_handle(switch_cache_db_handle_t **dbh) -{ - _switch_cache_db_release_db_handle(&switch_cache_db_sql_manager, dbh); -} - -SWITCH_DECLARE(void) _switch_cache_db_release_db_handle(switch_sql_manager_t *sql_manager, switch_cache_db_handle_t **dbh) { if (dbh && *dbh) { - switch_mutex_lock(sql_manager->dbh_mutex); + switch_mutex_lock(sql_manager.dbh_mutex); (*dbh)->last_used = switch_epoch_time_now(NULL); (*dbh)->io_mutex = NULL; @@ -427,9 +415,9 @@ SWITCH_DECLARE(void) _switch_cache_db_release_db_handle(switch_sql_manager_t *sq } } switch_mutex_unlock((*dbh)->mutex); - sql_manager->total_used_handles--; + sql_manager.total_used_handles--; *dbh = NULL; - switch_mutex_unlock(sql_manager->dbh_mutex); + switch_mutex_unlock(sql_manager.dbh_mutex); } } @@ -440,16 +428,7 @@ SWITCH_DECLARE(void) switch_cache_db_dismiss_db_handle(switch_cache_db_handle_t } -SWITCH_DECLARE(switch_status_t) _switch_cache_db_get_db_handle(switch_cache_db_handle_t ** dbh, - switch_cache_db_handle_type_t type, - switch_cache_db_connection_options_t *connection_options, - const char *file, const char *func, int line) -{ - return __switch_cache_db_get_db_handle(&switch_cache_db_sql_manager, dbh, type, connection_options, file, func, line); -} - -SWITCH_DECLARE(switch_status_t) __switch_cache_db_get_db_handle(switch_sql_manager_t *sql_manager, - switch_cache_db_handle_t **dbh, +SWITCH_DECLARE(switch_status_t) _switch_cache_db_get_db_handle(switch_cache_db_handle_t **dbh, switch_cache_db_handle_type_t type, switch_cache_db_connection_options_t *connection_options, const char *file, const char *func, int line) @@ -466,7 +445,7 @@ SWITCH_DECLARE(switch_status_t) __switch_cache_db_get_db_handle(switch_sql_manag const char *odbc_user = NULL; const char *odbc_pass = NULL; - while(runtime.max_db_handles && sql_manager->total_handles >= runtime.max_db_handles && sql_manager->total_used_handles >= sql_manager->total_handles) { + while(runtime.max_db_handles && sql_manager.total_handles >= runtime.max_db_handles && sql_manager.total_used_handles >= sql_manager.total_handles) { if (!waiting++) { switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, func, line, NULL, SWITCH_LOG_WARNING, "Max handles %u exceeded, blocking....\n", runtime.max_db_handles); @@ -517,7 +496,7 @@ SWITCH_DECLARE(switch_status_t) __switch_cache_db_get_db_handle(switch_sql_manag snprintf(db_callsite_str, sizeof(db_callsite_str) - 1, "%s:%d", file, line); snprintf(thread_str, sizeof(thread_str) - 1, "thread=\"%lu\"", (unsigned long) (intptr_t) self); - if ((new_dbh = get_handle(sql_manager, db_str, db_callsite_str, thread_str))) { + if ((new_dbh = get_handle(db_str, db_callsite_str, thread_str))) { switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, func, line, NULL, SWITCH_LOG_DEBUG10, "Reuse Unused Cached DB handle %s [%s]\n", new_dbh->name, switch_cache_db_type_name(new_dbh->type)); } else { @@ -573,6 +552,9 @@ SWITCH_DECLARE(switch_status_t) __switch_cache_db_get_db_handle(switch_sql_manag goto end; } + switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, func, line, NULL, SWITCH_LOG_DEBUG10, + "Create Cached DB handle %s [%s] %s:%d\n", new_dbh->name, switch_cache_db_type_name(type), file, line); + new_dbh = create_handle(type); if (db) { @@ -583,11 +565,7 @@ SWITCH_DECLARE(switch_status_t) __switch_cache_db_get_db_handle(switch_sql_manag new_dbh->native_handle.pgsql_dbh = pgsql_dbh; } - add_handle(sql_manager, new_dbh, db_str, db_callsite_str, thread_str); - - switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, func, line, NULL, SWITCH_LOG_DEBUG10, - "Create Cached DB handle %s [%s] %s:%d\n", new_dbh->name, switch_cache_db_type_name(type), file, line); - + add_handle(new_dbh, db_str, db_callsite_str, thread_str); } end: @@ -664,20 +642,18 @@ static switch_status_t switch_cache_db_execute_sql_real(switch_cache_db_handle_t return status; } -static void _wake_thread(switch_sql_manager_t *sql_manager, int force) +static void wake_thread(int force) { if (force) { - switch_thread_cond_signal(sql_manager->cond); + switch_thread_cond_signal(sql_manager.cond); return; } - if (switch_mutex_trylock(sql_manager->cond_mutex) == SWITCH_STATUS_SUCCESS) { - switch_thread_cond_signal(sql_manager->cond); - switch_mutex_unlock(sql_manager->cond_mutex); + if (switch_mutex_trylock(sql_manager.cond_mutex) == SWITCH_STATUS_SUCCESS) { + switch_thread_cond_signal(sql_manager.cond); + switch_mutex_unlock(sql_manager.cond_mutex); } } -#define wake_thread(f) _wake_thread(&switch_cache_db_sql_manager, f) - /** OMFG you cruel bastards. Who chooses 64k as a max buffer len for a sql statement, have you ever heard of transactions? @@ -1201,16 +1177,13 @@ SWITCH_DECLARE(switch_bool_t) switch_cache_db_test_reactive(switch_cache_db_hand static void *SWITCH_THREAD_FUNC switch_core_sql_db_thread(switch_thread_t *thread, void *obj) { - int sec = 0, reg_sec = 0; - switch_sql_manager_t *sql_manager; + int sec = 0, reg_sec = 0;; - sql_manager = (switch_sql_manager_t*)obj; + sql_manager.db_thread_running = 1; - sql_manager->db_thread_running = 1; - - while (sql_manager->db_thread_running == 1) { + while (sql_manager.db_thread_running == 1) { if (++sec == SQL_CACHE_TIMEOUT) { - sql_close(sql_manager, switch_epoch_time_now(NULL)); + sql_close(switch_epoch_time_now(NULL)); wake_thread(0); sec = 0; } @@ -1239,47 +1212,44 @@ static void *SWITCH_THREAD_FUNC switch_core_sql_thread(switch_thread_t *thread, int lc = 0, wrote = 0, do_sleep = 1; uint32_t sanity = 120; int auto_pause = 0; - switch_sql_manager_t *sql_manager; - - sql_manager = (switch_sql_manager_t*)obj; switch_assert(sqlbuf); - while (!sql_manager->event_db) { - if (switch_core_db_handle(&sql_manager->event_db) == SWITCH_STATUS_SUCCESS && sql_manager->event_db) + while (!sql_manager.event_db) { + if (switch_core_db_handle(&sql_manager.event_db) == SWITCH_STATUS_SUCCESS && sql_manager.event_db) break; switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Error getting core db, Retrying\n"); switch_yield(500000); sanity--; } - if (!sql_manager->event_db) { + if (!sql_manager.event_db) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Error getting core db Disabling core sql functionality\n"); return NULL; } - sql_manager->thread_running = 1; + sql_manager.thread_running = 1; - switch_mutex_lock(sql_manager->cond_mutex); + switch_mutex_lock(sql_manager.cond_mutex); - switch (switch_cache_db_sql_manager.event_db->type) { + switch (sql_manager.event_db->type) { case SCDB_TYPE_PGSQL: break; case SCDB_TYPE_ODBC: break; case SCDB_TYPE_CORE_DB: { - switch_cache_db_execute_sql(sql_manager->event_db, "PRAGMA synchronous=OFF;", NULL); - switch_cache_db_execute_sql(sql_manager->event_db, "PRAGMA count_changes=OFF;", NULL); - switch_cache_db_execute_sql(sql_manager->event_db, "PRAGMA temp_store=MEMORY;", NULL); - switch_cache_db_execute_sql(sql_manager->event_db, "PRAGMA journal_mode=OFF;", NULL); + switch_cache_db_execute_sql(sql_manager.event_db, "PRAGMA synchronous=OFF;", NULL); + switch_cache_db_execute_sql(sql_manager.event_db, "PRAGMA count_changes=OFF;", NULL); + switch_cache_db_execute_sql(sql_manager.event_db, "PRAGMA temp_store=MEMORY;", NULL); + switch_cache_db_execute_sql(sql_manager.event_db, "PRAGMA journal_mode=OFF;", NULL); } break; } - while (sql_manager->thread_running == 1) { - if (save_sql || switch_queue_trypop(sql_manager->sql_queue[0], &pop) == SWITCH_STATUS_SUCCESS || - switch_queue_trypop(sql_manager->sql_queue[1], &pop) == SWITCH_STATUS_SUCCESS) { + while (sql_manager.thread_running == 1) { + if (save_sql || switch_queue_trypop(sql_manager.sql_queue[0], &pop) == SWITCH_STATUS_SUCCESS || + switch_queue_trypop(sql_manager.sql_queue[1], &pop) == SWITCH_STATUS_SUCCESS) { if (save_sql) { sql = save_sql; @@ -1302,8 +1272,8 @@ static void *SWITCH_THREAD_FUNC switch_core_sql_thread(switch_thread_t *thread, sql_len = new_mlen; if (switch_test_flag((&runtime), SCF_DEBUG_SQL)) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, - "REALLOC %ld %d %d\n", (long int)sql_len, switch_queue_size(sql_manager->sql_queue[0]), - switch_queue_size(sql_manager->sql_queue[1])); + "REALLOC %ld %d %d\n", (long int)sql_len, switch_queue_size(sql_manager.sql_queue[0]), + switch_queue_size(sql_manager.sql_queue[1])); } if (!(tmp = realloc(sqlbuf, sql_len))) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "SQL thread ending on mem err\n"); @@ -1314,7 +1284,7 @@ static void *SWITCH_THREAD_FUNC switch_core_sql_thread(switch_thread_t *thread, } else { if (switch_test_flag((&runtime), SCF_DEBUG_SQL)) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, - "SAVE %d %d\n", switch_queue_size(sql_manager->sql_queue[0]), switch_queue_size(sql_manager->sql_queue[1])); + "SAVE %d %d\n", switch_queue_size(sql_manager.sql_queue[0]), switch_queue_size(sql_manager.sql_queue[1])); } save_sql = sql; sql = NULL; @@ -1323,7 +1293,7 @@ static void *SWITCH_THREAD_FUNC switch_core_sql_thread(switch_thread_t *thread, } } - iterations++; + iterations++; sprintf(sqlbuf + len, "%s;\n", sql); len += newlen; free(sql); @@ -1334,7 +1304,7 @@ static void *SWITCH_THREAD_FUNC switch_core_sql_thread(switch_thread_t *thread, } } - lc = switch_queue_size(sql_manager->sql_queue[0]) + switch_queue_size(sql_manager->sql_queue[1]); + lc = switch_queue_size(sql_manager.sql_queue[0]) + switch_queue_size(sql_manager.sql_queue[1]); if (lc > SWITCH_SQL_QUEUE_PAUSE_LEN) { @@ -1360,9 +1330,9 @@ static void *SWITCH_THREAD_FUNC switch_core_sql_thread(switch_thread_t *thread, if (trans && iterations && (iterations > target || !lc)) { if (switch_test_flag((&runtime), SCF_DEBUG_SQL)) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, - "RUN %d %d %d\n", switch_queue_size(sql_manager->sql_queue[0]), switch_queue_size(sql_manager->sql_queue[1]), iterations); + "RUN %d %d %d\n", switch_queue_size(sql_manager.sql_queue[0]), switch_queue_size(sql_manager.sql_queue[1]), iterations); } - if (switch_cache_db_persistant_execute_trans(sql_manager->event_db, sqlbuf, 1) != SWITCH_STATUS_SUCCESS) { + if (switch_cache_db_persistant_execute_trans(sql_manager.event_db, sqlbuf, 1) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "SQL thread unable to commit transaction, records lost!\n"); } if (switch_test_flag((&runtime), SCF_DEBUG_SQL)) { @@ -1383,10 +1353,10 @@ static void *SWITCH_THREAD_FUNC switch_core_sql_thread(switch_thread_t *thread, wrote = 1; } - lc = switch_queue_size(sql_manager->sql_queue[0]) + switch_queue_size(sql_manager->sql_queue[1]); + lc = switch_queue_size(sql_manager.sql_queue[0]) + switch_queue_size(sql_manager.sql_queue[1]); if (!lc) { - switch_thread_cond_wait(sql_manager->cond, sql_manager->cond_mutex); + switch_thread_cond_wait(sql_manager.cond, sql_manager.cond_mutex); } else if (wrote) { if (lc > 2000) { do_sleep = 0; @@ -1398,21 +1368,21 @@ static void *SWITCH_THREAD_FUNC switch_core_sql_thread(switch_thread_t *thread, } - switch_mutex_unlock(sql_manager->cond_mutex); + switch_mutex_unlock(sql_manager.cond_mutex); - while (switch_queue_trypop(sql_manager->sql_queue[0], &pop) == SWITCH_STATUS_SUCCESS) { + while (switch_queue_trypop(sql_manager.sql_queue[0], &pop) == SWITCH_STATUS_SUCCESS) { free(pop); } - while (switch_queue_trypop(sql_manager->sql_queue[1], &pop) == SWITCH_STATUS_SUCCESS) { + while (switch_queue_trypop(sql_manager.sql_queue[1], &pop) == SWITCH_STATUS_SUCCESS) { free(pop); } free(sqlbuf); - sql_manager->thread_running = 0; + sql_manager.thread_running = 0; - switch_cache_db_release_db_handle(&sql_manager->event_db); + switch_cache_db_release_db_handle(&sql_manager.event_db); return NULL; } @@ -1854,9 +1824,9 @@ static void core_event_handler(switch_event_t *event) for (i = 0; i < sql_idx; i++) { if (switch_stristr("update channels", sql[i]) || switch_stristr("delete from channels", sql[i])) { - switch_queue_push(switch_cache_db_sql_manager.sql_queue[1], sql[i]); + switch_queue_push(sql_manager.sql_queue[1], sql[i]); } else { - switch_queue_push(switch_cache_db_sql_manager.sql_queue[0], sql[i]); + switch_queue_push(sql_manager.sql_queue[0], sql[i]); } sql[i] = NULL; wake_thread(0); @@ -2415,7 +2385,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_add_registration(const char *user, c user, realm, switch_core_get_switchname()); } - switch_queue_push(switch_cache_db_sql_manager.sql_queue[0], sql); + switch_queue_push(sql_manager.sql_queue[0], sql); if ( !zstr(metadata) ) { sql = switch_mprintf("insert into registrations (reg_user,realm,token,url,expires,network_ip,network_port,network_proto,hostname,metadata) " @@ -2447,7 +2417,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_add_registration(const char *user, c } - switch_queue_push(switch_cache_db_sql_manager.sql_queue[0], sql); + switch_queue_push(sql_manager.sql_queue[0], sql); return SWITCH_STATUS_SUCCESS; } @@ -2467,7 +2437,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_del_registration(const char *user, c sql = switch_mprintf("delete from registrations where reg_user='%q' and realm='%q' and hostname='%q'", user, realm, switch_core_get_switchname()); } - switch_queue_push(switch_cache_db_sql_manager.sql_queue[0], sql); + switch_queue_push(sql_manager.sql_queue[0], sql); return SWITCH_STATUS_SUCCESS; } @@ -2490,33 +2460,35 @@ SWITCH_DECLARE(switch_status_t) switch_core_expire_registration(int force) sql = switch_mprintf("delete from registrations where expires > 0 and expires <= %ld and hostname='%q'", now, switch_core_get_switchname()); } - switch_queue_push(switch_cache_db_sql_manager.sql_queue[0], sql); + switch_queue_push(sql_manager.sql_queue[0], sql); return SWITCH_STATUS_SUCCESS; } -void switch_sqldb_init_sql_manager(switch_sql_manager_t *sql_manager, switch_memory_pool_t *pool, switch_bool_t manage) +switch_status_t switch_core_sqldb_start(switch_memory_pool_t *pool, switch_bool_t manage) { + switch_threadattr_t *thd_attr; + uint32_t sanity = 400; - sql_manager->memory_pool = pool; - sql_manager->manage = manage; + sql_manager.memory_pool = pool; + sql_manager.manage = manage; - switch_mutex_init(&sql_manager->dbh_mutex, SWITCH_MUTEX_NESTED, sql_manager->memory_pool); - switch_mutex_init(&sql_manager->io_mutex, SWITCH_MUTEX_NESTED, sql_manager->memory_pool); - switch_mutex_init(&sql_manager->cond_mutex, SWITCH_MUTEX_NESTED, sql_manager->memory_pool); - switch_mutex_init(&sql_manager->ctl_mutex, SWITCH_MUTEX_NESTED, sql_manager->memory_pool); + switch_mutex_init(&sql_manager.dbh_mutex, SWITCH_MUTEX_NESTED, sql_manager.memory_pool); + switch_mutex_init(&sql_manager.io_mutex, SWITCH_MUTEX_NESTED, sql_manager.memory_pool); + switch_mutex_init(&sql_manager.cond_mutex, SWITCH_MUTEX_NESTED, sql_manager.memory_pool); + switch_mutex_init(&sql_manager.ctl_mutex, SWITCH_MUTEX_NESTED, sql_manager.memory_pool); - switch_thread_cond_create(&sql_manager->cond, sql_manager->memory_pool); -} + switch_thread_cond_create(&sql_manager.cond, sql_manager.memory_pool); -switch_status_t switch_sqldb_connect(switch_sql_manager_t *sql_manager, switch_memory_pool_t *pool) -{ - top: + + if (!sql_manager.manage) goto skip; + + top: /* Activate SQL database */ - if (switch_core_db_handle(&sql_manager->dbh) != SWITCH_STATUS_SUCCESS) { + if (switch_core_db_handle(&sql_manager.dbh) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error Opening DB!\n"); if (switch_test_flag((&runtime), SCF_CORE_NON_SQLITE_DB_REQ)) { @@ -2540,25 +2512,8 @@ switch_status_t switch_sqldb_connect(switch_sql_manager_t *sql_manager, switch_m switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Opening DB\n"); - return SWITCH_STATUS_SUCCESS; -} -switch_status_t switch_core_sqldb_start(switch_memory_pool_t *pool, switch_bool_t manage) -{ - switch_threadattr_t *thd_attr; - uint32_t sanity = 400; - switch_sql_manager_t *sql_manager = &switch_cache_db_sql_manager; - - switch_sqldb_init_sql_manager(sql_manager, pool, manage); - - if (manage == SWITCH_FALSE) goto skip; - - top: - if (switch_sqldb_connect(sql_manager, pool) == SWITCH_STATUS_FALSE) { - return SWITCH_STATUS_FALSE; - } - - switch (sql_manager->dbh->type) { + switch (sql_manager.dbh->type) { case SCDB_TYPE_PGSQL: case SCDB_TYPE_ODBC: if (switch_test_flag((&runtime), SCF_CLEAR_SQL)) { @@ -2569,61 +2524,61 @@ switch_status_t switch_core_sqldb_start(switch_memory_pool_t *pool, switch_bool_ for (i = 0; tables[i]; i++) { switch_snprintfv(sql, sizeof(sql), "delete from %q where hostname='%q'", tables[i], hostname); - switch_cache_db_execute_sql(sql_manager->dbh, sql, NULL); + switch_cache_db_execute_sql(sql_manager.dbh, sql, NULL); } } break; case SCDB_TYPE_CORE_DB: { - switch_cache_db_execute_sql(sql_manager->dbh, "drop table channels", NULL); - switch_cache_db_execute_sql(sql_manager->dbh, "drop table calls", NULL); - switch_cache_db_execute_sql(sql_manager->dbh, "drop view detailed_calls", NULL); - switch_cache_db_execute_sql(sql_manager->dbh, "drop view basic_calls", NULL); - switch_cache_db_execute_sql(sql_manager->dbh, "drop table interfaces", NULL); - switch_cache_db_execute_sql(sql_manager->dbh, "drop table tasks", NULL); - switch_cache_db_execute_sql(sql_manager->dbh, "PRAGMA synchronous=OFF;", NULL); - switch_cache_db_execute_sql(sql_manager->dbh, "PRAGMA count_changes=OFF;", NULL); - switch_cache_db_execute_sql(sql_manager->dbh, "PRAGMA default_cache_size=8000", NULL); - switch_cache_db_execute_sql(sql_manager->dbh, "PRAGMA temp_store=MEMORY;", NULL); - switch_cache_db_execute_sql(sql_manager->dbh, "PRAGMA journal_mode=OFF;", NULL); + switch_cache_db_execute_sql(sql_manager.dbh, "drop table channels", NULL); + switch_cache_db_execute_sql(sql_manager.dbh, "drop table calls", NULL); + switch_cache_db_execute_sql(sql_manager.dbh, "drop view detailed_calls", NULL); + switch_cache_db_execute_sql(sql_manager.dbh, "drop view basic_calls", NULL); + switch_cache_db_execute_sql(sql_manager.dbh, "drop table interfaces", NULL); + switch_cache_db_execute_sql(sql_manager.dbh, "drop table tasks", NULL); + switch_cache_db_execute_sql(sql_manager.dbh, "PRAGMA synchronous=OFF;", NULL); + switch_cache_db_execute_sql(sql_manager.dbh, "PRAGMA count_changes=OFF;", NULL); + switch_cache_db_execute_sql(sql_manager.dbh, "PRAGMA default_cache_size=8000", NULL); + switch_cache_db_execute_sql(sql_manager.dbh, "PRAGMA temp_store=MEMORY;", NULL); + switch_cache_db_execute_sql(sql_manager.dbh, "PRAGMA journal_mode=OFF;", NULL); } break; } - switch_cache_db_test_reactive(sql_manager->dbh, "select hostname from aliases", "DROP TABLE aliases", create_alias_sql); - switch_cache_db_test_reactive(sql_manager->dbh, "select hostname from complete", "DROP TABLE complete", create_complete_sql); - switch_cache_db_test_reactive(sql_manager->dbh, "select hostname from nat", "DROP TABLE nat", create_nat_sql); - switch_cache_db_test_reactive(sql_manager->dbh, "delete from registrations where reg_user='' or network_proto='tcp' or network_proto='tls'", + switch_cache_db_test_reactive(sql_manager.dbh, "select hostname from aliases", "DROP TABLE aliases", create_alias_sql); + switch_cache_db_test_reactive(sql_manager.dbh, "select hostname from complete", "DROP TABLE complete", create_complete_sql); + switch_cache_db_test_reactive(sql_manager.dbh, "select hostname from nat", "DROP TABLE nat", create_nat_sql); + switch_cache_db_test_reactive(sql_manager.dbh, "delete from registrations where reg_user='' or network_proto='tcp' or network_proto='tls'", "DROP TABLE registrations", create_registrations_sql); - switch_cache_db_test_reactive(sql_manager->dbh, "select metadata from registrations", NULL, "ALTER TABLE registrations ADD COLUMN metadata VARCHAR(256)"); + switch_cache_db_test_reactive(sql_manager.dbh, "select metadata from registrations", NULL, "ALTER TABLE registrations ADD COLUMN metadata VARCHAR(256)"); - switch (sql_manager->dbh->type) { + switch (sql_manager.dbh->type) { case SCDB_TYPE_PGSQL: case SCDB_TYPE_ODBC: { char *err; - switch_cache_db_test_reactive(sql_manager->dbh, "select call_uuid, read_bit_rate, sent_callee_name from channels", "DROP TABLE channels", create_channels_sql); - switch_cache_db_test_reactive(sql_manager->dbh, "select * from detailed_calls where sent_callee_name=''", "DROP VIEW detailed_calls", detailed_calls_sql); - switch_cache_db_test_reactive(sql_manager->dbh, "select * from basic_calls where sent_callee_name=''", "DROP VIEW basic_calls", basic_calls_sql); - switch_cache_db_test_reactive(sql_manager->dbh, "select call_uuid from calls", "DROP TABLE calls", create_calls_sql); + switch_cache_db_test_reactive(sql_manager.dbh, "select call_uuid, read_bit_rate, sent_callee_name from channels", "DROP TABLE channels", create_channels_sql); + switch_cache_db_test_reactive(sql_manager.dbh, "select * from detailed_calls where sent_callee_name=''", "DROP VIEW detailed_calls", detailed_calls_sql); + switch_cache_db_test_reactive(sql_manager.dbh, "select * from basic_calls where sent_callee_name=''", "DROP VIEW basic_calls", basic_calls_sql); + switch_cache_db_test_reactive(sql_manager.dbh, "select call_uuid from calls", "DROP TABLE calls", create_calls_sql); if (runtime.odbc_dbtype == DBTYPE_DEFAULT) { - switch_cache_db_test_reactive(sql_manager->dbh, "delete from registrations where reg_user='' or network_proto='tcp' or network_proto='tls'", + switch_cache_db_test_reactive(sql_manager.dbh, "delete from registrations where reg_user='' or network_proto='tcp' or network_proto='tls'", "DROP TABLE registrations", create_registrations_sql); } else { char *tmp = switch_string_replace(create_registrations_sql, "url TEXT", "url VARCHAR(max)"); - switch_cache_db_test_reactive(sql_manager->dbh, "delete from registrations where reg_user='' or network_proto='tcp' or network_proto='tls'", + switch_cache_db_test_reactive(sql_manager.dbh, "delete from registrations where reg_user='' or network_proto='tcp' or network_proto='tls'", "DROP TABLE registrations", tmp); free(tmp); } - switch_cache_db_test_reactive(sql_manager->dbh, "select ikey from interfaces", "DROP TABLE interfaces", create_interfaces_sql); - switch_cache_db_test_reactive(sql_manager->dbh, "select hostname from tasks", "DROP TABLE tasks", create_tasks_sql); + switch_cache_db_test_reactive(sql_manager.dbh, "select ikey from interfaces", "DROP TABLE interfaces", create_interfaces_sql); + switch_cache_db_test_reactive(sql_manager.dbh, "select hostname from tasks", "DROP TABLE tasks", create_tasks_sql); if (runtime.odbc_dbtype == DBTYPE_DEFAULT) { - switch_cache_db_execute_sql(sql_manager->dbh, "begin;delete from channels where hostname='';delete from channels where hostname='';commit;", &err); + switch_cache_db_execute_sql(sql_manager.dbh, "begin;delete from channels where hostname='';delete from channels where hostname='';commit;", &err); } else { - switch_cache_db_execute_sql(sql_manager->dbh, "delete from channels where hostname='';delete from channels where hostname='';", &err); + switch_cache_db_execute_sql(sql_manager.dbh, "delete from channels where hostname='';delete from channels where hostname='';", &err); } if (err) { @@ -2631,7 +2586,7 @@ switch_status_t switch_core_sqldb_start(switch_memory_pool_t *pool, switch_bool_ runtime.odbc_user = NULL; runtime.odbc_pass = NULL; switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Transactions not supported on your DB, disabling non-SQLite support; using SQLite\n"); - switch_cache_db_release_db_handle(&sql_manager->dbh); + switch_cache_db_release_db_handle(&sql_manager.dbh); free(err); goto top; } @@ -2639,49 +2594,49 @@ switch_status_t switch_core_sqldb_start(switch_memory_pool_t *pool, switch_bool_ break; case SCDB_TYPE_CORE_DB: { - switch_cache_db_execute_sql(sql_manager->dbh, create_channels_sql, NULL); - switch_cache_db_execute_sql(sql_manager->dbh, create_calls_sql, NULL); - switch_cache_db_execute_sql(sql_manager->dbh, create_interfaces_sql, NULL); - switch_cache_db_execute_sql(sql_manager->dbh, create_tasks_sql, NULL); - switch_cache_db_execute_sql(sql_manager->dbh, detailed_calls_sql, NULL); - switch_cache_db_execute_sql(sql_manager->dbh, basic_calls_sql, NULL); + switch_cache_db_execute_sql(sql_manager.dbh, create_channels_sql, NULL); + switch_cache_db_execute_sql(sql_manager.dbh, create_calls_sql, NULL); + switch_cache_db_execute_sql(sql_manager.dbh, create_interfaces_sql, NULL); + switch_cache_db_execute_sql(sql_manager.dbh, create_tasks_sql, NULL); + switch_cache_db_execute_sql(sql_manager.dbh, detailed_calls_sql, NULL); + switch_cache_db_execute_sql(sql_manager.dbh, basic_calls_sql, NULL); } break; } - switch_cache_db_execute_sql(sql_manager->dbh, "delete from complete where sticky=0", NULL); - switch_cache_db_execute_sql(sql_manager->dbh, "delete from aliases where sticky=0", NULL); - switch_cache_db_execute_sql(sql_manager->dbh, "delete from nat where sticky=0", NULL); - switch_cache_db_execute_sql(sql_manager->dbh, "create index alias1 on aliases (alias)", NULL); - switch_cache_db_execute_sql(sql_manager->dbh, "create index tasks1 on tasks (hostname,task_id)", NULL); - switch_cache_db_execute_sql(sql_manager->dbh, "create index complete1 on complete (a1,hostname)", NULL); - switch_cache_db_execute_sql(sql_manager->dbh, "create index complete2 on complete (a2,hostname)", NULL); - switch_cache_db_execute_sql(sql_manager->dbh, "create index complete3 on complete (a3,hostname)", NULL); - switch_cache_db_execute_sql(sql_manager->dbh, "create index complete4 on complete (a4,hostname)", NULL); - switch_cache_db_execute_sql(sql_manager->dbh, "create index complete5 on complete (a5,hostname)", NULL); - switch_cache_db_execute_sql(sql_manager->dbh, "create index complete6 on complete (a6,hostname)", NULL); - switch_cache_db_execute_sql(sql_manager->dbh, "create index complete7 on complete (a7,hostname)", NULL); - switch_cache_db_execute_sql(sql_manager->dbh, "create index complete8 on complete (a8,hostname)", NULL); - switch_cache_db_execute_sql(sql_manager->dbh, "create index complete9 on complete (a9,hostname)", NULL); - switch_cache_db_execute_sql(sql_manager->dbh, "create index complete10 on complete (a10,hostname)", NULL); - switch_cache_db_execute_sql(sql_manager->dbh, "create index complete11 on complete (a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,hostname)", NULL); - switch_cache_db_execute_sql(sql_manager->dbh, "create index nat_map_port_proto on nat (port,proto,hostname)", NULL); - switch_cache_db_execute_sql(sql_manager->dbh, "create index channels1 on channels(hostname)", NULL); - switch_cache_db_execute_sql(sql_manager->dbh, "create index calls1 on calls(hostname)", NULL); - switch_cache_db_execute_sql(sql_manager->dbh, "create index chidx1 on channels (hostname)", NULL); - switch_cache_db_execute_sql(sql_manager->dbh, "create index uuindex on channels (uuid)", NULL); - switch_cache_db_execute_sql(sql_manager->dbh, "create index uuindex2 on channels (call_uuid)", NULL); - switch_cache_db_execute_sql(sql_manager->dbh, "create index callsidx1 on calls (hostname)", NULL); - switch_cache_db_execute_sql(sql_manager->dbh, "create index eruuindex on calls (caller_uuid)", NULL); - switch_cache_db_execute_sql(sql_manager->dbh, "create index eeuuindex on calls (callee_uuid)", NULL); - switch_cache_db_execute_sql(sql_manager->dbh, "create index eeuuindex2 on calls (call_uuid)", NULL); - switch_cache_db_execute_sql(sql_manager->dbh, "create index regindex1 on registrations (reg_user,realm,hostname)", NULL); + switch_cache_db_execute_sql(sql_manager.dbh, "delete from complete where sticky=0", NULL); + switch_cache_db_execute_sql(sql_manager.dbh, "delete from aliases where sticky=0", NULL); + switch_cache_db_execute_sql(sql_manager.dbh, "delete from nat where sticky=0", NULL); + switch_cache_db_execute_sql(sql_manager.dbh, "create index alias1 on aliases (alias)", NULL); + switch_cache_db_execute_sql(sql_manager.dbh, "create index tasks1 on tasks (hostname,task_id)", NULL); + switch_cache_db_execute_sql(sql_manager.dbh, "create index complete1 on complete (a1,hostname)", NULL); + switch_cache_db_execute_sql(sql_manager.dbh, "create index complete2 on complete (a2,hostname)", NULL); + switch_cache_db_execute_sql(sql_manager.dbh, "create index complete3 on complete (a3,hostname)", NULL); + switch_cache_db_execute_sql(sql_manager.dbh, "create index complete4 on complete (a4,hostname)", NULL); + switch_cache_db_execute_sql(sql_manager.dbh, "create index complete5 on complete (a5,hostname)", NULL); + switch_cache_db_execute_sql(sql_manager.dbh, "create index complete6 on complete (a6,hostname)", NULL); + switch_cache_db_execute_sql(sql_manager.dbh, "create index complete7 on complete (a7,hostname)", NULL); + switch_cache_db_execute_sql(sql_manager.dbh, "create index complete8 on complete (a8,hostname)", NULL); + switch_cache_db_execute_sql(sql_manager.dbh, "create index complete9 on complete (a9,hostname)", NULL); + switch_cache_db_execute_sql(sql_manager.dbh, "create index complete10 on complete (a10,hostname)", NULL); + switch_cache_db_execute_sql(sql_manager.dbh, "create index complete11 on complete (a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,hostname)", NULL); + switch_cache_db_execute_sql(sql_manager.dbh, "create index nat_map_port_proto on nat (port,proto,hostname)", NULL); + switch_cache_db_execute_sql(sql_manager.dbh, "create index channels1 on channels(hostname)", NULL); + switch_cache_db_execute_sql(sql_manager.dbh, "create index calls1 on calls(hostname)", NULL); + switch_cache_db_execute_sql(sql_manager.dbh, "create index chidx1 on channels (hostname)", NULL); + switch_cache_db_execute_sql(sql_manager.dbh, "create index uuindex on channels (uuid)", NULL); + switch_cache_db_execute_sql(sql_manager.dbh, "create index uuindex2 on channels (call_uuid)", NULL); + switch_cache_db_execute_sql(sql_manager.dbh, "create index callsidx1 on calls (hostname)", NULL); + switch_cache_db_execute_sql(sql_manager.dbh, "create index eruuindex on calls (caller_uuid)", NULL); + switch_cache_db_execute_sql(sql_manager.dbh, "create index eeuuindex on calls (callee_uuid)", NULL); + switch_cache_db_execute_sql(sql_manager.dbh, "create index eeuuindex2 on calls (call_uuid)", NULL); + switch_cache_db_execute_sql(sql_manager.dbh, "create index regindex1 on registrations (reg_user,realm,hostname)", NULL); skip: - if (sql_manager->manage) { + if (sql_manager.manage) { #ifdef SWITCH_SQL_BIND_EVERY_EVENT switch_event_bind("core_db", SWITCH_EVENT_ALL, SWITCH_EVENT_SUBCLASS_ANY, core_event_handler, NULL); #else @@ -2710,16 +2665,16 @@ switch_status_t switch_core_sqldb_start(switch_memory_pool_t *pool, switch_bool_ switch_event_bind("core_db", SWITCH_EVENT_NAT, SWITCH_EVENT_SUBCLASS_ANY, core_event_handler, NULL); #endif - switch_queue_create(&sql_manager->sql_queue[0], SWITCH_SQL_QUEUE_LEN, sql_manager->memory_pool); - switch_queue_create(&sql_manager->sql_queue[1], SWITCH_SQL_QUEUE_LEN, sql_manager->memory_pool); + switch_queue_create(&sql_manager.sql_queue[0], SWITCH_SQL_QUEUE_LEN, sql_manager.memory_pool); + switch_queue_create(&sql_manager.sql_queue[1], SWITCH_SQL_QUEUE_LEN, sql_manager.memory_pool); - switch_threadattr_create(&thd_attr, sql_manager->memory_pool); + switch_threadattr_create(&thd_attr, sql_manager.memory_pool); switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE); switch_threadattr_priority_set(thd_attr, SWITCH_PRI_REALTIME); switch_core_sqldb_start_thread(); - switch_thread_create(&sql_manager->db_thread, thd_attr, switch_core_sql_db_thread, sql_manager, sql_manager->memory_pool); + switch_thread_create(&sql_manager.db_thread, thd_attr, switch_core_sql_db_thread, NULL, sql_manager.memory_pool); - while (sql_manager->manage && !sql_manager->thread_running && --sanity) { + while (sql_manager.manage && !sql_manager.thread_running && --sanity) { switch_yield(10000); } } @@ -2727,36 +2682,37 @@ switch_status_t switch_core_sqldb_start(switch_memory_pool_t *pool, switch_bool_ } -SWITCH_DECLARE(void) switch_sqldb_stop_thread(switch_sql_manager_t *sql_manager) +SWITCH_DECLARE(void) switch_core_sqldb_stop_thread(void) { - switch_mutex_lock(sql_manager->ctl_mutex); - if (sql_manager->thread && sql_manager->thread_running) { + switch_mutex_lock(sql_manager.ctl_mutex); + if (sql_manager.thread && sql_manager.thread_running) { switch_status_t st; - if (sql_manager->manage) { - switch_queue_push(sql_manager->sql_queue[0], NULL); - switch_queue_push(sql_manager->sql_queue[1], NULL); + if (sql_manager.manage) { + switch_queue_push(sql_manager.sql_queue[0], NULL); + switch_queue_push(sql_manager.sql_queue[1], NULL); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Waiting for unfinished SQL transactions\n"); wake_thread(0); - sql_manager->thread_running = -1; - switch_thread_join(&st, sql_manager->thread); - sql_manager->thread = NULL; - switch_cache_db_release_db_handle(&sql_manager->dbh); - sql_manager->dbh = NULL; + sql_manager.thread_running = -1; + switch_thread_join(&st, sql_manager.thread); + sql_manager.thread = NULL; + switch_cache_db_release_db_handle(&sql_manager.dbh); + sql_manager.dbh = NULL; } else { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "SQL is not enabled\n"); } } else { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "SQL thread is not running\n"); } - switch_mutex_unlock(sql_manager->ctl_mutex); + switch_mutex_unlock(sql_manager.ctl_mutex); } - -void switch_core_recovery_create_indices(void) +SWITCH_DECLARE(void) switch_core_sqldb_start_thread(void) { switch_cache_db_handle_t *dbh; + switch_mutex_lock(sql_manager.ctl_mutex); + if (switch_core_recovery_db_handle(&dbh) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error Opening DB!\n"); @@ -2776,34 +2732,14 @@ void switch_core_recovery_create_indices(void) switch_cache_db_release_db_handle(&dbh); } -} - -SWITCH_DECLARE(void) switch_core_sqldb_start_thread(void) -{ - char *post_connect_sql[2]; - post_connect_sql[0] = "delete from channels"; - post_connect_sql[1] = "delete from calls"; - - switch_core_recovery_create_indices(); - switch_sqldb_start_thread(&switch_cache_db_sql_manager, switch_core_sql_thread, post_connect_sql, 2); - -} - -SWITCH_DECLARE(void) switch_sqldb_start_thread(switch_sql_manager_t *sql_manager, void *(SWITCH_THREAD_FUNC * func) (switch_thread_t *, void *), - char *post_connect_sql[], int argc) -{ - int i = 0; - - switch_mutex_lock(sql_manager->ctl_mutex); - - if (sql_manager->manage) { + if (sql_manager.manage) { top: - if (!sql_manager->dbh) { + if (!sql_manager.dbh) { /* Activate SQL database */ - if (switch_core_db_handle(&sql_manager->dbh) != SWITCH_STATUS_SUCCESS) { + if (switch_core_db_handle(&sql_manager.dbh) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error Opening DB!\n"); if (switch_test_flag((&runtime), SCF_CORE_NON_SQLITE_DB_REQ)) { @@ -2817,7 +2753,7 @@ SWITCH_DECLARE(void) switch_sqldb_start_thread(switch_sql_manager_t *sql_manager runtime.odbc_pass = NULL; runtime.odbc_dbtype = DBTYPE_DEFAULT; switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Falling back to core_db.\n"); - sql_manager->dbh = NULL; + sql_manager.dbh = NULL; goto top; } @@ -2826,21 +2762,18 @@ SWITCH_DECLARE(void) switch_sqldb_start_thread(switch_sql_manager_t *sql_manager goto end; } - if (argc && post_connect_sql) { - for ( i = 0; i < argc; i++) { - switch_cache_db_execute_sql(sql_manager->dbh, post_connect_sql[i], NULL); - } - } + switch_cache_db_execute_sql(sql_manager.dbh, "delete from channels", NULL); + switch_cache_db_execute_sql(sql_manager.dbh, "delete from calls", NULL); } - if (!sql_manager->thread) { + if (!sql_manager.thread) { switch_threadattr_t *thd_attr; switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Starting SQL thread.\n"); - switch_threadattr_create(&thd_attr, sql_manager->memory_pool); + switch_threadattr_create(&thd_attr, sql_manager.memory_pool); switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE); switch_threadattr_priority_set(thd_attr, SWITCH_PRI_REALTIME); - switch_thread_create(&sql_manager->thread, thd_attr, func, sql_manager, sql_manager->memory_pool); + switch_thread_create(&sql_manager.thread, thd_attr, switch_core_sql_thread, NULL, sql_manager.memory_pool); } else { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "SQL thread is already running\n"); } @@ -2850,38 +2783,28 @@ SWITCH_DECLARE(void) switch_sqldb_start_thread(switch_sql_manager_t *sql_manager end: - switch_mutex_unlock(sql_manager->ctl_mutex); + switch_mutex_unlock(sql_manager.ctl_mutex); } -void switch_sqldb_stop(switch_sql_manager_t *sql_manager) +void switch_core_sqldb_stop(void) { switch_status_t st; switch_event_unbind_callback(core_event_handler); - switch_sqldb_stop_thread(sql_manager); + switch_core_sqldb_stop_thread(); - if (sql_manager->db_thread && sql_manager->db_thread_running) { - sql_manager->db_thread_running = -1; - switch_thread_join(&st, sql_manager->db_thread); + if (sql_manager.db_thread && sql_manager.db_thread_running) { + sql_manager.db_thread_running = -1; + switch_thread_join(&st, sql_manager.db_thread); } - switch_cache_db_flush_handles(sql_manager); - sql_close(sql_manager, 0); -} - -void switch_core_sqldb_stop() -{ - switch_sqldb_stop(&switch_cache_db_sql_manager); + switch_cache_db_flush_handles(); + sql_close(0); } SWITCH_DECLARE(void) switch_cache_db_status(switch_stream_handle_t *stream) -{ - _switch_cache_db_status(&switch_cache_db_sql_manager, stream); -} - -SWITCH_DECLARE(void) _switch_cache_db_status(switch_sql_manager_t *sql_manager, switch_stream_handle_t *stream) { /* return some status info suitable for the cli */ switch_cache_db_handle_t *dbh = NULL; @@ -2892,16 +2815,11 @@ SWITCH_DECLARE(void) _switch_cache_db_status(switch_sql_manager_t *sql_manager, char *pos2 = NULL; int count = 0, used = 0; - switch_mutex_lock(sql_manager->dbh_mutex); + switch_mutex_lock(sql_manager.dbh_mutex); - for (dbh = sql_manager->handle_pool; dbh; dbh = dbh->next) { - char *needles[3]; + for (dbh = sql_manager.handle_pool; dbh; dbh = dbh->next) { + char *needle = "pass=\""; time_t diff = 0; - int i = 0; - - needles[0] = "pass=\""; - needles[1] = "password="; - needles[2] = "password='"; diff = now - dbh->last_used; @@ -2914,26 +2832,11 @@ SWITCH_DECLARE(void) _switch_cache_db_status(switch_sql_manager_t *sql_manager, /* sanitize password */ memset(cleankey_str, 0, sizeof(cleankey_str)); - for (i = 0; i < 3; i++) { - if((pos1 = strstr(dbh->name, needles[i]))) { - pos1 += strlen(needles[i]); - - if (!(pos2 = strstr(pos1, "\""))) { - if (!(pos2 = strstr(pos1, "'"))) { - if (!(pos2 = strstr(pos1, " "))) { - pos2 = pos1 + strlen(pos1); - } - } - } - strncpy(cleankey_str, dbh->name, pos1 - dbh->name); - strcpy(&cleankey_str[pos1 - dbh->name], pos2); - break; - } - } - if (i == 3) { - strncpy(cleankey_str, dbh->name, strlen(dbh->name)); - } - + pos1 = strstr(dbh->name, needle) + strlen(needle); + pos2 = strstr(pos1, "\""); + strncpy(cleankey_str, dbh->name, pos1 - dbh->name); + strcpy(&cleankey_str[pos1 - dbh->name], pos2); + count++; if (dbh->use_count) { @@ -2951,7 +2854,7 @@ SWITCH_DECLARE(void) _switch_cache_db_status(switch_sql_manager_t *sql_manager, stream->write_function(stream, "%d total. %d in use.\n", count, used); - switch_mutex_unlock(sql_manager->dbh_mutex); + switch_mutex_unlock(sql_manager.dbh_mutex); } SWITCH_DECLARE(char*)switch_sql_concat(void) From bcfc2dbeb159aa1d2443e804e4fc496eac8ab9ba Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Mon, 8 Oct 2012 16:28:03 -0500 Subject: [PATCH 137/252] we do want this one bit from the last patch --- src/switch_core_sqldb.c | 32 ++++++++++++++++++++++++++------ 1 file changed, 26 insertions(+), 6 deletions(-) diff --git a/src/switch_core_sqldb.c b/src/switch_core_sqldb.c index b679baab0c..bb82202fbc 100644 --- a/src/switch_core_sqldb.c +++ b/src/switch_core_sqldb.c @@ -2818,8 +2818,13 @@ SWITCH_DECLARE(void) switch_cache_db_status(switch_stream_handle_t *stream) switch_mutex_lock(sql_manager.dbh_mutex); for (dbh = sql_manager.handle_pool; dbh; dbh = dbh->next) { - char *needle = "pass=\""; + char *needles[3]; time_t diff = 0; + int i = 0; + + needles[0] = "pass=\""; + needles[1] = "password="; + needles[2] = "password='"; diff = now - dbh->last_used; @@ -2832,11 +2837,26 @@ SWITCH_DECLARE(void) switch_cache_db_status(switch_stream_handle_t *stream) /* sanitize password */ memset(cleankey_str, 0, sizeof(cleankey_str)); - pos1 = strstr(dbh->name, needle) + strlen(needle); - pos2 = strstr(pos1, "\""); - strncpy(cleankey_str, dbh->name, pos1 - dbh->name); - strcpy(&cleankey_str[pos1 - dbh->name], pos2); - + for (i = 0; i < 3; i++) { + if((pos1 = strstr(dbh->name, needles[i]))) { + pos1 += strlen(needles[i]); + + if (!(pos2 = strstr(pos1, "\""))) { + if (!(pos2 = strstr(pos1, "'"))) { + if (!(pos2 = strstr(pos1, " "))) { + pos2 = pos1 + strlen(pos1); + } + } + } + strncpy(cleankey_str, dbh->name, pos1 - dbh->name); + strcpy(&cleankey_str[pos1 - dbh->name], pos2); + break; + } + } + if (i == 3) { + strncpy(cleankey_str, dbh->name, strlen(dbh->name)); + } + count++; if (dbh->use_count) { From a20c556fb79f3de2d3c00db89e6c418829f24e36 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Mon, 8 Oct 2012 16:34:39 -0500 Subject: [PATCH 138/252] FS-4650 --resolve --- src/mod/applications/mod_commands/mod_commands.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/mod/applications/mod_commands/mod_commands.c b/src/mod/applications/mod_commands/mod_commands.c index 5923860507..7287d95acc 100644 --- a/src/mod/applications/mod_commands/mod_commands.c +++ b/src/mod/applications/mod_commands/mod_commands.c @@ -285,7 +285,7 @@ SWITCH_STANDARD_API(list_users_function) int32_t arg = 0; switch_xml_t xml_root, x_domains, x_domain_tag; switch_xml_t gts, gt, uts, ut; - char *_user = NULL, *_domain = NULL, *_group = NULL; + char *_user = NULL, *_domain = NULL, *_search_context = NULL, *_group = NULL; if ((pdata = strdup(cmd))) { @@ -300,10 +300,12 @@ SWITCH_STANDARD_API(list_users_function) if (!strcasecmp(argv[arg], "user")) { _user = argv[arg + 1]; } + if (!strcasecmp(argv[arg], "context")) { + _search_context = argv[arg + 1]; + } if (!strcasecmp(argv[arg], "domain")) { _domain = argv[arg + 1]; } - if (!strcasecmp(argv[arg], "group")) { _group = argv[arg + 1]; } @@ -370,6 +372,7 @@ SWITCH_STANDARD_API(list_users_function) us.x_user_tag = ut; us.x_domain_tag = x_domain_tag; us.stream = stream; + us.search_context = _search_context; dump_user(&us); } } @@ -383,6 +386,7 @@ SWITCH_STANDARD_API(list_users_function) us.x_user_tag = ut; us.x_domain_tag = x_domain_tag; us.stream = stream; + us.search_context = _search_context; dump_user(&us); } } From 7d7eaee942ecf8c3e2dd7dd6eef619d17dc1ba99 Mon Sep 17 00:00:00 2001 From: Eliot Gable Date: Mon, 8 Oct 2012 22:22:34 +0000 Subject: [PATCH 139/252] Switch to Poll instead of Select. --- src/switch_pgsql.c | 52 ++++++++++++++++++++++++++-------------------- 1 file changed, 30 insertions(+), 22 deletions(-) diff --git a/src/switch_pgsql.c b/src/switch_pgsql.c index 1094aee20b..2b695c3f7d 100644 --- a/src/switch_pgsql.c +++ b/src/switch_pgsql.c @@ -35,6 +35,7 @@ #ifdef SWITCH_HAVE_PGSQL #include +#include struct switch_pgsql_handle { @@ -168,8 +169,8 @@ SWITCH_DECLARE(switch_pgsql_status_t) switch_pgsql_next_result_timed(switch_pgsq switch_time_t ctime; unsigned int usec = msec * 1000; char *err_str; - fd_set pgset; - struct timeval timeout; + struct pollfd fds[2] = { {0} }; + int poll_res = 0; if(!handle) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "**BUG** Null handle passed to switch_pgsql_next_result.\n"); @@ -183,30 +184,37 @@ SWITCH_DECLARE(switch_pgsql_status_t) switch_pgsql_next_result_timed(switch_pgsq /* Wait for a result to become available, up to msec milliseconds */ start = switch_time_now(); - while((ctime = switch_time_now()) - start <= usec) { - FD_ZERO(&pgset); - FD_SET(handle->sock, &pgset); + while((ctime = switch_micro_time_now()) - start <= usec) { + int wait_time = (usec - (ctime - start)) / 1000; + fds[0].fd = handle->sock; + fds[0].events |= POLLIN; + fds[0].events |= POLLERR; - timeout.tv_sec = 0; - timeout.tv_usec = 500; - /* Wait for the PostgreSQL socket to be ready for data reads. */ - if (select(FD_SETSIZE, &pgset, NULL, NULL, &timeout) > 0) { - /* Then try to consume any input waiting. */ - if (PQconsumeInput(handle->con)) { - /* And check to see if we have a full result ready for reading */ - if (!PQisBusy(handle->con)) { - /* If we can pull a full result without blocking, then break this loop */ - break; + if ((poll_res = poll(&fds[0], 1, wait_time)) > -1 ) { + if (fds[0].revents & POLLIN) { + /* Then try to consume any input waiting. */ + if (PQconsumeInput(handle->con)) { + /* And check to see if we have a full result ready for reading */ + if (!PQisBusy(handle->con)) { + /* If we can pull a full result without blocking, then break this loop */ + break; + } + } else { + /* If we had an error trying to consume input, report it and cancel the query. */ + err_str = switch_pgsql_handle_get_error(handle); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "An error occurred trying to consume input for query (%s): %s\n", handle->sql, err_str); + switch_safe_free(err_str); + switch_pgsql_cancel(handle); + goto error; } - } else { - /* If we had an error trying to consume input, report it and cancel the query. */ - err_str = switch_pgsql_handle_get_error(handle); - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "An error occurred trying to consume input for query (%s): %s\n", handle->sql, err_str); - switch_safe_free(err_str); - switch_pgsql_cancel(handle); + } else if (fds[0].revents & POLLERR) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Poll error trying to read PGSQL socket for query (%s)\n", handle->sql); goto error; } + } else { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Poll failed trying to read PGSQL socket for query (%s)\n", handle->sql); + goto error; } } @@ -318,7 +326,7 @@ SWITCH_DECLARE(switch_pgsql_status_t) switch_pgsql_finish_results_real(const cha #endif } -#ifdef SWITCH_HAVE_PG +#ifdef SWITCH_HAVE_PGSQL static int db_is_up(switch_pgsql_handle_t *handle) { int ret = 0; From f059d97ff8b6724c7aca655bf4ca1ef6a8c860a9 Mon Sep 17 00:00:00 2001 From: Eliot Gable Date: Mon, 8 Oct 2012 22:48:26 +0000 Subject: [PATCH 140/252] Terminate buffers! --- src/switch_pgsql.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/switch_pgsql.c b/src/switch_pgsql.c index 2b695c3f7d..fc02ab73d5 100644 --- a/src/switch_pgsql.c +++ b/src/switch_pgsql.c @@ -629,10 +629,12 @@ SWITCH_DECLARE(switch_pgsql_status_t) switch_pgsql_handle_callback_exec_detailed if (tmp) { len = strlen(tmp); names[col] = malloc(len+1); + names[col][len] = '\0'; strncpy(names[col], tmp, len); len = PQgetlength(result->result, row, col); vals[col] = malloc(len+1); + vals[col][len] = '\0'; tmp = PQgetvalue(result->result, row, col); strncpy(vals[col], tmp, len); } else { From a0a584b0c95cbc187747e6f9e27c30cfcb4f3ca5 Mon Sep 17 00:00:00 2001 From: Ken Rice Date: Mon, 8 Oct 2012 20:56:54 -0400 Subject: [PATCH 141/252] you cant have -- inside an xml comment... we should really be testing changes like this to the config files before we push this as this wouldnt even make it past a clean install start up or reloadxml test --- conf/vanilla/autoload_configs/switch.conf.xml | 1 - 1 file changed, 1 deletion(-) diff --git a/conf/vanilla/autoload_configs/switch.conf.xml b/conf/vanilla/autoload_configs/switch.conf.xml index 34bdedcda9..fc0ac21b82 100644 --- a/conf/vanilla/autoload_configs/switch.conf.xml +++ b/conf/vanilla/autoload_configs/switch.conf.xml @@ -144,7 +144,6 @@ - + + + + diff --git a/src/mod/event_handlers/mod_cdr_mongodb/mod_cdr_mongodb.c b/src/mod/event_handlers/mod_cdr_mongodb/mod_cdr_mongodb.c index 003e57da82..0e8f67a2c3 100644 --- a/src/mod/event_handlers/mod_cdr_mongodb/mod_cdr_mongodb.c +++ b/src/mod/event_handlers/mod_cdr_mongodb/mod_cdr_mongodb.c @@ -39,6 +39,8 @@ static struct { char *mongo_host; uint32_t mongo_port; char *mongo_namespace; + char *mongo_username; + char *mongo_password; mongo mongo_conn[1]; switch_mutex_t *mongo_mutex; switch_bool_t log_b; @@ -48,6 +50,8 @@ static switch_xml_config_item_t config_settings[] = { /* key, flags, ptr, default_value, syntax, helptext */ SWITCH_CONFIG_ITEM_STRING_STRDUP("host", CONFIG_REQUIRED, &globals.mongo_host, "127.0.0.1", NULL, "MongoDB server host address"), SWITCH_CONFIG_ITEM_STRING_STRDUP("namespace", CONFIG_REQUIRED, &globals.mongo_namespace, NULL, "database.collection", "MongoDB namespace"), + SWITCH_CONFIG_ITEM_STRING_STRDUP("username", CONFIG_RELOADABLE, &globals.mongo_username, NULL, NULL, "MongoDB username"), + SWITCH_CONFIG_ITEM_STRING_STRDUP("password", CONFIG_RELOADABLE, &globals.mongo_password, NULL, NULL, "MongoDB password"), /* key, type, flags, ptr, default_value, data, syntax, helptext */ SWITCH_CONFIG_ITEM("port", SWITCH_CONFIG_INT, CONFIG_REQUIRED, &globals.mongo_port, 27017, NULL, NULL, "MongoDB server TCP port"), @@ -79,6 +83,29 @@ static void set_bson_profile_data(bson *b, switch_caller_profile_t *caller_profi } +static switch_status_t cdr_mongo_authenticate() { + switch_status_t status = SWITCH_STATUS_SUCCESS; + mongo_error_t db_status; + char *ns_tmp, *ns_split[2]; + + /* Split namespace db.collection into separate vars */ + switch_strdup(ns_tmp, globals.mongo_namespace); + switch_separate_string(ns_tmp, '.', ns_split, 2); + + db_status = mongo_cmd_authenticate(globals.mongo_conn, ns_split[0], globals.mongo_username, globals.mongo_password); + + if (db_status != MONGO_OK) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "mongo_cmd_authenticate: authentication failed\n"); + status = SWITCH_STATUS_FALSE; + } else { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Successfully authenticated %s@%s\n", globals.mongo_username, ns_split[0]); + } + + switch_safe_free(ns_tmp); + return status; +} + + static switch_status_t my_on_reporting(switch_core_session_t *session) { switch_status_t status = SWITCH_STATUS_SUCCESS; @@ -306,14 +333,22 @@ static switch_status_t my_on_reporting(switch_core_session_t *session) status = SWITCH_STATUS_FALSE; } else { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "MongoDB connection re-established.\n"); - if (mongo_insert(globals.mongo_conn, globals.mongo_namespace, &cdr, NULL) != MONGO_OK) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "mongo_insert: error code %d\n", globals.mongo_conn->err); - status = SWITCH_STATUS_FALSE; + + /* Re-authentication is necessary after a reconnect */ + if (globals.mongo_username && globals.mongo_password) { + status = cdr_mongo_authenticate(); + } + + if (db_status == MONGO_OK) { + if (mongo_insert(globals.mongo_conn, globals.mongo_namespace, &cdr, NULL) != MONGO_OK) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "mongo_insert: %s (error code %d)\n", globals.mongo_conn->errstr, globals.mongo_conn->err); + status = SWITCH_STATUS_FALSE; + } } } } else { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "mongo_insert: error code %d\n", globals.mongo_conn->err); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "mongo_insert: %s (error code %d)\n", globals.mongo_conn->errstr, globals.mongo_conn->err); status = SWITCH_STATUS_FALSE; } } @@ -385,6 +420,10 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_cdr_mongodb_load) switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Connected to MongoDB server %s:%d\n", globals.mongo_host, globals.mongo_port); } + if (globals.mongo_username && globals.mongo_password) { + status = cdr_mongo_authenticate(); + } + switch_mutex_init(&globals.mongo_mutex, SWITCH_MUTEX_NESTED, pool); switch_core_add_state_handler(&state_handlers); From 2b6e3425348809f3053687eca3c7078c7c584b7e Mon Sep 17 00:00:00 2001 From: Daniel Swarbrick Date: Sun, 21 Oct 2012 16:21:01 +0200 Subject: [PATCH 221/252] mod_cdr_mongodb: tweak auth handling --- .../event_handlers/mod_cdr_mongodb/mod_cdr_mongodb.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/mod/event_handlers/mod_cdr_mongodb/mod_cdr_mongodb.c b/src/mod/event_handlers/mod_cdr_mongodb/mod_cdr_mongodb.c index 0e8f67a2c3..5187cfb23c 100644 --- a/src/mod/event_handlers/mod_cdr_mongodb/mod_cdr_mongodb.c +++ b/src/mod/event_handlers/mod_cdr_mongodb/mod_cdr_mongodb.c @@ -339,11 +339,9 @@ static switch_status_t my_on_reporting(switch_core_session_t *session) status = cdr_mongo_authenticate(); } - if (db_status == MONGO_OK) { - if (mongo_insert(globals.mongo_conn, globals.mongo_namespace, &cdr, NULL) != MONGO_OK) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "mongo_insert: %s (error code %d)\n", globals.mongo_conn->errstr, globals.mongo_conn->err); - status = SWITCH_STATUS_FALSE; - } + if (mongo_insert(globals.mongo_conn, globals.mongo_namespace, &cdr, NULL) != MONGO_OK) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "mongo_insert: %s (error code %d)\n", globals.mongo_conn->errstr, globals.mongo_conn->err); + status = SWITCH_STATUS_FALSE; } } @@ -421,7 +419,9 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_cdr_mongodb_load) } if (globals.mongo_username && globals.mongo_password) { - status = cdr_mongo_authenticate(); + if (cdr_mongo_authenticate() != SWITCH_STATUS_SUCCESS) { + return SWITCH_STATUS_FALSE; + } } switch_mutex_init(&globals.mongo_mutex, SWITCH_MUTEX_NESTED, pool); From b53e4ed80003ee266cccbc9f69c7dbdeb4aaa316 Mon Sep 17 00:00:00 2001 From: Daniel Swarbrick Date: Sun, 21 Oct 2012 17:52:45 +0200 Subject: [PATCH 222/252] mod_cdr_mongodb: add support for replica sets (refs FS-4668) --- .../autoload_configs/cdr_mongodb.conf.xml | 3 +- .../mod_cdr_mongodb/mod_cdr_mongodb.c | 51 +++++++++++++++++-- 2 files changed, 48 insertions(+), 6 deletions(-) diff --git a/src/mod/event_handlers/mod_cdr_mongodb/conf/autoload_configs/cdr_mongodb.conf.xml b/src/mod/event_handlers/mod_cdr_mongodb/conf/autoload_configs/cdr_mongodb.conf.xml index 92751004ff..6750c46863 100644 --- a/src/mod/event_handlers/mod_cdr_mongodb/conf/autoload_configs/cdr_mongodb.conf.xml +++ b/src/mod/event_handlers/mod_cdr_mongodb/conf/autoload_configs/cdr_mongodb.conf.xml @@ -1,6 +1,7 @@ - + diff --git a/src/mod/event_handlers/mod_cdr_mongodb/mod_cdr_mongodb.c b/src/mod/event_handlers/mod_cdr_mongodb/mod_cdr_mongodb.c index 5187cfb23c..d4c4d7cf9a 100644 --- a/src/mod/event_handlers/mod_cdr_mongodb/mod_cdr_mongodb.c +++ b/src/mod/event_handlers/mod_cdr_mongodb/mod_cdr_mongodb.c @@ -33,12 +33,15 @@ #include #include +#define MONGO_REPLSET_MAX_MEMBERS 12 + static struct { switch_memory_pool_t *pool; int shutdown; char *mongo_host; - uint32_t mongo_port; + int mongo_port; char *mongo_namespace; + char *mongo_replset_name; char *mongo_username; char *mongo_password; mongo mongo_conn[1]; @@ -50,11 +53,12 @@ static switch_xml_config_item_t config_settings[] = { /* key, flags, ptr, default_value, syntax, helptext */ SWITCH_CONFIG_ITEM_STRING_STRDUP("host", CONFIG_REQUIRED, &globals.mongo_host, "127.0.0.1", NULL, "MongoDB server host address"), SWITCH_CONFIG_ITEM_STRING_STRDUP("namespace", CONFIG_REQUIRED, &globals.mongo_namespace, NULL, "database.collection", "MongoDB namespace"), + SWITCH_CONFIG_ITEM_STRING_STRDUP("replica_set_name", CONFIG_RELOADABLE, &globals.mongo_replset_name, "cdr_mongodb", NULL, "MongoDB replica set name"), SWITCH_CONFIG_ITEM_STRING_STRDUP("username", CONFIG_RELOADABLE, &globals.mongo_username, NULL, NULL, "MongoDB username"), SWITCH_CONFIG_ITEM_STRING_STRDUP("password", CONFIG_RELOADABLE, &globals.mongo_password, NULL, NULL, "MongoDB password"), /* key, type, flags, ptr, default_value, data, syntax, helptext */ - SWITCH_CONFIG_ITEM("port", SWITCH_CONFIG_INT, CONFIG_REQUIRED, &globals.mongo_port, 27017, NULL, NULL, "MongoDB server TCP port"), + SWITCH_CONFIG_ITEM("port", SWITCH_CONFIG_INT, CONFIG_REQUIRED, &globals.mongo_port, MONGO_DEFAULT_PORT, NULL, NULL, "MongoDB server TCP port"), SWITCH_CONFIG_ITEM("log-b-leg", SWITCH_CONFIG_BOOL, CONFIG_RELOADABLE, &globals.log_b, SWITCH_TRUE, NULL, NULL, "Log B-leg in addition to A-leg"), SWITCH_CONFIG_ITEM_END() @@ -389,6 +393,9 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_cdr_mongodb_load) { switch_status_t status = SWITCH_STATUS_SUCCESS; mongo_error_t db_status; + char *repl_hosts[MONGO_REPLSET_MAX_MEMBERS]; + char *mongo_host[2]; + int num_hosts, mongo_port; memset(&globals, 0, sizeof(globals)); globals.pool = pool; @@ -397,7 +404,32 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_cdr_mongodb_load) return SWITCH_STATUS_FALSE; } - db_status = mongo_connect(globals.mongo_conn, globals.mongo_host, globals.mongo_port); + num_hosts = switch_separate_string(globals.mongo_host, ',', repl_hosts, MONGO_REPLSET_MAX_MEMBERS); + + if (num_hosts > 1) { + int i; + + mongo_replset_init(globals.mongo_conn, globals.mongo_replset_name); + + for (i = 0; i < num_hosts; i++) { + switch_separate_string(repl_hosts[i], ':', mongo_host, 2); + mongo_port = mongo_host[1] ? atoi(mongo_host[1]) : globals.mongo_port; + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Adding MongoDB server %s:%d to replica set\n", mongo_host[0], mongo_port); + mongo_replset_add_seed(globals.mongo_conn, mongo_host[0], mongo_port); + } + + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Connecting to MongoDB replica set %s\n", globals.mongo_replset_name); + db_status = mongo_replset_connect(globals.mongo_conn); + } else { + switch_separate_string(globals.mongo_host, ':', mongo_host, 2); + + if (mongo_host[1]) { + globals.mongo_port = atoi(mongo_host[1]); + } + + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Connecting to MongoDB server %s:%d\n", globals.mongo_host, globals.mongo_port); + db_status = mongo_connect(globals.mongo_conn, globals.mongo_host, globals.mongo_port); + } if (db_status != MONGO_OK) { switch (globals.mongo_conn->err) { @@ -407,15 +439,24 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_cdr_mongodb_load) case MONGO_CONN_FAIL: switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "mongo_connect: connection failed\n"); break; + case MONGO_CONN_ADDR_FAIL: + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "mongo_connect: hostname lookup failed\n"); + break; case MONGO_CONN_NOT_MASTER: switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "mongo_connect: not master\n"); break; + case MONGO_CONN_BAD_SET_NAME: + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "mongo_replset_connect: configured replica set name does not match\n"); + break; + case MONGO_CONN_NO_PRIMARY: + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "mongo_replset_connect: cannot find replica set primary member\n"); + break; default: - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "mongo_connect: unknown error %d\n", db_status); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "mongo_connect: unknown error: status code %d, error code %d\n", db_status, globals.mongo_conn->err); } return SWITCH_STATUS_FALSE; } else { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Connected to MongoDB server %s:%d\n", globals.mongo_host, globals.mongo_port); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Connection established\n"); } if (globals.mongo_username && globals.mongo_password) { From a92fb019c54e6e70e9b4402d03062316a7ee90d5 Mon Sep 17 00:00:00 2001 From: Daniel Swarbrick Date: Sun, 21 Oct 2012 17:55:13 +0200 Subject: [PATCH 223/252] Add missing config param to sample config --- .../mod_cdr_mongodb/conf/autoload_configs/cdr_mongodb.conf.xml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/mod/event_handlers/mod_cdr_mongodb/conf/autoload_configs/cdr_mongodb.conf.xml b/src/mod/event_handlers/mod_cdr_mongodb/conf/autoload_configs/cdr_mongodb.conf.xml index 6750c46863..86e43d2098 100644 --- a/src/mod/event_handlers/mod_cdr_mongodb/conf/autoload_configs/cdr_mongodb.conf.xml +++ b/src/mod/event_handlers/mod_cdr_mongodb/conf/autoload_configs/cdr_mongodb.conf.xml @@ -5,6 +5,9 @@ + + + From 58f1ee7ff0057675bbf14d10c0b9c69e706601c1 Mon Sep 17 00:00:00 2001 From: Daniel Swarbrick Date: Sun, 21 Oct 2012 22:59:51 +0200 Subject: [PATCH 224/252] mod_cdr_mongodb: add post-v0.6 patch to driver to support Unix domain sockets --- .../mod_cdr_mongodb/driver/src/env_posix.c | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/src/mod/event_handlers/mod_cdr_mongodb/driver/src/env_posix.c b/src/mod/event_handlers/mod_cdr_mongodb/driver/src/env_posix.c index f1020ca80d..ab0e166cf9 100644 --- a/src/mod/event_handlers/mod_cdr_mongodb/driver/src/env_posix.c +++ b/src/mod/event_handlers/mod_cdr_mongodb/driver/src/env_posix.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -99,6 +100,36 @@ int mongo_env_set_socket_op_timeout( mongo *conn, int millis ) { return MONGO_OK; } +int mongo_env_unix_socket_connect( mongo *conn, const char *sock_path ) { + struct sockaddr_un addr; + int status, len; + + conn->connected = 0; + + conn->sock = socket( AF_UNIX, SOCK_STREAM, 0 ); + + if ( conn->sock < 0 ) { + conn->sock = 0; + return MONGO_ERROR; + } + + addr.sun_family = AF_UNIX; + strncpy( addr.sun_path, sock_path, sizeof(addr.sun_path) - 1 ); + len = sizeof( addr ); + + status = connect( conn->sock, (struct sockaddr *) &addr, len ); + if( status < 0 ){ + mongo_env_close_socket( conn->sock ); + conn->sock = 0; + conn->err = MONGO_CONN_FAIL; + return MONGO_ERROR; + } + + conn->connected = 1; + + return MONGO_OK; +} + int mongo_env_socket_connect( mongo *conn, const char *host, int port ) { char port_str[NI_MAXSERV]; int status; @@ -107,6 +138,10 @@ int mongo_env_socket_connect( mongo *conn, const char *host, int port ) { struct addrinfo *ai_list = NULL; struct addrinfo *ai_ptr = NULL; + if ( port < 0 ) { + return mongo_env_unix_socket_connect( conn, host ); + } + conn->sock = 0; conn->connected = 0; sprintf(port_str,"%d",port); From 970b2f176588a27676e4ada15c39d665dbc14fd5 Mon Sep 17 00:00:00 2001 From: Jeff Lenk Date: Sun, 21 Oct 2012 22:43:21 -0500 Subject: [PATCH 225/252] FS-4722 german say date day month year --- src/mod/say/mod_say_de/mod_say_de.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mod/say/mod_say_de/mod_say_de.c b/src/mod/say/mod_say_de/mod_say_de.c index b4ae2d83b4..1c1871732c 100644 --- a/src/mod/say/mod_say_de/mod_say_de.c +++ b/src/mod/say/mod_say_de/mod_say_de.c @@ -310,8 +310,8 @@ static switch_status_t de_say_time(switch_core_session_t *session, char *tosay, if (say_date) { say_file("time/day-%d.wav", tm.tm_wday); + say_num(tm.tm_mday, SSM_COUNTED); say_file("time/mon-%d.wav", tm.tm_mon); - say_num(tm.tm_mday, SSM_COUNTED); say_num(tm.tm_year + 1900, SSM_PRONOUNCED); } From 09c03667a8f3ff917ad0bc283fd79131a3b038ac Mon Sep 17 00:00:00 2001 From: Jeff Lenk Date: Sun, 21 Oct 2012 22:53:02 -0500 Subject: [PATCH 226/252] FS-4721 --resolve --- src/mod/say/mod_say_de/mod_say_de.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/mod/say/mod_say_de/mod_say_de.c b/src/mod/say/mod_say_de/mod_say_de.c index 1c1871732c..b38f02a798 100644 --- a/src/mod/say/mod_say_de/mod_say_de.c +++ b/src/mod/say/mod_say_de/mod_say_de.c @@ -97,12 +97,14 @@ static switch_status_t play_group(switch_say_method_t method, switch_say_gender_ if (b) { if (b > 1) { /*german nominativ for "one" in numbers like 21, 171, 4591 is flexed, 2-9 are not*/ - if ( c == 1 ) { - say_file("digits/s-1.wav"); - } else { - say_file("digits/%d.wav", c); - } - say_file("currency/and.wav"); + if (c > 0) { + if ( c == 1 ) { + say_file("digits/s-1.wav"); + } else { + say_file("digits/%d.wav", c); + } + say_file("currency/and.wav"); + } if (method == SSM_COUNTED) { say_file("digits/h-%d0.wav", b); } else { From a8ee444ab984eedee653ae162a9f05c96aa570e2 Mon Sep 17 00:00:00 2001 From: Jeff Lenk Date: Mon, 22 Oct 2012 09:24:45 -0500 Subject: [PATCH 227/252] FS-4748 --resolve --- src/switch_channel.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/switch_channel.c b/src/switch_channel.c index 6e4c607822..fd00c5f71e 100644 --- a/src/switch_channel.c +++ b/src/switch_channel.c @@ -268,7 +268,7 @@ SWITCH_DECLARE(const char *) switch_channel_callstate2str(switch_channel_callsta } -SWITCH_DECLARE(switch_call_cause_t) switch_channel_str2callstate(const char *str) +SWITCH_DECLARE(switch_channel_callstate_t) switch_channel_str2callstate(const char *str) { uint8_t x; switch_channel_callstate_t callstate = (switch_channel_callstate_t) SWITCH_CAUSE_NONE; @@ -283,7 +283,7 @@ SWITCH_DECLARE(switch_call_cause_t) switch_channel_str2callstate(const char *str } } } - return (switch_call_cause_t) callstate; + return callstate; } From 17d1ffe45c8b42e19a7c3815b63ab9879cded5f2 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Mon, 22 Oct 2012 11:56:22 -0400 Subject: [PATCH 228/252] FS-4748 the change to the header file did not make it into the commit --- src/include/switch_channel.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/include/switch_channel.h b/src/include/switch_channel.h index f4655a23e6..bddfb0f2d2 100644 --- a/src/include/switch_channel.h +++ b/src/include/switch_channel.h @@ -631,7 +631,7 @@ SWITCH_DECLARE(void) switch_channel_perform_set_callstate(switch_channel_t *chan #define switch_channel_set_callstate(channel, state) switch_channel_perform_set_callstate(channel, state, __FILE__, __SWITCH_FUNC__, __LINE__) SWITCH_DECLARE(switch_channel_callstate_t) switch_channel_get_callstate(switch_channel_t *channel); SWITCH_DECLARE(const char *) switch_channel_callstate2str(switch_channel_callstate_t callstate); -SWITCH_DECLARE(switch_call_cause_t) switch_channel_str2callstate(const char *str); +SWITCH_DECLARE(switch_channel_callstate_t) switch_channel_str2callstate(const char *str); SWITCH_DECLARE(void) switch_channel_mark_hold(switch_channel_t *channel, switch_bool_t on); /** @} */ From 4b6db1329c9983589e6f4f1036526a2d49e57f63 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Mon, 22 Oct 2012 13:37:41 -0400 Subject: [PATCH 229/252] FS-4729 try this patch clean --- src/include/switch_types.h | 1 + src/switch_ivr.c | 20 +++++++++++++++++++- 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/src/include/switch_types.h b/src/include/switch_types.h index c4c2ed7190..b766d1db40 100644 --- a/src/include/switch_types.h +++ b/src/include/switch_types.h @@ -1249,6 +1249,7 @@ typedef enum { CF_TRACKABLE, CF_NO_CDR, CF_EARLY_OK, + CF_MEDIA_TRANS, /* WARNING: DO NOT ADD ANY FLAGS BELOW THIS LINE */ /* IF YOU ADD NEW ONES CHECK IF THEY SHOULD PERSIST OR ZERO THEM IN switch_core_session.c switch_core_session_request_xml() */ CF_FLAG_MAX diff --git a/src/switch_ivr.c b/src/switch_ivr.c index b6c1127b31..b8fd0923e3 100644 --- a/src/switch_ivr.c +++ b/src/switch_ivr.c @@ -1476,6 +1476,13 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_media(const char *uuid, switch_media_ if ((session = switch_core_session_locate(uuid))) { channel = switch_core_session_get_channel(session); + + if (switch_channel_test_flag(channel, CF_MEDIA_TRANS)) { + switch_core_session_rwunlock(session); + return SWITCH_STATUS_INUSE; + } + + switch_channel_set_flag(channel, CF_MEDIA_TRANS); if ((flags & SMF_REBRIDGE) && !switch_channel_test_flag(channel, CF_BRIDGE_ORIGINATOR)) { swap = 1; @@ -1527,6 +1534,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_media(const char *uuid, switch_media_ } } + switch_channel_clear_flag(channel, CF_MEDIA_TRANS); switch_core_session_rwunlock(session); if (other_channel) { @@ -1559,6 +1567,13 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_nomedia(const char *uuid, switch_medi status = SWITCH_STATUS_SUCCESS; channel = switch_core_session_get_channel(session); + if (switch_channel_test_flag(channel, CF_MEDIA_TRANS)) { + switch_core_session_rwunlock(session); + return SWITCH_STATUS_INUSE; + } + + switch_channel_set_flag(channel, CF_MEDIA_TRANS); + if ((flags & SMF_REBRIDGE) && !switch_channel_test_flag(channel, CF_BRIDGE_ORIGINATOR)) { swap = 1; } @@ -1617,9 +1632,12 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_nomedia(const char *uuid, switch_medi switch_core_session_rwunlock(other_session); } } - switch_core_session_rwunlock(session); + + switch_channel_clear_flag(channel, CF_MEDIA_TRANS); } + + return status; } From 5ff654dab51014a37f7043206ea2fbe685e201f1 Mon Sep 17 00:00:00 2001 From: Seven Du Date: Tue, 23 Oct 2012 10:44:31 +0800 Subject: [PATCH 230/252] fix NIL case --- src/mod/event_handlers/mod_erlang_event/ei_helpers.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/mod/event_handlers/mod_erlang_event/ei_helpers.c b/src/mod/event_handlers/mod_erlang_event/ei_helpers.c index 0206f37718..9d39b725d7 100644 --- a/src/mod/event_handlers/mod_erlang_event/ei_helpers.c +++ b/src/mod/event_handlers/mod_erlang_event/ei_helpers.c @@ -305,6 +305,11 @@ int ei_decode_string_or_binary(char *buf, int *index, int maxlen, char *dst) ei_get_type(buf, index, &type, &size); + if (type == ERL_NIL_EXT || size == 0) { + dst[0] = '\0'; + return 0; + } + if (type != ERL_STRING_EXT && type != ERL_BINARY_EXT) { return -1; } else if (size > maxlen) { From 8589e031d0ff9792275c70016d881caa9e625a9b Mon Sep 17 00:00:00 2001 From: Jeff Lenk Date: Mon, 22 Oct 2012 22:01:22 -0500 Subject: [PATCH 231/252] vs2010 reswig --- .../mod_managed/freeswitch_wrap.2010.cxx | 472 ++++++++++++++++- .../mod_managed/managed/swig.2010.cs | 484 +++++++++++++++++- 2 files changed, 944 insertions(+), 12 deletions(-) diff --git a/src/mod/languages/mod_managed/freeswitch_wrap.2010.cxx b/src/mod/languages/mod_managed/freeswitch_wrap.2010.cxx index 51e4d83cf7..40aab99e82 100644 --- a/src/mod/languages/mod_managed/freeswitch_wrap.2010.cxx +++ b/src/mod/languages/mod_managed/freeswitch_wrap.2010.cxx @@ -7867,6 +7867,20 @@ SWIGEXPORT int SWIGSTDCALL CSharp_switch_core_session_get_loglevel(void * jarg1) } +SWIGEXPORT void * SWIGSTDCALL CSharp_switch_core_session_get_jb(void * jarg1, int jarg2) { + void * jresult ; + switch_core_session_t *arg1 = (switch_core_session_t *) 0 ; + switch_media_type_t arg2 ; + stfu_instance_t *result = 0 ; + + arg1 = (switch_core_session_t *)jarg1; + arg2 = (switch_media_type_t)jarg2; + result = (stfu_instance_t *)switch_core_session_get_jb(arg1,arg2); + jresult = (void *)result; + return jresult; +} + + SWIGEXPORT void SWIGSTDCALL CSharp_switch_core_session_soft_lock(void * jarg1, unsigned long jarg2) { switch_core_session_t *arg1 = (switch_core_session_t *) 0 ; uint32_t arg2 ; @@ -8105,6 +8119,20 @@ SWIGEXPORT void SWIGSTDCALL CSharp_switch_core_session_hupall_matching_var(char } +SWIGEXPORT void * SWIGSTDCALL CSharp_switch_core_session_findall_matching_var(char * jarg1, char * jarg2) { + void * jresult ; + char *arg1 = (char *) 0 ; + char *arg2 = (char *) 0 ; + switch_console_callback_match_t *result = 0 ; + + arg1 = (char *)jarg1; + arg2 = (char *)jarg2; + result = (switch_console_callback_match_t *)switch_core_session_findall_matching_var((char const *)arg1,(char const *)arg2); + jresult = (void *)result; + return jresult; +} + + SWIGEXPORT void SWIGSTDCALL CSharp_switch_core_session_hupall_endpoint(void * jarg1, int jarg2) { switch_endpoint_interface_t *arg1 = (switch_endpoint_interface_t *) 0 ; switch_call_cause_t arg2 ; @@ -11388,6 +11416,26 @@ SWIGEXPORT int SWIGSTDCALL CSharp__switch_cache_db_get_db_handle(void * jarg1, i } +SWIGEXPORT int SWIGSTDCALL CSharp__switch_cache_db_get_db_handle_dsn(void * jarg1, char * jarg2, char * jarg3, char * jarg4, int jarg5) { + int jresult ; + switch_cache_db_handle_t **arg1 = (switch_cache_db_handle_t **) 0 ; + char *arg2 = (char *) 0 ; + char *arg3 = (char *) 0 ; + char *arg4 = (char *) 0 ; + int arg5 ; + switch_status_t result; + + arg1 = (switch_cache_db_handle_t **)jarg1; + arg2 = (char *)jarg2; + arg3 = (char *)jarg3; + arg4 = (char *)jarg4; + arg5 = (int)jarg5; + result = (switch_status_t)_switch_cache_db_get_db_handle_dsn(arg1,(char const *)arg2,(char const *)arg3,(char const *)arg4,arg5); + jresult = result; + return jresult; +} + + SWIGEXPORT char * SWIGSTDCALL CSharp_switch_cache_db_execute_sql2str(void * jarg1, char * jarg2, char * jarg3, unsigned long jarg4, void * jarg5) { char * jresult ; switch_cache_db_handle_t *arg1 = (switch_cache_db_handle_t *) 0 ; @@ -11516,17 +11564,25 @@ SWIGEXPORT int SWIGSTDCALL CSharp_switch_cache_db_persistant_execute(void * jarg } -SWIGEXPORT int SWIGSTDCALL CSharp_switch_cache_db_persistant_execute_trans(void * jarg1, char * jarg2, unsigned long jarg3) { +SWIGEXPORT int SWIGSTDCALL CSharp_switch_cache_db_persistant_execute_trans_full(void * jarg1, char * jarg2, unsigned long jarg3, char * jarg4, char * jarg5, char * jarg6, char * jarg7) { int jresult ; switch_cache_db_handle_t *arg1 = (switch_cache_db_handle_t *) 0 ; char *arg2 = (char *) 0 ; uint32_t arg3 ; + char *arg4 = (char *) 0 ; + char *arg5 = (char *) 0 ; + char *arg6 = (char *) 0 ; + char *arg7 = (char *) 0 ; switch_status_t result; arg1 = (switch_cache_db_handle_t *)jarg1; arg2 = (char *)jarg2; arg3 = (uint32_t)jarg3; - result = (switch_status_t)switch_cache_db_persistant_execute_trans(arg1,arg2,arg3); + arg4 = (char *)jarg4; + arg5 = (char *)jarg5; + arg6 = (char *)jarg6; + arg7 = (char *)jarg7; + result = (switch_status_t)switch_cache_db_persistant_execute_trans_full(arg1,arg2,arg3,(char const *)arg4,(char const *)arg5,(char const *)arg6,(char const *)arg7); jresult = result; return jresult; } @@ -11768,6 +11824,24 @@ SWIGEXPORT int SWIGSTDCALL CSharp_switch_core_get_stacksizes(void * jarg1, void } +SWIGEXPORT int SWIGSTDCALL CSharp_switch_core_dbtype() { + int jresult ; + switch_cache_db_handle_type_t result; + + result = (switch_cache_db_handle_type_t)switch_core_dbtype(); + jresult = result; + return jresult; +} + + +SWIGEXPORT void SWIGSTDCALL CSharp_switch_core_sql_exec(char * jarg1) { + char *arg1 = (char *) 0 ; + + arg1 = (char *)jarg1; + switch_core_sql_exec((char const *)arg1); +} + + SWIGEXPORT int SWIGSTDCALL CSharp_switch_core_recovery_recover(char * jarg1, char * jarg2) { int jresult ; char *arg1 = (char *) 0 ; @@ -11810,6 +11884,104 @@ SWIGEXPORT void SWIGSTDCALL CSharp_switch_core_recovery_flush(char * jarg1, char } +SWIGEXPORT int SWIGSTDCALL CSharp_switch_switch_sql_queue_manager_push(void * jarg1, char * jarg2, unsigned long jarg3, int jarg4) { + int jresult ; + switch_sql_queue_manager_t *arg1 = (switch_sql_queue_manager_t *) 0 ; + char *arg2 = (char *) 0 ; + uint32_t arg3 ; + switch_bool_t arg4 ; + switch_status_t result; + + arg1 = (switch_sql_queue_manager_t *)jarg1; + arg2 = (char *)jarg2; + arg3 = (uint32_t)jarg3; + arg4 = (switch_bool_t)jarg4; + result = (switch_status_t)switch_switch_sql_queue_manager_push(arg1,(char const *)arg2,arg3,arg4); + jresult = result; + return jresult; +} + + +SWIGEXPORT int SWIGSTDCALL CSharp_switch_switch_sql_queue_manager_destroy(void * jarg1) { + int jresult ; + switch_sql_queue_manager_t **arg1 = (switch_sql_queue_manager_t **) 0 ; + switch_status_t result; + + arg1 = (switch_sql_queue_manager_t **)jarg1; + result = (switch_status_t)switch_switch_sql_queue_manager_destroy(arg1); + jresult = result; + return jresult; +} + + +SWIGEXPORT int SWIGSTDCALL CSharp_switch_switch_sql_queue_manager_init(void * jarg1, unsigned long jarg2, char * jarg3, char * jarg4, char * jarg5, char * jarg6, char * jarg7) { + int jresult ; + switch_sql_queue_manager_t **arg1 = (switch_sql_queue_manager_t **) 0 ; + uint32_t arg2 ; + char *arg3 = (char *) 0 ; + char *arg4 = (char *) 0 ; + char *arg5 = (char *) 0 ; + char *arg6 = (char *) 0 ; + char *arg7 = (char *) 0 ; + switch_status_t result; + + arg1 = (switch_sql_queue_manager_t **)jarg1; + arg2 = (uint32_t)jarg2; + arg3 = (char *)jarg3; + arg4 = (char *)jarg4; + arg5 = (char *)jarg5; + arg6 = (char *)jarg6; + arg7 = (char *)jarg7; + result = (switch_status_t)switch_switch_sql_queue_manager_init(arg1,arg2,(char const *)arg3,(char const *)arg4,(char const *)arg5,(char const *)arg6,(char const *)arg7); + jresult = result; + return jresult; +} + + +SWIGEXPORT int SWIGSTDCALL CSharp_switch_switch_sql_queue_manager_start(void * jarg1) { + int jresult ; + switch_sql_queue_manager_t *arg1 = (switch_sql_queue_manager_t *) 0 ; + switch_status_t result; + + arg1 = (switch_sql_queue_manager_t *)jarg1; + result = (switch_status_t)switch_switch_sql_queue_manager_start(arg1); + jresult = result; + return jresult; +} + + +SWIGEXPORT int SWIGSTDCALL CSharp_switch_switch_sql_queue_manager_stop(void * jarg1) { + int jresult ; + switch_sql_queue_manager_t *arg1 = (switch_sql_queue_manager_t *) 0 ; + switch_status_t result; + + arg1 = (switch_sql_queue_manager_t *)jarg1; + result = (switch_status_t)switch_switch_sql_queue_manager_stop(arg1); + jresult = result; + return jresult; +} + + +SWIGEXPORT int SWIGSTDCALL CSharp_switch_cache_db_execute_sql_event_callback(void * jarg1, char * jarg2, void * jarg3, void * jarg4, void * jarg5) { + int jresult ; + switch_cache_db_handle_t *arg1 = (switch_cache_db_handle_t *) 0 ; + char *arg2 = (char *) 0 ; + switch_db_event_callback_func_t arg3 = (switch_db_event_callback_func_t) 0 ; + void *arg4 = (void *) 0 ; + char **arg5 = (char **) 0 ; + switch_status_t result; + + arg1 = (switch_cache_db_handle_t *)jarg1; + arg2 = (char *)jarg2; + arg3 = (switch_db_event_callback_func_t)jarg3; + arg4 = (void *)jarg4; + arg5 = (char **)jarg5; + result = (switch_status_t)switch_cache_db_execute_sql_event_callback(arg1,(char const *)arg2,arg3,arg4,arg5); + jresult = result; + return jresult; +} + + SWIGEXPORT void * SWIGSTDCALL CSharp_switch_fork() { void * jresult ; pid_t result; @@ -15441,6 +15613,28 @@ SWIGEXPORT void * SWIGSTDCALL CSharp_switch_caller_profile_times_get(void * jarg } +SWIGEXPORT void SWIGSTDCALL CSharp_switch_caller_profile_old_times_set(void * jarg1, void * jarg2) { + switch_caller_profile *arg1 = (switch_caller_profile *) 0 ; + switch_channel_timetable *arg2 = (switch_channel_timetable *) 0 ; + + arg1 = (switch_caller_profile *)jarg1; + arg2 = (switch_channel_timetable *)jarg2; + if (arg1) (arg1)->old_times = arg2; +} + + +SWIGEXPORT void * SWIGSTDCALL CSharp_switch_caller_profile_old_times_get(void * jarg1) { + void * jresult ; + switch_caller_profile *arg1 = (switch_caller_profile *) 0 ; + switch_channel_timetable *result = 0 ; + + arg1 = (switch_caller_profile *)jarg1; + result = (switch_channel_timetable *) ((arg1)->old_times); + jresult = (void *)result; + return jresult; +} + + SWIGEXPORT void SWIGSTDCALL CSharp_switch_caller_profile_caller_extension_set(void * jarg1, void * jarg2) { switch_caller_profile *arg1 = (switch_caller_profile *) 0 ; switch_caller_extension *arg2 = (switch_caller_extension *) 0 ; @@ -16483,6 +16677,28 @@ SWIGEXPORT unsigned long SWIGSTDCALL CSharp_switch_frame_flags_get(void * jarg1) } +SWIGEXPORT void SWIGSTDCALL CSharp_switch_frame_user_data_set(void * jarg1, void * jarg2) { + switch_frame *arg1 = (switch_frame *) 0 ; + void *arg2 = (void *) 0 ; + + arg1 = (switch_frame *)jarg1; + arg2 = (void *)jarg2; + if (arg1) (arg1)->user_data = arg2; +} + + +SWIGEXPORT void * SWIGSTDCALL CSharp_switch_frame_user_data_get(void * jarg1) { + void * jresult ; + switch_frame *arg1 = (switch_frame *) 0 ; + void *result = 0 ; + + arg1 = (switch_frame *)jarg1; + result = (void *) ((arg1)->user_data); + jresult = (void *)result; + return jresult; +} + + SWIGEXPORT void * SWIGSTDCALL CSharp_new_switch_frame() { void * jresult ; switch_frame *result = 0 ; @@ -17313,6 +17529,28 @@ SWIGEXPORT void * SWIGSTDCALL CSharp_switch_io_routines_state_run_get(void * jar } +SWIGEXPORT void SWIGSTDCALL CSharp_switch_io_routines_get_jb_set(void * jarg1, void * jarg2) { + switch_io_routines *arg1 = (switch_io_routines *) 0 ; + switch_io_get_jb_t arg2 = (switch_io_get_jb_t) 0 ; + + arg1 = (switch_io_routines *)jarg1; + arg2 = (switch_io_get_jb_t)jarg2; + if (arg1) (arg1)->get_jb = arg2; +} + + +SWIGEXPORT void * SWIGSTDCALL CSharp_switch_io_routines_get_jb_get(void * jarg1) { + void * jresult ; + switch_io_routines *arg1 = (switch_io_routines *) 0 ; + switch_io_get_jb_t result; + + arg1 = (switch_io_routines *)jarg1; + result = (switch_io_get_jb_t) ((arg1)->get_jb); + jresult = (void *)result; + return jresult; +} + + SWIGEXPORT void SWIGSTDCALL CSharp_switch_io_routines_padding_set(void * jarg1, void * jarg2) { switch_io_routines *arg1 = (switch_io_routines *) 0 ; void **arg2 ; @@ -20387,6 +20625,144 @@ SWIGEXPORT void * SWIGSTDCALL CSharp_switch_asr_handle_memory_pool_get(void * ja } +SWIGEXPORT void SWIGSTDCALL CSharp_switch_asr_handle_buffer_set(void * jarg1, void * jarg2) { + switch_asr_handle *arg1 = (switch_asr_handle *) 0 ; + switch_buffer_t *arg2 = (switch_buffer_t *) 0 ; + + arg1 = (switch_asr_handle *)jarg1; + arg2 = (switch_buffer_t *)jarg2; + if (arg1) (arg1)->buffer = arg2; +} + + +SWIGEXPORT void * SWIGSTDCALL CSharp_switch_asr_handle_buffer_get(void * jarg1) { + void * jresult ; + switch_asr_handle *arg1 = (switch_asr_handle *) 0 ; + switch_buffer_t *result = 0 ; + + arg1 = (switch_asr_handle *)jarg1; + result = (switch_buffer_t *) ((arg1)->buffer); + jresult = (void *)result; + return jresult; +} + + +SWIGEXPORT void SWIGSTDCALL CSharp_switch_asr_handle_dbuf_set(void * jarg1, void * jarg2) { + switch_asr_handle *arg1 = (switch_asr_handle *) 0 ; + switch_byte_t *arg2 = (switch_byte_t *) 0 ; + + arg1 = (switch_asr_handle *)jarg1; + arg2 = (switch_byte_t *)jarg2; + if (arg1) (arg1)->dbuf = arg2; +} + + +SWIGEXPORT void * SWIGSTDCALL CSharp_switch_asr_handle_dbuf_get(void * jarg1) { + void * jresult ; + switch_asr_handle *arg1 = (switch_asr_handle *) 0 ; + switch_byte_t *result = 0 ; + + arg1 = (switch_asr_handle *)jarg1; + result = (switch_byte_t *) ((arg1)->dbuf); + jresult = (void *)result; + return jresult; +} + + +SWIGEXPORT void SWIGSTDCALL CSharp_switch_asr_handle_dbuflen_set(void * jarg1, void * jarg2) { + switch_asr_handle *arg1 = (switch_asr_handle *) 0 ; + switch_size_t arg2 ; + switch_size_t *argp2 ; + + arg1 = (switch_asr_handle *)jarg1; + argp2 = (switch_size_t *)jarg2; + if (!argp2) { + SWIG_CSharpSetPendingExceptionArgument(SWIG_CSharpArgumentNullException, "Attempt to dereference null switch_size_t", 0); + return ; + } + arg2 = *argp2; + if (arg1) (arg1)->dbuflen = arg2; +} + + +SWIGEXPORT void * SWIGSTDCALL CSharp_switch_asr_handle_dbuflen_get(void * jarg1) { + void * jresult ; + switch_asr_handle *arg1 = (switch_asr_handle *) 0 ; + switch_size_t result; + + arg1 = (switch_asr_handle *)jarg1; + result = ((arg1)->dbuflen); + jresult = new switch_size_t((const switch_size_t &)result); + return jresult; +} + + +SWIGEXPORT void SWIGSTDCALL CSharp_switch_asr_handle_resampler_set(void * jarg1, void * jarg2) { + switch_asr_handle *arg1 = (switch_asr_handle *) 0 ; + switch_audio_resampler_t *arg2 = (switch_audio_resampler_t *) 0 ; + + arg1 = (switch_asr_handle *)jarg1; + arg2 = (switch_audio_resampler_t *)jarg2; + if (arg1) (arg1)->resampler = arg2; +} + + +SWIGEXPORT void * SWIGSTDCALL CSharp_switch_asr_handle_resampler_get(void * jarg1) { + void * jresult ; + switch_asr_handle *arg1 = (switch_asr_handle *) 0 ; + switch_audio_resampler_t *result = 0 ; + + arg1 = (switch_asr_handle *)jarg1; + result = (switch_audio_resampler_t *) ((arg1)->resampler); + jresult = (void *)result; + return jresult; +} + + +SWIGEXPORT void SWIGSTDCALL CSharp_switch_asr_handle_samplerate_set(void * jarg1, unsigned long jarg2) { + switch_asr_handle *arg1 = (switch_asr_handle *) 0 ; + uint32_t arg2 ; + + arg1 = (switch_asr_handle *)jarg1; + arg2 = (uint32_t)jarg2; + if (arg1) (arg1)->samplerate = arg2; +} + + +SWIGEXPORT unsigned long SWIGSTDCALL CSharp_switch_asr_handle_samplerate_get(void * jarg1) { + unsigned long jresult ; + switch_asr_handle *arg1 = (switch_asr_handle *) 0 ; + uint32_t result; + + arg1 = (switch_asr_handle *)jarg1; + result = (uint32_t) ((arg1)->samplerate); + jresult = (unsigned long)result; + return jresult; +} + + +SWIGEXPORT void SWIGSTDCALL CSharp_switch_asr_handle_native_rate_set(void * jarg1, unsigned long jarg2) { + switch_asr_handle *arg1 = (switch_asr_handle *) 0 ; + uint32_t arg2 ; + + arg1 = (switch_asr_handle *)jarg1; + arg2 = (uint32_t)jarg2; + if (arg1) (arg1)->native_rate = arg2; +} + + +SWIGEXPORT unsigned long SWIGSTDCALL CSharp_switch_asr_handle_native_rate_get(void * jarg1) { + unsigned long jresult ; + switch_asr_handle *arg1 = (switch_asr_handle *) 0 ; + uint32_t result; + + arg1 = (switch_asr_handle *)jarg1; + result = (uint32_t) ((arg1)->native_rate); + jresult = (unsigned long)result; + return jresult; +} + + SWIGEXPORT void SWIGSTDCALL CSharp_switch_asr_handle_private_info_set(void * jarg1, void * jarg2) { switch_asr_handle *arg1 = (switch_asr_handle *) 0 ; void *arg2 = (void *) 0 ; @@ -22792,6 +23168,28 @@ SWIGEXPORT void * SWIGSTDCALL CSharp_switch_codec_next_get(void * jarg1) { } +SWIGEXPORT void SWIGSTDCALL CSharp_switch_codec_session_set(void * jarg1, void * jarg2) { + switch_codec *arg1 = (switch_codec *) 0 ; + switch_core_session_t *arg2 = (switch_core_session_t *) 0 ; + + arg1 = (switch_codec *)jarg1; + arg2 = (switch_core_session_t *)jarg2; + if (arg1) (arg1)->session = arg2; +} + + +SWIGEXPORT void * SWIGSTDCALL CSharp_switch_codec_session_get(void * jarg1) { + void * jresult ; + switch_codec *arg1 = (switch_codec *) 0 ; + switch_core_session_t *result = 0 ; + + arg1 = (switch_codec *)jarg1; + result = (switch_core_session_t *) ((arg1)->session); + jresult = (void *)result; + return jresult; +} + + SWIGEXPORT void * SWIGSTDCALL CSharp_new_switch_codec() { void * jresult ; switch_codec *result = 0 ; @@ -26349,10 +26747,10 @@ SWIGEXPORT char * SWIGSTDCALL CSharp_switch_channel_callstate2str(int jarg1) { SWIGEXPORT int SWIGSTDCALL CSharp_switch_channel_str2callstate(char * jarg1) { int jresult ; char *arg1 = (char *) 0 ; - switch_call_cause_t result; + switch_channel_callstate_t result; arg1 = (char *)jarg1; - result = (switch_call_cause_t)switch_channel_str2callstate((char const *)arg1); + result = (switch_channel_callstate_t)switch_channel_str2callstate((char const *)arg1); jresult = result; return jresult; } @@ -27978,6 +28376,24 @@ SWIGEXPORT int SWIGSTDCALL CSharp_switch_event_create_brackets(char * jarg1, cha } +SWIGEXPORT int SWIGSTDCALL CSharp_switch_event_create_array_pair(void * jarg1, void * jarg2, void * jarg3, int jarg4) { + int jresult ; + switch_event_t **arg1 = (switch_event_t **) 0 ; + char **arg2 = (char **) 0 ; + char **arg3 = (char **) 0 ; + int arg4 ; + switch_status_t result; + + arg1 = (switch_event_t **)jarg1; + arg2 = (char **)jarg2; + arg3 = (char **)jarg3; + arg4 = (int)jarg4; + result = (switch_status_t)switch_event_create_array_pair(arg1,arg2,arg3,arg4); + jresult = result; + return jresult; +} + + SWIGEXPORT int SWIGSTDCALL CSharp_switch_event_running() { int jresult ; switch_status_t result; @@ -31835,6 +32251,18 @@ SWIGEXPORT int SWIGSTDCALL CSharp_switch_rtp_pause_jitter_buffer(void * jarg1, i } +SWIGEXPORT void * SWIGSTDCALL CSharp_switch_rtp_get_jitter_buffer(void * jarg1) { + void * jresult ; + switch_rtp_t *arg1 = (switch_rtp_t *) 0 ; + stfu_instance_t *result = 0 ; + + arg1 = (switch_rtp_t *)jarg1; + result = (stfu_instance_t *)switch_rtp_get_jitter_buffer(arg1); + jresult = (void *)result; + return jresult; +} + + SWIGEXPORT void SWIGSTDCALL CSharp_switch_rtp_set_flag(void * jarg1, unsigned long jarg2) { switch_rtp_t *arg1 = (switch_rtp_t *) 0 ; switch_rtp_flag_t arg2 ; @@ -32521,6 +32949,28 @@ SWIGEXPORT int SWIGSTDCALL CSharp_switch_log_node_t_channel_get(void * jarg1) { } +SWIGEXPORT void SWIGSTDCALL CSharp_switch_log_node_t_slevel_set(void * jarg1, int jarg2) { + switch_log_node_t *arg1 = (switch_log_node_t *) 0 ; + switch_log_level_t arg2 ; + + arg1 = (switch_log_node_t *)jarg1; + arg2 = (switch_log_level_t)jarg2; + if (arg1) (arg1)->slevel = arg2; +} + + +SWIGEXPORT int SWIGSTDCALL CSharp_switch_log_node_t_slevel_get(void * jarg1) { + int jresult ; + switch_log_node_t *arg1 = (switch_log_node_t *) 0 ; + switch_log_level_t result; + + arg1 = (switch_log_node_t *)jarg1; + result = (switch_log_level_t) ((arg1)->slevel); + jresult = result; + return jresult; +} + + SWIGEXPORT void * SWIGSTDCALL CSharp_new_switch_log_node_t() { void * jresult ; switch_log_node_t *result = 0 ; @@ -33189,6 +33639,20 @@ SWIGEXPORT char * SWIGSTDCALL CSharp_switch_xml_toxml_nolock(void * jarg1, int j } +SWIGEXPORT char * SWIGSTDCALL CSharp_switch_xml_tohtml(void * jarg1, int jarg2) { + char * jresult ; + switch_xml_t arg1 = (switch_xml_t) 0 ; + switch_bool_t arg2 ; + char *result = 0 ; + + arg1 = (switch_xml_t)jarg1; + arg2 = (switch_bool_t)jarg2; + result = (char *)switch_xml_tohtml(arg1,arg2); + jresult = SWIG_csharp_string_callback((const char *)result); + return jresult; +} + + SWIGEXPORT char * SWIGSTDCALL CSharp_switch_xml_toxml_buf(void * jarg1, char * jarg2, void * jarg3, void * jarg4, int jarg5) { char * jresult ; switch_xml_t arg1 = (switch_xml_t) 0 ; diff --git a/src/mod/languages/mod_managed/managed/swig.2010.cs b/src/mod/languages/mod_managed/managed/swig.2010.cs index ae944a2be5..031eda1f37 100644 --- a/src/mod/languages/mod_managed/managed/swig.2010.cs +++ b/src/mod/languages/mod_managed/managed/swig.2010.cs @@ -1504,6 +1504,12 @@ public class freeswitch { return ret; } + public static SWIGTYPE_p_stfu_instance_t switch_core_session_get_jb(SWIGTYPE_p_switch_core_session session, switch_media_type_t type) { + IntPtr cPtr = freeswitchPINVOKE.switch_core_session_get_jb(SWIGTYPE_p_switch_core_session.getCPtr(session), (int)type); + SWIGTYPE_p_stfu_instance_t ret = (cPtr == IntPtr.Zero) ? null : new SWIGTYPE_p_stfu_instance_t(cPtr, false); + return ret; + } + public static void switch_core_session_soft_lock(SWIGTYPE_p_switch_core_session session, uint sec) { freeswitchPINVOKE.switch_core_session_soft_lock(SWIGTYPE_p_switch_core_session.getCPtr(session), sec); } @@ -1599,6 +1605,12 @@ public class freeswitch { freeswitchPINVOKE.switch_core_session_hupall_matching_var(var_name, var_val, (int)cause); } + public static switch_console_callback_match switch_core_session_findall_matching_var(string var_name, string var_val) { + IntPtr cPtr = freeswitchPINVOKE.switch_core_session_findall_matching_var(var_name, var_val); + switch_console_callback_match ret = (cPtr == IntPtr.Zero) ? null : new switch_console_callback_match(cPtr, false); + return ret; + } + public static void switch_core_session_hupall_endpoint(switch_endpoint_interface endpoint_interface, switch_call_cause_t cause) { freeswitchPINVOKE.switch_core_session_hupall_endpoint(switch_endpoint_interface.getCPtr(endpoint_interface), (int)cause); } @@ -2656,6 +2668,11 @@ public class freeswitch { return ret; } + public static switch_status_t _switch_cache_db_get_db_handle_dsn(SWIGTYPE_p_p_switch_cache_db_handle dbh, string dsn, string file, string func, int line) { + switch_status_t ret = (switch_status_t)freeswitchPINVOKE._switch_cache_db_get_db_handle_dsn(SWIGTYPE_p_p_switch_cache_db_handle.getCPtr(dbh), dsn, file, func, line); + return ret; + } + public static string switch_cache_db_execute_sql2str(SWIGTYPE_p_switch_cache_db_handle dbh, string sql, string str, uint len, ref string err) { string ret = freeswitchPINVOKE.switch_cache_db_execute_sql2str(SWIGTYPE_p_switch_cache_db_handle.getCPtr(dbh), sql, str, len, ref err); return ret; @@ -2695,8 +2712,8 @@ public class freeswitch { return ret; } - public static switch_status_t switch_cache_db_persistant_execute_trans(SWIGTYPE_p_switch_cache_db_handle dbh, string sql, uint retries) { - switch_status_t ret = (switch_status_t)freeswitchPINVOKE.switch_cache_db_persistant_execute_trans(SWIGTYPE_p_switch_cache_db_handle.getCPtr(dbh), sql, retries); + public static switch_status_t switch_cache_db_persistant_execute_trans_full(SWIGTYPE_p_switch_cache_db_handle dbh, string sql, uint retries, string pre_trans_execute, string post_trans_execute, string inner_pre_trans_execute, string inner_post_trans_execute) { + switch_status_t ret = (switch_status_t)freeswitchPINVOKE.switch_cache_db_persistant_execute_trans_full(SWIGTYPE_p_switch_cache_db_handle.getCPtr(dbh), sql, retries, pre_trans_execute, post_trans_execute, inner_pre_trans_execute, inner_post_trans_execute); return ret; } @@ -2794,6 +2811,15 @@ public class freeswitch { return ret; } + public static switch_cache_db_handle_type_t switch_core_dbtype() { + switch_cache_db_handle_type_t ret = (switch_cache_db_handle_type_t)freeswitchPINVOKE.switch_core_dbtype(); + return ret; + } + + public static void switch_core_sql_exec(string sql) { + freeswitchPINVOKE.switch_core_sql_exec(sql); + } + public static int switch_core_recovery_recover(string technology, string profile_name) { int ret = freeswitchPINVOKE.switch_core_recovery_recover(technology, profile_name); return ret; @@ -2811,6 +2837,36 @@ public class freeswitch { freeswitchPINVOKE.switch_core_recovery_flush(technology, profile_name); } + public static switch_status_t switch_switch_sql_queue_manager_push(SWIGTYPE_p_switch_sql_queue_manager qm, string sql, uint pos, switch_bool_t dup) { + switch_status_t ret = (switch_status_t)freeswitchPINVOKE.switch_switch_sql_queue_manager_push(SWIGTYPE_p_switch_sql_queue_manager.getCPtr(qm), sql, pos, (int)dup); + return ret; + } + + public static switch_status_t switch_switch_sql_queue_manager_destroy(SWIGTYPE_p_p_switch_sql_queue_manager qmp) { + switch_status_t ret = (switch_status_t)freeswitchPINVOKE.switch_switch_sql_queue_manager_destroy(SWIGTYPE_p_p_switch_sql_queue_manager.getCPtr(qmp)); + return ret; + } + + public static switch_status_t switch_switch_sql_queue_manager_init(SWIGTYPE_p_p_switch_sql_queue_manager qmp, uint numq, string dsn, string pre_trans_execute, string post_trans_execute, string inner_pre_trans_execute, string inner_post_trans_execute) { + switch_status_t ret = (switch_status_t)freeswitchPINVOKE.switch_switch_sql_queue_manager_init(SWIGTYPE_p_p_switch_sql_queue_manager.getCPtr(qmp), numq, dsn, pre_trans_execute, post_trans_execute, inner_pre_trans_execute, inner_post_trans_execute); + return ret; + } + + public static switch_status_t switch_switch_sql_queue_manager_start(SWIGTYPE_p_switch_sql_queue_manager qm) { + switch_status_t ret = (switch_status_t)freeswitchPINVOKE.switch_switch_sql_queue_manager_start(SWIGTYPE_p_switch_sql_queue_manager.getCPtr(qm)); + return ret; + } + + public static switch_status_t switch_switch_sql_queue_manager_stop(SWIGTYPE_p_switch_sql_queue_manager qm) { + switch_status_t ret = (switch_status_t)freeswitchPINVOKE.switch_switch_sql_queue_manager_stop(SWIGTYPE_p_switch_sql_queue_manager.getCPtr(qm)); + return ret; + } + + public static switch_status_t switch_cache_db_execute_sql_event_callback(SWIGTYPE_p_switch_cache_db_handle dbh, string sql, SWIGTYPE_p_f_p_void_p_switch_event__int callback, SWIGTYPE_p_void pdata, ref string err) { + switch_status_t ret = (switch_status_t)freeswitchPINVOKE.switch_cache_db_execute_sql_event_callback(SWIGTYPE_p_switch_cache_db_handle.getCPtr(dbh), sql, SWIGTYPE_p_f_p_void_p_switch_event__int.getCPtr(callback), SWIGTYPE_p_void.getCPtr(pdata), ref err); + return ret; + } + public static SWIGTYPE_p_pid_t switch_fork() { SWIGTYPE_p_pid_t ret = new SWIGTYPE_p_pid_t(freeswitchPINVOKE.switch_fork(), true); return ret; @@ -4189,8 +4245,8 @@ public class freeswitch { return ret; } - public static switch_call_cause_t switch_channel_str2callstate(string str) { - switch_call_cause_t ret = (switch_call_cause_t)freeswitchPINVOKE.switch_channel_str2callstate(str); + public static switch_channel_callstate_t switch_channel_str2callstate(string str) { + switch_channel_callstate_t ret = (switch_channel_callstate_t)freeswitchPINVOKE.switch_channel_str2callstate(str); return ret; } @@ -4491,6 +4547,11 @@ public class freeswitch { return ret; } + public static switch_status_t switch_event_create_array_pair(SWIGTYPE_p_p_switch_event arg0, ref string names, ref string vals, int len) { + switch_status_t ret = (switch_status_t)freeswitchPINVOKE.switch_event_create_array_pair(SWIGTYPE_p_p_switch_event.getCPtr(arg0), ref names, ref vals, len); + return ret; + } + public static switch_status_t switch_event_running() { switch_status_t ret = (switch_status_t)freeswitchPINVOKE.switch_event_running(); return ret; @@ -5438,6 +5499,12 @@ public class freeswitch { return ret; } + public static SWIGTYPE_p_stfu_instance_t switch_rtp_get_jitter_buffer(SWIGTYPE_p_switch_rtp rtp_session) { + IntPtr cPtr = freeswitchPINVOKE.switch_rtp_get_jitter_buffer(SWIGTYPE_p_switch_rtp.getCPtr(rtp_session)); + SWIGTYPE_p_stfu_instance_t ret = (cPtr == IntPtr.Zero) ? null : new SWIGTYPE_p_stfu_instance_t(cPtr, false); + return ret; + } + public static void switch_rtp_set_flag(SWIGTYPE_p_switch_rtp rtp_session, uint flags) { freeswitchPINVOKE.switch_rtp_set_flag(SWIGTYPE_p_switch_rtp.getCPtr(rtp_session), flags); } @@ -5724,6 +5791,11 @@ public class freeswitch { return ret; } + public static string switch_xml_tohtml(switch_xml xml, switch_bool_t prn_header) { + string ret = freeswitchPINVOKE.switch_xml_tohtml(switch_xml.getCPtr(xml), (int)prn_header); + return ret; + } + public static string switch_xml_toxml_buf(switch_xml xml, string buf, SWIGTYPE_p_switch_size_t buflen, SWIGTYPE_p_switch_size_t offset, switch_bool_t prn_header) { string ret = freeswitchPINVOKE.switch_xml_toxml_buf(switch_xml.getCPtr(xml), buf, SWIGTYPE_p_switch_size_t.getCPtr(buflen), SWIGTYPE_p_switch_size_t.getCPtr(offset), (int)prn_header); if (freeswitchPINVOKE.SWIGPendingException.Pending) throw freeswitchPINVOKE.SWIGPendingException.Retrieve(); @@ -8497,6 +8569,9 @@ class freeswitchPINVOKE { [DllImport("mod_managed", EntryPoint="CSharp_switch_core_session_get_loglevel")] public static extern int switch_core_session_get_loglevel(HandleRef jarg1); + [DllImport("mod_managed", EntryPoint="CSharp_switch_core_session_get_jb")] + public static extern IntPtr switch_core_session_get_jb(HandleRef jarg1, int jarg2); + [DllImport("mod_managed", EntryPoint="CSharp_switch_core_session_soft_lock")] public static extern void switch_core_session_soft_lock(HandleRef jarg1, uint jarg2); @@ -8557,6 +8632,9 @@ class freeswitchPINVOKE { [DllImport("mod_managed", EntryPoint="CSharp_switch_core_session_hupall_matching_var")] public static extern void switch_core_session_hupall_matching_var(string jarg1, string jarg2, int jarg3); + [DllImport("mod_managed", EntryPoint="CSharp_switch_core_session_findall_matching_var")] + public static extern IntPtr switch_core_session_findall_matching_var(string jarg1, string jarg2); + [DllImport("mod_managed", EntryPoint="CSharp_switch_core_session_hupall_endpoint")] public static extern void switch_core_session_hupall_endpoint(HandleRef jarg1, int jarg2); @@ -9301,6 +9379,9 @@ class freeswitchPINVOKE { [DllImport("mod_managed", EntryPoint="CSharp__switch_cache_db_get_db_handle")] public static extern int _switch_cache_db_get_db_handle(HandleRef jarg1, int jarg2, HandleRef jarg3, string jarg4, string jarg5, int jarg6); + [DllImport("mod_managed", EntryPoint="CSharp__switch_cache_db_get_db_handle_dsn")] + public static extern int _switch_cache_db_get_db_handle_dsn(HandleRef jarg1, string jarg2, string jarg3, string jarg4, int jarg5); + [DllImport("mod_managed", EntryPoint="CSharp_switch_cache_db_execute_sql2str")] public static extern string switch_cache_db_execute_sql2str(HandleRef jarg1, string jarg2, string jarg3, uint jarg4, ref string jarg5); @@ -9325,8 +9406,8 @@ class freeswitchPINVOKE { [DllImport("mod_managed", EntryPoint="CSharp_switch_cache_db_persistant_execute")] public static extern int switch_cache_db_persistant_execute(HandleRef jarg1, string jarg2, uint jarg3); - [DllImport("mod_managed", EntryPoint="CSharp_switch_cache_db_persistant_execute_trans")] - public static extern int switch_cache_db_persistant_execute_trans(HandleRef jarg1, string jarg2, uint jarg3); + [DllImport("mod_managed", EntryPoint="CSharp_switch_cache_db_persistant_execute_trans_full")] + public static extern int switch_cache_db_persistant_execute_trans_full(HandleRef jarg1, string jarg2, uint jarg3, string jarg4, string jarg5, string jarg6, string jarg7); [DllImport("mod_managed", EntryPoint="CSharp_switch_core_set_signal_handlers")] public static extern void switch_core_set_signal_handlers(); @@ -9388,6 +9469,12 @@ class freeswitchPINVOKE { [DllImport("mod_managed", EntryPoint="CSharp_switch_core_get_stacksizes")] public static extern int switch_core_get_stacksizes(HandleRef jarg1, HandleRef jarg2); + [DllImport("mod_managed", EntryPoint="CSharp_switch_core_dbtype")] + public static extern int switch_core_dbtype(); + + [DllImport("mod_managed", EntryPoint="CSharp_switch_core_sql_exec")] + public static extern void switch_core_sql_exec(string jarg1); + [DllImport("mod_managed", EntryPoint="CSharp_switch_core_recovery_recover")] public static extern int switch_core_recovery_recover(string jarg1, string jarg2); @@ -9400,6 +9487,24 @@ class freeswitchPINVOKE { [DllImport("mod_managed", EntryPoint="CSharp_switch_core_recovery_flush")] public static extern void switch_core_recovery_flush(string jarg1, string jarg2); + [DllImport("mod_managed", EntryPoint="CSharp_switch_switch_sql_queue_manager_push")] + public static extern int switch_switch_sql_queue_manager_push(HandleRef jarg1, string jarg2, uint jarg3, int jarg4); + + [DllImport("mod_managed", EntryPoint="CSharp_switch_switch_sql_queue_manager_destroy")] + public static extern int switch_switch_sql_queue_manager_destroy(HandleRef jarg1); + + [DllImport("mod_managed", EntryPoint="CSharp_switch_switch_sql_queue_manager_init")] + public static extern int switch_switch_sql_queue_manager_init(HandleRef jarg1, uint jarg2, string jarg3, string jarg4, string jarg5, string jarg6, string jarg7); + + [DllImport("mod_managed", EntryPoint="CSharp_switch_switch_sql_queue_manager_start")] + public static extern int switch_switch_sql_queue_manager_start(HandleRef jarg1); + + [DllImport("mod_managed", EntryPoint="CSharp_switch_switch_sql_queue_manager_stop")] + public static extern int switch_switch_sql_queue_manager_stop(HandleRef jarg1); + + [DllImport("mod_managed", EntryPoint="CSharp_switch_cache_db_execute_sql_event_callback")] + public static extern int switch_cache_db_execute_sql_event_callback(HandleRef jarg1, string jarg2, HandleRef jarg3, HandleRef jarg4, ref string jarg5); + [DllImport("mod_managed", EntryPoint="CSharp_switch_fork")] public static extern IntPtr switch_fork(); @@ -10201,6 +10306,12 @@ class freeswitchPINVOKE { [DllImport("mod_managed", EntryPoint="CSharp_switch_caller_profile_times_get")] public static extern IntPtr switch_caller_profile_times_get(HandleRef jarg1); + [DllImport("mod_managed", EntryPoint="CSharp_switch_caller_profile_old_times_set")] + public static extern void switch_caller_profile_old_times_set(HandleRef jarg1, HandleRef jarg2); + + [DllImport("mod_managed", EntryPoint="CSharp_switch_caller_profile_old_times_get")] + public static extern IntPtr switch_caller_profile_old_times_get(HandleRef jarg1); + [DllImport("mod_managed", EntryPoint="CSharp_switch_caller_profile_caller_extension_set")] public static extern void switch_caller_profile_caller_extension_set(HandleRef jarg1, HandleRef jarg2); @@ -10456,6 +10567,12 @@ class freeswitchPINVOKE { [DllImport("mod_managed", EntryPoint="CSharp_switch_frame_flags_get")] public static extern uint switch_frame_flags_get(HandleRef jarg1); + [DllImport("mod_managed", EntryPoint="CSharp_switch_frame_user_data_set")] + public static extern void switch_frame_user_data_set(HandleRef jarg1, HandleRef jarg2); + + [DllImport("mod_managed", EntryPoint="CSharp_switch_frame_user_data_get")] + public static extern IntPtr switch_frame_user_data_get(HandleRef jarg1); + [DllImport("mod_managed", EntryPoint="CSharp_new_switch_frame")] public static extern IntPtr new_switch_frame(); @@ -10678,6 +10795,12 @@ class freeswitchPINVOKE { [DllImport("mod_managed", EntryPoint="CSharp_switch_io_routines_state_run_get")] public static extern IntPtr switch_io_routines_state_run_get(HandleRef jarg1); + [DllImport("mod_managed", EntryPoint="CSharp_switch_io_routines_get_jb_set")] + public static extern void switch_io_routines_get_jb_set(HandleRef jarg1, HandleRef jarg2); + + [DllImport("mod_managed", EntryPoint="CSharp_switch_io_routines_get_jb_get")] + public static extern IntPtr switch_io_routines_get_jb_get(HandleRef jarg1); + [DllImport("mod_managed", EntryPoint="CSharp_switch_io_routines_padding_set")] public static extern void switch_io_routines_padding_set(HandleRef jarg1, HandleRef jarg2); @@ -11482,6 +11605,42 @@ class freeswitchPINVOKE { [DllImport("mod_managed", EntryPoint="CSharp_switch_asr_handle_memory_pool_get")] public static extern IntPtr switch_asr_handle_memory_pool_get(HandleRef jarg1); + [DllImport("mod_managed", EntryPoint="CSharp_switch_asr_handle_buffer_set")] + public static extern void switch_asr_handle_buffer_set(HandleRef jarg1, HandleRef jarg2); + + [DllImport("mod_managed", EntryPoint="CSharp_switch_asr_handle_buffer_get")] + public static extern IntPtr switch_asr_handle_buffer_get(HandleRef jarg1); + + [DllImport("mod_managed", EntryPoint="CSharp_switch_asr_handle_dbuf_set")] + public static extern void switch_asr_handle_dbuf_set(HandleRef jarg1, HandleRef jarg2); + + [DllImport("mod_managed", EntryPoint="CSharp_switch_asr_handle_dbuf_get")] + public static extern IntPtr switch_asr_handle_dbuf_get(HandleRef jarg1); + + [DllImport("mod_managed", EntryPoint="CSharp_switch_asr_handle_dbuflen_set")] + public static extern void switch_asr_handle_dbuflen_set(HandleRef jarg1, HandleRef jarg2); + + [DllImport("mod_managed", EntryPoint="CSharp_switch_asr_handle_dbuflen_get")] + public static extern IntPtr switch_asr_handle_dbuflen_get(HandleRef jarg1); + + [DllImport("mod_managed", EntryPoint="CSharp_switch_asr_handle_resampler_set")] + public static extern void switch_asr_handle_resampler_set(HandleRef jarg1, HandleRef jarg2); + + [DllImport("mod_managed", EntryPoint="CSharp_switch_asr_handle_resampler_get")] + public static extern IntPtr switch_asr_handle_resampler_get(HandleRef jarg1); + + [DllImport("mod_managed", EntryPoint="CSharp_switch_asr_handle_samplerate_set")] + public static extern void switch_asr_handle_samplerate_set(HandleRef jarg1, uint jarg2); + + [DllImport("mod_managed", EntryPoint="CSharp_switch_asr_handle_samplerate_get")] + public static extern uint switch_asr_handle_samplerate_get(HandleRef jarg1); + + [DllImport("mod_managed", EntryPoint="CSharp_switch_asr_handle_native_rate_set")] + public static extern void switch_asr_handle_native_rate_set(HandleRef jarg1, uint jarg2); + + [DllImport("mod_managed", EntryPoint="CSharp_switch_asr_handle_native_rate_get")] + public static extern uint switch_asr_handle_native_rate_get(HandleRef jarg1); + [DllImport("mod_managed", EntryPoint="CSharp_switch_asr_handle_private_info_set")] public static extern void switch_asr_handle_private_info_set(HandleRef jarg1, HandleRef jarg2); @@ -12124,6 +12283,12 @@ class freeswitchPINVOKE { [DllImport("mod_managed", EntryPoint="CSharp_switch_codec_next_get")] public static extern IntPtr switch_codec_next_get(HandleRef jarg1); + [DllImport("mod_managed", EntryPoint="CSharp_switch_codec_session_set")] + public static extern void switch_codec_session_set(HandleRef jarg1, HandleRef jarg2); + + [DllImport("mod_managed", EntryPoint="CSharp_switch_codec_session_get")] + public static extern IntPtr switch_codec_session_get(HandleRef jarg1); + [DllImport("mod_managed", EntryPoint="CSharp_new_switch_codec")] public static extern IntPtr new_switch_codec(); @@ -13339,6 +13504,9 @@ class freeswitchPINVOKE { [DllImport("mod_managed", EntryPoint="CSharp_switch_event_create_brackets")] public static extern int switch_event_create_brackets(string jarg1, char jarg2, char jarg3, char jarg4, HandleRef jarg5, ref string jarg6, int jarg7); + [DllImport("mod_managed", EntryPoint="CSharp_switch_event_create_array_pair")] + public static extern int switch_event_create_array_pair(HandleRef jarg1, ref string jarg2, ref string jarg3, int jarg4); + [DllImport("mod_managed", EntryPoint="CSharp_switch_event_running")] public static extern int switch_event_running(); @@ -14131,6 +14299,9 @@ class freeswitchPINVOKE { [DllImport("mod_managed", EntryPoint="CSharp_switch_rtp_pause_jitter_buffer")] public static extern int switch_rtp_pause_jitter_buffer(HandleRef jarg1, int jarg2); + [DllImport("mod_managed", EntryPoint="CSharp_switch_rtp_get_jitter_buffer")] + public static extern IntPtr switch_rtp_get_jitter_buffer(HandleRef jarg1); + [DllImport("mod_managed", EntryPoint="CSharp_switch_rtp_set_flag")] public static extern void switch_rtp_set_flag(HandleRef jarg1, uint jarg2); @@ -14287,6 +14458,12 @@ class freeswitchPINVOKE { [DllImport("mod_managed", EntryPoint="CSharp_switch_log_node_t_channel_get")] public static extern int switch_log_node_t_channel_get(HandleRef jarg1); + [DllImport("mod_managed", EntryPoint="CSharp_switch_log_node_t_slevel_set")] + public static extern void switch_log_node_t_slevel_set(HandleRef jarg1, int jarg2); + + [DllImport("mod_managed", EntryPoint="CSharp_switch_log_node_t_slevel_get")] + public static extern int switch_log_node_t_slevel_get(HandleRef jarg1); + [DllImport("mod_managed", EntryPoint="CSharp_new_switch_log_node_t")] public static extern IntPtr new_switch_log_node_t(); @@ -14449,6 +14626,9 @@ class freeswitchPINVOKE { [DllImport("mod_managed", EntryPoint="CSharp_switch_xml_toxml_nolock")] public static extern string switch_xml_toxml_nolock(HandleRef jarg1, int jarg2); + [DllImport("mod_managed", EntryPoint="CSharp_switch_xml_tohtml")] + public static extern string switch_xml_tohtml(HandleRef jarg1, int jarg2); + [DllImport("mod_managed", EntryPoint="CSharp_switch_xml_toxml_buf")] public static extern string switch_xml_toxml_buf(HandleRef jarg1, string jarg2, HandleRef jarg3, HandleRef jarg4, int jarg5); @@ -16789,6 +16969,36 @@ namespace FreeSWITCH.Native { using System; using System.Runtime.InteropServices; +public class SWIGTYPE_p_f_p_switch_core_session_enum_switch_media_type_t__p_stfu_instance_t { + private HandleRef swigCPtr; + + internal SWIGTYPE_p_f_p_switch_core_session_enum_switch_media_type_t__p_stfu_instance_t(IntPtr cPtr, bool futureUse) { + swigCPtr = new HandleRef(this, cPtr); + } + + protected SWIGTYPE_p_f_p_switch_core_session_enum_switch_media_type_t__p_stfu_instance_t() { + swigCPtr = new HandleRef(null, IntPtr.Zero); + } + + internal static HandleRef getCPtr(SWIGTYPE_p_f_p_switch_core_session_enum_switch_media_type_t__p_stfu_instance_t obj) { + return (obj == null) ? new HandleRef(null, IntPtr.Zero) : obj.swigCPtr; + } +} + +} +/* ---------------------------------------------------------------------------- + * This file was automatically generated by SWIG (http://www.swig.org). + * Version 2.0.1 + * + * Do not make changes to this file unless you know what you are doing--modify + * the SWIG interface file instead. + * ----------------------------------------------------------------------------- */ + +namespace FreeSWITCH.Native { + +using System; +using System.Runtime.InteropServices; + public class SWIGTYPE_p_f_p_switch_core_session_int__switch_status_t { private HandleRef swigCPtr; @@ -18439,6 +18649,36 @@ namespace FreeSWITCH.Native { using System; using System.Runtime.InteropServices; +public class SWIGTYPE_p_f_p_void_p_switch_event__int { + private HandleRef swigCPtr; + + internal SWIGTYPE_p_f_p_void_p_switch_event__int(IntPtr cPtr, bool futureUse) { + swigCPtr = new HandleRef(this, cPtr); + } + + protected SWIGTYPE_p_f_p_void_p_switch_event__int() { + swigCPtr = new HandleRef(null, IntPtr.Zero); + } + + internal static HandleRef getCPtr(SWIGTYPE_p_f_p_void_p_switch_event__int obj) { + return (obj == null) ? new HandleRef(null, IntPtr.Zero) : obj.swigCPtr; + } +} + +} +/* ---------------------------------------------------------------------------- + * This file was automatically generated by SWIG (http://www.swig.org). + * Version 2.0.1 + * + * Do not make changes to this file unless you know what you are doing--modify + * the SWIG interface file instead. + * ----------------------------------------------------------------------------- */ + +namespace FreeSWITCH.Native { + +using System; +using System.Runtime.InteropServices; + public class SWIGTYPE_p_f_p_void__void { private HandleRef swigCPtr; @@ -19669,6 +19909,36 @@ namespace FreeSWITCH.Native { using System; using System.Runtime.InteropServices; +public class SWIGTYPE_p_p_switch_sql_queue_manager { + private HandleRef swigCPtr; + + internal SWIGTYPE_p_p_switch_sql_queue_manager(IntPtr cPtr, bool futureUse) { + swigCPtr = new HandleRef(this, cPtr); + } + + protected SWIGTYPE_p_p_switch_sql_queue_manager() { + swigCPtr = new HandleRef(null, IntPtr.Zero); + } + + internal static HandleRef getCPtr(SWIGTYPE_p_p_switch_sql_queue_manager obj) { + return (obj == null) ? new HandleRef(null, IntPtr.Zero) : obj.swigCPtr; + } +} + +} +/* ---------------------------------------------------------------------------- + * This file was automatically generated by SWIG (http://www.swig.org). + * Version 2.0.1 + * + * Do not make changes to this file unless you know what you are doing--modify + * the SWIG interface file instead. + * ----------------------------------------------------------------------------- */ + +namespace FreeSWITCH.Native { + +using System; +using System.Runtime.InteropServices; + public class SWIGTYPE_p_p_switch_xml { private HandleRef swigCPtr; @@ -19969,6 +20239,36 @@ namespace FreeSWITCH.Native { using System; using System.Runtime.InteropServices; +public class SWIGTYPE_p_stfu_instance_t { + private HandleRef swigCPtr; + + internal SWIGTYPE_p_stfu_instance_t(IntPtr cPtr, bool futureUse) { + swigCPtr = new HandleRef(this, cPtr); + } + + protected SWIGTYPE_p_stfu_instance_t() { + swigCPtr = new HandleRef(null, IntPtr.Zero); + } + + internal static HandleRef getCPtr(SWIGTYPE_p_stfu_instance_t obj) { + return (obj == null) ? new HandleRef(null, IntPtr.Zero) : obj.swigCPtr; + } +} + +} +/* ---------------------------------------------------------------------------- + * This file was automatically generated by SWIG (http://www.swig.org). + * Version 2.0.1 + * + * Do not make changes to this file unless you know what you are doing--modify + * the SWIG interface file instead. + * ----------------------------------------------------------------------------- */ + +namespace FreeSWITCH.Native { + +using System; +using System.Runtime.InteropServices; + public class SWIGTYPE_p_switch_buffer { private HandleRef swigCPtr; @@ -20839,6 +21139,36 @@ namespace FreeSWITCH.Native { using System; using System.Runtime.InteropServices; +public class SWIGTYPE_p_switch_sql_queue_manager { + private HandleRef swigCPtr; + + internal SWIGTYPE_p_switch_sql_queue_manager(IntPtr cPtr, bool futureUse) { + swigCPtr = new HandleRef(this, cPtr); + } + + protected SWIGTYPE_p_switch_sql_queue_manager() { + swigCPtr = new HandleRef(null, IntPtr.Zero); + } + + internal static HandleRef getCPtr(SWIGTYPE_p_switch_sql_queue_manager obj) { + return (obj == null) ? new HandleRef(null, IntPtr.Zero) : obj.swigCPtr; + } +} + +} +/* ---------------------------------------------------------------------------- + * This file was automatically generated by SWIG (http://www.swig.org). + * Version 2.0.1 + * + * Do not make changes to this file unless you know what you are doing--modify + * the SWIG interface file instead. + * ----------------------------------------------------------------------------- */ + +namespace FreeSWITCH.Native { + +using System; +using System.Runtime.InteropServices; + public class SWIGTYPE_p_switch_ssize_t { private HandleRef swigCPtr; @@ -21741,6 +22071,71 @@ public class switch_asr_handle : IDisposable { } } + public SWIGTYPE_p_switch_buffer buffer { + set { + freeswitchPINVOKE.switch_asr_handle_buffer_set(swigCPtr, SWIGTYPE_p_switch_buffer.getCPtr(value)); + } + get { + IntPtr cPtr = freeswitchPINVOKE.switch_asr_handle_buffer_get(swigCPtr); + SWIGTYPE_p_switch_buffer ret = (cPtr == IntPtr.Zero) ? null : new SWIGTYPE_p_switch_buffer(cPtr, false); + return ret; + } + } + + public SWIGTYPE_p_unsigned_char dbuf { + set { + freeswitchPINVOKE.switch_asr_handle_dbuf_set(swigCPtr, SWIGTYPE_p_unsigned_char.getCPtr(value)); + } + get { + IntPtr cPtr = freeswitchPINVOKE.switch_asr_handle_dbuf_get(swigCPtr); + SWIGTYPE_p_unsigned_char ret = (cPtr == IntPtr.Zero) ? null : new SWIGTYPE_p_unsigned_char(cPtr, false); + return ret; + } + } + + public SWIGTYPE_p_switch_size_t dbuflen { + set { + freeswitchPINVOKE.switch_asr_handle_dbuflen_set(swigCPtr, SWIGTYPE_p_switch_size_t.getCPtr(value)); + if (freeswitchPINVOKE.SWIGPendingException.Pending) throw freeswitchPINVOKE.SWIGPendingException.Retrieve(); + } + get { + SWIGTYPE_p_switch_size_t ret = new SWIGTYPE_p_switch_size_t(freeswitchPINVOKE.switch_asr_handle_dbuflen_get(swigCPtr), true); + if (freeswitchPINVOKE.SWIGPendingException.Pending) throw freeswitchPINVOKE.SWIGPendingException.Retrieve(); + return ret; + } + } + + public switch_audio_resampler_t resampler { + set { + freeswitchPINVOKE.switch_asr_handle_resampler_set(swigCPtr, switch_audio_resampler_t.getCPtr(value)); + } + get { + IntPtr cPtr = freeswitchPINVOKE.switch_asr_handle_resampler_get(swigCPtr); + switch_audio_resampler_t ret = (cPtr == IntPtr.Zero) ? null : new switch_audio_resampler_t(cPtr, false); + return ret; + } + } + + public uint samplerate { + set { + freeswitchPINVOKE.switch_asr_handle_samplerate_set(swigCPtr, value); + } + get { + uint ret = freeswitchPINVOKE.switch_asr_handle_samplerate_get(swigCPtr); + return ret; + } + } + + public uint native_rate { + set { + freeswitchPINVOKE.switch_asr_handle_native_rate_set(swigCPtr, value); + } + get { + uint ret = freeswitchPINVOKE.switch_asr_handle_native_rate_get(swigCPtr); + return ret; + } + } + public SWIGTYPE_p_void private_info { set { freeswitchPINVOKE.switch_asr_handle_private_info_set(swigCPtr, SWIGTYPE_p_void.getCPtr(value)); @@ -23385,6 +23780,17 @@ public class switch_caller_profile : IDisposable { } } + public switch_channel_timetable old_times { + set { + freeswitchPINVOKE.switch_caller_profile_old_times_set(swigCPtr, switch_channel_timetable.getCPtr(value)); + } + get { + IntPtr cPtr = freeswitchPINVOKE.switch_caller_profile_old_times_get(swigCPtr); + switch_channel_timetable ret = (cPtr == IntPtr.Zero) ? null : new switch_channel_timetable(cPtr, false); + return ret; + } + } + public switch_caller_extension caller_extension { set { freeswitchPINVOKE.switch_caller_profile_caller_extension_set(swigCPtr, switch_caller_extension.getCPtr(value)); @@ -23748,6 +24154,7 @@ public enum switch_channel_flag_t { CF_TRACKABLE, CF_NO_CDR, CF_EARLY_OK, + CF_MEDIA_TRANS, CF_FLAG_MAX } @@ -24424,6 +24831,17 @@ public class switch_codec : IDisposable { } } + public SWIGTYPE_p_switch_core_session session { + set { + freeswitchPINVOKE.switch_codec_session_set(swigCPtr, SWIGTYPE_p_switch_core_session.getCPtr(value)); + } + get { + IntPtr cPtr = freeswitchPINVOKE.switch_codec_session_get(swigCPtr); + SWIGTYPE_p_switch_core_session ret = (cPtr == IntPtr.Zero) ? null : new SWIGTYPE_p_switch_core_session(cPtr, false); + return ret; + } + } + public switch_codec() : this(freeswitchPINVOKE.new_switch_codec(), true) { } @@ -28124,6 +28542,17 @@ public class switch_frame : IDisposable { } } + public SWIGTYPE_p_void user_data { + set { + freeswitchPINVOKE.switch_frame_user_data_set(swigCPtr, SWIGTYPE_p_void.getCPtr(value)); + } + get { + IntPtr cPtr = freeswitchPINVOKE.switch_frame_user_data_get(swigCPtr); + SWIGTYPE_p_void ret = (cPtr == IntPtr.Zero) ? null : new SWIGTYPE_p_void(cPtr, false); + return ret; + } + } + public switch_frame() : this(freeswitchPINVOKE.new_switch_frame(), true) { } @@ -29593,6 +30022,17 @@ public class switch_io_routines : IDisposable { } } + public SWIGTYPE_p_f_p_switch_core_session_enum_switch_media_type_t__p_stfu_instance_t get_jb { + set { + freeswitchPINVOKE.switch_io_routines_get_jb_set(swigCPtr, SWIGTYPE_p_f_p_switch_core_session_enum_switch_media_type_t__p_stfu_instance_t.getCPtr(value)); + } + get { + IntPtr cPtr = freeswitchPINVOKE.switch_io_routines_get_jb_get(swigCPtr); + SWIGTYPE_p_f_p_switch_core_session_enum_switch_media_type_t__p_stfu_instance_t ret = (cPtr == IntPtr.Zero) ? null : new SWIGTYPE_p_f_p_switch_core_session_enum_switch_media_type_t__p_stfu_instance_t(cPtr, false); + return ret; + } + } + public SWIGTYPE_p_p_void padding { set { freeswitchPINVOKE.switch_io_routines_padding_set(swigCPtr, SWIGTYPE_p_p_void.getCPtr(value)); @@ -29630,7 +30070,8 @@ public enum switch_io_routine_name_t { SWITCH_IO_RECEIVE_EVENT, SWITCH_IO_STATE_CHANGE, SWITCH_IO_READ_VIDEO_FRAME, - SWITCH_IO_WRITE_VIDEO_FRAME + SWITCH_IO_WRITE_VIDEO_FRAME, + SWITCH_IO_GET_JB } } @@ -30356,7 +30797,8 @@ public enum switch_log_level_t { SWITCH_LOG_CRIT = 2, SWITCH_LOG_ALERT = 1, SWITCH_LOG_CONSOLE = 0, - SWITCH_LOG_INVALID = 64 + SWITCH_LOG_INVALID = 64, + SWITCH_LOG_UNINIT = 1000 } } @@ -30495,6 +30937,16 @@ public class switch_log_node_t : IDisposable { } } + public switch_log_level_t slevel { + set { + freeswitchPINVOKE.switch_log_node_t_slevel_set(swigCPtr, (int)value); + } + get { + switch_log_level_t ret = (switch_log_level_t)freeswitchPINVOKE.switch_log_node_t_slevel_get(swigCPtr); + return ret; + } + } + public switch_log_node_t() : this(freeswitchPINVOKE.new_switch_log_node_t(), true) { } @@ -30703,6 +31155,22 @@ namespace FreeSWITCH.Native { namespace FreeSWITCH.Native { +public enum switch_media_type_t { + SWITCH_MEDIA_TYPE_AUDIO, + SWITCH_MEDIA_TYPE_VIDEO +} + +} +/* ---------------------------------------------------------------------------- + * This file was automatically generated by SWIG (http://www.swig.org). + * Version 2.0.1 + * + * Do not make changes to this file unless you know what you are doing--modify + * the SWIG interface file instead. + * ----------------------------------------------------------------------------- */ + +namespace FreeSWITCH.Native { + public enum switch_module_flag_enum_t { SMODF_NONE = 0, SMODF_GLOBAL_SYMBOLS = (1 << 0) From ce4fa8acfbfee222921ab79f549ac0fceed1341f Mon Sep 17 00:00:00 2001 From: Eliot Gable Date: Tue, 23 Oct 2012 13:39:31 +0000 Subject: [PATCH 232/252] Added switch_atomic_t option for config parsing. --- src/include/switch_xml_config.h | 8 ++++++ src/switch_xml_config.c | 43 +++++++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+) diff --git a/src/include/switch_xml_config.h b/src/include/switch_xml_config.h index fc669e4fc1..6a81e4b16f 100644 --- a/src/include/switch_xml_config.h +++ b/src/include/switch_xml_config.h @@ -39,6 +39,7 @@ SWITCH_BEGIN_EXTERN_C /*! \brief Type of value to parse */ typedef enum { SWITCH_CONFIG_INT, /*< (ptr=int* default=int data=NULL) Integer */ + SWITCH_CONFIG_ATOMIC, /*< (ptr=switch_atomic_t* default=uint32_t data=NULL) Integer */ SWITCH_CONFIG_STRING, /*< (ptr=[char* or char ** (for alloc)] default=char* data=switch_xml_config_string_options_t*) Zero-terminated C-string */ SWITCH_CONFIG_BOOL, /*< (ptr=switch_bool_t* default=switch_bool_t data=NULL) Yes and no */ SWITCH_CONFIG_CUSTOM, /*< (ptr= default= data=switch_xml_config_callback_t) Custom, get value through function pointer */ @@ -70,6 +71,13 @@ typedef struct { int max; } switch_xml_config_int_options_t; +typedef struct { + switch_bool_t enforce_min; + uint32_t min; + switch_bool_t enforce_max; + uint32_t max; +} switch_xml_config_atomic_options_t; + struct switch_xml_config_item; typedef struct switch_xml_config_item switch_xml_config_item_t; diff --git a/src/switch_xml_config.c b/src/switch_xml_config.c index c33dba4e8a..a6fdc55496 100644 --- a/src/switch_xml_config.c +++ b/src/switch_xml_config.c @@ -36,6 +36,7 @@ SWITCH_DECLARE_DATA switch_xml_config_string_options_t switch_config_string_strd static switch_xml_config_enum_item_t switch_config_types_enum[] = { {"int", SWITCH_CONFIG_INT}, + {"switch_atomic_t", SWITCH_CONFIG_INT}, {"string", SWITCH_CONFIG_STRING}, {"bool", SWITCH_CONFIG_BOOL}, {"custom", SWITCH_CONFIG_CUSTOM}, @@ -203,6 +204,48 @@ SWITCH_DECLARE(switch_status_t) switch_xml_config_parse_event(switch_event_t *ev } } break; + case SWITCH_CONFIG_ATOMIC: + { + switch_xml_config_atomic_options_t *atomic_options = (switch_xml_config_atomic_options_t *) item->data; + switch_atomic_t *dest = (switch_atomic_t *) ptr; + uint32_t uintval; + if (value) { + if (switch_is_number(value)) { + uintval = (uint32_t) strtoll(value, 10); + } else { + uintval = (uint32_t) (uintptr_t) item->defaultvalue; + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid value [%s] for parameter [%s], setting default [%u]\n", + value, item->key, uintval); + } + + if (atomic_options) { + /* Enforce validation options */ + if ((atomic_options->enforce_min && !(uintval >= atomic_options->min)) || (atomic_options->enforce_max && !(uintval <= atomic_options->max))) { + /* Validation failed, set default */ + uintval = (uint32_t) (uintptr_t) item->defaultvalue; + /* Then complain */ + if (atomic_options->enforce_min && atomic_options->enforce_max) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, + "Invalid value [%s] for parameter [%s], should be between [%u] and [%u], setting default [%u]\n", value, + item->key, atomic_options->min, atomic_options->max, uintval); + } else { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, + "Invalid value [%s] for parameter [%s], should be %s [%u], setting default [%u]\n", value, item->key, + atomic_options->enforce_min ? "at least" : "at max", + atomic_options->enforce_min ? atomic_options->min : atomic_options->max, uintval); + } + } + } + } else { + uintval = (uint32_t) (uintptr_t) item->defaultvalue; + } + + if (switch_atomic_read(dest) != uintval) { + switch_atomic_set(dest, uintval); + changed = SWITCH_TRUE; + } + } + break; case SWITCH_CONFIG_STRING: { switch_xml_config_string_options_t string_options_default = { 0 }; From d923f0f75c093dcda201110c83ec525bbdfa7b7d Mon Sep 17 00:00:00 2001 From: Eliot Gable Date: Tue, 23 Oct 2012 14:00:52 +0000 Subject: [PATCH 233/252] oops --- src/switch_xml_config.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/switch_xml_config.c b/src/switch_xml_config.c index a6fdc55496..8b13f12fde 100644 --- a/src/switch_xml_config.c +++ b/src/switch_xml_config.c @@ -211,7 +211,7 @@ SWITCH_DECLARE(switch_status_t) switch_xml_config_parse_event(switch_event_t *ev uint32_t uintval; if (value) { if (switch_is_number(value)) { - uintval = (uint32_t) strtoll(value, 10); + uintval = (uint32_t) strtoll(value, NULL, 10); } else { uintval = (uint32_t) (uintptr_t) item->defaultvalue; switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid value [%s] for parameter [%s], setting default [%u]\n", From 42fcaeacf59b76002798ccbab5bb0204c5e2a2e3 Mon Sep 17 00:00:00 2001 From: Eliot Gable Date: Tue, 23 Oct 2012 15:02:36 +0000 Subject: [PATCH 234/252] Better error message handling. --- src/switch_pgsql.c | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/src/switch_pgsql.c b/src/switch_pgsql.c index 8c6d59cf80..22ab6ffd6d 100644 --- a/src/switch_pgsql.c +++ b/src/switch_pgsql.c @@ -536,32 +536,32 @@ SWITCH_DECLARE(switch_pgsql_status_t) switch_pgsql_handle_exec_string(switch_pgs SWITCH_DECLARE(switch_pgsql_status_t) switch_pgsql_handle_exec_base(switch_pgsql_handle_t *handle, const char *sql, char **err) { #ifdef SWITCH_HAVE_PGSQL - char *err_str = NULL; + char *err_str = NULL, *er = NULL; handle->affected_rows = 0; if (!db_is_up(handle)) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Database is not up!\n"); + er = strdup("Database is not up!"); goto error; } if (handle->auto_commit == SWITCH_FALSE && handle->in_txn == SWITCH_FALSE) { if (switch_pgsql_send_query(handle, "BEGIN") != SWITCH_PGSQL_SUCCESS) { + er = strdup("Error sending BEGIN!"); switch_pgsql_finish_results(handle); - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error sending BEGIN!\n"); goto error; } if (switch_pgsql_finish_results(handle) != SWITCH_PGSQL_SUCCESS) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error sending BEGIN!\n"); + er = strdup("Error sending BEGIN!"); goto error; } handle->in_txn = SWITCH_TRUE; } if (switch_pgsql_send_query(handle, sql) != SWITCH_PGSQL_SUCCESS) { + er = strdup("Error sending query!"); switch_pgsql_finish_results(handle); - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error sending query!\n"); goto error; } @@ -571,7 +571,15 @@ SWITCH_DECLARE(switch_pgsql_status_t) switch_pgsql_handle_exec_base(switch_pgsql err_str = switch_pgsql_handle_get_error(handle); if (zstr(err_str)) { - err_str = strdup((char *)"SQL ERROR!"); + if (zstr(er)) { + err_str = strdup((char *)"SQL ERROR!"); + } else { + err_str = er; + } + } else { + if (!zstr(er)) { + free(er); + } } if (err_str) { From 2246b84554b237ba3fc63157ad8679be70d043a6 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Tue, 23 Oct 2012 11:05:39 -0400 Subject: [PATCH 235/252] fix missing line --- src/switch_ivr.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/switch_ivr.c b/src/switch_ivr.c index b8fd0923e3..df5af62391 100644 --- a/src/switch_ivr.c +++ b/src/switch_ivr.c @@ -1634,6 +1634,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_nomedia(const char *uuid, switch_medi } switch_channel_clear_flag(channel, CF_MEDIA_TRANS); + switch_core_session_rwunlock(session); } From 87c2bb552f45323f860216e1767e268d2be4d97e Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Tue, 23 Oct 2012 12:23:19 -0400 Subject: [PATCH 236/252] FS-4751 I am leaving out the one for devel-bootstrap.sh because I am not sure it should be /usr/pkg/bin/bash --- libs/libg722_1/configure.ac | 2 +- libs/sofia-sip/scripts/lcov-report | 2 +- libs/sofia-sip/scripts/uncovered | 2 +- libs/spandsp/configure.ac | 4 ++-- libs/spandsp/unpack_gsm0610_data.sh | 4 ++-- libs/tiff-4.0.2/configure.ac | 2 +- 6 files changed, 8 insertions(+), 8 deletions(-) diff --git a/libs/libg722_1/configure.ac b/libs/libg722_1/configure.ac index 62095ce374..829d7e0c45 100644 --- a/libs/libg722_1/configure.ac +++ b/libs/libg722_1/configure.ac @@ -200,7 +200,7 @@ AC_CHECK_HEADERS([audiofile.h]) AC_LANG([C]) -if test "${build}" == "${host}" +if test "${build}" = "${host}" then case "${host}" in x86_64-*) diff --git a/libs/sofia-sip/scripts/lcov-report b/libs/sofia-sip/scripts/lcov-report index 364f798128..77a0aaf40f 100755 --- a/libs/sofia-sip/scripts/lcov-report +++ b/libs/sofia-sip/scripts/lcov-report @@ -11,7 +11,7 @@ usage() { - test X$1 == X0 || exec >&2 + test X$1 = X0 || exec >&2 cat << EOF usage: coverage-report OPTIONS where OPTIONS are diff --git a/libs/sofia-sip/scripts/uncovered b/libs/sofia-sip/scripts/uncovered index 80f14ffad4..bdd156c789 100755 --- a/libs/sofia-sip/scripts/uncovered +++ b/libs/sofia-sip/scripts/uncovered @@ -11,7 +11,7 @@ usage() { - test X$1 == X0 || exec >&2 + test X$1 = X0 || exec >&2 cat < Date: Tue, 23 Oct 2012 13:00:16 -0400 Subject: [PATCH 237/252] OPENZAP-196 Fix casting issue - Apparently this fixes libpri BRI issues --- libs/freetdm/src/ftmod/ftmod_libpri/lpwrap_pri.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/freetdm/src/ftmod/ftmod_libpri/lpwrap_pri.c b/libs/freetdm/src/ftmod/ftmod_libpri/lpwrap_pri.c index 748b70a42f..c9f0576951 100644 --- a/libs/freetdm/src/ftmod/ftmod_libpri/lpwrap_pri.c +++ b/libs/freetdm/src/ftmod/ftmod_libpri/lpwrap_pri.c @@ -182,7 +182,7 @@ int lpwrap_init_pri(struct lpwrap_pri *spri, ftdm_span_t *span, ftdm_channel_t * #define timeval_to_ms(x) \ - (((ftdm_time_t)(x)->tv_sec * 1000) + (ftdm_time_t)((x)->tv_usec / 1000)) + (ftdm_time_t)(((x)->tv_sec * 1000) + ((x)->tv_usec / 1000)) int lpwrap_start_timer(struct lpwrap_pri *spri, struct lpwrap_timer *timer, const uint32_t timeout_ms, timeout_handler callback) { From 542e7153fcf2105952c3a5a2ece04488a868d28a Mon Sep 17 00:00:00 2001 From: Moises Silva Date: Tue, 23 Oct 2012 13:01:40 -0400 Subject: [PATCH 238/252] freetdm: Fix compilation with old libpri.h where AOC is not available --- libs/freetdm/src/ftmod/ftmod_libpri/ftmod_libpri.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libs/freetdm/src/ftmod/ftmod_libpri/ftmod_libpri.c b/libs/freetdm/src/ftmod/ftmod_libpri/ftmod_libpri.c index 37f27f3355..3b819df718 100644 --- a/libs/freetdm/src/ftmod/ftmod_libpri/ftmod_libpri.c +++ b/libs/freetdm/src/ftmod/ftmod_libpri/ftmod_libpri.c @@ -2249,6 +2249,7 @@ static int handle_facility_aoc_e(const struct pri_subcmd_aoc_e *aoc_e) ftdm_log(FTDM_LOG_INFO, "AOC-E:\n%s", tmp); return 0; } +#endif /** * \brief Handler for libpri facility events @@ -2275,6 +2276,7 @@ static int on_facility(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_ev int res = -1; switch (sub->cmd) { +#ifdef HAVE_LIBPRI_AOC case PRI_SUBCMD_AOC_S: /* AOC-S: Start of call */ res = handle_facility_aoc_s(&sub->u.aoc_s); break; @@ -2293,6 +2295,7 @@ static int on_facility(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_ev sub->u.aoc_request_response.charging_request, sub->u.aoc_request_response.charging_response); break; +#endif default: ftdm_log(FTDM_LOG_DEBUG, "FACILITY subcommand %d is not implemented, ignoring\n", sub->cmd); } @@ -2303,7 +2306,6 @@ static int on_facility(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_ev ftdm_log(FTDM_LOG_DEBUG, "Caught Event on span %d %u (%s)\n", ftdm_span_get_id(spri->span), event_type, lpwrap_pri_event_str(event_type)); return 0; } -#endif /** * \brief Handler for libpri dchan up event From 8b14f81343cfad456c74ea6ead68b283a24c3c7e Mon Sep 17 00:00:00 2001 From: Jeff Lenk Date: Tue, 23 Oct 2012 12:08:12 -0500 Subject: [PATCH 239/252] strtoll correction for windows --- src/switch_xml_config.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/switch_xml_config.c b/src/switch_xml_config.c index 8b13f12fde..888ed2c0f5 100644 --- a/src/switch_xml_config.c +++ b/src/switch_xml_config.c @@ -211,7 +211,7 @@ SWITCH_DECLARE(switch_status_t) switch_xml_config_parse_event(switch_event_t *ev uint32_t uintval; if (value) { if (switch_is_number(value)) { - uintval = (uint32_t) strtoll(value, NULL, 10); + uintval = (uint32_t) strtol(value, NULL, 10); } else { uintval = (uint32_t) (uintptr_t) item->defaultvalue; switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid value [%s] for parameter [%s], setting default [%u]\n", From 5f469ad2bd97197845f9bee354eece4ecc3b27d7 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Tue, 23 Oct 2012 13:14:51 -0400 Subject: [PATCH 240/252] FS-4753 --resolve this should properly detect it everywhere --- Makefile.am | 5 ++++- configure.in | 2 ++ libs/apr/.update | 2 +- libs/apr/Makefile.in | 12 ++++++++++++ libs/apr/configure.in | 3 +++ libs/apr/threadproc/unix/thread.c | 3 ++- libs/sofia-sip/.update | 2 +- libs/sofia-sip/Makefile.am | 3 +++ libs/sofia-sip/configure.ac | 3 +++ libs/sofia-sip/libsofia-sip-ua/su/su_pthread_port.c | 7 ++----- src/mod/endpoints/mod_sofia/Makefile.am | 1 + 11 files changed, 34 insertions(+), 9 deletions(-) diff --git a/Makefile.am b/Makefile.am index f11f891aac..036baafeba 100644 --- a/Makefile.am +++ b/Makefile.am @@ -450,7 +450,10 @@ libs/curl/lib/libcurl.la: libs/curl libs/curl/Makefile @cd libs/curl && $(MAKE) @$(TOUCH_TARGET) -libs/apr/libapr-1.la: libs/apr libs/apr/.update +libs/apr/Makefile: libs/apr/Makefile.in libs/apr/config.status libs/apr libs/apr/.update + @cd libs/apr && ./config.status + +libs/apr/libapr-1.la: libs/apr/Makefile touch src/include/switch.h @cd libs/apr && $(MAKE) @$(TOUCH_TARGET) diff --git a/configure.in b/configure.in index 89cf47d79e..2c4835afc2 100644 --- a/configure.in +++ b/configure.in @@ -559,6 +559,8 @@ AX_HAVE_CPU_SET AC_CHECK_LIB(rt, clock_gettime, [AC_DEFINE(HAVE_CLOCK_GETTIME, 1, [Define if you have clock_gettime()])]) AC_CHECK_LIB(rt, clock_getres, [AC_DEFINE(HAVE_CLOCK_GETRES, 1, [Define if you have clock_getres()])]) AC_CHECK_LIB(rt, clock_nanosleep, [AC_DEFINE(HAVE_CLOCK_NANOSLEEP, 1, [Define if you have clock_nanosleep()])]) +AC_CHECK_LIB(pthread, pthread_setschedprio, [AC_DEFINE(HAVE_PTHREAD_SETSCHEDPRIO, 1, [Define if you have pthread_setschedprio()])]) + AC_CHECK_FUNC(socket, , AC_CHECK_LIB(socket, socket)) AC_CHECK_FILE(/dev/ptmx, [AC_DEFINE(HAVE_DEV_PTMX, 1, [Define if you have /dev/ptmx])]) diff --git a/libs/apr/.update b/libs/apr/.update index 4452df8ef3..a55ae9a4f4 100644 --- a/libs/apr/.update +++ b/libs/apr/.update @@ -1 +1 @@ -Thu Sep 27 13:36:14 CDT 2012 +Tue Oct 23 13:13:30 EDT 2012 diff --git a/libs/apr/Makefile.in b/libs/apr/Makefile.in index fe6ad501c9..5aef325fe5 100644 --- a/libs/apr/Makefile.in +++ b/libs/apr/Makefile.in @@ -66,6 +66,18 @@ apr-config.out: $(APR_CONFIG) build/apr_rules.out: build/apr_rules.mk sed 's,^\(apr_build.*=\).*$$,\1$(installbuilddir),' < build/apr_rules.mk > $@ +.PRECIOUS: Makefile + +Makefile: $(srcdir)/Makefile.in $(top_blddir)/config.status + cd $(srcdir) && ./config.status + +$(top_blddir)/config.status: $(top_srcdir)/configure + $(SHELL) ./config.status --recheck + +$(top_srcdir)/configure: $(top_srcdir)/configure.in + cd $(srcdir) && autoconf + cd $(srcdir) && autoheader + install: $(TARGET_LIB) apr-config.out build/apr_rules.out $(APR_MKDIR) $(DESTDIR)$(libdir) $(DESTDIR)$(bindir) $(DESTDIR)$(installbuilddir) \ $(DESTDIR)$(libdir)/pkgconfig $(DESTDIR)$(includedir) diff --git a/libs/apr/configure.in b/libs/apr/configure.in index 68c030e124..412ee7e937 100644 --- a/libs/apr/configure.in +++ b/libs/apr/configure.in @@ -550,6 +550,7 @@ AC_CHECK_LIB(truerand, main) AC_SEARCH_LIBS(modf, m) AC_CHECK_LIB(dl, dlopen) + dnl ----------------------------- Checking for Threads echo "${nl}Checking for Threads..." @@ -1619,6 +1620,8 @@ APR_CHECK_DEFINE_FILES(POLLIN, poll.h sys/poll.h) if test "$threads" = "1"; then APR_CHECK_DEFINE(PTHREAD_PROCESS_SHARED, pthread.h) AC_CHECK_FUNCS(pthread_mutexattr_setpshared) + AC_CHECK_LIB(pthread, pthread_setschedprio, [AC_DEFINE(HAVE_PTHREAD_SETSCHEDPRIO, 1, [Define if you have pthread_setschedprio()])]) + # Some systems have setpshared and define PROCESS_SHARED, but don't # really support PROCESS_SHARED locks. So, we must validate that we # can go through the steps without receiving some sort of system error. diff --git a/libs/apr/threadproc/unix/thread.c b/libs/apr/threadproc/unix/thread.c index 786f83069e..391e5368c8 100644 --- a/libs/apr/threadproc/unix/thread.c +++ b/libs/apr/threadproc/unix/thread.c @@ -174,7 +174,8 @@ APR_DECLARE(apr_status_t) apr_thread_create(apr_thread_t **new, } if ((stat = pthread_create((*new)->td, temp, dummy_worker, (*new))) == 0) { -#ifndef __APPLE__ + +#ifdef HAVE_PTHREAD_SETSCHEDPRIO if (attr && attr->priority) { pthread_t *thread = (*new)->td; pthread_setschedprio(*thread, attr->priority); diff --git a/libs/sofia-sip/.update b/libs/sofia-sip/.update index ecae8fc840..22f5eeb029 100644 --- a/libs/sofia-sip/.update +++ b/libs/sofia-sip/.update @@ -1 +1 @@ -Mon Oct 1 12:24:45 CDT 2012 +Tue Oct 23 13:13:35 EDT 2012 diff --git a/libs/sofia-sip/Makefile.am b/libs/sofia-sip/Makefile.am index 069007d300..7279695865 100644 --- a/libs/sofia-sip/Makefile.am +++ b/libs/sofia-sip/Makefile.am @@ -40,6 +40,9 @@ dist_man_MANS = # man/man1/localinfo.1 man/man1/addrinfo.1 \ # man/man1/stunc.1 man/man1/sip-dig.1 +noop: + @echo ok + $(dist_man_MANS): manpages manpages: diff --git a/libs/sofia-sip/configure.ac b/libs/sofia-sip/configure.ac index 196d815157..1bce33e178 100644 --- a/libs/sofia-sip/configure.ac +++ b/libs/sofia-sip/configure.ac @@ -254,6 +254,9 @@ if test x"$have_check" = "xyes"; then fi AC_CHECK_HEADERS([fnmatch.h]) +AC_CHECK_LIB(pthread, pthread_setschedprio, [AC_DEFINE(HAVE_PTHREAD_SETSCHEDPRIO, 1, [Define if you have pthread_setschedprio()])]) + + dnl dl is currently used only in testing AC_CHECK_LIB([dl], [dlopen], [ dnl Note: -ldl is not added to LIBS diff --git a/libs/sofia-sip/libsofia-sip-ua/su/su_pthread_port.c b/libs/sofia-sip/libsofia-sip-ua/su/su_pthread_port.c index db314b28dd..5eb391f38d 100644 --- a/libs/sofia-sip/libsofia-sip-ua/su/su_pthread_port.c +++ b/libs/sofia-sip/libsofia-sip-ua/su/su_pthread_port.c @@ -269,13 +269,10 @@ int su_pthreaded_port_start(su_port_create_f *create, pthread_mutex_lock(arg.mutex); if (pthread_create(&tid, &attr, su_pthread_port_clone_main, &arg) == 0) { -#if defined (WIN32) - /* this needs to be revisited when pthread for Windows supports thread priority settings */ -#elif defined (__APPLE__) - /* no such function on Apple */ -#else +#ifdef HAVE_PTHREAD_SETSCHEDPRIO pthread_setschedprio(tid, 99); #endif + pthread_cond_wait(arg.cv, arg.mutex); thread_created = 1; } diff --git a/src/mod/endpoints/mod_sofia/Makefile.am b/src/mod/endpoints/mod_sofia/Makefile.am index efd6b2c385..7828c5eb49 100644 --- a/src/mod/endpoints/mod_sofia/Makefile.am +++ b/src/mod/endpoints/mod_sofia/Makefile.am @@ -41,6 +41,7 @@ BUILT_SOURCES = $(SOFIALA) $(mod_sofia_la_SOURCES) : $(BUILT_SOURCES) $(SOFIALA): $(SOFIA_DIR) $(SOFIA_DIR)/.update + cd $(SOFIA_BUILDDIR) && $(MAKE) noop cd $(SOFIA_BUILDDIR) && $(MAKE) SOFIA_CFLAGS="$(SWITCH_AM_CFLAGS)" $(TOUCH_TARGET) From f0895c9f51deea73155c12c0e8685def2fa7eca2 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Tue, 23 Oct 2012 18:14:27 -0400 Subject: [PATCH 241/252] print extended debug messages at alert level --- src/switch_log.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/switch_log.c b/src/switch_log.c index c8bdad3917..35314b0c3a 100644 --- a/src/switch_log.c +++ b/src/switch_log.c @@ -362,7 +362,7 @@ SWITCH_DECLARE(void) switch_log_vprintf(switch_text_channel_t channel, const cha return; } - level = 7; + level = 1; } if (level > limit_level) { From 7f46c7e29033f8086386881f5e3685968f7b93a0 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Tue, 23 Oct 2012 18:15:03 -0400 Subject: [PATCH 242/252] fix build dependancy regression to reduce rebuilds --- Makefile.am | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Makefile.am b/Makefile.am index 036baafeba..4f6f4c2bdd 100644 --- a/Makefile.am +++ b/Makefile.am @@ -452,8 +452,9 @@ libs/curl/lib/libcurl.la: libs/curl libs/curl/Makefile libs/apr/Makefile: libs/apr/Makefile.in libs/apr/config.status libs/apr libs/apr/.update @cd libs/apr && ./config.status + @$(TOUCH_TARGET) -libs/apr/libapr-1.la: libs/apr/Makefile +libs/apr/libapr-1.la: libs/apr/Makefile libs/apr/.update touch src/include/switch.h @cd libs/apr && $(MAKE) @$(TOUCH_TARGET) From 01dde19cbd967f0aa033dabb7a905ae356a34a2e Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Tue, 23 Oct 2012 18:19:32 -0400 Subject: [PATCH 243/252] FS-4741 --resolve use paypal@freeswitch.org --- .../mod_dialplan_xml/mod_dialplan_xml.c | 28 +++++++---- src/switch_xml.c | 46 ++++++++++++++++--- 2 files changed, 59 insertions(+), 15 deletions(-) diff --git a/src/mod/dialplans/mod_dialplan_xml/mod_dialplan_xml.c b/src/mod/dialplans/mod_dialplan_xml/mod_dialplan_xml.c index 2ff472afea..6b685d547d 100644 --- a/src/mod/dialplans/mod_dialplan_xml/mod_dialplan_xml.c +++ b/src/mod/dialplans/mod_dialplan_xml/mod_dialplan_xml.c @@ -79,6 +79,17 @@ static switch_status_t exec_app(switch_core_session_t *session, const char *app, return status; } + +#define check_tz() tzoff = switch_channel_get_variable(channel, "tod_tz_offset"); \ + do { \ + if (!zstr(tzoff) && switch_is_number(tzoff)) { \ + offset = atoi(tzoff); \ + } else { \ + tzoff = NULL; \ + } \ + break; \ + } while(tzoff) + static int parse_exten(switch_core_session_t *session, switch_caller_profile_t *caller_profile, switch_xml_t xexten, switch_caller_extension_t **extension) { switch_xml_t xcond, xaction, xexpression, xregex; @@ -88,13 +99,10 @@ static int parse_exten(switch_core_session_t *session, switch_caller_profile_t * char *expression_expanded = NULL, *field_expanded = NULL; switch_regex_t *re = NULL, *save_re = NULL; int offset = 0; - const char *tzoff = switch_channel_get_variable(channel, "tod_tz_offset"); + const char *tzoff; + + check_tz(); - if (!zstr(tzoff) && switch_is_number(tzoff)) { - offset = atoi(tzoff); - } else { - tzoff = NULL; - } if (!exten_name) { exten_name = "_anon_"; @@ -109,8 +117,11 @@ static int parse_exten(switch_core_session_t *session, switch_caller_profile_t * int ovector[30]; switch_bool_t anti_action = SWITCH_TRUE; break_t do_break_i = BREAK_ON_FALSE; + int time_match; + + check_tz(); + time_match = switch_xml_std_datetime_check(xcond, tzoff ? &offset : NULL); - int time_match = switch_xml_std_datetime_check(xcond, tzoff ? &offset : NULL); switch_safe_free(field_expanded); switch_safe_free(expression_expanded); @@ -161,8 +172,9 @@ static int parse_exten(switch_core_session_t *session, switch_caller_profile_t * switch_channel_del_variable_prefix(channel, "DP_REGEX_MATCH"); for (xregex = switch_xml_child(xcond, "regex"); xregex; xregex = xregex->next) { + check_tz(); time_match = switch_xml_std_datetime_check(xregex, tzoff ? &offset : NULL); - + if (time_match == 1) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG_CLEAN(session), SWITCH_LOG_DEBUG, "Dialplan: %s Date/Time Match (PASS) [%s]\n", diff --git a/src/switch_xml.c b/src/switch_xml.c index ec7eddec0a..237873e15d 100644 --- a/src/switch_xml.c +++ b/src/switch_xml.c @@ -2899,22 +2899,54 @@ SWITCH_DECLARE(int) switch_xml_std_datetime_check(switch_xml_t xcond, int *offse const char *xminday = switch_xml_attr(xcond, "minute-of-day"); const char *xtod = switch_xml_attr(xcond, "time-of-day"); const char *tzoff = switch_xml_attr(xcond, "tz-offset"); - int loffset = 0; + const char *isdst = switch_xml_attr(xcond, "dst"); + int loffset = -1000; + int eoffset = -1000; + int dst = -1000; switch_time_t ts = switch_micro_time_now(); int time_match = -1; - switch_time_exp_t tm; + switch_time_exp_t tm, tm2; + + if (!zstr(isdst)) { + dst = switch_true(isdst); + } if (!zstr(tzoff) && switch_is_number(tzoff)) { loffset = atoi(tzoff); - offset = &loffset; + } + + switch_time_exp_lt(&tm2, ts); + + if (offset) { + eoffset = *offset; + switch_time_exp_tz(&tm, ts, *offset); + } else { + tm = tm2; + } + + if (eoffset == -1000) { + eoffset = tm.tm_gmtoff / 3600; + } + + if (loffset == -1000) { + loffset = eoffset; } - if (offset) { - switch_time_exp_tz(&tm, ts, *offset); - } else { - switch_time_exp_lt(&tm, ts); + if (time_match && tzoff) { + time_match = loffset == eoffset; + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG9, + "XML DateTime Check: TZOFFSET[%d] == %d (%s)\n", eoffset, loffset, time_match ? "PASS" : "FAIL"); + + } + + if (time_match && dst > -1) { + time_match = (tm2.tm_isdst > 0 && dst > 0); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG9, + "XML DateTime Check: DST[%s] == %s (%s)\n", + tm2.tm_isdst > 0 ? "true" : "false", dst > 0 ? "true" : "false", time_match ? "PASS" : "FAIL"); + } if (time_match && xdt) { From 1a43405bed1b742e659dabfeb23cacb7c7a48c95 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Tue, 23 Oct 2012 20:38:03 -0400 Subject: [PATCH 244/252] up max db buffer size in core sql --- src/switch_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/switch_core.c b/src/switch_core.c index 82b08e3808..8f0895fb9b 100644 --- a/src/switch_core.c +++ b/src/switch_core.c @@ -1471,7 +1471,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_init(switch_core_flag_t flags, switc runtime.runlevel++; runtime.sql_buffer_len = 1024 * 32; - runtime.max_sql_buffer_len = 1024 * 1024; + runtime.max_sql_buffer_len = 1024 * 1024 * 10; runtime.dummy_cng_frame.data = runtime.dummy_data; runtime.dummy_cng_frame.datalen = sizeof(runtime.dummy_data); runtime.dummy_cng_frame.buflen = sizeof(runtime.dummy_data); From cecd0f4505e981041b416017bce1b1b2c19623dc Mon Sep 17 00:00:00 2001 From: Mahdi Moradi Date: Wed, 24 Oct 2012 18:59:36 +0330 Subject: [PATCH 245/252] With this changes, can say mobile numbers better. --- src/mod/say/mod_say_fa/mod_say_fa.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/mod/say/mod_say_fa/mod_say_fa.c b/src/mod/say/mod_say_fa/mod_say_fa.c index e044fca7b6..838465b612 100644 --- a/src/mod/say/mod_say_fa/mod_say_fa.c +++ b/src/mod/say/mod_say_fa/mod_say_fa.c @@ -502,8 +502,16 @@ static switch_status_t fa_say_telephone(switch_core_session_t *session, char *to } else { - play_group(SSM_PRONOUNCED,0,tosay[0] - 48,tosay[1] - 48,NULL,session,args); - fa_say_telephone(session,tosay + 2,say_args,args); + if ( tosay_length == 10 && (tosay[0] != '2' || tosay[1] != '1') ) + { + play_group(SSM_PRONOUNCED,tosay[0] - 48,tosay[1] - 48,tosay[2] - 48,NULL,session,args); + fa_say_telephone(session,tosay + 3,say_args,args); + } + else + { + play_group(SSM_PRONOUNCED,0,tosay[0] - 48,tosay[1] - 48,NULL,session,args); + fa_say_telephone(session,tosay + 2,say_args,args); + } } return SWITCH_STATUS_SUCCESS; } From fa9a0ed7042469b47d3537c332afafc12ae76be3 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Wed, 24 Oct 2012 12:34:03 -0500 Subject: [PATCH 246/252] FS-2746 found this assert in a BT on the conf box --- libs/xmlrpc-c/lib/abyss/src/response.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/libs/xmlrpc-c/lib/abyss/src/response.c b/libs/xmlrpc-c/lib/abyss/src/response.c index 235d787ff3..febd5af032 100644 --- a/libs/xmlrpc-c/lib/abyss/src/response.c +++ b/libs/xmlrpc-c/lib/abyss/src/response.c @@ -327,7 +327,12 @@ ResponseWriteStart(TSession * const sessionP) { -----------------------------------------------------------------------------*/ struct _TServer * const srvP = ConnServer(sessionP->connP)->srvP; - assert(!sessionP->responseStarted); + //assert(!sessionP->responseStarted); + + if (sessionP->responseStarted) { + TraceMsg("Abyss client called ResponseWriteStart() more than once\n"); + return FALSE; + } if (sessionP->status == 0) { /* Handler hasn't set status. That's an error */ From adce3f9c7cc2dc441483d6a2d3d61a0935cb4ae9 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Wed, 24 Oct 2012 13:53:54 -0400 Subject: [PATCH 247/252] FS-4729 try this version with the same debug patch applied --- src/switch_ivr_bridge.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/switch_ivr_bridge.c b/src/switch_ivr_bridge.c index 990b121f00..3d66adbd4d 100644 --- a/src/switch_ivr_bridge.c +++ b/src/switch_ivr_bridge.c @@ -1677,7 +1677,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_uuid_bridge(const char *originator_uu status = SWITCH_STATUS_SUCCESS; - switch_ivr_bridge_display(originator_session, originatee_session); + //switch_ivr_bridge_display(originator_session, originatee_session); /* release the read locks we have on the channels */ switch_core_session_rwunlock(originator_session); From f1e16ccbfa9bc0df6951f2ca9998b7d00221e29e Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Wed, 24 Oct 2012 12:33:13 -0500 Subject: [PATCH 248/252] only track calls once they have been answered --- src/switch_channel.c | 2 ++ src/switch_core_sqldb.c | 9 +++++++++ 2 files changed, 11 insertions(+) diff --git a/src/switch_channel.c b/src/switch_channel.c index fd00c5f71e..5ccca55184 100644 --- a/src/switch_channel.c +++ b/src/switch_channel.c @@ -3395,6 +3395,8 @@ SWITCH_DECLARE(switch_status_t) switch_channel_perform_mark_answered(switch_chan switch_channel_audio_sync(channel); + switch_core_recovery_track(channel->session); + return SWITCH_STATUS_SUCCESS; } diff --git a/src/switch_core_sqldb.c b/src/switch_core_sqldb.c index e23d427a1b..80ab68c110 100644 --- a/src/switch_core_sqldb.c +++ b/src/switch_core_sqldb.c @@ -2722,6 +2722,10 @@ SWITCH_DECLARE(void) switch_core_recovery_untrack(switch_core_session_t *session char *sql = NULL; switch_channel_t *channel = switch_core_session_get_channel(session); + if (!switch_channel_test_flag(channel, CF_ANSWERED) || switch_channel_get_state(channel) < CS_SOFT_EXECUTE) { + return; + } + if (!switch_channel_test_flag(channel, CF_TRACKABLE)) { return; } @@ -2756,6 +2760,11 @@ SWITCH_DECLARE(void) switch_core_recovery_track(switch_core_session_t *session) const char *profile_name; const char *technology; + + if (!switch_channel_test_flag(channel, CF_ANSWERED) || switch_channel_get_state(channel) < CS_SOFT_EXECUTE) { + return; + } + if (switch_channel_test_flag(channel, CF_RECOVERING) || !switch_channel_test_flag(channel, CF_TRACKABLE)) { return; } From 3124f8226c1c4d2e286316a22ce58f934d3e4a6b Mon Sep 17 00:00:00 2001 From: Jeff Lenk Date: Wed, 24 Oct 2012 19:17:15 -0500 Subject: [PATCH 249/252] FS-4761 --resolve --- src/mod/applications/mod_lcr/mod_lcr.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/mod/applications/mod_lcr/mod_lcr.c b/src/mod/applications/mod_lcr/mod_lcr.c index 8da2bd1dcc..55841170a4 100644 --- a/src/mod/applications/mod_lcr/mod_lcr.c +++ b/src/mod/applications/mod_lcr/mod_lcr.c @@ -1236,10 +1236,10 @@ static switch_status_t lcr_load_config() if (!strcasecmp(limit_type, "hash")) { profile->limit_type = "hash"; } else { - profile->limit_type = "sql"; + profile->limit_type = "db"; } } else { - profile->limit_type = "sql"; + profile->limit_type = "db"; } switch_core_hash_insert(globals.profile_hash, profile->name, profile); From b11649123a95a7e1cdbacd07987500452bb02ef5 Mon Sep 17 00:00:00 2001 From: Jeff Lenk Date: Thu, 25 Oct 2012 07:50:14 -0500 Subject: [PATCH 250/252] FS-4658 --resolve --- conf/vanilla/directory/default.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/conf/vanilla/directory/default.xml b/conf/vanilla/directory/default.xml index 0dc67412de..95b75b40dd 100644 --- a/conf/vanilla/directory/default.xml +++ b/conf/vanilla/directory/default.xml @@ -21,7 +21,7 @@ - + From 6e919cd43ba559111678a2c3a795323f34416a5e Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Thu, 25 Oct 2012 10:07:27 -0500 Subject: [PATCH 251/252] FS-4764 --resolve --- src/switch_ivr_bridge.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/switch_ivr_bridge.c b/src/switch_ivr_bridge.c index 3d66adbd4d..24e18f6b58 100644 --- a/src/switch_ivr_bridge.c +++ b/src/switch_ivr_bridge.c @@ -262,7 +262,7 @@ static void *audio_bridge_thread(switch_thread_t *thread, void *obj) if (switch_true(silence_var)) { silence_val = 1400; } else { - if ((silence_val = atoi(silence_var)) < 0) { + if ((silence_val = atoi(silence_var)) < -1) { silence_val = 0; } } From b8c0d3564c4ef1ec6595c1e2ce986d97f8792153 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Thu, 25 Oct 2012 12:55:50 -0500 Subject: [PATCH 252/252] FS-4765 --resolve --- src/mod/applications/mod_commands/mod_commands.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mod/applications/mod_commands/mod_commands.c b/src/mod/applications/mod_commands/mod_commands.c index 5e96474fd3..eb9db51e25 100644 --- a/src/mod/applications/mod_commands/mod_commands.c +++ b/src/mod/applications/mod_commands/mod_commands.c @@ -5415,7 +5415,7 @@ SWITCH_STANDARD_API(strftime_tz_api_function) } if (zstr(format)) { - format = "%Y-%m-%d"; + format = "%Y-%m-%d %T"; } if (format && switch_strftime_tz(tz_name, format, date, sizeof(date), when * 1000000) == SWITCH_STATUS_SUCCESS) { /* The lookup of the zone may fail. */