Freeswitch-svn
Threads by month
- ----- 2026 -----
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2006 -----
- December
- November
- October
- September
- August
- July
- June
January 2009
- 20 participants
- 514 discussions
[commit] r11219 - freeswitch/trunk/scripts/contrib/dschreiber/mod_nibblebill
by FreeSWITCH SVN 15 Jan '09
by FreeSWITCH SVN 15 Jan '09
15 Jan '09
Author: dschreiber
Date: Thu Jan 15 01:56:15 2009
New Revision: 11219
Log:
Updated nibblebill to add some dialplan applications
more to come
Modified:
freeswitch/trunk/scripts/contrib/dschreiber/mod_nibblebill/mod_nibblebill.c
Modified: freeswitch/trunk/scripts/contrib/dschreiber/mod_nibblebill/mod_nibblebill.c
==============================================================================
--- freeswitch/trunk/scripts/contrib/dschreiber/mod_nibblebill/mod_nibblebill.c (original)
+++ freeswitch/trunk/scripts/contrib/dschreiber/mod_nibblebill/mod_nibblebill.c Thu Jan 15 01:56:15 2009
@@ -29,9 +29,15 @@
* Darren Schreiber <d(a)d-man.org>
*
* mod_nibblebill.c - Nibble Billing
- * Set the session heartbeat on a call that has a billrate and deduct currency from
- * a database table each "tick" of the billing until funds are depleted.
- * Terminate the call upon depletion.
+ * Purpose is to allow real-time debiting of credit or cash from a database while calls are in progress. I had the following goals:
+ *
+ * Debit credit/cash from accounts real-time
+ * Allow for billing at different rates during a single call
+ * Allow for warning callers when their balance is low (via audio, in-channel)
+ * Allow for disconnecting or re-routing calls when balance is depleted
+ * Allow for billing to function as listed above with multiple concurrent calls
+ *
+ * Thanks go to bandwidth.com for funding this work.
*
*
* TODO: Create an override flag so you can force a start-time for when billing should count *from*
@@ -52,13 +58,20 @@
#endif
/* Defaults */
-/* static char SQL_LOOKUP[] = "SELECT cash FROM accounts WHERE id=\"%s\""; */
-static char SQL_SAVE[] = "UPDATE accounts SET cash=cash-%f WHERE id=\"%s\"";
+#ifdef SWITCH_HAVE_ODBC
+/*static char SQL_LOOKUP[] = "SELECT %s FROM %s WHERE %s=\"%s\"";*/
+static char SQL_SAVE[] = "UPDATE %s SET %s=%s-%f WHERE %s=\"%s\"";
+#endif
typedef struct
{
switch_time_t lastts; /* Last time we did any billing */
float total; /* Total amount billed so far */
+
+ switch_time_t pausets; /* Timestamp of when a pause action started. 0 if not paused */
+ float bill_adjustments; /* Adjustments to make to the next billing, based on pause/resume events */
+
+ float manual_adjustments; /* Manually added/deducted amounts from this account, to be committed at next database query */
} nibble_data_t;
@@ -88,12 +101,16 @@
float nobal_amt; /* Minimum amount that must remain in the account */
char *nobal_action; /* Drop action */
+ /* Other options */
+ int global_heartbeat; /* Supervise and bill every X seconds, 0 means off */
+
/* Database settings */
char *db_username;
char *db_password;
char *db_dsn;
- char *lookup_query;
- char *save_query;
+ char *db_table;
+ char *db_column_cash;
+ char *db_column_account;
#ifdef SWITCH_HAVE_ODBC
switch_odbc_handle_t *master_odbc;
#else
@@ -117,12 +134,14 @@
SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_db_username, globals.db_username);
SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_db_password, globals.db_password);
SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_db_dsn, globals.db_dsn);
-SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_lookup_query, globals.lookup_query);
-SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_save_query, globals.save_query);
+SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_db_table, globals.db_table);
+SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_db_column_cash, globals.db_column_cash);
+SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_db_column_account, globals.db_column_account);
SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_percall_action, globals.percall_action);
SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_lowbal_action, globals.lowbal_action);
SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_nobal_action, globals.nobal_action);
+#ifdef SWITCH_HAVE_ODBC
static int nibblebill_callback(void *pArg, int argc, char **argv, char **columnNames)
{
nibblebill_results_t *cbt = (nibblebill_results_t *) pArg;
@@ -131,6 +150,7 @@
return 0;
}
+#endif
static switch_status_t load_config(void)
{
@@ -141,7 +161,7 @@
if (!(xml = switch_xml_open_cfg(cf, &cfg, NULL))) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "open of %s failed\n", cf);
status = SWITCH_STATUS_SUCCESS; /* We don't fail because we can still write to a text file or buffer */
- goto done;
+ goto setdefaults;
}
if ((settings = switch_xml_child(cfg, "settings"))) {
@@ -149,35 +169,46 @@
char *var = (char *) switch_xml_attr_soft(param, "name");
char *val = (char *) switch_xml_attr_soft(param, "value");
- if (!strcasecmp(var, "db-username")) {
+ if (!strcasecmp(var, "db_username")) {
set_global_db_username(val);
- } else if (!strcasecmp(var, "db-password")) {
+ } else if (!strcasecmp(var, "db_password")) {
set_global_db_password(val);
- } else if (!strcasecmp(var, "db-dsn")) {
+ } else if (!strcasecmp(var, "db_dsn")) {
set_global_db_dsn(val);
- } else if (!strcasecmp(var, "lookup_query")) {
- set_global_lookup_query(val);
- } else if (!strcasecmp(var, "save_query")) {
- set_global_save_query(val);
+ } else if (!strcasecmp(var, "db_table")) {
+ set_global_db_table(val);
+ } else if (!strcasecmp(var, "db_column_cash")) {
+ set_global_db_column_cash(val);
+ } else if (!strcasecmp(var, "db_column_account")) {
+ set_global_db_column_account(val);
} else if (!strcasecmp(var, "percall_action")) {
set_global_percall_action(val);
+ } else if (!strcasecmp(var, "percall_max_amt")) {
+ globals.percall_max_amt = atof(val);
} else if (!strcasecmp(var, "lowbal_action")) {
set_global_lowbal_action(val);
+ } else if (!strcasecmp(var, "lowbal_amt")) {
+ globals.lowbal_amt = atof(val);
} else if (!strcasecmp(var, "nobal_action")) {
set_global_nobal_action(val);
+ } else if (!strcasecmp(var, "nobal_amt")) {
+ globals.nobal_amt = atof(val);
+ } else if (!strcasecmp(var, "global_heartbeat")) {
+ globals.global_heartbeat = atoi(val);
}
}
}
-done:
+/* Set defaults for any variables still not set */
+setdefaults:
if (switch_strlen_zero(globals.db_username)) {
- set_global_db_username("phonebooth");
+ set_global_db_username("bandwidth.com");
}
if (switch_strlen_zero(globals.db_password)) {
set_global_db_password("dev");
}
if (switch_strlen_zero(globals.db_dsn)) {
- set_global_db_dsn("phonebooth");
+ set_global_db_dsn("bandwidth.com");
}
if (switch_strlen_zero(globals.percall_action)) {
set_global_percall_action("hangup");
@@ -188,14 +219,13 @@
if (switch_strlen_zero(globals.nobal_action)) {
set_global_nobal_action("hangup");
}
- /* Need to add defaults for the integers! */
#ifdef SWITCH_HAVE_ODBC
if (globals.db_dsn) {
if (!(globals.master_odbc = switch_odbc_handle_new(globals.db_dsn, globals.db_username, globals.db_password))) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Cannot create handle to ODBC Database!\n");
status = SWITCH_STATUS_FALSE;
- goto reallydone;
+ goto done;
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Opened ODBC Database handle!\n");
}
@@ -203,7 +233,7 @@
if (switch_odbc_handle_connect(globals.master_odbc) != SWITCH_ODBC_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Cannot connect to ODBC driver/database %s (user: %s / pass %s)!\n", globals.db_dsn, globals.db_username, globals.db_password);
status = SWITCH_STATUS_FALSE;
- goto reallydone;
+ goto done;
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Opened ODBC Database!\n");
}
@@ -216,7 +246,7 @@
#endif
#ifdef SWITCH_HAVE_ODBC
-reallydone:
+done:
#endif
if (xml) {
@@ -245,7 +275,11 @@
static switch_status_t sched_billing(switch_core_session_t *session)
{
- switch_core_session_enable_heartbeat(session, 60);
+ if (globals.global_heartbeat > 0) {
+ switch_core_session_enable_heartbeat(session, globals.global_heartbeat);
+ }
+
+ // Check account balance here
return SWITCH_STATUS_SUCCESS;
@@ -263,7 +297,9 @@
nibble_data_t *nibble_data;
switch_time_t ts = switch_timestamp_now();
float billamount;
+ float adjustments = 0;
char date[80] = "";
+ char *tmp;
char *uuid;
switch_size_t retsize;
switch_time_exp_t tm;
@@ -313,6 +349,15 @@
/* Get our nibble data var. This will be NULL if it's our first call here for this session */
nibble_data = (nibble_data_t *) switch_channel_get_private(channel, "_nibble_data_");
+ /* Are we in paused mode? If so, we don't do anything here - go back! */
+ if (nibble_data->pausets > 0) {
+ if (globals.mutex) {
+ switch_mutex_unlock(globals.mutex);
+ }
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Received heartbeat, but we're paused - ignoring\n");
+ return SWITCH_STATUS_SUCCESS;
+ }
+
/* Have we done any billing on this channel yet? If no, set up vars for doing so */
if (!nibble_data) {
nibble_data = switch_core_session_alloc(session, sizeof(*nibble_data));
@@ -337,34 +382,46 @@
if ((ts - nibble_data->lastts) > 0) {
/* Convert billrate into microseconds and multiply by # of microseconds that have passed */
billamount = (atof(billrate) / 1000000 / 60) * ((ts - nibble_data->lastts));
+ adjustments = nibble_data->manual_adjustments + nibble_data->bill_adjustments;
/* if ODBC call fails, we should return BEFORE updating the timestamp of last success! */
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Billing $%f to %s (Call: %s / %f so far)\n", billamount, billaccount, uuid, nibble_data->total);
+ if (adjustments > 0) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "(Also adjusting the account by $%f)\n", adjustments);
+ }
+
/* DO ODBC BILLING HERE! */
#ifdef SWITCH_HAVE_ODBC
char sql[1024] = "";
nibblebill_results_t pdata;
memset(&pdata, 0, sizeof(pdata));
- if (!globals.save_query){
- snprintf(sql, 1024, SQL_SAVE, billamount, billaccount);
- } else {
- snprintf(sql, 1024, globals.save_query, billamount, billaccount);
- }
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Doing static update query\n[%s]\n", sql);
+ snprintf(sql, 1024, SQL_SAVE, globals.db_table, globals.db_column_cash, globals.db_column_cash, (billamount - adjustments), globals.db_column_account, billaccount);
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Doing update query\n[%s]\n", sql);
if (!(switch_odbc_handle_callback_exec(globals.master_odbc, sql, nibblebill_callback, &pdata) == SWITCH_ODBC_SUCCESS)){
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "DB Error while updating cash!\n");
/* TODO: If this is a hangup event, we should store this billing in a text file while the DB is unavailable */
- }
+ } else {
#endif
+ /* Increment total cost */
+ nibble_data->total += billamount;
- /* Increment total cost */
- nibble_data->total += billamount;
+ /* Get rid of any manual adjustments that were just committed */
+ nibble_data->manual_adjustments = 0;
+ nibble_data->bill_adjustments = 0;
+
+ /* Update channel variable with current billing */
+ tmp = switch_mprintf("%f", nibble_data->total);
+ switch_channel_set_variable(channel, "nibble_total_billed", tmp);
+ switch_safe_free(tmp);
+#ifdef SWITCH_HAVE_ODBC
+ }
+#endif
} else {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Just tried to bill %s negative minutes! wtf?\n", uuid);
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Just tried to bill %s negative minutes! wtf? That should be impossible.\n", uuid);
}
/* Update the last time we billed */
@@ -373,14 +430,16 @@
/* Save everything back */
switch_channel_set_private(channel, "_nibble_data_", nibble_data);
- /* Release the session lock */
- switch_core_session_rwunlock(session);
-
/* Done changing - release lock */
if (globals.mutex) {
switch_mutex_unlock(globals.mutex);
}
+ /* Go check if this call is allowed to continue */
+
+ /* Release the session lock */
+ switch_core_session_rwunlock(session);
+
return SWITCH_STATUS_SUCCESS;
}
@@ -421,28 +480,99 @@
switch_core_session_rwunlock(session);
}
-SWITCH_STANDARD_APP(nibblebill_app_function)
+
+static float nibblebill_check(switch_core_session_t *session)
{
switch_channel_t *channel = switch_core_session_get_channel(session);
+ nibble_data_t *nibble_data;
+ float amount = 0;
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "We made it!\n");
+ if (!channel) {
+ return -99999;
+ }
+
+ /* Lock this session's data for this module while we tinker with it */
+ if (globals.mutex) {
+ switch_mutex_lock(globals.mutex);
+ }
+
+ /* Get our nibble data var. This will be NULL if it's our first call here for this session */
+ nibble_data = (nibble_data_t *) switch_channel_get_private(channel, "_nibble_data_");
+
+ amount = nibble_data->total;
+
+ /* Done checking - release lock */
+ if (globals.mutex) {
+ switch_mutex_unlock(globals.mutex);
+ }
+
+ return amount;
+}
+
+static void nibblebill_adjust(switch_core_session_t *session, float amount)
+{
+ switch_channel_t *channel = switch_core_session_get_channel(session);
+ nibble_data_t *nibble_data;
+ char *uuid;
if (!channel) {
return;
}
+
+ uuid = switch_core_session_get_uuid(session);
+
+ /* Lock this session's data for this module while we tinker with it */
+ if (globals.mutex) {
+ switch_mutex_lock(globals.mutex);
+ }
+
+ /* Get our nibble data var. This will be NULL if it's our first call here for this session */
+ nibble_data = (nibble_data_t *) switch_channel_get_private(channel, "_nibble_data_");
+
+ /*Add or remove amount from adjusted billing here */
+ nibble_data->manual_adjustments += amount;
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Current adjustment for %s is $%f\n", uuid, amount);
+
+ /* Done changing - release lock */
+ if (globals.mutex) {
+ switch_mutex_unlock(globals.mutex);
+ }
+
+ /* Release the session lock */
+ switch_core_session_rwunlock(session);
+}
+
+#define CHECK_APP_SYNTAX ""
+SWITCH_STANDARD_APP(nibblebill_check_app_function)
+{
+ float amount;
+
+ amount = nibblebill_check(session);
+
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Current billing is at $%f\n", amount);
+}
+
+#define ADJUST_APP_SYNTAX "<amount>"
+SWITCH_STANDARD_APP(nibblebill_adjust_app_function)
+{
+ char *mydata = NULL;
+ int argc = 0;
+ char *argv[4] = { 0 };
+ float amount;
-/* if (!(mydata = switch_core_session_strdup(session, data))) {
+ if (!(mydata = switch_core_session_strdup(session, data))) {
return;
}
if ((argc = switch_separate_string(mydata, ' ', argv, (sizeof(argv) / sizeof(argv[0]))))) {
- destnum = argv[0];
- do_billing(session);
- }*/
+ amount = atof(argv[0]);
+ nibblebill_adjust(session, amount);
+ }
}
/* We get here from the API only (theoretically) */
-SWITCH_STANDARD_API(nibblebill_function)
+#define CHECK_API_SYNTAX "<uuid>"
+SWITCH_STANDARD_API(nibblebill_check_api_function)
{
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "We made it!\n");
@@ -459,7 +589,7 @@
{
/* on_init */ NULL,
/* on_routing */ NULL, /* Need to add a check here for anything in their account before routing */
- /* on_execute */ sched_billing, /* Turn on heartbeat for this session */
+ /* on_execute */ sched_billing, /* Turn on heartbeat for this session and do an initial account check */
/* on_hangup */ do_billing, /* On hangup - most important place to go bill */
/* on_exch_media */ NULL,
/* on_soft_exec */ NULL,
@@ -479,8 +609,20 @@
/* connect my internal structure to the blank pointer passed to me */
*module_interface = switch_loadable_module_create_module_interface(pool, modname);
- SWITCH_ADD_API(api_interface, "check", "Check the balance of an account", nibblebill_function, "");
- SWITCH_ADD_APP(app_interface, "check", "Check the balance on an account", "Perform an account check for fund balance", nibblebill_app_function, "<number>", SAF_SUPPORT_NOMEDIA);
+
+ /* Add API and CLI commands */
+/* SWITCH_ADD_API(api_interface, "pause", "Pause billing on a session", nibblebill_pause_api_function, PAUSE_API_SYNTAX);
+ SWITCH_ADD_API(api_interface, "resume", "Resume billing on a session", nibblebill_resume_api_function, RESUME_API_SYNTAX);
+ SWITCH_ADD_API(api_interface, "reset", "Reset billing start time to right now - disregard any unbilled time thus far", nibblebill_reset_api_function, RESET_API_SYNTAX);
+ SWITCH_ADD_API(api_interface, "adjust", "Add or deduct a dollar amount from a caller's account", nibblebill_adjust_api_function, ADJUST_API_SYNTAX);*/
+ SWITCH_ADD_API(api_interface, "check", "Check the balance of a session", nibblebill_check_api_function, CHECK_API_SYNTAX);
+
+ /* Add dialplan applications */
+/* SWITCH_ADD_APP(app_interface, "pause", "Pause billing on a session", "Pause billing on a session", nibblebill_pause_app_function, PAUSE_APP_SYNTAX, SAF_NONE);
+ SWITCH_ADD_APP(app_interface, "resume", "Resume billing on a session", "Resume billing on a session", nibblebill_resume_app_function, RESUME_APP_SYNTAX, SAF_NONE);
+ SWITCH_ADD_APP(app_interface, "reset", "Check the balance of a session", "Check the balance of a session", nibblebill_reset_app_function, RESET_APP_SYNTAX, SAF_NONE);*/
+ SWITCH_ADD_APP(app_interface, "adjust", "Add or deduct a dollar amount from a caller's account", "Add or deduct a dollar amount from a callers' account (use negative numbers to deduct)", nibblebill_adjust_app_function, ADJUST_APP_SYNTAX, SAF_NONE);
+ SWITCH_ADD_APP(app_interface, "check", "Check the balance on an account", "Perform an account check for fund balance on a specific caller's account", nibblebill_check_app_function, CHECK_APP_SYNTAX, SAF_NONE);
/* register state handlers for billing */
switch_core_add_state_handler(&nibble_state_handler);
1
0
[commit] r11218 - freeswitch/trunk/src/mod/languages/mod_managed/managed
by FreeSWITCH SVN 15 Jan '09
by FreeSWITCH SVN 15 Jan '09
15 Jan '09
Author: michaelgg
Date: Wed Jan 14 23:36:45 2009
New Revision: 11218
Log:
Fix DLL name in Makefile
Modified:
freeswitch/trunk/src/mod/languages/mod_managed/managed/Makefile
Modified: freeswitch/trunk/src/mod/languages/mod_managed/managed/Makefile
==============================================================================
--- freeswitch/trunk/src/mod/languages/mod_managed/managed/Makefile (original)
+++ freeswitch/trunk/src/mod/languages/mod_managed/managed/Makefile Wed Jan 14 23:36:45 2009
@@ -1,14 +1,14 @@
-all: mod_managed_lib.dll
+all: FreeSWITCH.Managed.dll
clean:
- rm -fr mod_managed_lib.dll
+ rm -fr FreeSWITCH.Managed.dll
-mod_managed_lib.dll: Loader.cs ManagedSession.cs ApiFunction.cs AppFunction.cs Extensions.cs Log.cs Demo.cs swig.cs
- gmcs -target:library -out:mod_managed_lib.dll -d:DEBUG Loader.cs ManagedSession.cs ApiFunction.cs AppFunction.cs Extensions.cs Log.cs Demo.cs swig.cs
+FreeSWITCH.Managed.dll: Loader.cs ManagedSession.cs ApiFunction.cs AppFunction.cs Extensions.cs Log.cs Demo.cs swig.cs
+ gmcs -target:library -out:FreeSWITCH.Managed.dll -d:DEBUG Loader.cs ManagedSession.cs ApiFunction.cs AppFunction.cs Extensions.cs Log.cs Demo.cs swig.cs
-install: mod_managed_lib.dll
- $(INSTALL) mod_managed_lib.dll $(DESTDIR)$(MODINSTDIR)
+install: FreeSWITCH.Managed.dll
+ $(INSTALL) FreeSWITCH.Managed.dll $(DESTDIR)$(MODINSTDIR)
uninstall:
- $(UNINSTALL) $(MODINSTDIR)/mod_managed_lib.dll
+ $(UNINSTALL) $(MODINSTDIR)/FreeSWITCH.Managed.dll
1
0
15 Jan '09
Author: mrene
Date: Wed Jan 14 22:50:06 2009
New Revision: 11217
Log:
tweak
Modified:
freeswitch/trunk/src/mod/applications/mod_limit/mod_limit.c
Modified: freeswitch/trunk/src/mod/applications/mod_limit/mod_limit.c
==============================================================================
--- freeswitch/trunk/src/mod/applications/mod_limit/mod_limit.c (original)
+++ freeswitch/trunk/src/mod/applications/mod_limit/mod_limit.c Wed Jan 14 22:50:06 2009
@@ -806,7 +806,7 @@
char *id = NULL;
char *hashkey = NULL;
char *xfer_exten = NULL;
- int max = 0;
+ int max = -1;
int interval = 0;
char *szinterval = NULL;
limit_hash_item_t *item = NULL;
1
0
15 Jan '09
Author: mrene
Date: Wed Jan 14 22:46:58 2009
New Revision: 11216
Log:
tweak
Modified:
freeswitch/trunk/src/mod/applications/mod_limit/mod_limit.c
Modified: freeswitch/trunk/src/mod/applications/mod_limit/mod_limit.c
==============================================================================
--- freeswitch/trunk/src/mod/applications/mod_limit/mod_limit.c (original)
+++ freeswitch/trunk/src/mod/applications/mod_limit/mod_limit.c Wed Jan 14 22:46:58 2009
@@ -822,7 +822,7 @@
argc = switch_separate_string(mydata, ' ', argv, (sizeof(argv) / sizeof(argv[0])));
}
- if (argc < 3) {
+ if (argc < 2) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "USAGE: limit_hash %s\n", LIMITHASH_USAGE);
return;
}
1
0
[commit] r11215 - freeswitch/trunk/scripts/contrib/dschreiber/mod_nibblebill
by FreeSWITCH SVN 15 Jan '09
by FreeSWITCH SVN 15 Jan '09
15 Jan '09
Author: dschreiber
Date: Wed Jan 14 22:20:56 2009
New Revision: 11215
Log:
Removed more whitespaces
Modified:
freeswitch/trunk/scripts/contrib/dschreiber/mod_nibblebill/mod_nibblebill.c
Modified: freeswitch/trunk/scripts/contrib/dschreiber/mod_nibblebill/mod_nibblebill.c
==============================================================================
--- freeswitch/trunk/scripts/contrib/dschreiber/mod_nibblebill/mod_nibblebill.c (original)
+++ freeswitch/trunk/scripts/contrib/dschreiber/mod_nibblebill/mod_nibblebill.c Wed Jan 14 22:20:56 2009
@@ -190,7 +190,6 @@
}
/* Need to add defaults for the integers! */
-
#ifdef SWITCH_HAVE_ODBC
if (globals.db_dsn) {
if (!(globals.master_odbc = switch_odbc_handle_new(globals.db_dsn, globals.db_username, globals.db_password))) {
@@ -209,14 +208,13 @@
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Opened ODBC Database!\n");
}
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Connected ODBC DSN: %s\n", globals.db_dsn);
- } else {
+ } else {
#endif
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "ODBC does not appear to be installed in the core. You need to run ./configure --enable-core-odbc-support\n");
#ifdef SWITCH_HAVE_ODBC
}
#endif
-
#ifdef SWITCH_HAVE_ODBC
reallydone:
#endif
@@ -254,7 +252,7 @@
}
/* This is where we actually charge the guy
- This can be called anytime a call is in progress or at the end of a call before the session is destroyed */
+ This can be called anytime a call is in progress or at the end of a call before the session is destroyed */
static switch_status_t do_billing(switch_core_session_t *session)
{
/* FS vars we will use */
@@ -265,10 +263,10 @@
nibble_data_t *nibble_data;
switch_time_t ts = switch_timestamp_now();
float billamount;
- char date[80] = "";
+ char date[80] = "";
char *uuid;
- switch_size_t retsize;
- switch_time_exp_t tm;
+ switch_size_t retsize;
+ switch_time_exp_t tm;
if (!session) {
/* wtf? Why are we here? */
@@ -488,10 +486,10 @@
switch_core_add_state_handler(&nibble_state_handler);
/* bind to heartbeat events */
- if (switch_event_bind_removable(modname, SWITCH_EVENT_SESSION_HEARTBEAT, SWITCH_EVENT_SUBCLASS_ANY, event_handler, NULL, &globals.node) != SWITCH_STATUS_SUCCESS) {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't bind event to monitor for session heartbeats!\n");
- return SWITCH_STATUS_GENERR;
- }
+ if (switch_event_bind_removable(modname, SWITCH_EVENT_SESSION_HEARTBEAT, SWITCH_EVENT_SUBCLASS_ANY, event_handler, NULL, &globals.node) != SWITCH_STATUS_SUCCESS) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't bind event to monitor for session heartbeats!\n");
+ return SWITCH_STATUS_GENERR;
+ }
/* indicate that the module should continue to be loaded */
return SWITCH_STATUS_SUCCESS;
1
0
[commit] r11214 - freeswitch/trunk/scripts/contrib/dschreiber/mod_nibblebill
by FreeSWITCH SVN 15 Jan '09
by FreeSWITCH SVN 15 Jan '09
15 Jan '09
Author: dschreiber
Date: Wed Jan 14 21:58:46 2009
New Revision: 11214
Log:
Formatting fixes, per Brian
Also changed comments to be C compat
Modified:
freeswitch/trunk/scripts/contrib/dschreiber/mod_nibblebill/mod_nibblebill.c
Modified: freeswitch/trunk/scripts/contrib/dschreiber/mod_nibblebill/mod_nibblebill.c
==============================================================================
--- freeswitch/trunk/scripts/contrib/dschreiber/mod_nibblebill/mod_nibblebill.c (original)
+++ freeswitch/trunk/scripts/contrib/dschreiber/mod_nibblebill/mod_nibblebill.c Wed Jan 14 21:58:46 2009
@@ -51,41 +51,44 @@
#include <switch_odbc.h>
#endif
-// Defaults
-//static char SQL_LOOKUP[] = "SELECT cash FROM accounts WHERE id=\"%s\"";
+/* Defaults */
+/* static char SQL_LOOKUP[] = "SELECT cash FROM accounts WHERE id=\"%s\""; */
static char SQL_SAVE[] = "UPDATE accounts SET cash=cash-%f WHERE id=\"%s\"";
-typedef struct {
- switch_time_t lastts; // Last time we did any billing
- float total; // Total amount billed so far
+typedef struct
+{
+ switch_time_t lastts; /* Last time we did any billing */
+ float total; /* Total amount billed so far */
} nibble_data_t;
-typedef struct nibblebill_results{
+typedef struct nibblebill_results
+{
float funds;
- float percall_max; // Overrides global on a per-user level
- float lowbal_amt; // ditto
+ float percall_max; /* Overrides global on a per-user level */
+ float lowbal_amt; /* ditto */
} nibblebill_results_t;
/* Keep track of our config, event hooks and database connection variables, for this module only */
-static struct {
- // Event hooks
+static struct
+{
+ /* Event hooks */
switch_event_node_t *node;
- // Global mutex (don't touch a session when it's already being touched)
+ /* Global mutex (don't touch a session when it's already being touched) */
switch_mutex_t *mutex;
- // Global billing config options
- float percall_max_amt; // Per-call billing limit (safety check, for fraud)
- char *percall_action; // Exceeded length of per-call action
- float lowbal_amt; // When we warn them they are near depletion
- char *lowbal_action; // Low balance action
- float nobal_amt; // Minimum amount that must remain in the account
- char *nobal_action; // Drop action
+ /* Global billing config options */
+ float percall_max_amt; /* Per-call billing limit (safety check, for fraud) */
+ char *percall_action; /* Exceeded length of per-call action */
+ float lowbal_amt; /* When we warn them they are near depletion */
+ char *lowbal_action; /* Low balance action */
+ float nobal_amt; /* Minimum amount that must remain in the account */
+ char *nobal_action; /* Drop action */
- // Database settings
+ /* Database settings */
char *db_username;
char *db_password;
char *db_dsn;
@@ -94,7 +97,7 @@
#ifdef SWITCH_HAVE_ODBC
switch_odbc_handle_t *master_odbc;
#else
- void *padding1; // Keep structures same size
+ void *padding1; /* Keep structures same size */
#endif
} globals;
@@ -120,8 +123,6 @@
SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_lowbal_action, globals.lowbal_action);
SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_nobal_action, globals.nobal_action);
-
-
static int nibblebill_callback(void *pArg, int argc, char **argv, char **columnNames)
{
nibblebill_results_t *cbt = (nibblebill_results_t *) pArg;
@@ -131,8 +132,6 @@
return 0;
}
-
-
static switch_status_t load_config(void)
{
char *cf = "nibblebill.conf";
@@ -141,7 +140,7 @@
if (!(xml = switch_xml_open_cfg(cf, &cfg, NULL))) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "open of %s failed\n", cf);
- status = SWITCH_STATUS_SUCCESS; // We don't fail because we can still write to a text file or buffer
+ status = SWITCH_STATUS_SUCCESS; /* We don't fail because we can still write to a text file or buffer */
goto done;
}
@@ -149,6 +148,7 @@
for (param = switch_xml_child(settings, "param"); param; param = param->next) {
char *var = (char *) switch_xml_attr_soft(param, "name");
char *val = (char *) switch_xml_attr_soft(param, "value");
+
if (!strcasecmp(var, "db-username")) {
set_global_db_username(val);
} else if (!strcasecmp(var, "db-password")) {
@@ -188,7 +188,7 @@
if (switch_strlen_zero(globals.nobal_action)) {
set_global_nobal_action("hangup");
}
- // Need to add defaults for the integers!
+ /* Need to add defaults for the integers! */
#ifdef SWITCH_HAVE_ODBC
@@ -200,6 +200,7 @@
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Opened ODBC Database handle!\n");
}
+
if (switch_odbc_handle_connect(globals.master_odbc) != SWITCH_ODBC_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Cannot connect to ODBC driver/database %s (user: %s / pass %s)!\n", globals.db_dsn, globals.db_username, globals.db_password);
status = SWITCH_STATUS_FALSE;
@@ -210,7 +211,7 @@
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Connected ODBC DSN: %s\n", globals.db_dsn);
} else {
#endif
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "ODBC does not appear to be installed in the core\n");
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "ODBC does not appear to be installed in the core. You need to run ./configure --enable-core-odbc-support\n");
#ifdef SWITCH_HAVE_ODBC
}
#endif
@@ -226,15 +227,15 @@
return status;
}
-
-void debug_event_handler(switch_event_t *event) {
+void debug_event_handler(switch_event_t *event)
+{
switch_event_header_t *event_header = NULL;
if (!event) {
return;
}
- // Print out all event headers, for fun
+ /* Print out all event headers, for fun */
if (event->headers) {
for (event_header = event->headers; event_header; event_header = event_header->next) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Header info: %s => %s\n", event_header->name, event_header->value);
@@ -243,7 +244,8 @@
}
-static switch_status_t sched_billing(switch_core_session_t *session) {
+static switch_status_t sched_billing(switch_core_session_t *session)
+{
switch_core_session_enable_heartbeat(session, 60);
@@ -251,15 +253,15 @@
}
-/* This is where we actually charge the guy */
-/* This can be called anytime a call is in progress or at the end of a call before the session is destroyed */
-static switch_status_t do_billing(switch_core_session_t *session) {
-
- // FS vars we will use
+/* This is where we actually charge the guy
+ This can be called anytime a call is in progress or at the end of a call before the session is destroyed */
+static switch_status_t do_billing(switch_core_session_t *session)
+{
+ /* FS vars we will use */
switch_channel_t *channel;
switch_caller_profile_t *profile;
- // Local vars
+ /* Local vars */
nibble_data_t *nibble_data;
switch_time_t ts = switch_timestamp_now();
float billamount;
@@ -269,34 +271,34 @@
switch_time_exp_t tm;
if (!session) {
- // wtf? Why are we here?
+ /* wtf? Why are we here? */
return SWITCH_STATUS_GENERR;
}
uuid = switch_core_session_get_uuid(session);
- // Get channel var
+ /* Get channel var */
channel = switch_core_session_get_channel(session);
if (!channel) {
return SWITCH_STATUS_GENERR;
}
- // Variables kept in FS but relevant only to this module
+ /* Variables kept in FS but relevant only to this module */
const char *billrate = switch_channel_get_variable(channel, "nibble_rate");
const char *billaccount = switch_channel_get_variable(channel, "nibble_account");
- // Return if there's no billing information on this session
+ /* Return if there's no billing information on this session */
if (!billrate || !billaccount) {
return SWITCH_STATUS_GENERR;
}
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Attempting to bill at $%s per minute to account %s\n", billrate, billaccount);
- // Get caller profile info from channel
+ /* Get caller profile info from channel */
profile = switch_channel_get_caller_profile(channel);
if (!profile) {
- // No caller profile (why would this happen?)
+ /* No caller profile (why would this happen?) */
return SWITCH_STATUS_GENERR;
}
@@ -305,15 +307,15 @@
return SWITCH_STATUS_SUCCESS;
}
- // Lock this session's data for this module while we tinker with it
+ /* Lock this session's data for this module while we tinker with it */
if (globals.mutex) {
switch_mutex_lock(globals.mutex);
}
- // Get our nibble data var. This will be NULL if it's our first call here for this session
+ /* Get our nibble data var. This will be NULL if it's our first call here for this session */
nibble_data = (nibble_data_t *) switch_channel_get_private(channel, "_nibble_data_");
- // Have we done any billing on this channel yet? If no, set up vars for doing so
+ /* Have we done any billing on this channel yet? If no, set up vars for doing so */
if (!nibble_data) {
nibble_data = switch_core_session_alloc(session, sizeof(*nibble_data));
if (!nibble_data) {
@@ -321,8 +323,8 @@
}
memset(nibble_data, 0, sizeof(*nibble_data));
- // Setup new billing data (based on call answer time, in case this module started late with active calls)
- nibble_data->lastts = profile->times->answered; // Set the initial answer time to match when the call was really answered
+ /* Setup new billing data (based on call answer time, in case this module started late with active calls) */
+ nibble_data->lastts = profile->times->answered; /* Set the initial answer time to match when the call was really answered */
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Beginning new billing on %s\n", uuid);
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Last successful billing time was %s\n", date);
@@ -335,13 +337,13 @@
if ((ts - nibble_data->lastts) > 0) {
- // Convert billrate into microseconds and multiply by # of microseconds that have passed
+ /* Convert billrate into microseconds and multiply by # of microseconds that have passed */
billamount = (atof(billrate) / 1000000 / 60) * ((ts - nibble_data->lastts));
- // if ODBC call fails, we should return BEFORE updating the timestamp of last success!
+ /* if ODBC call fails, we should return BEFORE updating the timestamp of last success! */
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Billing $%f to %s (Call: %s / %f so far)\n", billamount, billaccount, uuid, nibble_data->total);
- // DO ODBC BILLING HERE!
+ /* DO ODBC BILLING HERE! */
#ifdef SWITCH_HAVE_ODBC
char sql[1024] = "";
nibblebill_results_t pdata;
@@ -357,66 +359,65 @@
if (!(switch_odbc_handle_callback_exec(globals.master_odbc, sql, nibblebill_callback, &pdata) == SWITCH_ODBC_SUCCESS)){
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "DB Error while updating cash!\n");
- // TODO: If this is a hangup event, we should store this billing in a text file while the DB is unavailable
+ /* TODO: If this is a hangup event, we should store this billing in a text file while the DB is unavailable */
}
#endif
- // Increment total cost
+ /* Increment total cost */
nibble_data->total += billamount;
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Just tried to bill %s negative minutes! wtf?\n", uuid);
}
- // Update the last time we billed
+ /* Update the last time we billed */
nibble_data->lastts = ts;
- // Save everything back
+ /* Save everything back */
switch_channel_set_private(channel, "_nibble_data_", nibble_data);
- // Release the session lock
+ /* Release the session lock */
switch_core_session_rwunlock(session);
- // Done changing - release lock
+ /* Done changing - release lock */
if (globals.mutex) {
switch_mutex_unlock(globals.mutex);
}
-
return SWITCH_STATUS_SUCCESS;
}
-
/* You can turn on session heartbeat on a channel to have us check billing more often */
-static void event_handler(switch_event_t *event) {
+static void event_handler(switch_event_t *event)
+{
if (!event){
- // WTF? We should never get here - it means an event came in without the event info
+ /* WTF? We should never get here - it means an event came in without the event info */
return;
}
- // FS vars we'll need
+ /* FS vars we'll need */
switch_core_session_t *session;
char *uuid = switch_event_get_header(event, "Unique-ID");
- // Make sure everything is sane
+ /* Make sure everything is sane */
if (!uuid){
- // Donde esta channel?
+ /* Donde esta channel? */
return;
}
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Received request via %s!\n", switch_event_name (event->event_id));
- // Display debugging info
+ /* Display debugging info */
if (switch_event_get_header(event, "nibble_debug")) {
debug_event_handler(event);
}
- // Get session var
+ /* Get session var */
session = switch_core_session_locate(uuid);
if (!session) {
return;
}
- // Go bill
+ /* Go bill */
do_billing(session);
switch_core_session_rwunlock(session);
@@ -447,28 +448,28 @@
{
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "We made it!\n");
-// Check if session has variable "billrate" set. If it does, activate the heartbeat variable
-// switch_core_session_enable_heartbeat(switch_core_session_t *session, uint32_t seconds)
-// switch_core_session_sched_heartbeat(switch_core_session_t *session, uint32_t seconds)
+/* Check if session has variable "billrate" set. If it does, activate the heartbeat variable
+ switch_core_session_enable_heartbeat(switch_core_session_t *session, uint32_t seconds)
+ switch_core_session_sched_heartbeat(switch_core_session_t *session, uint32_t seconds)*/
return SWITCH_STATUS_SUCCESS;
}
-switch_state_handler_table_t nibble_state_handler = {
+switch_state_handler_table_t nibble_state_handler =
+{
/* on_init */ NULL,
- /* on_routing */ NULL, // Need to add a check here for anything in their account before routing
- /* on_execute */ sched_billing, // Turn on heartbeat for this session
- /* on_hangup */ do_billing, // On hangup - most important place to go bill
- /* on_exch_media */ NULL, // Run billing upon a call being established
+ /* on_routing */ NULL, /* Need to add a check here for anything in their account before routing */
+ /* on_execute */ sched_billing, /* Turn on heartbeat for this session */
+ /* on_hangup */ do_billing, /* On hangup - most important place to go bill */
+ /* on_exch_media */ NULL,
/* on_soft_exec */ NULL,
/* on_consume_med */ NULL,
/* on_hibernate */ NULL,
- /* on_reset */ do_billing // In case the switch is reset, we still want to log billing
+ /* on_reset */ NULL
};
-
SWITCH_MODULE_LOAD_FUNCTION(mod_nibblebill_load)
{
switch_api_interface_t *api_interface;
1
0
15 Jan '09
Author: mrene
Date: Wed Jan 14 21:53:09 2009
New Revision: 11213
Log:
Make max argument optional, acting as a counter only. Also set limit_usage and limit_rate channel variables upon limit_hash call.
Modified:
freeswitch/trunk/src/mod/applications/mod_limit/mod_limit.c
Modified: freeswitch/trunk/src/mod/applications/mod_limit/mod_limit.c
==============================================================================
--- freeswitch/trunk/src/mod/applications/mod_limit/mod_limit.c (original)
+++ freeswitch/trunk/src/mod/applications/mod_limit/mod_limit.c Wed Jan 14 21:53:09 2009
@@ -795,7 +795,7 @@
return SWITCH_STATUS_SUCCESS;
}
-#define LIMITHASH_USAGE "<realm> <id> <max>[/interval] [number [dialplan [context]]]"
+#define LIMITHASH_USAGE "<realm> <id> [<max>[/interval]] [number [dialplan [context]]]"
#define LIMITHASH_DESC "limit access to a resource and transfer to an extension if the limit is exceeded"
SWITCH_STANDARD_APP(limit_hash_function)
{
@@ -829,23 +829,27 @@
realm = argv[0];
id = argv[1];
- if ((szinterval = strchr(argv[2], '/')))
- {
- *szinterval++ = '\0';
- interval = atoi(szinterval);
- }
- max = atoi(argv[2]);
+ /* If max is omitted, only act as a counter and skip maximum checks */
+ if (argc > 2) {
+ if ((szinterval = strchr(argv[2], '/')))
+ {
+ *szinterval++ = '\0';
+ interval = atoi(szinterval);
+ }
+
+ max = atoi(argv[2]);
+
+ if (max < 0) {
+ max = 0;
+ }
+ }
- if (argc >= 4) {
+ if (argc > 3) {
xfer_exten = argv[3];
} else {
xfer_exten = limit_def_xfer_exten;
}
-
- if (max < 0) {
- max = 0;
- }
hashkey = switch_core_session_sprintf(session, "%s_%s", realm, id);
@@ -865,7 +869,7 @@
If we didnt, allow incrementing the counter.
If we did, dont touch it but do the validation anyways
*/
- increment = !!!switch_core_hash_find(channel_hash, hashkey);
+ increment = !switch_core_hash_find(channel_hash, hashkey);
} else {
/* This is the first limit check on this channel, create a hashtable, set our prviate data and add a state handler */
new_channel = 1;
@@ -879,13 +883,13 @@
/* Always increment rate when its checked as it doesnt depend on the channel */
item->rate_usage++;
- if (item->rate_usage > (uint32_t)max) {
+ if ((max >= 0) && (item->rate_usage > (uint32_t)max)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Usage for %s exceeds maximum rate of %d/%ds, now at %d\n", hashkey, max, interval, item->rate_usage);
switch_ivr_session_transfer(session, xfer_exten, argv[4], argv[5]);
goto end;
}
}
- } else if (item->total_usage + increment > (uint32_t)max) {
+ } else if ((max >= 0) && (item->total_usage + increment > (uint32_t)max)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Usage for %s is already at max value (%d)\n", hashkey, item->total_usage);
switch_ivr_session_transfer(session, xfer_exten, argv[4], argv[5]);
goto end;
@@ -898,14 +902,19 @@
switch_core_hash_insert(channel_hash, hashkey, item);
}
- if (interval == 0) {
+ if (max == -1) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Usage for %s is now %d\n", hashkey, item->total_usage);
+ } else if (interval == 0) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Usage for %s is now %d/%d\n", hashkey, item->total_usage, max);
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Usage for %s is now %d/%d for the last %d seconds\n", hashkey, item->rate_usage, max, interval);
}
}
-
+ /* Save current usage & rate into channel variables so it can be used later in the dialplan, or added to CDR records */
+ switch_channel_set_variable(channel, "limit_usage", switch_core_session_sprintf(session, "%d", item->total_usage));
+ switch_channel_set_variable(channel, "limit_rate", switch_core_session_sprintf(session, "%d", item->rate_usage));
+
if (new_channel) {
switch_core_hash_init(&channel_hash, switch_core_session_get_pool(session));
switch_core_hash_insert(channel_hash, hashkey, item);
1
0
Author: brian
Date: Wed Jan 14 21:46:46 2009
New Revision: 11212
Log:
lets set hold music to silence in this case it has special meaning ... it means SILENCE
Modified:
freeswitch/trunk/conf/dialplan/default.xml
Modified: freeswitch/trunk/conf/dialplan/default.xml
==============================================================================
--- freeswitch/trunk/conf/dialplan/default.xml (original)
+++ freeswitch/trunk/conf/dialplan/default.xml Wed Jan 14 21:46:46 2009
@@ -311,6 +311,7 @@
<!-- dial the freeswitch conference via SIP-->
<extension name="freeswitch_public_conf_via_sip">
<condition field="destination_number" expression="^9(888|1616|3232)$">
+ <action application="export" data="hold_music=silence"/>
<action application="bridge" data="sofia/${use_profile}/$1(a)conference.freeswitch.org"/>
</condition>
</extension>
1
0
15 Jan '09
Author: brian
Date: Wed Jan 14 21:42:45 2009
New Revision: 11211
Log:
Adding the ability to pass the var_name to store the results in.
Modified:
freeswitch/trunk/src/include/switch_cpp.h
freeswitch/trunk/src/include/switch_ivr.h
freeswitch/trunk/src/mod/applications/mod_dptools/mod_dptools.c
freeswitch/trunk/src/mod/languages/mod_java/src/org/freeswitch/swig/CoreSession.java
freeswitch/trunk/src/mod/languages/mod_java/src/org/freeswitch/swig/freeswitchJNI.java
freeswitch/trunk/src/mod/languages/mod_java/switch_swig_wrap.cpp
freeswitch/trunk/src/mod/languages/mod_lua/mod_lua_wrap.cpp
freeswitch/trunk/src/mod/languages/mod_managed/freeswitch_wrap.cxx
freeswitch/trunk/src/mod/languages/mod_managed/managed/swig.cs
freeswitch/trunk/src/mod/languages/mod_perl/mod_perl_wrap.cpp
freeswitch/trunk/src/mod/languages/mod_python/mod_python_wrap.cpp
freeswitch/trunk/src/switch_cpp.cpp
freeswitch/trunk/src/switch_ivr_play_say.c
Modified: freeswitch/trunk/src/include/switch_cpp.h
==============================================================================
--- freeswitch/trunk/src/include/switch_cpp.h (original)
+++ freeswitch/trunk/src/include/switch_cpp.h Wed Jan 14 21:42:45 2009
@@ -302,7 +302,8 @@
SWITCH_DECLARE(char *) playAndGetDigits(int min_digits,
int max_digits,
int max_tries,
- int timeout, char *terminators, char *audio_files, char *bad_input_audio_files, char *digits_regex);
+ int timeout, char *terminators, char *audio_files, char *bad_input_audio_files,
+ char *var_name, char *digits_regex);
/** \brief Play a file that resides on disk into the channel
*
Modified: freeswitch/trunk/src/include/switch_ivr.h
==============================================================================
--- freeswitch/trunk/src/include/switch_ivr.h (original)
+++ freeswitch/trunk/src/include/switch_ivr.h Wed Jan 14 21:42:45 2009
@@ -343,6 +343,7 @@
\param valid_terminators for input that can include # or * (useful for variable length prompts)
\param audio_file file to play
\param bad_input_audio_file file to play if the input from the user was invalid
+ \param var_name variable name to put results in
\param digit_buffer variable digits captured will be put back into (empty if capture failed)
\param digit_buffer_length length of the buffer for digits (should be the same or larger than max_digits)
\param digits_regex the qualifying regex
@@ -356,7 +357,8 @@
uint32_t timeout,
const char *valid_terminators,
const char *audio_file,
- const char *bad_input_audio_file, char *digit_buffer, uint32_t digit_buffer_length,
+ const char *bad_input_audio_file,
+ const char *var_name, char *digit_buffer, uint32_t digit_buffer_length,
const char *digits_regex);
SWITCH_DECLARE(switch_status_t) switch_ivr_speak_text_handle(switch_core_session_t *session,
Modified: freeswitch/trunk/src/mod/applications/mod_dptools/mod_dptools.c
==============================================================================
--- freeswitch/trunk/src/mod/applications/mod_dptools/mod_dptools.c (original)
+++ freeswitch/trunk/src/mod/applications/mod_dptools/mod_dptools.c Wed Jan 14 21:42:45 2009
@@ -1616,7 +1616,7 @@
SWITCH_STANDARD_APP(play_and_get_digits_function)
{
char *mydata;
- char *argv[8] = { 0 };
+ char *argv[9] = { 0 };
int argc;
int32_t min_digits = 0;
int32_t max_digits = 0;
@@ -1625,6 +1625,7 @@
char digit_buffer[128] = "";
const char *prompt_audio_file = NULL;
const char *bad_input_audio_file = NULL;
+ const char *var_name = NULL;
const char *valid_terminators = NULL;
const char *digits_regex = NULL;
@@ -1662,7 +1663,23 @@
}
if (argc > 7) {
- digits_regex = argv[7];
+ var_name = argv[7];
+ }
+
+ if (argc > 8) {
+ digits_regex = argv[8];
+ }
+
+ if (min_digits <= 1) {
+ min_digits = 1;
+ }
+
+ if (max_digits < min_digits) {
+ max_digits = min_digits;
+ }
+
+ if (timeout <= 1000) {
+ timeout = 1000;
}
if (switch_strlen_zero(valid_terminators)) {
@@ -1670,7 +1687,7 @@
}
switch_play_and_get_digits(session, min_digits, max_digits, max_tries, timeout, valid_terminators,
- prompt_audio_file, bad_input_audio_file, digit_buffer, sizeof(digit_buffer), digits_regex);
+ prompt_audio_file, bad_input_audio_file, var_name, digit_buffer, sizeof(digit_buffer), digits_regex);
}
#define SAY_SYNTAX "<module_name> <say_type> <say_method> <text>"
@@ -2611,9 +2628,9 @@
SWITCH_ADD_APP(app_interface, "gentones", "Generate Tones", "Generate tones to the channel", gentones_function, "<tgml_script>[|<loops>]", SAF_NONE);
SWITCH_ADD_APP(app_interface, "playback", "Playback File", "Playback a file to the channel", playback_function, "<path>", SAF_NONE);
SWITCH_ADD_APP(app_interface, "att_xfer", "Attended Transfer", "Attended Transfer", att_xfer_function, "<channel_url>", SAF_NONE);
- SWITCH_ADD_APP(app_interface, "read", "Read Digits", "Read Digits", read_function, "<min> <max> <file> <var name> <timeout> <terminators>", SAF_NONE);
+ SWITCH_ADD_APP(app_interface, "read", "Read Digits", "Read Digits", read_function, "<min> <max> <file> <var_name> <timeout> <terminators>", SAF_NONE);
SWITCH_ADD_APP(app_interface, "play_and_get_digits", "Play and get Digits", "Play and get Digits",
- play_and_get_digits_function, "<min> <max> <tries> <timeout> <terminators> <file> <invalid_file> <regexp>", SAF_NONE);
+ play_and_get_digits_function, "<min> <max> <tries> <timeout> <terminators> <file> <invalid_file> <var_name> <regexp>", SAF_NONE);
SWITCH_ADD_APP(app_interface, "stop_record_session", "Stop Record Session", STOP_SESS_REC_DESC, stop_record_session_function, "<path>", SAF_NONE);
SWITCH_ADD_APP(app_interface, "record_session", "Record Session", SESS_REC_DESC, record_session_function, "<path> [+<timeout>]", SAF_NONE);
SWITCH_ADD_APP(app_interface, "record", "Record File", "Record a file from the channels input", record_function,
Modified: freeswitch/trunk/src/mod/languages/mod_java/src/org/freeswitch/swig/CoreSession.java
==============================================================================
--- freeswitch/trunk/src/mod/languages/mod_java/src/org/freeswitch/swig/CoreSession.java (original)
+++ freeswitch/trunk/src/mod/languages/mod_java/src/org/freeswitch/swig/CoreSession.java Wed Jan 14 21:42:45 2009
@@ -233,8 +233,8 @@
return freeswitchJNI.CoreSession_read(swigCPtr, this, min_digits, max_digits, prompt_audio_file, timeout, valid_terminators);
}
- public String playAndGetDigits(int min_digits, int max_digits, int max_tries, int timeout, String terminators, String audio_files, String bad_input_audio_files, String digits_regex) {
- return freeswitchJNI.CoreSession_playAndGetDigits(swigCPtr, this, min_digits, max_digits, max_tries, timeout, terminators, audio_files, bad_input_audio_files, digits_regex);
+ public String playAndGetDigits(int min_digits, int max_digits, int max_tries, int timeout, String terminators, String audio_files, String bad_input_audio_files, String var_name, String digits_regex) {
+ return freeswitchJNI.CoreSession_playAndGetDigits(swigCPtr, this, min_digits, max_digits, max_tries, timeout, terminators, audio_files, bad_input_audio_files, var_name, digits_regex);
}
public int streamFile(String file, int starting_sample_count) {
Modified: freeswitch/trunk/src/mod/languages/mod_java/src/org/freeswitch/swig/freeswitchJNI.java
==============================================================================
--- freeswitch/trunk/src/mod/languages/mod_java/src/org/freeswitch/swig/freeswitchJNI.java (original)
+++ freeswitch/trunk/src/mod/languages/mod_java/src/org/freeswitch/swig/freeswitchJNI.java Wed Jan 14 21:42:45 2009
@@ -133,7 +133,7 @@
public final static native int CoreSession_transfer__SWIG_1(long jarg1, CoreSession jarg1_, String jarg2, String jarg3);
public final static native int CoreSession_transfer__SWIG_2(long jarg1, CoreSession jarg1_, String jarg2);
public final static native String CoreSession_read(long jarg1, CoreSession jarg1_, int jarg2, int jarg3, String jarg4, int jarg5, String jarg6);
- public final static native String CoreSession_playAndGetDigits(long jarg1, CoreSession jarg1_, int jarg2, int jarg3, int jarg4, int jarg5, String jarg6, String jarg7, String jarg8, String jarg9);
+ public final static native String CoreSession_playAndGetDigits(long jarg1, CoreSession jarg1_, int jarg2, int jarg3, int jarg4, int jarg5, String jarg6, String jarg7, String jarg8, String jarg9, String jarg10);
public final static native int CoreSession_streamFile__SWIG_0(long jarg1, CoreSession jarg1_, String jarg2, int jarg3);
public final static native int CoreSession_streamFile__SWIG_1(long jarg1, CoreSession jarg1_, String jarg2);
public final static native int CoreSession_sleep__SWIG_0(long jarg1, CoreSession jarg1_, int jarg2, int jarg3);
Modified: freeswitch/trunk/src/mod/languages/mod_java/switch_swig_wrap.cpp
==============================================================================
--- freeswitch/trunk/src/mod/languages/mod_java/switch_swig_wrap.cpp (original)
+++ freeswitch/trunk/src/mod/languages/mod_java/switch_swig_wrap.cpp Wed Jan 14 21:42:45 2009
@@ -2577,7 +2577,7 @@
}
-SWIGEXPORT jstring JNICALL Java_org_freeswitch_swig_freeswitchJNI_CoreSession_1playAndGetDigits(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_, jint jarg2, jint jarg3, jint jarg4, jint jarg5, jstring jarg6, jstring jarg7, jstring jarg8, jstring jarg9) {
+SWIGEXPORT jstring JNICALL Java_org_freeswitch_swig_freeswitchJNI_CoreSession_1playAndGetDigits(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_, jint jarg2, jint jarg3, jint jarg4, jint jarg5, jstring jarg6, jstring jarg7, jstring jarg8, jstring jarg9, jstring jarg10) {
jstring jresult = 0 ;
CoreSession *arg1 = (CoreSession *) 0 ;
int arg2 ;
@@ -2588,6 +2588,7 @@
char *arg7 = (char *) 0 ;
char *arg8 = (char *) 0 ;
char *arg9 = (char *) 0 ;
+ char *arg10 = (char *) 0 ;
char *result = 0 ;
(void)jenv;
@@ -2618,12 +2619,18 @@
arg9 = (char *)jenv->GetStringUTFChars(jarg9, 0);
if (!arg9) return 0;
}
- result = (char *)(arg1)->playAndGetDigits(arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9);
+ arg10 = 0;
+ if (jarg10) {
+ arg10 = (char *)jenv->GetStringUTFChars(jarg10, 0);
+ if (!arg10) return 0;
+ }
+ result = (char *)(arg1)->playAndGetDigits(arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9,arg10);
if(result) jresult = jenv->NewStringUTF((const char *)result);
if (arg6) jenv->ReleaseStringUTFChars(jarg6, (const char *)arg6);
if (arg7) jenv->ReleaseStringUTFChars(jarg7, (const char *)arg7);
if (arg8) jenv->ReleaseStringUTFChars(jarg8, (const char *)arg8);
if (arg9) jenv->ReleaseStringUTFChars(jarg9, (const char *)arg9);
+ if (arg10) jenv->ReleaseStringUTFChars(jarg10, (const char *)arg10);
return jresult;
}
Modified: freeswitch/trunk/src/mod/languages/mod_lua/mod_lua_wrap.cpp
==============================================================================
--- freeswitch/trunk/src/mod/languages/mod_lua/mod_lua_wrap.cpp (original)
+++ freeswitch/trunk/src/mod/languages/mod_lua/mod_lua_wrap.cpp Wed Jan 14 21:42:45 2009
@@ -5924,9 +5924,10 @@
char *arg7 = (char *) 0 ;
char *arg8 = (char *) 0 ;
char *arg9 = (char *) 0 ;
+ char *arg10 = (char *) 0 ;
char *result = 0 ;
- SWIG_check_num_args("playAndGetDigits",9,9)
+ SWIG_check_num_args("playAndGetDigits",10,10)
if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("playAndGetDigits",1,"CoreSession *");
if(!lua_isnumber(L,2)) SWIG_fail_arg("playAndGetDigits",2,"int");
if(!lua_isnumber(L,3)) SWIG_fail_arg("playAndGetDigits",3,"int");
@@ -5936,6 +5937,7 @@
if(!lua_isstring(L,7)) SWIG_fail_arg("playAndGetDigits",7,"char *");
if(!lua_isstring(L,8)) SWIG_fail_arg("playAndGetDigits",8,"char *");
if(!lua_isstring(L,9)) SWIG_fail_arg("playAndGetDigits",9,"char *");
+ if(!lua_isstring(L,10)) SWIG_fail_arg("playAndGetDigits",10,"char *");
if (!SWIG_IsOK(SWIG_ConvertPtr(L,1,(void**)&arg1,SWIGTYPE_p_CoreSession,0))){
SWIG_fail_ptr("CoreSession_playAndGetDigits",1,SWIGTYPE_p_CoreSession);
@@ -5949,7 +5951,8 @@
arg7 = (char *)lua_tostring(L, 7);
arg8 = (char *)lua_tostring(L, 8);
arg9 = (char *)lua_tostring(L, 9);
- result = (char *)(arg1)->playAndGetDigits(arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9);
+ arg10 = (char *)lua_tostring(L, 10);
+ result = (char *)(arg1)->playAndGetDigits(arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9,arg10);
SWIG_arg=0;
lua_pushstring(L,(const char*)result); SWIG_arg++;
return SWIG_arg;
Modified: freeswitch/trunk/src/mod/languages/mod_managed/freeswitch_wrap.cxx
==============================================================================
--- freeswitch/trunk/src/mod/languages/mod_managed/freeswitch_wrap.cxx (original)
+++ freeswitch/trunk/src/mod/languages/mod_managed/freeswitch_wrap.cxx Wed Jan 14 21:42:45 2009
@@ -21051,7 +21051,7 @@
}
-SWIGEXPORT int SWIGSTDCALL CSharp_switch_play_and_get_digits(void * jarg1, unsigned long jarg2, unsigned long jarg3, unsigned long jarg4, unsigned long jarg5, char * jarg6, char * jarg7, char * jarg8, char * jarg9, unsigned long jarg10, char * jarg11) {
+SWIGEXPORT int SWIGSTDCALL CSharp_switch_play_and_get_digits(void * jarg1, unsigned long jarg2, unsigned long jarg3, unsigned long jarg4, unsigned long jarg5, char * jarg6, char * jarg7, char * jarg8, char * jarg9, char * jarg10, unsigned long jarg11, char * jarg12) {
int jresult ;
switch_core_session_t *arg1 = (switch_core_session_t *) 0 ;
uint32_t arg2 ;
@@ -21062,8 +21062,9 @@
char *arg7 = (char *) 0 ;
char *arg8 = (char *) 0 ;
char *arg9 = (char *) 0 ;
- uint32_t arg10 ;
- char *arg11 = (char *) 0 ;
+ char *arg10 = (char *) 0 ;
+ uint32_t arg11 ;
+ char *arg12 = (char *) 0 ;
switch_status_t result;
arg1 = (switch_core_session_t *)jarg1;
@@ -21075,9 +21076,10 @@
arg7 = (char *)jarg7;
arg8 = (char *)jarg8;
arg9 = (char *)jarg9;
- arg10 = (uint32_t)jarg10;
- arg11 = (char *)jarg11;
- result = (switch_status_t)switch_play_and_get_digits(arg1,arg2,arg3,arg4,arg5,(char const *)arg6,(char const *)arg7,(char const *)arg8,arg9,arg10,(char const *)arg11);
+ arg10 = (char *)jarg10;
+ arg11 = (uint32_t)jarg11;
+ arg12 = (char *)jarg12;
+ result = (switch_status_t)switch_play_and_get_digits(arg1,arg2,arg3,arg4,arg5,(char const *)arg6,(char const *)arg7,(char const *)arg8,(char const *)arg9,arg10,arg11,(char const *)arg12);
jresult = result;
return jresult;
}
@@ -27355,7 +27357,7 @@
}
-SWIGEXPORT char * SWIGSTDCALL CSharp_CoreSession_PlayAndGetDigits(void * jarg1, int jarg2, int jarg3, int jarg4, int jarg5, char * jarg6, char * jarg7, char * jarg8, char * jarg9) {
+SWIGEXPORT char * SWIGSTDCALL CSharp_CoreSession_PlayAndGetDigits(void * jarg1, int jarg2, int jarg3, int jarg4, int jarg5, char * jarg6, char * jarg7, char * jarg8, char * jarg9, char * jarg10) {
char * jresult ;
CoreSession *arg1 = (CoreSession *) 0 ;
int arg2 ;
@@ -27366,6 +27368,7 @@
char *arg7 = (char *) 0 ;
char *arg8 = (char *) 0 ;
char *arg9 = (char *) 0 ;
+ char *arg10 = (char *) 0 ;
char *result = 0 ;
arg1 = (CoreSession *)jarg1;
@@ -27377,7 +27380,8 @@
arg7 = (char *)jarg7;
arg8 = (char *)jarg8;
arg9 = (char *)jarg9;
- result = (char *)(arg1)->playAndGetDigits(arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9);
+ arg10 = (char *)jarg10;
+ result = (char *)(arg1)->playAndGetDigits(arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9,arg10);
jresult = SWIG_csharp_string_callback((const char *)result);
return jresult;
}
Modified: freeswitch/trunk/src/mod/languages/mod_managed/managed/swig.cs
==============================================================================
--- freeswitch/trunk/src/mod/languages/mod_managed/managed/swig.cs (original)
+++ freeswitch/trunk/src/mod/languages/mod_managed/managed/swig.cs Wed Jan 14 21:42:45 2009
@@ -282,8 +282,8 @@
return ret;
}
- public string PlayAndGetDigits(int min_digits, int max_digits, int max_tries, int timeout, string terminators, string audio_files, string bad_input_audio_files, string digits_regex) {
- string ret = freeswitchPINVOKE.CoreSession_PlayAndGetDigits(swigCPtr, min_digits, max_digits, max_tries, timeout, terminators, audio_files, bad_input_audio_files, digits_regex);
+ public string PlayAndGetDigits(int min_digits, int max_digits, int max_tries, int timeout, string terminators, string audio_files, string bad_input_audio_files, string var_name, string digits_regex) {
+ string ret = freeswitchPINVOKE.CoreSession_PlayAndGetDigits(swigCPtr, min_digits, max_digits, max_tries, timeout, terminators, audio_files, bad_input_audio_files, var_name, digits_regex);
return ret;
}
@@ -3054,8 +3054,8 @@
return ret;
}
- public static switch_status_t switch_play_and_get_digits(SWIGTYPE_p_switch_core_session session, uint min_digits, uint max_digits, uint max_tries, uint timeout, string valid_terminators, string audio_file, string bad_input_audio_file, string digit_buffer, uint digit_buffer_length, string digits_regex) {
- switch_status_t ret = (switch_status_t)freeswitchPINVOKE.switch_play_and_get_digits(SWIGTYPE_p_switch_core_session.getCPtr(session), min_digits, max_digits, max_tries, timeout, valid_terminators, audio_file, bad_input_audio_file, digit_buffer, digit_buffer_length, digits_regex);
+ public static switch_status_t switch_play_and_get_digits(SWIGTYPE_p_switch_core_session session, uint min_digits, uint max_digits, uint max_tries, uint timeout, string valid_terminators, string audio_file, string bad_input_audio_file, string var_name, string digit_buffer, uint digit_buffer_length, string digits_regex) {
+ switch_status_t ret = (switch_status_t)freeswitchPINVOKE.switch_play_and_get_digits(SWIGTYPE_p_switch_core_session.getCPtr(session), min_digits, max_digits, max_tries, timeout, valid_terminators, audio_file, bad_input_audio_file, var_name, digit_buffer, digit_buffer_length, digits_regex);
return ret;
}
@@ -9342,7 +9342,7 @@
public static extern int switch_ivr_record_file(HandleRef jarg1, HandleRef jarg2, string jarg3, HandleRef jarg4, uint jarg5);
[DllImport("mod_managed", EntryPoint="CSharp_switch_play_and_get_digits")]
- public static extern int switch_play_and_get_digits(HandleRef jarg1, uint jarg2, uint jarg3, uint jarg4, uint jarg5, string jarg6, string jarg7, string jarg8, string jarg9, uint jarg10, string jarg11);
+ public static extern int switch_play_and_get_digits(HandleRef jarg1, uint jarg2, uint jarg3, uint jarg4, uint jarg5, string jarg6, string jarg7, string jarg8, string jarg9, string jarg10, uint jarg11, string jarg12);
[DllImport("mod_managed", EntryPoint="CSharp_switch_ivr_speak_text_handle")]
public static extern int switch_ivr_speak_text_handle(HandleRef jarg1, HandleRef jarg2, HandleRef jarg3, HandleRef jarg4, string jarg5, HandleRef jarg6);
@@ -10782,7 +10782,7 @@
public static extern string CoreSession_read(HandleRef jarg1, int jarg2, int jarg3, string jarg4, int jarg5, string jarg6);
[DllImport("mod_managed", EntryPoint="CSharp_CoreSession_PlayAndGetDigits")]
- public static extern string CoreSession_PlayAndGetDigits(HandleRef jarg1, int jarg2, int jarg3, int jarg4, int jarg5, string jarg6, string jarg7, string jarg8, string jarg9);
+ public static extern string CoreSession_PlayAndGetDigits(HandleRef jarg1, int jarg2, int jarg3, int jarg4, int jarg5, string jarg6, string jarg7, string jarg8, string jarg9, string jarg10);
[DllImport("mod_managed", EntryPoint="CSharp_CoreSession_StreamFile")]
public static extern int CoreSession_StreamFile(HandleRef jarg1, string jarg2, int jarg3);
Modified: freeswitch/trunk/src/mod/languages/mod_perl/mod_perl_wrap.cpp
==============================================================================
--- freeswitch/trunk/src/mod/languages/mod_perl/mod_perl_wrap.cpp (original)
+++ freeswitch/trunk/src/mod/languages/mod_perl/mod_perl_wrap.cpp Wed Jan 14 21:42:45 2009
@@ -7869,6 +7869,7 @@
char *arg7 = (char *) 0 ;
char *arg8 = (char *) 0 ;
char *arg9 = (char *) 0 ;
+ char *arg10 = (char *) 0 ;
char *result = 0 ;
void *argp1 = 0 ;
int res1 = 0 ;
@@ -7892,11 +7893,14 @@
int res9 ;
char *buf9 = 0 ;
int alloc9 = 0 ;
+ int res10 ;
+ char *buf10 = 0 ;
+ int alloc10 = 0 ;
int argvi = 0;
dXSARGS;
- if ((items < 9) || (items > 9)) {
- SWIG_croak("Usage: CoreSession_playAndGetDigits(self,min_digits,max_digits,max_tries,timeout,terminators,audio_files,bad_input_audio_files,digits_regex);");
+ if ((items < 10) || (items > 10)) {
+ SWIG_croak("Usage: CoreSession_playAndGetDigits(self,min_digits,max_digits,max_tries,timeout,terminators,audio_files,bad_input_audio_files,var_name,digits_regex);");
}
res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_CoreSession, 0 | 0 );
if (!SWIG_IsOK(res1)) {
@@ -7943,7 +7947,12 @@
SWIG_exception_fail(SWIG_ArgError(res9), "in method '" "CoreSession_playAndGetDigits" "', argument " "9"" of type '" "char *""'");
}
arg9 = reinterpret_cast< char * >(buf9);
- result = (char *)(arg1)->playAndGetDigits(arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9);
+ res10 = SWIG_AsCharPtrAndSize(ST(9), &buf10, NULL, &alloc10);
+ if (!SWIG_IsOK(res10)) {
+ SWIG_exception_fail(SWIG_ArgError(res10), "in method '" "CoreSession_playAndGetDigits" "', argument " "10"" of type '" "char *""'");
+ }
+ arg10 = reinterpret_cast< char * >(buf10);
+ result = (char *)(arg1)->playAndGetDigits(arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9,arg10);
ST(argvi) = SWIG_FromCharPtr((const char *)result); argvi++ ;
@@ -7954,6 +7963,7 @@
if (alloc7 == SWIG_NEWOBJ) delete[] buf7;
if (alloc8 == SWIG_NEWOBJ) delete[] buf8;
if (alloc9 == SWIG_NEWOBJ) delete[] buf9;
+ if (alloc10 == SWIG_NEWOBJ) delete[] buf10;
XSRETURN(argvi);
fail:
@@ -7965,6 +7975,7 @@
if (alloc7 == SWIG_NEWOBJ) delete[] buf7;
if (alloc8 == SWIG_NEWOBJ) delete[] buf8;
if (alloc9 == SWIG_NEWOBJ) delete[] buf9;
+ if (alloc10 == SWIG_NEWOBJ) delete[] buf10;
SWIG_croak_null();
}
}
Modified: freeswitch/trunk/src/mod/languages/mod_python/mod_python_wrap.cpp
==============================================================================
--- freeswitch/trunk/src/mod/languages/mod_python/mod_python_wrap.cpp (original)
+++ freeswitch/trunk/src/mod/languages/mod_python/mod_python_wrap.cpp Wed Jan 14 21:42:45 2009
@@ -7794,6 +7794,7 @@
char *arg7 = (char *) 0 ;
char *arg8 = (char *) 0 ;
char *arg9 = (char *) 0 ;
+ char *arg10 = (char *) 0 ;
char *result = 0 ;
void *argp1 = 0 ;
int res1 = 0 ;
@@ -7817,6 +7818,9 @@
int res9 ;
char *buf9 = 0 ;
int alloc9 = 0 ;
+ int res10 ;
+ char *buf10 = 0 ;
+ int alloc10 = 0 ;
PyObject * obj0 = 0 ;
PyObject * obj1 = 0 ;
PyObject * obj2 = 0 ;
@@ -7826,8 +7830,9 @@
PyObject * obj6 = 0 ;
PyObject * obj7 = 0 ;
PyObject * obj8 = 0 ;
+ PyObject * obj9 = 0 ;
- if (!PyArg_ParseTuple(args,(char *)"OOOOOOOOO:CoreSession_playAndGetDigits",&obj0,&obj1,&obj2,&obj3,&obj4,&obj5,&obj6,&obj7,&obj8)) SWIG_fail;
+ if (!PyArg_ParseTuple(args,(char *)"OOOOOOOOOO:CoreSession_playAndGetDigits",&obj0,&obj1,&obj2,&obj3,&obj4,&obj5,&obj6,&obj7,&obj8,&obj9)) SWIG_fail;
res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_CoreSession, 0 | 0 );
if (!SWIG_IsOK(res1)) {
SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "CoreSession_playAndGetDigits" "', argument " "1"" of type '" "CoreSession *""'");
@@ -7873,18 +7878,25 @@
SWIG_exception_fail(SWIG_ArgError(res9), "in method '" "CoreSession_playAndGetDigits" "', argument " "9"" of type '" "char *""'");
}
arg9 = reinterpret_cast< char * >(buf9);
- result = (char *)(arg1)->playAndGetDigits(arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9);
+ res10 = SWIG_AsCharPtrAndSize(obj9, &buf10, NULL, &alloc10);
+ if (!SWIG_IsOK(res10)) {
+ SWIG_exception_fail(SWIG_ArgError(res10), "in method '" "CoreSession_playAndGetDigits" "', argument " "10"" of type '" "char *""'");
+ }
+ arg10 = reinterpret_cast< char * >(buf10);
+ result = (char *)(arg1)->playAndGetDigits(arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9,arg10);
resultobj = SWIG_FromCharPtr((const char *)result);
if (alloc6 == SWIG_NEWOBJ) delete[] buf6;
if (alloc7 == SWIG_NEWOBJ) delete[] buf7;
if (alloc8 == SWIG_NEWOBJ) delete[] buf8;
if (alloc9 == SWIG_NEWOBJ) delete[] buf9;
+ if (alloc10 == SWIG_NEWOBJ) delete[] buf10;
return resultobj;
fail:
if (alloc6 == SWIG_NEWOBJ) delete[] buf6;
if (alloc7 == SWIG_NEWOBJ) delete[] buf7;
if (alloc8 == SWIG_NEWOBJ) delete[] buf8;
if (alloc9 == SWIG_NEWOBJ) delete[] buf9;
+ if (alloc10 == SWIG_NEWOBJ) delete[] buf10;
return NULL;
}
Modified: freeswitch/trunk/src/switch_cpp.cpp
==============================================================================
--- freeswitch/trunk/src/switch_cpp.cpp (original)
+++ freeswitch/trunk/src/switch_cpp.cpp Wed Jan 14 21:42:45 2009
@@ -748,7 +748,8 @@
int timeout,
char *terminators,
char *audio_files,
- char *bad_input_audio_files,
+ char *bad_input_audio_files,
+ char *var_name,
char *digits_regex)
{
switch_status_t status;
@@ -763,7 +764,8 @@
(uint32_t) timeout,
terminators,
audio_files,
- bad_input_audio_files,
+ bad_input_audio_files,
+ var_name,
dtmf_buf,
sizeof(dtmf_buf),
digits_regex);
Modified: freeswitch/trunk/src/switch_ivr_play_say.c
==============================================================================
--- freeswitch/trunk/src/switch_ivr_play_say.c (original)
+++ freeswitch/trunk/src/switch_ivr_play_say.c Wed Jan 14 21:42:45 2009
@@ -1503,6 +1503,7 @@
const char *valid_terminators,
const char *prompt_audio_file,
const char *bad_input_audio_file,
+ const char *var_name,
char *digit_buffer,
uint32_t digit_buffer_length,
const char *digits_regex)
@@ -1514,7 +1515,7 @@
memset(digit_buffer, 0, digit_buffer_length);
switch_channel_flush_dtmf(channel);
- status = switch_ivr_read(session, min_digits, max_digits, prompt_audio_file, NULL,
+ status = switch_ivr_read(session, min_digits, max_digits, prompt_audio_file, var_name,
digit_buffer, digit_buffer_length, timeout, valid_terminators);
if (status == SWITCH_STATUS_TIMEOUT && strlen(digit_buffer) >= min_digits) {
status = SWITCH_STATUS_SUCCESS;
1
0
[commit] r11210 - freeswitch/trunk/scripts/contrib/dschreiber/mod_nibblebill
by FreeSWITCH SVN 15 Jan '09
by FreeSWITCH SVN 15 Jan '09
15 Jan '09
Author: dschreiber
Date: Wed Jan 14 21:21:17 2009
New Revision: 11210
Log:
mod_nibblebill
This is a billing module created for FreeSWITCH. It's purpose is to allow real-time debiting of
credit or cash from a database while calls are in progress.
More info on the WIKI for mod_nibblebill
Added:
freeswitch/trunk/scripts/contrib/dschreiber/mod_nibblebill/
freeswitch/trunk/scripts/contrib/dschreiber/mod_nibblebill/mod_nibblebill.c
Added: freeswitch/trunk/scripts/contrib/dschreiber/mod_nibblebill/mod_nibblebill.c
==============================================================================
--- (empty file)
+++ freeswitch/trunk/scripts/contrib/dschreiber/mod_nibblebill/mod_nibblebill.c Wed Jan 14 21:21:17 2009
@@ -0,0 +1,520 @@
+/*
+ * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
+ * Copyright (C) 2005/2006, Anthony Minessale II <anthmct(a)yahoo.com>
+ *
+ * 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 <anthmct(a)yahoo.com>
+ *
+ * The Initial Developer of this module is
+ * Darren Schreiber <d(a)d-man.org>
+ *
+ * Portions created by the Initial Developer are Copyright (C)
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Darren Schreiber <d(a)d-man.org>
+ *
+ * mod_nibblebill.c - Nibble Billing
+ * Set the session heartbeat on a call that has a billrate and deduct currency from
+ * a database table each "tick" of the billing until funds are depleted.
+ * Terminate the call upon depletion.
+ *
+ *
+ * TODO: Create an override flag so you can force a start-time for when billing should count *from*
+ * TODO: Fix what happens when the DB is not available
+ * TODO: Fix what happens when the DB queries fail (right now, all are acting like success)
+ * TODO: Make the actions function for when funds are depleted
+ * TODO: Add app and CLI commands (pause, resume, reset, flush, deduct_funds, add_funds)
+ * TODO: Add buffering abilities
+ * TODO: Make error handling for database, such that when the database is down (or not installed) we just log to a text file
+ * TODO: Make a sample .XML config file!
+ * FUTURE: Possibly make the hooks not tied per-channel, and instead just do this as a supervision style application with one thread that watches all calls
+ */
+
+#include <switch.h>
+
+#ifdef SWITCH_HAVE_ODBC
+#include <switch_odbc.h>
+#endif
+
+// Defaults
+//static char SQL_LOOKUP[] = "SELECT cash FROM accounts WHERE id=\"%s\"";
+static char SQL_SAVE[] = "UPDATE accounts SET cash=cash-%f WHERE id=\"%s\"";
+
+typedef struct {
+ switch_time_t lastts; // Last time we did any billing
+ float total; // Total amount billed so far
+} nibble_data_t;
+
+
+typedef struct nibblebill_results{
+ float funds;
+
+ float percall_max; // Overrides global on a per-user level
+ float lowbal_amt; // ditto
+} nibblebill_results_t;
+
+
+/* Keep track of our config, event hooks and database connection variables, for this module only */
+static struct {
+ // Event hooks
+ switch_event_node_t *node;
+
+ // Global mutex (don't touch a session when it's already being touched)
+ switch_mutex_t *mutex;
+
+ // Global billing config options
+ float percall_max_amt; // Per-call billing limit (safety check, for fraud)
+ char *percall_action; // Exceeded length of per-call action
+ float lowbal_amt; // When we warn them they are near depletion
+ char *lowbal_action; // Low balance action
+ float nobal_amt; // Minimum amount that must remain in the account
+ char *nobal_action; // Drop action
+
+ // Database settings
+ char *db_username;
+ char *db_password;
+ char *db_dsn;
+ char *lookup_query;
+ char *save_query;
+#ifdef SWITCH_HAVE_ODBC
+ switch_odbc_handle_t *master_odbc;
+#else
+ void *padding1; // Keep structures same size
+#endif
+} globals;
+
+/**************************
+* Setup FreeSWITCH Macros *
+**************************/
+/* Define the module's load function */
+SWITCH_MODULE_LOAD_FUNCTION(mod_nibblebill_load);
+
+/* Define the module's shutdown function */
+SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_nibblebill_shutdown);
+
+/* Define the module's name, load function, shutdown function and runtime function */
+SWITCH_MODULE_DEFINITION(mod_nibblebill, mod_nibblebill_load, mod_nibblebill_shutdown, NULL);
+
+/* String setting functions */
+SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_db_username, globals.db_username);
+SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_db_password, globals.db_password);
+SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_db_dsn, globals.db_dsn);
+SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_lookup_query, globals.lookup_query);
+SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_save_query, globals.save_query);
+SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_percall_action, globals.percall_action);
+SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_lowbal_action, globals.lowbal_action);
+SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_nobal_action, globals.nobal_action);
+
+
+
+static int nibblebill_callback(void *pArg, int argc, char **argv, char **columnNames)
+{
+ nibblebill_results_t *cbt = (nibblebill_results_t *) pArg;
+
+ cbt->funds = atof(argv[0]);
+
+ return 0;
+}
+
+
+
+static switch_status_t load_config(void)
+{
+ char *cf = "nibblebill.conf";
+ switch_xml_t cfg, xml = NULL, param, settings;
+ switch_status_t status = SWITCH_STATUS_SUCCESS;
+
+ if (!(xml = switch_xml_open_cfg(cf, &cfg, NULL))) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "open of %s failed\n", cf);
+ status = SWITCH_STATUS_SUCCESS; // We don't fail because we can still write to a text file or buffer
+ goto done;
+ }
+
+ if ((settings = switch_xml_child(cfg, "settings"))) {
+ for (param = switch_xml_child(settings, "param"); param; param = param->next) {
+ char *var = (char *) switch_xml_attr_soft(param, "name");
+ char *val = (char *) switch_xml_attr_soft(param, "value");
+ if (!strcasecmp(var, "db-username")) {
+ set_global_db_username(val);
+ } else if (!strcasecmp(var, "db-password")) {
+ set_global_db_password(val);
+ } else if (!strcasecmp(var, "db-dsn")) {
+ set_global_db_dsn(val);
+ } else if (!strcasecmp(var, "lookup_query")) {
+ set_global_lookup_query(val);
+ } else if (!strcasecmp(var, "save_query")) {
+ set_global_save_query(val);
+ } else if (!strcasecmp(var, "percall_action")) {
+ set_global_percall_action(val);
+ } else if (!strcasecmp(var, "lowbal_action")) {
+ set_global_lowbal_action(val);
+ } else if (!strcasecmp(var, "nobal_action")) {
+ set_global_nobal_action(val);
+ }
+ }
+ }
+
+done:
+ if (switch_strlen_zero(globals.db_username)) {
+ set_global_db_username("phonebooth");
+ }
+ if (switch_strlen_zero(globals.db_password)) {
+ set_global_db_password("dev");
+ }
+ if (switch_strlen_zero(globals.db_dsn)) {
+ set_global_db_dsn("phonebooth");
+ }
+ if (switch_strlen_zero(globals.percall_action)) {
+ set_global_percall_action("hangup");
+ }
+ if (switch_strlen_zero(globals.lowbal_action)) {
+ set_global_lowbal_action("play ding");
+ }
+ if (switch_strlen_zero(globals.nobal_action)) {
+ set_global_nobal_action("hangup");
+ }
+ // Need to add defaults for the integers!
+
+
+#ifdef SWITCH_HAVE_ODBC
+ if (globals.db_dsn) {
+ if (!(globals.master_odbc = switch_odbc_handle_new(globals.db_dsn, globals.db_username, globals.db_password))) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Cannot create handle to ODBC Database!\n");
+ status = SWITCH_STATUS_FALSE;
+ goto reallydone;
+ } else {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Opened ODBC Database handle!\n");
+ }
+ if (switch_odbc_handle_connect(globals.master_odbc) != SWITCH_ODBC_SUCCESS) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Cannot connect to ODBC driver/database %s (user: %s / pass %s)!\n", globals.db_dsn, globals.db_username, globals.db_password);
+ status = SWITCH_STATUS_FALSE;
+ goto reallydone;
+ } else {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Opened ODBC Database!\n");
+ }
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Connected ODBC DSN: %s\n", globals.db_dsn);
+ } else {
+#endif
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "ODBC does not appear to be installed in the core\n");
+#ifdef SWITCH_HAVE_ODBC
+ }
+#endif
+
+
+#ifdef SWITCH_HAVE_ODBC
+reallydone:
+#endif
+
+ if (xml) {
+ switch_xml_free(xml);
+ }
+ return status;
+}
+
+
+void debug_event_handler(switch_event_t *event) {
+ switch_event_header_t *event_header = NULL;
+
+ if (!event) {
+ return;
+ }
+
+ // Print out all event headers, for fun
+ if (event->headers) {
+ for (event_header = event->headers; event_header; event_header = event_header->next) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Header info: %s => %s\n", event_header->name, event_header->value);
+ }
+ }
+}
+
+
+static switch_status_t sched_billing(switch_core_session_t *session) {
+
+ switch_core_session_enable_heartbeat(session, 60);
+
+ return SWITCH_STATUS_SUCCESS;
+
+}
+
+/* This is where we actually charge the guy */
+/* This can be called anytime a call is in progress or at the end of a call before the session is destroyed */
+static switch_status_t do_billing(switch_core_session_t *session) {
+
+ // FS vars we will use
+ switch_channel_t *channel;
+ switch_caller_profile_t *profile;
+
+ // Local vars
+ nibble_data_t *nibble_data;
+ switch_time_t ts = switch_timestamp_now();
+ float billamount;
+ char date[80] = "";
+ char *uuid;
+ switch_size_t retsize;
+ switch_time_exp_t tm;
+
+ if (!session) {
+ // wtf? Why are we here?
+ return SWITCH_STATUS_GENERR;
+ }
+
+ uuid = switch_core_session_get_uuid(session);
+
+ // Get channel var
+ channel = switch_core_session_get_channel(session);
+ if (!channel) {
+ return SWITCH_STATUS_GENERR;
+ }
+
+ // Variables kept in FS but relevant only to this module
+ const char *billrate = switch_channel_get_variable(channel, "nibble_rate");
+ const char *billaccount = switch_channel_get_variable(channel, "nibble_account");
+
+ // Return if there's no billing information on this session
+ if (!billrate || !billaccount) {
+ return SWITCH_STATUS_GENERR;
+ }
+
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Attempting to bill at $%s per minute to account %s\n", billrate, billaccount);
+
+ // Get caller profile info from channel
+ profile = switch_channel_get_caller_profile(channel);
+
+ if (!profile) {
+ // No caller profile (why would this happen?)
+ return SWITCH_STATUS_GENERR;
+ }
+
+ if (profile->times->answered < 1) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Not billing %s - call is not in answered state\n", billaccount);
+ return SWITCH_STATUS_SUCCESS;
+ }
+
+ // Lock this session's data for this module while we tinker with it
+ if (globals.mutex) {
+ switch_mutex_lock(globals.mutex);
+ }
+
+ // Get our nibble data var. This will be NULL if it's our first call here for this session
+ nibble_data = (nibble_data_t *) switch_channel_get_private(channel, "_nibble_data_");
+
+ // Have we done any billing on this channel yet? If no, set up vars for doing so
+ if (!nibble_data) {
+ nibble_data = switch_core_session_alloc(session, sizeof(*nibble_data));
+ if (!nibble_data) {
+ switch_assert(nibble_data);
+ }
+ memset(nibble_data, 0, sizeof(*nibble_data));
+
+ // Setup new billing data (based on call answer time, in case this module started late with active calls)
+ nibble_data->lastts = profile->times->answered; // Set the initial answer time to match when the call was really answered
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Beginning new billing on %s\n", uuid);
+ } else {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Last successful billing time was %s\n", date);
+ }
+
+ switch_time_exp_lt(&tm, nibble_data->lastts);
+ switch_strftime_nocheck(date, &retsize, sizeof(date), "%Y-%m-%d %T", &tm);
+
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%d seconds passed since last bill time of %s\n", (int) ((ts - nibble_data->lastts) / 1000000), date);
+
+
+ if ((ts - nibble_data->lastts) > 0) {
+ // Convert billrate into microseconds and multiply by # of microseconds that have passed
+ billamount = (atof(billrate) / 1000000 / 60) * ((ts - nibble_data->lastts));
+
+ // if ODBC call fails, we should return BEFORE updating the timestamp of last success!
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Billing $%f to %s (Call: %s / %f so far)\n", billamount, billaccount, uuid, nibble_data->total);
+
+ // DO ODBC BILLING HERE!
+#ifdef SWITCH_HAVE_ODBC
+ char sql[1024] = "";
+ nibblebill_results_t pdata;
+
+ memset(&pdata, 0, sizeof(pdata));
+ if (!globals.save_query){
+ snprintf(sql, 1024, SQL_SAVE, billamount, billaccount);
+ } else {
+ snprintf(sql, 1024, globals.save_query, billamount, billaccount);
+ }
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Doing static update query\n[%s]\n", sql);
+
+ if (!(switch_odbc_handle_callback_exec(globals.master_odbc, sql, nibblebill_callback, &pdata) == SWITCH_ODBC_SUCCESS)){
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "DB Error while updating cash!\n");
+
+ // TODO: If this is a hangup event, we should store this billing in a text file while the DB is unavailable
+ }
+#endif
+
+ // Increment total cost
+ nibble_data->total += billamount;
+ } else {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Just tried to bill %s negative minutes! wtf?\n", uuid);
+ }
+
+ // Update the last time we billed
+ nibble_data->lastts = ts;
+
+ // Save everything back
+ switch_channel_set_private(channel, "_nibble_data_", nibble_data);
+
+ // Release the session lock
+ switch_core_session_rwunlock(session);
+
+ // Done changing - release lock
+ if (globals.mutex) {
+ switch_mutex_unlock(globals.mutex);
+ }
+
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+
+/* You can turn on session heartbeat on a channel to have us check billing more often */
+static void event_handler(switch_event_t *event) {
+ if (!event){
+ // WTF? We should never get here - it means an event came in without the event info
+ return;
+ }
+
+ // FS vars we'll need
+ switch_core_session_t *session;
+ char *uuid = switch_event_get_header(event, "Unique-ID");
+
+ // Make sure everything is sane
+ if (!uuid){
+ // Donde esta channel?
+ return;
+ }
+
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Received request via %s!\n", switch_event_name (event->event_id));
+
+ // Display debugging info
+ if (switch_event_get_header(event, "nibble_debug")) {
+ debug_event_handler(event);
+ }
+
+ // Get session var
+ session = switch_core_session_locate(uuid);
+ if (!session) {
+ return;
+ }
+
+ // Go bill
+ do_billing(session);
+
+ switch_core_session_rwunlock(session);
+}
+
+SWITCH_STANDARD_APP(nibblebill_app_function)
+{
+ switch_channel_t *channel = switch_core_session_get_channel(session);
+
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "We made it!\n");
+
+ if (!channel) {
+ return;
+ }
+
+/* if (!(mydata = switch_core_session_strdup(session, data))) {
+ return;
+ }
+
+ if ((argc = switch_separate_string(mydata, ' ', argv, (sizeof(argv) / sizeof(argv[0]))))) {
+ destnum = argv[0];
+ do_billing(session);
+ }*/
+}
+
+/* We get here from the API only (theoretically) */
+SWITCH_STANDARD_API(nibblebill_function)
+{
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "We made it!\n");
+
+// Check if session has variable "billrate" set. If it does, activate the heartbeat variable
+// switch_core_session_enable_heartbeat(switch_core_session_t *session, uint32_t seconds)
+// switch_core_session_sched_heartbeat(switch_core_session_t *session, uint32_t seconds)
+
+
+ return SWITCH_STATUS_SUCCESS;
+
+}
+
+switch_state_handler_table_t nibble_state_handler = {
+ /* on_init */ NULL,
+ /* on_routing */ NULL, // Need to add a check here for anything in their account before routing
+ /* on_execute */ sched_billing, // Turn on heartbeat for this session
+ /* on_hangup */ do_billing, // On hangup - most important place to go bill
+ /* on_exch_media */ NULL, // Run billing upon a call being established
+ /* on_soft_exec */ NULL,
+ /* on_consume_med */ NULL,
+ /* on_hibernate */ NULL,
+ /* on_reset */ do_billing // In case the switch is reset, we still want to log billing
+};
+
+
+SWITCH_MODULE_LOAD_FUNCTION(mod_nibblebill_load)
+{
+ switch_api_interface_t *api_interface;
+ switch_application_interface_t *app_interface;
+
+ /* Set every byte in this structure to 0 */
+ memset(&globals, 0, sizeof(globals));
+ load_config();
+
+ /* connect my internal structure to the blank pointer passed to me */
+ *module_interface = switch_loadable_module_create_module_interface(pool, modname);
+ SWITCH_ADD_API(api_interface, "check", "Check the balance of an account", nibblebill_function, "");
+ SWITCH_ADD_APP(app_interface, "check", "Check the balance on an account", "Perform an account check for fund balance", nibblebill_app_function, "<number>", SAF_SUPPORT_NOMEDIA);
+
+ /* register state handlers for billing */
+ switch_core_add_state_handler(&nibble_state_handler);
+
+ /* bind to heartbeat events */
+ if (switch_event_bind_removable(modname, SWITCH_EVENT_SESSION_HEARTBEAT, SWITCH_EVENT_SUBCLASS_ANY, event_handler, NULL, &globals.node) != SWITCH_STATUS_SUCCESS) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't bind event to monitor for session heartbeats!\n");
+ return SWITCH_STATUS_GENERR;
+ }
+
+ /* indicate that the module should continue to be loaded */
+ return SWITCH_STATUS_SUCCESS;
+}
+
+SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_nibblebill_shutdown)
+{
+ switch_event_unbind(&globals.node);
+ switch_core_remove_state_handler(&nibble_state_handler);
+
+#ifdef SWITCH_HAVE_ODBC
+ switch_odbc_handle_disconnect(globals.master_odbc);
+#endif
+
+ return SWITCH_STATUS_UNLOAD;
+}
+
+/* For Emacs:
+ * Local Variables:
+ * mode:c
+ * indent-tabs-mode:t
+ * tab-width:4
+ * c-basic-offset:4
+ * End:
+ * For VIM:
+ * vim:set softtabstop=4 shiftwidth=4 tabstop=4 expandtab:
+ */
1
0