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
- 12151 discussions
[commit] r10496 - in freeswitch/trunk/scripts/contrib/intralanman/C/lcr: mod_lcr sql
by FreeSWITCH SVN 21 Nov '08
by FreeSWITCH SVN 21 Nov '08
21 Nov '08
Author: intralanman
Date: Fri Nov 21 11:09:17 2008
New Revision: 10496
Log:
add pg schema && rm -f `find brainfart`
Added:
freeswitch/trunk/scripts/contrib/intralanman/C/lcr/sql/
freeswitch/trunk/scripts/contrib/intralanman/C/lcr/sql/postgres-8.3.sql
Removed:
freeswitch/trunk/scripts/contrib/intralanman/C/lcr/mod_lcr/mod_lcr.c.rej.orig
Added: freeswitch/trunk/scripts/contrib/intralanman/C/lcr/sql/postgres-8.3.sql
==============================================================================
--- (empty file)
+++ freeswitch/trunk/scripts/contrib/intralanman/C/lcr/sql/postgres-8.3.sql Fri Nov 21 11:09:17 2008
@@ -0,0 +1,79 @@
+-- Table: carriers
+
+-- DROP TABLE carriers;
+
+CREATE TABLE carriers
+(
+ id serial NOT NULL,
+ carrier_name VARCHAR(255) NOT NULL,
+ CONSTRAINT carriers_pkey PRIMARY KEY (id)
+);
+
+-- Table: carrier_gateway
+
+-- DROP TABLE carrier_gateway;
+
+CREATE TABLE carrier_gateway
+(
+ id serial NOT NULL,
+ carrier_id integer REFERENCES carriers(id),
+ prefix VARCHAR(128) NOT NULL DEFAULT '',
+ suffix VARCHAR(128) NOT NULL DEFAULT '',
+ CONSTRAINT carrier_gateway_pkey PRIMARY KEY (id)
+);
+
+-- Index: gateway
+
+-- DROP INDEX gateway;
+
+CREATE UNIQUE INDEX gateway
+ ON carrier_gateway
+ (gateway, term_host, port);
+
+-- Table: lcr
+
+-- DROP TABLE lcr;
+
+CREATE TABLE lcr
+(
+ id serial NOT NULL,
+ digits VARCHAR(15),
+ rate numeric(11,5) NOT NULL,
+ carrier_id integer NOT NULL REFERENCES carriers(id),
+ lead_strip integer NOT NULL DEFAULT 0,
+ trail_strip integer NOT NULL DEFAULT 0,
+ prefix VARCHAR(16) NOT NULL DEFAULT '',
+ suffix VARCHAR(16) NOT NULL DEFAULT '',
+ lcr_profile VARCHAR(32),
+ date_start timestamp with time zone NOT NULL,
+ date_end timestamp with time zone NOT NULL,
+ quality numeric(10,6) NOT NULL DEFAULT 0,
+ reliability numeric(10,6) NOT NULL DEFAULT 0,
+ CONSTRAINT lcr_pkey PRIMARY KEY (id)
+);
+
+-- Index: digits_rate
+
+-- DROP INDEX digits_rate;
+
+CREATE INDEX digits_rate
+ ON lcr
+ USING btree
+ (digits, rate);
+
+-- Index: profile_digits_15
+
+-- DROP INDEX profile_digits_15;
+
+CREATE INDEX profile_digits_15
+ ON lcr
+ (digits, lcr_profile);
+
+-- Index: unique_route
+
+-- DROP INDEX unique_route;
+
+CREATE INDEX unique_route
+ ON lcr
+ (digits, carrier_id);
+
1
0
[commit] r10495 - in freeswitch/trunk/scripts/contrib/intralanman/C: lcr lcr/mod_lcr mod_lcr
by FreeSWITCH SVN 21 Nov '08
by FreeSWITCH SVN 21 Nov '08
21 Nov '08
Author: intralanman
Date: Fri Nov 21 11:01:57 2008
New Revision: 10495
Log:
mod_lcr with conf file and patches from stkn and rupa
Added:
freeswitch/trunk/scripts/contrib/intralanman/C/lcr/
freeswitch/trunk/scripts/contrib/intralanman/C/lcr/mod_lcr/
freeswitch/trunk/scripts/contrib/intralanman/C/lcr/mod_lcr/Makefile
freeswitch/trunk/scripts/contrib/intralanman/C/lcr/mod_lcr/mod_lcr.c
freeswitch/trunk/scripts/contrib/intralanman/C/lcr/mod_lcr/mod_lcr.c.orig
freeswitch/trunk/scripts/contrib/intralanman/C/lcr/mod_lcr/mod_lcr.c.rej.orig
Removed:
freeswitch/trunk/scripts/contrib/intralanman/C/mod_lcr/
Added: freeswitch/trunk/scripts/contrib/intralanman/C/lcr/mod_lcr/Makefile
==============================================================================
--- (empty file)
+++ freeswitch/trunk/scripts/contrib/intralanman/C/lcr/mod_lcr/Makefile Fri Nov 21 11:01:57 2008
@@ -0,0 +1,3 @@
+BASE=../../../..
+LOCAL_CFLAGS += `if test -f $(BASE)/.libs/libfreeswitch_la-switch_odbc.o ; then echo -DSWITCH_HAVE_ODBC; fi ;`
+include $(BASE)/build/modmake.rules
Added: freeswitch/trunk/scripts/contrib/intralanman/C/lcr/mod_lcr/mod_lcr.c
==============================================================================
--- (empty file)
+++ freeswitch/trunk/scripts/contrib/intralanman/C/lcr/mod_lcr/mod_lcr.c Fri Nov 21 11:01:57 2008
@@ -0,0 +1,539 @@
+/*
+ * 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>
+ * Portions created by the Initial Developer are Copyright (C)
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Raymond Chandler <intralanman(a)gmail.com>
+ *
+ * mod_lcr.c -- Least Cost Routing Module
+ *
+ */
+
+#include <switch.h>
+#include <switch_odbc.h>
+
+
+#define LCR_SYNTAX "lcr <digits>"
+
+/* SQL Query places */
+#define LCR_DIGITS_PLACE 0
+#define LCR_CARRIER_PLACE 1
+#define LCR_RATE_PLACE 2
+#define LCR_GATEWAY_PLACE 3
+#define LCR_IP_ADDRESS_PLACE 4
+#define LCR_PORT_PLACE 5
+#define LCR_LSTRIP_PLACE 6
+#define LCR_TSTRIP_PLACE 7
+#define LCR_PREFIX_PLACE 8
+#define LCR_SUFFIX_PLACE 9
+
+
+#define LCR_DIALSTRING_PLACE 3
+#define LCR_HEADERS_COUNT 4
+char headers[LCR_HEADERS_COUNT][32] = {
+ "Digit Match",
+ "Carrier",
+ "Rate",
+ "Dialstring",
+};
+
+struct odbc_obj {
+ switch_odbc_handle_t *handle;
+ SQLHSTMT stmt;
+ SQLCHAR *colbuf;
+ int32_t cblen;
+ SQLCHAR *code;
+ int32_t codelen;
+};
+
+struct lcr_obj {
+ char *carrier_name;
+ char *gateway_name;
+ char *term_host;
+ char *port;
+ char *digit_str;
+ char *prefix;
+ char *suffix;
+ char *dialstring;
+ float rate;
+ size_t lstrip;
+ size_t tstrip;
+ size_t digit_len;
+ struct lcr_obj *next;
+};
+
+struct max_obj {
+ size_t carrier_name;
+ size_t gateway_name;
+ size_t digit_str;
+ size_t rate;
+ size_t dialstring;
+};
+
+typedef struct odbc_obj odbc_obj_t;
+typedef odbc_obj_t *odbc_handle;
+
+typedef struct lcr_obj lcr_obj_t;
+typedef lcr_obj_t *lcr_route;
+
+typedef struct max_obj max_obj_t;
+typedef max_obj_t *max_len;
+
+struct callback_obj {
+ lcr_route head;
+ int matches;
+ char *lookup_number;
+};
+typedef struct callback_obj callback_t;
+
+static struct {
+ switch_memory_pool_t *pool;
+ char *dbname;
+ char *odbc_dsn;
+ switch_mutex_t *mutex;
+ switch_odbc_handle_t *master_odbc;
+ void *filler1;
+} globals;
+
+
+SWITCH_MODULE_LOAD_FUNCTION(mod_lcr_load);
+SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_lcr_shutdown);
+SWITCH_MODULE_DEFINITION(mod_lcr, mod_lcr_load, mod_lcr_shutdown, NULL);
+
+static char *get_bridge_data(const char *dialed_number, lcr_route cur_route) {
+ size_t lstrip;
+ size_t tstrip;
+ char *data = NULL;
+ char *destination_number = NULL;
+
+ destination_number = strdup(dialed_number);
+
+ tstrip = ((cur_route->digit_len - cur_route->tstrip) + 1);
+ lstrip = cur_route->lstrip;
+
+ if (strlen(destination_number) > tstrip && cur_route->tstrip > 0) {
+ destination_number[tstrip] = '\0';
+ }
+ if (strlen(destination_number) > lstrip && cur_route->lstrip > 0) {
+ destination_number += lstrip;
+ }
+
+ if (strlen(cur_route->gateway_name) > 0) {
+ data = switch_mprintf("sofia/gateway/%s/%s%s%s", cur_route->gateway_name
+ , cur_route->prefix, destination_number, cur_route->suffix
+ );
+ } else {
+ char port[8];
+ switch_snprintf(port, sizeof(port), ":%s", cur_route->port);
+ data = switch_mprintf("sofia/${use_profile}/%s@%s%s"
+ , destination_number, cur_route->term_host, (strlen(cur_route->port) > 0 ? port : "")
+ );
+ }
+
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Returning Dialstring %s\n", data);
+ switch_safe_free(destination_number);
+ return data;
+}
+
+void init_max_lens(max_len maxes) {
+ maxes->digit_str = (headers[LCR_DIGITS_PLACE] == NULL ? 0 : strlen(headers[LCR_DIGITS_PLACE]));
+ maxes->carrier_name = (headers[LCR_CARRIER_PLACE] == NULL ? 0 : strlen(headers[LCR_CARRIER_PLACE]));
+ maxes->gateway_name = (headers[LCR_GATEWAY_PLACE] == NULL ? 0 : strlen(headers[LCR_GATEWAY_PLACE]));
+ maxes->dialstring = (headers[LCR_DIALSTRING_PLACE] == NULL ? 0 : strlen(headers[LCR_DIALSTRING_PLACE]));
+ maxes->digit_str = (headers[LCR_DIGITS_PLACE] == NULL ? 0 : strlen(headers[LCR_DIGITS_PLACE]));
+ maxes->rate = 8;
+}
+
+switch_status_t process_max_lengths(max_obj_t *maxes, lcr_route routes, char *destination_number) {
+ lcr_route current = NULL;
+ init_max_lens(maxes);
+ if (routes == NULL ) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "no routes\n");
+ return SWITCH_STATUS_FALSE;
+ }
+ if (maxes == NULL ) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "no maxes\n");
+ return SWITCH_STATUS_FALSE;
+ }
+
+ if (routes != NULL && maxes != NULL) {
+ for (current = routes; current; current = current->next) {
+ size_t this_len;
+ if (current->gateway_name != NULL) {
+ this_len = strlen(current->gateway_name);
+ if (this_len > maxes->gateway_name) {
+ maxes->gateway_name = this_len;
+ }
+ }
+ if (current->carrier_name != NULL) {
+ this_len = strlen(current->carrier_name);
+ if (this_len > maxes->carrier_name) {
+ maxes->carrier_name = this_len;
+ }
+ }
+ if (current->dialstring != NULL) {
+ this_len = strlen(current->dialstring);
+ if (this_len > maxes->dialstring) {
+ maxes->dialstring = this_len;
+ }
+ }
+ if (current->digit_str != NULL) {
+ if (current->digit_len > maxes->digit_str) {
+ maxes->digit_str = current->digit_len;
+ }
+ }
+ }
+ }
+ return SWITCH_STATUS_SUCCESS;
+}
+
+static switch_bool_t lcr_execute_sql_callback(char *sql, switch_core_db_callback_func_t callback, void *pdata) {
+ if (globals.odbc_dsn) {
+ switch_odbc_handle_callback_exec(globals.master_odbc, sql, callback, pdata);
+ return SWITCH_TRUE;
+ } else {
+ return SWITCH_FALSE;
+ }
+}
+
+int route_add_callback(void *pArg, int argc, char **argv, char **columnNames) {
+ lcr_route additional = NULL;
+ lcr_route current = NULL;
+ callback_t *cbt = (callback_t *) pArg;
+
+ cbt->matches++;
+
+ switch_zmalloc(additional, sizeof(lcr_obj_t));
+
+ additional->digit_len = strlen(argv[LCR_DIGITS_PLACE]);
+ additional->digit_str = switch_safe_strdup(argv[LCR_DIGITS_PLACE]);
+ additional->suffix = switch_safe_strdup(argv[LCR_SUFFIX_PLACE]);
+ additional->prefix = switch_safe_strdup(argv[LCR_PREFIX_PLACE]);
+ additional->carrier_name = switch_safe_strdup(argv[LCR_CARRIER_PLACE]);
+ additional->rate = (float)atof(argv[LCR_RATE_PLACE]);
+ additional->gateway_name = switch_safe_strdup(argv[LCR_GATEWAY_PLACE]);
+ additional->term_host = switch_safe_strdup(argv[LCR_IP_ADDRESS_PLACE]);
+ additional->port = switch_safe_strdup(argv[LCR_PORT_PLACE]);
+ additional->lstrip = atoi(argv[LCR_LSTRIP_PLACE]);
+ additional->tstrip = atoi(argv[LCR_TSTRIP_PLACE]);
+ additional->dialstring = get_bridge_data(cbt->lookup_number, additional);
+
+ if (cbt->head != NULL) {
+ for (current = cbt->head; current; current = current->next) {
+
+ if (switch_strlen_zero(additional->gateway_name) && switch_strlen_zero(additional->term_host) && switch_strlen_zero(additional->port) ) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING
+ , "WTF?!? There's no way to dial this Gateway: %s IP:Port %s:%s\n"
+ , additional->gateway_name, additional->term_host, additional->port
+ );
+ break;
+ }
+
+ if (!strcmp(current->gateway_name, additional->gateway_name)) {
+ if (!strcmp(current->term_host, additional->term_host) && !strcmp(current->port, additional->port)) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG
+ , "Ignoring Duplicate route for termination point (%s:%s)\n"
+ , additional->term_host, additional->port
+ );
+ switch_safe_free(additional);
+ break;
+ }
+ }
+
+ if (current->next == NULL) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "adding route to end of list\n");
+ current->next = additional;
+ break;
+ }
+
+ }
+ } else {
+ additional->next = cbt->head;
+ cbt->head = additional;
+ }
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+switch_status_t lcr_do_lookup(char *digits, callback_t *cb_struct) {
+ /* instantiate the object/struct we defined earlier */
+ switch_stream_handle_t sql_stream = { 0 };
+ size_t n, digit_len = strlen(digits);
+ char *digits_copy;
+
+ if (switch_strlen_zero(digits)) {
+ return SWITCH_FALSE;
+ }
+
+ digits_copy = strdup(digits);
+
+ SWITCH_STANDARD_STREAM(sql_stream);
+
+ /* set up the query to be executed */
+ sql_stream.write_function(&sql_stream,
+ "SELECT l.digits, c.Carrier_Name, l.rate, cg.gateway, cg.term_host, cg.port, l.lead_strip, l.trail_strip, l.prefix, l.suffix "
+ );
+ sql_stream.write_function(&sql_stream, "FROM lcr l JOIN carriers c ON l.carrier_id=c.id JOIN carrier_gateway cg ON c.id=cg.carrier_id ");
+ for (n = digit_len; n > 0; n--) {
+ digits_copy[n] = '\0';
+ sql_stream.write_function(&sql_stream, "%s digits='%s' ", (n==digit_len ? "WHERE" : "OR"), digits_copy);
+ }
+ sql_stream.write_function(&sql_stream, "ORDER BY digits DESC, rate;");
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "%s\n", (char *)sql_stream.data);
+ lcr_execute_sql_callback((char *)sql_stream.data, route_add_callback, cb_struct);
+ switch_safe_free(sql_stream.data);
+ return SWITCH_STATUS_SUCCESS;
+}
+
+static switch_status_t lcr_load_config() {
+ char *cf = "lcr.conf";
+ switch_xml_t cfg, xml, settings, param;
+ switch_status_t status = SWITCH_STATUS_SUCCESS;
+ char *odbc_user = NULL;
+ char *odbc_pass = NULL;
+ if (!(xml = switch_xml_open_cfg(cf, &cfg, NULL))) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "open of %s failed\n", cf);
+ return SWITCH_STATUS_TERM;
+ }
+ if ((settings = switch_xml_child(cfg, "settings"))) {
+ for (param = switch_xml_child(settings, "param"); param; param = param->next) {
+ char *var = NULL;
+ char *val = NULL;
+ var = (char *) switch_xml_attr_soft(param, "name");
+ val = (char *) switch_xml_attr_soft(param, "value");
+ if (!strcasecmp(var, "odbc-dsn") && !switch_strlen_zero(val)) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "odbc_dsn is %s\n", val);
+ globals.odbc_dsn = switch_core_strdup(globals.pool, val);
+ if ((odbc_user = strchr(globals.odbc_dsn, ':'))) {
+ *odbc_user++ = '\0';
+ if ((odbc_pass = strchr(odbc_user, ':'))) {
+ *odbc_pass++ = '\0';
+ }
+ }
+ }
+ }
+ }
+ if (globals.odbc_dsn) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO
+ , "dsn is \"%s\", user is \"%s\", and password is \"%s\"\n"
+ , globals.odbc_dsn, odbc_user, odbc_pass
+ );
+ if (!(globals.master_odbc = switch_odbc_handle_new(globals.odbc_dsn, odbc_user, odbc_pass))) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Cannot Open ODBC Database!\n");
+ status = SWITCH_STATUS_FALSE;
+ goto done;
+ }
+ if (switch_odbc_handle_connect(globals.master_odbc) != SWITCH_ODBC_SUCCESS) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Cannot Open ODBC Database!\n");
+ status = SWITCH_STATUS_FALSE;
+ goto done;
+ }
+ }
+ done:
+ switch_xml_free(xml);
+ return status;
+}
+
+static void destroy_list(lcr_route *head) {
+ lcr_route cur = NULL, top = *head;
+ while (top) {
+ cur = top;
+ top = top->next;
+ switch_safe_free(cur->digit_str);
+ switch_safe_free(cur->suffix);
+ switch_safe_free(cur->prefix);
+ switch_safe_free(cur->carrier_name);
+ switch_safe_free(cur->gateway_name);
+ switch_safe_free(cur);
+ }
+ *head = NULL;
+}
+
+SWITCH_STANDARD_DIALPLAN(lcr_dialplan_hunt) {
+ switch_caller_extension_t *extension = NULL;
+ switch_channel_t *channel = switch_core_session_get_channel(session);
+ callback_t routes = { 0 };
+ lcr_route cur_route = { 0 };
+ char *bridge_data = NULL;;
+
+ if (!caller_profile) {
+ caller_profile = switch_channel_get_caller_profile(channel);
+ }
+
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "LCR Lookup on %s\n", caller_profile->destination_number);
+ routes.lookup_number = caller_profile->destination_number;
+ if (lcr_do_lookup(caller_profile->destination_number, &routes) == SWITCH_STATUS_SUCCESS) {
+ if ((extension = switch_caller_extension_new(session, caller_profile->destination_number, caller_profile->destination_number)) == 0) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "memory error!\n");
+ destroy_list(&routes.head);
+ return NULL;
+ }
+
+ switch_channel_set_variable(channel, SWITCH_CONTINUE_ON_FAILURE_VARIABLE, "true");
+ switch_channel_set_variable(channel, SWITCH_HANGUP_AFTER_BRIDGE_VARIABLE, "true");
+ for (cur_route = routes.head; cur_route; cur_route = cur_route->next) {
+ //bridge_data = get_bridge_data(caller_profile->destination_number, cur_route);
+ switch_caller_extension_add_application(session, extension, "bridge", cur_route->dialstring);
+ switch_safe_free(bridge_data);
+ }
+ destroy_list(&routes.head);
+ } else {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "LCR lookup failed for %s\n", caller_profile->destination_number);
+ }
+ switch_safe_free(bridge_data);
+
+ return extension;
+}
+
+void str_repeat(size_t how_many, char *what, switch_stream_handle_t *str_stream) {
+ size_t i;
+ //switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "repeating %d of '%s'\n", how_many, what);
+ if (how_many > 0) {
+ for (i=0; i<how_many; i++) {
+ str_stream->write_function(str_stream, "%s", what);
+ }
+ }
+}
+
+SWITCH_STANDARD_API(dialplan_lcr_function) {
+ char *argv[4] = { 0 };
+ int argc;
+ char *mydata = NULL;
+ char *dialstring = NULL;
+ char *destination_number = NULL;
+ lcr_route current = NULL;
+ max_obj_t maximum_lengths = { 0 };
+ callback_t cb_struct = { 0 };
+ //switch_malloc(maximum_lengths, sizeof(max_obj_t));
+
+ if (switch_strlen_zero(cmd)) {
+ goto usage;
+ }
+ mydata = switch_safe_strdup(cmd);
+ if ((argc = switch_separate_string(mydata, ' ', argv, (sizeof(argv) / sizeof(argv[0]))))) {
+ destination_number = strdup(argv[0]);
+ cb_struct.lookup_number = destination_number;
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO
+ , "data passed to lcr is [%s]\n", cmd
+ );
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO
+ , "lcr lookup returned [%d]\n"
+ , lcr_do_lookup(destination_number, &cb_struct)
+ );
+ if (cb_struct.head != NULL) {
+ process_max_lengths(&maximum_lengths, cb_struct.head, destination_number);
+
+ stream->write_function(stream, " | %s", headers[LCR_DIGITS_PLACE]);
+ str_repeat((maximum_lengths.digit_str - strlen(headers[LCR_DIGITS_PLACE])), " ", stream);
+
+ stream->write_function(stream, " | %s", headers[LCR_CARRIER_PLACE]);
+ str_repeat((maximum_lengths.carrier_name - strlen(headers[LCR_CARRIER_PLACE])), " ", stream);
+
+ stream->write_function(stream, " | %s", headers[LCR_RATE_PLACE]);
+ str_repeat((maximum_lengths.rate - strlen(headers[LCR_RATE_PLACE])), " ", stream);
+
+ stream->write_function(stream, " | %s", headers[LCR_DIALSTRING_PLACE]);
+ str_repeat((maximum_lengths.dialstring - strlen(headers[LCR_DIALSTRING_PLACE])), " ", stream);
+
+ stream->write_function(stream, " |\n");
+
+
+ current = cb_struct.head;
+ while (current) {
+ char srate[10];
+ dialstring = get_bridge_data(destination_number, current);
+ switch_snprintf(srate, sizeof(srate), "%0.5f", current->rate);
+
+
+ stream->write_function(stream, " | %s", current->digit_str);
+ str_repeat((maximum_lengths.digit_str - current->digit_len), " ", stream);
+
+ stream->write_function(stream, " | %s", current->carrier_name );
+ str_repeat((maximum_lengths.carrier_name - strlen(current->carrier_name)), " ", stream);
+
+ stream->write_function(stream, " | %s", srate );
+ str_repeat((maximum_lengths.rate - strlen(srate)), " ", stream);
+
+ stream->write_function(stream, " | %s", dialstring);
+ str_repeat((maximum_lengths.dialstring - strlen(dialstring)), " ", stream);
+
+ stream->write_function(stream, " |\n");
+
+ switch_safe_free(dialstring);
+ current = current->next;
+
+ }
+
+ destroy_list(&cb_struct.head);
+ switch_safe_free(dialstring);
+ } else {
+ stream->write_function(stream, "No Routes To Display\n");
+ }
+ }
+
+ switch_safe_free(mydata);
+ return SWITCH_STATUS_SUCCESS;
+ usage:
+ stream->write_function(stream, "USAGE: %s\n", LCR_SYNTAX);
+ return SWITCH_STATUS_SUCCESS;
+}
+
+SWITCH_MODULE_LOAD_FUNCTION(mod_lcr_load) {
+ switch_api_interface_t *dialplan_lcr_api_interface;
+ switch_dialplan_interface_t *dp_interface;
+
+ *module_interface = switch_loadable_module_create_module_interface(pool, modname);
+#ifndef SWITCH_HAVE_ODBC
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "You must have ODBC support in FreeSWITCH to use this module\n");
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "\t./configure --enable-core-odbc-support\n");
+ return SWITCH_STATUS_FALSE;
+#endif
+ globals.pool = pool;
+ if (lcr_load_config() != SWITCH_STATUS_SUCCESS) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Unable to load lcr config file\n");
+ return SWITCH_STATUS_FALSE;
+ }
+ if (switch_mutex_init(&globals.mutex, SWITCH_MUTEX_NESTED, globals.pool) != SWITCH_STATUS_SUCCESS) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "failed to initialize mutex\n");
+ }
+ SWITCH_ADD_API(dialplan_lcr_api_interface, "lcr", "Least Cost Routing Module", dialplan_lcr_function, LCR_SYNTAX);
+ SWITCH_ADD_DIALPLAN(dp_interface, "lcr", lcr_dialplan_hunt);
+
+ /* indicate that the module should continue to be loaded */
+ return SWITCH_STATUS_SUCCESS;
+}
+
+SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_lcr_shutdown) {
+ return SWITCH_STATUS_SUCCESS;
+}
+
+/* For Emacs:
+ * Local Variables:
+ * mode:c
+ * indent-tabs-mode:t
+ * tab-width:4
+ * c-basic-offset:4
+ * End:
+ * For VIM:
+ * vim:set softtabstop=4 shiftwidth=4 tabstop=4 expandtab:
+ */
Added: freeswitch/trunk/scripts/contrib/intralanman/C/lcr/mod_lcr/mod_lcr.c.orig
==============================================================================
--- (empty file)
+++ freeswitch/trunk/scripts/contrib/intralanman/C/lcr/mod_lcr/mod_lcr.c.orig Fri Nov 21 11:01:57 2008
@@ -0,0 +1,539 @@
+/*
+ * 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>
+ * Portions created by the Initial Developer are Copyright (C)
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Raymond Chandler <intralanman(a)gmail.com>
+ *
+ * mod_lcr.c -- Least Cost Routing Module
+ *
+ */
+
+#include <switch.h>
+#include <switch_odbc.h>
+
+
+#define LCR_SYNTAX "lcr <digits>"
+
+/* SQL Query places */
+#define LCR_DIGITS_PLACE 0
+#define LCR_CARRIER_PLACE 1
+#define LCR_RATE_PLACE 2
+#define LCR_GATEWAY_PLACE 3
+#define LCR_IP_ADDRESS_PLACE 4
+#define LCR_PORT_PLACE 5
+#define LCR_LSTRIP_PLACE 6
+#define LCR_TSTRIP_PLACE 7
+#define LCR_PREFIX_PLACE 8
+#define LCR_SUFFIX_PLACE 9
+
+
+#define LCR_DIALSTRING_PLACE 3
+#define LCR_HEADERS_COUNT 4
+char headers[LCR_HEADERS_COUNT][32] = {
+ "Digit Match",
+ "Carrier",
+ "Rate",
+ "Dialstring",
+};
+
+struct odbc_obj {
+ switch_odbc_handle_t *handle;
+ SQLHSTMT stmt;
+ SQLCHAR *colbuf;
+ int32_t cblen;
+ SQLCHAR *code;
+ int32_t codelen;
+};
+
+struct lcr_obj {
+ char *carrier_name;
+ char *gateway_name;
+ char *term_host;
+ char *port;
+ char *digit_str;
+ char *prefix;
+ char *suffix;
+ char *dialstring;
+ float rate;
+ size_t lstrip;
+ size_t tstrip;
+ size_t digit_len;
+ struct lcr_obj *next;
+};
+
+struct max_obj {
+ size_t carrier_name;
+ size_t gateway_name;
+ size_t digit_str;
+ size_t rate;
+ size_t dialstring;
+};
+
+typedef struct odbc_obj odbc_obj_t;
+typedef odbc_obj_t *odbc_handle;
+
+typedef struct lcr_obj lcr_obj_t;
+typedef lcr_obj_t *lcr_route;
+
+typedef struct max_obj max_obj_t;
+typedef max_obj_t *max_len;
+
+struct callback_obj {
+ lcr_route head;
+ int matches;
+ char *lookup_number;
+};
+typedef struct callback_obj callback_t;
+
+static struct {
+ switch_memory_pool_t *pool;
+ char *dbname;
+ char *odbc_dsn;
+ switch_mutex_t *mutex;
+ switch_odbc_handle_t *master_odbc;
+ void *filler1;
+} globals;
+
+
+SWITCH_MODULE_LOAD_FUNCTION(mod_lcr_load);
+SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_lcr_shutdown);
+SWITCH_MODULE_DEFINITION(mod_lcr, mod_lcr_load, mod_lcr_shutdown, NULL);
+
+static char *get_bridge_data(const char *dialed_number, lcr_route cur_route) {
+ size_t lstrip;
+ size_t tstrip;
+ char *data = NULL;
+ char *destination_number = NULL;
+
+ destination_number = strdup(dialed_number);
+
+ tstrip = ((cur_route->digit_len - cur_route->tstrip) + 1);
+ lstrip = cur_route->lstrip;
+
+ if (strlen(destination_number) > tstrip && cur_route->tstrip > 0) {
+ destination_number[tstrip] = '\0';
+ }
+ if (strlen(destination_number) > lstrip && cur_route->lstrip > 0) {
+ destination_number += lstrip;
+ }
+
+ if (strlen(cur_route->gateway_name) > 0) {
+ data = switch_mprintf("sofia/gateway/%s/%s%s%s", cur_route->gateway_name
+ , cur_route->prefix, destination_number, cur_route->suffix
+ );
+ } else {
+ char port[8];
+ switch_snprintf(port, sizeof(port), ":%s", cur_route->port);
+ data = switch_mprintf("sofia/${use_profile}/%s@%s%s"
+ , destination_number, cur_route->term_host, (strlen(cur_route->port) > 0 ? port : "")
+ );
+ }
+
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Returning Dialstring %s\n", data);
+ switch_safe_free(destination_number);
+ return data;
+}
+
+void init_max_lens(max_len maxes) {
+ maxes->digit_str = (headers[LCR_DIGITS_PLACE] == NULL ? 0 : strlen(headers[LCR_DIGITS_PLACE]));
+ maxes->carrier_name = (headers[LCR_CARRIER_PLACE] == NULL ? 0 : strlen(headers[LCR_CARRIER_PLACE]));
+ maxes->gateway_name = (headers[LCR_GATEWAY_PLACE] == NULL ? 0 : strlen(headers[LCR_GATEWAY_PLACE]));
+ maxes->dialstring = (headers[LCR_DIALSTRING_PLACE] == NULL ? 0 : strlen(headers[LCR_DIALSTRING_PLACE]));
+ maxes->digit_str = (headers[LCR_DIGITS_PLACE] == NULL ? 0 : strlen(headers[LCR_DIGITS_PLACE]));
+ maxes->rate = 8;
+}
+
+switch_status_t process_max_lengths(max_obj_t *maxes, lcr_route routes, char *destination_number) {
+ lcr_route current = NULL;
+ init_max_lens(maxes);
+ if (routes == NULL ) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "no routes\n");
+ return SWITCH_STATUS_FALSE;
+ }
+ if (maxes == NULL ) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "no maxes\n");
+ return SWITCH_STATUS_FALSE;
+ }
+
+ if (routes != NULL && maxes != NULL) {
+ for (current = routes; current; current = current->next) {
+ size_t this_len;
+ if (current->gateway_name != NULL) {
+ this_len = strlen(current->gateway_name);
+ if (this_len > maxes->gateway_name) {
+ maxes->gateway_name = this_len;
+ }
+ }
+ if (current->carrier_name != NULL) {
+ this_len = strlen(current->carrier_name);
+ if (this_len > maxes->carrier_name) {
+ maxes->carrier_name = this_len;
+ }
+ }
+ if (current->dialstring != NULL) {
+ this_len = strlen(current->dialstring);
+ if (this_len > maxes->dialstring) {
+ maxes->dialstring = this_len;
+ }
+ }
+ if (current->digit_str != NULL) {
+ if (current->digit_len > maxes->digit_str) {
+ maxes->digit_str = current->digit_len;
+ }
+ }
+ }
+ }
+ return SWITCH_STATUS_SUCCESS;
+}
+
+static switch_bool_t lcr_execute_sql_callback(char *sql, switch_core_db_callback_func_t callback, void *pdata) {
+ if (globals.odbc_dsn) {
+ switch_odbc_handle_callback_exec(globals.master_odbc, sql, callback, pdata);
+ return SWITCH_TRUE;
+ } else {
+ return SWITCH_FALSE;
+ }
+}
+
+int route_add_callback(void *pArg, int argc, char **argv, char **columnNames) {
+ lcr_route additional = NULL;
+ lcr_route current = NULL;
+ callback_t *cbt = (callback_t *) pArg;
+
+ cbt->matches++;
+
+ switch_zmalloc(additional, sizeof(lcr_obj_t));
+
+ additional->digit_len = strlen(argv[LCR_DIGITS_PLACE]);
+ additional->digit_str = switch_safe_strdup(argv[LCR_DIGITS_PLACE]);
+ additional->suffix = switch_safe_strdup(argv[LCR_SUFFIX_PLACE]);
+ additional->prefix = switch_safe_strdup(argv[LCR_PREFIX_PLACE]);
+ additional->carrier_name = switch_safe_strdup(argv[LCR_CARRIER_PLACE]);
+ additional->rate = (float)atof(argv[LCR_RATE_PLACE]);
+ additional->gateway_name = switch_safe_strdup(argv[LCR_GATEWAY_PLACE]);
+ additional->term_host = switch_safe_strdup(argv[LCR_IP_ADDRESS_PLACE]);
+ additional->port = switch_safe_strdup(argv[LCR_PORT_PLACE]);
+ additional->lstrip = atoi(argv[LCR_LSTRIP_PLACE]);
+ additional->tstrip = atoi(argv[LCR_TSTRIP_PLACE]);
+ additional->dialstring = get_bridge_data(cbt->lookup_number, additional);
+
+ if (cbt->head != NULL) {
+ for (current = cbt->head; current; current = current->next) {
+
+ if (switch_strlen_zero(additional->gateway_name) && switch_strlen_zero(additional->term_host) && switch_strlen_zero(additional->port) ) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING
+ , "WTF?!? There's no way to dial this Gateway: %s IP:Port %s:%s\n"
+ , additional->gateway_name, additional->term_host, additional->port
+ );
+ break;
+ }
+
+ if (!strcmp(current->gateway_name, additional->gateway_name)) {
+ if (!strcmp(current->term_host, additional->term_host) && !strcmp(current->port, additional->port)) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG
+ , "Ignoring Duplicate route for termination point (%s:%s)\n"
+ , additional->term_host, additional->port
+ );
+ switch_safe_free(additional);
+ break;
+ }
+ }
+
+ if (current->next == NULL) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "adding route to end of list\n");
+ current->next = additional;
+ break;
+ }
+
+ }
+ } else {
+ additional->next = cbt->head;
+ cbt->head = additional;
+ }
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+switch_status_t lcr_do_lookup(char *digits, callback_t *cb_struct) {
+ /* instantiate the object/struct we defined earlier */
+ switch_stream_handle_t sql_stream = { 0 };
+ size_t n, digit_len = strlen(digits);
+ char *digits_copy;
+
+ if (switch_strlen_zero(digits)) {
+ return SWITCH_FALSE;
+ }
+
+ digits_copy = strdup(digits);
+
+ SWITCH_STANDARD_STREAM(sql_stream);
+
+ /* set up the query to be executed */
+ sql_stream.write_function(&sql_stream,
+ "SELECT l.digits, c.Carrier_Name, l.rate, cg.gateway, cg.term_host, cg.port, l.lead_strip, l.trail_strip, l.prefix, l.suffix "
+ );
+ sql_stream.write_function(&sql_stream, "FROM lcr l JOIN carriers c ON l.carrier_id=c.id JOIN carrier_gateway cg ON c.id=cg.carrier_id ");
+ for (n = digit_len; n > 0; n--) {
+ digits_copy[n] = '\0';
+ sql_stream.write_function(&sql_stream, "%s digits='%s' ", (n==digit_len ? "WHERE" : "OR"), digits_copy);
+ }
+ sql_stream.write_function(&sql_stream, "ORDER BY digits DESC, rate;");
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "%s\n", (char *)sql_stream.data);
+ lcr_execute_sql_callback((char *)sql_stream.data, route_add_callback, cb_struct);
+ switch_safe_free(sql_stream.data);
+ return SWITCH_STATUS_SUCCESS;
+}
+
+static switch_status_t lcr_load_config() {
+ char *cf = "lcr.conf";
+ switch_xml_t cfg, xml, settings, param;
+ switch_status_t status = SWITCH_STATUS_SUCCESS;
+ char *odbc_user = NULL;
+ char *odbc_pass = NULL;
+ if (!(xml = switch_xml_open_cfg(cf, &cfg, NULL))) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "open of %s failed\n", cf);
+ return SWITCH_STATUS_TERM;
+ }
+ if ((settings = switch_xml_child(cfg, "settings"))) {
+ for (param = switch_xml_child(settings, "param"); param; param = param->next) {
+ char *var = NULL;
+ char *val = NULL;
+ var = (char *) switch_xml_attr_soft(param, "name");
+ val = (char *) switch_xml_attr_soft(param, "value");
+ if (!strcasecmp(var, "odbc-dsn") && !switch_strlen_zero(val)) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "odbc_dsn is %s\n", val);
+ globals.odbc_dsn = switch_core_strdup(globals.pool, val);
+ if ((odbc_user = strchr(globals.odbc_dsn, ':'))) {
+ *odbc_user++ = '\0';
+ if ((odbc_pass = strchr(odbc_user, ':'))) {
+ *odbc_pass++ = '\0';
+ }
+ }
+ }
+ }
+ }
+ if (globals.odbc_dsn) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO
+ , "dsn is \"%s\", user is \"%s\", and password is \"%s\"\n"
+ , globals.odbc_dsn, odbc_user, odbc_pass
+ );
+ if (!(globals.master_odbc = switch_odbc_handle_new(globals.odbc_dsn, odbc_user, odbc_pass))) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Cannot Open ODBC Database!\n");
+ status = SWITCH_STATUS_FALSE;
+ goto done;
+ }
+ if (switch_odbc_handle_connect(globals.master_odbc) != SWITCH_ODBC_SUCCESS) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Cannot Open ODBC Database!\n");
+ status = SWITCH_STATUS_FALSE;
+ goto done;
+ }
+ }
+ done:
+ switch_xml_free(xml);
+ return status;
+}
+
+static void destroy_list(lcr_route *head) {
+ lcr_route cur = NULL, top = *head;
+ while (top) {
+ cur = top;
+ top = top->next;
+ switch_safe_free(cur->digit_str);
+ switch_safe_free(cur->suffix);
+ switch_safe_free(cur->prefix);
+ switch_safe_free(cur->carrier_name);
+ switch_safe_free(cur->gateway_name);
+ switch_safe_free(cur);
+ }
+ *head = NULL;
+}
+
+SWITCH_STANDARD_DIALPLAN(lcr_dialplan_hunt) {
+ switch_caller_extension_t *extension = NULL;
+ switch_channel_t *channel = switch_core_session_get_channel(session);
+ callback_t routes = { 0 };
+ lcr_route cur_route = { 0 };
+ char *bridge_data = NULL;;
+
+ if (!caller_profile) {
+ caller_profile = switch_channel_get_caller_profile(channel);
+ }
+
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "LCR Lookup on %s\n", caller_profile->destination_number);
+ routes.lookup_number = caller_profile->destination_number;
+ if (lcr_do_lookup(caller_profile->destination_number, &routes) == SWITCH_STATUS_SUCCESS) {
+ if ((extension = switch_caller_extension_new(session, caller_profile->destination_number, caller_profile->destination_number)) == 0) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "memory error!\n");
+ destroy_list(&routes.head);
+ return NULL;
+ }
+
+ switch_channel_set_variable(channel, SWITCH_CONTINUE_ON_FAILURE_VARIABLE, "true");
+ switch_channel_set_variable(channel, SWITCH_HANGUP_AFTER_BRIDGE_VARIABLE, "true");
+ for (cur_route = routes.head; cur_route; cur_route = cur_route->next) {
+ //bridge_data = get_bridge_data(caller_profile->destination_number, cur_route);
+ switch_caller_extension_add_application(session, extension, "bridge", cur_route->dialstring);
+ switch_safe_free(bridge_data);
+ }
+ destroy_list(&routes.head);
+ } else {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "LCR lookup failed for %s\n", caller_profile->destination_number);
+ }
+ switch_safe_free(bridge_data);
+
+ return extension;
+}
+
+void str_repeat(size_t how_many, char *what, switch_stream_handle_t *str_stream) {
+ size_t i;
+ //switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "repeating %d of '%s'\n", how_many, what);
+ if (how_many > 0) {
+ for (i=0; i<how_many; i++) {
+ str_stream->write_function(str_stream, "%s", what);
+ }
+ }
+}
+
+SWITCH_STANDARD_API(dialplan_lcr_function) {
+ char *argv[4] = { 0 };
+ int argc;
+ char *mydata = NULL;
+ char *dialstring = NULL;
+ char *destination_number = NULL;
+ lcr_route current = NULL;
+ max_obj_t maximum_lengths = { 0 };
+ callback_t cb_struct = { 0 };
+ //switch_malloc(maximum_lengths, sizeof(max_obj_t));
+
+ if (switch_strlen_zero(cmd)) {
+ goto usage;
+ }
+ mydata = switch_safe_strdup(cmd);
+ if ((argc = switch_separate_string(mydata, ' ', argv, (sizeof(argv) / sizeof(argv[0]))))) {
+ destination_number = strdup(argv[0]);
+ cb_struct.lookup_number = destination_number;
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO
+ , "data passed to lcr is [%s]\n", cmd
+ );
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO
+ , "lcr lookup returned [%d]\n"
+ , lcr_do_lookup(destination_number, &cb_struct)
+ );
+ if (cb_struct.head != NULL) {
+ process_max_lengths(&maximum_lengths, cb_struct.head, destination_number);
+
+ stream->write_function(stream, " | %s", headers[LCR_DIGITS_PLACE]);
+ str_repeat((maximum_lengths.digit_str - strlen(headers[LCR_DIGITS_PLACE])), " ", stream);
+
+ stream->write_function(stream, " | %s", headers[LCR_CARRIER_PLACE]);
+ str_repeat((maximum_lengths.carrier_name - strlen(headers[LCR_CARRIER_PLACE])), " ", stream);
+
+ stream->write_function(stream, " | %s", headers[LCR_RATE_PLACE]);
+ str_repeat((maximum_lengths.rate - strlen(headers[LCR_RATE_PLACE])), " ", stream);
+
+ stream->write_function(stream, " | %s", headers[LCR_DIALSTRING_PLACE]);
+ str_repeat((maximum_lengths.dialstring - strlen(headers[LCR_DIALSTRING_PLACE])), " ", stream);
+
+ stream->write_function(stream, " |\n");
+
+
+ current = cb_struct.head;
+ while (current) {
+ char srate[10];
+ dialstring = get_bridge_data(destination_number, current);
+ switch_snprintf(srate, sizeof(srate), "%0.5f", current->rate);
+
+
+ stream->write_function(stream, " | %s", current->digit_str);
+ str_repeat((maximum_lengths.digit_str - current->digit_len), " ", stream);
+
+ stream->write_function(stream, " | %s", current->carrier_name );
+ str_repeat((maximum_lengths.carrier_name - strlen(current->carrier_name)), " ", stream);
+
+ stream->write_function(stream, " | %s", srate );
+ str_repeat((maximum_lengths.rate - strlen(srate)), " ", stream);
+
+ stream->write_function(stream, " | %s", dialstring);
+ str_repeat((maximum_lengths.dialstring - strlen(dialstring)), " ", stream);
+
+ stream->write_function(stream, " |\n");
+
+ switch_safe_free(dialstring);
+ current = current->next;
+
+ }
+
+ destroy_list(&cb_struct.head);
+ switch_safe_free(dialstring);
+ } else {
+ stream->write_function(stream, "No Routes To Display\n");
+ }
+ }
+
+ switch_safe_free(mydata);
+ return SWITCH_STATUS_SUCCESS;
+ usage:
+ stream->write_function(stream, "USAGE: %s\n", LCR_SYNTAX);
+ return SWITCH_STATUS_SUCCESS;
+}
+
+SWITCH_MODULE_LOAD_FUNCTION(mod_lcr_load) {
+ switch_api_interface_t *dialplan_lcr_api_interface;
+ switch_dialplan_interface_t *dp_interface;
+
+ *module_interface = switch_loadable_module_create_module_interface(pool, modname);
+#ifndef SWITCH_HAVE_ODBC
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "You must have ODBC support in FreeSWITCH to use this module\n");
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "\t./configure --enable-core-odbc-support\n");
+ return SWITCH_STATUS_FALSE;
+#endif
+ globals.pool = pool;
+ if (lcr_load_config() != SWITCH_STATUS_SUCCESS) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Unable to load lcr config file\n");
+ return SWITCH_STATUS_FALSE;
+ }
+ if (switch_mutex_init(&globals.mutex, SWITCH_MUTEX_NESTED, globals.pool) != SWITCH_STATUS_SUCCESS) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "failed to initialize mutex\n");
+ }
+ SWITCH_ADD_API(dialplan_lcr_api_interface, "lcr", "Least Cost Routing Module", dialplan_lcr_function, LCR_SYNTAX);
+ SWITCH_ADD_DIALPLAN(dp_interface, "lcr", lcr_dialplan_hunt);
+
+ /* indicate that the module should continue to be loaded */
+ return SWITCH_STATUS_SUCCESS;
+}
+
+SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_lcr_shutdown) {
+ return SWITCH_STATUS_SUCCESS;
+}
+
+/* For Emacs:
+ * Local Variables:
+ * mode:c
+ * indent-tabs-mode:t
+ * tab-width:4
+ * c-basic-offset:4
+ * End:
+ * For VIM:
+ * vim:set softtabstop=4 shiftwidth=4 tabstop=4 expandtab:
+ */
Added: freeswitch/trunk/scripts/contrib/intralanman/C/lcr/mod_lcr/mod_lcr.c.rej.orig
==============================================================================
--- (empty file)
+++ freeswitch/trunk/scripts/contrib/intralanman/C/lcr/mod_lcr/mod_lcr.c.rej.orig Fri Nov 21 11:01:57 2008
@@ -0,0 +1,450 @@
+***************
+*** 24,29 ****
+ * Contributor(s):
+ *
+ * Raymond Chandler <intralanman(a)gmail.com>
+ *
+ * mod_lcr.c -- Least Cost Routing Module
+ *
+--- 24,30 ----
+ * Contributor(s):
+ *
+ * Raymond Chandler <intralanman(a)gmail.com>
++ * Rupa Schomaker <rupa(a)rupa.com>
+ *
+ * mod_lcr.c -- Least Cost Routing Module
+ *
+***************
+*** 39,51 ****
+ #define LCR_DIGITS_PLACE 0
+ #define LCR_CARRIER_PLACE 1
+ #define LCR_RATE_PLACE 2
+- #define LCR_GATEWAY_PLACE 3
+- #define LCR_IP_ADDRESS_PLACE 4
+- #define LCR_PORT_PLACE 5
+- #define LCR_LSTRIP_PLACE 6
+- #define LCR_TSTRIP_PLACE 7
+- #define LCR_PREFIX_PLACE 8
+- #define LCR_SUFFIX_PLACE 9
+
+
+ #define LCR_DIALSTRING_PLACE 3
+--- 40,51 ----
+ #define LCR_DIGITS_PLACE 0
+ #define LCR_CARRIER_PLACE 1
+ #define LCR_RATE_PLACE 2
++ #define LCR_GW_PREFIX_PLACE 3
++ #define LCR_GW_SUFFIX_PLACE 4
++ #define LCR_LSTRIP_PLACE 5
++ #define LCR_TSTRIP_PLACE 6
++ #define LCR_PREFIX_PLACE 7
++ #define LCR_SUFFIX_PLACE 8
+
+
+ #define LCR_DIALSTRING_PLACE 3
+***************
+*** 68,81 ****
+
+ struct lcr_obj {
+ char *carrier_name;
+- char *gateway_name;
+- char *term_host;
+- char *port;
+ char *digit_str;
+ char *prefix;
+ char *suffix;
+ char *dialstring;
+ float rate;
+ size_t lstrip;
+ size_t tstrip;
+ size_t digit_len;
+--- 68,81 ----
+
+ struct lcr_obj {
+ char *carrier_name;
++ char *gw_prefix;
++ char *gw_suffix;
+ char *digit_str;
+ char *prefix;
+ char *suffix;
+ char *dialstring;
+ float rate;
++ char *rate_str;
+ size_t lstrip;
+ size_t tstrip;
+ size_t digit_len;
+***************
+*** 84,90 ****
+
+ struct max_obj {
+ size_t carrier_name;
+- size_t gateway_name;
+ size_t digit_str;
+ size_t rate;
+ size_t dialstring;
+--- 84,89 ----
+
+ struct max_obj {
+ size_t carrier_name;
+ size_t digit_str;
+ size_t rate;
+ size_t dialstring;
+***************
+*** 138,155 ****
+ destination_number += lstrip;
+ }
+
+- if (strlen(cur_route->gateway_name) > 0) {
+- data = switch_mprintf("sofia/gateway/%s/%s%s%s", cur_route->gateway_name
+- , cur_route->prefix, destination_number, cur_route->suffix
+- );
+- } else {
+- char port[8];
+- switch_snprintf(port, sizeof(port), ":%s", cur_route->port);
+- data = switch_mprintf("sofia/${use_profile}/%s@%s%s"
+- , destination_number, cur_route->term_host, (strlen(cur_route->port) > 0 ? port : "")
+- );
+- }
+-
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Returning Dialstring %s\n", data);
+ switch_safe_free(destination_number);
+ return data;
+--- 137,145 ----
+ destination_number += lstrip;
+ }
+
++ data = switch_mprintf("%s%s%s%s%s", cur_route->gw_prefix, cur_route->prefix
++ , destination_number, cur_route->suffix, cur_route->gw_suffix);
++
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Returning Dialstring %s\n", data);
+ switch_safe_free(destination_number);
+ return data;
+***************
+*** 158,164 ****
+ void init_max_lens(max_len maxes) {
+ maxes->digit_str = (headers[LCR_DIGITS_PLACE] == NULL ? 0 : strlen(headers[LCR_DIGITS_PLACE]));
+ maxes->carrier_name = (headers[LCR_CARRIER_PLACE] == NULL ? 0 : strlen(headers[LCR_CARRIER_PLACE]));
+- maxes->gateway_name = (headers[LCR_GATEWAY_PLACE] == NULL ? 0 : strlen(headers[LCR_GATEWAY_PLACE]));
+ maxes->dialstring = (headers[LCR_DIALSTRING_PLACE] == NULL ? 0 : strlen(headers[LCR_DIALSTRING_PLACE]));
+ maxes->digit_str = (headers[LCR_DIGITS_PLACE] == NULL ? 0 : strlen(headers[LCR_DIGITS_PLACE]));
+ maxes->rate = 8;
+--- 148,153 ----
+ void init_max_lens(max_len maxes) {
+ maxes->digit_str = (headers[LCR_DIGITS_PLACE] == NULL ? 0 : strlen(headers[LCR_DIGITS_PLACE]));
+ maxes->carrier_name = (headers[LCR_CARRIER_PLACE] == NULL ? 0 : strlen(headers[LCR_CARRIER_PLACE]));
+ maxes->dialstring = (headers[LCR_DIALSTRING_PLACE] == NULL ? 0 : strlen(headers[LCR_DIALSTRING_PLACE]));
+ maxes->digit_str = (headers[LCR_DIGITS_PLACE] == NULL ? 0 : strlen(headers[LCR_DIGITS_PLACE]));
+ maxes->rate = 8;
+***************
+*** 179,190 ****
+ if (routes != NULL && maxes != NULL) {
+ for (current = routes; current; current = current->next) {
+ size_t this_len;
+- if (current->gateway_name != NULL) {
+- this_len = strlen(current->gateway_name);
+- if (this_len > maxes->gateway_name) {
+- maxes->gateway_name = this_len;
+- }
+- }
+ if (current->carrier_name != NULL) {
+ this_len = strlen(current->carrier_name);
+ if (this_len > maxes->carrier_name) {
+--- 168,173 ----
+ if (routes != NULL && maxes != NULL) {
+ for (current = routes; current; current = current->next) {
+ size_t this_len;
+ if (current->carrier_name != NULL) {
+ this_len = strlen(current->carrier_name);
+ if (this_len > maxes->carrier_name) {
+***************
+*** 202,207 ****
+ maxes->digit_str = current->digit_len;
+ }
+ }
+ }
+ }
+ return SWITCH_STATUS_SUCCESS;
+--- 185,196 ----
+ maxes->digit_str = current->digit_len;
+ }
+ }
++ if (current->rate_str != NULL) {
++ this_len = strlen(current->rate_str);
++ if (this_len > maxes->rate) {
++ maxes->rate = this_len;
++ }
++ }
+ }
+ }
+ return SWITCH_STATUS_SUCCESS;
+***************
+*** 220,225 ****
+ lcr_route additional = NULL;
+ lcr_route current = NULL;
+ callback_t *cbt = (callback_t *) pArg;
+
+ cbt->matches++;
+
+--- 209,215 ----
+ lcr_route additional = NULL;
+ lcr_route current = NULL;
+ callback_t *cbt = (callback_t *) pArg;
++ char srate[10];
+
+ cbt->matches++;
+
+***************
+*** 231,239 ****
+ additional->prefix = switch_safe_strdup(argv[LCR_PREFIX_PLACE]);
+ additional->carrier_name = switch_safe_strdup(argv[LCR_CARRIER_PLACE]);
+ additional->rate = (float)atof(argv[LCR_RATE_PLACE]);
+- additional->gateway_name = switch_safe_strdup(argv[LCR_GATEWAY_PLACE]);
+- additional->term_host = switch_safe_strdup(argv[LCR_IP_ADDRESS_PLACE]);
+- additional->port = switch_safe_strdup(argv[LCR_PORT_PLACE]);
+ additional->lstrip = atoi(argv[LCR_LSTRIP_PLACE]);
+ additional->tstrip = atoi(argv[LCR_TSTRIP_PLACE]);
+ additional->dialstring = get_bridge_data(cbt->lookup_number, additional);
+--- 221,230 ----
+ additional->prefix = switch_safe_strdup(argv[LCR_PREFIX_PLACE]);
+ additional->carrier_name = switch_safe_strdup(argv[LCR_CARRIER_PLACE]);
+ additional->rate = (float)atof(argv[LCR_RATE_PLACE]);
++ switch_snprintf(srate, sizeof(srate), "%0.5f", additional->rate);
++ additional->rate_str = switch_safe_strdup(srate);
++ additional->gw_prefix = switch_safe_strdup(argv[LCR_GW_PREFIX_PLACE]);
++ additional->gw_suffix = switch_safe_strdup(argv[LCR_GW_SUFFIX_PLACE]);
+ additional->lstrip = atoi(argv[LCR_LSTRIP_PLACE]);
+ additional->tstrip = atoi(argv[LCR_TSTRIP_PLACE]);
+ additional->dialstring = get_bridge_data(cbt->lookup_number, additional);
+***************
+*** 241,263 ****
+ if (cbt->head != NULL) {
+ for (current = cbt->head; current; current = current->next) {
+
+- if (switch_strlen_zero(additional->gateway_name) && switch_strlen_zero(additional->term_host) && switch_strlen_zero(additional->port) ) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING
+- , "WTF?!? There's no way to dial this Gateway: %s IP:Port %s:%s\n"
+- , additional->gateway_name, additional->term_host, additional->port
+- );
+ break;
+ }
+
+- if (!strcmp(current->gateway_name, additional->gateway_name)) {
+- if (!strcmp(current->term_host, additional->term_host) && !strcmp(current->port, additional->port)) {
+- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG
+- , "Ignoring Duplicate route for termination point (%s:%s)\n"
+- , additional->term_host, additional->port
+- );
+- switch_safe_free(additional);
+- break;
+- }
+ }
+
+ if (current->next == NULL) {
+--- 232,252 ----
+ if (cbt->head != NULL) {
+ for (current = cbt->head; current; current = current->next) {
+
++ if (switch_strlen_zero(additional->gw_prefix) && switch_strlen_zero(additional->gw_suffix) ) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING
++ , "WTF?!? There's no way to dial this Gateway: Carrier: \"%s\" Prefix: \"%s\", Suffix \"%s\"\n"
++ , additional->carrier_name
++ , additional->gw_prefix, additional->gw_suffix);
+ break;
+ }
+
++ if (!strcmp(current->gw_prefix, additional->gw_prefix) && !strcmp(current->gw_suffix, additional->gw_suffix)) {
++ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG
++ , "Ignoring Duplicate route for termination point (%s:%s)\n"
++ , additional->gw_prefix, additional->gw_suffix
++ );
++ switch_safe_free(additional);
++ break;
+ }
+
+ if (current->next == NULL) {
+***************
+*** 291,297 ****
+
+ /* set up the query to be executed */
+ sql_stream.write_function(&sql_stream,
+- "SELECT l.digits, c.Carrier_Name, l.rate, cg.gateway, cg.term_host, cg.port, l.lead_strip, l.trail_strip, l.prefix, l.suffix "
+ );
+ sql_stream.write_function(&sql_stream, "FROM lcr l JOIN carriers c ON l.carrier_id=c.id JOIN carrier_gateway cg ON c.id=cg.carrier_id ");
+ for (n = digit_len; n > 0; n--) {
+--- 280,286 ----
+
+ /* set up the query to be executed */
+ sql_stream.write_function(&sql_stream,
++ "SELECT l.digits, c.carrier_name, l.rate, cg.prefix AS gw_prefix, cg.suffix AS gw_suffix, l.lead_strip, l.trail_strip, l.prefix, l.suffix "
+ );
+ sql_stream.write_function(&sql_stream, "FROM lcr l JOIN carriers c ON l.carrier_id=c.id JOIN carrier_gateway cg ON c.id=cg.carrier_id ");
+ for (n = digit_len; n > 0; n--) {
+***************
+*** 363,369 ****
+ switch_safe_free(cur->suffix);
+ switch_safe_free(cur->prefix);
+ switch_safe_free(cur->carrier_name);
+- switch_safe_free(cur->gateway_name);
+ switch_safe_free(cur);
+ }
+ *head = NULL;
+--- 352,360 ----
+ switch_safe_free(cur->suffix);
+ switch_safe_free(cur->prefix);
+ switch_safe_free(cur->carrier_name);
++ switch_safe_free(cur->gw_prefix);
++ switch_safe_free(cur->gw_suffix);
++ switch_safe_free(cur->rate_str);
+ switch_safe_free(cur);
+ }
+ *head = NULL;
+***************
+*** 407,420 ****
+
+ void str_repeat(size_t how_many, char *what, switch_stream_handle_t *str_stream) {
+ size_t i;
+ //switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "repeating %d of '%s'\n", how_many, what);
+ if (how_many > 0) {
+- for (i=0; i<how_many; i++) {
+ str_stream->write_function(str_stream, "%s", what);
+ }
+ }
+ }
+
+ SWITCH_STANDARD_API(dialplan_lcr_function) {
+ char *argv[4] = { 0 };
+ int argc;
+--- 398,459 ----
+
+ void str_repeat(size_t how_many, char *what, switch_stream_handle_t *str_stream) {
+ size_t i;
++ const size_t HOW_MANY_MAX = 100;
+ //switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "repeating %d of '%s'\n", how_many, what);
+ if (how_many > 0) {
++ for (i=0; i<how_many && i<HOW_MANY_MAX; i++) {
+ str_stream->write_function(str_stream, "%s", what);
+ }
+ }
+ }
+
++ SWITCH_STANDARD_APP(lcr_app_function)
++ {
++ int argc = 0;
++ char *argv[4] = { 0 };
++ char *mydata = NULL;
++ char *dest = NULL;
++ char rbuf[1024] = "";
++ char vbuf[1024] = "";
++ char *rbp = rbuf;
++ switch_size_t l = 0, rbl = sizeof(rbuf);
++ uint32_t cnt = 1;
++ switch_channel_t *channel = switch_core_session_get_channel(session);
++ char *last_delim = "|";
++ callback_t routes = { 0 };
++ lcr_route cur_route = { 0 };
++
++ if (!(mydata = switch_core_session_strdup(session, data))) {
++ return;
++ }
++
++ if ((argc = switch_separate_string(mydata, ' ', argv, (sizeof(argv) / sizeof(argv[0]))))) {
++ dest = argv[0];
++
++ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "LCR Lookup on %s\n", dest);
++ routes.lookup_number = dest;
++ if (lcr_do_lookup(dest, &routes) == SWITCH_STATUS_SUCCESS) {
++ for (cur_route = routes.head; cur_route; cur_route = cur_route->next) {
++ switch_snprintf(vbuf, sizeof(vbuf), "lcr_route_%d", cnt++);
++ switch_channel_set_variable(channel, vbuf, cur_route->dialstring);
++ switch_snprintf(rbp, rbl, "%s|", cur_route->dialstring);
++ last_delim = end_of_p(rbp);
++ l = strlen(cur_route->dialstring) + 1;
++ rbp += l;
++ rbl -= l;
++ }
++ switch_snprintf(vbuf, sizeof(vbuf), "%d", cnt-1);
++ switch_channel_set_variable(channel, "lcr_route_count", vbuf);
++ *(rbuf + strlen(rbuf) - 1) = '\0';
++ switch_channel_set_variable(channel, "lcr_auto_route", rbuf);
++ destroy_list(&routes.head);
++ } else {
++ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "LCR lookup failed for %s\n", dest);
++ }
++ }
++ }
++
++
+ SWITCH_STANDARD_API(dialplan_lcr_function) {
+ char *argv[4] = { 0 };
+ int argc;
+***************
+*** 460,468 ****
+
+ current = cb_struct.head;
+ while (current) {
+- char srate[10];
+ dialstring = get_bridge_data(destination_number, current);
+- switch_snprintf(srate, sizeof(srate), "%0.5f", current->rate);
+
+
+ stream->write_function(stream, " | %s", current->digit_str);
+--- 499,505 ----
+
+ current = cb_struct.head;
+ while (current) {
+ dialstring = get_bridge_data(destination_number, current);
+
+
+ stream->write_function(stream, " | %s", current->digit_str);
+***************
+*** 471,478 ****
+ stream->write_function(stream, " | %s", current->carrier_name );
+ str_repeat((maximum_lengths.carrier_name - strlen(current->carrier_name)), " ", stream);
+
+- stream->write_function(stream, " | %s", srate );
+- str_repeat((maximum_lengths.rate - strlen(srate)), " ", stream);
+
+ stream->write_function(stream, " | %s", dialstring);
+ str_repeat((maximum_lengths.dialstring - strlen(dialstring)), " ", stream);
+--- 508,515 ----
+ stream->write_function(stream, " | %s", current->carrier_name );
+ str_repeat((maximum_lengths.carrier_name - strlen(current->carrier_name)), " ", stream);
+
++ stream->write_function(stream, " | %s", current->rate_str );
++ str_repeat((maximum_lengths.rate - strlen(current->rate_str)), " ", stream);
+
+ stream->write_function(stream, " | %s", dialstring);
+ str_repeat((maximum_lengths.dialstring - strlen(dialstring)), " ", stream);
+***************
+*** 500,505 ****
+
+ SWITCH_MODULE_LOAD_FUNCTION(mod_lcr_load) {
+ switch_api_interface_t *dialplan_lcr_api_interface;
+ switch_dialplan_interface_t *dp_interface;
+
+ *module_interface = switch_loadable_module_create_module_interface(pool, modname);
+--- 537,543 ----
+
+ SWITCH_MODULE_LOAD_FUNCTION(mod_lcr_load) {
+ switch_api_interface_t *dialplan_lcr_api_interface;
++ switch_application_interface_t *app_interface;
+ switch_dialplan_interface_t *dp_interface;
+
+ *module_interface = switch_loadable_module_create_module_interface(pool, modname);
+***************
+*** 517,522 ****
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "failed to initialize mutex\n");
+ }
+ SWITCH_ADD_API(dialplan_lcr_api_interface, "lcr", "Least Cost Routing Module", dialplan_lcr_function, LCR_SYNTAX);
+ SWITCH_ADD_DIALPLAN(dp_interface, "lcr", lcr_dialplan_hunt);
+
+ /* indicate that the module should continue to be loaded */
+--- 555,562 ----
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "failed to initialize mutex\n");
+ }
+ SWITCH_ADD_API(dialplan_lcr_api_interface, "lcr", "Least Cost Routing Module", dialplan_lcr_function, LCR_SYNTAX);
++ SWITCH_ADD_APP(app_interface, "lcr", "Perform an LCR lookup", "Perform an LCR lookup", lcr_app_function, "<number>",
++ SAF_SUPPORT_NOMEDIA);
+ SWITCH_ADD_DIALPLAN(dp_interface, "lcr", lcr_dialplan_hunt);
+
+ /* indicate that the module should continue to be loaded */
1
0
Author: anthm
Date: Fri Nov 21 10:55:17 2008
New Revision: 10494
Log:
fix issue where pid file is accidentally truncated (part2)
Modified:
freeswitch/trunk/src/switch.c
Modified: freeswitch/trunk/src/switch.c
==============================================================================
--- freeswitch/trunk/src/switch.c (original)
+++ freeswitch/trunk/src/switch.c Fri Nov 21 10:55:17 2008
@@ -610,15 +610,13 @@
pid_path,
SWITCH_FOPEN_READ,
SWITCH_FPROT_UREAD | SWITCH_FPROT_UWRITE,
- pool) != SWITCH_STATUS_SUCCESS) {
- fprintf(stderr, "Cannot open pid file %s.\n", pid_path);
- return 255;
+ pool) == SWITCH_STATUS_SUCCESS) {
+
+ old_pid_len = sizeof(old_pid_buffer);
+ switch_file_read(fd, old_pid_buffer, &old_pid_len);
+ switch_file_close(fd);
}
- old_pid_len = sizeof(old_pid_buffer);
- switch_file_read(fd, old_pid_buffer, &old_pid_len);
- switch_file_close(fd);
-
if (switch_file_open(&fd,
pid_path,
SWITCH_FOPEN_WRITE | SWITCH_FOPEN_CREATE | SWITCH_FOPEN_TRUNCATE,
@@ -631,7 +629,9 @@
if (switch_file_lock(fd, SWITCH_FLOCK_EXCLUSIVE | SWITCH_FLOCK_NONBLOCK) != SWITCH_STATUS_SUCCESS) {
fprintf(stderr, "Cannot lock pid file %s.\n", pid_path);
old_pid_len = strlen(old_pid_buffer);
- switch_file_write(fd, old_pid_buffer, &old_pid_len);
+ if (strlen(old_pid_buffer)) {
+ switch_file_write(fd, old_pid_buffer, &old_pid_len);
+ }
return 255;
}
1
0
Author: anthm
Date: Fri Nov 21 10:52:22 2008
New Revision: 10493
Log:
fix issue where pid file is accidentally truncated
Modified:
freeswitch/trunk/src/switch.c
Modified: freeswitch/trunk/src/switch.c
==============================================================================
--- freeswitch/trunk/src/switch.c (original)
+++ freeswitch/trunk/src/switch.c Fri Nov 21 10:52:22 2008
@@ -253,7 +253,8 @@
{
char pid_path[256] = ""; /* full path to the pid file */
char pid_buffer[32] = ""; /* pid string */
- switch_size_t pid_len;
+ char old_pid_buffer[32] = ""; /* pid string */
+ switch_size_t pid_len, old_pid_len;
const char *err = NULL; /* error value for return from freeswitch initialization */
#ifndef WIN32
int nf = 0; /* TRUE if we are running in nofork mode */
@@ -603,17 +604,34 @@
pid_len = strlen(pid_buffer);
apr_pool_create(&pool, NULL);
+
+
if (switch_file_open(&fd,
- pid_path,
- SWITCH_FOPEN_WRITE | SWITCH_FOPEN_CREATE | SWITCH_FOPEN_TRUNCATE,
- SWITCH_FPROT_UREAD | SWITCH_FPROT_UWRITE,
- pool) != SWITCH_STATUS_SUCCESS) {
- fprintf(stderr, "Cannot open pid file %s.\n", pid_path);
- return 255;
+ pid_path,
+ SWITCH_FOPEN_READ,
+ SWITCH_FPROT_UREAD | SWITCH_FPROT_UWRITE,
+ pool) != SWITCH_STATUS_SUCCESS) {
+ fprintf(stderr, "Cannot open pid file %s.\n", pid_path);
+ return 255;
+ }
+
+ old_pid_len = sizeof(old_pid_buffer);
+ switch_file_read(fd, old_pid_buffer, &old_pid_len);
+ switch_file_close(fd);
+
+ if (switch_file_open(&fd,
+ pid_path,
+ SWITCH_FOPEN_WRITE | SWITCH_FOPEN_CREATE | SWITCH_FOPEN_TRUNCATE,
+ SWITCH_FPROT_UREAD | SWITCH_FPROT_UWRITE,
+ pool) != SWITCH_STATUS_SUCCESS) {
+ fprintf(stderr, "Cannot open pid file %s.\n", pid_path);
+ return 255;
}
if (switch_file_lock(fd, SWITCH_FLOCK_EXCLUSIVE | SWITCH_FLOCK_NONBLOCK) != SWITCH_STATUS_SUCCESS) {
fprintf(stderr, "Cannot lock pid file %s.\n", pid_path);
+ old_pid_len = strlen(old_pid_buffer);
+ switch_file_write(fd, old_pid_buffer, &old_pid_len);
return 255;
}
1
0
Author: gmaruzz
Date: Fri Nov 21 10:46:42 2008
New Revision: 10492
Log:
skypiax: config files
Modified:
freeswitch/branches/gmaruzz/stuff/skypiax.conf.xml
Modified: freeswitch/branches/gmaruzz/stuff/skypiax.conf.xml
==============================================================================
--- freeswitch/branches/gmaruzz/stuff/skypiax.conf.xml (original)
+++ freeswitch/branches/gmaruzz/stuff/skypiax.conf.xml Fri Nov 21 10:46:42 2008
@@ -1,5 +1,5 @@
<configuration name="skypiax.conf" description="Skypiax Configuration">
- <settings>
+ <global_settings>
<param name="debug" value="8"/>
<param name="port" value="4569"/>
<param name="ip" value="127.0.0.1"/>
@@ -8,10 +8,10 @@
<param name="codec-prefs" value="gsm,ulaw"/>
<param name="codec-rates" value="8000,16000"/>
<param name="hold-music" value="$${moh_uri}"/>
- </settings>
- <!-- one entry here per skypiax span -->
- <analog_spans>
- <span id="2" name="testing">
+ </global_settings>
+ <!-- one entry here per skypiax interface -->
+ <per_interface_settings>
+ <interface id="2" name="testing">
<param name="hold-music" value="$${moh_uri}"/>
<param name="tonegroup" value="us"/>
<param name="digit-timeout" value="2000"/>
@@ -22,9 +22,9 @@
<param name="dial-regex" value="9996"/>
<param name="dial-regex-fail" value="9996"/>
<param name="X11-display" value=":99"/>
- </span>
+ </interface>
<!-- following has no id, error! -->
- <span name="ciapalo">
+ <interface name="ciapalo">
<param name="hold-music" value="$${moh_uri}"/>
<param name="tonegroup" value="us"/>
<param name="digit-timeout" value="2000"/>
@@ -35,9 +35,9 @@
<param name="dial-regex" value="9996"/>
<param name="dial-regex-fail" value="9996"/>
<param name="X11-display" value=":991"/>
- </span>
+ </interface>
<!-- following has no id, error! -->
- <span>
+ <interface>
<param name="hold-music" value="$${moh_uri}"/>
<param name="tonegroup" value="us"/>
<param name="digit-timeout" value="2000"/>
@@ -48,8 +48,8 @@
<param name="dial-regex" value="9996"/>
<param name="dial-regex-fail" value="9996"/>
<param name="X11-display" value=":991"/>
- </span>
- <span id="55" name="cucu">
+ </interface>
+ <interface id="55" name="cucu">
<param name="hold-music" value="$${moh_uri}"/>
<param name="tonegroup" value="us"/>
<param name="digit-timeout" value="2000"/>
@@ -59,8 +59,8 @@
<param name="enable-callerid" value="true"/>
<param name="dial-regex" value="9996"/>
<param name="dial-regex-fail" value="9996"/>
- </span>
- <span id="55c" name="cucu">
+ </interface>
+ <interface id="55c" name="cucu">
<param name="hold-music" value="$${moh_uri}"/>
<param name="tonegroup" value="us"/>
<param name="digit-timeout" value="2000"/>
@@ -71,8 +71,8 @@
<param name="dial-regex" value="9996"/>
<param name="dial-regex-fail" value="9996"/>
<param name="X11-display" value=":991"/>
- </span>
- <span id="73">
+ </interface>
+ <interface id="73">
<param name="hold-music" value="$${moh_uri}"/>
<param name="tonegroup" value="us"/>
<param name="digit-timeout" value="2000"/>
@@ -83,8 +83,8 @@
<param name="dial-regex" value="9996"/>
<param name="dial-regex-fail" value="9996"/>
<param name="X11-display" value=":991"/>
- </span>
- <span id="3">
+ </interface>
+ <interface id="3">
<param name="hold-music" value="$${moh_uri}"/>
<param name="tonegroup" value="us"/>
<param name="digit-timeout" value="2000"/>
@@ -94,6 +94,6 @@
<param name="enable-callerid" value="true"/>
<param name="dial-regex" value="9996"/>
<param name="dial-regex-fail" value="9996"/>
- </span>
- </analog_spans>
+ </interface>
+ </per_interface_settings>
</configuration>
1
0
[commit] r10491 - freeswitch/branches/gmaruzz/src/mod/endpoints/mod_skypiax
by FreeSWITCH SVN 21 Nov '08
by FreeSWITCH SVN 21 Nov '08
21 Nov '08
Author: gmaruzz
Date: Fri Nov 21 10:44:46 2008
New Revision: 10491
Log:
skypiax: now it can be used for multiple consecutive calls, incoming and outbound. Time to begin a general rewriting.
Modified:
freeswitch/branches/gmaruzz/src/mod/endpoints/mod_skypiax/mod_skypiax.c
Modified: freeswitch/branches/gmaruzz/src/mod/endpoints/mod_skypiax/mod_skypiax.c
==============================================================================
--- freeswitch/branches/gmaruzz/src/mod/endpoints/mod_skypiax/mod_skypiax.c (original)
+++ freeswitch/branches/gmaruzz/src/mod/endpoints/mod_skypiax/mod_skypiax.c Fri Nov 21 10:44:46 2008
@@ -194,8 +194,8 @@
int control_to_send;
int audiopipe[2];
int audioskypepipe[2];
- pthread_t tcp_srv_thread;
- pthread_t tcp_cli_thread;
+ switch_thread_t *tcp_srv_thread;
+ switch_thread_t *tcp_cli_thread;
short audiobuf[160];
int audiobuf_is_loaded;
@@ -436,7 +436,28 @@
sin_size = sizeof(remote_addr);
while ((fd = accept(s, (struct sockaddr *) &remote_addr, &sin_size)) > 0) {
DEBUGA_SKYPE("ACCEPTED\n", SKYPIAX_P_LOG);
- while (1) {
+ while (p->interface_state != SKYPIAX_STATE_DOWN && (p->skype_callflow == CALLFLOW_STATUS_INPROGRESS ||p->skype_callflow == SKYPIAX_STATE_UP)) {
+
+ int fdselect;
+ int rt;
+ fd_set fs;
+ struct timeval to;
+
+ exit=1;
+
+
+
+
+
+
+ fdselect = fd;
+ FD_ZERO(&fs);
+ FD_SET(fdselect, &fs);
+ to.tv_usec = 100;
+ to.tv_sec = 0;
+ rt = select(fdselect + 1, &fs, NULL, NULL, &to);
+ if (rt > 0) {
+
len = recv(fd, in, sizeof(short) * GG, 0);
//DEBUGA_SKYPE("recv %d\n", SKYPIAX_P_LOG, len);
if (len > 0) {
@@ -467,6 +488,7 @@
exit = 1;
break;
}
+ }
}
DEBUGA_SKYPE("Skype client GONE\n", SKYPIAX_P_LOG);
close(fd);
@@ -494,6 +516,7 @@
int a;
int i;
int got;
+ int exit=0;
if (option_debug > 10) {
DEBUGA_PBX("ENTERING FUNC\n", SKYPIAX_P_LOG);
@@ -517,6 +540,7 @@
if (option_debug > 10) {
DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
}
+ close(s);
return NULL;
}
DEBUGA_SKYPE("started tcp_cli_thread thread.\n", SKYPIAX_P_LOG);
@@ -527,7 +551,27 @@
while ((fd = accept(s, (struct sockaddr *) &remote_addr, &sin_size)) > 0) {
ERRORA("ACCEPTED\n", SKYPIAX_P_LOG);
//while (1 && p->owner && p->owner->_state == SKYPIAX_STATE_UP) FIXME FIXME FIXME
- while (1) {
+ while (p->interface_state != SKYPIAX_STATE_DOWN && (p->skype_callflow == CALLFLOW_STATUS_INPROGRESS ||p->skype_callflow == SKYPIAX_STATE_UP)) {
+ int fdselect;
+ int rt;
+ fd_set fs;
+ struct timeval to;
+
+ exit=1;
+
+
+
+
+
+
+ fdselect = p->audioskypepipe[0];
+ FD_ZERO(&fs);
+ FD_SET(fdselect, &fs);
+ to.tv_usec = 100;
+ to.tv_sec = 0;
+ rt = select(fdselect + 1, &fs, NULL, NULL, &to);
+ if (rt > 0) {
+
got = read(p->audioskypepipe[0], in, (NN / 2) * sizeof(short));
//ERRORA("got %d\n", SKYPIAX_P_LOG, got);
@@ -550,10 +594,13 @@
} else {
usleep(1000);
}
+ }
}
DEBUGA_SKYPE("Skype server GONE\n", SKYPIAX_P_LOG);
close(fd);
+ if (exit)
+ break;
}
DEBUGA_SKYPE("client (I am it) GONE\n", SKYPIAX_P_LOG);
@@ -614,6 +661,10 @@
struct skypiax_interface *p;
short buf[640];
int samples;
+ int fd;
+ int rt;
+ fd_set fs;
+ struct timeval to;
p = tech_pvt->p;
@@ -622,6 +673,14 @@
memset(buf, '\0', sizeof(buf));
+ fd = p->audiopipe[0];
+ FD_ZERO(&fs);
+ FD_SET(fd, &fs);
+ to.tv_usec = 100000;
+ to.tv_sec = 0;
+ rt = select(fd + 1, &fs, NULL, NULL, &to);
+ if (rt > 0) {
+
//if ((samples = read(p->audiopipe[0], buf, SAMPLES_PER_FRAME * sizeof(short))) != 320)
if ((samples = read(p->audiopipe[0], tech_pvt->read_frame.data, SAMPLES_PER_FRAME * sizeof(short))) != 320) {
@@ -634,6 +693,11 @@
//DEBUGA_SKYPE("read=====> GOOD samples=%d\n", SKYPIAX_P_LOG, samples);
/* A real frame */
}
+ } else {
+ DEBUGA_SKYPE("select returned %d\n", SKYPIAX_P_LOG, rt);
+
+
+ }
//DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
@@ -794,12 +858,16 @@
switch (sig) {
case SWITCH_SIG_KILL:
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "%s CHANNEL got SWITCH_SIG_KILL\n", switch_channel_get_name(channel));
switch_clear_flag_locked(tech_pvt, TFLAG_IO);
switch_clear_flag_locked(tech_pvt, TFLAG_VOICE);
- switch_channel_hangup(channel, SWITCH_CAUSE_NORMAL_CLEARING);
+ switch_set_flag_locked(tech_pvt, TFLAG_HANGUP);
+ //switch_channel_hangup(channel, SWITCH_CAUSE_NORMAL_CLEARING);
+ //switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "CHANNEL after TFLAG_HUP\n");
//switch_thread_cond_signal(tech_pvt->cond);
break;
case SWITCH_SIG_BREAK:
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "%s CHANNEL got SWITCH_SIG_BREAK\n", switch_channel_get_name(channel));
switch_set_flag_locked(tech_pvt, TFLAG_BREAK);
break;
default:
@@ -852,7 +920,8 @@
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "skypiax_skypeaudio_read ERROR\n");
} else {
- //switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "skypiax_skypeaudio_read SUCCESS\n");
+ switch_set_flag_locked(tech_pvt, TFLAG_VOICE);
+ //switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "skypiax_skypeaudio_read SUCCESS\n");
}
@@ -888,8 +957,8 @@
}
#endif
+ //switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "============>\n");
- switch_set_flag_locked(tech_pvt, TFLAG_VOICE); //FIXME
if (switch_test_flag(tech_pvt, TFLAG_IO) && switch_test_flag(tech_pvt, TFLAG_VOICE)) {
switch_clear_flag_locked(tech_pvt, TFLAG_VOICE);
@@ -904,9 +973,11 @@
}
#endif
return SWITCH_STATUS_SUCCESS;
- }
+ }
+
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "CHANNEL READ no TFLAG_IO\n");
+ return SWITCH_STATUS_FALSE;
- switch_yield(1000);
}
@@ -1831,52 +1902,50 @@
+#if 0
if (!p->tcp_srv_thread) {
if(1)
{
- switch_thread_t *thread;
+#endif
+ //switch_thread_t *thread;
+ if(1){
switch_threadattr_t *thd_attr = NULL;
switch_threadattr_create(&thd_attr, module_pool);
switch_threadattr_detach_set(thd_attr, 1);
switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE);
- switch_thread_create(&thread, thd_attr, skypiax_do_tcp_srv_thread, p, module_pool);
+ switch_thread_create(&p->tcp_srv_thread, thd_attr, skypiax_do_tcp_srv_thread, p, module_pool);
DEBUGA_SKYPE("started tcp_srv_thread thread.\n", SKYPIAX_P_LOG);
+#if 0
}
}
+#endif
+#if 0
if (!p->tcp_cli_thread) {
if(1)
{
- switch_thread_t *thread;
- switch_threadattr_t *thd_attr = NULL;
+#endif
+ //switch_thread_t *thread;
+ //switch_threadattr_t *thd_attr = NULL;
switch_threadattr_create(&thd_attr, module_pool);
switch_threadattr_detach_set(thd_attr, 1);
switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE);
- switch_thread_create(&thread, thd_attr, skypiax_do_tcp_cli_thread, p, module_pool);
+ switch_thread_create(&p->tcp_cli_thread, thd_attr, skypiax_do_tcp_cli_thread, p, module_pool);
DEBUGA_SKYPE("started tcp_cli_thread thread.\n", SKYPIAX_P_LOG);
}
+#if 0
+ }
-#ifdef NOTDEF
- if (ast_pthread_create
- (&p->tcp_cli_thread, NULL, skypiax_do_tcp_cli_thread, p) < 0) {
- ERRORA("Unable to start tcp_cli_thread thread.\n", SKYPIAX_P_LOG);
- if (option_debug > 100) {
- DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG);
- }
- return -1;
- } else {
- DEBUGA_SKYPE("started tcp_cli_thread thread.\n", SKYPIAX_P_LOG);
- }
-#endif //NOTDEF
}
+#endif
usleep(100000);
sprintf(msg_to_skype, "ALTER CALL %s SET_OUTPUT PORT=\"5556\"", id);
@@ -2134,14 +2203,30 @@
while (1) {
usleep(1000);
res = skypiax_skype_read(p);
-#if 0
+#if 1
+ //if (res == CALLFLOW_INCOMING_HANGUP && p->interface_state != SKYPIAX_STATE_DOWN)
if (res == CALLFLOW_INCOMING_HANGUP) {
+ switch_core_session_t *session = NULL;
+ private_t *tech_pvt;
+ switch_channel_t *channel;
+
+
+ p->interface_state=SKYPIAX_STATE_DOWN;
//if (option_debug)
DEBUGA_SKYPE("skype call ended\n", SKYPIAX_P_LOG);
- if (p->owner) {
- pthread_testcancel();
- ast_queue_control(p->owner, SKYPIAX_CONTROL_HANGUP);
- }
+
+ tech_pvt = p->tech_pvt;
+ session = tech_pvt->session;
+
+ channel = switch_core_session_get_channel(session);
+ DEBUGA_SKYPE("before channel_on_hangup\n", SKYPIAX_P_LOG);
+
+ //switch_channel_set_state(channel, CS_HANGUP);
+
+ switch_channel_hangup(channel, SWITCH_CAUSE_NORMAL_CLEARING);
+ DEBUGA_SKYPE("after channel_on_hangup\n", SKYPIAX_P_LOG);
+
+ //DEBUGA_SKYPE("set state to CS_HANGUP\n", SKYPIAX_P_LOG);
}
#endif
}
@@ -2440,11 +2525,15 @@
switch_clear_flag_locked(tech_pvt, TFLAG_IO);
switch_clear_flag_locked(tech_pvt, TFLAG_VOICE);
- //switch_thread_cond_signal(tech_pvt->cond);
- WARNINGA("hanging up skype call: %s\n", SKYPIAX_P_LOG, p->skype_call_id);
- //sprintf(msg_to_skype, "SET CALL %s STATUS FINISHED", p->skype_call_id);
- sprintf(msg_to_skype, "ALTER CALL %s HANGUP", p->skype_call_id);
- skypiax_skype_write(p, msg_to_skype);
+ //switch_set_flag_locked(tech_pvt, TFLAG_HANGUP);
+
+ if(strlen(p->skype_call_id)) {
+ //switch_thread_cond_signal(tech_pvt->cond);
+ WARNINGA("hanging up skype call: %s\n", SKYPIAX_P_LOG, p->skype_call_id);
+ //sprintf(msg_to_skype, "SET CALL %s STATUS FINISHED", p->skype_call_id);
+ sprintf(msg_to_skype, "ALTER CALL %s HANGUP", p->skype_call_id);
+ skypiax_skype_write(p, msg_to_skype);
+ }
if (tech_pvt->read_codec.implementation) {
switch_core_codec_destroy(&tech_pvt->read_codec);
1
0
Author: anthm
Date: Fri Nov 21 09:25:24 2008
New Revision: 10490
Log:
good measure
Modified:
freeswitch/trunk/src/switch_rtp.c
Modified: freeswitch/trunk/src/switch_rtp.c
==============================================================================
--- freeswitch/trunk/src/switch_rtp.c (original)
+++ freeswitch/trunk/src/switch_rtp.c Fri Nov 21 09:25:24 2008
@@ -1007,8 +1007,11 @@
if (rtp_session->sock_input) {
char o[4] = "DOH";
- switch_size_t len = sizeof(o);
-
+ switch_size_t len;
+
+ len = sizeof(o);
+ switch_socket_sendto(rtp_session->sock_input, rtp_session->local_addr, 0, (void *) o, &len);
+ len = sizeof(o);
switch_socket_sendto(rtp_session->sock_input, rtp_session->local_addr, 0, (void *) o, &len);
}
switch_mutex_unlock(rtp_session->flag_mutex);
1
0
21 Nov '08
Author: anthm
Date: Fri Nov 21 08:56:32 2008
New Revision: 10489
Log:
add playback_terminator support to phrase and say app
Modified:
freeswitch/trunk/src/mod/applications/mod_dptools/mod_dptools.c
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 Fri Nov 21 08:56:32 2008
@@ -126,22 +126,6 @@
}
}
-#define SAY_SYNTAX "<module_name> <say_type> <say_method> <text>"
-SWITCH_STANDARD_APP(say_function)
-{
- char *argv[4] = { 0 };
- int argc;
- char *lbuf = NULL;
-
- if (!switch_strlen_zero(data) && (lbuf = switch_core_session_strdup(session, data))
- && (argc = switch_separate_string(lbuf, ' ', argv, (sizeof(argv) / sizeof(argv[0])))) == 4) {
- switch_ivr_say(session, argv[3], argv[0], argv[1], argv[2], NULL);
- } else {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Usage: %s\n", SAY_SYNTAX);
- }
-
-}
-
#define SOFT_HOLD_SYNTAX "<unhold key> [<moh_a>] [<moh_b>]"
SWITCH_STANDARD_APP(soft_hold_function)
{
@@ -563,25 +547,6 @@
return;
}
-SWITCH_STANDARD_APP(phrase_function)
-{
- char *mydata = NULL;
-
- if (!switch_strlen_zero(data) && (mydata = switch_core_session_strdup(session, data))) {
- const char *lang;
- char *macro = mydata;
- char *mdata = NULL;
-
- if ((mdata = strchr(macro, ','))) {
- *mdata++ = '\0';
- }
-
- lang = switch_channel_get_variable(switch_core_session_get_channel(session), "language");
-
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Execute %s(%s) lang %s\n", macro, switch_str_nil(mdata), switch_str_nil(lang));
- switch_ivr_phrase_macro(session, macro, mdata, lang, NULL);
- }
-}
SWITCH_STANDARD_APP(hangup_function)
{
@@ -1142,7 +1107,6 @@
&& switch_ivr_menu_stack_xml_build(xml_ctx, &menu_stack, xml_menus, xml_menu) == SWITCH_STATUS_SUCCESS) {
switch_xml_free(cxml);
cxml = NULL;
- switch_channel_pre_answer(channel);
switch_ivr_menu_execute(session, menu_stack, (char *) data, NULL);
switch_ivr_menu_stack_free(menu_stack);
} else {
@@ -1407,8 +1371,6 @@
switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
}
- switch_channel_pre_answer(channel);
-
args.input_callback = on_dtmf;
args.buf = buf;
args.buflen = sizeof(buf);
@@ -1625,12 +1587,64 @@
switch_ivr_read(session, min_digits, max_digits, prompt_audio_file, var_name, digit_buffer, sizeof(digit_buffer), timeout, valid_terminators);
}
-SWITCH_STANDARD_APP(playback_function)
+
+
+#define SAY_SYNTAX "<module_name> <say_type> <say_method> <text>"
+SWITCH_STANDARD_APP(say_function)
{
+ char *argv[4] = { 0 };
+ int argc;
+ char *lbuf = NULL;
switch_input_args_t args = { 0 };
switch_channel_t *channel = switch_core_session_get_channel(session);
- switch_channel_pre_answer(switch_core_session_get_channel(session));
+ if (!switch_strlen_zero(data) && (lbuf = switch_core_session_strdup(session, data))
+ && (argc = switch_separate_string(lbuf, ' ', argv, (sizeof(argv) / sizeof(argv[0])))) == 4) {
+
+ args.input_callback = on_dtmf;
+
+ switch_channel_set_variable(channel, SWITCH_PLAYBACK_TERMINATOR_USED, "" );
+
+ switch_ivr_say(session, argv[3], argv[0], argv[1], argv[2], &args);
+ } else {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Usage: %s\n", SAY_SYNTAX);
+ }
+
+}
+
+
+SWITCH_STANDARD_APP(phrase_function)
+{
+ char *mydata = NULL;
+ switch_input_args_t args = { 0 };
+ switch_channel_t *channel = switch_core_session_get_channel(session);
+
+ if (!switch_strlen_zero(data) && (mydata = switch_core_session_strdup(session, data))) {
+ const char *lang;
+ char *macro = mydata;
+ char *mdata = NULL;
+
+ if ((mdata = strchr(macro, ','))) {
+ *mdata++ = '\0';
+ }
+
+ lang = switch_channel_get_variable(switch_core_session_get_channel(session), "language");
+
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Execute %s(%s) lang %s\n", macro, switch_str_nil(mdata), switch_str_nil(lang));
+
+ args.input_callback = on_dtmf;
+
+ switch_channel_set_variable(channel, SWITCH_PLAYBACK_TERMINATOR_USED, "" );
+
+ switch_ivr_phrase_macro(session, macro, mdata, lang, &args);
+ }
+}
+
+
+SWITCH_STANDARD_APP(playback_function)
+{
+ switch_input_args_t args = { 0 };
+ switch_channel_t *channel = switch_core_session_get_channel(session);
args.input_callback = on_dtmf;
@@ -1652,8 +1666,6 @@
return;
}
- switch_channel_pre_answer(switch_core_session_get_channel(session));
-
if ((l = strchr(tone_script, '|'))) {
*l++ = '\0';
loops = atoi(l);
1
0
[commit] r10488 - freeswitch/trunk/src/mod/languages/mod_managed/managed
by FreeSWITCH SVN 21 Nov '08
by FreeSWITCH SVN 21 Nov '08
21 Nov '08
Author: mikej
Date: Thu Nov 20 19:15:02 2008
New Revision: 10488
Log:
swigall
Modified:
freeswitch/trunk/src/mod/languages/mod_managed/managed/swig.cs
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 Thu Nov 20 19:15:02 2008
@@ -16791,7 +16791,7 @@
CF_ORIGINATOR = (1 << 3),
CF_TRANSFER = (1 << 4),
CF_ACCEPT_CNG = (1 << 5),
- CF_WAIT_FOR_ME = (1 << 6),
+ CF_REDIRECT = (1 << 6),
CF_BRIDGED = (1 << 7),
CF_HOLD = (1 << 8),
CF_SERVICE = (1 << 9),
@@ -16815,8 +16815,7 @@
CF_PROXY_MEDIA = (1 << 27),
CF_INNER_BRIDGE = (1 << 28),
CF_REQ_MEDIA = (1 << 29),
- CF_VERBOSE_EVENTS = (1 << 30),
- CF_MASTER = (1 << 31)
+ CF_VERBOSE_EVENTS = (1 << 30)
}
}
1
0
21 Nov '08
Author: anthm
Date: Thu Nov 20 19:09:11 2008
New Revision: 10487
Log:
code reworking do make current
Modified:
freeswitch/trunk/src/include/private/switch_core_pvt.h
freeswitch/trunk/src/include/switch_types.h
freeswitch/trunk/src/switch_channel.c
freeswitch/trunk/src/switch_core_codec.c
freeswitch/trunk/src/switch_core_io.c
freeswitch/trunk/src/switch_core_session.c
freeswitch/trunk/src/switch_core_state_machine.c
freeswitch/trunk/src/switch_ivr_bridge.c
freeswitch/trunk/src/switch_ivr_originate.c
Modified: freeswitch/trunk/src/include/private/switch_core_pvt.h
==============================================================================
--- freeswitch/trunk/src/include/private/switch_core_pvt.h (original)
+++ freeswitch/trunk/src/include/private/switch_core_pvt.h Thu Nov 20 19:09:11 2008
@@ -118,6 +118,8 @@
switch_mutex_t *mutex;
switch_mutex_t *resample_mutex;
+ switch_mutex_t *codec_read_mutex;
+ switch_mutex_t *codec_write_mutex;
switch_thread_cond_t *cond;
switch_thread_rwlock_t *rwlock;
Modified: freeswitch/trunk/src/include/switch_types.h
==============================================================================
--- freeswitch/trunk/src/include/switch_types.h (original)
+++ freeswitch/trunk/src/include/switch_types.h Thu Nov 20 19:09:11 2008
@@ -732,7 +732,7 @@
CF_ORIGINATOR = (1 << 3) - Channel is an originator
CF_TRANSFER = (1 << 4) - Channel is being transfered
CF_ACCEPT_CNG = (1 << 5) - Channel will accept CNG frames
-CF_WAIT_FOR_ME = (1 << 6) - Channel wants you to wait
+CF_REDIRECT = (1 << 6) - Channel is being redirected
CF_BRIDGED = (1 << 7) - Channel in a bridge
CF_HOLD = (1 << 8) - Channel is on hold
CF_SERVICE = (1 << 9) - Channel has a service thread
@@ -763,7 +763,7 @@
CF_ORIGINATOR = (1 << 3),
CF_TRANSFER = (1 << 4),
CF_ACCEPT_CNG = (1 << 5),
- CF_WAIT_FOR_ME = (1 << 6),
+ CF_REDIRECT = (1 << 6),
CF_BRIDGED = (1 << 7),
CF_HOLD = (1 << 8),
CF_SERVICE = (1 << 9),
@@ -787,12 +787,13 @@
CF_PROXY_MEDIA = (1 << 27),
CF_INNER_BRIDGE = (1 << 28),
CF_REQ_MEDIA = (1 << 29),
- CF_VERBOSE_EVENTS = (1 << 30),
- CF_MASTER = (1 << 31)
+ CF_VERBOSE_EVENTS = (1 << 30)
} switch_channel_flag_enum_t;
+
typedef uint32_t switch_channel_flag_t;
+
/*!
\enum switch_frame_flag_t
\brief Frame Flags
Modified: freeswitch/trunk/src/switch_channel.c
==============================================================================
--- freeswitch/trunk/src/switch_channel.c (original)
+++ freeswitch/trunk/src/switch_channel.c Thu Nov 20 19:09:11 2008
@@ -841,7 +841,6 @@
switch_clear_flag(channel, CF_TAGGED);
if (channel->state >= CS_ROUTING) {
- switch_clear_flag(channel, CF_TRANSFER);
switch_channel_presence(channel, "unknown", (char *) state_names[state], NULL);
}
Modified: freeswitch/trunk/src/switch_core_codec.c
==============================================================================
--- freeswitch/trunk/src/switch_core_codec.c (original)
+++ freeswitch/trunk/src/switch_core_codec.c Thu Nov 20 19:09:11 2008
@@ -46,6 +46,7 @@
{
switch_mutex_t *mutex = NULL;
+ switch_mutex_lock(session->codec_read_mutex);
if (session->read_codec) mutex = session->read_codec->mutex;
if (mutex) switch_mutex_lock(mutex);
session->real_read_codec = session->read_codec = NULL;
@@ -54,16 +55,19 @@
session->enc_read_frame.codec = session->read_codec;
session->enc_write_frame.codec = session->read_codec;
if (mutex) switch_mutex_unlock(mutex);
+ switch_mutex_unlock(session->codec_read_mutex);
}
SWITCH_DECLARE(void) switch_core_session_unset_write_codec(switch_core_session_t *session)
{
switch_mutex_t *mutex = NULL;
+ switch_mutex_lock(session->codec_write_mutex);
if (session->write_codec) mutex = session->write_codec->mutex;
if (mutex) switch_mutex_lock(mutex);
session->real_write_codec = session->write_codec = NULL;
if (mutex) switch_mutex_unlock(mutex);
+ switch_mutex_unlock(session->codec_write_mutex);
}
@@ -74,6 +78,8 @@
char tmp[30];
switch_status_t status = SWITCH_STATUS_SUCCESS;
+ switch_mutex_lock(session->codec_read_mutex);
+
if (codec && !codec->implementation) {
codec = NULL;
}
@@ -128,6 +134,7 @@
end:
+ switch_mutex_unlock(session->codec_read_mutex);
return status;
}
@@ -192,6 +199,8 @@
char tmp[30];
switch_status_t status = SWITCH_STATUS_SUCCESS;
+ switch_mutex_lock(session->codec_write_mutex);
+
if (!codec || !codec->implementation) {
if (session->real_write_codec) {
session->write_codec = session->real_write_codec;
@@ -241,6 +250,7 @@
}
end:
+ switch_mutex_unlock(session->codec_write_mutex);
return status;
}
Modified: freeswitch/trunk/src/switch_core_io.c
==============================================================================
--- freeswitch/trunk/src/switch_core_io.c (original)
+++ freeswitch/trunk/src/switch_core_io.c Thu Nov 20 19:09:11 2008
@@ -110,10 +110,15 @@
switch_assert(session != NULL);
if (!(session->read_codec && session->read_codec->implementation)) {
+ if (switch_channel_test_flag(session->channel, CF_PROXY_MODE) || switch_channel_get_state(session->channel) == CS_HIBERNATE) {
+ *frame = &runtime.dummy_cng_frame;
+ return SWITCH_STATUS_SUCCESS;
+ }
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "%s has no read codec.\n", switch_channel_get_name(session->channel));
return SWITCH_STATUS_FALSE;
}
+ switch_mutex_lock(session->codec_read_mutex);
switch_mutex_lock(session->read_codec->mutex);
top:
@@ -521,7 +526,8 @@
}
switch_mutex_unlock(session->read_codec->mutex);
-
+ switch_mutex_unlock(session->codec_read_mutex);
+
return status;
}
@@ -588,7 +594,8 @@
}
switch_mutex_lock(session->write_codec->mutex);
switch_mutex_lock(frame->codec->mutex);
-
+ switch_mutex_lock(session->codec_write_mutex);
+
if ((session->write_codec && frame->codec && session->write_codec->implementation != frame->codec->implementation)) {
need_codec = TRUE;
if (session->write_codec->implementation->codec_id == frame->codec->implementation->codec_id) {
@@ -977,7 +984,8 @@
switch_mutex_unlock(session->write_codec->mutex);
switch_mutex_unlock(frame->codec->mutex);
-
+ switch_mutex_unlock(session->codec_write_mutex);
+
return status;
}
Modified: freeswitch/trunk/src/switch_core_session.c
==============================================================================
--- freeswitch/trunk/src/switch_core_session.c (original)
+++ freeswitch/trunk/src/switch_core_session.c Thu Nov 20 19:09:11 2008
@@ -747,6 +747,7 @@
switch_channel_t *channel = switch_core_session_get_channel(session);
switch_size_t has;
+
switch_core_session_set_read_codec(session, NULL);
/* clear resamplers */
@@ -1102,6 +1103,8 @@
switch_mutex_init(&session->mutex, SWITCH_MUTEX_NESTED, session->pool);
switch_mutex_init(&session->resample_mutex, SWITCH_MUTEX_NESTED, session->pool);
+ switch_mutex_init(&session->codec_read_mutex, SWITCH_MUTEX_NESTED, session->pool);
+ switch_mutex_init(&session->codec_write_mutex, SWITCH_MUTEX_NESTED, session->pool);
switch_thread_rwlock_create(&session->bug_rwlock, session->pool);
switch_thread_cond_create(&session->cond, session->pool);
switch_thread_rwlock_create(&session->rwlock, session->pool);
Modified: freeswitch/trunk/src/switch_core_state_machine.c
==============================================================================
--- freeswitch/trunk/src/switch_core_state_machine.c (original)
+++ freeswitch/trunk/src/switch_core_state_machine.c Thu Nov 20 19:09:11 2008
@@ -165,7 +165,7 @@
}
if (switch_channel_get_state(session->channel) == CS_EXECUTE) {
- switch_channel_hangup(session->channel, SWITCH_CAUSE_NORMAL_CLEARING);
+ switch_channel_hangup(session->channel, SWITCH_CAUSE_NORMAL_CLEARING);
}
}
@@ -185,7 +185,6 @@
{
switch_assert(session != NULL);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s Standard PARK\n", switch_channel_get_name(session->channel));
- switch_channel_clear_flag(session->channel, CF_TRANSFER);
switch_core_session_reset(session, SWITCH_TRUE);
switch_ivr_park(session, NULL);
}
@@ -373,6 +372,7 @@
int do_extra_handlers = 1;
switch_channel_set_running_state(session->channel, state);
+ switch_channel_clear_flag(session->channel, CF_TRANSFER);
switch (state) {
case CS_NEW: /* Just created, Waiting for first instructions */
Modified: freeswitch/trunk/src/switch_ivr_bridge.c
==============================================================================
--- freeswitch/trunk/src/switch_ivr_bridge.c (original)
+++ freeswitch/trunk/src/switch_ivr_bridge.c Thu Nov 20 19:09:11 2008
@@ -140,7 +140,8 @@
switch_channel_wait_for_flag(chan_b, CF_BRIDGED, SWITCH_TRUE, 10000, chan_a);
if (!switch_channel_test_flag(chan_b, CF_BRIDGED)) {
- if (!(switch_channel_test_flag(chan_b, CF_TRANSFER) || switch_channel_get_state(chan_b) == CS_RESET)) {
+ if (!(switch_channel_test_flag(chan_b, CF_TRANSFER) || switch_channel_test_flag(chan_b, CF_REDIRECT)
+ || switch_channel_get_state(chan_b) == CS_RESET)) {
switch_channel_hangup(chan_b, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
}
goto end_of_bridge_loop;
@@ -208,11 +209,11 @@
goto end_of_bridge_loop;
}
- if (switch_channel_test_flag(chan_a, CF_TRANSFER)) {
+ if (switch_channel_test_flag(chan_a, CF_TRANSFER) || switch_channel_test_flag(chan_a, CF_REDIRECT)) {
data->clean_exit = 1;
}
- if (data->clean_exit || switch_channel_test_flag(chan_b, CF_TRANSFER)) {
+ if (data->clean_exit || switch_channel_test_flag(chan_b, CF_TRANSFER) || switch_channel_test_flag(chan_b, CF_REDIRECT)) {
switch_channel_clear_flag(chan_a, CF_HOLD);
switch_channel_clear_flag(chan_a, CF_SUSPEND);
goto end_of_bridge_loop;
@@ -352,8 +353,6 @@
if (switch_core_session_write_frame(session_b, read_frame, SWITCH_IO_FLAG_NONE, stream_id) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG,
"%s ending bridge by request from write function\n", switch_channel_get_name(chan_b));
-
-
goto end_of_bridge_loop;
}
}
@@ -467,7 +466,7 @@
switch_ivr_park_session(session);
}
- if (!switch_channel_test_flag(channel, CF_TRANSFER) && bd && !bd->clean_exit && state != CS_PARK &&
+ if (!switch_channel_test_flag(channel, CF_TRANSFER) && !switch_channel_test_flag(channel, CF_REDIRECT) && bd && !bd->clean_exit && state != CS_PARK &&
state != CS_ROUTING && !switch_channel_test_flag(channel, CF_INNER_BRIDGE)) {
switch_channel_hangup(channel, SWITCH_CAUSE_NORMAL_CLEARING);
}
@@ -485,6 +484,9 @@
}
}
+ if (switch_channel_get_state(channel) < CS_HANGUP) {
+ switch_channel_set_state(channel, CS_RESET);
+ }
return SWITCH_STATUS_FALSE;
}
@@ -526,33 +528,38 @@
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s CUSTOM RESET\n", switch_channel_get_name(channel));
- switch_channel_clear_flag(channel, CF_TRANSFER);
+ switch_channel_clear_flag(channel, CF_REDIRECT);
+
switch_channel_clear_flag(channel, CF_ORIGINATING);
- if (switch_channel_test_flag(channel, (uint32_t)CF_MASTER)) {
+ if (switch_channel_test_flag(channel, CF_ORIGINATOR)) {
switch_channel_set_state(channel, CS_SOFT_EXECUTE);
}
return SWITCH_STATUS_SUCCESS;
}
+static switch_status_t uuid_bridge_on_hibernate(switch_core_session_t *session)
+{
+ switch_channel_set_state(switch_core_session_get_channel(session), CS_RESET);
+ return SWITCH_STATUS_FALSE;
+}
+
static switch_status_t uuid_bridge_on_soft_execute(switch_core_session_t *session)
{
switch_channel_t *channel = switch_core_session_get_channel(session);
switch_core_session_t *other_session;
const char *other_uuid = NULL;
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s CUSTOM TRANSMIT\n", switch_channel_get_name(channel));
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s CUSTOM SOFT_EXECUTE\n", switch_channel_get_name(channel));
switch_channel_clear_state_handler(channel, NULL);
- switch_channel_clear_flag(channel, CF_TRANSFER);
-
- if (!switch_channel_test_flag(channel, (uint32_t)CF_MASTER)) {
+ if (!switch_channel_test_flag(channel, CF_ORIGINATOR)) {
return SWITCH_STATUS_SUCCESS;
}
- switch_channel_clear_flag(channel, (uint32_t)CF_MASTER);
-
+ switch_channel_clear_flag(channel, CF_ORIGINATOR);
+
if ((other_uuid = switch_channel_get_variable(channel, SWITCH_UUID_BRIDGE)) && (other_session = switch_core_session_locate(other_uuid))) {
switch_channel_t *other_channel = switch_core_session_get_channel(other_session);
switch_event_t *event;
@@ -575,8 +582,6 @@
switch_channel_wait_for_state(channel, other_channel, CS_SOFT_EXECUTE);
- switch_channel_clear_flag(channel, CF_TRANSFER);
- switch_channel_clear_flag(other_channel, CF_TRANSFER);
switch_core_session_reset(session, SWITCH_TRUE);
@@ -618,7 +623,7 @@
switch_ivr_multi_threaded_bridge(session, other_session, NULL, NULL, NULL);
state = switch_channel_get_state(channel);
- if (!switch_channel_test_flag(channel, CF_TRANSFER) && state < CS_HANGUP && state != CS_ROUTING && state != CS_PARK) {
+ if (!switch_channel_test_flag(channel, CF_TRANSFER) && !switch_channel_test_flag(channel, CF_REDIRECT) && state < CS_HANGUP && state != CS_ROUTING && state != CS_PARK) {
switch_channel_set_state(channel, CS_EXECUTE);
}
switch_core_session_rwunlock(other_session);
@@ -638,8 +643,8 @@
/*.on_hangup */ NULL,
/*.on_exchange_media */ NULL,
/*.on_soft_execute */ uuid_bridge_on_soft_execute,
- /*.on_consume_media */ NULL,
- /*.on_hibernate */ NULL,
+ /*.on_consume_media */ uuid_bridge_on_hibernate,
+ /*.on_hibernate */ uuid_bridge_on_hibernate,
/*.on_reset */ uuid_bridge_on_reset
};
@@ -649,7 +654,6 @@
channel = switch_core_session_get_channel(session);
switch_assert(channel != NULL);
- switch_channel_clear_flag(channel, CF_TRANSFER);
switch_channel_set_variable(channel, SWITCH_BRIDGE_VARIABLE, switch_channel_get_variable(channel, SWITCH_SIGNAL_BRIDGE_VARIABLE));
@@ -785,8 +789,6 @@
int inner_bridge = switch_channel_test_flag(caller_channel, CF_INNER_BRIDGE);
switch_channel_set_flag(caller_channel, CF_ORIGINATOR);
- switch_channel_clear_flag(caller_channel, CF_TRANSFER);
- switch_channel_clear_flag(peer_channel, CF_TRANSFER);
b_leg->session = peer_session;
switch_copy_string(b_leg->b_uuid, switch_core_session_get_uuid(session), sizeof(b_leg->b_uuid));
@@ -830,7 +832,8 @@
if ((status = switch_ivr_wait_for_answer(session, peer_session)) != SWITCH_STATUS_SUCCESS) {
switch_channel_state_t w_state = switch_channel_get_state(caller_channel);
switch_channel_hangup(peer_channel, SWITCH_CAUSE_ALLOTTED_TIMEOUT);
- if (w_state < CS_HANGUP && w_state != CS_ROUTING && w_state != CS_PARK && !switch_channel_test_flag(caller_channel, CF_TRANSFER) &&
+ if (w_state < CS_HANGUP && w_state != CS_ROUTING && w_state != CS_PARK &&
+ !switch_channel_test_flag(caller_channel, CF_REDIRECT) && !switch_channel_test_flag(caller_channel, CF_TRANSFER) &&
w_state != CS_EXECUTE) {
const char *ext = switch_channel_get_variable(peer_channel, "original_destination_number");
if (!ext) {
@@ -911,10 +914,6 @@
switch_channel_clear_flag(caller_channel, CF_ORIGINATOR);
- if (!switch_channel_test_flag(peer_channel, CF_TRANSFER) && switch_channel_get_state(peer_channel) == CS_EXCHANGE_MEDIA) {
- switch_channel_set_state(peer_channel, CS_RESET);
- }
-
while (switch_channel_get_state(peer_channel) == CS_EXCHANGE_MEDIA) {
switch_cond_next();
}
@@ -943,8 +942,9 @@
}
state = switch_channel_get_state(caller_channel);
-
- if (!switch_channel_test_flag(caller_channel, CF_TRANSFER) && !a_leg->clean_exit && !inner_bridge) {
+
+ if (!switch_channel_test_flag(caller_channel, CF_TRANSFER) && !switch_channel_test_flag(caller_channel, CF_REDIRECT)
+ && !a_leg->clean_exit && !inner_bridge) {
if ((state != CS_EXECUTE && state != CS_SOFT_EXECUTE && state != CS_PARK && state != CS_ROUTING) ||
(switch_channel_test_flag(peer_channel, CF_ANSWERED) && state < CS_HANGUP)) {
if (switch_true(switch_channel_get_variable(caller_channel, SWITCH_HANGUP_AFTER_BRIDGE_VARIABLE))) {
@@ -955,6 +955,11 @@
}
}
+ if (switch_channel_test_flag(caller_channel, CF_REDIRECT)) {
+ switch_channel_set_state(caller_channel, CS_RESET);
+ }
+
+
return status;
}
@@ -992,6 +997,7 @@
switch_status_t status = SWITCH_STATUS_FALSE;
switch_caller_profile_t *cp, *originator_cp, *originatee_cp;
char *p;
+ switch_channel_state_t state;
if ((originator_session = switch_core_session_locate(originator_uuid))) {
if ((originatee_session = switch_core_session_locate(originatee_uuid))) {
@@ -1033,14 +1039,11 @@
* originatee_session will fall asleep and originator_session will bridge to it
*/
- switch_channel_clear_state_handler(originator_channel, NULL);
- switch_channel_clear_state_handler(originatee_channel, NULL);
- switch_channel_set_flag(originator_channel, (uint32_t)CF_MASTER);
- switch_channel_clear_flag(originatee_channel, (uint32_t)CF_MASTER);
- switch_channel_add_state_handler(originator_channel, &uuid_bridge_state_handlers);
- switch_channel_add_state_handler(originatee_channel, &uuid_bridge_state_handlers);
- switch_channel_set_variable(originator_channel, SWITCH_UUID_BRIDGE, switch_core_session_get_uuid(originatee_session));
+ switch_channel_set_flag(originator_channel, CF_REDIRECT);
+ switch_channel_set_flag(originatee_channel, CF_REDIRECT);
+
+ switch_channel_set_variable(originator_channel, SWITCH_UUID_BRIDGE, switch_core_session_get_uuid(originatee_session));
switch_channel_set_variable(originator_channel, SWITCH_BRIDGE_CHANNEL_VARIABLE, switch_channel_get_name(originatee_channel));
switch_channel_set_variable(originator_channel, SWITCH_BRIDGE_UUID_VARIABLE, switch_core_session_get_uuid(originatee_session));
switch_channel_set_variable(originator_channel, SWITCH_SIGNAL_BOND_VARIABLE, switch_core_session_get_uuid(originatee_session));
@@ -1089,13 +1092,23 @@
switch_channel_set_flag(originator_channel, CF_TRANSFER);
switch_channel_set_flag(originatee_channel, CF_TRANSFER);
+
switch_channel_clear_flag(originator_channel, CF_ORIGINATING);
switch_channel_clear_flag(originatee_channel, CF_ORIGINATING);
/* change the states and let the chips fall where they may */
- switch_channel_set_state(originator_channel, CS_RESET);
- switch_channel_set_state(originatee_channel, CS_RESET);
+ switch_channel_clear_state_handler(originator_channel, NULL);
+ switch_channel_clear_state_handler(originatee_channel, NULL);
+ switch_channel_set_state_flag(originator_channel, CF_ORIGINATOR);
+ switch_channel_clear_flag(originatee_channel, CF_ORIGINATOR);
+ switch_channel_add_state_handler(originator_channel, &uuid_bridge_state_handlers);
+ switch_channel_add_state_handler(originatee_channel, &uuid_bridge_state_handlers);
+ state = switch_channel_get_state(originator_channel);
+ switch_channel_set_state(originator_channel, state == CS_HIBERNATE ? CS_CONSUME_MEDIA : CS_HIBERNATE);
+ state = switch_channel_get_state(originatee_channel);
+ switch_channel_set_state(originatee_channel, state == CS_HIBERNATE ? CS_CONSUME_MEDIA : CS_HIBERNATE);
+
status = SWITCH_STATUS_SUCCESS;
/* release the read locks we have on the channels */
Modified: freeswitch/trunk/src/switch_ivr_originate.c
==============================================================================
--- freeswitch/trunk/src/switch_ivr_originate.c (original)
+++ freeswitch/trunk/src/switch_ivr_originate.c Thu Nov 20 19:09:11 2008
@@ -231,7 +231,9 @@
state = switch_channel_get_state(peer_channels[i]);
if (state >= CS_HANGUP || state == CS_RESET || switch_channel_test_flag(peer_channels[i], CF_TRANSFER) ||
- switch_channel_test_flag(peer_channels[i], CF_BRIDGED) || !switch_channel_test_flag(peer_channels[i], CF_ORIGINATING)
+ switch_channel_test_flag(peer_channels[i], CF_REDIRECT) ||
+ switch_channel_test_flag(peer_channels[i], CF_BRIDGED) ||
+ !switch_channel_test_flag(peer_channels[i], CF_ORIGINATING)
) {
(*hups)++;
} else if ((switch_channel_test_flag(peer_channels[i], CF_ANSWERED) ||
@@ -1453,8 +1455,11 @@
continue;
}
- if (switch_channel_test_flag(peer_channels[i], CF_TRANSFER) || switch_channel_test_flag(peer_channels[i], CF_BRIDGED) ||
- switch_channel_get_state(peer_channels[i]) == CS_RESET || !switch_channel_test_flag(peer_channels[i], CF_ORIGINATING)
+ if (switch_channel_test_flag(peer_channels[i], CF_TRANSFER)
+ || switch_channel_test_flag(peer_channels[i], CF_REDIRECT)
+ || switch_channel_test_flag(peer_channels[i], CF_BRIDGED) ||
+ switch_channel_get_state(peer_channels[i]) == CS_RESET ||
+ !switch_channel_test_flag(peer_channels[i], CF_ORIGINATING)
) {
continue;
}
@@ -1652,6 +1657,7 @@
}
} else if ((state=switch_channel_get_state(peer_channels[i])) < CS_HANGUP && switch_channel_test_flag(peer_channels[i], CF_ORIGINATING)) {
if (!(state == CS_RESET || switch_channel_test_flag(peer_channels[i], CF_TRANSFER) ||
+ switch_channel_test_flag(peer_channels[i], CF_REDIRECT) ||
switch_channel_test_flag(peer_channels[i], CF_BRIDGED))) {
switch_channel_hangup(peer_channels[i], *cause);
}
1
0