[Freeswitch-svn] [commit] r13432 - freeswitch/trunk/scripts/contrib/dschreiber/mod_nibblebill
FreeSWITCH SVN
dschreiber at freeswitch.org
Mon May 25 22:50:41 PDT 2009
Author: dschreiber
Date: Tue May 26 00:50:41 2009
New Revision: 13432
Log:
Added feature mod_nibblebill to check balance and transfer the caller to an alternate dialplan context & extension if they deplete their funds.
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 Tue May 26 00:50:41 2009
@@ -56,8 +56,8 @@
/* Defaults */
#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";
+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
@@ -73,7 +73,7 @@
typedef struct nibblebill_results
{
- float funds;
+ float balance;
float percall_max; /* Overrides global on a per-user level */
float lowbal_amt; /* ditto */
@@ -117,6 +117,8 @@
#endif
} globals;
+static void nibblebill_pause(switch_core_session_t *session);
+
/**************************
* Setup FreeSWITCH Macros *
**************************/
@@ -141,14 +143,14 @@
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)
+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]);
+ cbt->balance = atof(argv[0]);
return 0;
-}*/
+}
#endif
static switch_status_t load_config(void)
@@ -271,6 +273,37 @@
}
+static void transfer_call(switch_core_session_t *session, char *destination)
+{
+ char *argv[4] = { 0 };
+
+ switch_separate_string(destination, ' ', argv, (sizeof(argv) / sizeof(argv[0])));
+
+ const char *uuid;
+ switch_channel_t *channel = switch_core_session_get_channel(session);
+ /* Find the uuid of our B leg. If it exists, transfer it first */
+ if ((uuid = switch_channel_get_variable(channel, SWITCH_SIGNAL_BOND_VARIABLE))) {
+ /* Make sure we are in the media path on B leg */
+ switch_ivr_media(uuid, SMF_REBRIDGE);
+
+ /* Get info on the B leg */
+ switch_core_session_t *b_session;
+ if ((b_session = switch_core_session_locate(uuid))) {
+ /* Transfer the B leg */
+ switch_ivr_session_transfer(b_session, argv[0], argv[1], argv[2]);
+ switch_core_session_rwunlock(b_session);
+ }
+ }
+
+ /* Make sure we are in the media path on A leg */
+ uuid = switch_core_session_get_uuid(session);
+ switch_ivr_media(uuid, SMF_REBRIDGE);
+
+ /* Transfer the A leg */
+ switch_ivr_session_transfer(session, argv[0], argv[1], argv[2]);
+}
+
+
/* At this time, billing never succeeds if you don't have a database. */
static switch_status_t bill_event(float billamount, const char *billaccount)
{
@@ -300,6 +333,36 @@
}
+static float get_balance(const char *billaccount)
+{
+#ifdef SWITCH_HAVE_ODBC
+ char sql[1024] = "";
+ nibblebill_results_t pdata;
+ float balance = 0.00;
+
+ memset(&pdata, 0, sizeof(pdata));
+ snprintf(sql, 1024, SQL_LOOKUP, globals.db_column_cash, globals.db_table, globals.db_column_account, billaccount);
+
+ if (switch_odbc_handle_callback_exec(globals.master_odbc, sql, nibblebill_callback, &pdata) != SWITCH_ODBC_SUCCESS) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error running this query: [%s]\n", sql);
+#endif
+ /* TODO: Return -1 for safety */
+
+ return -1.00;
+#ifdef SWITCH_HAVE_ODBC
+ } else {
+ /* Successfully retrieved! */
+ balance = pdata.balance;
+
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Retrieved current balance for account %s (balance = %f)\n", billaccount, balance);
+ }
+
+#endif
+ return balance;
+}
+
+
+
/* 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)
@@ -426,6 +489,20 @@
/* Save this location, but only if the channel/session are not hungup (otherwise, we're done) */
if (channel && switch_channel_get_state(channel) != CS_HANGUP) {
switch_channel_set_private(channel, "_nibble_data_", nibble_data);
+
+ /* See if this person has enough money left to continue the call */
+ float balance;
+ balance = get_balance(billaccount);
+ if (balance < globals.nobal_amt) {
+ /* Not enough money - reroute call to nobal location */
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Balance of %f fell below allowed amount of %f! (Account %s)\n", balance, globals.nobal_amt, billaccount);
+
+ /* IMPORTANT: Billing must be paused before the transfer occurs! This prevents infinite loops, since the transfer will result */
+ /* in nibblebill checking the call again in the routing process for an allowed balance! */
+ /* If you intend to give the user the option to re-up their balance, you must clear & resume billing once the balance is updated! */
+ nibblebill_pause(session);
+ transfer_call(session, globals.nobal_action);
+ }
}
/* Done changing - release lock */
@@ -648,6 +725,7 @@
}
+
#define APP_SYNTAX "pause | resume | reset | adjust <amount> | heartbeat <seconds> | check"
SWITCH_STANDARD_APP(nibblebill_app_function)
{
More information about the Freeswitch-svn
mailing list