2007-03-29 22:34:40 +00:00
|
|
|
/*
|
|
|
|
* FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
|
2012-04-18 16:51:48 +00:00
|
|
|
* Copyright (C) 2005-2012, Anthony Minessale II <anthm@freeswitch.org>
|
2007-03-29 22:34:40 +00:00
|
|
|
*
|
|
|
|
* 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
|
2009-02-04 21:20:54 +00:00
|
|
|
* Anthony Minessale II <anthm@freeswitch.org>
|
2007-03-29 22:34:40 +00:00
|
|
|
* Portions created by the Initial Developer are Copyright (C)
|
|
|
|
* the Initial Developer. All Rights Reserved.
|
|
|
|
*
|
|
|
|
* Contributor(s):
|
|
|
|
*
|
2009-02-04 21:20:54 +00:00
|
|
|
* Anthony Minessale II <anthm@freeswitch.org>
|
2007-03-29 22:34:40 +00:00
|
|
|
* Michael Jerris <mike@jerris.com>
|
|
|
|
* Paul D. Tinsley <pdt at jackhammer.org>
|
2011-12-14 19:23:54 +00:00
|
|
|
* Joseph Sullivan <jossulli@amazon.com>
|
2007-03-29 22:34:40 +00:00
|
|
|
*
|
|
|
|
*
|
|
|
|
* switch_core_session.c -- Main Core Library (session routines)
|
|
|
|
*
|
|
|
|
*/
|
2008-01-27 17:36:53 +00:00
|
|
|
|
2007-12-30 21:42:15 +00:00
|
|
|
#include "switch.h"
|
|
|
|
#include "switch_core.h"
|
2007-05-14 17:10:46 +00:00
|
|
|
#include "private/switch_core_pvt.h"
|
2007-03-29 22:34:40 +00:00
|
|
|
|
2009-12-30 20:55:04 +00:00
|
|
|
struct switch_session_manager session_manager;
|
2007-03-29 22:34:40 +00:00
|
|
|
|
2011-09-02 14:34:40 +00:00
|
|
|
SWITCH_DECLARE(void) switch_core_session_set_dmachine(switch_core_session_t *session, switch_ivr_dmachine_t *dmachine, switch_digit_action_target_t target)
|
2010-10-07 23:30:07 +00:00
|
|
|
{
|
2011-09-02 14:34:40 +00:00
|
|
|
int i = (int) target;
|
|
|
|
|
|
|
|
if (i == 0 || i == 1) {
|
2011-10-04 19:37:48 +00:00
|
|
|
if (dmachine) {
|
|
|
|
switch_ivr_dmachine_set_target(dmachine, target);
|
|
|
|
}
|
2011-09-02 14:34:40 +00:00
|
|
|
session->dmachine[i] = dmachine;
|
|
|
|
}
|
2010-10-07 23:30:07 +00:00
|
|
|
}
|
|
|
|
|
2011-09-02 14:34:40 +00:00
|
|
|
SWITCH_DECLARE(switch_ivr_dmachine_t *) switch_core_session_get_dmachine(switch_core_session_t *session, switch_digit_action_target_t target)
|
2010-10-07 23:30:07 +00:00
|
|
|
{
|
2011-09-02 14:34:40 +00:00
|
|
|
int i = (int) target;
|
|
|
|
|
|
|
|
if (i == 0 || i == 1) {
|
|
|
|
return session->dmachine[i];
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
2010-10-07 23:30:07 +00:00
|
|
|
}
|
|
|
|
|
2012-10-18 19:29:00 +00:00
|
|
|
|
|
|
|
SWITCH_DECLARE(stfu_instance_t *) switch_core_session_get_jb(switch_core_session_t *session, switch_media_type_t type)
|
|
|
|
{
|
|
|
|
if (session->endpoint_interface->io_routines->get_jb) {
|
|
|
|
return session->endpoint_interface->io_routines->get_jb(session, type);
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2010-07-15 06:00:08 +00:00
|
|
|
SWITCH_DECLARE(void) switch_core_session_soft_lock(switch_core_session_t *session, uint32_t sec)
|
|
|
|
{
|
|
|
|
session->soft_lock = sec;
|
|
|
|
}
|
|
|
|
|
|
|
|
SWITCH_DECLARE(void) switch_core_session_soft_unlock(switch_core_session_t *session)
|
|
|
|
{
|
|
|
|
session->soft_lock = 0;
|
|
|
|
}
|
|
|
|
|
2011-01-06 23:41:17 +00:00
|
|
|
SWITCH_DECLARE(switch_status_t) switch_core_session_set_codec_slin(switch_core_session_t *session, switch_slin_data_t *data)
|
|
|
|
|
|
|
|
{
|
|
|
|
switch_codec_implementation_t read_impl = { 0 };
|
|
|
|
int interval;
|
|
|
|
|
|
|
|
switch_core_session_get_read_impl(session, &read_impl);
|
|
|
|
interval = read_impl.microseconds_per_packet / 1000;
|
|
|
|
data->session = session;
|
|
|
|
|
|
|
|
if (switch_core_codec_init(&data->codec,
|
|
|
|
"L16",
|
|
|
|
NULL,
|
|
|
|
read_impl.actual_samples_per_second,
|
|
|
|
interval,
|
|
|
|
1, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE, NULL, NULL) == SWITCH_STATUS_SUCCESS) {
|
|
|
|
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session),
|
|
|
|
SWITCH_LOG_DEBUG, "Codec Activated L16@%uhz %dms\n", read_impl.actual_samples_per_second, interval);
|
|
|
|
|
|
|
|
memset(&data->write_frame, 0, sizeof(data->write_frame));
|
|
|
|
|
|
|
|
data->write_frame.codec = &data->codec;
|
|
|
|
data->write_frame.data = data->frame_data;
|
|
|
|
data->write_frame.buflen = sizeof(data->frame_data);
|
|
|
|
data->write_frame.datalen = 0;
|
|
|
|
switch_core_session_set_read_codec(session, &data->codec);
|
|
|
|
return SWITCH_STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
return SWITCH_STATUS_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-05-12 14:48:14 +00:00
|
|
|
SWITCH_DECLARE(switch_core_session_t *) switch_core_session_perform_locate(const char *uuid_str, const char *file, const char *func, int line)
|
2007-03-29 22:34:40 +00:00
|
|
|
{
|
|
|
|
switch_core_session_t *session = NULL;
|
|
|
|
|
|
|
|
if (uuid_str) {
|
2009-03-07 17:45:37 +00:00
|
|
|
switch_mutex_lock(runtime.session_hash_mutex);
|
2007-05-10 16:56:29 +00:00
|
|
|
if ((session = switch_core_hash_find(session_manager.session_table, uuid_str))) {
|
2007-03-29 22:34:40 +00:00
|
|
|
/* Acquire a read lock on the session */
|
|
|
|
#ifdef SWITCH_DEBUG_RWLOCKS
|
2008-11-01 16:18:04 +00:00
|
|
|
if (switch_core_session_perform_read_lock(session, file, func, line) != SWITCH_STATUS_SUCCESS) {
|
2009-02-20 01:10:59 +00:00
|
|
|
#if EMACS_CC_MODE_IS_BUGGY
|
|
|
|
}
|
|
|
|
#endif
|
2007-03-29 22:34:40 +00:00
|
|
|
#else
|
2008-11-01 16:18:04 +00:00
|
|
|
if (switch_core_session_read_lock(session) != SWITCH_STATUS_SUCCESS) {
|
2007-03-29 22:34:40 +00:00
|
|
|
#endif
|
|
|
|
/* not available, forget it */
|
|
|
|
session = NULL;
|
|
|
|
}
|
|
|
|
}
|
2009-03-07 17:45:37 +00:00
|
|
|
switch_mutex_unlock(runtime.session_hash_mutex);
|
2007-03-29 22:34:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* if its not NULL, now it's up to you to rwunlock this */
|
|
|
|
return session;
|
|
|
|
}
|
|
|
|
|
2009-04-28 14:13:05 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
2012-08-15 20:11:57 +00:00
|
|
|
|
2009-04-28 14:13:05 +00:00
|
|
|
SWITCH_DECLARE(switch_core_session_t *) switch_core_session_perform_force_locate(const char *uuid_str, const char *file, const char *func, int line)
|
|
|
|
{
|
|
|
|
switch_core_session_t *session = NULL;
|
|
|
|
switch_status_t status;
|
2010-02-06 03:38:24 +00:00
|
|
|
|
2009-04-28 14:13:05 +00:00
|
|
|
if (uuid_str) {
|
|
|
|
switch_mutex_lock(runtime.session_hash_mutex);
|
|
|
|
if ((session = switch_core_hash_find(session_manager.session_table, uuid_str))) {
|
|
|
|
/* Acquire a read lock on the session */
|
|
|
|
|
|
|
|
if (switch_test_flag(session, SSF_DESTROYED)) {
|
|
|
|
status = SWITCH_STATUS_FALSE;
|
|
|
|
#ifdef SWITCH_DEBUG_RWLOCKS
|
2010-05-06 16:38:36 +00:00
|
|
|
switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, func, line, uuid_str, SWITCH_LOG_ERROR, "%s %s Read lock FAIL\n",
|
|
|
|
switch_core_session_get_uuid(session), switch_channel_get_name(session->channel));
|
2009-04-28 14:13:05 +00:00
|
|
|
#endif
|
|
|
|
} else {
|
|
|
|
status = (switch_status_t) switch_thread_rwlock_tryrdlock(session->rwlock);
|
|
|
|
#ifdef SWITCH_DEBUG_RWLOCKS
|
2010-05-06 16:38:36 +00:00
|
|
|
switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, func, line, uuid_str, SWITCH_LOG_ERROR, "%s %s Read lock ACQUIRED\n",
|
|
|
|
switch_core_session_get_uuid(session), switch_channel_get_name(session->channel));
|
2009-04-28 14:13:05 +00:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
if (status != SWITCH_STATUS_SUCCESS) {
|
|
|
|
/* not available, forget it */
|
|
|
|
session = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
switch_mutex_unlock(runtime.session_hash_mutex);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* if its not NULL, now it's up to you to rwunlock this */
|
|
|
|
return session;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-08-15 20:11:57 +00:00
|
|
|
SWITCH_DECLARE(switch_status_t) switch_core_session_perform_get_partner(switch_core_session_t *session, switch_core_session_t **partner,
|
|
|
|
const char *file, const char *func, int line)
|
2009-04-27 17:45:04 +00:00
|
|
|
{
|
|
|
|
const char *uuid;
|
2010-02-06 03:38:24 +00:00
|
|
|
|
2012-05-29 18:10:15 +00:00
|
|
|
if ((uuid = switch_channel_get_partner_uuid(session->channel))) {
|
2012-08-15 20:11:57 +00:00
|
|
|
if ((*partner = switch_core_session_perform_locate(uuid, file, func, line))) {
|
2009-04-28 14:13:05 +00:00
|
|
|
return SWITCH_STATUS_SUCCESS;
|
|
|
|
}
|
2009-04-27 17:45:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
*partner = NULL;
|
|
|
|
return SWITCH_STATUS_FALSE;
|
|
|
|
}
|
|
|
|
|
2008-07-01 23:41:09 +00:00
|
|
|
|
2010-04-02 19:45:36 +00:00
|
|
|
struct str_node {
|
|
|
|
char *str;
|
|
|
|
struct str_node *next;
|
|
|
|
};
|
|
|
|
|
2012-11-01 18:07:42 +00:00
|
|
|
SWITCH_DECLARE(uint32_t) switch_core_session_hupall_matching_var_ans(const char *var_name, const char *var_val, switch_call_cause_t cause,
|
|
|
|
switch_hup_type_t type)
|
2008-07-01 23:41:09 +00:00
|
|
|
{
|
|
|
|
switch_hash_index_t *hi;
|
|
|
|
void *val;
|
|
|
|
switch_core_session_t *session;
|
2009-03-09 22:51:31 +00:00
|
|
|
switch_memory_pool_t *pool;
|
2010-04-02 19:45:36 +00:00
|
|
|
struct str_node *head = NULL, *np;
|
2012-11-01 18:07:42 +00:00
|
|
|
uint32_t r = 0;
|
2010-02-06 03:38:24 +00:00
|
|
|
|
2009-03-09 22:51:31 +00:00
|
|
|
switch_core_new_memory_pool(&pool);
|
2008-07-01 23:41:09 +00:00
|
|
|
|
2010-02-06 03:38:24 +00:00
|
|
|
if (!var_val)
|
2012-11-01 18:07:42 +00:00
|
|
|
return r;
|
2008-11-07 23:08:57 +00:00
|
|
|
|
2009-03-07 17:45:37 +00:00
|
|
|
switch_mutex_lock(runtime.session_hash_mutex);
|
2008-07-01 23:41:09 +00:00
|
|
|
for (hi = switch_hash_first(NULL, session_manager.session_table); hi; hi = switch_hash_next(hi)) {
|
|
|
|
switch_hash_this(hi, NULL, NULL, &val);
|
|
|
|
if (val) {
|
|
|
|
session = (switch_core_session_t *) val;
|
2008-11-12 19:28:05 +00:00
|
|
|
if (switch_core_session_read_lock(session) == SWITCH_STATUS_SUCCESS) {
|
2012-11-01 18:07:42 +00:00
|
|
|
int ans = switch_channel_test_flag(switch_core_session_get_channel(session), CF_ANSWERED);
|
|
|
|
if ((ans && (type & SHT_ANSWERED)) || (!ans && (type & SHT_UNANSWERED))) {
|
|
|
|
np = switch_core_alloc(pool, sizeof(*np));
|
|
|
|
np->str = switch_core_strdup(pool, session->uuid_str);
|
|
|
|
np->next = head;
|
|
|
|
head = np;
|
|
|
|
}
|
2008-11-12 19:28:05 +00:00
|
|
|
switch_core_session_rwunlock(session);
|
2008-07-01 23:41:09 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2009-03-07 17:45:37 +00:00
|
|
|
switch_mutex_unlock(runtime.session_hash_mutex);
|
2009-03-09 22:51:31 +00:00
|
|
|
|
2010-04-02 19:45:36 +00:00
|
|
|
for(np = head; np; np = np->next) {
|
|
|
|
if ((session = switch_core_session_locate(np->str))) {
|
2011-02-22 19:16:16 +00:00
|
|
|
const char *this_val;
|
2011-11-18 19:17:56 +00:00
|
|
|
if (switch_channel_up_nosig(session->channel) &&
|
2011-02-22 19:16:16 +00:00
|
|
|
(this_val = switch_channel_get_variable(session->channel, var_name)) && (!strcmp(this_val, var_val))) {
|
|
|
|
switch_channel_hangup(session->channel, cause);
|
2012-11-01 18:07:42 +00:00
|
|
|
r++;
|
2011-02-22 19:16:16 +00:00
|
|
|
}
|
2009-03-09 22:51:31 +00:00
|
|
|
switch_core_session_rwunlock(session);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
switch_core_destroy_memory_pool(&pool);
|
|
|
|
|
2012-11-01 18:07:42 +00:00
|
|
|
return r;
|
2010-02-06 03:38:24 +00:00
|
|
|
}
|
2008-07-01 23:41:09 +00:00
|
|
|
|
2012-10-11 14:57:02 +00:00
|
|
|
|
|
|
|
SWITCH_DECLARE(switch_console_callback_match_t *) switch_core_session_findall_matching_var(const char *var_name, const char *var_val)
|
|
|
|
{
|
|
|
|
switch_hash_index_t *hi;
|
|
|
|
void *val;
|
|
|
|
switch_core_session_t *session;
|
|
|
|
switch_memory_pool_t *pool;
|
|
|
|
struct str_node *head = NULL, *np;
|
|
|
|
switch_console_callback_match_t *my_matches = NULL;
|
|
|
|
|
|
|
|
switch_core_new_memory_pool(&pool);
|
|
|
|
|
|
|
|
if (!var_val)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
switch_mutex_lock(runtime.session_hash_mutex);
|
|
|
|
for (hi = switch_hash_first(NULL, session_manager.session_table); hi; hi = switch_hash_next(hi)) {
|
|
|
|
switch_hash_this(hi, NULL, NULL, &val);
|
|
|
|
if (val) {
|
|
|
|
session = (switch_core_session_t *) val;
|
|
|
|
if (switch_core_session_read_lock(session) == SWITCH_STATUS_SUCCESS) {
|
|
|
|
np = switch_core_alloc(pool, sizeof(*np));
|
|
|
|
np->str = switch_core_strdup(pool, session->uuid_str);
|
|
|
|
np->next = head;
|
|
|
|
head = np;
|
|
|
|
switch_core_session_rwunlock(session);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
switch_mutex_unlock(runtime.session_hash_mutex);
|
|
|
|
|
|
|
|
for(np = head; np; np = np->next) {
|
|
|
|
if ((session = switch_core_session_locate(np->str))) {
|
|
|
|
const char *this_val;
|
|
|
|
if (switch_channel_up_nosig(session->channel) &&
|
|
|
|
(this_val = switch_channel_get_variable_dup(session->channel, var_name, SWITCH_FALSE, -1)) && (!strcmp(this_val, var_val))) {
|
|
|
|
switch_console_push_match(&my_matches, (const char *) np->str);
|
|
|
|
}
|
|
|
|
switch_core_session_rwunlock(session);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
switch_core_destroy_memory_pool(&pool);
|
|
|
|
|
|
|
|
|
|
|
|
return my_matches;
|
|
|
|
}
|
|
|
|
|
2008-07-01 23:41:09 +00:00
|
|
|
SWITCH_DECLARE(void) switch_core_session_hupall_endpoint(const switch_endpoint_interface_t *endpoint_interface, switch_call_cause_t cause)
|
|
|
|
{
|
|
|
|
switch_hash_index_t *hi;
|
|
|
|
void *val;
|
|
|
|
switch_core_session_t *session;
|
2009-03-09 22:51:31 +00:00
|
|
|
switch_memory_pool_t *pool;
|
2010-04-02 19:45:36 +00:00
|
|
|
struct str_node *head = NULL, *np;
|
|
|
|
|
2009-03-09 22:51:31 +00:00
|
|
|
switch_core_new_memory_pool(&pool);
|
2010-04-02 19:45:36 +00:00
|
|
|
|
2009-03-07 17:45:37 +00:00
|
|
|
switch_mutex_lock(runtime.session_hash_mutex);
|
2008-07-01 23:41:09 +00:00
|
|
|
for (hi = switch_hash_first(NULL, session_manager.session_table); hi; hi = switch_hash_next(hi)) {
|
|
|
|
switch_hash_this(hi, NULL, NULL, &val);
|
|
|
|
if (val) {
|
|
|
|
session = (switch_core_session_t *) val;
|
2009-01-09 20:34:01 +00:00
|
|
|
if (switch_core_session_read_lock(session) == SWITCH_STATUS_SUCCESS) {
|
|
|
|
if (session->endpoint_interface == endpoint_interface) {
|
2010-04-02 19:45:36 +00:00
|
|
|
np = switch_core_alloc(pool, sizeof(*np));
|
|
|
|
np->str = switch_core_strdup(pool, session->uuid_str);
|
|
|
|
np->next = head;
|
|
|
|
head = np;
|
2009-01-09 20:34:01 +00:00
|
|
|
}
|
|
|
|
switch_core_session_rwunlock(session);
|
2008-07-01 23:41:09 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2009-03-07 17:45:37 +00:00
|
|
|
switch_mutex_unlock(runtime.session_hash_mutex);
|
2009-03-09 22:51:31 +00:00
|
|
|
|
2010-04-02 19:45:36 +00:00
|
|
|
for(np = head; np; np = np->next) {
|
|
|
|
if ((session = switch_core_session_locate(np->str))) {
|
2009-03-09 22:51:31 +00:00
|
|
|
switch_channel_hangup(session->channel, cause);
|
|
|
|
switch_core_session_rwunlock(session);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
switch_core_destroy_memory_pool(&pool);
|
|
|
|
|
2010-02-06 03:38:24 +00:00
|
|
|
}
|
2008-07-01 23:41:09 +00:00
|
|
|
|
2007-03-29 22:34:40 +00:00
|
|
|
SWITCH_DECLARE(void) switch_core_session_hupall(switch_call_cause_t cause)
|
|
|
|
{
|
|
|
|
switch_hash_index_t *hi;
|
|
|
|
void *val;
|
|
|
|
switch_core_session_t *session;
|
2009-03-09 22:51:31 +00:00
|
|
|
switch_memory_pool_t *pool;
|
2010-04-02 19:45:36 +00:00
|
|
|
struct str_node *head = NULL, *np;
|
2010-02-06 03:38:24 +00:00
|
|
|
|
2009-03-09 22:51:31 +00:00
|
|
|
switch_core_new_memory_pool(&pool);
|
2010-04-02 19:45:36 +00:00
|
|
|
|
2009-03-09 22:51:31 +00:00
|
|
|
|
|
|
|
switch_mutex_lock(runtime.session_hash_mutex);
|
|
|
|
for (hi = switch_hash_first(NULL, session_manager.session_table); hi; hi = switch_hash_next(hi)) {
|
|
|
|
switch_hash_this(hi, NULL, NULL, &val);
|
|
|
|
if (val) {
|
|
|
|
session = (switch_core_session_t *) val;
|
|
|
|
if (switch_core_session_read_lock(session) == SWITCH_STATUS_SUCCESS) {
|
2010-04-02 19:45:36 +00:00
|
|
|
np = switch_core_alloc(pool, sizeof(*np));
|
|
|
|
np->str = switch_core_strdup(pool, session->uuid_str);
|
|
|
|
np->next = head;
|
|
|
|
head = np;
|
2009-03-09 22:51:31 +00:00
|
|
|
switch_core_session_rwunlock(session);
|
2009-01-09 20:34:01 +00:00
|
|
|
}
|
2007-03-29 22:34:40 +00:00
|
|
|
}
|
2009-03-09 22:51:31 +00:00
|
|
|
}
|
|
|
|
switch_mutex_unlock(runtime.session_hash_mutex);
|
2010-02-06 03:38:24 +00:00
|
|
|
|
2010-04-02 19:45:36 +00:00
|
|
|
for(np = head; np; np = np->next) {
|
|
|
|
if ((session = switch_core_session_locate(np->str))) {
|
2009-03-09 22:51:31 +00:00
|
|
|
switch_channel_hangup(session->channel, cause);
|
|
|
|
switch_core_session_rwunlock(session);
|
2007-03-29 22:34:40 +00:00
|
|
|
}
|
|
|
|
}
|
2009-03-09 22:51:31 +00:00
|
|
|
|
|
|
|
switch_core_destroy_memory_pool(&pool);
|
2010-02-06 03:38:24 +00:00
|
|
|
|
2007-03-29 22:34:40 +00:00
|
|
|
}
|
|
|
|
|
2010-02-06 03:38:24 +00:00
|
|
|
|
2013-03-27 20:51:23 +00:00
|
|
|
SWITCH_DECLARE(switch_console_callback_match_t *) switch_core_session_findall(void)
|
|
|
|
{
|
|
|
|
switch_hash_index_t *hi;
|
|
|
|
void *val;
|
|
|
|
switch_core_session_t *session;
|
|
|
|
switch_console_callback_match_t *my_matches = NULL;
|
|
|
|
|
|
|
|
switch_mutex_lock(runtime.session_hash_mutex);
|
|
|
|
for (hi = switch_hash_first(NULL, session_manager.session_table); hi; hi = switch_hash_next(hi)) {
|
|
|
|
switch_hash_this(hi, NULL, NULL, &val);
|
|
|
|
if (val) {
|
|
|
|
session = (switch_core_session_t *) val;
|
|
|
|
if (switch_core_session_read_lock(session) == SWITCH_STATUS_SUCCESS) {
|
|
|
|
switch_console_push_match(&my_matches, session->uuid_str);
|
|
|
|
switch_core_session_rwunlock(session);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
switch_mutex_unlock(runtime.session_hash_mutex);
|
|
|
|
|
|
|
|
return my_matches;
|
|
|
|
}
|
|
|
|
|
2007-12-30 21:42:15 +00:00
|
|
|
SWITCH_DECLARE(switch_status_t) switch_core_session_message_send(const char *uuid_str, switch_core_session_message_t *message)
|
2007-03-29 22:34:40 +00:00
|
|
|
{
|
|
|
|
switch_core_session_t *session = NULL;
|
|
|
|
switch_status_t status = SWITCH_STATUS_FALSE;
|
|
|
|
|
2009-03-07 17:45:37 +00:00
|
|
|
switch_mutex_lock(runtime.session_hash_mutex);
|
2007-05-10 16:56:29 +00:00
|
|
|
if ((session = switch_core_hash_find(session_manager.session_table, uuid_str)) != 0) {
|
2007-03-29 22:34:40 +00:00
|
|
|
/* Acquire a read lock on the session or forget it the channel is dead */
|
|
|
|
if (switch_core_session_read_lock(session) == SWITCH_STATUS_SUCCESS) {
|
2011-11-18 19:17:56 +00:00
|
|
|
if (switch_channel_up_nosig(session->channel)) {
|
2007-03-29 22:34:40 +00:00
|
|
|
status = switch_core_session_receive_message(session, message);
|
|
|
|
}
|
|
|
|
switch_core_session_rwunlock(session);
|
|
|
|
}
|
|
|
|
}
|
2009-03-07 17:45:37 +00:00
|
|
|
switch_mutex_unlock(runtime.session_hash_mutex);
|
2007-03-29 22:34:40 +00:00
|
|
|
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
2007-12-30 21:42:15 +00:00
|
|
|
SWITCH_DECLARE(switch_status_t) switch_core_session_event_send(const char *uuid_str, switch_event_t **event)
|
2007-03-29 22:34:40 +00:00
|
|
|
{
|
|
|
|
switch_core_session_t *session = NULL;
|
|
|
|
switch_status_t status = SWITCH_STATUS_FALSE;
|
|
|
|
|
2009-03-07 17:45:37 +00:00
|
|
|
switch_mutex_lock(runtime.session_hash_mutex);
|
2007-05-10 16:56:29 +00:00
|
|
|
if ((session = switch_core_hash_find(session_manager.session_table, uuid_str)) != 0) {
|
2007-03-29 22:34:40 +00:00
|
|
|
/* Acquire a read lock on the session or forget it the channel is dead */
|
|
|
|
if (switch_core_session_read_lock(session) == SWITCH_STATUS_SUCCESS) {
|
2011-11-18 19:17:56 +00:00
|
|
|
if (switch_channel_up_nosig(session->channel)) {
|
2007-03-29 22:34:40 +00:00
|
|
|
status = switch_core_session_queue_event(session, event);
|
|
|
|
}
|
|
|
|
switch_core_session_rwunlock(session);
|
|
|
|
}
|
|
|
|
}
|
2009-03-07 17:45:37 +00:00
|
|
|
switch_mutex_unlock(runtime.session_hash_mutex);
|
2007-03-29 22:34:40 +00:00
|
|
|
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
SWITCH_DECLARE(void *) switch_core_session_get_private(switch_core_session_t *session)
|
|
|
|
{
|
2007-12-11 19:23:57 +00:00
|
|
|
switch_assert(session != NULL);
|
2007-03-29 22:34:40 +00:00
|
|
|
return session->private_info;
|
|
|
|
}
|
2010-02-06 03:38:24 +00:00
|
|
|
|
2007-03-29 22:34:40 +00:00
|
|
|
|
|
|
|
SWITCH_DECLARE(switch_status_t) switch_core_session_set_private(switch_core_session_t *session, void *private_info)
|
|
|
|
{
|
2007-12-11 19:23:57 +00:00
|
|
|
switch_assert(session != NULL);
|
2007-03-29 22:34:40 +00:00
|
|
|
session->private_info = private_info;
|
|
|
|
return SWITCH_STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
SWITCH_DECLARE(int) switch_core_session_add_stream(switch_core_session_t *session, void *private_info)
|
|
|
|
{
|
|
|
|
session->streams[session->stream_count++] = private_info;
|
|
|
|
return session->stream_count - 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
SWITCH_DECLARE(void *) switch_core_session_get_stream(switch_core_session_t *session, int index)
|
|
|
|
{
|
|
|
|
return session->streams[index];
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
SWITCH_DECLARE(int) switch_core_session_get_stream_count(switch_core_session_t *session)
|
|
|
|
{
|
|
|
|
return session->stream_count;
|
|
|
|
}
|
|
|
|
|
2008-05-27 04:30:03 +00:00
|
|
|
SWITCH_DECLARE(switch_call_cause_t) switch_core_session_outgoing_channel(switch_core_session_t *session, switch_event_t *var_event,
|
|
|
|
const char *endpoint_name,
|
|
|
|
switch_caller_profile_t *caller_profile,
|
|
|
|
switch_core_session_t **new_session,
|
2010-02-06 03:38:24 +00:00
|
|
|
switch_memory_pool_t **pool,
|
|
|
|
switch_originate_flag_t flags, switch_call_cause_t *cancel_cause)
|
2007-03-29 22:34:40 +00:00
|
|
|
{
|
|
|
|
switch_io_event_hook_outgoing_channel_t *ptr;
|
|
|
|
switch_status_t status = SWITCH_STATUS_FALSE;
|
2008-11-19 19:22:20 +00:00
|
|
|
switch_endpoint_interface_t *endpoint_interface;
|
2007-03-29 22:34:40 +00:00
|
|
|
switch_channel_t *channel = NULL;
|
|
|
|
switch_caller_profile_t *outgoing_profile = caller_profile;
|
|
|
|
switch_call_cause_t cause = SWITCH_CAUSE_REQUESTED_CHAN_UNAVAIL;
|
2007-12-24 19:23:36 +00:00
|
|
|
const char *forwardvar;
|
|
|
|
int forwardval = 70;
|
2007-03-29 22:34:40 +00:00
|
|
|
|
|
|
|
if ((endpoint_interface = switch_loadable_module_get_endpoint_interface(endpoint_name)) == 0) {
|
2009-08-13 20:35:02 +00:00
|
|
|
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Could not locate channel type %s\n", endpoint_name);
|
2007-03-29 22:34:40 +00:00
|
|
|
return SWITCH_CAUSE_CHAN_NOT_IMPLEMENTED;
|
|
|
|
}
|
|
|
|
|
2007-12-24 19:23:36 +00:00
|
|
|
if (!endpoint_interface->io_routines->outgoing_channel) {
|
2009-08-13 20:35:02 +00:00
|
|
|
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Could not locate outgoing channel interface for %s\n", endpoint_name);
|
2007-12-24 19:23:36 +00:00
|
|
|
return SWITCH_CAUSE_CHAN_NOT_IMPLEMENTED;
|
|
|
|
}
|
2007-03-29 22:34:40 +00:00
|
|
|
|
2007-12-24 19:23:36 +00:00
|
|
|
if (session) {
|
|
|
|
channel = switch_core_session_get_channel(session);
|
2007-12-24 23:32:01 +00:00
|
|
|
|
2008-05-16 15:29:44 +00:00
|
|
|
switch_assert(channel != NULL);
|
2008-05-27 04:30:03 +00:00
|
|
|
|
2007-12-24 23:32:01 +00:00
|
|
|
forwardvar = switch_channel_get_variable(channel, SWITCH_MAX_FORWARDS_VARIABLE);
|
2009-10-23 16:03:42 +00:00
|
|
|
if (!zstr(forwardvar)) {
|
2008-05-27 04:30:03 +00:00
|
|
|
forwardval = atoi(forwardvar) - 1;
|
2007-12-24 23:32:01 +00:00
|
|
|
}
|
|
|
|
if (forwardval <= 0) {
|
|
|
|
return SWITCH_CAUSE_EXCHANGE_ROUTING_ERROR;
|
|
|
|
}
|
|
|
|
|
2007-12-24 19:23:36 +00:00
|
|
|
if (caller_profile) {
|
|
|
|
const char *ecaller_id_name = NULL, *ecaller_id_number = NULL;
|
2010-02-06 03:38:24 +00:00
|
|
|
|
2008-08-11 21:27:20 +00:00
|
|
|
if (!(flags & SOF_NO_EFFECTIVE_CID_NAME)) {
|
|
|
|
ecaller_id_name = switch_channel_get_variable(channel, "effective_caller_id_name");
|
|
|
|
}
|
2007-08-28 21:43:18 +00:00
|
|
|
|
2008-08-11 21:27:20 +00:00
|
|
|
if (!(flags & SOF_NO_EFFECTIVE_CID_NUM)) {
|
|
|
|
ecaller_id_number = switch_channel_get_variable(channel, "effective_caller_id_number");
|
|
|
|
}
|
2007-12-24 19:23:36 +00:00
|
|
|
|
|
|
|
if (ecaller_id_name || ecaller_id_number) {
|
|
|
|
outgoing_profile = switch_caller_profile_clone(session, caller_profile);
|
|
|
|
|
|
|
|
if (ecaller_id_name) {
|
|
|
|
outgoing_profile->caller_id_name = ecaller_id_name;
|
|
|
|
}
|
|
|
|
if (ecaller_id_number) {
|
|
|
|
outgoing_profile->caller_id_number = ecaller_id_number;
|
2007-03-29 22:34:40 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2007-12-24 19:23:36 +00:00
|
|
|
if (!outgoing_profile) {
|
|
|
|
outgoing_profile = switch_channel_get_caller_profile(channel);
|
2007-04-16 20:51:19 +00:00
|
|
|
}
|
2007-12-24 19:23:36 +00:00
|
|
|
}
|
2007-04-16 20:51:19 +00:00
|
|
|
|
2008-05-27 04:30:03 +00:00
|
|
|
if ((cause =
|
2010-02-06 03:38:24 +00:00
|
|
|
endpoint_interface->io_routines->outgoing_channel(session, var_event, outgoing_profile, new_session, pool, flags,
|
|
|
|
cancel_cause)) != SWITCH_CAUSE_SUCCESS) {
|
2008-11-19 19:22:20 +00:00
|
|
|
UNPROTECT_INTERFACE(endpoint_interface);
|
2007-12-24 19:23:36 +00:00
|
|
|
return cause;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (session) {
|
|
|
|
for (ptr = session->event_hooks.outgoing_channel; ptr; ptr = ptr->next) {
|
2008-05-15 19:29:35 +00:00
|
|
|
if ((status = ptr->outgoing_channel(session, var_event, caller_profile, *new_session, flags)) != SWITCH_STATUS_SUCCESS) {
|
2007-12-24 19:23:36 +00:00
|
|
|
break;
|
2007-03-29 22:34:40 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-02-06 01:05:01 +00:00
|
|
|
if (!*new_session) {
|
2010-02-06 03:38:24 +00:00
|
|
|
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_CRIT,
|
|
|
|
"Outgoing method for endpoint: [%s] returned: [%s] but there is no new session!\n", endpoint_name,
|
|
|
|
switch_channel_cause2str(cause));
|
2008-11-19 19:22:20 +00:00
|
|
|
UNPROTECT_INTERFACE(endpoint_interface);
|
2008-02-06 01:05:01 +00:00
|
|
|
return SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER;
|
|
|
|
} else {
|
2011-04-22 21:43:29 +00:00
|
|
|
switch_caller_profile_t *profile = NULL, *cloned_profile = NULL;
|
2007-03-29 22:34:40 +00:00
|
|
|
switch_event_t *event;
|
|
|
|
switch_channel_t *peer_channel = switch_core_session_get_channel(*new_session);
|
2008-11-04 16:46:33 +00:00
|
|
|
const char *use_uuid;
|
2008-05-27 04:30:03 +00:00
|
|
|
|
2008-05-16 15:29:44 +00:00
|
|
|
switch_assert(peer_channel);
|
2008-05-27 04:30:03 +00:00
|
|
|
|
2012-10-11 17:44:31 +00:00
|
|
|
if (channel && switch_true(switch_channel_get_variable(channel, "session_copy_loglevel"))) {
|
|
|
|
(*new_session)->loglevel = session->loglevel;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-11-04 16:46:33 +00:00
|
|
|
if ((use_uuid = switch_event_get_header(var_event, "origination_uuid"))) {
|
2009-03-13 01:57:10 +00:00
|
|
|
use_uuid = switch_core_session_strdup(*new_session, use_uuid);
|
2008-11-04 16:46:33 +00:00
|
|
|
if (switch_core_session_set_uuid(*new_session, use_uuid) == SWITCH_STATUS_SUCCESS) {
|
|
|
|
switch_event_del_header(var_event, "origination_uuid");
|
2010-02-06 03:38:24 +00:00
|
|
|
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(*new_session), SWITCH_LOG_DEBUG, "%s set UUID=%s\n", switch_channel_get_name(peer_channel),
|
|
|
|
use_uuid);
|
2008-11-04 16:46:33 +00:00
|
|
|
} else {
|
2010-02-06 03:38:24 +00:00
|
|
|
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(*new_session), SWITCH_LOG_CRIT, "%s set UUID=%s FAILED\n",
|
|
|
|
switch_channel_get_name(peer_channel), use_uuid);
|
2008-11-04 16:46:33 +00:00
|
|
|
}
|
|
|
|
}
|
2010-02-06 03:38:24 +00:00
|
|
|
|
2008-05-16 15:29:44 +00:00
|
|
|
if (channel) {
|
2009-11-06 16:11:26 +00:00
|
|
|
const char *val;
|
2009-02-10 19:09:06 +00:00
|
|
|
switch_codec_t *vid_read_codec = NULL, *read_codec = switch_core_session_get_read_codec(session);
|
2011-08-01 15:22:55 +00:00
|
|
|
const char *ep, *max_forwards = switch_core_session_sprintf(session, "%d", forwardval);
|
2008-05-16 15:29:44 +00:00
|
|
|
|
2007-12-24 19:23:36 +00:00
|
|
|
switch_channel_set_variable(peer_channel, SWITCH_MAX_FORWARDS_VARIABLE, max_forwards);
|
2007-03-29 22:34:40 +00:00
|
|
|
|
2008-05-16 15:29:44 +00:00
|
|
|
profile = switch_channel_get_caller_profile(channel);
|
|
|
|
|
2009-02-10 19:19:53 +00:00
|
|
|
vid_read_codec = switch_core_session_get_video_read_codec(session);
|
|
|
|
|
2009-04-09 17:17:12 +00:00
|
|
|
if (read_codec && read_codec->implementation && switch_core_codec_ready(read_codec)) {
|
2009-02-10 19:19:53 +00:00
|
|
|
char rc[80] = "", vrc[80] = "", tmp[160] = "";
|
2010-02-06 03:38:24 +00:00
|
|
|
|
2009-02-10 19:19:53 +00:00
|
|
|
switch_codec2str(read_codec, rc, sizeof(rc));
|
2009-04-09 17:17:12 +00:00
|
|
|
if (vid_read_codec && vid_read_codec->implementation && switch_core_codec_ready(vid_read_codec)) {
|
2009-02-10 19:19:53 +00:00
|
|
|
vrc[0] = ',';
|
2012-04-13 12:33:00 +00:00
|
|
|
switch_codec2str(vid_read_codec, vrc + 1, sizeof(vrc) - 1);
|
2010-02-06 03:38:24 +00:00
|
|
|
switch_channel_set_variable(peer_channel, SWITCH_ORIGINATOR_VIDEO_CODEC_VARIABLE, vrc + 1);
|
2009-02-10 19:19:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
switch_snprintf(tmp, sizeof(tmp), "%s%s", rc, vrc);
|
2007-03-29 22:34:40 +00:00
|
|
|
switch_channel_set_variable(peer_channel, SWITCH_ORIGINATOR_CODEC_VARIABLE, tmp);
|
2011-08-01 15:22:55 +00:00
|
|
|
} else if ((ep = switch_channel_get_variable(channel, "ep_codec_string"))) {
|
|
|
|
switch_channel_set_variable(peer_channel, SWITCH_ORIGINATOR_CODEC_VARIABLE, ep);
|
2007-03-29 22:34:40 +00:00
|
|
|
}
|
|
|
|
|
2007-03-30 00:13:31 +00:00
|
|
|
switch_channel_set_variable(peer_channel, SWITCH_ORIGINATOR_VARIABLE, switch_core_session_get_uuid(session));
|
|
|
|
switch_channel_set_variable(peer_channel, SWITCH_SIGNAL_BOND_VARIABLE, switch_core_session_get_uuid(session));
|
2012-03-09 17:43:37 +00:00
|
|
|
// Needed by 3PCC proxy so that aleg can find bleg to pass SDP to, when final ACK arrives.
|
2012-05-29 18:10:15 +00:00
|
|
|
switch_channel_set_variable(channel, SWITCH_ORIGINATE_SIGNAL_BOND_VARIABLE, switch_core_session_get_uuid(*new_session));
|
2007-03-29 22:34:40 +00:00
|
|
|
|
2008-01-14 16:10:56 +00:00
|
|
|
if ((val = switch_channel_get_variable(channel, SWITCH_PROCESS_CDR_VARIABLE))) {
|
|
|
|
switch_channel_set_variable(peer_channel, SWITCH_PROCESS_CDR_VARIABLE, val);
|
|
|
|
}
|
|
|
|
|
2007-03-29 22:34:40 +00:00
|
|
|
if ((val = switch_channel_get_variable(channel, SWITCH_R_SDP_VARIABLE))) {
|
|
|
|
switch_channel_set_variable(peer_channel, SWITCH_B_SDP_VARIABLE, val);
|
|
|
|
}
|
|
|
|
|
2008-02-21 17:48:41 +00:00
|
|
|
if (switch_channel_test_flag(channel, CF_PROXY_MODE)) {
|
2009-10-19 19:58:23 +00:00
|
|
|
if (switch_channel_test_cap(peer_channel, CC_BYPASS_MEDIA)) {
|
2010-02-06 03:38:24 +00:00
|
|
|
switch_channel_set_flag(peer_channel, CF_PROXY_MODE);
|
2009-10-19 19:58:23 +00:00
|
|
|
} else {
|
2010-02-06 03:38:24 +00:00
|
|
|
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING,
|
|
|
|
"%s does not support the proxy feature, disabling.\n", switch_channel_get_name(peer_channel));
|
2009-10-19 19:58:23 +00:00
|
|
|
switch_channel_clear_flag(channel, CF_PROXY_MODE);
|
2009-10-20 17:03:03 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (switch_channel_test_flag(channel, CF_PROXY_MEDIA)) {
|
|
|
|
if (switch_channel_test_cap(peer_channel, CC_PROXY_MEDIA)) {
|
|
|
|
switch_channel_set_flag(peer_channel, CF_PROXY_MEDIA);
|
|
|
|
if (switch_channel_test_flag(channel, CF_VIDEO)) {
|
|
|
|
switch_channel_set_flag(peer_channel, CF_VIDEO);
|
|
|
|
}
|
|
|
|
} else {
|
2010-02-06 03:38:24 +00:00
|
|
|
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING,
|
|
|
|
"%s does not support the proxy feature, disabling.\n", switch_channel_get_name(peer_channel));
|
2009-10-19 19:58:23 +00:00
|
|
|
switch_channel_clear_flag(channel, CF_PROXY_MEDIA);
|
2008-05-23 19:41:23 +00:00
|
|
|
}
|
2007-03-29 22:34:40 +00:00
|
|
|
}
|
add enhanced zrtp passthrough (zrtp passthru) mode
ZRTP passthrough mode allows two ZRTP-capable clients to negotiate an
end-to-end security association through FreeSWITCH. The clients are
therefore able to be certain that the FreeSWITCH instance mediating
the call cannot eavesdrop on their conversation.
Importantly, this capability is maintained across multiple FreeSWITCH
hops. If widely deployed, this enables a global network architecture
where two people can speak securely with strong cryptographically
protected authentication and confidentiality.
With this commit we implement a zrtp-passthru mode that handles all
the details of the negotiation intelligently. This mode can be
selected by setting the boolean parameter inbound-zrtp-passthru in the
sofia profile. This will also force late-negotiation as it is
essential for correctly negotiating an end-to-end ZRTP security
association.
When an incoming call with a zrtp-hash is received and this mode is
enabled, we find the first audio and the first video zrtp-hash in the
SDP and store them as remote values on this channel. Once a b-leg is
available, we set the local zrtp-hash values on that channel to the
remote zrtp-hash values collected from the a-leg.
Because zrtp-passthru absolutely requires that the channels negotiate
the same codec, we offer to the b-leg only codecs that the a-leg can
speak. Once the b-leg accepts a codec, we will force that choice onto
the a-leg.
If the b-leg sends us zrtp-hash values in the signaling, we store
those as remote values on the b-leg and copy them to the local values
on the a-leg.
At this point, each leg has the zrtp-hash values from the other, and
we know we can do ZRTP passthrough mode on the call. We send the
b-leg's zrtp-hash back to the a-leg in the 200 OK.
We then enable UDPTL mode on the rtp streams for both the audio and
the video so that we don't interfere in the ZRTP negotiation.
If the b-leg fails to return a zrtp-hash in the signaling, we set up a
ZRTP security association with the a-leg ourselves, if we are so
equipped. Likewise, if the a-leg fails to send a zrtp-hash in the
signaling, we attempt to set up a ZRTP security association ourselves
with the b-leg.
The zrtp-passthru mode can also be enabled in the dialplan by setting
the boolean channel variable zrtp_passthru. If enabled in this
manner, we can't force late-negotiation, so the user would need to be
sure this is configured.
If ZRTP passthrough mode is not enabled in either manner, this change
should have no effect.
Channel variables for each of the various zrtp-hash values are set,
though it is anticipated that there is no good reason to use them, so
they may be removed without warning. For checking whether zrtp
passthrough mode was successful, we provide the channel variable
zrtp_passthru_active which is set on both legs.
Though not implemented by this commit, the changes here should make it
more straightforward to add correct zrtp-hash values to the signaling
and verify that correct hello hash values are received when FreeSWITCH
is acting as a terminating leg of the ZRTP security association.
A historical note...
This commit replaces the recently-added sdp_zrtp_hash_string method,
commit 2ab1605a8887adc62be1b75f6ef67af87ff080de.
This prior method sets a channel variable from the a-leg's zrtp-hash,
then relies on the dialplan to export this channel variable to the
b-leg, where it is put into the SDP.
While it was a great start and wonderful for testing, this approach
has some drawbacks that motivated the present work:
* There's no good way to pass the zrtp-hash from the b-leg back to
the a-leg. In fact, the implementation seems to send the a-leg's
zrtp-hash back to the originating client in the 200 OK. This is
not correct.
* To support video, we'd need to have a separate dialplan variable,
and the dialplan author would need to deal with that explicitly.
* The API is problematic as it requires the dialplan author to
understand intricate details of how ZRTP works to implement a
correct dialplan. Further, by providing too fine-grained control
(but at the same time, not enough control) it would limit our
ability to make the behavior smarter once people started relying on
this.
2012-05-24 20:39:03 +00:00
|
|
|
|
|
|
|
if (switch_channel_test_flag(channel, CF_ZRTP_PASSTHRU_REQ)) {
|
|
|
|
switch_channel_set_flag(peer_channel, CF_ZRTP_PASSTHRU_REQ);
|
|
|
|
}
|
2007-03-29 22:34:40 +00:00
|
|
|
|
|
|
|
if (profile) {
|
|
|
|
if ((cloned_profile = switch_caller_profile_clone(*new_session, profile)) != 0) {
|
|
|
|
switch_channel_set_originator_caller_profile(peer_channel, cloned_profile);
|
|
|
|
}
|
|
|
|
}
|
2010-09-08 18:19:56 +00:00
|
|
|
|
|
|
|
|
|
|
|
if ((profile = switch_channel_get_caller_profile(peer_channel))) {
|
|
|
|
if ((cloned_profile = switch_caller_profile_clone(session, profile)) != 0) {
|
|
|
|
switch_channel_set_origination_caller_profile(channel, cloned_profile);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-10-16 01:51:15 +00:00
|
|
|
}
|
2007-03-29 22:34:40 +00:00
|
|
|
|
2007-10-16 01:51:15 +00:00
|
|
|
if (switch_event_create(&event, SWITCH_EVENT_CHANNEL_OUTGOING) == SWITCH_STATUS_SUCCESS) {
|
|
|
|
switch_channel_event_set_data(peer_channel, event);
|
|
|
|
switch_event_fire(&event);
|
2007-03-29 22:34:40 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-11-19 19:22:20 +00:00
|
|
|
UNPROTECT_INTERFACE(endpoint_interface);
|
2007-03-29 22:34:40 +00:00
|
|
|
return cause;
|
|
|
|
}
|
|
|
|
|
2008-11-05 00:20:30 +00:00
|
|
|
static const char *message_names[] = {
|
2008-12-30 19:50:33 +00:00
|
|
|
"REDIRECT_AUDIO",
|
|
|
|
"TRANSMIT_TEXT",
|
|
|
|
"ANSWER",
|
|
|
|
"PROGRESS",
|
|
|
|
"BRIDGE",
|
|
|
|
"UNBRIDGE",
|
|
|
|
"TRANSFER",
|
|
|
|
"RINGING",
|
|
|
|
"MEDIA",
|
|
|
|
"NOMEDIA",
|
|
|
|
"HOLD",
|
|
|
|
"UNHOLD",
|
|
|
|
"REDIRECT",
|
|
|
|
"RESPOND",
|
|
|
|
"BROADCAST",
|
|
|
|
"MEDIA_REDIRECT",
|
|
|
|
"DEFLECT",
|
|
|
|
"VIDEO_REFRESH_REQ",
|
|
|
|
"DISPLAY",
|
|
|
|
"TRANSCODING_NECESSARY",
|
|
|
|
"AUDIO_SYNC",
|
|
|
|
"REQUEST_IMAGE_MEDIA",
|
2009-10-23 23:47:51 +00:00
|
|
|
"UUID_CHANGE",
|
2010-01-22 20:11:34 +00:00
|
|
|
"SIMPLIFY",
|
2013-04-26 22:47:06 +00:00
|
|
|
"DEBUG_MEDIA",
|
2010-01-21 18:03:54 +00:00
|
|
|
"PROXY_MEDIA",
|
2010-02-06 03:38:24 +00:00
|
|
|
"APPLICATION_EXEC",
|
|
|
|
"APPLICATION_EXEC_COMPLETE",
|
2010-04-16 15:01:00 +00:00
|
|
|
"PHONE_EVENT",
|
2012-01-09 16:03:51 +00:00
|
|
|
"T38_DESCRIPTION",
|
2011-05-30 05:07:32 +00:00
|
|
|
"UDPTL_MODE",
|
|
|
|
"CLEAR_PROGRESS",
|
|
|
|
"JITTER_BUFFER",
|
|
|
|
"RECOVERY_REFRESH",
|
2011-08-30 14:15:22 +00:00
|
|
|
"SIGNAL_DATA",
|
2013-05-18 22:10:44 +00:00
|
|
|
"MESSAGE",
|
2011-12-13 20:16:16 +00:00
|
|
|
"INFO",
|
|
|
|
"AUDIO_DATA",
|
2012-05-08 13:50:33 +00:00
|
|
|
"BLIND_TRANSFER_RESPONSE",
|
2012-06-22 23:08:59 +00:00
|
|
|
"STUN_ERROR",
|
2008-12-30 19:50:33 +00:00
|
|
|
"INVALID"
|
2008-11-05 00:20:30 +00:00
|
|
|
};
|
|
|
|
|
2010-02-06 03:38:24 +00:00
|
|
|
SWITCH_DECLARE(switch_status_t) switch_core_session_perform_receive_message(switch_core_session_t *session,
|
2008-11-05 00:20:30 +00:00
|
|
|
switch_core_session_message_t *message,
|
|
|
|
const char *file, const char *func, int line)
|
2007-03-29 22:34:40 +00:00
|
|
|
{
|
2007-04-16 16:53:30 +00:00
|
|
|
switch_io_event_hook_receive_message_t *ptr;
|
2007-03-29 22:34:40 +00:00
|
|
|
switch_status_t status = SWITCH_STATUS_SUCCESS;
|
|
|
|
|
2007-12-11 19:23:57 +00:00
|
|
|
switch_assert(session != NULL);
|
2007-03-29 22:34:40 +00:00
|
|
|
|
2010-07-14 17:40:08 +00:00
|
|
|
if ((status = switch_core_session_read_lock_hangup(session)) != SWITCH_STATUS_SUCCESS) {
|
2008-02-25 16:35:19 +00:00
|
|
|
return status;
|
|
|
|
}
|
2010-07-14 17:40:08 +00:00
|
|
|
|
2009-10-13 20:28:45 +00:00
|
|
|
if (!message->_file) {
|
|
|
|
message->_file = file;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!message->_func) {
|
|
|
|
message->_func = func;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!message->_line) {
|
|
|
|
message->_line = line;
|
|
|
|
}
|
2008-11-05 00:20:30 +00:00
|
|
|
|
2011-05-30 05:07:32 +00:00
|
|
|
if (message->message_id > SWITCH_MESSAGE_INVALID-1) {
|
|
|
|
message->message_id = SWITCH_MESSAGE_INVALID-1;
|
2008-11-05 00:20:30 +00:00
|
|
|
}
|
|
|
|
|
2010-02-06 03:38:24 +00:00
|
|
|
switch_log_printf(SWITCH_CHANNEL_ID_LOG, message->_file, message->_func, message->_line,
|
|
|
|
switch_core_session_get_uuid(session), SWITCH_LOG_DEBUG1, "%s receive message [%s]\n",
|
2008-11-05 00:20:30 +00:00
|
|
|
switch_channel_get_name(session->channel), message_names[message->message_id]);
|
2009-10-23 22:04:34 +00:00
|
|
|
|
2010-02-06 03:38:24 +00:00
|
|
|
|
2010-06-18 21:52:39 +00:00
|
|
|
if (message->message_id == SWITCH_MESSAGE_INDICATE_CLEAR_PROGRESS) {
|
|
|
|
switch_channel_clear_flag(session->channel, CF_EARLY_MEDIA);
|
|
|
|
}
|
|
|
|
|
2012-04-17 21:13:41 +00:00
|
|
|
if (message->message_id == SWITCH_MESSAGE_INDICATE_DISPLAY) {
|
|
|
|
char *arg = NULL;
|
|
|
|
|
|
|
|
if (zstr(message->string_array_arg[0]) && !zstr(message->string_arg)) {
|
|
|
|
arg = switch_core_session_strdup(session, message->string_arg);
|
|
|
|
switch_separate_string(arg, '|', (char **)message->string_array_arg, 2);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!zstr(message->string_array_arg[0])) {
|
|
|
|
switch_channel_set_variable(session->channel, "last_sent_callee_id_name", message->string_array_arg[0]);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!zstr(message->string_array_arg[1])) {
|
|
|
|
switch_channel_set_variable(session->channel, "last_sent_callee_id_number", message->string_array_arg[1]);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (switch_true(switch_channel_get_variable(session->channel, SWITCH_IGNORE_DISPLAY_UPDATES_VARIABLE))) {
|
|
|
|
switch_log_printf(SWITCH_CHANNEL_ID_LOG, message->_file, message->_func, message->_line,
|
|
|
|
switch_core_session_get_uuid(session), SWITCH_LOG_DEBUG1, "Ignoring display update.\n");
|
|
|
|
status = SWITCH_STATUS_SUCCESS;
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
2009-10-23 22:04:34 +00:00
|
|
|
}
|
2010-02-06 03:38:24 +00:00
|
|
|
|
2011-11-18 19:17:56 +00:00
|
|
|
if (switch_channel_down_nosig(session->channel) && message->message_id != SWITCH_MESSAGE_INDICATE_SIGNAL_DATA) {
|
2011-06-16 19:37:22 +00:00
|
|
|
switch_log_printf(SWITCH_CHANNEL_ID_LOG, message->_file, message->_func, message->_line,
|
|
|
|
switch_core_session_get_uuid(session), SWITCH_LOG_DEBUG, "%s skip receive message [%s] (channel is hungup already)\n",
|
|
|
|
switch_channel_get_name(session->channel), message_names[message->message_id]);
|
2010-07-14 17:40:08 +00:00
|
|
|
|
2012-12-22 17:51:03 +00:00
|
|
|
} else {
|
|
|
|
if (session->media_handle) {
|
|
|
|
status = switch_core_media_receive_message(session, message);
|
|
|
|
}
|
2013-05-03 16:03:17 +00:00
|
|
|
if (status == SWITCH_STATUS_SUCCESS || message->message_id == SWITCH_MESSAGE_INDICATE_SIGNAL_DATA) {
|
2012-12-22 17:51:03 +00:00
|
|
|
if (session->endpoint_interface->io_routines->receive_message) {
|
|
|
|
status = session->endpoint_interface->io_routines->receive_message(session, message);
|
|
|
|
}
|
|
|
|
}
|
2007-03-29 22:34:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (status == SWITCH_STATUS_SUCCESS) {
|
2007-04-16 16:53:30 +00:00
|
|
|
for (ptr = session->event_hooks.receive_message; ptr; ptr = ptr->next) {
|
|
|
|
if ((status = ptr->receive_message(session, message)) != SWITCH_STATUS_SUCCESS) {
|
2007-03-29 22:34:40 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2012-05-08 13:50:33 +00:00
|
|
|
|
|
|
|
|
|
|
|
if (message->message_id == SWITCH_MESSAGE_INDICATE_BRIDGE &&
|
|
|
|
switch_channel_test_flag(session->channel, CF_CONFIRM_BLIND_TRANSFER)) {
|
|
|
|
switch_core_session_t *other_session;
|
|
|
|
const char *uuid = switch_channel_get_variable(session->channel, "blind_transfer_uuid");
|
|
|
|
|
|
|
|
switch_channel_clear_flag(session->channel, CF_CONFIRM_BLIND_TRANSFER);
|
|
|
|
|
|
|
|
if (!zstr(uuid) && (other_session = switch_core_session_locate(uuid))) {
|
|
|
|
switch_core_session_message_t msg = { 0 };
|
|
|
|
msg.message_id = SWITCH_MESSAGE_INDICATE_BLIND_TRANSFER_RESPONSE;
|
|
|
|
msg.from = __FILE__;
|
|
|
|
msg.numeric_arg = 1;
|
|
|
|
switch_core_session_receive_message(other_session, &msg);
|
|
|
|
switch_core_session_rwunlock(other_session);
|
|
|
|
}
|
|
|
|
}
|
2007-03-29 22:34:40 +00:00
|
|
|
}
|
|
|
|
|
2012-04-23 18:25:21 +00:00
|
|
|
|
2008-11-05 00:20:30 +00:00
|
|
|
message->_file = NULL;
|
|
|
|
message->_func = NULL;
|
|
|
|
message->_line = 0;
|
2010-02-06 03:38:24 +00:00
|
|
|
|
2011-11-18 19:17:56 +00:00
|
|
|
if (switch_channel_up_nosig(session->channel)) {
|
2012-04-23 18:25:21 +00:00
|
|
|
if (message->message_id == SWITCH_MESSAGE_INDICATE_BRIDGE || message->message_id == SWITCH_MESSAGE_INDICATE_UNBRIDGE) {
|
|
|
|
switch_core_media_bug_flush_all(session);
|
2012-10-12 17:23:56 +00:00
|
|
|
switch_core_recovery_track(session);
|
2012-04-23 18:25:21 +00:00
|
|
|
}
|
|
|
|
|
2010-07-14 17:40:08 +00:00
|
|
|
switch (message->message_id) {
|
|
|
|
case SWITCH_MESSAGE_REDIRECT_AUDIO:
|
|
|
|
case SWITCH_MESSAGE_INDICATE_ANSWER:
|
|
|
|
case SWITCH_MESSAGE_INDICATE_PROGRESS:
|
|
|
|
case SWITCH_MESSAGE_INDICATE_BRIDGE:
|
|
|
|
case SWITCH_MESSAGE_INDICATE_UNBRIDGE:
|
|
|
|
case SWITCH_MESSAGE_INDICATE_TRANSFER:
|
|
|
|
case SWITCH_MESSAGE_INDICATE_RINGING:
|
|
|
|
case SWITCH_MESSAGE_INDICATE_MEDIA:
|
|
|
|
case SWITCH_MESSAGE_INDICATE_NOMEDIA:
|
|
|
|
case SWITCH_MESSAGE_INDICATE_HOLD:
|
|
|
|
case SWITCH_MESSAGE_INDICATE_UNHOLD:
|
|
|
|
case SWITCH_MESSAGE_INDICATE_REDIRECT:
|
|
|
|
case SWITCH_MESSAGE_INDICATE_RESPOND:
|
|
|
|
case SWITCH_MESSAGE_INDICATE_BROADCAST:
|
|
|
|
case SWITCH_MESSAGE_INDICATE_MEDIA_REDIRECT:
|
|
|
|
case SWITCH_MESSAGE_INDICATE_DEFLECT:
|
|
|
|
switch_core_session_kill_channel(session, SWITCH_SIG_BREAK);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
2008-11-19 22:27:17 +00:00
|
|
|
}
|
|
|
|
|
2010-02-06 03:38:24 +00:00
|
|
|
end:
|
2009-10-28 20:48:56 +00:00
|
|
|
|
2009-10-12 22:23:55 +00:00
|
|
|
switch_core_session_free_message(&message);
|
2008-02-25 16:35:19 +00:00
|
|
|
switch_core_session_rwunlock(session);
|
|
|
|
|
2007-03-29 22:34:40 +00:00
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
2007-04-16 16:53:30 +00:00
|
|
|
SWITCH_DECLARE(switch_status_t) switch_core_session_pass_indication(switch_core_session_t *session, switch_core_session_message_types_t indication)
|
2007-03-29 22:34:40 +00:00
|
|
|
{
|
2008-05-27 04:30:03 +00:00
|
|
|
switch_core_session_message_t msg = { 0 };
|
2007-04-16 16:53:30 +00:00
|
|
|
switch_core_session_t *other_session;
|
2007-11-01 11:28:26 +00:00
|
|
|
const char *uuid;
|
2008-01-28 07:26:10 +00:00
|
|
|
switch_channel_t *channel = switch_core_session_get_channel(session);
|
2007-03-29 22:34:40 +00:00
|
|
|
switch_status_t status = SWITCH_STATUS_SUCCESS;
|
|
|
|
|
2012-05-29 18:10:15 +00:00
|
|
|
if (((uuid = switch_channel_get_partner_uuid(channel))) && (other_session = switch_core_session_locate(uuid))) {
|
2007-04-16 16:53:30 +00:00
|
|
|
msg.message_id = indication;
|
|
|
|
msg.from = __FILE__;
|
|
|
|
status = switch_core_session_receive_message(other_session, &msg);
|
|
|
|
switch_core_session_rwunlock(other_session);
|
|
|
|
} else {
|
|
|
|
status = SWITCH_STATUS_FALSE;
|
2007-03-29 22:34:40 +00:00
|
|
|
}
|
2008-05-27 04:30:03 +00:00
|
|
|
|
2007-03-29 22:34:40 +00:00
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
2007-03-30 00:13:31 +00:00
|
|
|
SWITCH_DECLARE(switch_status_t) switch_core_session_queue_indication(switch_core_session_t *session, switch_core_session_message_types_t indication)
|
2007-03-29 22:34:40 +00:00
|
|
|
{
|
|
|
|
switch_core_session_message_t *msg;
|
|
|
|
|
|
|
|
if ((msg = malloc(sizeof(*msg)))) {
|
|
|
|
memset(msg, 0, sizeof(*msg));
|
|
|
|
msg->message_id = indication;
|
|
|
|
msg->from = __FILE__;
|
|
|
|
switch_set_flag(msg, SCSMF_DYNAMIC);
|
2007-04-16 16:53:30 +00:00
|
|
|
switch_core_session_queue_message(session, msg);
|
2007-03-29 22:34:40 +00:00
|
|
|
return SWITCH_STATUS_SUCCESS;
|
|
|
|
}
|
2008-05-27 04:30:03 +00:00
|
|
|
|
2007-03-29 22:34:40 +00:00
|
|
|
return SWITCH_STATUS_FALSE;
|
|
|
|
}
|
|
|
|
|
2007-03-30 00:13:31 +00:00
|
|
|
SWITCH_DECLARE(switch_status_t) switch_core_session_queue_message(switch_core_session_t *session, switch_core_session_message_t *message)
|
2007-03-29 22:34:40 +00:00
|
|
|
{
|
|
|
|
switch_status_t status = SWITCH_STATUS_FALSE;
|
|
|
|
|
2007-12-11 19:23:57 +00:00
|
|
|
switch_assert(session != NULL);
|
2007-03-29 22:34:40 +00:00
|
|
|
|
|
|
|
if (session->message_queue) {
|
|
|
|
if (switch_queue_trypush(session->message_queue, message) == SWITCH_STATUS_SUCCESS) {
|
|
|
|
status = SWITCH_STATUS_SUCCESS;
|
|
|
|
}
|
2009-10-12 22:23:55 +00:00
|
|
|
|
2009-10-20 17:03:03 +00:00
|
|
|
switch_core_session_kill_channel(session, SWITCH_SIG_BREAK);
|
|
|
|
|
2012-11-27 00:09:04 +00:00
|
|
|
switch_core_session_wake_session_thread(session);
|
|
|
|
|
2007-03-29 22:34:40 +00:00
|
|
|
}
|
2008-05-27 04:30:03 +00:00
|
|
|
|
2007-03-29 22:34:40 +00:00
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
2009-10-12 22:23:55 +00:00
|
|
|
SWITCH_DECLARE(void) switch_core_session_free_message(switch_core_session_message_t **message)
|
|
|
|
{
|
|
|
|
switch_core_session_message_t *to_free = *message;
|
|
|
|
int i;
|
|
|
|
char *s;
|
|
|
|
|
|
|
|
*message = NULL;
|
|
|
|
|
|
|
|
if (switch_test_flag(to_free, SCSMF_DYNAMIC)) {
|
2010-02-06 03:38:24 +00:00
|
|
|
s = (char *) to_free->string_arg;
|
2009-10-12 22:23:55 +00:00
|
|
|
switch_safe_free(s);
|
|
|
|
switch_safe_free(to_free->pointer_arg);
|
2010-02-06 03:38:24 +00:00
|
|
|
|
2009-10-12 22:23:55 +00:00
|
|
|
for (i = 0; i < MESSAGE_STRING_ARG_MAX; i++) {
|
2010-02-06 03:38:24 +00:00
|
|
|
s = (char *) to_free->string_array_arg[i];
|
2009-10-12 22:23:55 +00:00
|
|
|
switch_safe_free(s);
|
|
|
|
}
|
|
|
|
|
|
|
|
switch_safe_free(to_free);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-03-30 00:13:31 +00:00
|
|
|
SWITCH_DECLARE(switch_status_t) switch_core_session_dequeue_message(switch_core_session_t *session, switch_core_session_message_t **message)
|
2007-03-29 22:34:40 +00:00
|
|
|
{
|
|
|
|
switch_status_t status = SWITCH_STATUS_FALSE;
|
|
|
|
void *pop;
|
|
|
|
|
2007-12-11 19:23:57 +00:00
|
|
|
switch_assert(session != NULL);
|
2007-03-29 22:34:40 +00:00
|
|
|
|
2013-02-22 23:46:54 +00:00
|
|
|
if (session->message_queue) {
|
2007-03-29 22:34:40 +00:00
|
|
|
if ((status = (switch_status_t) switch_queue_trypop(session->message_queue, &pop)) == SWITCH_STATUS_SUCCESS) {
|
|
|
|
*message = (switch_core_session_message_t *) pop;
|
2009-10-21 18:48:28 +00:00
|
|
|
if ((*message)->delivery_time && (*message)->delivery_time > switch_epoch_time_now(NULL)) {
|
|
|
|
switch_core_session_queue_message(session, *message);
|
|
|
|
*message = NULL;
|
|
|
|
status = SWITCH_STATUS_FALSE;
|
|
|
|
}
|
2007-03-29 22:34:40 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
|
|
|
SWITCH_DECLARE(switch_status_t) switch_core_session_flush_message(switch_core_session_t *session)
|
|
|
|
{
|
2010-11-08 21:04:51 +00:00
|
|
|
switch_status_t status = SWITCH_STATUS_FALSE;
|
|
|
|
void *pop;
|
2007-03-29 22:34:40 +00:00
|
|
|
switch_core_session_message_t *message;
|
|
|
|
|
2010-11-08 21:04:51 +00:00
|
|
|
switch_assert(session != NULL);
|
|
|
|
|
2011-08-19 21:25:26 +00:00
|
|
|
|
2010-11-08 21:04:51 +00:00
|
|
|
if (session->message_queue) {
|
|
|
|
while ((status = (switch_status_t) switch_queue_trypop(session->message_queue, &pop)) == SWITCH_STATUS_SUCCESS) {
|
|
|
|
message = (switch_core_session_message_t *) pop;
|
2011-08-19 21:25:26 +00:00
|
|
|
switch_ivr_process_indications(session, message);
|
2010-11-08 21:04:51 +00:00
|
|
|
switch_core_session_free_message(&message);
|
|
|
|
}
|
2007-03-29 22:34:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return SWITCH_STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2011-07-08 17:52:12 +00:00
|
|
|
SWITCH_DECLARE(switch_status_t) switch_core_session_queue_signal_data(switch_core_session_t *session, void *signal_data)
|
|
|
|
{
|
|
|
|
switch_status_t status = SWITCH_STATUS_FALSE;
|
|
|
|
|
|
|
|
switch_assert(session != NULL);
|
|
|
|
|
|
|
|
if (session->signal_data_queue) {
|
2013-02-22 23:46:54 +00:00
|
|
|
if (switch_queue_push(session->signal_data_queue, signal_data) == SWITCH_STATUS_SUCCESS) {
|
2011-07-08 17:52:12 +00:00
|
|
|
status = SWITCH_STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch_core_session_kill_channel(session, SWITCH_SIG_BREAK);
|
|
|
|
|
2012-11-27 00:09:04 +00:00
|
|
|
switch_core_session_wake_session_thread(session);
|
|
|
|
|
2011-07-08 17:52:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
|
|
|
SWITCH_DECLARE(switch_status_t) switch_core_session_dequeue_signal_data(switch_core_session_t *session, void **signal_data)
|
|
|
|
{
|
|
|
|
switch_status_t status = SWITCH_STATUS_FALSE;
|
|
|
|
void *pop;
|
|
|
|
|
|
|
|
switch_assert(session != NULL);
|
|
|
|
|
2013-02-22 23:46:54 +00:00
|
|
|
if (session->signal_data_queue) {
|
2011-07-08 17:52:12 +00:00
|
|
|
if ((status = (switch_status_t) switch_queue_trypop(session->signal_data_queue, &pop)) == SWITCH_STATUS_SUCCESS) {
|
|
|
|
*signal_data = pop;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return status;
|
|
|
|
}
|
2007-03-29 22:34:40 +00:00
|
|
|
|
2007-03-30 00:13:31 +00:00
|
|
|
SWITCH_DECLARE(switch_status_t) switch_core_session_receive_event(switch_core_session_t *session, switch_event_t **event)
|
2007-03-29 22:34:40 +00:00
|
|
|
{
|
|
|
|
switch_io_event_hook_receive_event_t *ptr;
|
|
|
|
switch_status_t status = SWITCH_STATUS_FALSE;
|
|
|
|
|
2007-12-11 19:23:57 +00:00
|
|
|
switch_assert(session != NULL);
|
2007-03-29 22:34:40 +00:00
|
|
|
|
|
|
|
/* Acquire a read lock on the session or forget it the channel is dead */
|
|
|
|
if (switch_core_session_read_lock(session) == SWITCH_STATUS_SUCCESS) {
|
2011-11-18 19:17:56 +00:00
|
|
|
if (switch_channel_up_nosig(session->channel)) {
|
2007-03-29 22:34:40 +00:00
|
|
|
if (session->endpoint_interface->io_routines->receive_event) {
|
|
|
|
status = session->endpoint_interface->io_routines->receive_event(session, *event);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (status == SWITCH_STATUS_SUCCESS) {
|
|
|
|
for (ptr = session->event_hooks.receive_event; ptr; ptr = ptr->next) {
|
|
|
|
if ((status = ptr->receive_event(session, *event)) != SWITCH_STATUS_SUCCESS) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (status == SWITCH_STATUS_BREAK) {
|
|
|
|
status = SWITCH_STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (status == SWITCH_STATUS_SUCCESS) {
|
|
|
|
switch_event_destroy(event);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
switch_core_session_rwunlock(session);
|
|
|
|
}
|
|
|
|
|
|
|
|
switch_core_session_kill_channel(session, SWITCH_SIG_BREAK);
|
|
|
|
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
|
|
|
SWITCH_DECLARE(switch_status_t) switch_core_session_queue_event(switch_core_session_t *session, switch_event_t **event)
|
|
|
|
{
|
|
|
|
switch_status_t status = SWITCH_STATUS_FALSE;
|
|
|
|
|
2007-12-11 19:23:57 +00:00
|
|
|
switch_assert(session != NULL);
|
2007-03-29 22:34:40 +00:00
|
|
|
|
|
|
|
if (session->event_queue) {
|
|
|
|
if (switch_queue_trypush(session->event_queue, *event) == SWITCH_STATUS_SUCCESS) {
|
|
|
|
*event = NULL;
|
|
|
|
status = SWITCH_STATUS_SUCCESS;
|
2010-11-30 17:01:54 +00:00
|
|
|
|
2012-11-27 00:09:04 +00:00
|
|
|
switch_core_session_wake_session_thread(session);
|
2007-03-29 22:34:40 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
2010-11-30 15:49:12 +00:00
|
|
|
SWITCH_DECLARE(uint32_t) switch_core_session_messages_waiting(switch_core_session_t *session)
|
|
|
|
{
|
|
|
|
int x = 0;
|
|
|
|
|
|
|
|
if (session->private_event_queue) {
|
|
|
|
x += switch_queue_size(session->private_event_queue);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (session->message_queue) {
|
|
|
|
x += switch_queue_size(session->message_queue);
|
|
|
|
}
|
|
|
|
|
|
|
|
return x;
|
|
|
|
}
|
|
|
|
|
2007-05-15 00:05:32 +00:00
|
|
|
SWITCH_DECLARE(uint32_t) switch_core_session_event_count(switch_core_session_t *session)
|
2007-03-29 22:34:40 +00:00
|
|
|
{
|
|
|
|
if (session->event_queue) {
|
2007-05-15 00:05:32 +00:00
|
|
|
return switch_queue_size(session->event_queue);
|
2007-03-29 22:34:40 +00:00
|
|
|
}
|
|
|
|
|
2007-05-15 00:05:32 +00:00
|
|
|
return 0;
|
2007-03-29 22:34:40 +00:00
|
|
|
}
|
|
|
|
|
2009-02-21 23:19:58 +00:00
|
|
|
SWITCH_DECLARE(switch_status_t) switch_core_session_dequeue_event(switch_core_session_t *session, switch_event_t **event, switch_bool_t force)
|
2007-03-29 22:34:40 +00:00
|
|
|
{
|
|
|
|
switch_status_t status = SWITCH_STATUS_FALSE;
|
|
|
|
void *pop;
|
|
|
|
|
2007-12-11 19:23:57 +00:00
|
|
|
switch_assert(session != NULL);
|
2007-03-29 22:34:40 +00:00
|
|
|
|
2009-02-21 23:19:58 +00:00
|
|
|
if (session->event_queue && (force || !switch_channel_test_flag(session->channel, CF_DIVERT_EVENTS))) {
|
2007-03-29 22:34:40 +00:00
|
|
|
if ((status = (switch_status_t) switch_queue_trypop(session->event_queue, &pop)) == SWITCH_STATUS_SUCCESS) {
|
|
|
|
*event = (switch_event_t *) pop;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
2009-12-10 01:29:02 +00:00
|
|
|
SWITCH_DECLARE(switch_status_t) switch_core_session_queue_private_event(switch_core_session_t *session, switch_event_t **event, switch_bool_t priority)
|
2007-03-29 22:34:40 +00:00
|
|
|
{
|
|
|
|
switch_status_t status = SWITCH_STATUS_FALSE;
|
2009-12-10 01:29:02 +00:00
|
|
|
switch_queue_t *queue;
|
2007-03-29 22:34:40 +00:00
|
|
|
|
2007-12-11 19:23:57 +00:00
|
|
|
switch_assert(session != NULL);
|
2012-10-09 16:47:33 +00:00
|
|
|
switch_assert(event != NULL);
|
2007-03-29 22:34:40 +00:00
|
|
|
|
|
|
|
if (session->private_event_queue) {
|
2009-12-10 01:29:02 +00:00
|
|
|
queue = priority ? session->private_event_queue_pri : session->private_event_queue;
|
2010-02-06 03:38:24 +00:00
|
|
|
|
2007-03-29 22:34:40 +00:00
|
|
|
(*event)->event_id = SWITCH_EVENT_PRIVATE_COMMAND;
|
2009-12-10 01:29:02 +00:00
|
|
|
if (switch_queue_trypush(queue, *event) == SWITCH_STATUS_SUCCESS) {
|
2007-03-29 22:34:40 +00:00
|
|
|
*event = NULL;
|
|
|
|
switch_core_session_kill_channel(session, SWITCH_SIG_BREAK);
|
|
|
|
status = SWITCH_STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
2009-12-02 18:13:11 +00:00
|
|
|
#define check_media(session) \
|
|
|
|
{ \
|
|
|
|
if (switch_channel_test_flag(session->channel, CF_BROADCAST_DROP_MEDIA)) { \
|
|
|
|
switch_channel_clear_flag(session->channel, CF_BROADCAST_DROP_MEDIA); \
|
|
|
|
switch_ivr_nomedia(session->uuid_str, SMF_REBRIDGE); \
|
|
|
|
} \
|
|
|
|
} \
|
2010-02-06 03:38:24 +00:00
|
|
|
|
2007-05-15 00:05:32 +00:00
|
|
|
SWITCH_DECLARE(uint32_t) switch_core_session_private_event_count(switch_core_session_t *session)
|
2007-03-29 22:34:40 +00:00
|
|
|
{
|
2008-05-16 13:16:27 +00:00
|
|
|
switch_channel_t *channel = switch_core_session_get_channel(session);
|
2009-12-02 18:13:11 +00:00
|
|
|
uint32_t count = 0;
|
2010-02-06 03:38:24 +00:00
|
|
|
|
2009-12-10 01:29:02 +00:00
|
|
|
if (session->private_event_queue) {
|
|
|
|
|
|
|
|
if (!switch_channel_test_flag(channel, CF_EVENT_LOCK)) {
|
|
|
|
count = switch_queue_size(session->private_event_queue);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!switch_channel_test_flag(channel, CF_EVENT_LOCK_PRI)) {
|
|
|
|
count += switch_queue_size(session->private_event_queue_pri);
|
|
|
|
}
|
|
|
|
|
2009-12-02 18:13:11 +00:00
|
|
|
if (count == 0) {
|
|
|
|
check_media(session);
|
|
|
|
}
|
2007-03-29 22:34:40 +00:00
|
|
|
}
|
2008-05-27 04:30:03 +00:00
|
|
|
|
2009-12-02 18:13:11 +00:00
|
|
|
return count;
|
2007-03-29 22:34:40 +00:00
|
|
|
}
|
|
|
|
|
2007-03-30 00:13:31 +00:00
|
|
|
SWITCH_DECLARE(switch_status_t) switch_core_session_dequeue_private_event(switch_core_session_t *session, switch_event_t **event)
|
2007-03-29 22:34:40 +00:00
|
|
|
{
|
|
|
|
switch_status_t status = SWITCH_STATUS_FALSE;
|
|
|
|
void *pop;
|
2008-01-28 07:26:10 +00:00
|
|
|
switch_channel_t *channel = switch_core_session_get_channel(session);
|
2009-12-10 01:29:02 +00:00
|
|
|
switch_queue_t *queue;
|
2010-02-06 03:38:24 +00:00
|
|
|
|
2009-12-10 01:29:02 +00:00
|
|
|
if (session->private_event_queue) {
|
|
|
|
if (switch_queue_size(session->private_event_queue_pri)) {
|
|
|
|
queue = session->private_event_queue_pri;
|
2007-03-29 22:34:40 +00:00
|
|
|
|
2009-12-10 01:29:02 +00:00
|
|
|
if (switch_channel_test_flag(channel, CF_EVENT_LOCK_PRI)) {
|
|
|
|
return SWITCH_STATUS_FALSE;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
queue = session->private_event_queue;
|
2010-02-06 03:38:24 +00:00
|
|
|
|
2009-12-10 01:29:02 +00:00
|
|
|
if (switch_channel_test_flag(channel, CF_EVENT_LOCK)) {
|
|
|
|
return SWITCH_STATUS_FALSE;
|
|
|
|
}
|
|
|
|
}
|
2007-03-29 22:34:40 +00:00
|
|
|
|
2009-12-10 01:29:02 +00:00
|
|
|
if ((status = (switch_status_t) switch_queue_trypop(queue, &pop)) == SWITCH_STATUS_SUCCESS) {
|
2007-03-29 22:34:40 +00:00
|
|
|
*event = (switch_event_t *) pop;
|
2009-12-02 18:13:11 +00:00
|
|
|
} else {
|
|
|
|
check_media(session);
|
2007-03-29 22:34:40 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
2008-02-15 16:01:12 +00:00
|
|
|
SWITCH_DECLARE(uint32_t) switch_core_session_flush_private_events(switch_core_session_t *session)
|
|
|
|
{
|
|
|
|
switch_status_t status = SWITCH_STATUS_FALSE;
|
|
|
|
int x = 0;
|
|
|
|
void *pop;
|
|
|
|
|
|
|
|
if (session->private_event_queue) {
|
2009-12-10 01:29:02 +00:00
|
|
|
while ((status = (switch_status_t) switch_queue_trypop(session->private_event_queue_pri, &pop)) == SWITCH_STATUS_SUCCESS) {
|
2012-12-23 04:29:33 +00:00
|
|
|
if (pop) {
|
|
|
|
switch_event_t *event = (switch_event_t *) pop;
|
|
|
|
switch_event_destroy(&event);
|
|
|
|
}
|
2009-12-10 01:29:02 +00:00
|
|
|
x++;
|
|
|
|
}
|
2008-02-15 16:01:12 +00:00
|
|
|
while ((status = (switch_status_t) switch_queue_trypop(session->private_event_queue, &pop)) == SWITCH_STATUS_SUCCESS) {
|
2012-12-23 04:29:33 +00:00
|
|
|
if (pop) {
|
|
|
|
switch_event_t *event = (switch_event_t *) pop;
|
|
|
|
switch_event_destroy(&event);
|
|
|
|
}
|
2008-02-15 16:01:12 +00:00
|
|
|
x++;
|
|
|
|
}
|
2009-12-02 18:13:11 +00:00
|
|
|
check_media(session);
|
2008-02-15 16:01:12 +00:00
|
|
|
}
|
2008-05-27 04:30:03 +00:00
|
|
|
|
2008-02-15 16:01:12 +00:00
|
|
|
return x;
|
|
|
|
}
|
|
|
|
|
2009-01-09 20:34:01 +00:00
|
|
|
SWITCH_DECLARE(void) switch_core_session_reset(switch_core_session_t *session, switch_bool_t flush_dtmf, switch_bool_t reset_read_codec)
|
2007-03-29 22:34:40 +00:00
|
|
|
{
|
2008-01-28 07:26:10 +00:00
|
|
|
switch_channel_t *channel = switch_core_session_get_channel(session);
|
2007-03-29 22:34:40 +00:00
|
|
|
switch_size_t has;
|
|
|
|
|
2009-01-09 20:34:01 +00:00
|
|
|
if (reset_read_codec) {
|
|
|
|
switch_core_session_set_read_codec(session, NULL);
|
|
|
|
}
|
2008-10-29 00:04:20 +00:00
|
|
|
|
2008-05-27 04:30:03 +00:00
|
|
|
/* clear resamplers */
|
2008-07-14 22:15:24 +00:00
|
|
|
switch_mutex_lock(session->resample_mutex);
|
2007-12-12 21:30:55 +00:00
|
|
|
switch_resample_destroy(&session->read_resampler);
|
|
|
|
switch_resample_destroy(&session->write_resampler);
|
2008-07-14 22:15:24 +00:00
|
|
|
switch_mutex_unlock(session->resample_mutex);
|
2007-03-29 22:34:40 +00:00
|
|
|
/* clear indications */
|
|
|
|
switch_core_session_flush_message(session);
|
2009-05-01 21:31:16 +00:00
|
|
|
|
2008-10-06 23:05:55 +00:00
|
|
|
/* wipe these, they will be recreated if need be */
|
2009-05-01 21:31:16 +00:00
|
|
|
switch_mutex_lock(session->codec_write_mutex);
|
2007-03-29 22:34:40 +00:00
|
|
|
switch_buffer_destroy(&session->raw_write_buffer);
|
2009-05-01 21:31:16 +00:00
|
|
|
switch_mutex_unlock(session->codec_write_mutex);
|
|
|
|
|
|
|
|
switch_mutex_lock(session->codec_read_mutex);
|
|
|
|
switch_buffer_destroy(&session->raw_read_buffer);
|
|
|
|
switch_mutex_unlock(session->codec_read_mutex);
|
2008-05-27 04:30:03 +00:00
|
|
|
|
2008-01-13 18:39:51 +00:00
|
|
|
if (flush_dtmf) {
|
|
|
|
while ((has = switch_channel_has_dtmf(channel))) {
|
|
|
|
switch_channel_flush_dtmf(channel);
|
|
|
|
}
|
2007-03-29 22:34:40 +00:00
|
|
|
}
|
|
|
|
|
2008-05-13 20:36:23 +00:00
|
|
|
switch_clear_flag(session, SSF_WARN_TRANSCODE);
|
2007-04-09 18:38:47 +00:00
|
|
|
switch_ivr_deactivate_unicast(session);
|
2007-03-30 22:13:19 +00:00
|
|
|
switch_channel_clear_flag(channel, CF_BREAK);
|
2007-03-29 22:34:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
SWITCH_DECLARE(switch_channel_t *) switch_core_session_get_channel(switch_core_session_t *session)
|
|
|
|
{
|
2008-01-28 07:26:10 +00:00
|
|
|
switch_assert(session->channel);
|
2007-03-29 22:34:40 +00:00
|
|
|
return session->channel;
|
|
|
|
}
|
|
|
|
|
2012-11-15 19:16:50 +00:00
|
|
|
SWITCH_DECLARE(switch_mutex_t *) switch_core_session_get_mutex(switch_core_session_t *session)
|
|
|
|
{
|
|
|
|
return session->mutex;
|
|
|
|
}
|
|
|
|
|
2011-08-19 21:25:26 +00:00
|
|
|
SWITCH_DECLARE(switch_status_t) switch_core_session_wake_session_thread(switch_core_session_t *session)
|
2007-03-29 22:34:40 +00:00
|
|
|
{
|
2011-08-19 21:25:26 +00:00
|
|
|
switch_status_t status;
|
2013-02-22 23:46:54 +00:00
|
|
|
int tries = 0;
|
2011-08-19 21:25:26 +00:00
|
|
|
|
2013-02-22 23:46:54 +00:00
|
|
|
/* If trylock fails the signal is already awake so we needn't bother ..... or do we????*/
|
2010-02-06 03:38:24 +00:00
|
|
|
|
2013-02-22 23:46:54 +00:00
|
|
|
top:
|
2011-08-19 21:25:26 +00:00
|
|
|
|
2013-02-22 23:46:54 +00:00
|
|
|
status = switch_mutex_trylock(session->mutex);
|
|
|
|
|
2011-08-19 21:25:26 +00:00
|
|
|
if (status == SWITCH_STATUS_SUCCESS) {
|
2010-02-06 03:38:24 +00:00
|
|
|
switch_thread_cond_signal(session->cond);
|
|
|
|
switch_mutex_unlock(session->mutex);
|
2013-02-22 23:46:54 +00:00
|
|
|
} else {
|
|
|
|
if (switch_channel_state_thread_trylock(session->channel) == SWITCH_STATUS_SUCCESS) {
|
|
|
|
/* We've beat them for sure, as soon as we release this lock, they will be checking their queue on the next line. */
|
|
|
|
switch_channel_state_thread_unlock(session->channel);
|
|
|
|
} else {
|
|
|
|
/* What luck! The channel has already started going to sleep *after* we checked if we need to wake it up.
|
|
|
|
It will miss any messages in its queue because they were inserted after *it* checked its queue. (catch-22)
|
|
|
|
So, it's not asleep yet, but it's too late for us to be sure they know we want them to stay awake and check its queue again.
|
|
|
|
Now *we* need to sleep instead but just for 1ms so we can circle back and try again.
|
|
|
|
This is so rare (yet possible) to happen that we can be fairly certian it will not happen 2x in a row but we'll try 10x just in case.
|
|
|
|
*/
|
|
|
|
if (++tries < 10) {
|
|
|
|
switch_cond_next();
|
|
|
|
goto top;
|
|
|
|
}
|
|
|
|
}
|
2007-03-29 22:34:40 +00:00
|
|
|
}
|
2011-08-19 21:25:26 +00:00
|
|
|
|
|
|
|
return status;
|
2009-10-12 22:23:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
SWITCH_DECLARE(void) switch_core_session_signal_state_change(switch_core_session_t *session)
|
|
|
|
{
|
|
|
|
switch_status_t status = SWITCH_STATUS_SUCCESS;
|
|
|
|
switch_io_event_hook_state_change_t *ptr;
|
|
|
|
|
|
|
|
switch_core_session_wake_session_thread(session);
|
2007-03-29 22:34:40 +00:00
|
|
|
|
|
|
|
if (session->endpoint_interface->io_routines->state_change) {
|
|
|
|
status = session->endpoint_interface->io_routines->state_change(session);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (status == SWITCH_STATUS_SUCCESS) {
|
|
|
|
for (ptr = session->event_hooks.state_change; ptr; ptr = ptr->next) {
|
|
|
|
if ((status = ptr->state_change(session)) != SWITCH_STATUS_SUCCESS) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2007-05-16 17:35:00 +00:00
|
|
|
switch_core_session_kill_channel(session, SWITCH_SIG_BREAK);
|
2007-03-29 22:34:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
SWITCH_DECLARE(unsigned int) switch_core_session_running(switch_core_session_t *session)
|
|
|
|
{
|
2010-05-03 17:29:56 +00:00
|
|
|
return switch_test_flag(session, SSF_THREAD_RUNNING) ? 1 : 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
SWITCH_DECLARE(unsigned int) switch_core_session_started(switch_core_session_t *session)
|
|
|
|
{
|
|
|
|
return switch_test_flag(session, SSF_THREAD_STARTED) ? 1 : 0;
|
2007-03-29 22:34:40 +00:00
|
|
|
}
|
|
|
|
|
2011-10-12 19:55:32 +00:00
|
|
|
SWITCH_DECLARE(int) switch_core_session_sync_clock(void)
|
|
|
|
{
|
|
|
|
int doit = 0;
|
|
|
|
|
|
|
|
switch_mutex_lock(runtime.session_hash_mutex);
|
|
|
|
if (session_manager.session_count == 0) {
|
|
|
|
doit = 1;
|
|
|
|
} else {
|
|
|
|
switch_set_flag((&runtime), SCF_SYNC_CLOCK_REQUESTED);
|
|
|
|
}
|
|
|
|
switch_mutex_unlock(runtime.session_hash_mutex);
|
|
|
|
|
|
|
|
if (doit) {
|
|
|
|
switch_time_sync();
|
|
|
|
}
|
|
|
|
|
|
|
|
return doit;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2007-05-11 00:27:55 +00:00
|
|
|
SWITCH_DECLARE(void) switch_core_session_perform_destroy(switch_core_session_t **session, const char *file, const char *func, int line)
|
2007-03-29 22:34:40 +00:00
|
|
|
{
|
|
|
|
switch_memory_pool_t *pool;
|
|
|
|
switch_event_t *event;
|
2008-11-13 17:40:25 +00:00
|
|
|
switch_endpoint_interface_t *endpoint_interface = (*session)->endpoint_interface;
|
2011-09-02 14:34:40 +00:00
|
|
|
int i;
|
2007-03-29 22:34:40 +00:00
|
|
|
|
2012-12-23 04:29:33 +00:00
|
|
|
|
|
|
|
switch_core_session_flush_private_events(*session);
|
|
|
|
|
2012-08-16 17:09:19 +00:00
|
|
|
if (switch_core_session_running(*session) && !switch_test_flag((*session), SSF_DESTROYABLE)) {
|
|
|
|
switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, func, line, switch_core_session_get_uuid(*session), SWITCH_LOG_ERROR,
|
|
|
|
"Cowardly ignoring an attempt to call destroy on a running session.\n");
|
|
|
|
}
|
|
|
|
|
2009-08-13 20:35:02 +00:00
|
|
|
switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, func, line, switch_core_session_get_uuid(*session), SWITCH_LOG_NOTICE, "Close Channel %s [%s]\n",
|
2008-05-27 04:30:03 +00:00
|
|
|
switch_channel_get_name((*session)->channel), switch_channel_state_name(switch_channel_get_state((*session)->channel)));
|
2008-01-21 17:14:43 +00:00
|
|
|
|
2008-07-14 22:15:24 +00:00
|
|
|
|
2009-01-09 20:34:01 +00:00
|
|
|
switch_core_session_reset(*session, TRUE, SWITCH_TRUE);
|
2010-02-06 03:38:24 +00:00
|
|
|
|
2008-05-27 04:30:03 +00:00
|
|
|
switch_core_media_bug_remove_all(*session);
|
2007-04-09 18:38:47 +00:00
|
|
|
switch_ivr_deactivate_unicast(*session);
|
2008-05-27 04:30:03 +00:00
|
|
|
|
2007-03-29 22:34:40 +00:00
|
|
|
switch_scheduler_del_task_group((*session)->uuid_str);
|
|
|
|
|
2009-03-07 17:45:37 +00:00
|
|
|
switch_mutex_lock(runtime.session_hash_mutex);
|
2007-05-10 16:56:29 +00:00
|
|
|
switch_core_hash_delete(session_manager.session_table, (*session)->uuid_str);
|
|
|
|
if (session_manager.session_count) {
|
|
|
|
session_manager.session_count--;
|
2011-10-12 19:55:32 +00:00
|
|
|
if (session_manager.session_count == 0) {
|
|
|
|
if (switch_test_flag((&runtime), SCF_SYNC_CLOCK_REQUESTED)) {
|
|
|
|
switch_time_sync();
|
|
|
|
switch_clear_flag((&runtime), SCF_SYNC_CLOCK_REQUESTED);
|
|
|
|
}
|
|
|
|
}
|
2007-03-29 22:34:40 +00:00
|
|
|
}
|
2009-03-07 17:45:37 +00:00
|
|
|
switch_mutex_unlock(runtime.session_hash_mutex);
|
2007-03-29 22:34:40 +00:00
|
|
|
|
2010-12-11 16:41:34 +00:00
|
|
|
if ((*session)->plc) {
|
|
|
|
plc_free((*session)->plc);
|
|
|
|
(*session)->plc = NULL;
|
|
|
|
}
|
|
|
|
|
2007-03-29 22:34:40 +00:00
|
|
|
if (switch_event_create(&event, SWITCH_EVENT_CHANNEL_DESTROY) == SWITCH_STATUS_SUCCESS) {
|
|
|
|
switch_channel_event_set_data((*session)->channel, event);
|
|
|
|
switch_event_fire(&event);
|
|
|
|
}
|
|
|
|
|
2009-04-10 17:43:18 +00:00
|
|
|
switch_core_session_destroy_state(*session);
|
2008-01-21 17:14:43 +00:00
|
|
|
|
2007-03-29 22:34:40 +00:00
|
|
|
switch_buffer_destroy(&(*session)->raw_read_buffer);
|
|
|
|
switch_buffer_destroy(&(*session)->raw_write_buffer);
|
2007-10-15 16:25:08 +00:00
|
|
|
switch_ivr_clear_speech_cache(*session);
|
2007-03-29 22:34:40 +00:00
|
|
|
switch_channel_uninit((*session)->channel);
|
|
|
|
|
2011-09-02 14:34:40 +00:00
|
|
|
for (i = 0; i < 2; i++) {
|
|
|
|
if ((*session)->dmachine[i]) {
|
|
|
|
switch_ivr_dmachine_destroy(&(*session)->dmachine[i]);
|
|
|
|
}
|
2010-10-07 23:30:07 +00:00
|
|
|
}
|
|
|
|
|
2007-03-29 22:34:40 +00:00
|
|
|
pool = (*session)->pool;
|
2007-09-29 01:06:08 +00:00
|
|
|
//#ifndef NDEBUG
|
|
|
|
//memset(*session, 0, sizeof(switch_core_session_t));
|
|
|
|
//#endif
|
2007-03-29 22:34:40 +00:00
|
|
|
*session = NULL;
|
2007-09-29 01:06:08 +00:00
|
|
|
switch_core_destroy_memory_pool(&pool);
|
2008-05-27 04:30:03 +00:00
|
|
|
|
2008-11-12 19:28:05 +00:00
|
|
|
UNPROTECT_INTERFACE(endpoint_interface);
|
2007-03-29 22:34:40 +00:00
|
|
|
}
|
|
|
|
|
2009-04-10 17:43:18 +00:00
|
|
|
|
|
|
|
|
2008-10-21 16:22:38 +00:00
|
|
|
SWITCH_STANDARD_SCHED_FUNC(sch_heartbeat_callback)
|
|
|
|
{
|
|
|
|
switch_event_t *event;
|
|
|
|
switch_core_session_t *session;
|
|
|
|
char *uuid = task->cmd_arg;
|
2010-02-06 03:38:24 +00:00
|
|
|
|
2008-10-21 16:22:38 +00:00
|
|
|
if ((session = switch_core_session_locate(uuid))) {
|
|
|
|
switch_event_create(&event, SWITCH_EVENT_SESSION_HEARTBEAT);
|
|
|
|
switch_channel_event_set_data(session->channel, event);
|
|
|
|
switch_event_fire(&event);
|
2008-10-22 03:03:43 +00:00
|
|
|
|
|
|
|
/* reschedule this task */
|
2009-01-25 21:23:07 +00:00
|
|
|
task->runtime = switch_epoch_time_now(NULL) + session->track_duration;
|
2008-10-22 03:03:43 +00:00
|
|
|
|
2008-10-21 16:22:38 +00:00
|
|
|
switch_core_session_rwunlock(session);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
SWITCH_DECLARE(void) switch_core_session_unsched_heartbeat(switch_core_session_t *session)
|
|
|
|
{
|
|
|
|
if (session->track_id) {
|
|
|
|
switch_scheduler_del_task_id(session->track_id);
|
|
|
|
session->track_id = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
SWITCH_DECLARE(void) switch_core_session_sched_heartbeat(switch_core_session_t *session, uint32_t seconds)
|
|
|
|
{
|
|
|
|
|
|
|
|
switch_core_session_unsched_heartbeat(session);
|
2010-02-06 03:38:24 +00:00
|
|
|
session->track_id = switch_scheduler_add_task(switch_epoch_time_now(NULL), sch_heartbeat_callback, (char *) __SWITCH_FUNC__,
|
2008-10-21 16:22:38 +00:00
|
|
|
switch_core_session_get_uuid(session), 0, strdup(switch_core_session_get_uuid(session)), SSHF_FREE_ARG);
|
|
|
|
}
|
|
|
|
|
2008-10-07 21:03:37 +00:00
|
|
|
SWITCH_DECLARE(void) switch_core_session_enable_heartbeat(switch_core_session_t *session, uint32_t seconds)
|
|
|
|
{
|
|
|
|
switch_assert(session != NULL);
|
2008-10-07 21:42:31 +00:00
|
|
|
|
2008-12-08 15:30:08 +00:00
|
|
|
if (!seconds) {
|
2008-10-07 21:42:31 +00:00
|
|
|
seconds = 60;
|
|
|
|
}
|
|
|
|
|
2009-08-01 06:11:22 +00:00
|
|
|
session->track_duration = seconds;
|
|
|
|
|
2010-02-06 03:38:24 +00:00
|
|
|
if (switch_channel_test_flag(session->channel, CF_PROXY_MODE)) {
|
|
|
|
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "%s using scheduler due to bypass_media mode\n",
|
|
|
|
switch_channel_get_name(session->channel));
|
2008-10-21 16:22:38 +00:00
|
|
|
switch_core_session_sched_heartbeat(session, seconds);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch_core_session_unsched_heartbeat(session);
|
2010-02-06 03:38:24 +00:00
|
|
|
|
|
|
|
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "%s setting session heartbeat to %u second(s).\n",
|
2008-10-07 21:03:37 +00:00
|
|
|
switch_channel_get_name(session->channel), seconds);
|
2009-08-01 06:11:22 +00:00
|
|
|
|
2008-10-07 21:42:31 +00:00
|
|
|
session->read_frame_count = 0;
|
2010-02-06 03:38:24 +00:00
|
|
|
|
2008-10-07 21:03:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
SWITCH_DECLARE(void) switch_core_session_disable_heartbeat(switch_core_session_t *session)
|
|
|
|
{
|
2008-10-21 16:22:38 +00:00
|
|
|
switch_core_session_unsched_heartbeat(session);
|
2008-10-07 21:03:37 +00:00
|
|
|
switch_assert(session != NULL);
|
2008-10-07 21:42:31 +00:00
|
|
|
session->read_frame_count = 0;
|
2008-10-07 21:03:37 +00:00
|
|
|
session->track_duration = 0;
|
2010-02-06 03:38:24 +00:00
|
|
|
|
2008-10-07 21:03:37 +00:00
|
|
|
}
|
|
|
|
|
2010-01-23 18:35:05 +00:00
|
|
|
SWITCH_DECLARE(switch_bool_t) switch_core_session_in_thread(switch_core_session_t *session)
|
|
|
|
{
|
2010-01-24 19:23:58 +00:00
|
|
|
return switch_thread_equal(switch_thread_self(), session->thread_id) ? SWITCH_TRUE : SWITCH_FALSE;
|
2010-01-23 18:35:05 +00:00
|
|
|
}
|
|
|
|
|
2008-05-27 04:30:03 +00:00
|
|
|
static void *SWITCH_THREAD_FUNC switch_core_session_thread(switch_thread_t *thread, void *obj)
|
2007-03-29 22:34:40 +00:00
|
|
|
{
|
|
|
|
switch_core_session_t *session = obj;
|
2008-02-21 21:38:49 +00:00
|
|
|
switch_event_t *event;
|
|
|
|
char *event_str = NULL;
|
|
|
|
const char *val;
|
|
|
|
|
2007-03-29 22:34:40 +00:00
|
|
|
session->thread = thread;
|
2009-09-14 20:10:58 +00:00
|
|
|
session->thread_id = switch_thread_self();
|
|
|
|
|
2007-03-29 22:34:40 +00:00
|
|
|
switch_core_session_run(session);
|
2008-06-25 19:56:20 +00:00
|
|
|
switch_core_media_bug_remove_all(session);
|
2010-07-15 06:00:08 +00:00
|
|
|
|
|
|
|
if (session->soft_lock) {
|
|
|
|
uint32_t loops = session->soft_lock * 10;
|
|
|
|
|
|
|
|
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Session %" SWITCH_SIZE_T_FMT " (%s) Soft-Locked, "
|
|
|
|
"Waiting %u for external entities\n",
|
|
|
|
session->id, switch_channel_get_name(session->channel), session->soft_lock);
|
|
|
|
|
|
|
|
while(--loops > 0) {
|
|
|
|
if (!session->soft_lock) break;
|
|
|
|
switch_yield(100000);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2009-08-13 20:35:02 +00:00
|
|
|
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Session %" SWITCH_SIZE_T_FMT " (%s) Locked, Waiting on external entities\n",
|
2007-03-29 22:34:40 +00:00
|
|
|
session->id, switch_channel_get_name(session->channel));
|
|
|
|
switch_core_session_write_lock(session);
|
|
|
|
switch_set_flag(session, SSF_DESTROYED);
|
2008-02-21 21:38:49 +00:00
|
|
|
|
|
|
|
if ((val = switch_channel_get_variable(session->channel, "memory_debug")) && switch_true(val)) {
|
2008-10-02 17:10:05 +00:00
|
|
|
if (switch_event_create(&event, SWITCH_EVENT_GENERAL) == SWITCH_STATUS_SUCCESS) {
|
2008-02-21 21:38:49 +00:00
|
|
|
switch_channel_event_set_data(session->channel, event);
|
|
|
|
switch_event_serialize(event, &event_str, SWITCH_FALSE);
|
|
|
|
switch_assert(event_str);
|
|
|
|
switch_core_memory_pool_tag(switch_core_session_get_pool(session), switch_core_session_strdup(session, event_str));
|
|
|
|
free(event_str);
|
2008-03-14 16:21:13 +00:00
|
|
|
switch_event_destroy(&event);
|
2008-02-21 21:38:49 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-03-29 22:34:40 +00:00
|
|
|
switch_core_session_rwunlock(session);
|
|
|
|
|
2009-08-13 20:35:02 +00:00
|
|
|
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_NOTICE, "Session %" SWITCH_SIZE_T_FMT " (%s) Ended\n",
|
2007-04-22 19:11:22 +00:00
|
|
|
session->id, switch_channel_get_name(session->channel));
|
2012-08-16 17:09:19 +00:00
|
|
|
|
|
|
|
switch_set_flag(session, SSF_DESTROYABLE);
|
2007-03-29 22:34:40 +00:00
|
|
|
switch_core_session_destroy(&session);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2012-08-21 05:14:43 +00:00
|
|
|
typedef struct switch_thread_pool_node_s {
|
|
|
|
switch_memory_pool_t *pool;
|
|
|
|
} switch_thread_pool_node_t;
|
|
|
|
|
|
|
|
static void *SWITCH_THREAD_FUNC switch_core_session_thread_pool_worker(switch_thread_t *thread, void *obj)
|
|
|
|
{
|
|
|
|
switch_thread_pool_node_t *node = (switch_thread_pool_node_t *) obj;
|
|
|
|
switch_memory_pool_t *pool = node->pool;
|
|
|
|
void *pop;
|
|
|
|
int check = 0;
|
|
|
|
|
|
|
|
switch_mutex_lock(session_manager.mutex);
|
|
|
|
session_manager.running++;
|
|
|
|
switch_mutex_unlock(session_manager.mutex);
|
|
|
|
|
2012-08-22 00:47:05 +00:00
|
|
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG10, "Worker Thread %ld Started\n", (long) thread);
|
|
|
|
|
2012-08-21 05:14:43 +00:00
|
|
|
while(session_manager.ready) {
|
|
|
|
switch_status_t check_status;
|
|
|
|
|
2012-11-15 00:43:22 +00:00
|
|
|
pop = NULL;
|
|
|
|
|
2012-08-21 05:14:43 +00:00
|
|
|
if (check) {
|
|
|
|
check_status = switch_queue_trypop(session_manager.thread_queue, &pop);
|
|
|
|
} else {
|
2012-11-15 23:59:11 +00:00
|
|
|
switch_mutex_lock(session_manager.mutex);
|
|
|
|
session_manager.popping++;
|
|
|
|
switch_mutex_unlock(session_manager.mutex);
|
|
|
|
|
2012-08-21 05:14:43 +00:00
|
|
|
check_status = switch_queue_pop(session_manager.thread_queue, &pop);
|
2012-11-15 23:59:11 +00:00
|
|
|
|
|
|
|
switch_mutex_lock(session_manager.mutex);
|
|
|
|
session_manager.popping--;
|
|
|
|
switch_mutex_unlock(session_manager.mutex);
|
2012-08-21 05:14:43 +00:00
|
|
|
}
|
|
|
|
|
2012-11-15 00:43:22 +00:00
|
|
|
if (check_status == SWITCH_STATUS_SUCCESS && pop) {
|
2012-10-25 16:31:42 +00:00
|
|
|
switch_thread_data_t *td = (switch_thread_data_t *) pop;
|
2012-10-07 14:40:24 +00:00
|
|
|
|
2012-10-25 16:31:42 +00:00
|
|
|
if (!td) break;
|
2012-08-21 05:14:43 +00:00
|
|
|
|
|
|
|
switch_mutex_lock(session_manager.mutex);
|
|
|
|
session_manager.busy++;
|
|
|
|
switch_mutex_unlock(session_manager.mutex);
|
|
|
|
|
2012-10-25 16:31:42 +00:00
|
|
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG10, "Worker Thread %ld Processing\n", (long) thread);
|
2012-08-22 00:47:05 +00:00
|
|
|
|
|
|
|
|
2012-10-25 16:31:42 +00:00
|
|
|
td->func(thread, td->obj);
|
|
|
|
|
|
|
|
if (td->alloc) {
|
|
|
|
free(td);
|
|
|
|
}
|
|
|
|
|
|
|
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG10, "Worker Thread %ld Done Processing\n", (long) thread);
|
|
|
|
|
2012-08-21 05:14:43 +00:00
|
|
|
switch_mutex_lock(session_manager.mutex);
|
|
|
|
session_manager.busy--;
|
|
|
|
switch_mutex_unlock(session_manager.mutex);
|
|
|
|
|
|
|
|
} else {
|
|
|
|
if (check) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
check++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-08-22 00:47:05 +00:00
|
|
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG10, "Worker Thread %ld Ended\n", (long) thread);
|
|
|
|
|
2012-08-21 05:14:43 +00:00
|
|
|
switch_mutex_lock(session_manager.mutex);
|
|
|
|
session_manager.running--;
|
|
|
|
switch_mutex_unlock(session_manager.mutex);
|
|
|
|
|
|
|
|
switch_core_destroy_memory_pool(&pool);
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2012-08-22 15:08:20 +00:00
|
|
|
static void thread_launch_failure(void)
|
|
|
|
{
|
|
|
|
uint32_t sess_count;
|
|
|
|
|
|
|
|
switch_mutex_lock(session_manager.mutex);
|
|
|
|
|
|
|
|
sess_count = switch_core_session_count();
|
|
|
|
|
|
|
|
if (sess_count > 110) {
|
|
|
|
|
|
|
|
switch_core_session_limit(sess_count - 10);
|
|
|
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "LUKE: I'm hit, but not bad.\n");
|
|
|
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT,
|
|
|
|
"LUKE'S VOICE: Artoo, see what you can do with it. Hang on back there....\n"
|
|
|
|
"Green laserfire moves past the beeping little robot as his head turns. "
|
|
|
|
"After a few beeps and a twist of his mechanical arm,\n"
|
|
|
|
"Artoo reduces the max sessions to %d thus, saving the switch from certain doom.\n", sess_count - 10);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
switch_mutex_unlock(session_manager.mutex);
|
|
|
|
}
|
2012-08-21 05:14:43 +00:00
|
|
|
|
|
|
|
static switch_status_t check_queue(void)
|
|
|
|
{
|
|
|
|
switch_status_t status = SWITCH_STATUS_FALSE;
|
|
|
|
int ttl = 0;
|
|
|
|
int x = 0;
|
|
|
|
|
|
|
|
switch_mutex_lock(session_manager.mutex);
|
2012-11-15 23:59:11 +00:00
|
|
|
ttl = switch_queue_size(session_manager.thread_queue);
|
2012-08-21 05:14:43 +00:00
|
|
|
x = (session_manager.running - session_manager.busy);
|
|
|
|
switch_mutex_unlock(session_manager.mutex);
|
|
|
|
|
|
|
|
|
|
|
|
while (x < ttl) {
|
|
|
|
switch_thread_t *thread;
|
|
|
|
switch_threadattr_t *thd_attr;
|
|
|
|
switch_memory_pool_t *pool;
|
|
|
|
switch_thread_pool_node_t *node;
|
|
|
|
|
|
|
|
switch_core_new_memory_pool(&pool);
|
|
|
|
node = switch_core_alloc(pool, sizeof(*node));
|
|
|
|
node->pool = pool;
|
|
|
|
|
|
|
|
switch_threadattr_create(&thd_attr, node->pool);
|
|
|
|
switch_threadattr_detach_set(thd_attr, 1);
|
|
|
|
switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE);
|
2012-10-01 15:20:48 +00:00
|
|
|
switch_threadattr_priority_set(thd_attr, SWITCH_PRI_LOW);
|
2012-08-21 05:14:43 +00:00
|
|
|
|
|
|
|
if (switch_thread_create(&thread, thd_attr, switch_core_session_thread_pool_worker, node, node->pool) != SWITCH_STATUS_SUCCESS) {
|
|
|
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Thread Failure!\n");
|
|
|
|
switch_core_destroy_memory_pool(&pool);
|
|
|
|
status = SWITCH_STATUS_GENERR;
|
2012-08-22 15:08:20 +00:00
|
|
|
thread_launch_failure();
|
2012-08-21 05:14:43 +00:00
|
|
|
} else {
|
|
|
|
status = SWITCH_STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
x++;
|
|
|
|
}
|
|
|
|
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void *SWITCH_THREAD_FUNC switch_core_session_thread_pool_manager(switch_thread_t *thread, void *obj)
|
|
|
|
{
|
|
|
|
int x = 0;
|
|
|
|
|
|
|
|
while(session_manager.ready) {
|
|
|
|
switch_yield(100000);
|
|
|
|
|
|
|
|
if (++x == 300) {
|
2012-11-15 23:59:11 +00:00
|
|
|
if (session_manager.popping) {
|
|
|
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG10,
|
|
|
|
"Thread pool: running:%d busy:%d popping:%d\n", session_manager.running, session_manager.busy, session_manager.popping);
|
|
|
|
|
2012-12-17 17:29:09 +00:00
|
|
|
switch_queue_interrupt_all(session_manager.thread_queue);
|
2012-11-15 23:59:11 +00:00
|
|
|
|
2012-11-15 00:43:22 +00:00
|
|
|
x--;
|
2012-11-15 23:59:11 +00:00
|
|
|
|
|
|
|
continue;
|
2012-11-15 00:43:22 +00:00
|
|
|
} else {
|
|
|
|
x = 0;
|
|
|
|
}
|
2012-08-21 05:14:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
check_queue();
|
|
|
|
}
|
2012-12-04 22:04:16 +00:00
|
|
|
|
|
|
|
while(session_manager.running) {
|
2012-12-17 17:29:09 +00:00
|
|
|
switch_queue_interrupt_all(session_manager.thread_queue);
|
2012-12-04 22:04:16 +00:00
|
|
|
switch_yield(20000);
|
|
|
|
}
|
|
|
|
|
2012-11-15 00:43:22 +00:00
|
|
|
|
2012-08-21 05:14:43 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2012-10-25 16:31:42 +00:00
|
|
|
SWITCH_DECLARE(switch_status_t) switch_thread_pool_launch_thread(switch_thread_data_t **tdp)
|
|
|
|
{
|
|
|
|
switch_status_t status = SWITCH_STATUS_SUCCESS;
|
|
|
|
switch_thread_data_t *td;
|
|
|
|
|
|
|
|
switch_assert(tdp);
|
|
|
|
|
|
|
|
td = *tdp;
|
|
|
|
*tdp = NULL;
|
|
|
|
|
|
|
|
switch_queue_push(session_manager.thread_queue, td);
|
|
|
|
check_queue();
|
|
|
|
|
|
|
|
return status;
|
|
|
|
}
|
2012-08-21 05:14:43 +00:00
|
|
|
|
|
|
|
SWITCH_DECLARE(switch_status_t) switch_core_session_thread_pool_launch(switch_core_session_t *session)
|
|
|
|
{
|
2012-08-22 00:47:05 +00:00
|
|
|
switch_status_t status = SWITCH_STATUS_INUSE;
|
2012-10-25 16:31:42 +00:00
|
|
|
switch_thread_data_t *td;
|
|
|
|
|
2012-08-22 00:47:05 +00:00
|
|
|
switch_mutex_lock(session->mutex);
|
|
|
|
if (switch_test_flag(session, SSF_THREAD_RUNNING)) {
|
|
|
|
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_CRIT, "Cannot double-launch thread!\n");
|
|
|
|
} else if (switch_test_flag(session, SSF_THREAD_STARTED)) {
|
|
|
|
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_CRIT, "Cannot launch thread again after it has already been run!\n");
|
|
|
|
} else {
|
|
|
|
status = SWITCH_STATUS_SUCCESS;
|
|
|
|
switch_set_flag(session, SSF_THREAD_RUNNING);
|
|
|
|
switch_set_flag(session, SSF_THREAD_STARTED);
|
2012-10-25 16:31:42 +00:00
|
|
|
td = switch_core_session_alloc(session, sizeof(*td));
|
|
|
|
td->obj = session;
|
|
|
|
td->func = switch_core_session_thread;
|
|
|
|
switch_queue_push(session_manager.thread_queue, td);
|
2012-08-22 00:47:05 +00:00
|
|
|
check_queue();
|
2012-08-21 05:14:43 +00:00
|
|
|
}
|
2012-08-22 00:47:05 +00:00
|
|
|
switch_mutex_unlock(session->mutex);
|
2012-08-21 05:14:43 +00:00
|
|
|
|
2012-08-22 00:47:05 +00:00
|
|
|
return status;
|
2012-08-21 05:14:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-05-11 00:27:55 +00:00
|
|
|
SWITCH_DECLARE(switch_status_t) switch_core_session_thread_launch(switch_core_session_t *session)
|
2007-03-29 22:34:40 +00:00
|
|
|
{
|
2007-05-31 13:32:23 +00:00
|
|
|
switch_status_t status = SWITCH_STATUS_FALSE;
|
2007-03-29 22:34:40 +00:00
|
|
|
switch_thread_t *thread;
|
2012-08-21 05:14:43 +00:00
|
|
|
switch_threadattr_t *thd_attr;
|
|
|
|
|
2010-06-17 19:28:31 +00:00
|
|
|
if (switch_test_flag(session, SSF_THREAD_RUNNING) || switch_test_flag(session, SSF_THREAD_STARTED)) {
|
2012-08-16 17:09:19 +00:00
|
|
|
status = SWITCH_STATUS_INUSE;
|
2010-06-17 19:28:31 +00:00
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
2012-08-22 00:47:05 +00:00
|
|
|
|
|
|
|
if (switch_test_flag((&runtime), SCF_SESSION_THREAD_POOL)) {
|
|
|
|
return switch_core_session_thread_pool_launch(session);
|
|
|
|
}
|
|
|
|
|
2007-05-29 20:57:17 +00:00
|
|
|
switch_mutex_lock(session->mutex);
|
2008-05-27 04:30:03 +00:00
|
|
|
|
2010-05-03 17:29:56 +00:00
|
|
|
if (switch_test_flag(session, SSF_THREAD_RUNNING)) {
|
|
|
|
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_CRIT, "Cannot double-launch thread!\n");
|
|
|
|
} else if (switch_test_flag(session, SSF_THREAD_STARTED)) {
|
|
|
|
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_CRIT, "Cannot launch thread again after it has already been run!\n");
|
|
|
|
} else {
|
|
|
|
switch_set_flag(session, SSF_THREAD_RUNNING);
|
|
|
|
switch_set_flag(session, SSF_THREAD_STARTED);
|
2012-08-22 00:47:05 +00:00
|
|
|
|
|
|
|
switch_threadattr_create(&thd_attr, session->pool);
|
|
|
|
switch_threadattr_detach_set(thd_attr, 1);
|
2007-03-29 22:34:40 +00:00
|
|
|
switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE);
|
2012-08-22 00:47:05 +00:00
|
|
|
|
2007-05-11 00:27:55 +00:00
|
|
|
if (switch_thread_create(&thread, thd_attr, switch_core_session_thread, session, session->pool) == SWITCH_STATUS_SUCCESS) {
|
2010-05-03 17:29:56 +00:00
|
|
|
switch_set_flag(session, SSF_THREAD_STARTED);
|
2007-05-29 20:57:17 +00:00
|
|
|
status = SWITCH_STATUS_SUCCESS;
|
2007-05-11 00:27:55 +00:00
|
|
|
} else {
|
2010-05-03 17:29:56 +00:00
|
|
|
switch_clear_flag(session, SSF_THREAD_RUNNING);
|
|
|
|
switch_clear_flag(session, SSF_THREAD_STARTED);
|
2009-08-13 20:35:02 +00:00
|
|
|
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_CRIT, "Cannot create thread!\n");
|
2012-08-22 15:08:20 +00:00
|
|
|
thread_launch_failure();
|
2007-03-29 22:34:40 +00:00
|
|
|
}
|
|
|
|
}
|
2007-05-11 00:27:55 +00:00
|
|
|
|
2007-05-29 20:57:17 +00:00
|
|
|
switch_mutex_unlock(session->mutex);
|
|
|
|
|
2010-06-17 19:28:31 +00:00
|
|
|
end:
|
|
|
|
|
2007-05-29 20:57:17 +00:00
|
|
|
return status;
|
2007-03-29 22:34:40 +00:00
|
|
|
}
|
|
|
|
|
2007-03-30 00:13:31 +00:00
|
|
|
SWITCH_DECLARE(void) switch_core_session_launch_thread(switch_core_session_t *session, switch_thread_start_t func, void *obj)
|
2007-03-29 22:34:40 +00:00
|
|
|
{
|
|
|
|
switch_thread_t *thread;
|
|
|
|
switch_threadattr_t *thd_attr = NULL;
|
|
|
|
switch_threadattr_create(&thd_attr, session->pool);
|
|
|
|
switch_threadattr_detach_set(thd_attr, 1);
|
|
|
|
|
|
|
|
switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE);
|
2012-08-22 15:08:20 +00:00
|
|
|
if (switch_thread_create(&thread, thd_attr, func, obj, session->pool) != SWITCH_STATUS_SUCCESS) {
|
|
|
|
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_CRIT, "Cannot create thread!\n");
|
|
|
|
thread_launch_failure();
|
|
|
|
}
|
2007-03-29 22:34:40 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
|
2008-11-04 16:46:33 +00:00
|
|
|
SWITCH_DECLARE(switch_status_t) switch_core_session_set_uuid(switch_core_session_t *session, const char *use_uuid)
|
|
|
|
{
|
|
|
|
switch_event_t *event;
|
2009-10-22 14:54:29 +00:00
|
|
|
switch_core_session_message_t msg = { 0 };
|
2010-12-01 16:31:28 +00:00
|
|
|
switch_caller_profile_t *profile;
|
2008-11-04 16:46:33 +00:00
|
|
|
|
|
|
|
switch_assert(use_uuid);
|
|
|
|
|
2012-09-27 19:27:28 +00:00
|
|
|
if (!strcmp(use_uuid, session->uuid_str)) {
|
|
|
|
return SWITCH_STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-03-13 01:57:10 +00:00
|
|
|
switch_mutex_lock(runtime.session_hash_mutex);
|
2008-11-04 16:46:33 +00:00
|
|
|
if (switch_core_hash_find(session_manager.session_table, use_uuid)) {
|
2012-04-10 21:17:16 +00:00
|
|
|
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_CRIT, "Duplicate UUID!\n");
|
2009-03-13 01:57:10 +00:00
|
|
|
switch_mutex_unlock(runtime.session_hash_mutex);
|
2010-02-06 03:38:24 +00:00
|
|
|
return SWITCH_STATUS_FALSE;
|
2008-11-04 16:46:33 +00:00
|
|
|
}
|
|
|
|
|
2009-10-22 14:54:29 +00:00
|
|
|
msg.message_id = SWITCH_MESSAGE_INDICATE_UUID_CHANGE;
|
|
|
|
msg.from = switch_channel_get_name(session->channel);
|
|
|
|
msg.string_array_arg[0] = session->uuid_str;
|
|
|
|
msg.string_array_arg[1] = use_uuid;
|
|
|
|
switch_core_session_receive_message(session, &msg);
|
|
|
|
|
2010-12-01 16:31:28 +00:00
|
|
|
if ((profile = switch_channel_get_caller_profile(session->channel))) {
|
|
|
|
profile->uuid = switch_core_strdup(profile->pool, use_uuid);
|
|
|
|
}
|
|
|
|
|
2011-08-04 06:04:21 +00:00
|
|
|
switch_channel_set_variable(session->channel, "uuid", use_uuid);
|
|
|
|
switch_channel_set_variable(session->channel, "call_uuid", use_uuid);
|
|
|
|
|
2008-11-04 16:46:33 +00:00
|
|
|
switch_event_create(&event, SWITCH_EVENT_CHANNEL_UUID);
|
|
|
|
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Old-Unique-ID", session->uuid_str);
|
|
|
|
switch_core_hash_delete(session_manager.session_table, session->uuid_str);
|
|
|
|
switch_set_string(session->uuid_str, use_uuid);
|
|
|
|
switch_core_hash_insert(session_manager.session_table, session->uuid_str, session);
|
2009-03-07 17:45:37 +00:00
|
|
|
switch_mutex_unlock(runtime.session_hash_mutex);
|
2008-11-04 16:46:33 +00:00
|
|
|
switch_channel_event_set_data(session->channel, event);
|
|
|
|
switch_event_fire(&event);
|
2010-02-06 03:38:24 +00:00
|
|
|
|
2008-11-04 16:46:33 +00:00
|
|
|
|
|
|
|
return SWITCH_STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2010-02-06 03:38:24 +00:00
|
|
|
static char *xml_find_var(switch_xml_t vars, const char *name)
|
|
|
|
{
|
|
|
|
switch_xml_t var;
|
|
|
|
if ((var = switch_xml_child(vars, name)) && var->txt) {
|
|
|
|
return var->txt;
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void parse_array(const char *str, uint32_t *array, int32_t array_len)
|
|
|
|
{
|
|
|
|
char *p, *v, *dup, *next = NULL;
|
|
|
|
|
|
|
|
if (zstr(str)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
dup = strdup(str);
|
|
|
|
|
|
|
|
p = dup;
|
|
|
|
while (p) {
|
|
|
|
if ((next = strchr(p, ';'))) {
|
|
|
|
*next++ = '\0';
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((v = strchr(p, '='))) {
|
|
|
|
*v++ = '\0';
|
|
|
|
}
|
|
|
|
|
|
|
|
if (p && v) {
|
|
|
|
int x = 0, y = 0;
|
|
|
|
|
|
|
|
x = atoi(p);
|
|
|
|
y = atoi(v);
|
|
|
|
|
|
|
|
if (x < array_len) {
|
|
|
|
array[x] = y;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
p = next;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
free(dup);
|
|
|
|
}
|
|
|
|
|
|
|
|
SWITCH_DECLARE(switch_core_session_t *) switch_core_session_request_xml(switch_endpoint_interface_t *endpoint_interface,
|
|
|
|
switch_memory_pool_t **pool, switch_xml_t xml)
|
|
|
|
{
|
|
|
|
switch_core_session_t *session;
|
|
|
|
switch_channel_t *channel;
|
|
|
|
switch_xml_t tag, tag2, tag3, vars, callflow;
|
|
|
|
switch_call_direction_t direction = SWITCH_CALL_DIRECTION_OUTBOUND;
|
2011-04-22 21:43:29 +00:00
|
|
|
char *flag_str = NULL, *cap_str = NULL, *direction_s = NULL, *uuid = NULL;
|
2010-02-06 03:38:24 +00:00
|
|
|
uint32_t flags[CF_FLAG_MAX] = { 0 };
|
|
|
|
uint32_t caps[CC_FLAG_MAX] = { 0 };
|
|
|
|
int i;
|
|
|
|
|
|
|
|
vars = switch_xml_child(xml, "variables");
|
|
|
|
uuid = xml_find_var(vars, "uuid");
|
|
|
|
|
|
|
|
if ((tag = switch_xml_child(xml, "channel_data"))) {
|
|
|
|
direction_s = xml_find_var(tag, "direction");
|
|
|
|
direction = !strcmp(direction_s, "outbound") ? SWITCH_CALL_DIRECTION_OUTBOUND : SWITCH_CALL_DIRECTION_INBOUND;
|
|
|
|
flag_str = xml_find_var(tag, "flags");
|
|
|
|
cap_str = xml_find_var(tag, "caps");
|
|
|
|
}
|
|
|
|
|
|
|
|
parse_array(flag_str, flags, CF_FLAG_MAX);
|
|
|
|
parse_array(cap_str, caps, CC_FLAG_MAX);
|
|
|
|
|
2012-08-22 21:24:09 +00:00
|
|
|
flags[CF_RECOVERING] = 0;
|
|
|
|
flags[CF_RECOVERING_BRIDGE] = 0;
|
|
|
|
flags[CF_TRACKED] = 0;
|
2011-08-26 01:21:53 +00:00
|
|
|
flags[CF_TRANSFER] = 0;
|
|
|
|
flags[CF_ACCEPT_CNG] = 0;
|
|
|
|
flags[CF_REDIRECT] = 0;
|
|
|
|
flags[CF_BRIDGED] = 0;
|
|
|
|
flags[CF_HOLD] = 0;
|
|
|
|
flags[CF_SERVICE] = 0;
|
|
|
|
flags[CF_TAGGED] = 0;
|
|
|
|
flags[CF_WINNER] = 0;
|
2012-08-30 21:52:34 +00:00
|
|
|
flags[CF_EARLY_OK] = 0;
|
2011-08-26 01:21:53 +00:00
|
|
|
flags[CF_CONTROLLED] = 0;
|
|
|
|
flags[CF_SUSPEND] = 0;
|
|
|
|
flags[CF_EVENT_PARSE] = 0;
|
|
|
|
flags[CF_GEN_RINGBACK] = 0;
|
|
|
|
flags[CF_BREAK] = 0;
|
|
|
|
flags[CF_BROADCAST] = 0;
|
|
|
|
flags[CF_UNICAST] = 0;
|
|
|
|
flags[CF_EVENT_LOCK] = 0;
|
|
|
|
flags[CF_EVENT_LOCK_PRI] = 0;
|
|
|
|
flags[CF_RESET] = 0;
|
|
|
|
flags[CF_ORIGINATING] = 0;
|
|
|
|
flags[CF_STOP_BROADCAST] = 0;
|
|
|
|
flags[CF_INNER_BRIDGE] = 0;
|
|
|
|
flags[CF_REQ_MEDIA] = 0;
|
|
|
|
flags[CF_PAUSE_BUGS] = 0;
|
|
|
|
flags[CF_DIVERT_EVENTS] = 0;
|
|
|
|
flags[CF_BLOCK_STATE] = 0;
|
|
|
|
flags[CF_FS_RTP] = 0;
|
|
|
|
flags[CF_REPORTING] = 0;
|
|
|
|
flags[CF_PARK] = 0;
|
|
|
|
flags[CF_TIMESTAMP_SET] = 0;
|
|
|
|
flags[CF_ORIGINATOR] = 0;
|
|
|
|
flags[CF_XFER_ZOMBIE] = 0;
|
|
|
|
flags[CF_MEDIA_ACK] = 0;
|
|
|
|
flags[CF_THREAD_SLEEPING] = 0;
|
|
|
|
flags[CF_DISABLE_RINGBACK] = 0;
|
|
|
|
flags[CF_NOT_READY] = 0;
|
|
|
|
flags[CF_SIGNAL_BRIDGE_TTL] = 0;
|
|
|
|
flags[CF_MEDIA_BRIDGE_TTL] = 0;
|
|
|
|
flags[CF_BYPASS_MEDIA_AFTER_BRIDGE] = 0;
|
|
|
|
flags[CF_LEG_HOLDING] = 0;
|
|
|
|
flags[CF_BROADCAST_DROP_MEDIA] = 0;
|
|
|
|
flags[CF_EARLY_HANGUP] = 0;
|
|
|
|
flags[CF_MEDIA_SET] = 0;
|
|
|
|
flags[CF_CONSUME_ON_ORIGINATE] = 0;
|
|
|
|
flags[CF_PASSTHRU_PTIME_MISMATCH] = 0;
|
|
|
|
flags[CF_BRIDGE_NOWRITE] = 0;
|
|
|
|
flags[CF_RECOVERED] = 0;
|
|
|
|
flags[CF_JITTERBUFFER] = 0;
|
2011-11-08 14:02:17 +00:00
|
|
|
flags[CF_JITTERBUFFER_PLC] = 0;
|
2011-08-26 01:21:53 +00:00
|
|
|
flags[CF_DIALPLAN] = 0;
|
|
|
|
flags[CF_BLOCK_BROADCAST_UNTIL_MEDIA] = 0;
|
|
|
|
flags[CF_CNG_PLC] = 0;
|
|
|
|
flags[CF_ATTENDED_TRANSFER] = 0;
|
|
|
|
flags[CF_LAZY_ATTENDED_TRANSFER] = 0;
|
|
|
|
flags[CF_SIGNAL_DATA] = 0;
|
|
|
|
flags[CF_SIMPLIFY] = 0;
|
|
|
|
|
|
|
|
|
2010-08-26 17:19:49 +00:00
|
|
|
if (!(session = switch_core_session_request_uuid(endpoint_interface, direction, SOF_NO_LIMITS, pool, uuid))) {
|
2010-02-06 03:38:24 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
channel = switch_core_session_get_channel(session);
|
|
|
|
|
|
|
|
for (i = 0; i < CF_FLAG_MAX; i++) {
|
|
|
|
if (flags[i]) {
|
|
|
|
switch_channel_set_flag_value(channel, i, flags[i]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < CC_FLAG_MAX; i++) {
|
|
|
|
if (caps[i]) {
|
|
|
|
switch_channel_set_cap_value(channel, i, caps[i]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((tag2 = switch_xml_child(xml, "variables"))) {
|
|
|
|
for (tag = tag2->child; tag; tag = tag->sibling) {
|
|
|
|
if (tag->name && tag->txt) {
|
|
|
|
char *p = strdup(tag->txt);
|
|
|
|
char *val = p;
|
|
|
|
switch_url_decode(val);
|
|
|
|
switch_channel_set_variable(channel, tag->name, val);
|
2010-06-23 16:47:39 +00:00
|
|
|
if (!strcasecmp(tag->name, "channel_name")) {
|
|
|
|
switch_channel_set_name(channel, val);
|
|
|
|
}
|
2010-02-06 03:38:24 +00:00
|
|
|
free(p);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2010-10-13 21:17:36 +00:00
|
|
|
|
2010-02-06 03:38:24 +00:00
|
|
|
if ((callflow = switch_xml_child(xml, "callflow"))) {
|
|
|
|
if ((tag2 = switch_xml_child(callflow, "caller_profile"))) {
|
|
|
|
switch_caller_profile_t *caller_profile;
|
|
|
|
char *tmp;
|
|
|
|
|
|
|
|
caller_profile = switch_caller_profile_new(switch_core_session_get_pool(session),
|
|
|
|
xml_find_var(tag2, "username"),
|
|
|
|
xml_find_var(tag2, "dialplan"),
|
|
|
|
xml_find_var(tag2, "caller_id_name"),
|
|
|
|
xml_find_var(tag2, "caller_id_number"),
|
|
|
|
xml_find_var(tag2, "network_addr"),
|
|
|
|
xml_find_var(tag2, "ani"),
|
|
|
|
xml_find_var(tag2, "aniii"),
|
|
|
|
xml_find_var(tag2, "rdnis"),
|
|
|
|
xml_find_var(tag2, "source"),
|
|
|
|
xml_find_var(tag2, "context"), xml_find_var(tag2, "destination_number"));
|
|
|
|
|
|
|
|
if ((tmp = xml_find_var(tag2, "callee_id_name"))) {
|
|
|
|
caller_profile->callee_id_name = switch_core_session_strdup(session, tmp);
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((tmp = xml_find_var(tag2, "callee_id_number"))) {
|
|
|
|
caller_profile->callee_id_number = switch_core_session_strdup(session, tmp);
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((tag3 = switch_xml_child(callflow, "times"))) {
|
|
|
|
caller_profile->times = (switch_channel_timetable_t *) switch_core_session_alloc(session, sizeof(*caller_profile->times));
|
|
|
|
|
|
|
|
caller_profile->times->resurrected = switch_time_now();
|
|
|
|
|
|
|
|
for (tag3 = tag3->child; tag3; tag3 = tag3->sibling) {
|
|
|
|
int64_t v;
|
|
|
|
|
|
|
|
if (tag3->name && tag3->txt) {
|
|
|
|
v = atoll(tag3->txt);
|
|
|
|
if (!strcmp(tag3->name, "created_time")) {
|
|
|
|
caller_profile->times->created = v;
|
|
|
|
} else if (!strcmp(tag3->name, "profile_created_time")) {
|
|
|
|
caller_profile->times->profile_created = v;
|
|
|
|
} else if (!strcmp(tag3->name, "progress_time")) {
|
|
|
|
caller_profile->times->progress = v;
|
|
|
|
} else if (!strcmp(tag3->name, "progress_media_time")) {
|
|
|
|
caller_profile->times->progress_media = v;
|
|
|
|
} else if (!strcmp(tag3->name, "answered_time")) {
|
|
|
|
caller_profile->times->answered = v;
|
|
|
|
} else if (!strcmp(tag3->name, "hangup_time")) {
|
|
|
|
caller_profile->times->hungup = v;
|
|
|
|
} else if (!strcmp(tag3->name, "transfer_time")) {
|
|
|
|
caller_profile->times->transferred = v;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
switch_channel_set_caller_profile(channel, caller_profile);
|
|
|
|
if ((tag = switch_xml_child(tag2, "originator")) && (tag = tag->child)) {
|
|
|
|
caller_profile = switch_caller_profile_new(switch_core_session_get_pool(session),
|
|
|
|
xml_find_var(tag, "username"),
|
|
|
|
xml_find_var(tag, "dialplan"),
|
|
|
|
xml_find_var(tag, "caller_id_name"),
|
|
|
|
xml_find_var(tag, "caller_id_number"),
|
|
|
|
xml_find_var(tag, "network_addr"),
|
|
|
|
xml_find_var(tag, "ani"),
|
|
|
|
xml_find_var(tag, "aniii"),
|
|
|
|
xml_find_var(tag, "rdnis"),
|
|
|
|
xml_find_var(tag, "source"),
|
|
|
|
xml_find_var(tag, "context"), xml_find_var(tag, "destination_number"));
|
|
|
|
|
|
|
|
switch_channel_set_originator_caller_profile(channel, caller_profile);
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((tag = switch_xml_child(tag2, "originatee")) && (tag = tag->child)) {
|
|
|
|
caller_profile = switch_caller_profile_new(switch_core_session_get_pool(session),
|
|
|
|
xml_find_var(tag, "username"),
|
|
|
|
xml_find_var(tag, "dialplan"),
|
|
|
|
xml_find_var(tag, "caller_id_name"),
|
|
|
|
xml_find_var(tag, "caller_id_number"),
|
|
|
|
xml_find_var(tag, "network_addr"),
|
|
|
|
xml_find_var(tag, "ani"),
|
|
|
|
xml_find_var(tag, "aniii"),
|
|
|
|
xml_find_var(tag, "rdnis"),
|
|
|
|
xml_find_var(tag, "source"),
|
|
|
|
xml_find_var(tag, "context"), xml_find_var(tag, "destination_number"));
|
|
|
|
|
|
|
|
switch_channel_set_originatee_caller_profile(channel, caller_profile);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2010-10-13 21:17:36 +00:00
|
|
|
|
|
|
|
switch_channel_set_flag(channel, CF_RECOVERED);
|
2010-02-06 03:38:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-10-26 14:00:59 +00:00
|
|
|
if (!channel || !switch_channel_get_caller_profile(channel)) {
|
|
|
|
if (session) {
|
|
|
|
switch_core_session_destroy(&session);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-02-06 03:38:24 +00:00
|
|
|
return session;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2008-11-13 17:40:25 +00:00
|
|
|
SWITCH_DECLARE(switch_core_session_t *) switch_core_session_request_uuid(switch_endpoint_interface_t
|
2010-02-06 03:38:24 +00:00
|
|
|
*endpoint_interface,
|
2009-02-23 16:31:59 +00:00
|
|
|
switch_call_direction_t direction,
|
2010-08-26 17:19:49 +00:00
|
|
|
switch_originate_flag_t originate_flags,
|
2010-02-06 03:38:24 +00:00
|
|
|
switch_memory_pool_t **pool, const char *use_uuid)
|
2007-03-29 22:34:40 +00:00
|
|
|
{
|
|
|
|
switch_memory_pool_t *usepool;
|
|
|
|
switch_core_session_t *session;
|
|
|
|
switch_uuid_t uuid;
|
|
|
|
uint32_t count = 0;
|
2007-10-03 16:44:11 +00:00
|
|
|
int32_t sps = 0;
|
2007-03-29 22:34:40 +00:00
|
|
|
|
2008-11-12 19:28:05 +00:00
|
|
|
|
2008-11-04 16:46:33 +00:00
|
|
|
if (use_uuid && switch_core_hash_find(session_manager.session_table, use_uuid)) {
|
|
|
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Duplicate UUID!\n");
|
2010-02-06 03:38:24 +00:00
|
|
|
return NULL;
|
2008-11-04 16:46:33 +00:00
|
|
|
}
|
|
|
|
|
2011-12-14 19:23:54 +00:00
|
|
|
if (direction == SWITCH_CALL_DIRECTION_INBOUND && !switch_core_ready_inbound()) {
|
|
|
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "The system cannot create any inbound sessions at this time.\n");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (direction == SWITCH_CALL_DIRECTION_OUTBOUND && !switch_core_ready_outbound()) {
|
|
|
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "The system cannot create any outbound sessions at this time.\n");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2007-07-06 16:29:25 +00:00
|
|
|
if (!switch_core_ready() || endpoint_interface == NULL) {
|
|
|
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "The system cannot create any sessions at this time.\n");
|
|
|
|
return NULL;
|
|
|
|
}
|
2007-03-29 22:34:40 +00:00
|
|
|
|
2010-03-10 20:21:34 +00:00
|
|
|
if (runtime.min_idle_time > 0 && runtime.profile_time < runtime.min_idle_time) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2008-11-12 19:28:05 +00:00
|
|
|
PROTECT_INTERFACE(endpoint_interface);
|
|
|
|
|
2010-08-26 17:19:49 +00:00
|
|
|
if (!(originate_flags & SOF_NO_LIMITS)) {
|
|
|
|
switch_mutex_lock(runtime.throttle_mutex);
|
|
|
|
count = session_manager.session_count;
|
|
|
|
sps = --runtime.sps;
|
|
|
|
switch_mutex_unlock(runtime.throttle_mutex);
|
|
|
|
|
|
|
|
if (sps <= 0) {
|
|
|
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Throttle Error! %d\n", session_manager.session_count);
|
|
|
|
UNPROTECT_INTERFACE(endpoint_interface);
|
|
|
|
return NULL;
|
|
|
|
}
|
2008-05-27 04:30:03 +00:00
|
|
|
|
2010-08-26 17:19:49 +00:00
|
|
|
if ((count + 1) > session_manager.session_limit) {
|
|
|
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Over Session Limit! %d\n", session_manager.session_limit);
|
|
|
|
UNPROTECT_INTERFACE(endpoint_interface);
|
|
|
|
return NULL;
|
|
|
|
}
|
2007-10-03 16:44:11 +00:00
|
|
|
}
|
2007-03-29 22:34:40 +00:00
|
|
|
|
|
|
|
|
|
|
|
if (pool && *pool) {
|
|
|
|
usepool = *pool;
|
|
|
|
*pool = NULL;
|
2007-10-23 00:11:03 +00:00
|
|
|
} else {
|
|
|
|
switch_core_new_memory_pool(&usepool);
|
2007-03-29 22:34:40 +00:00
|
|
|
}
|
|
|
|
|
2007-10-23 00:11:03 +00:00
|
|
|
session = switch_core_alloc(usepool, sizeof(*session));
|
|
|
|
session->pool = usepool;
|
2009-05-22 18:19:55 +00:00
|
|
|
|
|
|
|
switch_core_memory_pool_set_data(session->pool, "__session", session);
|
2010-02-06 03:38:24 +00:00
|
|
|
|
2009-02-23 16:31:59 +00:00
|
|
|
if (switch_channel_alloc(&session->channel, direction, session->pool) != SWITCH_STATUS_SUCCESS) {
|
2007-10-23 00:11:03 +00:00
|
|
|
abort();
|
2007-03-29 22:34:40 +00:00
|
|
|
}
|
|
|
|
|
2009-02-24 00:05:19 +00:00
|
|
|
switch_channel_init(session->channel, session, CS_NEW, 0);
|
|
|
|
|
2009-02-23 16:31:59 +00:00
|
|
|
if (direction == SWITCH_CALL_DIRECTION_OUTBOUND) {
|
|
|
|
switch_channel_set_flag(session->channel, CF_OUTBOUND);
|
|
|
|
}
|
2010-02-06 03:38:24 +00:00
|
|
|
|
2007-03-29 22:34:40 +00:00
|
|
|
/* The session *IS* the pool you may not alter it because you have no idea how
|
|
|
|
its all private it will be passed to the thread run function */
|
|
|
|
|
2008-11-04 16:46:33 +00:00
|
|
|
if (use_uuid) {
|
|
|
|
switch_set_string(session->uuid_str, use_uuid);
|
|
|
|
} else {
|
|
|
|
switch_uuid_get(&uuid);
|
|
|
|
switch_uuid_format(session->uuid_str, &uuid);
|
|
|
|
}
|
|
|
|
|
2010-02-06 03:38:24 +00:00
|
|
|
switch_channel_set_variable(session->channel, "uuid", session->uuid_str);
|
2011-08-04 06:04:21 +00:00
|
|
|
switch_channel_set_variable(session->channel, "call_uuid", session->uuid_str);
|
2010-02-06 03:38:24 +00:00
|
|
|
|
2007-03-29 22:34:40 +00:00
|
|
|
session->endpoint_interface = endpoint_interface;
|
|
|
|
session->raw_write_frame.data = session->raw_write_buf;
|
|
|
|
session->raw_write_frame.buflen = sizeof(session->raw_write_buf);
|
|
|
|
session->raw_read_frame.data = session->raw_read_buf;
|
|
|
|
session->raw_read_frame.buflen = sizeof(session->raw_read_buf);
|
|
|
|
|
|
|
|
|
|
|
|
session->enc_write_frame.data = session->enc_write_buf;
|
|
|
|
session->enc_write_frame.buflen = sizeof(session->enc_write_buf);
|
|
|
|
session->enc_read_frame.data = session->enc_read_buf;
|
|
|
|
session->enc_read_frame.buflen = sizeof(session->enc_read_buf);
|
|
|
|
|
|
|
|
switch_mutex_init(&session->mutex, SWITCH_MUTEX_NESTED, session->pool);
|
2008-01-04 00:19:09 +00:00
|
|
|
switch_mutex_init(&session->resample_mutex, SWITCH_MUTEX_NESTED, session->pool);
|
2008-11-21 00:09:11 +00:00
|
|
|
switch_mutex_init(&session->codec_read_mutex, SWITCH_MUTEX_NESTED, session->pool);
|
|
|
|
switch_mutex_init(&session->codec_write_mutex, SWITCH_MUTEX_NESTED, session->pool);
|
2010-03-22 16:22:19 +00:00
|
|
|
switch_mutex_init(&session->frame_read_mutex, SWITCH_MUTEX_NESTED, session->pool);
|
2007-03-29 22:34:40 +00:00
|
|
|
switch_thread_rwlock_create(&session->bug_rwlock, session->pool);
|
|
|
|
switch_thread_cond_create(&session->cond, session->pool);
|
|
|
|
switch_thread_rwlock_create(&session->rwlock, session->pool);
|
2010-11-30 21:34:22 +00:00
|
|
|
switch_thread_rwlock_create(&session->io_rwlock, session->pool);
|
2007-09-24 19:34:25 +00:00
|
|
|
switch_queue_create(&session->message_queue, SWITCH_MESSAGE_QUEUE_LEN, session->pool);
|
2011-07-08 17:52:12 +00:00
|
|
|
switch_queue_create(&session->signal_data_queue, SWITCH_MESSAGE_QUEUE_LEN, session->pool);
|
2007-09-24 19:34:25 +00:00
|
|
|
switch_queue_create(&session->event_queue, SWITCH_EVENT_QUEUE_LEN, session->pool);
|
|
|
|
switch_queue_create(&session->private_event_queue, SWITCH_EVENT_QUEUE_LEN, session->pool);
|
2009-12-10 01:29:02 +00:00
|
|
|
switch_queue_create(&session->private_event_queue_pri, SWITCH_EVENT_QUEUE_LEN, session->pool);
|
2009-03-07 17:45:37 +00:00
|
|
|
|
|
|
|
switch_mutex_lock(runtime.session_hash_mutex);
|
2007-05-10 16:56:29 +00:00
|
|
|
switch_core_hash_insert(session_manager.session_table, session->uuid_str, session);
|
2009-03-07 17:45:37 +00:00
|
|
|
session->id = session_manager.session_id++;
|
2007-05-10 16:56:29 +00:00
|
|
|
session_manager.session_count++;
|
2013-07-20 20:00:06 +00:00
|
|
|
|
2013-07-21 03:13:27 +00:00
|
|
|
if (session_manager.session_count > (uint32_t)runtime.sessions_peak) {
|
2013-07-20 20:00:06 +00:00
|
|
|
runtime.sessions_peak = session_manager.session_count;
|
|
|
|
}
|
2013-07-21 03:13:27 +00:00
|
|
|
if (session_manager.session_count > (uint32_t)runtime.sessions_peak_fivemin) {
|
2013-07-20 20:00:06 +00:00
|
|
|
runtime.sessions_peak_fivemin = session_manager.session_count;
|
|
|
|
}
|
|
|
|
|
2009-03-07 17:45:37 +00:00
|
|
|
switch_mutex_unlock(runtime.session_hash_mutex);
|
2010-02-06 03:38:24 +00:00
|
|
|
|
2011-11-02 17:37:31 +00:00
|
|
|
switch_channel_set_variable_printf(session->channel, "session_id", "%u", session->id);
|
|
|
|
|
2007-03-29 22:34:40 +00:00
|
|
|
return session;
|
|
|
|
}
|
|
|
|
|
|
|
|
SWITCH_DECLARE(uint32_t) switch_core_session_count(void)
|
|
|
|
{
|
2007-05-10 16:56:29 +00:00
|
|
|
return session_manager.session_count;
|
2007-03-29 22:34:40 +00:00
|
|
|
}
|
|
|
|
|
2008-10-17 00:10:49 +00:00
|
|
|
SWITCH_DECLARE(switch_size_t) switch_core_session_get_id(switch_core_session_t *session)
|
2008-10-08 20:59:16 +00:00
|
|
|
{
|
|
|
|
return session->id;
|
|
|
|
}
|
|
|
|
|
2012-08-29 15:38:37 +00:00
|
|
|
SWITCH_DECLARE(switch_size_t) switch_core_session_id_dec(void)
|
|
|
|
{
|
|
|
|
switch_mutex_lock(runtime.session_hash_mutex);
|
|
|
|
session_manager.session_id--;
|
|
|
|
switch_mutex_unlock(runtime.session_hash_mutex);
|
|
|
|
return session_manager.session_id;
|
|
|
|
}
|
|
|
|
|
2007-04-22 01:25:02 +00:00
|
|
|
SWITCH_DECLARE(switch_size_t) switch_core_session_id(void)
|
|
|
|
{
|
2007-05-10 16:56:29 +00:00
|
|
|
return session_manager.session_id;
|
2007-04-22 01:25:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-02-06 03:38:24 +00:00
|
|
|
SWITCH_DECLARE(switch_core_session_t *) switch_core_session_request_by_name(const char *endpoint_name,
|
|
|
|
switch_call_direction_t direction, switch_memory_pool_t **pool)
|
2007-03-29 22:34:40 +00:00
|
|
|
{
|
2008-11-13 17:40:25 +00:00
|
|
|
switch_endpoint_interface_t *endpoint_interface;
|
2008-11-19 19:22:20 +00:00
|
|
|
switch_core_session_t *session;
|
2007-03-29 22:34:40 +00:00
|
|
|
|
|
|
|
if ((endpoint_interface = switch_loadable_module_get_endpoint_interface(endpoint_name)) == 0) {
|
|
|
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Could not locate channel type %s\n", endpoint_name);
|
|
|
|
return NULL;
|
|
|
|
}
|
2008-11-13 17:40:25 +00:00
|
|
|
|
2010-08-26 17:19:49 +00:00
|
|
|
session = switch_core_session_request(endpoint_interface, direction, SOF_NONE, pool);
|
2008-11-19 19:22:20 +00:00
|
|
|
|
|
|
|
UNPROTECT_INTERFACE(endpoint_interface);
|
2008-11-12 19:28:05 +00:00
|
|
|
|
2008-11-19 19:22:20 +00:00
|
|
|
return session;
|
2007-03-29 22:34:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#ifndef SWITCH_PREFIX_DIR
|
|
|
|
#define SWITCH_PREFIX_DIR "."
|
|
|
|
#endif
|
|
|
|
|
|
|
|
SWITCH_DECLARE(uint8_t) switch_core_session_compare(switch_core_session_t *a, switch_core_session_t *b)
|
|
|
|
{
|
2007-12-11 19:23:57 +00:00
|
|
|
switch_assert(a != NULL);
|
|
|
|
switch_assert(b != NULL);
|
2007-03-29 22:34:40 +00:00
|
|
|
|
|
|
|
return (uint8_t) (a->endpoint_interface == b->endpoint_interface);
|
|
|
|
}
|
|
|
|
|
2008-07-30 15:04:56 +00:00
|
|
|
SWITCH_DECLARE(uint8_t) switch_core_session_check_interface(switch_core_session_t *session, const switch_endpoint_interface_t *endpoint_interface)
|
|
|
|
{
|
|
|
|
switch_assert(session != NULL);
|
|
|
|
switch_assert(endpoint_interface != NULL);
|
|
|
|
|
|
|
|
return (uint8_t) (session->endpoint_interface == endpoint_interface);
|
|
|
|
}
|
|
|
|
|
2007-03-29 22:34:40 +00:00
|
|
|
SWITCH_DECLARE(char *) switch_core_session_get_uuid(switch_core_session_t *session)
|
|
|
|
{
|
|
|
|
return session->uuid_str;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
SWITCH_DECLARE(uint32_t) switch_core_session_limit(uint32_t new_limit)
|
|
|
|
{
|
|
|
|
if (new_limit) {
|
2007-05-10 16:56:29 +00:00
|
|
|
session_manager.session_limit = new_limit;
|
2007-03-29 22:34:40 +00:00
|
|
|
}
|
|
|
|
|
2007-05-10 16:56:29 +00:00
|
|
|
return session_manager.session_limit;
|
2007-03-29 22:34:40 +00:00
|
|
|
}
|
|
|
|
|
2010-03-10 20:21:34 +00:00
|
|
|
SWITCH_DECLARE(double) switch_core_min_idle_cpu(double new_limit)
|
|
|
|
{
|
|
|
|
if (new_limit >= 0) {
|
|
|
|
runtime.min_idle_time = new_limit;
|
|
|
|
}
|
|
|
|
|
|
|
|
return runtime.min_idle_time;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
SWITCH_DECLARE(double) switch_core_idle_cpu(void)
|
|
|
|
{
|
|
|
|
return runtime.profile_time;
|
|
|
|
}
|
|
|
|
|
2007-10-03 16:44:11 +00:00
|
|
|
SWITCH_DECLARE(uint32_t) switch_core_sessions_per_second(uint32_t new_limit)
|
|
|
|
{
|
|
|
|
if (new_limit) {
|
|
|
|
runtime.sps_total = new_limit;
|
|
|
|
}
|
|
|
|
|
|
|
|
return runtime.sps_total;
|
|
|
|
}
|
|
|
|
|
2007-03-30 02:20:13 +00:00
|
|
|
void switch_core_session_init(switch_memory_pool_t *pool)
|
2007-03-29 22:34:40 +00:00
|
|
|
{
|
2007-05-10 16:56:29 +00:00
|
|
|
memset(&session_manager, 0, sizeof(session_manager));
|
|
|
|
session_manager.session_limit = 1000;
|
|
|
|
session_manager.session_id = 1;
|
|
|
|
session_manager.memory_pool = pool;
|
|
|
|
switch_core_hash_init(&session_manager.session_table, session_manager.memory_pool);
|
2012-08-22 00:47:05 +00:00
|
|
|
|
|
|
|
if (switch_test_flag((&runtime), SCF_SESSION_THREAD_POOL)) {
|
|
|
|
switch_threadattr_t *thd_attr;
|
2012-08-21 05:14:43 +00:00
|
|
|
|
2012-08-22 00:47:05 +00:00
|
|
|
switch_mutex_init(&session_manager.mutex, SWITCH_MUTEX_NESTED, session_manager.memory_pool);
|
|
|
|
switch_queue_create(&session_manager.thread_queue, 100000, session_manager.memory_pool);
|
|
|
|
switch_threadattr_create(&thd_attr, session_manager.memory_pool);
|
|
|
|
switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE);
|
2012-08-29 16:46:36 +00:00
|
|
|
switch_thread_create(&session_manager.manager_thread, thd_attr, switch_core_session_thread_pool_manager, NULL, session_manager.memory_pool);
|
2012-08-22 00:47:05 +00:00
|
|
|
session_manager.ready = 1;
|
|
|
|
}
|
2012-08-21 05:14:43 +00:00
|
|
|
|
2007-03-29 22:34:40 +00:00
|
|
|
}
|
2007-04-20 23:45:14 +00:00
|
|
|
|
2007-09-29 01:06:08 +00:00
|
|
|
void switch_core_session_uninit(void)
|
|
|
|
{
|
2012-08-21 14:58:23 +00:00
|
|
|
int sanity = 100;
|
2012-08-29 16:46:36 +00:00
|
|
|
switch_status_t st = SWITCH_STATUS_FALSE;
|
2012-08-21 14:58:23 +00:00
|
|
|
|
2007-09-29 01:06:08 +00:00
|
|
|
switch_core_hash_destroy(&session_manager.session_table);
|
2012-08-21 05:14:43 +00:00
|
|
|
session_manager.ready = 0;
|
2012-08-21 05:39:56 +00:00
|
|
|
|
2012-08-29 16:46:36 +00:00
|
|
|
switch_thread_join(&st, session_manager.manager_thread);
|
|
|
|
|
2012-08-21 14:58:23 +00:00
|
|
|
while(session_manager.running && --sanity > 0) {
|
2012-08-21 05:39:56 +00:00
|
|
|
switch_queue_interrupt_all(session_manager.thread_queue);
|
|
|
|
switch_yield(100000);
|
|
|
|
}
|
2012-08-21 05:14:43 +00:00
|
|
|
|
2007-09-29 01:06:08 +00:00
|
|
|
}
|
2007-04-20 23:45:14 +00:00
|
|
|
|
2007-04-21 01:03:58 +00:00
|
|
|
SWITCH_DECLARE(switch_app_log_t *) switch_core_session_get_app_log(switch_core_session_t *session)
|
|
|
|
{
|
|
|
|
return session->app_log;
|
|
|
|
}
|
|
|
|
|
2009-12-02 18:13:11 +00:00
|
|
|
SWITCH_DECLARE(switch_status_t) switch_core_session_get_app_flags(const char *app, int32_t *flags)
|
|
|
|
{
|
|
|
|
switch_application_interface_t *application_interface;
|
|
|
|
switch_status_t status = SWITCH_STATUS_FALSE;
|
|
|
|
|
|
|
|
switch_assert(flags);
|
|
|
|
|
|
|
|
*flags = 0;
|
|
|
|
|
|
|
|
if ((application_interface = switch_loadable_module_get_application_interface(app)) == 0) {
|
|
|
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid Application %s\n", app);
|
2009-12-11 21:51:10 +00:00
|
|
|
goto end;
|
2009-12-02 18:13:11 +00:00
|
|
|
} else if (application_interface->flags) {
|
|
|
|
*flags = application_interface->flags;
|
|
|
|
status = SWITCH_STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2009-12-11 21:51:10 +00:00
|
|
|
UNPROTECT_INTERFACE(application_interface);
|
|
|
|
|
2010-02-06 03:38:24 +00:00
|
|
|
end:
|
2009-12-11 21:51:10 +00:00
|
|
|
|
2009-12-02 18:13:11 +00:00
|
|
|
return status;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2010-11-30 17:01:54 +00:00
|
|
|
SWITCH_DECLARE(switch_status_t) switch_core_session_execute_application_async(switch_core_session_t *session, const char *app, const char *arg)
|
|
|
|
{
|
|
|
|
switch_event_t *execute_event;
|
2011-02-04 01:32:14 +00:00
|
|
|
char *ap, *arp;
|
|
|
|
|
|
|
|
if (!arg && strstr(app, "::")) {
|
|
|
|
ap = switch_core_session_strdup(session, app);
|
|
|
|
app = ap;
|
|
|
|
|
|
|
|
if ((arp = strstr(ap, "::"))) {
|
|
|
|
*arp = '\0';
|
|
|
|
arg = arp + 2;
|
|
|
|
}
|
|
|
|
}
|
2010-11-30 17:01:54 +00:00
|
|
|
|
|
|
|
if (switch_event_create(&execute_event, SWITCH_EVENT_COMMAND) == SWITCH_STATUS_SUCCESS) {
|
|
|
|
switch_event_add_header_string(execute_event, SWITCH_STACK_BOTTOM, "call-command", "execute");
|
|
|
|
switch_event_add_header_string(execute_event, SWITCH_STACK_BOTTOM, "execute-app-name", app);
|
|
|
|
|
|
|
|
if (arg) {
|
|
|
|
switch_event_add_header_string(execute_event, SWITCH_STACK_BOTTOM, "execute-app-arg", arg);
|
|
|
|
}
|
|
|
|
|
2010-12-23 01:10:30 +00:00
|
|
|
if (!switch_channel_test_flag(session->channel, CF_PROXY_MODE)) {
|
|
|
|
switch_channel_set_flag(session->channel, CF_BLOCK_BROADCAST_UNTIL_MEDIA);
|
|
|
|
}
|
|
|
|
|
2010-11-30 17:01:54 +00:00
|
|
|
switch_event_add_header_string(execute_event, SWITCH_STACK_BOTTOM, "event-lock", "true");
|
|
|
|
switch_core_session_queue_private_event(session, &execute_event, SWITCH_FALSE);
|
|
|
|
|
|
|
|
return SWITCH_STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
return SWITCH_STATUS_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-02-06 03:38:24 +00:00
|
|
|
SWITCH_DECLARE(switch_status_t) switch_core_session_execute_application_get_flags(switch_core_session_t *session, const char *app,
|
2009-12-02 18:13:11 +00:00
|
|
|
const char *arg, int32_t *flags)
|
2008-04-02 15:11:07 +00:00
|
|
|
{
|
2008-11-13 17:40:25 +00:00
|
|
|
switch_application_interface_t *application_interface;
|
2009-04-23 05:26:21 +00:00
|
|
|
switch_status_t status = SWITCH_STATUS_SUCCESS;
|
2010-02-06 03:38:24 +00:00
|
|
|
|
2011-11-18 19:17:56 +00:00
|
|
|
if (switch_channel_down_nosig(session->channel)) {
|
2011-09-13 14:35:41 +00:00
|
|
|
char *p;
|
|
|
|
if (!arg && (p = strstr(app, "::"))) {
|
|
|
|
*p++ = '0';
|
|
|
|
*p++ = '0';
|
|
|
|
arg = p;
|
|
|
|
|
|
|
|
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "%s ASYNC CALL CONVERTED TO INLINE %s(%s)\n",
|
|
|
|
switch_channel_get_name(session->channel), app, switch_str_nil(arg));
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((application_interface = switch_loadable_module_get_application_interface(app)) == 0) {
|
|
|
|
return SWITCH_STATUS_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (switch_test_flag(application_interface, SAF_ZOMBIE_EXEC)) {
|
|
|
|
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s ZOMBIE EXEC %s(%s)\n",
|
|
|
|
switch_channel_get_name(session->channel), app, switch_str_nil(arg));
|
|
|
|
goto exec;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG,
|
|
|
|
"%s Channel is hungup and application '%s' does not have the zombie_exec flag.\n",
|
|
|
|
switch_channel_get_name(session->channel), app);
|
2011-10-24 13:47:08 +00:00
|
|
|
|
|
|
|
switch_goto_status(SWITCH_STATUS_IGNORE, done);
|
2009-02-20 15:30:01 +00:00
|
|
|
}
|
|
|
|
|
2011-09-13 14:35:41 +00:00
|
|
|
if (!arg && strstr(app, "::")) {
|
|
|
|
return switch_core_session_execute_application_async(session, app, arg);
|
|
|
|
}
|
|
|
|
|
2008-04-02 15:11:07 +00:00
|
|
|
if ((application_interface = switch_loadable_module_get_application_interface(app)) == 0) {
|
2009-08-13 20:35:02 +00:00
|
|
|
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Invalid Application %s\n", app);
|
2008-04-02 15:11:07 +00:00
|
|
|
switch_channel_hangup(session->channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
|
2011-10-24 13:47:08 +00:00
|
|
|
switch_goto_status(SWITCH_STATUS_FALSE, done);
|
2008-04-02 15:11:07 +00:00
|
|
|
}
|
2008-05-27 04:30:03 +00:00
|
|
|
|
2008-04-02 15:11:07 +00:00
|
|
|
if (!application_interface->application_function) {
|
2009-08-13 20:35:02 +00:00
|
|
|
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "No Function for %s\n", app);
|
2008-04-02 15:11:07 +00:00
|
|
|
switch_channel_hangup(session->channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
|
2009-04-23 05:26:21 +00:00
|
|
|
switch_goto_status(SWITCH_STATUS_FALSE, done);
|
2008-04-02 15:11:07 +00:00
|
|
|
}
|
2008-05-27 04:30:03 +00:00
|
|
|
|
2009-12-02 18:13:11 +00:00
|
|
|
if (flags && application_interface->flags) {
|
|
|
|
*flags = application_interface->flags;
|
|
|
|
}
|
|
|
|
|
2013-07-11 22:38:24 +00:00
|
|
|
if (!switch_test_flag(application_interface, SAF_SUPPORT_NOMEDIA) && (switch_channel_test_flag(session->channel, CF_VIDEO))) {
|
|
|
|
switch_core_session_refresh_video(session);
|
|
|
|
}
|
|
|
|
|
2008-04-02 15:11:07 +00:00
|
|
|
if (switch_channel_test_flag(session->channel, CF_PROXY_MODE) && !switch_test_flag(application_interface, SAF_SUPPORT_NOMEDIA)) {
|
|
|
|
switch_ivr_media(session->uuid_str, SMF_NONE);
|
2009-08-13 20:35:02 +00:00
|
|
|
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Application %s Requires media on channel %s!\n",
|
2008-04-02 15:11:07 +00:00
|
|
|
app, switch_channel_get_name(session->channel));
|
|
|
|
} else if (!switch_test_flag(application_interface, SAF_SUPPORT_NOMEDIA) && !switch_channel_media_ready(session->channel)) {
|
2010-11-29 19:00:19 +00:00
|
|
|
if (switch_channel_direction(session->channel) == SWITCH_CALL_DIRECTION_INBOUND) {
|
|
|
|
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Application %s Requires media! pre_answering channel %s\n",
|
|
|
|
app, switch_channel_get_name(session->channel));
|
|
|
|
if (switch_channel_pre_answer(session->channel) != SWITCH_STATUS_SUCCESS) {
|
|
|
|
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Well, that didn't work very well did it? ...\n");
|
|
|
|
switch_goto_status(SWITCH_STATUS_FALSE, done);
|
|
|
|
}
|
|
|
|
} else {
|
2010-12-23 01:10:30 +00:00
|
|
|
uint32_t ready = 0, sanity = 2000;
|
|
|
|
|
|
|
|
do {
|
|
|
|
sanity--;
|
2011-02-28 23:11:29 +00:00
|
|
|
ready = switch_channel_media_up(session->channel);
|
2010-12-23 01:10:30 +00:00
|
|
|
switch_cond_next();
|
|
|
|
} while(!ready && sanity);
|
|
|
|
|
|
|
|
if (!ready) {
|
|
|
|
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING,
|
|
|
|
"Cannot execute app '%s' media required on an outbound channel that does not have media established\n", app);
|
|
|
|
switch_goto_status(SWITCH_STATUS_FALSE, done);
|
|
|
|
}
|
2008-04-02 15:11:07 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-09-13 14:35:41 +00:00
|
|
|
exec:
|
|
|
|
|
2009-01-30 23:46:00 +00:00
|
|
|
switch_core_session_exec(session, application_interface, arg);
|
2009-01-30 23:08:55 +00:00
|
|
|
|
2010-02-06 03:38:24 +00:00
|
|
|
done:
|
2009-12-11 21:51:10 +00:00
|
|
|
|
2009-01-30 23:08:55 +00:00
|
|
|
UNPROTECT_INTERFACE(application_interface);
|
2010-02-06 03:38:24 +00:00
|
|
|
|
2009-04-23 05:26:21 +00:00
|
|
|
return status;
|
2009-01-30 23:08:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
SWITCH_DECLARE(switch_status_t) switch_core_session_exec(switch_core_session_t *session,
|
|
|
|
const switch_application_interface_t *application_interface, const char *arg)
|
|
|
|
{
|
|
|
|
switch_app_log_t *log, *lp;
|
|
|
|
switch_event_t *event;
|
|
|
|
const char *var;
|
|
|
|
switch_channel_t *channel = switch_core_session_get_channel(session);
|
|
|
|
char *expanded = NULL;
|
2012-07-02 19:55:45 +00:00
|
|
|
const char *app, *app_uuid_var;
|
2010-02-06 03:38:24 +00:00
|
|
|
switch_core_session_message_t msg = { 0 };
|
2011-06-15 18:03:39 +00:00
|
|
|
char delim = ',';
|
2011-06-18 16:52:37 +00:00
|
|
|
int scope = 0;
|
2012-07-02 19:55:45 +00:00
|
|
|
char uuid_str[SWITCH_UUID_FORMATTED_LENGTH + 1];
|
|
|
|
char *app_uuid = uuid_str;
|
2013-07-17 00:15:56 +00:00
|
|
|
|
2012-07-02 19:55:45 +00:00
|
|
|
if ((app_uuid_var = switch_channel_get_variable(channel, "app_uuid"))) {
|
|
|
|
app_uuid = (char *)app_uuid_var;
|
|
|
|
switch_channel_set_variable(channel, "app_uuid", NULL);
|
|
|
|
} else {
|
|
|
|
switch_uuid_str(uuid_str, sizeof(uuid_str));
|
|
|
|
}
|
2011-06-18 15:28:23 +00:00
|
|
|
|
2009-01-30 23:08:55 +00:00
|
|
|
switch_assert(application_interface);
|
|
|
|
|
|
|
|
app = application_interface->interface_name;
|
2010-02-06 03:38:24 +00:00
|
|
|
|
2009-03-06 03:54:38 +00:00
|
|
|
if (arg) {
|
|
|
|
expanded = switch_channel_expand_variables(session->channel, arg);
|
2008-04-02 15:11:07 +00:00
|
|
|
}
|
|
|
|
|
2011-06-15 18:03:39 +00:00
|
|
|
if (expanded && *expanded == '%' && (*(expanded+1) == '[' || *(expanded+2) == '[')) {
|
|
|
|
char *p, *dup;
|
|
|
|
switch_event_t *ovars = NULL;
|
|
|
|
|
|
|
|
p = expanded + 1;
|
|
|
|
|
|
|
|
if (*p != '[') {
|
|
|
|
delim = *p;
|
|
|
|
p++;
|
|
|
|
}
|
|
|
|
|
|
|
|
dup = strdup(p);
|
|
|
|
|
|
|
|
if (expanded != arg) {
|
|
|
|
switch_safe_free(expanded);
|
|
|
|
}
|
|
|
|
|
|
|
|
switch_event_create_brackets(dup, '[', ']', delim, &ovars, &expanded, SWITCH_TRUE);
|
|
|
|
free(dup);
|
|
|
|
|
|
|
|
switch_channel_set_scope_variables(session->channel, &ovars);
|
2011-06-18 15:28:23 +00:00
|
|
|
scope = 1;
|
2011-06-15 18:03:39 +00:00
|
|
|
}
|
|
|
|
|
2011-06-18 15:28:23 +00:00
|
|
|
|
2010-02-06 03:38:24 +00:00
|
|
|
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG_CLEAN(session), SWITCH_LOG_DEBUG, "EXECUTE %s %s(%s)\n",
|
2009-03-06 03:54:38 +00:00
|
|
|
switch_channel_get_name(session->channel), app, switch_str_nil(expanded));
|
|
|
|
|
2008-08-25 16:30:28 +00:00
|
|
|
if ((var = switch_channel_get_variable(session->channel, "verbose_presence")) && switch_true(var)) {
|
2008-04-04 21:36:04 +00:00
|
|
|
char *myarg = NULL;
|
|
|
|
if (expanded) {
|
2008-07-28 15:38:52 +00:00
|
|
|
myarg = switch_mprintf("%s(%s)", app, expanded);
|
2009-10-23 16:03:42 +00:00
|
|
|
} else if (!zstr(arg)) {
|
2008-07-28 15:38:52 +00:00
|
|
|
myarg = switch_mprintf("%s(%s)", app, arg);
|
|
|
|
} else {
|
|
|
|
myarg = switch_mprintf("%s", app);
|
2008-04-04 21:36:04 +00:00
|
|
|
}
|
|
|
|
if (myarg) {
|
2008-08-25 16:30:28 +00:00
|
|
|
switch_channel_presence(session->channel, "unknown", myarg, NULL);
|
2008-04-04 21:36:04 +00:00
|
|
|
switch_safe_free(myarg);
|
2008-04-02 15:11:07 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-05-22 01:08:30 +00:00
|
|
|
if (!(var = switch_channel_get_variable(session->channel, SWITCH_DISABLE_APP_LOG_VARIABLE)) || (!(switch_true(var)))) {
|
|
|
|
log = switch_core_session_alloc(session, sizeof(*log));
|
2007-04-21 01:03:58 +00:00
|
|
|
|
2008-05-22 01:08:30 +00:00
|
|
|
log->app = switch_core_session_strdup(session, application_interface->interface_name);
|
2009-02-02 17:04:56 +00:00
|
|
|
if (expanded) {
|
|
|
|
log->arg = switch_core_session_strdup(session, expanded);
|
|
|
|
}
|
2007-04-21 01:03:58 +00:00
|
|
|
|
2011-05-16 18:41:52 +00:00
|
|
|
log->stamp = switch_time_now();
|
|
|
|
|
2008-05-27 04:30:03 +00:00
|
|
|
for (lp = session->app_log; lp && lp->next; lp = lp->next);
|
2007-04-21 01:03:58 +00:00
|
|
|
|
2008-05-22 01:08:30 +00:00
|
|
|
if (lp) {
|
|
|
|
lp->next = log;
|
|
|
|
} else {
|
|
|
|
session->app_log = log;
|
|
|
|
}
|
2007-04-21 01:03:58 +00:00
|
|
|
}
|
2010-02-06 03:38:24 +00:00
|
|
|
|
2008-12-08 15:42:37 +00:00
|
|
|
switch_channel_set_variable(channel, SWITCH_CURRENT_APPLICATION_VARIABLE, application_interface->interface_name);
|
2009-03-27 15:07:49 +00:00
|
|
|
switch_channel_set_variable_var_check(channel, SWITCH_CURRENT_APPLICATION_DATA_VARIABLE, expanded, SWITCH_FALSE);
|
2008-12-08 15:42:37 +00:00
|
|
|
switch_channel_set_variable(channel, SWITCH_CURRENT_APPLICATION_RESPONSE_VARIABLE, NULL);
|
2010-02-06 03:38:24 +00:00
|
|
|
|
2007-06-23 05:41:07 +00:00
|
|
|
if (switch_event_create(&event, SWITCH_EVENT_CHANNEL_EXECUTE) == SWITCH_STATUS_SUCCESS) {
|
|
|
|
switch_channel_event_set_data(session->channel, event);
|
2008-08-16 02:17:09 +00:00
|
|
|
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Application", application_interface->interface_name);
|
2009-01-31 00:16:27 +00:00
|
|
|
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Application-Data", expanded);
|
2012-07-02 19:55:45 +00:00
|
|
|
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Application-UUID", app_uuid);
|
2007-06-23 05:41:07 +00:00
|
|
|
switch_event_fire(&event);
|
|
|
|
}
|
|
|
|
|
2008-01-28 07:26:10 +00:00
|
|
|
switch_channel_clear_flag(session->channel, CF_BREAK);
|
2008-01-11 16:50:05 +00:00
|
|
|
|
|
|
|
switch_assert(application_interface->application_function);
|
|
|
|
|
2008-07-01 23:41:09 +00:00
|
|
|
switch_channel_set_variable(session->channel, SWITCH_CURRENT_APPLICATION_VARIABLE, application_interface->interface_name);
|
2008-05-27 04:30:03 +00:00
|
|
|
|
2010-02-06 03:38:24 +00:00
|
|
|
msg.from = __FILE__;
|
|
|
|
msg.message_id = SWITCH_MESSAGE_INDICATE_APPLICATION_EXEC;
|
|
|
|
msg.string_array_arg[0] = application_interface->interface_name;
|
|
|
|
msg.string_array_arg[1] = expanded;
|
|
|
|
switch_core_session_receive_message(session, &msg);
|
|
|
|
|
2013-07-17 00:15:56 +00:00
|
|
|
if (switch_channel_test_flag(channel, CF_VIDEO)) {
|
|
|
|
switch_channel_set_flag(channel, CF_VIDEO_ECHO);
|
|
|
|
switch_channel_clear_flag(channel, CF_VIDEO_PASSIVE);
|
|
|
|
switch_core_session_refresh_video(session);
|
|
|
|
}
|
|
|
|
|
2009-01-30 23:08:55 +00:00
|
|
|
application_interface->application_function(session, expanded);
|
2010-02-06 03:38:24 +00:00
|
|
|
|
2013-07-17 00:15:56 +00:00
|
|
|
if (switch_channel_test_flag(channel, CF_VIDEO)) {
|
|
|
|
switch_channel_set_flag(channel, CF_VIDEO_ECHO);
|
|
|
|
switch_channel_clear_flag(channel, CF_VIDEO_PASSIVE);
|
|
|
|
switch_core_session_refresh_video(session);
|
|
|
|
}
|
2007-06-23 05:41:07 +00:00
|
|
|
if (switch_event_create(&event, SWITCH_EVENT_CHANNEL_EXECUTE_COMPLETE) == SWITCH_STATUS_SUCCESS) {
|
2008-12-08 15:42:37 +00:00
|
|
|
const char *resp = switch_channel_get_variable(session->channel, SWITCH_CURRENT_APPLICATION_RESPONSE_VARIABLE);
|
2007-06-23 05:41:07 +00:00
|
|
|
switch_channel_event_set_data(session->channel, event);
|
2008-08-16 02:17:09 +00:00
|
|
|
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Application", application_interface->interface_name);
|
2009-01-31 00:16:27 +00:00
|
|
|
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Application-Data", expanded);
|
2008-12-08 15:42:37 +00:00
|
|
|
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Application-Response", resp ? resp : "_none_");
|
2012-07-02 19:55:45 +00:00
|
|
|
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Application-UUID", app_uuid);
|
2007-06-23 05:41:07 +00:00
|
|
|
switch_event_fire(&event);
|
|
|
|
}
|
2007-04-21 01:03:58 +00:00
|
|
|
|
2010-02-06 03:38:24 +00:00
|
|
|
msg.message_id = SWITCH_MESSAGE_INDICATE_APPLICATION_EXEC_COMPLETE;
|
|
|
|
switch_core_session_receive_message(session, &msg);
|
|
|
|
|
2009-01-30 23:08:55 +00:00
|
|
|
if (expanded != arg) {
|
|
|
|
switch_safe_free(expanded);
|
|
|
|
}
|
2010-02-06 03:38:24 +00:00
|
|
|
|
2011-06-18 15:28:23 +00:00
|
|
|
if (scope) {
|
|
|
|
switch_channel_set_scope_variables(session->channel, NULL);
|
|
|
|
}
|
2011-06-15 18:03:39 +00:00
|
|
|
|
2007-04-21 01:03:58 +00:00
|
|
|
return SWITCH_STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2008-05-27 04:30:03 +00:00
|
|
|
SWITCH_DECLARE(switch_status_t) switch_core_session_execute_exten(switch_core_session_t *session, const char *exten, const char *dialplan,
|
|
|
|
const char *context)
|
2007-04-20 23:45:14 +00:00
|
|
|
{
|
|
|
|
char *dp[25];
|
|
|
|
char *dpstr;
|
|
|
|
int argc, x, count = 0;
|
2008-03-10 18:38:01 +00:00
|
|
|
switch_caller_profile_t *profile, *new_profile, *pp = NULL;
|
2008-01-28 07:26:10 +00:00
|
|
|
switch_channel_t *channel = switch_core_session_get_channel(session);
|
2007-04-20 23:45:14 +00:00
|
|
|
switch_dialplan_interface_t *dialplan_interface = NULL;
|
|
|
|
switch_caller_extension_t *extension = NULL;
|
2007-04-29 03:42:38 +00:00
|
|
|
switch_status_t status = SWITCH_STATUS_SUCCESS;
|
|
|
|
|
2007-04-20 23:45:14 +00:00
|
|
|
if (!(profile = switch_channel_get_caller_profile(channel))) {
|
2007-04-29 03:42:38 +00:00
|
|
|
return SWITCH_STATUS_FALSE;
|
|
|
|
}
|
2008-05-27 04:30:03 +00:00
|
|
|
|
2007-04-29 03:42:38 +00:00
|
|
|
if (session->stack_count > SWITCH_MAX_STACKS) {
|
2010-02-06 03:38:24 +00:00
|
|
|
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Error %s too many stacked extensions\n",
|
|
|
|
switch_channel_get_name(session->channel));
|
2007-04-29 03:42:38 +00:00
|
|
|
return SWITCH_STATUS_FALSE;
|
2007-04-20 23:45:14 +00:00
|
|
|
}
|
|
|
|
|
2007-04-29 03:42:38 +00:00
|
|
|
session->stack_count++;
|
2008-05-27 04:30:03 +00:00
|
|
|
|
2007-04-20 23:45:14 +00:00
|
|
|
new_profile = switch_caller_profile_clone(session, profile);
|
2009-04-10 21:37:17 +00:00
|
|
|
new_profile->destination_number = switch_core_strdup(new_profile->pool, exten);
|
2012-02-16 22:09:41 +00:00
|
|
|
new_profile->times = (switch_channel_timetable_t *) switch_core_session_alloc(session, sizeof(*new_profile->times));
|
|
|
|
*new_profile->times = *profile->times;
|
2012-02-16 16:20:55 +00:00
|
|
|
|
2008-05-27 04:30:03 +00:00
|
|
|
|
2009-10-23 16:03:42 +00:00
|
|
|
if (!zstr(dialplan)) {
|
2009-04-10 21:37:17 +00:00
|
|
|
new_profile->dialplan = switch_core_strdup(new_profile->pool, dialplan);
|
2007-04-20 23:45:14 +00:00
|
|
|
}
|
2008-05-27 04:30:03 +00:00
|
|
|
|
2009-10-23 16:03:42 +00:00
|
|
|
if (!zstr(context)) {
|
2009-04-10 21:37:17 +00:00
|
|
|
new_profile->context = switch_core_strdup(new_profile->pool, context);
|
2007-04-20 23:45:14 +00:00
|
|
|
}
|
|
|
|
|
2010-02-06 03:38:24 +00:00
|
|
|
dpstr = switch_core_session_strdup(session, new_profile->dialplan);
|
2007-04-20 23:45:14 +00:00
|
|
|
|
2009-06-05 01:05:11 +00:00
|
|
|
switch_channel_set_hunt_caller_profile(channel, new_profile);
|
2007-04-20 23:45:14 +00:00
|
|
|
argc = switch_separate_string(dpstr, ',', dp, (sizeof(dp) / sizeof(dp[0])));
|
|
|
|
for (x = 0; x < argc; x++) {
|
|
|
|
char *dpname = dp[x];
|
|
|
|
char *dparg = NULL;
|
2008-05-27 04:30:03 +00:00
|
|
|
|
2007-04-20 23:45:14 +00:00
|
|
|
if (dpname) {
|
|
|
|
if ((dparg = strchr(dpname, ':'))) {
|
|
|
|
*dparg++ = '\0';
|
|
|
|
}
|
2008-05-16 14:59:28 +00:00
|
|
|
} else {
|
|
|
|
continue;
|
2007-04-20 23:45:14 +00:00
|
|
|
}
|
2008-05-16 14:59:28 +00:00
|
|
|
|
2007-04-20 23:45:14 +00:00
|
|
|
if (!(dialplan_interface = switch_loadable_module_get_dialplan_interface(dpname))) {
|
|
|
|
continue;
|
|
|
|
}
|
2008-05-27 04:30:03 +00:00
|
|
|
|
2007-04-20 23:45:14 +00:00
|
|
|
count++;
|
2008-05-27 04:30:03 +00:00
|
|
|
|
2009-07-28 18:33:18 +00:00
|
|
|
extension = dialplan_interface->hunt_function(session, dparg, new_profile);
|
2010-02-06 03:38:24 +00:00
|
|
|
UNPROTECT_INTERFACE(dialplan_interface);
|
2009-07-28 18:33:18 +00:00
|
|
|
|
|
|
|
if (extension) {
|
2007-04-20 23:45:14 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2008-05-27 04:30:03 +00:00
|
|
|
|
2007-04-20 23:45:14 +00:00
|
|
|
if (!extension) {
|
2007-04-29 03:42:38 +00:00
|
|
|
status = SWITCH_STATUS_FALSE;
|
|
|
|
goto done;
|
2007-04-20 23:45:14 +00:00
|
|
|
}
|
|
|
|
|
2007-04-21 01:03:58 +00:00
|
|
|
new_profile->caller_extension = extension;
|
|
|
|
|
2008-03-10 18:38:01 +00:00
|
|
|
if (profile->caller_extension) {
|
2008-05-27 04:30:03 +00:00
|
|
|
for (pp = profile->caller_extension->children; pp && pp->next; pp = pp->next);
|
|
|
|
|
2008-03-10 18:38:01 +00:00
|
|
|
if (pp) {
|
|
|
|
pp->next = new_profile;
|
|
|
|
} else {
|
|
|
|
profile->caller_extension->children = new_profile;
|
|
|
|
}
|
2007-04-21 01:03:58 +00:00
|
|
|
}
|
|
|
|
|
2007-04-20 23:45:14 +00:00
|
|
|
while (switch_channel_ready(channel) && extension->current_application) {
|
2009-08-13 20:35:02 +00:00
|
|
|
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_NOTICE, "Execute %s(%s)\n",
|
2007-04-20 23:45:14 +00:00
|
|
|
extension->current_application->application_name, switch_str_nil(extension->current_application->application_data));
|
2008-05-27 04:30:03 +00:00
|
|
|
|
2008-04-02 15:11:07 +00:00
|
|
|
if (switch_core_session_execute_application(session,
|
|
|
|
extension->current_application->application_name,
|
|
|
|
extension->current_application->application_data) != SWITCH_STATUS_SUCCESS) {
|
2007-04-29 03:42:38 +00:00
|
|
|
goto done;
|
2007-04-20 23:45:14 +00:00
|
|
|
}
|
2008-05-27 04:30:03 +00:00
|
|
|
|
|
|
|
extension->current_application = extension->current_application->next;
|
2007-04-20 23:45:14 +00:00
|
|
|
}
|
|
|
|
|
2008-05-27 04:30:03 +00:00
|
|
|
done:
|
2009-06-05 01:05:11 +00:00
|
|
|
switch_channel_set_hunt_caller_profile(channel, NULL);
|
|
|
|
|
2007-04-29 03:42:38 +00:00
|
|
|
session->stack_count--;
|
2008-05-27 04:30:03 +00:00
|
|
|
return status;
|
2007-04-20 23:45:14 +00:00
|
|
|
}
|
|
|
|
|
2010-01-20 19:19:48 +00:00
|
|
|
SWITCH_DECLARE(switch_status_t) switch_core_session_set_loglevel(switch_core_session_t *session, switch_log_level_t loglevel)
|
|
|
|
{
|
2010-02-06 03:38:24 +00:00
|
|
|
switch_assert(session != NULL);
|
|
|
|
session->loglevel = loglevel;
|
|
|
|
return SWITCH_STATUS_SUCCESS;
|
2010-01-20 19:19:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
SWITCH_DECLARE(switch_log_level_t) switch_core_session_get_loglevel(switch_core_session_t *session)
|
|
|
|
{
|
2010-02-06 03:38:24 +00:00
|
|
|
switch_assert(session != NULL);
|
|
|
|
return session->loglevel;
|
2010-01-20 19:19:48 +00:00
|
|
|
}
|
|
|
|
|
2013-06-18 00:52:37 +00:00
|
|
|
SWITCH_DECLARE(switch_status_t) switch_core_session_refresh_video(switch_core_session_t *session)
|
|
|
|
{
|
|
|
|
switch_channel_t *channel = switch_core_session_get_channel(session);
|
|
|
|
|
|
|
|
if (switch_channel_test_flag(channel, CF_VIDEO)) {
|
|
|
|
switch_core_session_message_t msg = { 0 };
|
|
|
|
msg.from = __FILE__;
|
|
|
|
msg.message_id = SWITCH_MESSAGE_INDICATE_VIDEO_REFRESH_REQ;
|
|
|
|
switch_core_session_receive_message(session, &msg);
|
|
|
|
return SWITCH_STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
return SWITCH_STATUS_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-01-27 17:36:53 +00:00
|
|
|
/* For Emacs:
|
|
|
|
* Local Variables:
|
|
|
|
* mode:c
|
2008-02-03 22:14:57 +00:00
|
|
|
* indent-tabs-mode:t
|
2008-01-27 17:36:53 +00:00
|
|
|
* tab-width:4
|
|
|
|
* c-basic-offset:4
|
|
|
|
* End:
|
|
|
|
* For VIM:
|
2013-06-25 16:50:17 +00:00
|
|
|
* vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
|
2008-01-27 17:36:53 +00:00
|
|
|
*/
|