Freeswitch-trunk
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
April 2007
- 3 participants
- 201 discussions
29 Apr '07
Author: anthm
Date: Sat Apr 28 21:16:49 2007
New Revision: 5036
Modified:
freeswitch/trunk/src/mod/endpoints/mod_sofia/mod_sofia.c
freeswitch/trunk/src/mod/endpoints/mod_sofia/mod_sofia.h
freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia.c
freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia_glue.c
freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia_presence.c
freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia_reg.c
freeswitch/trunk/src/switch_odbc.c
Log:
either break everything or make it cooler ... ?
Modified: freeswitch/trunk/src/mod/endpoints/mod_sofia/mod_sofia.c
==============================================================================
--- freeswitch/trunk/src/mod/endpoints/mod_sofia/mod_sofia.c (original)
+++ freeswitch/trunk/src/mod/endpoints/mod_sofia/mod_sofia.c Sat Apr 28 21:16:49 2007
@@ -244,6 +244,10 @@
switch_clear_flag_locked(tech_pvt, TFLAG_IO);
+ switch_mutex_lock(tech_pvt->profile->flag_mutex);
+ tech_pvt->profile->inuse--;
+ switch_mutex_unlock(tech_pvt->profile->flag_mutex);
+
if (tech_pvt->sofia_private) {
*tech_pvt->sofia_private->uuid = '\0';
}
@@ -275,7 +279,6 @@
assert(channel != NULL);
tech_pvt = (private_object_t *) switch_core_session_get_private(session);
- assert(tech_pvt != NULL);
if (!switch_test_flag(tech_pvt, TFLAG_ANS) && !switch_channel_test_flag(channel, CF_OUTBOUND)) {
switch_set_flag_locked(tech_pvt, TFLAG_ANS);
@@ -314,9 +317,11 @@
}
}
}
+
nua_respond(tech_pvt->nh, SIP_200_OK,
SIPTAG_CONTACT_STR(tech_pvt->profile->url),
SOATAG_USER_SDP_STR(tech_pvt->local_sdp_str), SOATAG_AUDIO_AUX("cn telephone-event"), NUTAG_INCLUDE_EXTRA_SDP(1), TAG_END());
+
}
return SWITCH_STATUS_SUCCESS;
@@ -336,7 +341,7 @@
tech_pvt = (private_object_t *) switch_core_session_get_private(session);
assert(tech_pvt != NULL);
- if (switch_test_flag(tech_pvt, TFLAG_HUP)) {
+ if (switch_test_flag(tech_pvt, TFLAG_HUP) || !sofia_test_pflag(tech_pvt->profile, PFLAG_RUNNING)) {
return SWITCH_STATUS_FALSE;
}
@@ -408,7 +413,7 @@
}
}
- if (switch_test_flag(tech_pvt, TFLAG_HUP)) {
+ if (switch_test_flag(tech_pvt, TFLAG_HUP) || !sofia_test_pflag(tech_pvt->profile, PFLAG_RUNNING)) {
return SWITCH_STATUS_FALSE;
}
@@ -440,7 +445,7 @@
tech_pvt = (private_object_t *) switch_core_session_get_private(session);
assert(tech_pvt != NULL);
- if (switch_test_flag(tech_pvt, TFLAG_HUP)) {
+ if (switch_test_flag(tech_pvt, TFLAG_HUP) || !sofia_test_pflag(tech_pvt->profile, PFLAG_RUNNING)) {
return SWITCH_STATUS_FALSE;
}
@@ -535,7 +540,7 @@
}
}
- if (switch_test_flag(tech_pvt, TFLAG_HUP)) {
+ if (switch_test_flag(tech_pvt, TFLAG_HUP) || !sofia_test_pflag(tech_pvt->profile, PFLAG_RUNNING)) {
return SWITCH_STATUS_FALSE;
}
@@ -880,6 +885,126 @@
return SWITCH_STATUS_SUCCESS;
}
+typedef switch_status_t (*sofia_command_t) (char **argv, int argc, switch_stream_handle_t *stream);
+
+
+static switch_status_t cmd_status(char **argv, int argc, switch_stream_handle_t *stream)
+{
+ sofia_profile_t *profile = NULL;
+ switch_hash_index_t *hi;
+ void *val;
+ int c = 0;
+
+ switch_mutex_lock(mod_sofia_globals.hash_mutex);
+ for (hi = switch_hash_first(switch_hash_pool_get(mod_sofia_globals.profile_hash), mod_sofia_globals.profile_hash); hi; hi = switch_hash_next(hi)) {
+ switch_hash_this(hi, NULL, NULL, &val);
+ profile = (sofia_profile_t *) val;
+ if (sofia_test_pflag(profile, PFLAG_RUNNING)) {
+ stream->write_function(stream, "Profile %s\n", profile->name);
+ c++;
+ }
+ }
+ switch_mutex_unlock(mod_sofia_globals.hash_mutex);
+ stream->write_function(stream, "%d profiles\n", c);
+ return SWITCH_STATUS_SUCCESS;
+
+}
+
+static switch_status_t cmd_profile(char **argv, int argc, switch_stream_handle_t *stream)
+{
+ sofia_profile_t *profile = NULL;
+ char *profile_name = argv[0];
+
+ if (argc < 2) {
+ stream->write_function(stream, "Invalid Args!\n");
+ return SWITCH_STATUS_SUCCESS;
+ }
+
+ if (!strcasecmp(argv[1], "start")) {
+ if (config_sofia(1, argv[0]) == SWITCH_STATUS_SUCCESS) {
+ stream->write_function(stream, "%s started successfully\n", argv[0]);
+ } else {
+ stream->write_function(stream, "Failure starting %s\n", argv[0]);
+ }
+ return SWITCH_STATUS_SUCCESS;
+ }
+
+ if (switch_strlen_zero(profile_name) || !(profile = sofia_glue_find_profile(profile_name))) {
+ stream->write_function(stream, "Invalid Profile [%s]", switch_str_nil(profile_name));
+ return SWITCH_STATUS_SUCCESS;
+ }
+
+ if (!strcasecmp(argv[1], "stop")) {
+ sofia_clear_pflag_locked(profile, PFLAG_RUNNING);
+ stream->write_function(stream, "stopping: %s", profile->name);
+ }
+
+ if (profile) {
+ switch_thread_rwlock_unlock(profile->rwlock);
+ }
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+static switch_status_t sofia_function(char *cmd, switch_core_session_t *isession, switch_stream_handle_t *stream)
+{
+ char *argv[1024] = { 0 };
+ int argc = 0;
+ char *mycmd = NULL;
+ switch_status_t status = SWITCH_STATUS_SUCCESS;
+ sofia_command_t func = NULL;
+ int lead = 1;
+ const char *usage_string = "USAGE:\n"
+ "--------------------------------------------------------------------------------\n"
+ "sofia help\n"
+ "sofia profile <options>\n"
+ "sofia status\n"
+ "--------------------------------------------------------------------------------\n";
+
+ if (isession) {
+ return SWITCH_STATUS_FALSE;
+ }
+
+ if (switch_strlen_zero(cmd)) {
+ stream->write_function(stream, "%s", usage_string);
+ goto done;
+ }
+
+ if (!(mycmd = strdup(cmd))) {
+ status = SWITCH_STATUS_MEMERR;
+ goto done;
+ }
+
+ if (!(argc = switch_separate_string(mycmd, ' ', argv, (sizeof(argv) / sizeof(argv[0]))))) {
+ stream->write_function(stream, "%s", usage_string);
+ goto done;
+ }
+
+ if (!strcasecmp(argv[0], "profile")) {
+ func = cmd_profile;
+ } else if (!strcasecmp(argv[0], "status")) {
+ func = cmd_status;
+ } else if (!strcasecmp(argv[0], "help")) {
+ stream->write_function(stream, "%s", usage_string);
+ goto done;
+ }
+
+ if (func) {
+ status = func(&argv[lead], argc - lead, stream);
+ } else {
+ stream->write_function(stream, "Unknown Command [%s]\n", argv[0]);
+ }
+
+
+ done:
+
+ switch_safe_free(mycmd);
+
+ return status;
+
+
+}
+
static const switch_io_routines_t sofia_io_routines = {
/*.outgoing_channel */ sofia_outgoing_channel,
/*.read_frame */ sofia_read_frame,
@@ -928,6 +1053,14 @@
/*.management_function */ sofia_manage
};
+static switch_api_interface_t sofia_api_interface = {
+ /*.interface_name */ "sofia",
+ /*.desc */ "Sofia Controls",
+ /*.function */ sofia_function,
+ /*.syntax */ "<cmd> <args>",
+ /*.next */ NULL
+};
+
static const switch_loadable_module_interface_t sofia_module_interface = {
/*.module_name */ modname,
/*.endpoint_interface */ &sofia_endpoint_interface,
@@ -935,7 +1068,7 @@
/*.dialplan_interface */ NULL,
/*.codec_interface */ NULL,
/*.application_interface */ NULL,
- /*.api_interface */ NULL,
+ /*.api_interface */ &sofia_api_interface,
/*.file_interface */ NULL,
/*.speech_interface */ NULL,
/*.directory_interface */ NULL,
@@ -954,7 +1087,7 @@
switch_call_cause_t cause = SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER;
switch_core_session_t *nsession;
char *data, *profile_name, *dest;
- sofia_profile_t *profile;
+ sofia_profile_t *profile = NULL;
switch_caller_profile_t *caller_profile = NULL;
private_object_t *tech_pvt = NULL;
switch_channel_t *nchannel;
@@ -979,7 +1112,7 @@
if (!strncasecmp(profile_name, "gateway", 7)) {
char *gw;
- outbound_reg_t *gateway_ptr;
+ sofia_gateway_t *gateway_ptr = NULL;
if (!(gw = strchr(profile_name, '/'))) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid URL\n");
@@ -1016,6 +1149,7 @@
tech_pvt->dest = switch_core_session_sprintf(nsession, "sip:%s", dest);
}
tech_pvt->invite_contact = switch_core_session_strdup(nsession, gateway_ptr->register_contact);
+ sofia_reg_release_gateway(gateway_ptr);
} else {
if (!(dest = strchr(profile_name, '/'))) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid URL\n");
@@ -1102,6 +1236,10 @@
}
done:
+ if (profile) {
+ switch_thread_rwlock_unlock(profile->rwlock);
+ }
+
return cause;
}
@@ -1133,7 +1271,7 @@
switch_core_hash_init(&mod_sofia_globals.gateway_hash, module_pool);
switch_mutex_init(&mod_sofia_globals.hash_mutex, SWITCH_MUTEX_NESTED, module_pool);
- if (config_sofia(0) != SWITCH_STATUS_SUCCESS) {
+ if (config_sofia(0, NULL) != SWITCH_STATUS_SUCCESS) {
return SWITCH_STATUS_GENERR;
}
Modified: freeswitch/trunk/src/mod/endpoints/mod_sofia/mod_sofia.h
==============================================================================
--- freeswitch/trunk/src/mod/endpoints/mod_sofia/mod_sofia.h (original)
+++ freeswitch/trunk/src/mod/endpoints/mod_sofia/mod_sofia.h Sat Apr 28 21:16:49 2007
@@ -47,8 +47,8 @@
static const char modname[] = "mod_sofia";
static const switch_state_handler_table_t noop_state_handler = { 0 };
-struct outbound_reg;
-typedef struct outbound_reg outbound_reg_t;
+struct sofia_gateway;
+typedef struct sofia_gateway sofia_gateway_t;
struct sofia_profile;
typedef struct sofia_profile sofia_profile_t;
@@ -82,7 +82,7 @@
struct sofia_private {
char uuid[SWITCH_UUID_FORMATTED_LENGTH + 1];
- outbound_reg_t *gateway;
+ sofia_gateway_t *gateway;
su_home_t *home;
};
@@ -109,7 +109,8 @@
PFLAG_PRESENCE = (1 << 4),
PFLAG_PASS_RFC2833 = (1 << 5),
PFLAG_DISABLE_TRANSCODING = (1 << 6),
- PFLAG_REWRITE_TIMESTAMPS = (1 << 7)
+ PFLAG_REWRITE_TIMESTAMPS = (1 << 7),
+ PFLAG_RUNNING = (1 << 8)
} PFLAGS;
typedef enum {
@@ -170,7 +171,7 @@
REG_STATE_NOREG
} reg_state_t;
-struct outbound_reg {
+struct sofia_gateway {
sofia_private_t *sofia_private;
nua_handle_t *nh;
sofia_profile_t *profile;
@@ -191,7 +192,7 @@
uint32_t flags;
reg_state_t state;
switch_memory_pool_t *pool;
- struct outbound_reg *next;
+ struct sofia_gateway *next;
};
@@ -229,11 +230,14 @@
uint32_t codec_flags;
switch_mutex_t *ireg_mutex;
switch_mutex_t *gateway_mutex;
- outbound_reg_t *gateways;
+ sofia_gateway_t *gateways;
su_home_t *home;
switch_hash_t *profile_hash;
switch_hash_t *chat_hash;
switch_core_db_t *master_db;
+ switch_thread_rwlock_t *rwlock;
+ switch_mutex_t *flag_mutex;
+ uint32_t inuse;
#ifdef SWITCH_HAVE_ODBC
char *odbc_dsn;
char *odbc_user;
@@ -350,6 +354,17 @@
AUTH_STALE,
} auth_res_t;
+
+#define sofia_test_pflag(obj, flag) ((obj)->pflags & flag)
+#define sofia_set_pflag(obj, flag) (obj)->pflags |= (flag)
+#define sofia_set_pflag_locked(obj, flag) assert(obj->flag_mutex != NULL);\
+switch_mutex_lock(obj->flag_mutex);\
+(obj)->pflags |= (flag);\
+switch_mutex_unlock(obj->flag_mutex);
+#define sofia_clear_pflag_locked(obj, flag) switch_mutex_lock(obj->flag_mutex); (obj)->pflags &= ~(flag); switch_mutex_unlock(obj->flag_mutex);
+#define sofia_clear_pflag(obj, flag) (obj)->pflags &= ~(flag)
+#define sofia_copy_pflags(dest, src, flags) (dest)->pflags &= ~(flags); (dest)->pflags |= ((src)->pflags & (flags))
+
/* Function Prototypes */
/*************************************************************************************************************************************************************/
@@ -398,7 +413,7 @@
void sofia_presence_event_handler(switch_event_t *event);
void sofia_presence_mwi_event_handler(switch_event_t *event);
void sofia_presence_cancel(void);
-switch_status_t config_sofia(int reload);
+switch_status_t config_sofia(int reload, char *profile_name);
auth_res_t sofia_reg_parse_auth(sofia_profile_t *profile, sip_authorization_t const *authorization, const char *regstr, char *np, size_t nplen, char *ip);
void sofia_reg_handle_sip_r_challenge(int status,
char const *phrase,
@@ -427,8 +442,8 @@
void sofia_reg_check_gateway(sofia_profile_t *profile, time_t now);
void sofia_reg_unregister(sofia_profile_t *profile);
switch_status_t sofia_glue_ext_address_lookup(char **ip, switch_port_t *port, char *sourceip, switch_memory_pool_t *pool);
-outbound_reg_t *sofia_reg_find_gateway(char *key);
-void sofia_reg_add_gateway(char *key, outbound_reg_t *gateway);
+sofia_gateway_t *sofia_reg_find_gateway(char *key);
+void sofia_reg_add_gateway(char *key, sofia_gateway_t *gateway);
void sofia_glue_pass_sdp(private_object_t *tech_pvt, char *sdp);
int sofia_glue_get_user_host(char *in, char **user, char **host);
switch_call_cause_t sofia_glue_sip_cause_to_freeswitch(int status);
@@ -449,3 +464,4 @@
void *pdata);
char *sofia_glue_execute_sql2str(sofia_profile_t *profile, switch_mutex_t *mutex, char *sql, char *resbuf, size_t len);
void sofia_glue_check_video_codecs(private_object_t *tech_pvt);
+void sofia_reg_release_gateway(sofia_gateway_t *gateway);
Modified: freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia.c
==============================================================================
--- freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia.c (original)
+++ freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia.c Sat Apr 28 21:16:49 2007
@@ -70,7 +70,7 @@
}
}
-
+
if (status != 100 && status != 200) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "event [%s] status [%d][%s] session: %s\n",
nua_event_name(event), status, phrase, session ? switch_channel_get_name(channel) : "n/a");
@@ -110,6 +110,10 @@
switch (event) {
case nua_r_shutdown:
+ if (status >= 200) {
+ su_root_break(profile->s_root);
+ }
+ break;
case nua_r_get_params:
case nua_r_invite:
case nua_r_unregister:
@@ -201,7 +205,7 @@
char *rpid = switch_event_get_header(event, "orig-rpid");
long expires = (long) time(NULL) + atol(exp_str);
char *profile_name = switch_event_get_header(event, "orig-profile-name");
- sofia_profile_t *profile;
+ sofia_profile_t *profile = NULL;
char buf[512];
if (!rpid) {
@@ -233,6 +237,9 @@
}
+ if (profile) {
+ switch_thread_rwlock_unlock(profile->rwlock);
+ }
}
}
@@ -340,7 +347,9 @@
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Starting thread for %s\n", profile->name);
- while (mod_sofia_globals.running == 1) {
+
+ sofia_set_pflag_locked(profile, PFLAG_RUNNING);
+ while (mod_sofia_globals.running == 1 && sofia_test_pflag(profile, PFLAG_RUNNING)) {
if (++ireg_loops >= IREG_SECONDS) {
sofia_reg_check_expire(profile, time(NULL));
ireg_loops = 0;
@@ -353,23 +362,40 @@
su_root_step(profile->s_root, 1000);
}
-
- sofia_glue_sql_close(profile);
+ //sofia_reg_check_expire(profile, 0);
+ //sofia_reg_check_gateway(profile, 0);
+ switch_thread_rwlock_wrlock(profile->rwlock);
sofia_reg_unregister(profile);
- su_home_unref(profile->home);
+ nua_shutdown(profile->nua);
+ su_root_run(profile->s_root);
+ nua_destroy(profile->nua);
+ while(0 && profile->inuse) {
+ switch_yield(1000000);
+ }
+
if (switch_event_create(&s_event, SWITCH_EVENT_UNPUBLISH) == SWITCH_STATUS_SUCCESS) {
switch_event_add_header(s_event, SWITCH_STACK_BOTTOM, "service", "_sip._udp");
switch_event_add_header(s_event, SWITCH_STACK_BOTTOM, "port", "%d", profile->sip_port);
switch_event_fire(&s_event);
}
+ sofia_glue_sql_close(profile);
+ su_home_unref(profile->home);
su_root_destroy(profile->s_root);
pool = profile->pool;
+
+ switch_mutex_lock(mod_sofia_globals.hash_mutex);
+ switch_core_hash_delete(mod_sofia_globals.profile_hash, profile->name);
+ switch_mutex_unlock(mod_sofia_globals.hash_mutex);
+
+ switch_thread_rwlock_unlock(profile->rwlock);
+
switch_core_destroy_memory_pool(&pool);
+
end:
switch_mutex_lock(mod_sofia_globals.mutex);
@@ -417,14 +443,15 @@
}
-switch_status_t config_sofia(int reload)
+switch_status_t config_sofia(int reload, char *profile_name)
{
char *cf = "sofia.conf";
switch_xml_t cfg, xml = NULL, xprofile, param, settings, profiles, gateway_tag, gateways_tag;
switch_status_t status = SWITCH_STATUS_SUCCESS;
sofia_profile_t *profile = NULL;
char url[512] = "";
-
+ sofia_gateway_t *gp;
+ int profile_found = 0;
if (!reload) {
su_init();
@@ -432,6 +459,14 @@
su_log_redirect(tport_log, logger, NULL);
}
+
+ if (!switch_strlen_zero(profile_name) && (profile = sofia_glue_find_profile(profile_name))) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Profile [%s] Already exists.\n", switch_str_nil(profile_name));
+ status = SWITCH_STATUS_FALSE;
+ switch_thread_rwlock_unlock(profile->rwlock);
+ return status;
+ }
+
if (!(xml = switch_xml_open_cfg(cf, &cfg, NULL))) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "open of %s failed\n", cf);
status = SWITCH_STATUS_FALSE;
@@ -458,7 +493,18 @@
char *xprofilename = (char *) switch_xml_attr_soft(xprofile, "name");
switch_memory_pool_t *pool = NULL;
-
+ if (!xprofilename) {
+ xprofilename = "unnamed";
+ }
+
+ if (profile_name) {
+ if (strcasecmp(profile_name, xprofilename)) {
+ continue;
+ } else {
+ profile_found = 1;
+ }
+ }
+
/* Setup the pool */
if ((status = switch_core_new_memory_pool(&pool)) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Memory Error!\n");
@@ -470,9 +516,7 @@
goto done;
}
- if (!xprofilename) {
- xprofilename = "unnamed";
- }
+
profile->pool = pool;
@@ -481,7 +525,8 @@
profile->dbname = switch_core_strdup(profile->pool, url);
switch_core_hash_init(&profile->chat_hash, profile->pool);
-
+ switch_thread_rwlock_create(&profile->rwlock, profile->pool);
+ switch_mutex_init(&profile->flag_mutex, SWITCH_MUTEX_NESTED, profile->pool);
profile->dtmf_duration = 100;
profile->codec_ms = 20;
@@ -503,7 +548,6 @@
if ((profile->odbc_pass = strchr(profile->odbc_user, ':'))) {
*profile->odbc_pass++ = '\0';
}
-
#else
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "ODBC IS NOT AVAILABLE!\n");
@@ -682,7 +726,7 @@
if ((gateways_tag = switch_xml_child(xprofile, "gateways"))) {
for (gateway_tag = switch_xml_child(gateways_tag, "gateway"); gateway_tag; gateway_tag = gateway_tag->next) {
char *name = (char *) switch_xml_attr_soft(gateway_tag, "name");
- outbound_reg_t *gateway;
+ sofia_gateway_t *gateway;
if (switch_strlen_zero(name)) {
name = "anonymous";
@@ -790,12 +834,15 @@
gateway->next = profile->gateways;
profile->gateways = gateway;
- if (sofia_reg_find_gateway(gateway->name)) {
+ if ((gp = sofia_reg_find_gateway(gateway->name))) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Ignoring duplicate gateway '%s'\n", gateway->name);
- } else if (sofia_reg_find_gateway(gateway->register_from)) {
+ sofia_reg_release_gateway(gp);
+ } else if ((gp=sofia_reg_find_gateway(gateway->register_from))) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Ignoring duplicate uri '%s'\n", gateway->register_from);
- } else if (sofia_reg_find_gateway(gateway->register_contact)) {
+ sofia_reg_release_gateway(gp);
+ } else if ((gp=sofia_reg_find_gateway(gateway->register_contact))) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Ignoring duplicate contact '%s'\n", gateway->register_from);
+ sofia_reg_release_gateway(gp);
} else {
sofia_reg_add_gateway(gateway->name, gateway);
sofia_reg_add_gateway(gateway->register_from, gateway);
@@ -816,6 +863,9 @@
}
profile = NULL;
}
+ if (profile_found) {
+ break;
+ }
}
}
done:
@@ -823,6 +873,11 @@
switch_xml_free(xml);
}
+ if (profile_name && !profile_found) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "No Such Profile '%s'\n", profile_name);
+ status = SWITCH_STATUS_FALSE;
+ }
+
return status;
}
@@ -1169,6 +1224,10 @@
tech_pvt->nh = NULL;
+ switch_mutex_lock(profile->flag_mutex);
+ profile->inuse--;
+ switch_mutex_unlock(profile->flag_mutex);
+
} else if (sofia_private) {
if (sofia_private->home) {
su_home_unref(sofia_private->home);
@@ -1706,7 +1765,7 @@
if (sip->sip_request->rq_url) {
- outbound_reg_t *gateway;
+ sofia_gateway_t *gateway;
char *from_key = switch_core_session_sprintf(session, "sip:%s@%s",
(char *) sip->sip_request->rq_url->url_user,
(char *) sip->sip_request->rq_url->url_host);
@@ -1714,6 +1773,7 @@
if ((gateway = sofia_reg_find_gateway(from_key))) {
context = gateway->register_context;
switch_channel_set_variable(channel, "sip_gateway", gateway->name);
+ sofia_reg_release_gateway(gateway);
}
}
Modified: freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia_glue.c
==============================================================================
--- freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia_glue.c (original)
+++ freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia_glue.c Sat Apr 28 21:16:49 2007
@@ -315,9 +315,13 @@
switch_mutex_lock(tech_pvt->flag_mutex);
+ switch_mutex_lock(profile->flag_mutex);
tech_pvt->flags = profile->flags;
- switch_mutex_unlock(tech_pvt->flag_mutex);
tech_pvt->profile = profile;
+ profile->inuse++;
+ switch_mutex_unlock(profile->flag_mutex);
+ switch_mutex_unlock(tech_pvt->flag_mutex);
+
if (tech_pvt->bte) {
tech_pvt->te = tech_pvt->bte;
} else if (!tech_pvt->te) {
@@ -1420,7 +1424,14 @@
sofia_profile_t *profile;
switch_mutex_lock(mod_sofia_globals.hash_mutex);
- profile = (sofia_profile_t *) switch_core_hash_find(mod_sofia_globals.profile_hash, key);
+ if ((profile = (sofia_profile_t *) switch_core_hash_find(mod_sofia_globals.profile_hash, key))) {
+ if (!sofia_test_pflag(profile, PFLAG_RUNNING)) {
+ profile = NULL;
+ } else if (switch_thread_rwlock_tryrdlock(profile->rwlock) != SWITCH_STATUS_SUCCESS) {
+ profile = NULL;
+ }
+ }
+
switch_mutex_unlock(mod_sofia_globals.hash_mutex);
return profile;
@@ -1508,6 +1519,7 @@
} else {
#endif
switch_core_db_close(profile->master_db);
+ profile->master_db = NULL;
#ifdef SWITCH_HAVE_ODBC
}
#endif
Modified: freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia_presence.c
==============================================================================
--- freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia_presence.c (original)
+++ freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia_presence.c Sat Apr 28 21:16:49 2007
@@ -43,7 +43,7 @@
{
char buf[256];
char *user, *host;
- sofia_profile_t *profile;
+ sofia_profile_t *profile = NULL;
char *ffrom = NULL;
nua_handle_t *msg_nh;
char *contact;
@@ -98,6 +98,10 @@
switch_safe_free(ffrom);
free(user);
+
+ if (profile) {
+ switch_thread_rwlock_unlock(profile->rwlock);
+ }
}
return SWITCH_STATUS_SUCCESS;
@@ -178,7 +182,7 @@
{
char *account, *dup_account, *yn, *host, *user;
char *sql;
- sofia_profile_t *profile;
+ sofia_profile_t *profile = NULL;
switch_stream_handle_t stream = { 0 };
switch_event_header_t *hp;
@@ -230,11 +234,16 @@
switch_safe_free(sql);
switch_safe_free(dup_account);
+
+ if (profile) {
+ switch_thread_rwlock_unlock(profile->rwlock);
+ }
+
}
void sofia_presence_event_handler(switch_event_t *event)
{
- sofia_profile_t *profile;
+ sofia_profile_t *profile = NULL;
switch_hash_index_t *hi;
void *val;
char *from = switch_event_get_header(event, "from");
@@ -364,6 +373,9 @@
sofia_presence_resub_callback,
profile);
+
+ switch_thread_rwlock_unlock(profile->rwlock);
+
switch_safe_free(sql);
}
switch_safe_free(user);
@@ -569,7 +581,7 @@
char *expires = argv[10];
char *body = argv[11];
char *exp;
- sofia_profile_t *profile;
+ sofia_profile_t *profile = NULL;
char *tmp, *id = NULL;
nua_handle_t *nh;
int expire_sec = atoi(expires);
@@ -606,6 +618,11 @@
switch_safe_free(id);
switch_safe_free(exp);
+
+ if (profile) {
+ switch_thread_rwlock_unlock(profile->rwlock);
+ }
+
return 0;
}
Modified: freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia_reg.c
==============================================================================
--- freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia_reg.c (original)
+++ freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia_reg.c Sat Apr 28 21:16:49 2007
@@ -39,7 +39,7 @@
void sofia_reg_unregister(sofia_profile_t *profile)
{
- outbound_reg_t *gateway_ptr;
+ sofia_gateway_t *gateway_ptr;
for (gateway_ptr = profile->gateways; gateway_ptr; gateway_ptr = gateway_ptr->next) {
if (gateway_ptr->sofia_private) {
free(gateway_ptr->sofia_private);
@@ -52,11 +52,16 @@
void sofia_reg_check_gateway(sofia_profile_t *profile, time_t now)
{
- outbound_reg_t *gateway_ptr;
+ sofia_gateway_t *gateway_ptr;
for (gateway_ptr = profile->gateways; gateway_ptr; gateway_ptr = gateway_ptr->next) {
int ss_state = nua_callstate_authenticating;
reg_state_t ostate = gateway_ptr->state;
+ if (!now) {
+ gateway_ptr->state = ostate = REG_STATE_UNREGED;
+ gateway_ptr->expires_str = "0";
+ }
+
switch (ostate) {
case REG_STATE_NOREG:
break;
@@ -80,14 +85,26 @@
gateway_ptr->sofia_private->gateway = gateway_ptr;
nua_handle_bind(gateway_ptr->nh, gateway_ptr->sofia_private);
- nua_register(gateway_ptr->nh,
- SIPTAG_FROM_STR(gateway_ptr->register_from),
- SIPTAG_CONTACT_STR(gateway_ptr->register_contact),
- SIPTAG_EXPIRES_STR(gateway_ptr->expires_str),
- NUTAG_REGISTRAR(gateway_ptr->register_proxy),
- NUTAG_OUTBOUND("no-options-keepalive"), NUTAG_OUTBOUND("no-validate"), NUTAG_KEEPALIVE(0), TAG_NULL());
- gateway_ptr->retry = now + 10;
+ if (now) {
+ nua_register(gateway_ptr->nh,
+ SIPTAG_FROM_STR(gateway_ptr->register_from),
+ SIPTAG_CONTACT_STR(gateway_ptr->register_contact),
+ SIPTAG_EXPIRES_STR(gateway_ptr->expires_str),
+ NUTAG_REGISTRAR(gateway_ptr->register_proxy),
+ NUTAG_OUTBOUND("no-options-keepalive"), NUTAG_OUTBOUND("no-validate"), NUTAG_KEEPALIVE(0), TAG_NULL());
+ gateway_ptr->retry = now + 10;
+ } else {
+ nua_unregister(gateway_ptr->nh,
+ SIPTAG_FROM_STR(gateway_ptr->register_from),
+ SIPTAG_CONTACT_STR(gateway_ptr->register_contact),
+ SIPTAG_EXPIRES_STR(gateway_ptr->expires_str),
+ NUTAG_REGISTRAR(gateway_ptr->register_proxy),
+ NUTAG_OUTBOUND("no-options-keepalive"), NUTAG_OUTBOUND("no-validate"), NUTAG_KEEPALIVE(0), TAG_NULL());
+ }
+
+ gateway_ptr->retry = now + time(NULL);
gateway_ptr->state = REG_STATE_TRYING;
+
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error registering %s\n", gateway_ptr->name);
gateway_ptr->state = REG_STATE_FAILED;
@@ -107,7 +124,6 @@
break;
}
}
-
}
@@ -157,7 +173,11 @@
}
#endif
- snprintf(sql, sizeof(sql), "select '%s',* from sip_registrations where expires > 0 and expires <= %ld", profile->name, (long) now);
+ if (now) {
+ snprintf(sql, sizeof(sql), "select '%s',* from sip_registrations where expires > 0 and expires <= %ld", profile->name, (long) now);
+ } else {
+ snprintf(sql, sizeof(sql), "select '%s',* from sip_registrations where expires > 0", profile->name);
+ }
switch_mutex_lock(profile->ireg_mutex);
sofia_glue_execute_sql_callback(profile,
@@ -166,12 +186,23 @@
sql,
sofia_reg_del_callback,
NULL);
-
- snprintf(sql, sizeof(sql), "delete from sip_registrations where expires > 0 and expires <= %ld", (long) now);
+ if (now) {
+ snprintf(sql, sizeof(sql), "delete from sip_registrations where expires > 0 and expires <= %ld", (long) now);
+ } else {
+ snprintf(sql, sizeof(sql), "delete from sip_registrations where expires > 0");
+ }
sofia_glue_execute_sql(profile, SWITCH_TRUE, sql, NULL);
- snprintf(sql, sizeof(sql), "delete from sip_authentication where expires > 0 and expires <= %ld", (long) now);
+ if (now) {
+ snprintf(sql, sizeof(sql), "delete from sip_authentication where expires > 0 and expires <= %ld", (long) now);
+ } else {
+ snprintf(sql, sizeof(sql), "delete from sip_authentication where expires > 0");
+ }
sofia_glue_execute_sql(profile, SWITCH_TRUE, sql, NULL);
- snprintf(sql, sizeof(sql), "delete from sip_subscriptions where expires > 0 and expires <= %ld", (long) now);
+ if (now) {
+ snprintf(sql, sizeof(sql), "delete from sip_subscriptions where expires > 0 and expires <= %ld", (long) now);
+ } else {
+ snprintf(sql, sizeof(sql), "delete from sip_subscriptions where expires > 0");
+ }
sofia_glue_execute_sql(profile, SWITCH_TRUE, sql, NULL);
switch_mutex_unlock(profile->ireg_mutex);
@@ -479,7 +510,7 @@
char const *phrase,
nua_t * nua, sofia_profile_t *profile, nua_handle_t * nh, switch_core_session_t *session, sip_t const *sip, tagi_t tags[])
{
- outbound_reg_t *gateway = NULL;
+ sofia_gateway_t *gateway = NULL;
sip_www_authenticate_t const *authenticate = NULL;
char const *realm = NULL;
char *p = NULL, *duprealm = NULL, *qrealm = NULL;
@@ -522,7 +553,7 @@
}
if (profile) {
- outbound_reg_t *gateway_ptr;
+ sofia_gateway_t *gateway_ptr;
if ((duprealm = strdup(realm))) {
qrealm = duprealm;
@@ -548,13 +579,21 @@
}
if (!gateway) {
+ switch_mutex_lock(mod_sofia_globals.hash_mutex);
for (gateway_ptr = profile->gateways; gateway_ptr; gateway_ptr = gateway_ptr->next) {
if (scheme && qrealm && !strcasecmp(gateway_ptr->register_scheme, scheme)
&& !strcasecmp(gateway_ptr->register_realm, qrealm)) {
gateway = gateway_ptr;
+
+ if (!switch_test_flag(gateway->profile, PFLAG_RUNNING)) {
+ gateway = NULL;
+ } else if (switch_thread_rwlock_tryrdlock(gateway->profile->rwlock) != SWITCH_STATUS_SUCCESS) {
+ gateway = NULL;
+ }
break;
}
}
+ switch_mutex_unlock(mod_sofia_globals.hash_mutex);
}
if (!gateway) {
@@ -578,7 +617,7 @@
tl_gets(tags, NUTAG_CALLSTATE_REF(ss_state), SIPTAG_WWW_AUTHENTICATE_REF(authenticate), TAG_END());
nua_authenticate(nh, SIPTAG_EXPIRES_STR(gateway->expires_str), NUTAG_AUTH(authentication), TAG_END());
-
+ sofia_reg_release_gateway(gateway);
return;
cancel:
@@ -761,18 +800,29 @@
}
-outbound_reg_t *sofia_reg_find_gateway(char *key)
+sofia_gateway_t *sofia_reg_find_gateway(char *key)
{
- outbound_reg_t *gateway;
+ sofia_gateway_t *gateway = NULL;
switch_mutex_lock(mod_sofia_globals.hash_mutex);
- gateway = (outbound_reg_t *) switch_core_hash_find(mod_sofia_globals.gateway_hash, key);
- switch_mutex_unlock(mod_sofia_globals.hash_mutex);
+ if ((gateway = (sofia_gateway_t *) switch_core_hash_find(mod_sofia_globals.gateway_hash, key))) {
+ if (!sofia_test_pflag(gateway->profile, PFLAG_RUNNING)) {
+ gateway = NULL;
+ } else if (switch_thread_rwlock_tryrdlock(gateway->profile->rwlock) != SWITCH_STATUS_SUCCESS) {
+ gateway = NULL;
+ }
+ }
+ switch_mutex_unlock(mod_sofia_globals.hash_mutex);
return gateway;
}
-void sofia_reg_add_gateway(char *key, outbound_reg_t * gateway)
+void sofia_reg_release_gateway(sofia_gateway_t *gateway)
+{
+ switch_thread_rwlock_unlock(gateway->profile->rwlock);
+}
+
+void sofia_reg_add_gateway(char *key, sofia_gateway_t * gateway)
{
switch_mutex_lock(mod_sofia_globals.hash_mutex);
switch_core_hash_insert(mod_sofia_globals.gateway_hash, key, gateway);
Modified: freeswitch/trunk/src/switch_odbc.c
==============================================================================
--- freeswitch/trunk/src/switch_odbc.c (original)
+++ freeswitch/trunk/src/switch_odbc.c Sat Apr 28 21:16:49 2007
@@ -372,6 +372,7 @@
switch_safe_free(handle->password);
free(handle);
}
+ *handlep = NULL;
}
SWITCH_DECLARE(switch_odbc_state_t) switch_odbc_handle_get_state(switch_odbc_handle_t *handle)
1
0
[commit] r5035 - in freeswitch/trunk/src: . include mod/applications/mod_conference mod/applications/mod_enum mod/dialplans/mod_dialplan_xml mod/endpoints/mod_sofia
by Freeswitch SVN 28 Apr '07
by Freeswitch SVN 28 Apr '07
28 Apr '07
Author: anthm
Date: Sat Apr 28 17:48:03 2007
New Revision: 5035
Modified:
freeswitch/trunk/src/include/switch_channel.h
freeswitch/trunk/src/mod/applications/mod_conference/mod_conference.c
freeswitch/trunk/src/mod/applications/mod_enum/mod_enum.c
freeswitch/trunk/src/mod/dialplans/mod_dialplan_xml/mod_dialplan_xml.c
freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia_glue.c
freeswitch/trunk/src/switch_channel.c
freeswitch/trunk/src/switch_ivr.c
freeswitch/trunk/src/switch_ivr_originate.c
Log:
add locking to vars
Modified: freeswitch/trunk/src/include/switch_channel.h
==============================================================================
--- freeswitch/trunk/src/include/switch_channel.h (original)
+++ freeswitch/trunk/src/include/switch_channel.h Sat Apr 28 17:48:03 2007
@@ -228,6 +228,7 @@
* @remark Use switch_hash_next and switch_hash_this with this function to iterate all the channel variables
*/
SWITCH_DECLARE(switch_hash_index_t *) switch_channel_variable_first(switch_channel_t *channel, switch_memory_pool_t *pool);
+SWITCH_DECLARE(void) switch_channel_variable_last(switch_channel_t *channel);
/*!
\brief Assign a caller extension to a given channel
Modified: freeswitch/trunk/src/mod/applications/mod_conference/mod_conference.c
==============================================================================
--- freeswitch/trunk/src/mod/applications/mod_conference/mod_conference.c (original)
+++ freeswitch/trunk/src/mod/applications/mod_conference/mod_conference.c Sat Apr 28 17:48:03 2007
@@ -1025,10 +1025,6 @@
if (member->energy_level > 3000) {
member->energy_level = 3000;
}
- switch_mutex_unlock(member->flag_mutex);
-
- snprintf(msg, sizeof(msg), "Energy level %d", member->energy_level);
- conference_member_say(member, msg, 0);
if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, CONF_EVENT_MAINT) == SWITCH_STATUS_SUCCESS) {
switch_channel_t *channel = switch_core_session_get_channel(member->session);
@@ -1040,6 +1036,12 @@
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "New-Level", "%d", member->energy_level);
switch_event_fire(&event);
}
+ switch_mutex_unlock(member->flag_mutex);
+
+ snprintf(msg, sizeof(msg), "Energy level %d", member->energy_level);
+ conference_member_say(member, msg, 0);
+
+
}
}
@@ -1051,10 +1053,6 @@
switch_mutex_lock(member->flag_mutex);
member->energy_level = member->conference->energy_level;
- switch_mutex_unlock(member->flag_mutex);
-
- snprintf(msg, sizeof(msg), "Energy level %d", member->energy_level);
- conference_member_say(member, msg, 0);
if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, CONF_EVENT_MAINT) == SWITCH_STATUS_SUCCESS) {
switch_channel_t *channel = switch_core_session_get_channel(member->session);
@@ -1066,6 +1064,11 @@
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "New-Level", "%d", member->energy_level);
switch_event_fire(&event);
}
+ switch_mutex_unlock(member->flag_mutex);
+
+ snprintf(msg, sizeof(msg), "Energy level %d", member->energy_level);
+ conference_member_say(member, msg, 0);
+
}
}
@@ -1080,10 +1083,6 @@
if (member->energy_level < 0) {
member->energy_level = 0;
}
- switch_mutex_unlock(member->flag_mutex);
-
- snprintf(msg, sizeof(msg), "Energy level %d", member->energy_level);
- conference_member_say(member, msg, 0);
if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, CONF_EVENT_MAINT) == SWITCH_STATUS_SUCCESS) {
switch_channel_t *channel = switch_core_session_get_channel(member->session);
@@ -1095,6 +1094,13 @@
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "New-Level", "%d", member->energy_level);
switch_event_fire(&event);
}
+ switch_mutex_unlock(member->flag_mutex);
+
+ snprintf(msg, sizeof(msg), "Energy level %d", member->energy_level);
+ conference_member_say(member, msg, 0);
+
+
+
}
}
@@ -1107,10 +1113,7 @@
switch_mutex_lock(member->flag_mutex);
member->volume_out_level++;
switch_normalize_volume(member->volume_out_level);
- switch_mutex_unlock(member->flag_mutex);
- snprintf(msg, sizeof(msg), "Volume level %d", member->volume_out_level);
- conference_member_say(member, msg, 0);
if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, CONF_EVENT_MAINT) == SWITCH_STATUS_SUCCESS) {
switch_channel_t *channel = switch_core_session_get_channel(member->session);
@@ -1122,6 +1125,12 @@
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "New-Level", "%d", member->volume_out_level);
switch_event_fire(&event);
}
+ switch_mutex_unlock(member->flag_mutex);
+
+
+ snprintf(msg, sizeof(msg), "Volume level %d", member->volume_out_level);
+ conference_member_say(member, msg, 0);
+
}
}
@@ -1133,10 +1142,7 @@
switch_mutex_lock(member->flag_mutex);
member->volume_out_level = 0;
- switch_mutex_unlock(member->flag_mutex);
- snprintf(msg, sizeof(msg), "Volume level %d", member->volume_out_level);
- conference_member_say(member, msg, 0);
if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, CONF_EVENT_MAINT) == SWITCH_STATUS_SUCCESS) {
switch_channel_t *channel = switch_core_session_get_channel(member->session);
@@ -1148,6 +1154,13 @@
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "New-Level", "%d", member->volume_out_level);
switch_event_fire(&event);
}
+ switch_mutex_unlock(member->flag_mutex);
+
+
+ snprintf(msg, sizeof(msg), "Volume level %d", member->volume_out_level);
+ conference_member_say(member, msg, 0);
+
+
}
}
@@ -1160,10 +1173,6 @@
switch_mutex_lock(member->flag_mutex);
member->volume_out_level--;
switch_normalize_volume(member->volume_out_level);
- switch_mutex_unlock(member->flag_mutex);
-
- snprintf(msg, sizeof(msg), "Volume level %d", member->volume_out_level);
- conference_member_say(member, msg, 0);
if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, CONF_EVENT_MAINT) == SWITCH_STATUS_SUCCESS) {
switch_channel_t *channel = switch_core_session_get_channel(member->session);
@@ -1175,6 +1184,12 @@
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "New-Level", "%d", member->volume_out_level);
switch_event_fire(&event);
}
+ switch_mutex_unlock(member->flag_mutex);
+
+ snprintf(msg, sizeof(msg), "Volume level %d", member->volume_out_level);
+ conference_member_say(member, msg, 0);
+
+
}
}
@@ -1187,10 +1202,7 @@
switch_mutex_lock(member->flag_mutex);
member->volume_in_level++;
switch_normalize_volume(member->volume_in_level);
- switch_mutex_unlock(member->flag_mutex);
- snprintf(msg, sizeof(msg), "Gain level %d", member->volume_in_level);
- conference_member_say(member, msg, 0);
if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, CONF_EVENT_MAINT) == SWITCH_STATUS_SUCCESS) {
switch_channel_t *channel = switch_core_session_get_channel(member->session);
@@ -1202,6 +1214,14 @@
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "New-Level", "%d", member->volume_in_level);
switch_event_fire(&event);
}
+ switch_mutex_unlock(member->flag_mutex);
+
+
+ snprintf(msg, sizeof(msg), "Gain level %d", member->volume_in_level);
+ conference_member_say(member, msg, 0);
+
+
+
}
}
@@ -1213,10 +1233,6 @@
switch_mutex_lock(member->flag_mutex);
member->volume_in_level = 0;
- switch_mutex_unlock(member->flag_mutex);
-
- snprintf(msg, sizeof(msg), "Gain level %d", member->volume_in_level);
- conference_member_say(member, msg, 0);
if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, CONF_EVENT_MAINT) == SWITCH_STATUS_SUCCESS) {
switch_channel_t *channel = switch_core_session_get_channel(member->session);
@@ -1228,6 +1244,13 @@
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "New-Level", "%d", member->volume_in_level);
switch_event_fire(&event);
}
+ switch_mutex_unlock(member->flag_mutex);
+
+ snprintf(msg, sizeof(msg), "Gain level %d", member->volume_in_level);
+ conference_member_say(member, msg, 0);
+
+
+
}
}
@@ -1240,10 +1263,7 @@
switch_mutex_lock(member->flag_mutex);
member->volume_in_level--;
switch_normalize_volume(member->volume_in_level);
- switch_mutex_unlock(member->flag_mutex);
- snprintf(msg, sizeof(msg), "Gain level %d", member->volume_in_level);
- conference_member_say(member, msg, 0);
if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, CONF_EVENT_MAINT) == SWITCH_STATUS_SUCCESS) {
switch_channel_t *channel = switch_core_session_get_channel(member->session);
@@ -1255,6 +1275,13 @@
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "New-Level", "%d", member->volume_in_level);
switch_event_fire(&event);
}
+ switch_mutex_unlock(member->flag_mutex);
+
+
+ snprintf(msg, sizeof(msg), "Gain level %d", member->volume_in_level);
+ conference_member_say(member, msg, 0);
+
+
}
}
Modified: freeswitch/trunk/src/mod/applications/mod_enum/mod_enum.c
==============================================================================
--- freeswitch/trunk/src/mod/applications/mod_enum/mod_enum.c (original)
+++ freeswitch/trunk/src/mod/applications/mod_enum/mod_enum.c Sat Apr 28 17:48:03 2007
@@ -591,11 +591,14 @@
void *vval;
const void *vvar;
- for (hi = switch_channel_variable_first(channel, switch_core_session_get_pool(session)); hi; hi = switch_hash_next(hi)) {
- switch_hash_this(hi, &vvar, NULL, &vval);
- if (vvar && !strncmp(vvar, "enum_", 5)) {
- switch_channel_set_variable(channel, (char *) vvar, NULL);
+ if ((hi = switch_channel_variable_first(channel, switch_core_session_get_pool(session)))) {
+ for (; hi; hi = switch_hash_next(hi)) {
+ switch_hash_this(hi, &vvar, NULL, &vval);
+ if (vvar && !strncmp(vvar, "enum_", 5)) {
+ switch_channel_set_variable(channel, (char *) vvar, NULL);
+ }
}
+ switch_channel_variable_last(channel);
}
for (rtp = globals.route_order; rtp; rtp = rtp->next) {
Modified: freeswitch/trunk/src/mod/dialplans/mod_dialplan_xml/mod_dialplan_xml.c
==============================================================================
--- freeswitch/trunk/src/mod/dialplans/mod_dialplan_xml/mod_dialplan_xml.c (original)
+++ freeswitch/trunk/src/mod/dialplans/mod_dialplan_xml/mod_dialplan_xml.c Sat Apr 28 17:48:03 2007
@@ -251,28 +251,30 @@
stream.write_function(&stream, "%s=%s&", prof_names[x], encode_buf);
}
+ if ((hi = switch_channel_variable_first(channel, switch_core_session_get_pool(session)))) {
+ for (; hi; hi = switch_hash_next(hi)) {
+ void *val;
+ const void *var;
+ switch_hash_this(hi, &var, NULL, &val);
+
+ new_len = (strlen((char *) var) * 3) + 1;
+ if (encode_len < new_len) {
+ char *tmp;
+
+ encode_len = new_len;
+
+ if (!(tmp = realloc(encode_buf, encode_len))) {
+ goto done;
+ }
- for (hi = switch_channel_variable_first(channel, switch_core_session_get_pool(session)); hi; hi = switch_hash_next(hi)) {
- void *val;
- const void *var;
- switch_hash_this(hi, &var, NULL, &val);
-
- new_len = (strlen((char *) var) * 3) + 1;
- if (encode_len < new_len) {
- char *tmp;
-
- encode_len = new_len;
-
- if (!(tmp = realloc(encode_buf, encode_len))) {
- goto done;
+ encode_buf = tmp;
}
- encode_buf = tmp;
- }
-
- switch_url_encode((char *) val, encode_buf, encode_len - 1);
- stream.write_function(&stream, "%s=%s&", (char *) var, encode_buf);
+ switch_url_encode((char *) val, encode_buf, encode_len - 1);
+ stream.write_function(&stream, "%s=%s&", (char *) var, encode_buf);
+ }
+ switch_channel_variable_last(channel);
}
e = (char *) stream.data + (strlen((char *) stream.data) - 1);
Modified: freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia_glue.c
==============================================================================
--- freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia_glue.c (original)
+++ freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia_glue.c Sat Apr 28 17:48:03 2007
@@ -570,17 +570,20 @@
SWITCH_STANDARD_STREAM(stream);
- for (hi = switch_channel_variable_first(channel, switch_core_session_get_pool(tech_pvt->session)); hi; hi = switch_hash_next(hi)) {
- switch_hash_this(hi, &vvar, NULL, &vval);
- if (vvar && vval) {
- const char *name = vvar;
- char *value = (char *) vval;
-
- if (!strncasecmp(name, SOFIA_SIP_HEADER_PREFIX, strlen(SOFIA_SIP_HEADER_PREFIX))) {
- const char *hname = name + strlen(SOFIA_SIP_HEADER_PREFIX);
- stream.write_function(&stream, "%s: %s\r\n", hname, value);
+ if ((hi = switch_channel_variable_first(channel, switch_core_session_get_pool(tech_pvt->session)))) {
+ for (; hi; hi = switch_hash_next(hi)) {
+ switch_hash_this(hi, &vvar, NULL, &vval);
+ if (vvar && vval) {
+ const char *name = vvar;
+ char *value = (char *) vval;
+
+ if (!strncasecmp(name, SOFIA_SIP_HEADER_PREFIX, strlen(SOFIA_SIP_HEADER_PREFIX))) {
+ const char *hname = name + strlen(SOFIA_SIP_HEADER_PREFIX);
+ stream.write_function(&stream, "%s: %s\r\n", hname, value);
+ }
}
}
+ switch_channel_variable_last(channel);
}
if (stream.data) {
Modified: freeswitch/trunk/src/switch_channel.c
==============================================================================
--- freeswitch/trunk/src/switch_channel.c (original)
+++ freeswitch/trunk/src/switch_channel.c Sat Apr 28 17:48:03 2007
@@ -115,6 +115,7 @@
switch_hash_t *variables;
switch_hash_t *private_hash;
switch_call_cause_t hangup_cause;
+ int vi;
};
@@ -306,6 +307,7 @@
char *v = NULL;
assert(channel != NULL);
+ switch_mutex_lock(channel->profile_mutex);
if (!(v = switch_core_hash_find(channel->variables, varname))) {
if (!channel->caller_profile || !(v = switch_caller_get_field_by_name(channel->caller_profile, varname))) {
if (!strcmp(varname, "base_dir")) {
@@ -314,27 +316,50 @@
v = switch_core_get_variable(varname);
}
}
+ switch_mutex_unlock(channel->profile_mutex);
return v;
}
+SWITCH_DECLARE(void) switch_channel_variable_last(switch_channel_t *channel)
+{
+ assert(channel != NULL);
+ if (channel->vi) {
+ switch_mutex_unlock(channel->profile_mutex);
+ }
+}
+
SWITCH_DECLARE(switch_hash_index_t *) switch_channel_variable_first(switch_channel_t *channel, switch_memory_pool_t *pool)
{
+ switch_hash_index_t *hi;
+
assert(channel != NULL);
- return switch_hash_first(pool, channel->variables);
+
+ if ((hi = switch_hash_first(pool, channel->variables))) {
+ switch_mutex_lock(channel->profile_mutex);
+ channel->vi = 1;
+ }
+
+ return hi;
}
SWITCH_DECLARE(switch_status_t) switch_channel_set_private(switch_channel_t *channel, char *key, void *private_info)
{
assert(channel != NULL);
+ switch_mutex_lock(channel->profile_mutex);
switch_core_hash_insert_dup(channel->private_hash, switch_core_session_strdup(channel->session, key), private_info);
+ switch_mutex_unlock(channel->profile_mutex);
return SWITCH_STATUS_SUCCESS;
}
SWITCH_DECLARE(void *) switch_channel_get_private(switch_channel_t *channel, char *key)
{
assert(channel != NULL);
- return switch_core_hash_find(channel->private_hash, key);
+ void *val;
+ switch_mutex_lock(channel->profile_mutex);
+ val = switch_core_hash_find(channel->private_hash, key);
+ switch_mutex_unlock(channel->profile_mutex);
+ return val;
}
SWITCH_DECLARE(switch_status_t) switch_channel_set_name(switch_channel_t *channel, char *name)
@@ -361,12 +386,14 @@
assert(channel != NULL);
if (varname) {
+ switch_mutex_lock(channel->profile_mutex);
switch_core_hash_delete(channel->variables, varname);
if (!switch_strlen_zero(value)) {
switch_core_hash_insert_dup(channel->variables, varname, switch_core_session_strdup(channel->session, value));
} else {
switch_core_hash_delete(channel->variables, varname);
}
+ switch_mutex_unlock(channel->profile_mutex);
return SWITCH_STATUS_SUCCESS;
}
@@ -378,12 +405,14 @@
assert(channel != NULL);
if (varname) {
+ switch_mutex_lock(channel->profile_mutex);
switch_core_hash_delete(channel->variables, varname);
if (!switch_strlen_zero(value)) {
switch_core_hash_insert_dup(channel->variables, varname, value);
} else {
switch_core_hash_delete(channel->variables, varname);
}
+ switch_mutex_unlock(channel->profile_mutex);
return SWITCH_STATUS_SUCCESS;
}
Modified: freeswitch/trunk/src/switch_ivr.c
==============================================================================
--- freeswitch/trunk/src/switch_ivr.c (original)
+++ freeswitch/trunk/src/switch_ivr.c Sat Apr 28 17:48:03 2007
@@ -900,11 +900,14 @@
void *vval;
const void *vvar;
- for (hi = switch_channel_variable_first(chana, switch_core_session_get_pool(sessa)); hi; hi = switch_hash_next(hi)) {
- switch_hash_this(hi, &vvar, NULL, &vval);
- if (vvar && vval && (!prefix || (var && !strncmp((char *) vvar, var, strlen(var))))) {
- switch_channel_set_variable(chanb, (char *) vvar, (char *) vval);
+ if ((hi = switch_channel_variable_first(chana, switch_core_session_get_pool(sessa)))) {
+ for (; hi; hi = switch_hash_next(hi)) {
+ switch_hash_this(hi, &vvar, NULL, &vval);
+ if (vvar && vval && (!prefix || (var && !strncmp((char *) vvar, var, strlen(var))))) {
+ switch_channel_set_variable(chanb, (char *) vvar, (char *) vval);
+ }
}
+ switch_channel_variable_last(chana);
}
}
@@ -1260,20 +1263,23 @@
}
}
- for (hi = switch_channel_variable_first(channel, switch_core_session_get_pool(session)); hi; hi = switch_hash_next(hi)) {
- switch_hash_this(hi, &vvar, NULL, &vval);
- if (vvar && vval) {
- if ((variable = switch_xml_add_child_d(variables, (char *) vvar, v_off++))) {
- char *data;
- char *value = (char *) vval;
- switch_size_t dlen = strlen(value) * 3;
-
- if ((data = switch_core_session_alloc(session, dlen))) {
- switch_url_encode(value, data, dlen);
- switch_xml_set_txt_d(variable, data);
+ if (((hi = switch_channel_variable_first(channel, switch_core_session_get_pool(session))))) {
+ for (; hi; hi = switch_hash_next(hi)) {
+ switch_hash_this(hi, &vvar, NULL, &vval);
+ if (vvar && vval) {
+ if ((variable = switch_xml_add_child_d(variables, (char *) vvar, v_off++))) {
+ char *data;
+ char *value = (char *) vval;
+ switch_size_t dlen = strlen(value) * 3;
+
+ if ((data = switch_core_session_alloc(session, dlen))) {
+ switch_url_encode(value, data, dlen);
+ switch_xml_set_txt_d(variable, data);
+ }
}
}
}
+ switch_channel_variable_last(channel);
}
caller_profile = switch_channel_get_caller_profile(channel);
Modified: freeswitch/trunk/src/switch_ivr_originate.c
==============================================================================
--- freeswitch/trunk/src/switch_ivr_originate.c (original)
+++ freeswitch/trunk/src/switch_ivr_originate.c Sat Apr 28 17:48:03 2007
@@ -323,11 +323,14 @@
assert(caller_channel != NULL);
/* Copy all the channel variables into the event */
- for (hi = switch_channel_variable_first(caller_channel, switch_core_session_get_pool(session)); hi; hi = switch_hash_next(hi)) {
- switch_hash_this(hi, &vvar, NULL, &vval);
- if (vvar && vval) {
- switch_event_add_header(var_event, SWITCH_STACK_BOTTOM, (void *) vvar, "%s", (char *) vval);
+ if ((hi = switch_channel_variable_first(caller_channel, switch_core_session_get_pool(session)))) {
+ for (; hi; hi = switch_hash_next(hi)) {
+ switch_hash_this(hi, &vvar, NULL, &vval);
+ if (vvar && vval) {
+ switch_event_add_header(var_event, SWITCH_STACK_BOTTOM, (void *) vvar, "%s", (char *) vval);
+ }
}
+ switch_channel_variable_last(caller_channel);
}
}
1
0
Author: mikej
Date: Sat Apr 28 15:27:17 2007
New Revision: 5034
Added:
freeswitch/trunk/scripts/combineconf.pl
Modified:
freeswitch/trunk/conf/conference.conf.xml
freeswitch/trunk/conf/default_context.xml
freeswitch/trunk/conf/dingaling.conf.xml
freeswitch/trunk/conf/enum.conf.xml
freeswitch/trunk/conf/freeswitch.xml
freeswitch/trunk/conf/sofia.conf.xml
Log:
updates, cleanups, and clarifications to the sample conf files. Uses more of the preprocessor variables for simplicity. FSBUILD-2 from Mark D. Anderson. Thanks Mark.
Modified: freeswitch/trunk/conf/conference.conf.xml
==============================================================================
--- freeswitch/trunk/conf/conference.conf.xml (original)
+++ freeswitch/trunk/conf/conference.conf.xml Sat Apr 28 15:27:17 2007
@@ -1,8 +1,8 @@
<!-- None of these paths are real if you want any of these options you need to really set them up -->
<configuration name="conference.conf" description="Audio Conference">
- <!-- Advertise certian presence on startup . -->
+ <!-- Advertise certain presence on startup . -->
<advertise>
- <room name="888(a)sub.mydomain.com" status="FreeSWITCH"/>
+ <room name="888@$${server_name}" status="FreeSWITCH"/>
</advertise>
<!-- These are the default keys that map when you do not specify a caller control group -->
@@ -29,7 +29,7 @@
<!--If no profile is specified it will default to "default"-->
<profile name="default">
<!-- Domain (for presence) -->
- <param name="domain" value="sub.mydomain.com"/>
+ <param name="domain" value="$${server_name}"/>
<!-- Sample Rate-->
<param name="rate" value="8000"/>
<!-- Number of milliseconds per frame -->
@@ -81,9 +81,9 @@
<!-- Conference pin -->
<!--<param name="pin" value="12345"/>-->
<!-- Default Caller ID Name for outbound calls -->
- <param name="caller-id-name" value="FreeSWITCH"/>
+ <param name="caller-id-name" value="$${outbound_caller_name}"/>
<!-- Default Caller ID Number for outbound calls -->
- <param name="caller-id-number" value="8777423583"/>
+ <param name="caller-id-number" value="$${outbound_caller_id}"/>
</profile>
</profiles>
</configuration>
Modified: freeswitch/trunk/conf/default_context.xml
==============================================================================
--- freeswitch/trunk/conf/default_context.xml (original)
+++ freeswitch/trunk/conf/default_context.xml Sat Apr 28 15:27:17 2007
@@ -29,7 +29,7 @@
<!-- Call the FreeSWITCH conference via SIP -->
<!--<extension name="FreeSWITCH Conference SIP">-->
<!--<condition field="destination_number" expression="^888$">-->
- <!--<action application="bridge" data="sofia/$${domain}/888(a)conference.freeswitch.org"/>-->
+ <!--<action application="bridge" data="sofia/$${sip_profile}/888(a)conference.freeswitch.org"/>-->
<!--</condition>-->
<!--</extension> -->
@@ -53,7 +53,7 @@
<!-- Request a certain tone/file to be played while you wait for the call to be answered-->
<action application="set" data="ringback=${us-ring}"/>
<!--<action application="set" data="ringback=/home/ring.wav"/>-->
- <action application="bridge" data="sofia/$${domain}/1234(a)conference.freeswitch.org"/>
+ <action application="bridge" data="sofia/$${sip_profile}/1234(a)conference.freeswitch.org"/>
</condition>
</extension>
@@ -67,7 +67,7 @@
<!-- Start a dynamic conference and call someone at the same time -->
<extension name="2000">
<condition field="destination_number" expression="^2000$">
- <action application="conference" data="bridge:mydynaconf:sofia/$${domain}/1234@conference.freeswitch.org"/>
+ <action application="conference" data="bridge:mydynaconf:sofia/$${sip_profile}/1234@conference.freeswitch.org"/>
</condition>
</extension>
Modified: freeswitch/trunk/conf/dingaling.conf.xml
==============================================================================
--- freeswitch/trunk/conf/dingaling.conf.xml (original)
+++ freeswitch/trunk/conf/dingaling.conf.xml Sat Apr 28 15:27:17 2007
@@ -8,12 +8,13 @@
<!-- Client Profile (Original mode) -->
<x-profile type="client">
- <param name="name" value="$${domain}"/>
+ <param name="name" value="$${xmpp_client_profile}"/>
<param name="login" value="myjid(a)myserver.com/talk"/>
<param name="password" value="mypass"/>
<param name="dialplan" value="XML"/>
<param name="message" value="Jingle all the way"/>
- <param name="rtp-ip" value="auto"/>
+ <param name="rtp-ip" value="$${bind_server_ip}"/>
+ <!-- <param name="ext-rtp-ip" value="$${external_rtp_ip"/> -->
<param name="auto-login" value="true"/>
<!-- SASL "plain" or "md5" -->
<param name="sasl" value="plain"/>
@@ -23,9 +24,6 @@
<param name="tls" value="true"/>
<!-- disable to trade async for more calls -->
<param name="use-rtp-timer" value="true"/>
- <!-- or -->
- <!-- <param name="rtp-ip" value="auto"/> -->
- <!-- <param name="ext-rtp-ip" value="stun:stun.server.com"/> -->
<!-- default extension (if one cannot be determined) -->
<param name="exten" value="888"/>
<!-- VAD choose one -->
@@ -37,11 +35,10 @@
<!-- Component (Server to Server Login) -->
<x-profile type="component">
- <!-- All traffic for *(a)sub.mydomain.com will come to you -->
- <param name="name" value="$${subdomain}"/>
+ <param name="name" value="$${xmpp_server_profile}"/>
<param name="password" value="secret"/>
<param name="dialplan" value="XML"/>
- <param name="rtp-ip" value="auto"/>
+ <param name="rtp-ip" value="$${bind_server_ip}"/>
<param name="server" value="jabber.server.org:5347"/>
<!-- disable to trade async for more calls -->
<param name="use-rtp-timer" value="true"/>
Modified: freeswitch/trunk/conf/enum.conf.xml
==============================================================================
--- freeswitch/trunk/conf/enum.conf.xml (original)
+++ freeswitch/trunk/conf/enum.conf.xml Sat Apr 28 15:27:17 2007
@@ -4,8 +4,8 @@
</settings>
<routes>
- <route service="E2U+SIP" regex="sip:(.*)" replace="sofia/$${domain}/$1"/>
+ <route service="E2U+SIP" regex="sip:(.*)" replace="sofia/$${sip_profile}/$1"/>
<route service="E2U+IAX2" regex="iax2:(.*)" replace="iax/$1"/>
- <route service="E2U+XMPP" regex="XMPP:(.*)" replace="dingaling/$${domain}/$1"/>
+ <route service="E2U+XMPP" regex="XMPP:(.*)" replace="dingaling/$${xmpp_server_profile}/$1"/>
</routes>
</configuration>
Modified: freeswitch/trunk/conf/freeswitch.xml
==============================================================================
--- freeswitch/trunk/conf/freeswitch.xml (original)
+++ freeswitch/trunk/conf/freeswitch.xml Sat Apr 28 15:27:17 2007
@@ -13,34 +13,115 @@
Don't modify it while freeswitch is running cos it is mem mapped in most cases =D
-->
- <!--#set "domain=mydomain.com"-->
- <!--#set "subdomain=sub.mydomain.com"-->
- <!--#set "default_codecs=PCMU@20i"-->
- <!--my domain is $${domain}-->
+ <!-- Preprocessor Variables
+ These are introduced when configuration strings must be consistent across modules.
+ -->
+ <!-- sip_profile
+ Must be a domain name if you are being a registry server; otherwise
+ can be any string.
+ used by: sofia.conf.xml enum.conf.xml default_context.xml directory.xml
+ -->
+ <!--#set "sip_profile=mydomain.com"-->
+ <!-- xmpp_client_profile and xmpp_server_profile
+ xmpp_client_profile can be any string.
+ xmpp_server_profile is appended to "dingaling_" to form the database name
+ containing the "subscriptions" table.
+ used by: dingaling.conf.xml enum.conf.xml
+ -->
+ <!--#set "xmpp_client_profile=xmppc"-->
+ <!--#set "xmpp_server_profile=xmpps"-->
+ <!-- bind_server_ip
+ Can be an ip address, a dns name, or "auto".
+ This determines an ip address available on this host to bind.
+ If you are separating RTP and SIP traffic, you will want to have
+ use different addresses where this variable appears.
+ Used by: sofia.conf.xml dingaling.conf.xml
+ -->
+ <!--#set "bind_server_ip=auto"-->
+ <!-- external_rtp_ip
+ Used as the public IP address for SDP.
+ Can be an ip address or a string like "stun:stun.server.com"
+ If unspecified, the bind_server_ip value is used.
+ Used by: sofia.conf.xml dingaling.conf.xml
+ -->
+ <!--#set "external_rtp_ip=stun:stun.server.com"-->
+ <!-- server_name
+ A public ip address or DNS name that is used when advertising conference
+ presence or registering sip.
+ Used by: conference.conf.xml
+ -->
+ <!-- outbound_caller_id and outbound_caller_name
+ The caller ID telephone number we should use when calling out.
+ Used by: conference.conf.xml
+ -->
+ <!--#set "outbound_caller_name=FreeSWITCH"-->
+ <!--#set "outbound_caller_id=8777423583"-->
+
<section name="configuration" description="Various Configuration">
<!--#include "switch.conf.xml"-->
<!--#include "modules.conf.xml"-->
- <!--#include "spidermonkey.conf.xml"-->
+
+ <!-- Order doesn't matter, but for clarity these are in same order as modules.conf.xml.
+ If they aren't loaded by modules.conf.xml, then they are ignored.
+ -->
+ <!-- Loggers -->
+ <!--#include "console.conf.xml"-->
+ <!--#include "syslog.conf.xml"-->
+
+ <!-- Multi-Faceted -->
+ <!--#include "enum.conf.xml"-->
+
+ <!-- XML Interfaces -->
+ <!--#include "xml_rpc.conf.xml"-->
+ <!--#include "xml_curl.conf.xml"-->
+ <!-- none for mod_xml_cdr -->
+
+ <!-- Event Handlers -->
+ <!--#include "cdr.conf.xml"-->
<!--#include "event_multicast.conf.xml"-->
<!--#include "event_socket.conf.xml"-->
+ <!--#include "xmpp_event.conf.xml"-->
+ <!--#include "zeroconf.conf.xml"-->
+
+ <!-- Directory Interfaces -->
+ <!-- none for mod_ldap; dialplan_directory.conf.xml has ldap connection info -->
+
+ <!-- Endpoints -->
+ <!--#include "dingaling.conf.xml"-->
<!--#include "iax.conf.xml"-->
- <!--#include "console.conf.xml"-->
- <!--#include "sofia.conf.xml"-->
- <!--#include "syslog.conf.xml"-->
- <!--#include "woomera.conf.xml"-->
- <!--#include "wanpipe.conf.xml"-->
<!--#include "portaudio.conf.xml"-->
<!--#include "alsa.conf.xml"-->
- <!--#include "zeroconf.conf.xml"-->
- <!--#include "xmpp_event.conf.xml"-->
- <!--#include "dialplan_directory.conf.xml"-->
- <!--#include "dingaling.conf.xml"-->
- <!--#include "xml_curl.conf.xml"-->
- <!--#include "xml_rpc.conf.xml"-->
- <!--#include "rss.conf.xml"-->
+ <!--#include "sofia.conf.xml"-->
+ <!--#include "wanpipe.conf.xml"-->
+ <!--#include "woomera.conf.xml"-->
+
+ <!-- Applications -->
+ <!-- none for mod_bridgecall, mod_commands, mod_echo, mod_park, mod_playback -->
<!--#include "conference.conf.xml"-->
- <!--#include "enum.conf.xml"-->
+ <!-- ivr.conf is used by mod_dptools -->
<!--#include "ivr.conf.xml"-->
+
+ <!-- Dialplan Interfaces -->
+ <!--#include "dialplan_directory.conf.xml"-->
+ <!-- mod_dialplan_xml is configured in the separate "dialplan" section. -->
+
+ <!-- Codec Interfaces -->
+ <!-- no configuration needed -->
+ <!-- File Format Interfaces -->
+ <!-- no configuration needed -->
+ <!-- Timers -->
+ <!-- no configuration needed -->
+
+ <!-- Languages -->
+ <!--#include "spidermonkey.conf.xml"-->
+ <!-- none for mod_perl -->
+
+ <!-- ASR /TTS -->
+ <!-- none for mod_cepstral -->
+ <!--#include "rss.conf.xml"-->
+
+ <!-- Say -->
+ <!-- none for mod_say_en -->
<!--#include "mod_cdr.conf.xml"-->
</section>
@@ -48,6 +129,8 @@
<!--#include "default_context.xml"-->
</section>
+ <!-- mod_dingaling is reliant on the vcard data in the "directory" section. -->
+ <!-- mod_sofia is reliant on the user data for authorization -->
<section name="directory" description="User Directory">
<!--#include "directory.xml"-->
</section>
@@ -66,3 +149,4 @@
</document>
+
Modified: freeswitch/trunk/conf/sofia.conf.xml
==============================================================================
--- freeswitch/trunk/conf/sofia.conf.xml (original)
+++ freeswitch/trunk/conf/sofia.conf.xml Sat Apr 28 15:27:17 2007
@@ -1,6 +1,6 @@
<configuration name="sofia.conf" description="sofia Endpoint">
<profiles>
- <profile name="$${domain}">
+ <profile name="$${sip_profile}">
<!-- Outbound Registrations -->
<gateways>
<!--<gateway name="asterlink.com">-->
@@ -28,12 +28,12 @@
<param name="sip-port" value="5060"/>
<param name="dialplan" value="enum,XML"/>
<param name="dtmf-duration" value="100"/>
- <param name="codec-prefs" value="$${default_codecs}"/>
+ <param name="codec-prefs" value="PCMU@20i"/>
<param name="codec-ms" value="20"/>
<param name="use-rtp-timer" value="true"/>
<param name="rtp-timer-name" value="soft"/>
- <param name="rtp-ip" value="auto"/>
- <param name="sip-ip" value="auto"/>
+ <param name="rtp-ip" value="$${bind_server_ip}"/>
+ <param name="sip-ip" value="$${bind_server_ip}"/>
<!--If you don't want to pass through timestampes from 1 RTP call to another (on a per call basis with rtp_rewrite_timestamps chanvar)-->
<!--<param name="rtp-rewrite-timestampes" value="true"/>-->
@@ -60,9 +60,8 @@
<!-- on authed calls, authenticate *all* the packets not just invite -->
<!--<param name="auth-all-packets" value="true"/>-->
- <!-- optional ; -->
- <!-- <param name="ext-rtp-ip" value="stun:stun.server.com"/>-->
- <!-- <param name="ext-rtp-ip" value="100.101.102.103"/> -->
+ <!-- <param name="ext-rtp-ip" value="$${external_rtp_ip}"/>-->
+
<!-- <param name="ext-sip-ip" value="100.101.102.103"/> -->
<!-- VAD choose one (out is a good choice); -->
<!-- <param name="vad" value="in"/> -->
Added: freeswitch/trunk/scripts/combineconf.pl
==============================================================================
--- (empty file)
+++ freeswitch/trunk/scripts/combineconf.pl Sat Apr 28 15:27:17 2007
@@ -0,0 +1,49 @@
+#!/usr/bin/perl -w
+use strict;
+
+=head1 NAME
+
+combineconf.pl - expand #include PIs in a freeswitch conf file
+
+=head1 SYNOPSIS
+
+ # cd conf
+ # ../scripts/combineconf.pl freeswitch.xml > freeswitch_combined.xml
+
+=head1 DESCRIPTION
+
+This is recursive, and will take multiple input files on the command line.
+
+You need to run it from the working directory that the relative include paths
+except to be resolved from.
+
+=head1 AUTHOR
+
+Mark D. Anderson (mda(a)discerning.com)
+Released under same terms as Perl, or alternatively the MPL.
+
+=cut
+
+use IO::File;
+
+sub filter_file {
+ my ($f) = @_;
+ my $fh = $f eq '-' ? \*STDIN : IO::File->new($f, 'r');
+ die "ERROR: Can't open $f: $!\n" unless $fh;
+ while(<$fh>) {
+ if (m/<!--#include\s+"(.*?)"/) {
+ filter_file($1);
+ }
+ else {print;}
+ }
+ undef $fh;
+}
+
+sub main {
+ die "Usage: $0 file1 ...\nCombined output goes to stdout. Use '-' as the filename to use stdin." unless @ARGV;
+ for(@ARGV) {
+ filter_file($_);
+ }
+}
+
+main();
1
0
Author: mikej
Date: Sat Apr 28 15:00:57 2007
New Revision: 5033
Modified:
freeswitch/trunk/src/include/switch_apr.h
freeswitch/trunk/src/switch_apr.c
Log:
wrap some other bits for use in the near future.
Modified: freeswitch/trunk/src/include/switch_apr.h
==============================================================================
--- freeswitch/trunk/src/include/switch_apr.h (original)
+++ freeswitch/trunk/src/include/switch_apr.h Sat Apr 28 15:00:57 2007
@@ -733,6 +733,10 @@
*/
SWITCH_DECLARE(switch_status_t) switch_file_write(switch_file_t * thefile, const void *buf, switch_size_t *nbytes);
+SWITCH_DECLARE(switch_status_t) switch_file_mktemp(switch_file_t **thefile, char *templ, int32_t flags, switch_memory_pool_t *pool);
+
+SWITCH_DECLARE(switch_size_t) switch_file_get_size(switch_file_t *thefile);
+
SWITCH_DECLARE(switch_status_t) switch_file_exists(const char *filename, switch_memory_pool_t *pool);
/** @} */
Modified: freeswitch/trunk/src/switch_apr.c
==============================================================================
--- freeswitch/trunk/src/switch_apr.c (original)
+++ freeswitch/trunk/src/switch_apr.c Sat Apr 28 15:00:57 2007
@@ -335,6 +335,17 @@
return apr_file_write(thefile, buf, nbytes);
}
+SWITCH_DECLARE(switch_status_t) switch_file_mktemp(switch_file_t **thefile, char *templ, int32_t flags, switch_memory_pool_t *pool)
+{
+ return apr_file_mktemp(thefile, templ, flags, pool);
+}
+
+SWITCH_DECLARE(switch_size_t) switch_file_get_size(switch_file_t *thefile)
+{
+ struct apr_finfo_t finfo;
+ return apr_file_info_get(&finfo, APR_FINFO_SIZE, thefile) == SWITCH_STATUS_SUCCESS ? (switch_size_t)finfo.size : 0;
+}
+
SWITCH_DECLARE(switch_status_t) switch_file_exists(const char *filename, switch_memory_pool_t *pool)
{
int32_t wanted = APR_FINFO_TYPE;
1
0
28 Apr '07
Author: mikej
Date: Sat Apr 28 10:48:18 2007
New Revision: 5032
Modified:
freeswitch/trunk/src/mod/languages/mod_spidermonkey/mod_spidermonkey.c
Log:
limit callback recursion to a happy number for all. FSCORE-6
Modified: freeswitch/trunk/src/mod/languages/mod_spidermonkey/mod_spidermonkey.c
==============================================================================
--- freeswitch/trunk/src/mod/languages/mod_spidermonkey/mod_spidermonkey.c (original)
+++ freeswitch/trunk/src/mod/languages/mod_spidermonkey/mod_spidermonkey.c Sat Apr 28 10:48:18 2007
@@ -623,7 +623,7 @@
return Event;
}
-#define MAX_STACK_DEPTH 12
+#define MAX_STACK_DEPTH 2
static switch_status_t js_common_callback(switch_core_session_t *session, void *input, switch_input_type_t itype, void *buf, unsigned int buflen)
{
1
0
27 Apr '07
Author: anthm
Date: Fri Apr 27 18:28:25 2007
New Revision: 5031
Modified:
freeswitch/trunk/src/mod/endpoints/mod_dingaling/mod_dingaling.c
Log:
sigh
Modified: freeswitch/trunk/src/mod/endpoints/mod_dingaling/mod_dingaling.c
==============================================================================
--- freeswitch/trunk/src/mod/endpoints/mod_dingaling/mod_dingaling.c (original)
+++ freeswitch/trunk/src/mod/endpoints/mod_dingaling/mod_dingaling.c Fri Apr 27 18:28:25 2007
@@ -2623,7 +2623,7 @@
tech_pvt->codec_index = -1;
tech_pvt->profile = profile;
tech_pvt->local_port = switch_rtp_request_port();
- //switch_set_flag_locked(tech_pvt, TFLAG_ANSWER);
+ switch_set_flag_locked(tech_pvt, TFLAG_ANSWER);
tech_pvt->recip = switch_core_session_strdup(session, from);
if (!(exten = ldl_session_get_value(dlsession, "dnis"))) {
exten = profile->exten;
1
0
[commit] r5030 - in freeswitch/trunk/src/mod: endpoints/mod_alsa endpoints/mod_sofia xml_int/mod_xml_rpc
by Freeswitch SVN 27 Apr '07
by Freeswitch SVN 27 Apr '07
27 Apr '07
Author: anthm
Date: Fri Apr 27 17:13:02 2007
New Revision: 5030
Modified:
freeswitch/trunk/src/mod/endpoints/mod_alsa/mod_alsa.c
freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia.c
freeswitch/trunk/src/mod/xml_int/mod_xml_rpc/mod_xml_rpc.c
Log:
update
Modified: freeswitch/trunk/src/mod/endpoints/mod_alsa/mod_alsa.c
==============================================================================
--- freeswitch/trunk/src/mod/endpoints/mod_alsa/mod_alsa.c (original)
+++ freeswitch/trunk/src/mod/endpoints/mod_alsa/mod_alsa.c Fri Apr 27 17:13:02 2007
@@ -26,7 +26,7 @@
* Anthony Minessale II <anthmct(a)yahoo.com>
*
*
- * mod_portaudio.c -- PortAudio Endpoint Module
+ * mod_alsa.c -- Alsa Endpoint Module
*
*/
#include <switch.h>
@@ -99,6 +99,7 @@
char *ring_file;
char *hold_file;
char *timer_name;
+ char *device_name;
int call_id;
switch_hash_t *call_hash;
switch_mutex_t *device_lock;
@@ -108,7 +109,7 @@
int codec_ms;
snd_pcm_t *audio_stream_in;
snd_pcm_t *audio_stream_out;
- snd_pcm_t *ring_stream;
+
switch_codec_t read_codec;
switch_codec_t write_codec;
@@ -127,33 +128,31 @@
#define PA_SLAVE 0
-SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_dialplan, globals.dialplan)
- SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_cid_name, globals.cid_name)
- SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_cid_num, globals.cid_num)
- SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_ring_file, globals.ring_file)
- SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_hold_file, globals.hold_file)
- SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_timer_name, globals.timer_name)
+SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_dialplan, globals.dialplan)//;
+SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_cid_name, globals.cid_name)//;
+SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_cid_num, globals.cid_num)//;
+SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_ring_file, globals.ring_file)//;
+SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_hold_file, globals.hold_file)//;
+SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_timer_name, globals.timer_name)//;
+SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_device_name, globals.device_name)//;
+
#define is_master(t) switch_test_flag(t, TFLAG_MASTER)
- static void add_pvt(private_t * tech_pvt, int master);
- static void remove_pvt(private_t * tech_pvt);
- static switch_status_t channel_on_init(switch_core_session_t *session);
- static switch_status_t channel_on_hangup(switch_core_session_t *session);
- static switch_status_t channel_on_ring(switch_core_session_t *session);
- static switch_status_t channel_on_loopback(switch_core_session_t *session);
- static switch_status_t channel_on_transmit(switch_core_session_t *session);
- static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *session,
- switch_caller_profile_t *outbound_profile,
- switch_core_session_t **new_session, switch_memory_pool_t **pool);
- static switch_status_t channel_read_frame(switch_core_session_t *session, switch_frame_t **frame, int timeout, switch_io_flag_t flags, int stream_id);
- static switch_status_t channel_write_frame(switch_core_session_t *session, switch_frame_t *frame, int timeout, switch_io_flag_t flags, int stream_id);
- static switch_status_t channel_kill_channel(switch_core_session_t *session, int sig);
- static switch_status_t engage_device(unsigned int samplerate, int codec_ms);
- static switch_status_t engage_ring_device(unsigned int sample_rate, int channels);
- static void deactivate_ring_device(void);
-
- static switch_status_t load_config(void);
- static switch_status_t pa_cmd(char *dest, switch_core_session_t *session, switch_stream_handle_t *stream);
- static switch_status_t padep(char *dest, switch_core_session_t *session, switch_stream_handle_t *stream);
+static void add_pvt(private_t * tech_pvt, int master);
+static void remove_pvt(private_t * tech_pvt);
+static switch_status_t channel_on_init(switch_core_session_t *session);
+static switch_status_t channel_on_hangup(switch_core_session_t *session);
+static switch_status_t channel_on_ring(switch_core_session_t *session);
+static switch_status_t channel_on_loopback(switch_core_session_t *session);
+static switch_status_t channel_on_transmit(switch_core_session_t *session);
+static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *session,
+ switch_caller_profile_t *outbound_profile,
+ switch_core_session_t **new_session, switch_memory_pool_t **pool);
+static switch_status_t channel_read_frame(switch_core_session_t *session, switch_frame_t **frame, int timeout, switch_io_flag_t flags, int stream_id);
+static switch_status_t channel_write_frame(switch_core_session_t *session, switch_frame_t *frame, int timeout, switch_io_flag_t flags, int stream_id);
+static switch_status_t channel_kill_channel(switch_core_session_t *session, int sig);
+static switch_status_t engage_device(unsigned int samplerate, int codec_ms);
+static switch_status_t load_config(void);
+static switch_status_t pa_cmd(char *dest, switch_core_session_t *session, switch_stream_handle_t *stream);
/*
@@ -161,7 +160,7 @@
returning SWITCH_STATUS_SUCCESS tells the core to execute the standard state method next
so if you fully implement the state you can return SWITCH_STATUS_FALSE to skip it.
*/
- static switch_status_t channel_on_init(switch_core_session_t *session)
+static switch_status_t channel_on_init(switch_core_session_t *session)
{
switch_channel_t *channel;
private_t *tech_pvt = NULL;
@@ -224,7 +223,7 @@
globals.read_codec.implementation->samples_per_second,
SWITCH_FILE_FLAG_READ | SWITCH_FILE_DATA_SHORT, NULL) == SWITCH_STATUS_SUCCESS) {
- if (engage_ring_device(fh.samplerate, fh.channels) != SWITCH_STATUS_SUCCESS) {
+ if (engage_device(fh.samplerate, fh.channels) != SWITCH_STATUS_SUCCESS) {
switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Ring Error!\n");
switch_core_file_close(&fh);
@@ -265,7 +264,7 @@
if (olen == 0) {
break;
}
- snd_pcm_writei(globals.ring_stream, abuf, (int) olen);
+ snd_pcm_writei(globals.audio_stream_out, abuf, (int) olen);
}
}
}
@@ -277,7 +276,6 @@
}
if (ring_file) {
- deactivate_ring_device();
switch_core_file_close(&fh);
switch_core_codec_destroy(&tech_pvt->write_codec);
switch_core_timer_destroy(&tech_pvt->timer);
@@ -335,27 +333,22 @@
static void deactivate_audio_device(void)
{
+
switch_mutex_lock(globals.device_lock);
if (globals.audio_stream_in) {
+ snd_pcm_drain(globals.audio_stream_in);
snd_pcm_close(globals.audio_stream_in);
globals.audio_stream_in = NULL;
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Close IN stream\n");
}
if (globals.audio_stream_out) {
+ snd_pcm_drain(globals.audio_stream_out);
snd_pcm_close(globals.audio_stream_out);
globals.audio_stream_out = NULL;
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Close OUT stream\n");
}
switch_mutex_unlock(globals.device_lock);
-}
-
-
-static void deactivate_ring_device(void)
-{
- switch_mutex_lock(globals.device_lock);
- if (globals.ring_stream) {
- snd_pcm_close(globals.ring_stream);
- globals.ring_stream = NULL;
- }
- switch_mutex_unlock(globals.device_lock);
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "DONE\n");
}
@@ -423,8 +416,7 @@
if (globals.call_list) {
switch_set_flag_locked(globals.call_list, TFLAG_MASTER);
} else {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "No more channels, deactivating audio\n");
- deactivate_audio_device();
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "No more channels\n");
}
switch_mutex_unlock(globals.pvt_lock);
@@ -604,12 +596,12 @@
goto hold;
}
- cng:
+ cng:
switch_yield(globals.read_codec.implementation->microseconds_per_frame);
*frame = &globals.cng_frame;
return SWITCH_STATUS_SUCCESS;
- hold:
+ hold:
{
switch_size_t olen = globals.read_codec.implementation->samples_per_frame;
@@ -638,11 +630,9 @@
}
switch_mutex_lock(globals.device_lock);
-
-
- if ((samples = snd_pcm_readi (globals.audio_stream_in, globals.read_frame.data, globals.read_codec.implementation->samples_per_frame)) != 0) {
- globals.read_frame.datalen = samples / 2;
- globals.read_frame.samples = globals.read_frame.datalen / 2;
+ if ((samples = snd_pcm_readi (globals.audio_stream_in, globals.read_frame.data, globals.read_codec.implementation->samples_per_frame)) > 0) {
+ globals.read_frame.datalen = samples * 2;
+ globals.read_frame.samples = samples;
switch_core_timer_check(&globals.timer);
globals.read_frame.timestamp = globals.timer.samplecount;
@@ -734,52 +724,12 @@
return SWITCH_STATUS_SUCCESS;
}
-static switch_api_interface_t send_dtmf_interface = {
- /*.interface_name */ "padtmf",
- /*.desc */ "DEPRICATED (see 'pa')",
- /*.function */ padep,
- /*.syntax */ "DEPRICATED (see 'pa')",
- /*.next */ NULL
-};
-
-static switch_api_interface_t answer_call_interface = {
- /*.interface_name */ "paoffhook",
- /*.desc */ "DEPRICATED (see 'pa')",
- /*.function */ padep,
- /*.syntax */ "DEPRICATED (see 'pa')",
- /*.next */ &send_dtmf_interface
-};
-
-static switch_api_interface_t channel_info_interface = {
- /*.interface_name */ "painfo",
- /*.desc */ "DEPRICATED (see 'pa')",
- /*.function */ padep,
- /*.syntax */ "DEPRICATED (see 'pa')",
- /*.next */ &answer_call_interface
-};
-
-static switch_api_interface_t channel_hup_interface = {
- /*.interface_name */ "pahup",
- /*.desc */ "DEPRICATED (see 'pa')",
- /*.function */ padep,
- /*.syntax */ "DEPRICATED (see 'pa')",
- /*.next */ &channel_info_interface
-};
-
-static switch_api_interface_t channel_call_interface = {
- /*.interface_name */ "pacall",
- /*.desc */ "DEPRICATED (see 'pa')",
- /*.function */ padep,
- /*.syntax */ "DEPRICATED (see 'pa')",
- /*.next */ &channel_hup_interface
-};
-
static switch_api_interface_t channel_api_interface = {
- /*.interface_name */ "pa",
+ /*.interface_name */ "alsa",
/*.desc */ "Alsa",
/*.function */ pa_cmd,
/*.syntax */ "<command> [<args>]",
- /*.next */ &channel_call_interface
+ /*.next */
};
static const switch_state_handler_table_t channel_event_handlers = {
@@ -947,6 +897,8 @@
set_global_hold_file(val);
} else if (!strcmp(var, "timer-name")) {
set_global_timer_name(val);
+ } else if (!strcmp(var, "device-name")) {
+ set_global_device_name(val);
} else if (!strcmp(var, "sample-rate")) {
globals.sample_rate = atoi(val);
} else if (!strcmp(var, "codec-ms")) {
@@ -965,6 +917,10 @@
set_global_dialplan("default");
}
+ if (!globals.device_name) {
+ set_global_device_name("default");
+ }
+
if (!globals.sample_rate) {
globals.sample_rate = 8000;
}
@@ -988,6 +944,8 @@
SWITCH_MOD_DECLARE(switch_status_t) switch_module_shutdown(void)
{
+ deactivate_audio_device();
+
if (globals.read_codec.implementation) {
switch_core_codec_destroy(&globals.read_codec);
}
@@ -1005,7 +963,7 @@
{
int err = 0;
snd_pcm_hw_params_t *hw_params = NULL;
- char *device = "default";
+ char *device = globals.device_name;
if (globals.audio_stream_in && globals.audio_stream_out) {
return SWITCH_STATUS_SUCCESS;
@@ -1038,18 +996,18 @@
} else {
if (switch_core_codec_init(&globals.write_codec,
"L16",
- NULL,
+ NULL,
sample_rate, codec_ms, 1, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE, NULL,
NULL) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Can't load codec?\n");
switch_core_codec_destroy(&globals.read_codec);
return SWITCH_STATUS_FALSE;
- }
+ }
}
if (switch_core_timer_init(&globals.timer,
globals.timer_name, codec_ms, globals.read_codec.implementation->samples_per_frame,
- module_pool) != SWITCH_STATUS_SUCCESS) {
+ module_pool) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "setup timer failed!\n");
switch_core_codec_destroy(&globals.read_codec);
switch_core_codec_destroy(&globals.write_codec);
@@ -1121,13 +1079,13 @@
hw_params = NULL;
-
if ((err = snd_pcm_open (&globals.audio_stream_in, device, SND_PCM_STREAM_CAPTURE, 0)) < 0) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "cannot open audio device %s (%s)\n",
device,
snd_strerror (err));
goto fail;
}
+
if ((err = snd_pcm_hw_params_malloc (&hw_params)) < 0) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "cannot allocate hardware parameter structure (%s)\n",
snd_strerror (err));
@@ -1163,7 +1121,19 @@
snd_strerror (err));
goto fail;
}
-
+
+ if ((err = snd_pcm_hw_params_set_period_time (globals.audio_stream_in, hw_params, globals.read_codec.implementation->microseconds_per_frame, 0)) < 0) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "cannot set period time (%s)\n",
+ snd_strerror (err));
+ goto fail;
+ }
+
+ if ((err = snd_pcm_hw_params_set_period_size (globals.audio_stream_in, hw_params, globals.read_codec.implementation->samples_per_frame, 0)) < 0) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "cannot set period size (%s)\n",
+ snd_strerror (err));
+ goto fail;
+ }
+
if ((err = snd_pcm_hw_params (globals.audio_stream_in, hw_params)) < 0) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "cannot set parameters (%s)\n",
snd_strerror (err));
@@ -1181,11 +1151,23 @@
goto fail;
}
+ if ((err = snd_pcm_start (globals.audio_stream_out)) < 0) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "cannot start audio interface for use (%s)\n",
+ snd_strerror (err));
+ goto fail;
+ }
+
if ((err = snd_pcm_prepare (globals.audio_stream_in)) < 0) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "cannot prepare audio interface for use (%s)\n",
snd_strerror (err));
goto fail;
}
+
+ if ((err = snd_pcm_start (globals.audio_stream_in)) < 0) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "cannot start audio interface for use (%s)\n",
+ snd_strerror (err));
+ goto fail;
+ }
switch_mutex_unlock(globals.device_lock);
return SWITCH_STATUS_SUCCESS;
@@ -1217,108 +1199,6 @@
}
-
-static switch_status_t engage_ring_device(unsigned int sample_rate, int channels)
-{
- int err = 0;
- snd_pcm_hw_params_t *hw_params;
- char *device = "default";
-
- if (globals.ring_stream) {
- return SWITCH_STATUS_SUCCESS;
- }
-
- if (!sample_rate) {
- sample_rate = globals.sample_rate;
- }
-
- switch_mutex_lock(globals.device_lock);
- /* LOCKED ************************************************************************************************** */
-
-
- if ((err = snd_pcm_open (&globals.ring_stream, device, SND_PCM_STREAM_PLAYBACK, 0)) < 0) {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "cannot open audio device %s (%s)\n",
- device,
- snd_strerror (err));
- goto fail;
- }
-
- if ((err = snd_pcm_hw_params_malloc (&hw_params)) < 0) {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "cannot allocate hardware parameter structure (%s)\n",
- snd_strerror (err));
- goto fail;
- }
-
- if ((err = snd_pcm_hw_params_any (globals.ring_stream, hw_params)) < 0) {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "cannot initialize hardware parameter structure (%s)\n",
- snd_strerror (err));
- goto fail;
- }
-
- if ((err = snd_pcm_hw_params_set_access (globals.ring_stream, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "cannot set access type (%s)\n",
- snd_strerror (err));
- goto fail;
- }
-
- if ((err = snd_pcm_hw_params_set_format (globals.ring_stream, hw_params, SND_PCM_FORMAT_S16_LE)) < 0) {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "cannot set sample format (%s)\n",
- snd_strerror (err));
- goto fail;
- }
-
- if ((err = snd_pcm_hw_params_set_rate_near (globals.ring_stream, hw_params, &sample_rate, 0)) < 0) {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "cannot set sample rate (%s)\n",
- snd_strerror (err));
- goto fail;
- }
-
- if ((err = snd_pcm_hw_params_set_channels (globals.ring_stream, hw_params, 1)) < 0) {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "cannot set channel count (%s)\n",
- snd_strerror (err));
- goto fail;
- }
-
- if ((err = snd_pcm_hw_params (globals.ring_stream, hw_params)) < 0) {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "cannot set parameters (%s)\n",
- snd_strerror (err));
- goto fail;
- }
-
- if (hw_params) {
- snd_pcm_hw_params_free (hw_params);
- hw_params = NULL;
- }
-
- if ((err = snd_pcm_prepare (globals.ring_stream)) < 0) {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "cannot prepare audio interface for use (%s)\n",
- snd_strerror (err));
- goto fail;
- }
-
- switch_mutex_unlock(globals.device_lock);
- return SWITCH_STATUS_SUCCESS;
-
- fail:
- switch_mutex_unlock(globals.device_lock);
-
-
- if (hw_params) {
- snd_pcm_hw_params_free (hw_params);
- hw_params = NULL;
- }
-
- if (globals.ring_stream) {
- snd_pcm_close (globals.ring_stream);
- }
-
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Can't open audio device!\n");
- switch_core_codec_destroy(&globals.read_codec);
- switch_core_codec_destroy(&globals.write_codec);
-
- return SWITCH_STATUS_FALSE;
-}
-
static switch_status_t dtmf_call(char **argv, int argc, switch_stream_handle_t *stream)
{
char *dtmf = argv[0];
@@ -1377,7 +1257,7 @@
stream->write_function(stream, "NO SUCH CALL\n");
}
- done:
+ done:
switch_mutex_unlock(globals.pvt_lock);
return SWITCH_STATUS_SUCCESS;
@@ -1444,7 +1324,7 @@
break;
}
}
- done:
+ done:
switch_mutex_unlock(globals.pvt_lock);
stream->write_function(stream, "Answered %d channels.\n", x);
@@ -1498,7 +1378,7 @@
goto bad;
}
- desc:
+ desc:
x = 0;
stream->write_function(stream, "FLAGS: ");
if (switch_test_flag((&globals), GFLAG_EAR)) {
@@ -1515,9 +1395,9 @@
goto done;
- bad:
+ bad:
stream->write_function(stream, "Usage: flags [on|off] <flags>\n");
- done:
+ done:
return SWITCH_STATUS_SUCCESS;
}
@@ -1636,12 +1516,6 @@
return SWITCH_STATUS_SUCCESS;
}
-static switch_status_t padep(char *cmd, switch_core_session_t *isession, switch_stream_handle_t *stream)
-{
- stream->write_function(stream, "This command no longer exists (try 'pa help')\n");
- return SWITCH_STATUS_SUCCESS;
-}
-
static switch_status_t pa_cmd(char *cmd, switch_core_session_t *isession, switch_stream_handle_t *stream)
{
char *argv[1024] = { 0 };
@@ -1650,22 +1524,66 @@
switch_status_t status = SWITCH_STATUS_SUCCESS;
pa_command_t func = NULL;
int lead = 1, devval = 0;
+ char *wcmd = NULL, *action = NULL;
+ char cmd_buf[1024] = "";
+
const char *usage_string = "USAGE:\n"
"--------------------------------------------------------------------------------\n"
- "pa help\n"
- "pa dump\n"
- "pa call <dest> [<dialplan> <cid_name> <cid_num> <rate>]\n"
- "pa answer [<call_id>]\n"
- "pa hangup [<call_id>]\n"
- "pa list\n"
- "pa switch [<call_id>|none]\n"
- "pa dtmf <digit string>\n"
- "pa flags [on|off] [ear] [mouth]\n"
+ "alsa help\n"
+ "alsa dump\n"
+ "alsa call <dest> [<dialplan> <cid_name> <cid_num> <rate>]\n"
+ "alsa answer [<call_id>]\n"
+ "alsa hangup [<call_id>]\n"
+ "alsa list\n"
+ "alsa switch [<call_id>|none]\n"
+ "alsa dtmf <digit string>\n"
+ "alsa flags [on|off] [ear] [mouth]\n"
"--------------------------------------------------------------------------------\n";
- if (switch_strlen_zero(cmd)) {
- stream->write_function(stream, "%s", usage_string);
- goto done;
+ if (stream->event) {
+#if 0
+ switch_event_header_t *hp;
+ stream->write_function(stream, "<pre>");
+ for (hp = stream->event->headers; hp; hp = hp->next) {
+ stream->write_function(stream, "[%s]=[%s]\n", hp->name, hp->value);
+ }
+ stream->write_function(stream, "</pre>");
+#endif
+
+ wcmd = switch_str_nil(switch_event_get_header(stream->event, "wcmd"));
+ action = switch_event_get_header(stream->event, "action");
+
+ if (action) {
+ if (strlen(action) == 1) {
+ snprintf(cmd_buf, sizeof(cmd_buf), "dtmf %s", action);
+ cmd = cmd_buf;
+ } else if (!strcmp(action, "mute")) {
+ snprintf(cmd_buf, sizeof(cmd_buf), "flags off mouth");
+ cmd = cmd_buf;
+ } else if (!strcmp(action, "unmute")) {
+ snprintf(cmd_buf, sizeof(cmd_buf), "flags on mouth");
+ cmd = cmd_buf;
+ } else if (!strcmp(action, "switch")) {
+ snprintf(cmd_buf, sizeof(cmd_buf), "switch %s", wcmd);
+ cmd = cmd_buf;
+ } else if (!strcmp(action, "call")) {
+ snprintf(cmd_buf, sizeof(cmd_buf), "call %s", wcmd);
+ cmd = cmd_buf;
+ } else if (!strcmp(action, "hangup") || !strcmp(action, "list") || !strcmp(action, "answer")) {
+ cmd = action;
+ }
+ }
+
+ if (switch_strlen_zero(cmd)) {
+ goto done;
+ }
+
+ } else {
+
+ if (switch_strlen_zero(cmd)) {
+ stream->write_function(stream, "%s", usage_string);
+ goto done;
+ }
}
if (!(mycmd = strdup(cmd))) {
@@ -1711,7 +1629,43 @@
}
}
- done:
+ done:
+
+ if (stream->event) {
+
+ stream->write_function(stream,
+ "<br><br><table align=center><tr><td><center><form method=post>\n"
+ "<input type=text name=wcmd size=40><br><br>\n"
+
+ "<input name=action type=submit value=\"call\"> "
+ "<input name=action type=submit value=\"hangup\"> "
+ "<input name=action type=submit value=\"list\"> "
+ "<input name=action type=submit value=\"switch\"> "
+ "<input name=action type=submit value=\"mute\"> "
+ "<input name=action type=submit value=\"unmute\"> "
+ "<input name=action type=submit value=\"answer\"> <br><br>"
+ "<table border=1>\n"
+ "<tr><td><input name=action type=submit value=\"1\"></td>"
+ "<td><input name=action type=submit value=\"2\"></td>"
+ "<td><input name=action type=submit value=\"3\"></td></tr>\n"
+
+ "<tr><td><input name=action type=submit value=\"4\"></td>"
+ "<td><input name=action type=submit value=\"5\"></td>"
+ "<td><input name=action type=submit value=\"6\"></td></tr>\n"
+
+ "<tr><td><input name=action type=submit value=\"7\"></td>"
+ "<td><input name=action type=submit value=\"8\"></td>"
+ "<td><input name=action type=submit value=\"9\"></td></tr>\n"
+
+ "<tr><td><input name=action type=submit value=\"*\"></td>"
+ "<td><input name=action type=submit value=\"0\"></td>"
+ "<td><input name=action type=submit value=\"#\"></td></tr>\n"
+ "</table>"
+
+ "</form><br></center></td></tr></table>\n"
+ );
+ }
+
switch_safe_free(mycmd);
Modified: freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia.c
==============================================================================
--- freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia.c (original)
+++ freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia.c Fri Apr 27 17:13:02 2007
@@ -254,11 +254,15 @@
profile->s_root = su_root_create(NULL);
profile->home = su_home_new(sizeof(*profile->home));
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Creating agent for %s\n", profile->name);
+
profile->nua = nua_create(profile->s_root, /* Event loop */
sofia_event_callback, /* Callback for processing events */
profile, /* Additional data to pass to callback */
NUTAG_URL(profile->bindurl), NTATAG_UDP_MTU(65536), TAG_END()); /* Last tag should always finish the sequence */
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Created agent for %s\n", profile->name);
+
nua_set_params(profile->nua,
//NUTAG_EARLY_MEDIA(1),
NUTAG_AUTOANSWER(0),
@@ -275,6 +279,7 @@
TAG_IF((profile->pflags & PFLAG_PRESENCE), NUTAG_ALLOW_EVENTS("message-summary")),
SIPTAG_SUPPORTED_STR("100rel, precondition"), SIPTAG_USER_AGENT_STR(SOFIA_USER_AGENT), TAG_END());
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Set params for %s\n", profile->name);
for (node = profile->aliases; node; node = node->next) {
node->nua = nua_create(profile->s_root, /* Event loop */
@@ -301,6 +306,7 @@
goto end;
}
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "activated db for %s\n", profile->name);
switch_mutex_init(&profile->ireg_mutex, SWITCH_MUTEX_NESTED, profile->pool);
switch_mutex_init(&profile->gateway_mutex, SWITCH_MUTEX_NESTED, profile->pool);
@@ -332,6 +338,8 @@
sofia_presence_establish_presence(profile);
}
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Starting thread for %s\n", profile->name);
+
while (mod_sofia_globals.running == 1) {
if (++ireg_loops >= IREG_SECONDS) {
sofia_reg_check_expire(profile, time(NULL));
Modified: freeswitch/trunk/src/mod/xml_int/mod_xml_rpc/mod_xml_rpc.c
==============================================================================
--- freeswitch/trunk/src/mod/xml_int/mod_xml_rpc/mod_xml_rpc.c (original)
+++ freeswitch/trunk/src/mod/xml_int/mod_xml_rpc/mod_xml_rpc.c Fri Apr 27 17:13:02 2007
@@ -169,6 +169,9 @@
}
if (switch_event_create(&stream.event, SWITCH_EVENT_API) == SWITCH_STATUS_SUCCESS) {
+ const char * const content_length = RequestHeaderValue(r, "content-length");
+
+
if (r->uri)
switch_event_add_header(stream.event, SWITCH_STACK_BOTTOM, "HTTP-URI", "%s", r->uri);
if (r->query)
@@ -187,6 +190,82 @@
switch_event_add_header(stream.event, SWITCH_STACK_BOTTOM, "HTTP-USER", "%s", r->user);
if (r->port)
switch_event_add_header(stream.event, SWITCH_STACK_BOTTOM, "HTTP-PORT", "%u", r->port);
+ if (r->query || content_length) {
+ char *q, *qd;
+ char *next;
+ char *query = r->query;
+ char *name, *val;
+ char qbuf[8192] = "";
+
+ if (r->method == m_post && content_length) {
+ int len = atoi(content_length);
+ int qlen = 0;
+
+ if (len > 0) {
+ int succeeded;
+ char *qp = qbuf;
+ do {
+ int blen = r->conn->buffersize - r->conn->bufferpos;
+
+ if ((qlen + blen) > len) {
+ blen = len - qlen;
+ }
+
+ qlen += blen;
+
+ if ( qlen > sizeof(qbuf) ) {
+ break;
+ }
+
+ memcpy(qp, r->conn->buffer + r->conn->bufferpos, blen);
+ qp += blen;
+
+ if (qlen >= len) {
+ break;
+ }
+ } while ((succeeded = ConnRead(r->conn, r->server->timeout)));
+
+ query = qbuf;
+ }
+
+ }
+ if (query) {
+ switch_event_add_header(stream.event, SWITCH_STACK_BOTTOM, "HTTP-QUERY", "%s", query);
+
+ qd = strdup(query);
+ assert(qd != NULL);
+
+ q = qd;
+ next = q;
+
+ do {
+ char *p;
+
+ if ((next = strchr(next, '&'))) {
+ *next++ = '\0';
+ }
+
+ for (p = q; p && *p; p++) {
+ if (*p == '+') {
+ *p = ' ';
+ }
+ }
+
+ switch_url_decode(q);
+
+
+ name = q;
+ if ((val = strchr(name, '='))) {
+ *val++ = '\0';
+ switch_event_add_header(stream.event, SWITCH_STACK_BOTTOM, name, "%s", val);
+ }
+ q = next;
+ } while (q != NULL);
+
+ free(qd);
+
+ }
+ }
}
command = r->uri + 5;
1
0
27 Apr '07
Author: mikej
Date: Fri Apr 27 16:36:34 2007
New Revision: 5029
Modified:
freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia_glue.c
Log:
don't put @ in from string if there is no user part.
Modified: freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia_glue.c
==============================================================================
--- freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia_glue.c (original)
+++ freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia_glue.c Fri Apr 27 16:36:34 2007
@@ -474,9 +474,11 @@
sofia_glue_tech_prepare_codecs(tech_pvt);
if (!tech_pvt->from_str) {
- tech_pvt->from_str = switch_core_session_sprintf(tech_pvt->session, "\"%s\" <sip:%s@%s>",
+ tech_pvt->from_str = switch_core_session_sprintf(tech_pvt->session, "\"%s\" <sip:%s%s%s>",
cid_name,
- cid_num, tech_pvt->profile->extsipip ? tech_pvt->profile->extsipip : tech_pvt->profile->sipip);
+ cid_num,
+ !switch_strlen_zero(cid_num) ? "@" : "",
+ tech_pvt->profile->extsipip ? tech_pvt->profile->extsipip : tech_pvt->profile->sipip);
}
1
0
26 Apr '07
Author: mikej
Date: Thu Apr 26 19:09:26 2007
New Revision: 5024
Modified:
freeswitch/trunk/src/mod/languages/mod_spidermonkey/mod_spidermonkey.c
freeswitch/trunk/src/mod/languages/mod_spidermonkey/mod_spidermonkey.h
Log:
address http://jira.freeswitch.org/browse/FSCORE-6 We still need to test what the right number is for stack depth is for different platforms. We can get 13 out of msvc on my box (set the level to 12) but this is probably platform dependent and stack size dependent. How can we compute this?
Modified: freeswitch/trunk/src/mod/languages/mod_spidermonkey/mod_spidermonkey.c
==============================================================================
--- freeswitch/trunk/src/mod/languages/mod_spidermonkey/mod_spidermonkey.c (original)
+++ freeswitch/trunk/src/mod/languages/mod_spidermonkey/mod_spidermonkey.c Thu Apr 26 19:09:26 2007
@@ -623,6 +623,7 @@
return Event;
}
+#define MAX_STACK_DEPTH 12
static switch_status_t js_common_callback(switch_core_session_t *session, void *input, switch_input_type_t itype, void *buf, unsigned int buflen)
{
@@ -639,6 +640,8 @@
return SWITCH_STATUS_FALSE;
}
+ jss->stack_depth++;
+
switch (itype) {
case SWITCH_INPUT_TYPE_EVENT:
if ((event = (switch_event_t *) input)) {
@@ -648,6 +651,7 @@
}
}
if (!Event) {
+ jss->stack_depth--;
return SWITCH_STATUS_FALSE;
}
break;
@@ -662,10 +666,17 @@
argv[argc++] = cb_state->arg;
}
+ if (jss->stack_depth > MAX_STACK_DEPTH) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Maximum recursive callback limit %d reached.\n", MAX_STACK_DEPTH);
+ jss->stack_depth--;
+ return SWITCH_STATUS_FALSE;
+ }
+
JS_ResumeRequest(cb_state->cx, cb_state->saveDepth);
JS_CallFunction(cb_state->cx, cb_state->obj, cb_state->function, argc, argv, &cb_state->ret);
cb_state->saveDepth = JS_SuspendRequest(cb_state->cx);
+ jss->stack_depth--;
return SWITCH_STATUS_SUCCESS;
}
@@ -2037,6 +2048,7 @@
jss->flags = flags;
jss->cx = cx;
jss->obj = session_obj;
+ jss->stack_depth = 0;
if ((JS_SetPrivate(cx, session_obj, jss) &&
JS_DefineProperties(cx, session_obj, session_props) && JS_DefineFunctions(cx, session_obj, session_methods))) {
return session_obj;
Modified: freeswitch/trunk/src/mod/languages/mod_spidermonkey/mod_spidermonkey.h
==============================================================================
--- freeswitch/trunk/src/mod/languages/mod_spidermonkey/mod_spidermonkey.h (original)
+++ freeswitch/trunk/src/mod/languages/mod_spidermonkey/mod_spidermonkey.h Thu Apr 26 19:09:26 2007
@@ -129,6 +129,7 @@
unsigned int flags;
switch_call_cause_t cause;
JSFunction *on_hangup;
+ int stack_depth;
switch_channel_state_t hook_state;
};
1
0
26 Apr '07
Author: anthm
Date: Thu Apr 26 18:15:07 2007
New Revision: 5023
Added:
freeswitch/trunk/src/mod/endpoints/mod_alsa/
freeswitch/trunk/src/mod/endpoints/mod_alsa/Makefile
freeswitch/trunk/src/mod/endpoints/mod_alsa/mod_alsa.c
Modified:
freeswitch/trunk/conf/freeswitch.xml
freeswitch/trunk/conf/modules.conf.xml
Log:
mod_alsa (pa impersonator)
Modified: freeswitch/trunk/conf/freeswitch.xml
==============================================================================
--- freeswitch/trunk/conf/freeswitch.xml (original)
+++ freeswitch/trunk/conf/freeswitch.xml Thu Apr 26 18:15:07 2007
@@ -30,6 +30,7 @@
<!--#include "woomera.conf.xml"-->
<!--#include "wanpipe.conf.xml"-->
<!--#include "portaudio.conf.xml"-->
+ <!--#include "alsa.conf.xml"-->
<!--#include "zeroconf.conf.xml"-->
<!--#include "xmpp_event.conf.xml"-->
<!--#include "dialplan_directory.conf.xml"-->
Modified: freeswitch/trunk/conf/modules.conf.xml
==============================================================================
--- freeswitch/trunk/conf/modules.conf.xml (original)
+++ freeswitch/trunk/conf/modules.conf.xml Thu Apr 26 18:15:07 2007
@@ -27,6 +27,7 @@
<!-- <load module="mod_dingaling"/> -->
<!--<load module="mod_iax"/>-->
<load module="mod_portaudio"/>
+ <load module="mod_alsa"/>
<load module="mod_sofia"/>
<!-- <load module="mod_wanpipe"/> -->
<!-- <load module="mod_woomera"/> -->
Added: freeswitch/trunk/src/mod/endpoints/mod_alsa/Makefile
==============================================================================
--- (empty file)
+++ freeswitch/trunk/src/mod/endpoints/mod_alsa/Makefile Thu Apr 26 18:15:07 2007
@@ -0,0 +1,10 @@
+BASE=../../../..
+
+LOCAL_CFLAGS=-I. -I$(PA_DIR)/include -D__EXTENSION__=1
+LOCAL_LDFLAGS=-lasound
+LOCAL_OBJS=
+LOCAL_SOURCES=
+
+include $(BASE)/build/modmake.rules
+
+$(LOCAL_OBJS): $(LOCAL_SOURCES)
Added: freeswitch/trunk/src/mod/endpoints/mod_alsa/mod_alsa.c
==============================================================================
--- (empty file)
+++ freeswitch/trunk/src/mod/endpoints/mod_alsa/mod_alsa.c Thu Apr 26 18:15:07 2007
@@ -0,0 +1,1731 @@
+/*
+ * 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):
+ *
+ * Anthony Minessale II <anthmct(a)yahoo.com>
+ *
+ *
+ * mod_portaudio.c -- PortAudio Endpoint Module
+ *
+ */
+#include <switch.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+#include <string.h>
+#include <alsa/asoundlib.h>
+
+#define MY_EVENT_RINGING "alsa::ringing"
+
+static const char modname[] = "mod_alsa";
+
+static switch_memory_pool_t *module_pool = NULL;
+//static int running = 1;
+
+#define SAMPLE_TYPE paInt16
+//#define SAMPLE_TYPE paFloat32
+typedef short SAMPLE;
+
+typedef switch_status_t (*pa_command_t) (char **argv, int argc, switch_stream_handle_t *stream);
+
+typedef enum {
+ GFLAG_NONE = 0,
+ GFLAG_EAR = (1 << 0),
+ GFLAG_MOUTH = (1 << 1),
+ GFLAG_RING = (1 << 2)
+} GFLAGS;
+
+typedef enum {
+ TFLAG_IO = (1 << 0),
+ TFLAG_INBOUND = (1 << 1),
+ TFLAG_OUTBOUND = (1 << 2),
+ TFLAG_DTMF = (1 << 3),
+ TFLAG_VOICE = (1 << 4),
+ TFLAG_HANGUP = (1 << 5),
+ TFLAG_LINEAR = (1 << 6),
+ TFLAG_ANSWER = (1 << 7),
+ TFLAG_HUP = (1 << 8),
+ TFLAG_MASTER = (1 << 9)
+} TFLAGS;
+
+struct private_object {
+ unsigned int flags;
+ switch_core_session_t *session;
+ switch_caller_profile_t *caller_profile;
+ char call_id[50];
+ int sample_rate;
+ int codec_ms;
+ switch_mutex_t *flag_mutex;
+ char *hold_file;
+ switch_file_handle_t fh;
+ switch_file_handle_t *hfh;
+ switch_frame_t hold_frame;
+ unsigned char holdbuf[SWITCH_RECOMMENDED_BUFFER_SIZE];
+ switch_codec_t write_codec;
+ switch_timer_t timer;
+ struct private_object *next;
+};
+
+typedef struct private_object private_t;
+
+static struct {
+ int debug;
+ int port;
+ char *cid_name;
+ char *cid_num;
+ char *dialplan;
+ char *ring_file;
+ char *hold_file;
+ char *timer_name;
+ int call_id;
+ switch_hash_t *call_hash;
+ switch_mutex_t *device_lock;
+ switch_mutex_t *pvt_lock;
+ switch_mutex_t *flag_mutex;
+ int sample_rate;
+ int codec_ms;
+ snd_pcm_t *audio_stream_in;
+ snd_pcm_t *audio_stream_out;
+ snd_pcm_t *ring_stream;
+
+ switch_codec_t read_codec;
+ switch_codec_t write_codec;
+ switch_frame_t read_frame;
+ switch_frame_t cng_frame;
+ unsigned char databuf[SWITCH_RECOMMENDED_BUFFER_SIZE];
+ unsigned char cngbuf[SWITCH_RECOMMENDED_BUFFER_SIZE];
+ private_t *call_list;
+ int ring_interval;
+ GFLAGS flags;
+ switch_timer_t timer;
+} globals;
+
+
+#define PA_MASTER 1
+#define PA_SLAVE 0
+
+
+SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_dialplan, globals.dialplan)
+ SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_cid_name, globals.cid_name)
+ SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_cid_num, globals.cid_num)
+ SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_ring_file, globals.ring_file)
+ SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_hold_file, globals.hold_file)
+ SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_timer_name, globals.timer_name)
+#define is_master(t) switch_test_flag(t, TFLAG_MASTER)
+ static void add_pvt(private_t * tech_pvt, int master);
+ static void remove_pvt(private_t * tech_pvt);
+ static switch_status_t channel_on_init(switch_core_session_t *session);
+ static switch_status_t channel_on_hangup(switch_core_session_t *session);
+ static switch_status_t channel_on_ring(switch_core_session_t *session);
+ static switch_status_t channel_on_loopback(switch_core_session_t *session);
+ static switch_status_t channel_on_transmit(switch_core_session_t *session);
+ static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *session,
+ switch_caller_profile_t *outbound_profile,
+ switch_core_session_t **new_session, switch_memory_pool_t **pool);
+ static switch_status_t channel_read_frame(switch_core_session_t *session, switch_frame_t **frame, int timeout, switch_io_flag_t flags, int stream_id);
+ static switch_status_t channel_write_frame(switch_core_session_t *session, switch_frame_t *frame, int timeout, switch_io_flag_t flags, int stream_id);
+ static switch_status_t channel_kill_channel(switch_core_session_t *session, int sig);
+ static switch_status_t engage_device(unsigned int samplerate, int codec_ms);
+ static switch_status_t engage_ring_device(unsigned int sample_rate, int channels);
+ static void deactivate_ring_device(void);
+
+ static switch_status_t load_config(void);
+ static switch_status_t pa_cmd(char *dest, switch_core_session_t *session, switch_stream_handle_t *stream);
+ static switch_status_t padep(char *dest, switch_core_session_t *session, switch_stream_handle_t *stream);
+
+
+/*
+ State methods they get called when the state changes to the specific state
+ returning SWITCH_STATUS_SUCCESS tells the core to execute the standard state method next
+ so if you fully implement the state you can return SWITCH_STATUS_FALSE to skip it.
+*/
+ static switch_status_t channel_on_init(switch_core_session_t *session)
+{
+ switch_channel_t *channel;
+ private_t *tech_pvt = NULL;
+ switch_time_t last;
+ int waitsec = globals.ring_interval * 1000000;
+ switch_file_handle_t fh = { 0 };
+ char *val, *ring_file = NULL, *hold_file = NULL;
+ int16_t abuf[2048];
+
+ tech_pvt = switch_core_session_get_private(session);
+ assert(tech_pvt != NULL);
+
+ channel = switch_core_session_get_channel(session);
+ assert(channel != NULL);
+
+
+ last = switch_time_now() - waitsec;
+
+
+
+ if ((val = switch_channel_get_variable(channel, "pa_hold_file"))) {
+ hold_file = val;
+ } else {
+ hold_file = globals.hold_file;
+ }
+
+ if (hold_file) {
+ tech_pvt->hold_file = switch_core_session_strdup(session, hold_file);
+ }
+
+ if (switch_test_flag(tech_pvt, TFLAG_OUTBOUND)) {
+
+
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s CHANNEL INIT %d %d\n",
+ switch_channel_get_name(channel), switch_channel_get_state(channel), switch_test_flag(tech_pvt, TFLAG_ANSWER));
+
+
+
+ if (engage_device(tech_pvt->sample_rate, tech_pvt->codec_ms) != SWITCH_STATUS_SUCCESS) {
+ switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
+ return SWITCH_STATUS_FALSE;
+ }
+
+ if (switch_test_flag(tech_pvt, TFLAG_OUTBOUND)) {
+ add_pvt(tech_pvt, PA_SLAVE);
+
+ ring_file = globals.ring_file;
+ if ((val = switch_channel_get_variable(channel, "pa_ring_file"))) {
+ ring_file = val;
+ }
+
+ if (switch_test_flag((&globals), GFLAG_RING)) {
+ ring_file = NULL;
+ }
+ switch_set_flag_locked((&globals), GFLAG_RING);
+ if (ring_file) {
+ if (switch_core_file_open(&fh,
+ ring_file,
+ globals.read_codec.implementation->number_of_channels,
+ globals.read_codec.implementation->samples_per_second,
+ SWITCH_FILE_FLAG_READ | SWITCH_FILE_DATA_SHORT, NULL) == SWITCH_STATUS_SUCCESS) {
+
+ if (engage_ring_device(fh.samplerate, fh.channels) != SWITCH_STATUS_SUCCESS) {
+ switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Ring Error!\n");
+ switch_core_file_close(&fh);
+ return SWITCH_STATUS_GENERR;
+ }
+ } else {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Cannot open %s, disabling ring file!\n", ring_file);
+ ring_file = NULL;
+ }
+ }
+ }
+
+ switch_core_session_queue_indication(session, SWITCH_MESSAGE_INDICATE_RINGING);
+ switch_channel_mark_ring_ready(channel);
+
+ while (switch_channel_get_state(channel) == CS_INIT && !switch_test_flag(tech_pvt, TFLAG_ANSWER)) {
+ if (switch_time_now() - last >= waitsec) {
+ char buf[512];
+ switch_event_t *event;
+
+ snprintf(buf, sizeof(buf), "BRRRRING! BRRRRING! call %s\n", tech_pvt->call_id);
+
+ if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, MY_EVENT_RINGING) == SWITCH_STATUS_SUCCESS) {
+ switch_event_add_header(event, SWITCH_STACK_BOTTOM, "event_info", "%s", buf);
+ switch_event_add_header(event, SWITCH_STACK_BOTTOM, "call_id", "%s", tech_pvt->call_id);
+ switch_channel_event_set_data(channel, event);
+ switch_event_fire(&event);
+ }
+
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s\n", buf);
+ last = switch_time_now();
+ if (ring_file) {
+ unsigned int pos = 0;
+ switch_core_file_seek(&fh, &pos, 0, SEEK_SET);
+ for (;;) {
+ switch_size_t olen = 1024;
+ switch_core_file_read(&fh, abuf, &olen);
+ if (olen == 0) {
+ break;
+ }
+ snd_pcm_writei(globals.ring_stream, abuf, (int) olen);
+ }
+ }
+ }
+
+ switch_yield(globals.read_codec.implementation->microseconds_per_frame);
+
+ }
+ switch_clear_flag_locked((&globals), GFLAG_RING);
+ }
+
+ if (ring_file) {
+ deactivate_ring_device();
+ switch_core_file_close(&fh);
+ switch_core_codec_destroy(&tech_pvt->write_codec);
+ switch_core_timer_destroy(&tech_pvt->timer);
+ }
+
+ if (switch_test_flag(tech_pvt, TFLAG_OUTBOUND)) {
+ if (!switch_test_flag(tech_pvt, TFLAG_ANSWER)) {
+ switch_channel_hangup(channel, SWITCH_CAUSE_NO_ANSWER);
+ return SWITCH_STATUS_SUCCESS;
+ }
+ }
+
+ switch_set_flag_locked(tech_pvt, TFLAG_IO);
+
+ /* Move Channel's State Machine to RING */
+ switch_channel_set_state(channel, CS_RING);
+
+ return SWITCH_STATUS_SUCCESS;
+
+}
+
+static switch_status_t channel_on_ring(switch_core_session_t *session)
+{
+ switch_channel_t *channel = NULL;
+ private_t *tech_pvt = NULL;
+
+ channel = switch_core_session_get_channel(session);
+ assert(channel != NULL);
+
+ tech_pvt = switch_core_session_get_private(session);
+ assert(tech_pvt != NULL);
+
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s CHANNEL RING\n", switch_channel_get_name(channel));
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+static switch_status_t channel_on_execute(switch_core_session_t *session)
+{
+
+ switch_channel_t *channel = NULL;
+ private_t *tech_pvt = NULL;
+
+ channel = switch_core_session_get_channel(session);
+ assert(channel != NULL);
+
+ tech_pvt = switch_core_session_get_private(session);
+ assert(tech_pvt != NULL);
+
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s CHANNEL EXECUTE\n", switch_channel_get_name(channel));
+
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+static void deactivate_audio_device(void)
+{
+ switch_mutex_lock(globals.device_lock);
+ if (globals.audio_stream_in) {
+ snd_pcm_close(globals.audio_stream_in);
+ globals.audio_stream_in = NULL;
+ }
+ if (globals.audio_stream_out) {
+ snd_pcm_close(globals.audio_stream_out);
+ globals.audio_stream_out = NULL;
+ }
+ switch_mutex_unlock(globals.device_lock);
+}
+
+
+static void deactivate_ring_device(void)
+{
+ switch_mutex_lock(globals.device_lock);
+ if (globals.ring_stream) {
+ snd_pcm_close(globals.ring_stream);
+ globals.ring_stream = NULL;
+ }
+ switch_mutex_unlock(globals.device_lock);
+}
+
+
+
+static void add_pvt(private_t * tech_pvt, int master)
+{
+ private_t *tp;
+ uint8_t in_list = 0;
+
+ switch_mutex_lock(globals.pvt_lock);
+
+ if (switch_strlen_zero(tech_pvt->call_id)) {
+ snprintf(tech_pvt->call_id, sizeof(tech_pvt->call_id), "%d", ++globals.call_id);
+ switch_core_hash_insert(globals.call_hash, tech_pvt->call_id, tech_pvt);
+ switch_core_session_set_read_codec(tech_pvt->session, &globals.read_codec);
+ switch_core_session_set_write_codec(tech_pvt->session, &globals.write_codec);
+ }
+
+ for (tp = globals.call_list; tp; tp = tp->next) {
+ if (tp == tech_pvt) {
+ in_list = 1;
+ }
+ if (master) {
+ switch_clear_flag_locked(tp, TFLAG_MASTER);
+ }
+ }
+
+
+ if (master) {
+ if (!in_list) {
+ tech_pvt->next = globals.call_list;
+ globals.call_list = tech_pvt;
+ }
+ switch_set_flag_locked(tech_pvt, TFLAG_MASTER);
+
+ } else if (!in_list) {
+ for (tp = globals.call_list; tp && tp->next; tp = tp->next);
+ if (tp) {
+ tp->next = tech_pvt;
+ } else {
+ globals.call_list = tech_pvt;
+ }
+ }
+
+ switch_mutex_unlock(globals.pvt_lock);
+}
+
+static void remove_pvt(private_t * tech_pvt)
+{
+ private_t *tp, *last = NULL;
+
+ switch_mutex_lock(globals.pvt_lock);
+ for (tp = globals.call_list; tp; tp = tp->next) {
+ switch_clear_flag_locked(tp, TFLAG_MASTER);
+ if (tp == tech_pvt) {
+ if (last) {
+ last->next = tp->next;
+ } else {
+ globals.call_list = tp->next;
+ }
+ }
+ last = tp;
+ }
+
+ if (globals.call_list) {
+ switch_set_flag_locked(globals.call_list, TFLAG_MASTER);
+ } else {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "No more channels, deactivating audio\n");
+ deactivate_audio_device();
+ }
+
+ switch_mutex_unlock(globals.pvt_lock);
+}
+
+static switch_status_t channel_on_hangup(switch_core_session_t *session)
+{
+ switch_channel_t *channel = NULL;
+ private_t *tech_pvt = NULL;
+
+ channel = switch_core_session_get_channel(session);
+ assert(channel != NULL);
+
+ tech_pvt = switch_core_session_get_private(session);
+ assert(tech_pvt != NULL);
+
+ remove_pvt(tech_pvt);
+
+ switch_clear_flag_locked(tech_pvt, TFLAG_IO);
+ switch_set_flag_locked(tech_pvt, TFLAG_HUP);
+
+ switch_core_hash_delete(globals.call_hash, tech_pvt->call_id);
+
+ if (tech_pvt->hfh) {
+ tech_pvt->hfh = NULL;
+ switch_core_file_close(&tech_pvt->fh);
+ }
+
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s CHANNEL HANGUP\n", switch_channel_get_name(channel));
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+static switch_status_t channel_kill_channel(switch_core_session_t *session, int sig)
+{
+ switch_channel_t *channel = NULL;
+ private_t *tech_pvt = NULL;
+
+ channel = switch_core_session_get_channel(session);
+ assert(channel != NULL);
+
+ tech_pvt = switch_core_session_get_private(session);
+ assert(tech_pvt != NULL);
+
+ switch (sig) {
+ case SWITCH_SIG_KILL:
+ switch_set_flag_locked(tech_pvt, TFLAG_HUP);
+ switch_channel_hangup(channel, SWITCH_CAUSE_NORMAL_CLEARING);
+ break;
+ default:
+ break;
+ }
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s CHANNEL KILL\n", switch_channel_get_name(channel));
+
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+static switch_status_t channel_on_transmit(switch_core_session_t *session)
+{
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "CHANNEL TRANSMIT\n");
+ return SWITCH_STATUS_SUCCESS;
+}
+
+static switch_status_t channel_on_loopback(switch_core_session_t *session)
+{
+ switch_channel_t *channel = NULL;
+ private_t *tech_pvt = NULL;
+
+ channel = switch_core_session_get_channel(session);
+ assert(channel != NULL);
+
+ tech_pvt = switch_core_session_get_private(session);
+ assert(tech_pvt != NULL);
+
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "CHANNEL LOOPBACK\n");
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+
+static switch_status_t channel_waitfor_read(switch_core_session_t *session, int ms, int stream_id)
+{
+ private_t *tech_pvt = NULL;
+
+ tech_pvt = switch_core_session_get_private(session);
+ assert(tech_pvt != NULL);
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+static switch_status_t channel_waitfor_write(switch_core_session_t *session, int ms, int stream_id)
+{
+ private_t *tech_pvt = NULL;
+
+ tech_pvt = switch_core_session_get_private(session);
+ assert(tech_pvt != NULL);
+
+ return SWITCH_STATUS_SUCCESS;
+
+}
+
+static switch_status_t channel_send_dtmf(switch_core_session_t *session, char *dtmf)
+{
+ private_t *tech_pvt = NULL;
+
+ tech_pvt = switch_core_session_get_private(session);
+ assert(tech_pvt != NULL);
+
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "DTMF ON CALL %s [%s]\n", tech_pvt->call_id, dtmf);
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+static switch_status_t channel_read_frame(switch_core_session_t *session, switch_frame_t **frame, int timeout, switch_io_flag_t flags, int stream_id)
+{
+ switch_channel_t *channel = NULL;
+ private_t *tech_pvt = NULL;
+ int samples = 0;
+ switch_status_t status = SWITCH_STATUS_FALSE;
+
+ channel = switch_core_session_get_channel(session);
+ assert(channel != NULL);
+
+ tech_pvt = switch_core_session_get_private(session);
+ assert(tech_pvt != NULL);
+
+ if (!globals.audio_stream_in) {
+ return SWITCH_STATUS_FALSE;
+ }
+
+ if (switch_test_flag(tech_pvt, TFLAG_HUP)) {
+ return SWITCH_STATUS_FALSE;
+ }
+
+ if (!switch_test_flag(tech_pvt, TFLAG_IO)) {
+ goto cng;
+ }
+
+ if (!is_master(tech_pvt)) {
+ if (tech_pvt->hold_file) {
+ if (!tech_pvt->hfh) {
+ int codec_ms = tech_pvt->codec_ms ? tech_pvt->codec_ms : globals.codec_ms;
+ int sample_rate = tech_pvt->sample_rate ? tech_pvt->sample_rate : globals.sample_rate;
+
+ if (switch_core_codec_init(&tech_pvt->write_codec,
+ "L16",
+ NULL,
+ sample_rate,
+ codec_ms,
+ 1,
+ SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE,
+ NULL, switch_core_session_get_pool(tech_pvt->session)) != SWITCH_STATUS_SUCCESS) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Can't load codec?\n");
+ switch_core_codec_destroy(&globals.read_codec);
+ tech_pvt->hold_file = NULL;
+ goto cng;
+ }
+
+ if (switch_core_file_open(&tech_pvt->fh,
+ tech_pvt->hold_file,
+ globals.read_codec.implementation->number_of_channels,
+ globals.read_codec.implementation->samples_per_second,
+ SWITCH_FILE_FLAG_READ | SWITCH_FILE_DATA_SHORT,
+ switch_core_session_get_pool(tech_pvt->session)) != SWITCH_STATUS_SUCCESS) {
+ switch_core_codec_destroy(&tech_pvt->write_codec);
+ tech_pvt->hold_file = NULL;
+ goto cng;
+ }
+
+ tech_pvt->hfh = &tech_pvt->fh;
+ tech_pvt->hold_frame.data = tech_pvt->holdbuf;
+ tech_pvt->hold_frame.buflen = sizeof(tech_pvt->holdbuf);
+ tech_pvt->hold_frame.rate = sample_rate;
+ tech_pvt->hold_frame.codec = &tech_pvt->write_codec;
+ }
+
+ goto hold;
+ }
+ cng:
+ switch_yield(globals.read_codec.implementation->microseconds_per_frame);
+ *frame = &globals.cng_frame;
+ return SWITCH_STATUS_SUCCESS;
+
+ hold:
+
+ {
+ switch_size_t olen = globals.read_codec.implementation->samples_per_frame;
+ if (switch_core_timer_next(&tech_pvt->timer) != SWITCH_STATUS_SUCCESS) {
+ switch_core_file_close(&tech_pvt->fh);
+ switch_core_codec_destroy(&tech_pvt->write_codec);
+ goto cng;
+ }
+ switch_core_file_read(tech_pvt->hfh, tech_pvt->hold_frame.data, &olen);
+
+ if (olen == 0) {
+ unsigned int pos = 0;
+ switch_core_file_seek(tech_pvt->hfh, &pos, 0, SEEK_SET);
+ goto cng;
+ }
+
+
+ tech_pvt->hold_frame.datalen = (uint32_t) (olen * sizeof(int16_t));
+ tech_pvt->hold_frame.samples = (uint32_t) olen;
+ tech_pvt->hold_frame.timestamp = tech_pvt->timer.samplecount;
+ *frame = &tech_pvt->hold_frame;
+
+ }
+
+ return SWITCH_STATUS_SUCCESS;
+ }
+
+ switch_mutex_lock(globals.device_lock);
+
+
+ if ((samples = snd_pcm_readi (globals.audio_stream_in, globals.read_frame.data, globals.read_codec.implementation->samples_per_frame)) != 0) {
+ globals.read_frame.datalen = samples / 2;
+ globals.read_frame.samples = globals.read_frame.datalen / 2;
+
+ switch_core_timer_check(&globals.timer);
+ globals.read_frame.timestamp = globals.timer.samplecount;
+ *frame = &globals.read_frame;
+
+ if (!switch_test_flag((&globals), GFLAG_MOUTH)) {
+ memset(globals.read_frame.data, 255, globals.read_frame.datalen);
+ }
+
+ status = SWITCH_STATUS_SUCCESS;
+ }
+ switch_mutex_unlock(globals.device_lock);
+
+ return status;
+}
+
+static switch_status_t channel_write_frame(switch_core_session_t *session, switch_frame_t *frame, int timeout, switch_io_flag_t flags, int stream_id)
+{
+ switch_channel_t *channel = NULL;
+ private_t *tech_pvt = NULL;
+ switch_status_t status = SWITCH_STATUS_FALSE;
+ channel = switch_core_session_get_channel(session);
+ assert(channel != NULL);
+
+ tech_pvt = switch_core_session_get_private(session);
+ assert(tech_pvt != NULL);
+
+ if (!globals.audio_stream_out) {
+ return SWITCH_STATUS_FALSE;
+ }
+
+ if (switch_test_flag(tech_pvt, TFLAG_HUP)) {
+ return SWITCH_STATUS_FALSE;
+ }
+
+ if (!is_master(tech_pvt) || !switch_test_flag(tech_pvt, TFLAG_IO)) {
+ return SWITCH_STATUS_SUCCESS;
+ }
+
+ if (globals.audio_stream_out) {
+ if (switch_test_flag((&globals), GFLAG_EAR)) {
+ snd_pcm_writei(globals.audio_stream_out, (short *) frame->data, (int) (frame->datalen / sizeof(SAMPLE)));
+ }
+ status = SWITCH_STATUS_SUCCESS;
+ }
+
+ return status;
+
+}
+
+static switch_status_t channel_answer_channel(switch_core_session_t *session)
+{
+ private_t *tech_pvt;
+ switch_channel_t *channel = NULL;
+
+ channel = switch_core_session_get_channel(session);
+ assert(channel != NULL);
+
+ tech_pvt = switch_core_session_get_private(session);
+ assert(tech_pvt != NULL);
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+static switch_status_t channel_receive_message(switch_core_session_t *session, switch_core_session_message_t *msg)
+{
+ switch_channel_t *channel;
+ private_t *tech_pvt;
+
+ channel = switch_core_session_get_channel(session);
+ assert(channel != NULL);
+
+ tech_pvt = switch_core_session_get_private(session);
+ assert(tech_pvt != NULL);
+
+
+ switch (msg->message_id) {
+ case SWITCH_MESSAGE_INDICATE_ANSWER:
+ channel_answer_channel(session);
+ break;
+ case SWITCH_MESSAGE_INDICATE_PROGRESS:
+ {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Engage Early Media\n");
+ switch_set_flag_locked(tech_pvt, TFLAG_IO);
+ }
+ default:
+ break;
+ }
+ return SWITCH_STATUS_SUCCESS;
+}
+
+static switch_api_interface_t send_dtmf_interface = {
+ /*.interface_name */ "padtmf",
+ /*.desc */ "DEPRICATED (see 'pa')",
+ /*.function */ padep,
+ /*.syntax */ "DEPRICATED (see 'pa')",
+ /*.next */ NULL
+};
+
+static switch_api_interface_t answer_call_interface = {
+ /*.interface_name */ "paoffhook",
+ /*.desc */ "DEPRICATED (see 'pa')",
+ /*.function */ padep,
+ /*.syntax */ "DEPRICATED (see 'pa')",
+ /*.next */ &send_dtmf_interface
+};
+
+static switch_api_interface_t channel_info_interface = {
+ /*.interface_name */ "painfo",
+ /*.desc */ "DEPRICATED (see 'pa')",
+ /*.function */ padep,
+ /*.syntax */ "DEPRICATED (see 'pa')",
+ /*.next */ &answer_call_interface
+};
+
+static switch_api_interface_t channel_hup_interface = {
+ /*.interface_name */ "pahup",
+ /*.desc */ "DEPRICATED (see 'pa')",
+ /*.function */ padep,
+ /*.syntax */ "DEPRICATED (see 'pa')",
+ /*.next */ &channel_info_interface
+};
+
+static switch_api_interface_t channel_call_interface = {
+ /*.interface_name */ "pacall",
+ /*.desc */ "DEPRICATED (see 'pa')",
+ /*.function */ padep,
+ /*.syntax */ "DEPRICATED (see 'pa')",
+ /*.next */ &channel_hup_interface
+};
+
+static switch_api_interface_t channel_api_interface = {
+ /*.interface_name */ "pa",
+ /*.desc */ "Alsa",
+ /*.function */ pa_cmd,
+ /*.syntax */ "<command> [<args>]",
+ /*.next */ &channel_call_interface
+};
+
+static const switch_state_handler_table_t channel_event_handlers = {
+ /*.on_init */ channel_on_init,
+ /*.on_ring */ channel_on_ring,
+ /*.on_execute */ channel_on_execute,
+ /*.on_hangup */ channel_on_hangup,
+ /*.on_loopback */ channel_on_loopback,
+ /*.on_transmit */ channel_on_transmit
+};
+
+static const switch_io_routines_t channel_io_routines = {
+ /*.outgoing_channel */ channel_outgoing_channel,
+ /*.read_frame */ channel_read_frame,
+ /*.write_frame */ channel_write_frame,
+ /*.kill_channel */ channel_kill_channel,
+ /*.waitfor_read */ channel_waitfor_read,
+ /*.waitfor_write */ channel_waitfor_write,
+ /*.send_dtmf */ channel_send_dtmf,
+ /*.receive_message */ channel_receive_message
+};
+
+static const switch_endpoint_interface_t channel_endpoint_interface = {
+ /*.interface_name */ "alsa",
+ /*.io_routines */ &channel_io_routines,
+ /*.event_handlers */ &channel_event_handlers,
+ /*.private */ NULL,
+ /*.next */ NULL
+};
+
+static const switch_loadable_module_interface_t channel_module_interface = {
+ /*.module_name */ modname,
+ /*.endpoint_interface */ &channel_endpoint_interface,
+ /*.timer_interface */ NULL,
+ /*.dialplan_interface */ NULL,
+ /*.codec_interface */ NULL,
+ /*.application_interface */ NULL,
+ /*.api_interface */ &channel_api_interface
+};
+
+/* Make sure when you have 2 sessions in the same scope that you pass the appropriate one to the routines
+ that allocate memory or you will have 1 channel with memory allocated from another channel's pool!
+*/
+static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *session,
+ switch_caller_profile_t *outbound_profile,
+ switch_core_session_t **new_session, switch_memory_pool_t **pool)
+{
+
+ if ((*new_session = switch_core_session_request(&channel_endpoint_interface, pool)) != 0) {
+ private_t *tech_pvt;
+ switch_channel_t *channel;
+ switch_caller_profile_t *caller_profile;
+
+ switch_core_session_add_stream(*new_session, NULL);
+ if ((tech_pvt = (private_t *) switch_core_session_alloc(*new_session, sizeof(private_t))) != 0) {
+ memset(tech_pvt, 0, sizeof(*tech_pvt));
+ switch_mutex_init(&tech_pvt->flag_mutex, SWITCH_MUTEX_NESTED, switch_core_session_get_pool(*new_session));
+ channel = switch_core_session_get_channel(*new_session);
+ switch_core_session_set_private(*new_session, tech_pvt);
+ tech_pvt->session = *new_session;
+ globals.flags = GFLAG_EAR | GFLAG_MOUTH;
+ } else {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Hey where is my memory pool?\n");
+ switch_core_session_destroy(new_session);
+ return SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER;
+ }
+
+ if (outbound_profile) {
+ char name[128];
+ char *id = !switch_strlen_zero(outbound_profile->caller_id_number) ? outbound_profile->caller_id_number : "na";
+ snprintf(name, sizeof(name), "Alsa/%s", id);
+
+ switch_channel_set_name(channel, name);
+
+ caller_profile = switch_caller_profile_clone(*new_session, outbound_profile);
+ switch_channel_set_caller_profile(channel, caller_profile);
+ tech_pvt->caller_profile = caller_profile;
+ } else {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Doh! no caller profile\n");
+ switch_core_session_destroy(new_session);
+ return SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER;
+ }
+
+ switch_channel_set_flag(channel, CF_OUTBOUND);
+ switch_set_flag_locked(tech_pvt, TFLAG_OUTBOUND);
+ switch_channel_set_state(channel, CS_INIT);
+ return SWITCH_CAUSE_SUCCESS;
+ }
+
+ return SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER;
+
+}
+
+
+SWITCH_MOD_DECLARE(switch_status_t) switch_module_load(const switch_loadable_module_interface_t **module_interface, char *filename)
+{
+
+ switch_status_t status;
+
+ if (switch_core_new_memory_pool(&module_pool) != SWITCH_STATUS_SUCCESS) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "OH OH no pool\n");
+ return SWITCH_STATUS_TERM;
+ }
+
+
+
+ if ((status = load_config()) != SWITCH_STATUS_SUCCESS) {
+ return status;
+ }
+
+
+
+ switch_core_hash_init(&globals.call_hash, module_pool);
+ switch_mutex_init(&globals.device_lock, SWITCH_MUTEX_NESTED, module_pool);
+ switch_mutex_init(&globals.pvt_lock, SWITCH_MUTEX_NESTED, module_pool);
+ switch_mutex_init(&globals.flag_mutex, SWITCH_MUTEX_NESTED, module_pool);
+
+
+
+ if (switch_event_reserve_subclass(MY_EVENT_RINGING) != SWITCH_STATUS_SUCCESS) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't register subclass!");
+ return SWITCH_STATUS_GENERR;
+ }
+
+ globals.read_frame.data = globals.databuf;
+ globals.read_frame.buflen = sizeof(globals.databuf);
+ globals.cng_frame.data = globals.cngbuf;
+ globals.cng_frame.buflen = sizeof(globals.cngbuf);
+ globals.cng_frame.datalen = sizeof(globals.cngbuf);
+ switch_set_flag((&globals.cng_frame), SFF_CNG);
+
+ /* connect my internal structure to the blank pointer passed to me */
+ *module_interface = &channel_module_interface;
+
+ /* indicate that the module should continue to be loaded */
+ return SWITCH_STATUS_SUCCESS;
+}
+
+
+static switch_status_t load_config(void)
+{
+ char *cf = "alsa.conf";
+ switch_xml_t cfg, xml, settings, param;
+
+ 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;
+ }
+
+ memset(&globals, 0, sizeof(globals));
+
+
+ if ((settings = switch_xml_child(cfg, "settings"))) {
+ for (param = switch_xml_child(settings, "param"); param; param = param->next) {
+ char *var = (char *) switch_xml_attr_soft(param, "name");
+ char *val = (char *) switch_xml_attr_soft(param, "value");
+
+ if (!strcmp(var, "debug")) {
+ globals.debug = atoi(val);
+ } else if (!strcmp(var, "ring-interval")) {
+ globals.ring_interval = atoi(val);
+ } else if (!strcmp(var, "ring-file")) {
+ set_global_ring_file(val);
+ } else if (!strcmp(var, "hold-file")) {
+ set_global_hold_file(val);
+ } else if (!strcmp(var, "timer-name")) {
+ set_global_timer_name(val);
+ } else if (!strcmp(var, "sample-rate")) {
+ globals.sample_rate = atoi(val);
+ } else if (!strcmp(var, "codec-ms")) {
+ globals.codec_ms = atoi(val);
+ } else if (!strcmp(var, "dialplan")) {
+ set_global_dialplan(val);
+ } else if (!strcmp(var, "cid-name")) {
+ set_global_cid_name(val);
+ } else if (!strcmp(var, "cid-num")) {
+ set_global_cid_num(val);
+ }
+ }
+ }
+
+ if (!globals.dialplan) {
+ set_global_dialplan("default");
+ }
+
+ if (!globals.sample_rate) {
+ globals.sample_rate = 8000;
+ }
+
+ if (!globals.codec_ms) {
+ globals.codec_ms = 20;
+ }
+
+ if (!globals.ring_interval) {
+ globals.ring_interval = 5;
+ }
+
+ if (!globals.timer_name) {
+ set_global_timer_name("soft");
+ }
+
+ switch_xml_free(xml);
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+SWITCH_MOD_DECLARE(switch_status_t) switch_module_shutdown(void)
+{
+ if (globals.read_codec.implementation) {
+ switch_core_codec_destroy(&globals.read_codec);
+ }
+
+ if (globals.write_codec.implementation) {
+ switch_core_codec_destroy(&globals.write_codec);
+ }
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+
+
+static switch_status_t engage_device(unsigned int sample_rate, int codec_ms)
+{
+ int err = 0;
+ snd_pcm_hw_params_t *hw_params = NULL;
+ char *device = "default";
+
+ if (globals.audio_stream_in && globals.audio_stream_out) {
+ return SWITCH_STATUS_SUCCESS;
+ }
+
+ if (globals.audio_stream_in) {
+ snd_pcm_close (globals.audio_stream_in);
+ globals.audio_stream_in = NULL;
+ }
+
+ if (globals.audio_stream_out) {
+ snd_pcm_close (globals.audio_stream_out);
+ globals.audio_stream_out = NULL;
+ }
+
+ if (!sample_rate) {
+ sample_rate = globals.sample_rate;
+ }
+
+ if (!codec_ms) {
+ codec_ms = globals.codec_ms;
+ }
+
+ if (switch_core_codec_init(&globals.read_codec,
+ "L16",
+ NULL, sample_rate, codec_ms, 1, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE, NULL,
+ NULL) != SWITCH_STATUS_SUCCESS) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Can't load codec?\n");
+ return SWITCH_STATUS_FALSE;
+ } else {
+ if (switch_core_codec_init(&globals.write_codec,
+ "L16",
+ NULL,
+ sample_rate, codec_ms, 1, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE, NULL,
+ NULL) != SWITCH_STATUS_SUCCESS) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Can't load codec?\n");
+ switch_core_codec_destroy(&globals.read_codec);
+ return SWITCH_STATUS_FALSE;
+ }
+ }
+
+ if (switch_core_timer_init(&globals.timer,
+ globals.timer_name, codec_ms, globals.read_codec.implementation->samples_per_frame,
+ module_pool) != SWITCH_STATUS_SUCCESS) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "setup timer failed!\n");
+ switch_core_codec_destroy(&globals.read_codec);
+ switch_core_codec_destroy(&globals.write_codec);
+ return SWITCH_STATUS_FALSE;
+ }
+
+
+
+ globals.read_frame.rate = sample_rate;
+ globals.read_frame.codec = &globals.read_codec;
+
+
+
+ switch_mutex_lock(globals.device_lock);
+ /* LOCKED ************************************************************************************************** */
+
+
+ if ((err = snd_pcm_open (&globals.audio_stream_out, device, SND_PCM_STREAM_PLAYBACK, 0)) < 0) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "cannot open audio device %s (%s)\n",
+ device,
+ snd_strerror (err));
+ goto fail;
+ }
+
+ if ((err = snd_pcm_hw_params_malloc (&hw_params)) < 0) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "cannot allocate hardware parameter structure (%s)\n",
+ snd_strerror (err));
+ goto fail;
+ }
+
+ if ((err = snd_pcm_hw_params_any (globals.audio_stream_out, hw_params)) < 0) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "cannot initialize hardware parameter structure (%s)\n",
+ snd_strerror (err));
+ goto fail;
+ }
+
+ if ((err = snd_pcm_hw_params_set_access (globals.audio_stream_out, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "cannot set access type (%s)\n",
+ snd_strerror (err));
+ goto fail;
+ }
+
+ if ((err = snd_pcm_hw_params_set_format (globals.audio_stream_out, hw_params, SND_PCM_FORMAT_S16_LE)) < 0) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "cannot set sample format (%s)\n",
+ snd_strerror (err));
+ goto fail;
+ }
+
+ if ((err = snd_pcm_hw_params_set_rate_near (globals.audio_stream_out, hw_params, &sample_rate, 0)) < 0) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "cannot set sample rate (%s)\n",
+ snd_strerror (err));
+ goto fail;
+ }
+
+ if ((err = snd_pcm_hw_params_set_channels (globals.audio_stream_out, hw_params, 1)) < 0) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "cannot set channel count (%s)\n",
+ snd_strerror (err));
+ goto fail;
+ }
+
+ if ((err = snd_pcm_hw_params (globals.audio_stream_out, hw_params)) < 0) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "cannot set parameters (%s)\n",
+ snd_strerror (err));
+ goto fail;
+ }
+
+
+ snd_pcm_hw_params_free (hw_params);
+ hw_params = NULL;
+
+
+
+ if ((err = snd_pcm_open (&globals.audio_stream_in, device, SND_PCM_STREAM_CAPTURE, 0)) < 0) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "cannot open audio device %s (%s)\n",
+ device,
+ snd_strerror (err));
+ goto fail;
+ }
+ if ((err = snd_pcm_hw_params_malloc (&hw_params)) < 0) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "cannot allocate hardware parameter structure (%s)\n",
+ snd_strerror (err));
+ goto fail;
+ }
+
+ if ((err = snd_pcm_hw_params_any (globals.audio_stream_in, hw_params)) < 0) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "cannot initialize hardware parameter structure (%s)\n",
+ snd_strerror (err));
+ goto fail;
+ }
+
+ if ((err = snd_pcm_hw_params_set_access (globals.audio_stream_in, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "cannot set access type (%s)\n",
+ snd_strerror (err));
+ goto fail;
+ }
+
+ if ((err = snd_pcm_hw_params_set_format (globals.audio_stream_in, hw_params, SND_PCM_FORMAT_S16_LE)) < 0) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "cannot set sample format (%s)\n",
+ snd_strerror (err));
+ goto fail;
+ }
+
+ if ((err = snd_pcm_hw_params_set_rate_near (globals.audio_stream_in, hw_params, &sample_rate, 0)) < 0) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "cannot set sample rate (%s)\n",
+ snd_strerror (err));
+ goto fail;
+ }
+
+ if ((err = snd_pcm_hw_params_set_channels (globals.audio_stream_in, hw_params, 1)) < 0) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "cannot set channel count (%s)\n",
+ snd_strerror (err));
+ goto fail;
+ }
+
+ if ((err = snd_pcm_hw_params (globals.audio_stream_in, hw_params)) < 0) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "cannot set parameters (%s)\n",
+ snd_strerror (err));
+ goto fail;
+ }
+
+ if (hw_params) {
+ snd_pcm_hw_params_free (hw_params);
+ hw_params = NULL;
+ }
+
+ if ((err = snd_pcm_prepare (globals.audio_stream_out)) < 0) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "cannot prepare audio interface for use (%s)\n",
+ snd_strerror (err));
+ goto fail;
+ }
+
+ if ((err = snd_pcm_prepare (globals.audio_stream_in)) < 0) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "cannot prepare audio interface for use (%s)\n",
+ snd_strerror (err));
+ goto fail;
+ }
+
+ switch_mutex_unlock(globals.device_lock);
+ return SWITCH_STATUS_SUCCESS;
+
+ fail:
+
+ if (hw_params) {
+ snd_pcm_hw_params_free (hw_params);
+ hw_params = NULL;
+ }
+
+ switch_mutex_unlock(globals.device_lock);
+
+ if (globals.audio_stream_in) {
+ snd_pcm_close (globals.audio_stream_in);
+ }
+
+ if (globals.audio_stream_out) {
+ snd_pcm_close (globals.audio_stream_out);
+ }
+
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Can't open audio device!\n");
+ switch_core_codec_destroy(&globals.read_codec);
+ switch_core_codec_destroy(&globals.write_codec);
+
+ return SWITCH_STATUS_FALSE;
+
+
+
+}
+
+
+static switch_status_t engage_ring_device(unsigned int sample_rate, int channels)
+{
+ int err = 0;
+ snd_pcm_hw_params_t *hw_params;
+ char *device = "default";
+
+ if (globals.ring_stream) {
+ return SWITCH_STATUS_SUCCESS;
+ }
+
+ if (!sample_rate) {
+ sample_rate = globals.sample_rate;
+ }
+
+ switch_mutex_lock(globals.device_lock);
+ /* LOCKED ************************************************************************************************** */
+
+
+ if ((err = snd_pcm_open (&globals.ring_stream, device, SND_PCM_STREAM_PLAYBACK, 0)) < 0) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "cannot open audio device %s (%s)\n",
+ device,
+ snd_strerror (err));
+ goto fail;
+ }
+
+ if ((err = snd_pcm_hw_params_malloc (&hw_params)) < 0) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "cannot allocate hardware parameter structure (%s)\n",
+ snd_strerror (err));
+ goto fail;
+ }
+
+ if ((err = snd_pcm_hw_params_any (globals.ring_stream, hw_params)) < 0) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "cannot initialize hardware parameter structure (%s)\n",
+ snd_strerror (err));
+ goto fail;
+ }
+
+ if ((err = snd_pcm_hw_params_set_access (globals.ring_stream, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "cannot set access type (%s)\n",
+ snd_strerror (err));
+ goto fail;
+ }
+
+ if ((err = snd_pcm_hw_params_set_format (globals.ring_stream, hw_params, SND_PCM_FORMAT_S16_LE)) < 0) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "cannot set sample format (%s)\n",
+ snd_strerror (err));
+ goto fail;
+ }
+
+ if ((err = snd_pcm_hw_params_set_rate_near (globals.ring_stream, hw_params, &sample_rate, 0)) < 0) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "cannot set sample rate (%s)\n",
+ snd_strerror (err));
+ goto fail;
+ }
+
+ if ((err = snd_pcm_hw_params_set_channels (globals.ring_stream, hw_params, 1)) < 0) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "cannot set channel count (%s)\n",
+ snd_strerror (err));
+ goto fail;
+ }
+
+ if ((err = snd_pcm_hw_params (globals.ring_stream, hw_params)) < 0) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "cannot set parameters (%s)\n",
+ snd_strerror (err));
+ goto fail;
+ }
+
+ if (hw_params) {
+ snd_pcm_hw_params_free (hw_params);
+ hw_params = NULL;
+ }
+
+ if ((err = snd_pcm_prepare (globals.ring_stream)) < 0) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "cannot prepare audio interface for use (%s)\n",
+ snd_strerror (err));
+ goto fail;
+ }
+
+ switch_mutex_unlock(globals.device_lock);
+ return SWITCH_STATUS_SUCCESS;
+
+ fail:
+ switch_mutex_unlock(globals.device_lock);
+
+
+ if (hw_params) {
+ snd_pcm_hw_params_free (hw_params);
+ hw_params = NULL;
+ }
+
+ if (globals.ring_stream) {
+ snd_pcm_close (globals.ring_stream);
+ }
+
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Can't open audio device!\n");
+ switch_core_codec_destroy(&globals.read_codec);
+ switch_core_codec_destroy(&globals.write_codec);
+
+ return SWITCH_STATUS_FALSE;
+}
+
+static switch_status_t dtmf_call(char **argv, int argc, switch_stream_handle_t *stream)
+{
+ char *dtmf = argv[0];
+
+ if (switch_strlen_zero(dtmf)) {
+ stream->write_function(stream, "No DTMF Supplied!\n");
+ } else {
+ switch_mutex_lock(globals.pvt_lock);
+ if (globals.call_list) {
+ switch_channel_t *channel = switch_core_session_get_channel(globals.call_list->session);
+ switch_channel_queue_dtmf(channel, dtmf);
+ }
+ switch_mutex_unlock(globals.pvt_lock);
+ }
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+static switch_status_t switch_call(char **argv, int argc, switch_stream_handle_t *stream)
+{
+ private_t *tp, *tech_pvt = NULL;
+ char *callid = argv[0];
+ uint8_t one_call = 0;
+
+ switch_mutex_lock(globals.pvt_lock);
+ if (switch_strlen_zero(callid)) {
+ if (globals.call_list) {
+ if (globals.call_list->next) {
+ tech_pvt = globals.call_list->next;
+ } else {
+ tech_pvt = globals.call_list;
+ one_call = 1;
+ }
+ }
+ } else if (!strcasecmp(callid, "none")) {
+ for (tp = globals.call_list; tp; tp = tp->next) {
+ switch_clear_flag_locked(tp, TFLAG_MASTER);
+ }
+ stream->write_function(stream, "OK\n");
+ goto done;
+ } else {
+ tech_pvt = switch_core_hash_find(globals.call_hash, callid);
+ }
+
+ if (tech_pvt) {
+ if (tech_pvt == globals.call_list && !tech_pvt->next) {
+ one_call = 1;
+ }
+
+ if (!one_call) {
+ remove_pvt(tech_pvt);
+ }
+ add_pvt(tech_pvt, PA_MASTER);
+ stream->write_function(stream, "OK\n");
+ } else {
+ stream->write_function(stream, "NO SUCH CALL\n");
+ }
+
+ done:
+ switch_mutex_unlock(globals.pvt_lock);
+
+ return SWITCH_STATUS_SUCCESS;
+
+}
+
+static switch_status_t hangup_call(char **argv, int argc, switch_stream_handle_t *stream)
+{
+ private_t *tech_pvt;
+ char *callid = argv[0];
+
+ switch_mutex_lock(globals.pvt_lock);
+ if (switch_strlen_zero(callid)) {
+ tech_pvt = globals.call_list;
+ } else {
+ tech_pvt = switch_core_hash_find(globals.call_hash, callid);
+ }
+
+ if (tech_pvt) {
+ switch_channel_hangup(switch_core_session_get_channel(tech_pvt->session), SWITCH_CAUSE_NORMAL_CLEARING);
+ //switch_set_flag_locked(tech_pvt, TFLAG_HUP);
+ stream->write_function(stream, "OK\n");
+ } else {
+ stream->write_function(stream, "NO SUCH CALL\n");
+ }
+ switch_mutex_unlock(globals.pvt_lock);
+
+ return SWITCH_STATUS_SUCCESS;
+
+}
+
+static switch_status_t answer_call(char **argv, int argc, switch_stream_handle_t *stream)
+{
+ private_t *tp;
+ int x = 0;
+ char *callid = argv[0];
+
+ switch_mutex_lock(globals.pvt_lock);
+
+ if (!switch_strlen_zero(callid)) {
+ if ((tp = switch_core_hash_find(globals.call_hash, callid))) {
+ if (switch_test_flag(tp, TFLAG_ANSWER)) {
+ stream->write_function(stream, "CALL ALREADY ANSWERED\n");
+ } else {
+ switch_channel_t *channel = switch_core_session_get_channel(tp->session);
+ switch_set_flag_locked(tp, TFLAG_ANSWER);
+ switch_channel_answer(channel);
+ add_pvt(tp, PA_MASTER);
+ }
+ } else {
+ stream->write_function(stream, "NO SUCH CALL\n");
+ }
+
+ goto done;
+ }
+
+ for (tp = globals.call_list; tp; tp = tp->next) {
+ if (!switch_test_flag(tp, TFLAG_ANSWER)) {
+ switch_channel_t *channel = switch_core_session_get_channel(tp->session);
+ switch_set_flag_locked(tp, TFLAG_ANSWER);
+ switch_channel_answer(channel);
+ add_pvt(tp, PA_MASTER);
+ x++;
+ break;
+ }
+ }
+ done:
+ switch_mutex_unlock(globals.pvt_lock);
+
+ stream->write_function(stream, "Answered %d channels.\n", x);
+
+
+ return SWITCH_STATUS_SUCCESS;
+
+}
+
+static switch_status_t do_flags(char **argv, int argc, switch_stream_handle_t *stream)
+{
+ char *action = argv[0];
+ char *flag_str = argv[1];
+ GFLAGS flags = GFLAG_NONE;
+ char *p;
+ int x = 0;
+
+ if (argc < 2) {
+ goto desc;
+ }
+
+ for (x = 1; x < argc; x++) {
+ flag_str = argv[x];
+ for (p = flag_str; *p; p++) {
+ *p = (char) tolower(*p);
+ }
+
+ if (strstr(flag_str, "ear")) {
+ flags |= GFLAG_EAR;
+ }
+ if (strstr(flag_str, "mouth")) {
+ flags |= GFLAG_MOUTH;
+ }
+ }
+
+ if (!strcasecmp(action, "on")) {
+ if (flags & GFLAG_EAR) {
+ switch_set_flag((&globals), GFLAG_EAR);
+ }
+ if (flags & GFLAG_MOUTH) {
+ switch_set_flag((&globals), GFLAG_MOUTH);
+ }
+ } else if (!strcasecmp(action, "off")) {
+ if (flags & GFLAG_EAR) {
+ switch_clear_flag((&globals), GFLAG_EAR);
+ }
+ if (flags & GFLAG_MOUTH) {
+ switch_clear_flag((&globals), GFLAG_MOUTH);
+ }
+ } else {
+ goto bad;
+ }
+
+ desc:
+ x = 0;
+ stream->write_function(stream, "FLAGS: ");
+ if (switch_test_flag((&globals), GFLAG_EAR)) {
+ stream->write_function(stream, "ear");
+ x++;
+ }
+ if (switch_test_flag((&globals), GFLAG_MOUTH)) {
+ stream->write_function(stream, "%smouth", x ? "|" : "");
+ x++;
+ }
+ if (!x) {
+ stream->write_function(stream, "none");
+ }
+
+ goto done;
+
+ bad:
+ stream->write_function(stream, "Usage: flags [on|off] <flags>\n");
+ done:
+ return SWITCH_STATUS_SUCCESS;
+}
+
+static switch_status_t list_calls(char **argv, int argc, switch_stream_handle_t *stream)
+{
+ private_t *tp;
+ int x = 0;
+ char *cid_name = "n/a";
+ char *cid_num = "n/a";
+
+ switch_mutex_lock(globals.pvt_lock);
+ for (tp = globals.call_list; tp; tp = tp->next) {
+ switch_channel_t *channel;
+ switch_caller_profile_t *profile;
+ x++;
+ channel = switch_core_session_get_channel(tp->session);
+
+ if ((profile = switch_channel_get_caller_profile(channel))) {
+ if (profile->originatee_caller_profile) {
+ cid_name = "Outbound Call";
+ cid_num = profile->originatee_caller_profile->destination_number;
+ } else {
+ cid_name = profile->caller_id_name;
+ cid_num = profile->caller_id_number;
+ }
+ }
+
+ stream->write_function(stream, "%s %s [%s (%s)] %s\n", tp->call_id, switch_channel_get_name(channel),
+ cid_name, cid_num, switch_test_flag(tp, TFLAG_MASTER) ? "active" : "hold");
+ }
+ switch_mutex_unlock(globals.pvt_lock);
+
+ stream->write_function(stream, "\n%d call%s\n", x, x == 1 ? "" : "s");
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+static switch_status_t place_call(char **argv, int argc, switch_stream_handle_t *stream)
+{
+ switch_core_session_t *session;
+ switch_status_t status = SWITCH_STATUS_SUCCESS;
+ char *dest = NULL;
+
+ if (!argv[0]) {
+ stream->write_function(stream, "FAIL:Usage: call <dest>\n");
+ return SWITCH_STATUS_SUCCESS;
+ }
+ dest = argv[0];
+
+ if ((session = switch_core_session_request(&channel_endpoint_interface, NULL)) != 0) {
+ private_t *tech_pvt;
+ switch_channel_t *channel;
+ char *dialplan = globals.dialplan;
+ char *cid_name = globals.cid_name;
+ char *cid_num = globals.cid_num;
+
+ switch_core_session_add_stream(session, NULL);
+ if ((tech_pvt = (private_t *) switch_core_session_alloc(session, sizeof(private_t))) != 0) {
+ memset(tech_pvt, 0, sizeof(*tech_pvt));
+ switch_mutex_init(&tech_pvt->flag_mutex, SWITCH_MUTEX_NESTED, switch_core_session_get_pool(session));
+ channel = switch_core_session_get_channel(session);
+ switch_core_session_set_private(session, tech_pvt);
+ tech_pvt->session = session;
+ globals.flags = GFLAG_EAR | GFLAG_MOUTH;
+ } else {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Hey where is my memory pool?\n");
+ switch_core_session_destroy(&session);
+ return SWITCH_STATUS_MEMERR;
+ }
+
+ if (!switch_strlen_zero(argv[1])) {
+ dialplan = argv[1];
+ }
+
+ if (!switch_strlen_zero(argv[2])) {
+ cid_num = argv[2];
+ }
+
+ if (!switch_strlen_zero(argv[3])) {
+ cid_name = argv[3];
+ }
+
+ if (!switch_strlen_zero(argv[4])) {
+ tech_pvt->sample_rate = atoi(argv[4]);
+ }
+
+ if (!switch_strlen_zero(argv[4])) {
+ tech_pvt->codec_ms = atoi(argv[5]);
+ }
+
+ if ((tech_pvt->caller_profile = switch_caller_profile_new(switch_core_session_get_pool(session),
+ NULL,
+ dialplan, cid_name, cid_num, NULL, NULL, NULL, NULL, (char *) modname, NULL,
+ dest)) != 0) {
+ char name[128];
+ snprintf(name, sizeof(name), "Alsa/%s",
+ tech_pvt->caller_profile->destination_number ? tech_pvt->caller_profile->destination_number : modname);
+ switch_channel_set_name(channel, name);
+
+ switch_channel_set_caller_profile(channel, tech_pvt->caller_profile);
+ }
+ tech_pvt->session = session;
+ if ((status = engage_device(tech_pvt->sample_rate, tech_pvt->codec_ms)) == SWITCH_STATUS_SUCCESS) {
+ switch_set_flag_locked(tech_pvt, TFLAG_ANSWER);
+ switch_channel_mark_answered(channel);
+ switch_channel_set_state(channel, CS_INIT);
+ switch_core_session_thread_launch(tech_pvt->session);
+ add_pvt(tech_pvt, PA_MASTER);
+ stream->write_function(stream, "SUCCESS:%s:%s\n", tech_pvt->call_id, switch_core_session_get_uuid(tech_pvt->session));
+ } else {
+ switch_core_session_destroy(&session);
+ stream->write_function(stream, "FAIL:Device Error!\n");
+ }
+ }
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+static switch_status_t padep(char *cmd, switch_core_session_t *isession, switch_stream_handle_t *stream)
+{
+ stream->write_function(stream, "This command no longer exists (try 'pa help')\n");
+ return SWITCH_STATUS_SUCCESS;
+}
+
+static switch_status_t pa_cmd(char *cmd, switch_core_session_t *isession, switch_stream_handle_t *stream)
+{
+ char *argv[1024] = { 0 };
+ int argc = 0;
+ char *mycmd = NULL, *devname = NULL;
+ switch_status_t status = SWITCH_STATUS_SUCCESS;
+ pa_command_t func = NULL;
+ int lead = 1, devval = 0;
+ const char *usage_string = "USAGE:\n"
+ "--------------------------------------------------------------------------------\n"
+ "pa help\n"
+ "pa dump\n"
+ "pa call <dest> [<dialplan> <cid_name> <cid_num> <rate>]\n"
+ "pa answer [<call_id>]\n"
+ "pa hangup [<call_id>]\n"
+ "pa list\n"
+ "pa switch [<call_id>|none]\n"
+ "pa dtmf <digit string>\n"
+ "pa flags [on|off] [ear] [mouth]\n"
+ "--------------------------------------------------------------------------------\n";
+
+ if (switch_strlen_zero(cmd)) {
+ stream->write_function(stream, "%s", usage_string);
+ goto done;
+ }
+
+ if (!(mycmd = strdup(cmd))) {
+ status = SWITCH_STATUS_MEMERR;
+ goto done;
+ }
+
+ if (!(argc = switch_separate_string(mycmd, ' ', argv, (sizeof(argv) / sizeof(argv[0]))))) {
+ stream->write_function(stream, "%s", usage_string);
+ goto done;
+ }
+
+ if (!strcasecmp(argv[0], "call")) {
+ func = place_call;
+ } else if (!strcasecmp(argv[0], "help")) {
+ stream->write_function(stream, "%s", usage_string);
+ goto done;
+ } else if (!strcasecmp(argv[0], "list")) {
+ func = list_calls;
+ } else if (!strcasecmp(argv[0], "flags")) {
+ func = do_flags;
+ } else if (!strcasecmp(argv[0], "hangup")) {
+ func = hangup_call;
+ } else if (!strcasecmp(argv[0], "answer")) {
+ func = answer_call;
+ } else if (!strcasecmp(argv[0], "switch")) {
+ func = switch_call;
+ } else if (!strcasecmp(argv[0], "dtmf")) {
+ func = dtmf_call;
+ }
+
+ if (func) {
+ status = func(&argv[lead], argc - lead, stream);
+ } else {
+ if (devname) {
+ if (devval > 0) {
+ stream->write_function(stream, "%s set to %d\n", devname, devval);
+ } else {
+ stream->write_function(stream, "%s not set (invalid value)\n", devname);
+ }
+ } else {
+ stream->write_function(stream, "Unknown Command [%s]\n", argv[0]);
+ }
+ }
+
+ done:
+
+ switch_safe_free(mycmd);
+
+ return status;
+}
+
+
+/* For Emacs:
+ * Local Variables:
+ * mode:c
+ * indent-tabs-mode:t
+ * tab-width:4
+ * c-basic-offset:4
+ * End:
+ * For VIM:
+ * vim:set softtabstop=4 shiftwidth=4 tabstop=4 expandtab:
+ */
1
0