2005-11-19 20:07:43 +00:00
|
|
|
/*
|
|
|
|
* FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
|
|
|
|
* Copyright (C) 2005/2006, Anthony Minessale II <anthmct@yahoo.com>
|
|
|
|
*
|
|
|
|
* Version: MPL 1.1
|
|
|
|
*
|
|
|
|
* The contents of this file are subject to the Mozilla Public License Version
|
|
|
|
* 1.1 (the "License"); you may not use this file except in compliance with
|
|
|
|
* the License. You may obtain a copy of the License at
|
|
|
|
* http://www.mozilla.org/MPL/
|
|
|
|
*
|
|
|
|
* Software distributed under the License is distributed on an "AS IS" basis,
|
|
|
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
|
|
|
* for the specific language governing rights and limitations under the
|
|
|
|
* License.
|
|
|
|
*
|
|
|
|
* The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
|
|
|
|
*
|
|
|
|
* The Initial Developer of the Original Code is
|
|
|
|
* Anthony Minessale II <anthmct@yahoo.com>
|
|
|
|
* Portions created by the Initial Developer are Copyright (C)
|
|
|
|
* the Initial Developer. All Rights Reserved.
|
|
|
|
*
|
|
|
|
* Contributor(s):
|
|
|
|
*
|
|
|
|
* Anthony Minessale II <anthmct@yahoo.com>
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* switch_core.c -- Main Core Library
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
#include <switch.h>
|
|
|
|
|
|
|
|
#ifdef EMBED_PERL
|
|
|
|
#include <EXTERN.h>
|
|
|
|
#include <perl.h>
|
|
|
|
|
2006-01-20 15:05:05 +00:00
|
|
|
static char *embedding[] = { "", "-e", "" };
|
|
|
|
EXTERN_C void xs_init(pTHX);
|
2005-11-19 20:07:43 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
struct switch_core_session {
|
|
|
|
unsigned long id;
|
|
|
|
char name[80];
|
2006-03-01 22:55:28 +00:00
|
|
|
int thread_running;
|
2005-11-19 20:07:43 +00:00
|
|
|
switch_memory_pool *pool;
|
|
|
|
switch_channel *channel;
|
|
|
|
switch_thread *thread;
|
|
|
|
const switch_endpoint_interface *endpoint_interface;
|
|
|
|
struct switch_io_event_hooks event_hooks;
|
|
|
|
switch_codec *read_codec;
|
|
|
|
switch_codec *write_codec;
|
2006-01-14 16:44:52 +00:00
|
|
|
|
2005-11-19 20:07:43 +00:00
|
|
|
switch_buffer *raw_write_buffer;
|
|
|
|
switch_frame raw_write_frame;
|
|
|
|
switch_frame enc_write_frame;
|
2006-01-14 16:44:52 +00:00
|
|
|
unsigned char *raw_write_buf[SWITCH_RECCOMMENDED_BUFFER_SIZE];
|
|
|
|
unsigned char *enc_write_buf[SWITCH_RECCOMMENDED_BUFFER_SIZE];
|
2005-11-19 20:07:43 +00:00
|
|
|
|
|
|
|
switch_buffer *raw_read_buffer;
|
|
|
|
switch_frame raw_read_frame;
|
|
|
|
switch_frame enc_read_frame;
|
2006-01-14 16:44:52 +00:00
|
|
|
unsigned char *raw_read_buf[SWITCH_RECCOMMENDED_BUFFER_SIZE];
|
|
|
|
unsigned char *enc_read_buf[SWITCH_RECCOMMENDED_BUFFER_SIZE];
|
2005-11-19 20:07:43 +00:00
|
|
|
|
2006-01-02 17:28:59 +00:00
|
|
|
|
|
|
|
switch_audio_resampler *read_resampler;
|
|
|
|
switch_audio_resampler *write_resampler;
|
|
|
|
|
2005-11-19 20:07:43 +00:00
|
|
|
switch_mutex_t *mutex;
|
|
|
|
switch_thread_cond_t *cond;
|
|
|
|
|
2006-01-09 18:40:56 +00:00
|
|
|
void *streams[SWITCH_MAX_STREAMS];
|
|
|
|
int stream_count;
|
|
|
|
|
2006-01-20 15:05:05 +00:00
|
|
|
char uuid_str[SWITCH_UUID_FORMATTED_LENGTH + 1];
|
2006-02-26 04:52:34 +00:00
|
|
|
void *private_info;
|
2005-11-19 20:07:43 +00:00
|
|
|
};
|
|
|
|
|
2006-03-01 06:25:56 +00:00
|
|
|
SWITCH_DECLARE_DATA switch_directories SWITCH_GLOBAL_dirs;
|
2006-02-28 21:21:48 +00:00
|
|
|
|
2005-11-19 20:07:43 +00:00
|
|
|
struct switch_core_runtime {
|
|
|
|
time_t initiated;
|
|
|
|
unsigned long session_id;
|
|
|
|
apr_pool_t *memory_pool;
|
|
|
|
switch_hash *session_table;
|
2005-12-21 22:25:22 +00:00
|
|
|
switch_core_db *db;
|
2006-02-07 20:47:15 +00:00
|
|
|
const struct switch_state_handler_table *state_handlers[SWITCH_MAX_STATE_HANDLERS];
|
|
|
|
int state_handler_index;
|
2005-11-19 20:07:43 +00:00
|
|
|
#ifdef EMBED_PERL
|
|
|
|
PerlInterpreter *my_perl;
|
|
|
|
#endif
|
|
|
|
FILE *console;
|
|
|
|
};
|
|
|
|
|
|
|
|
/* Prototypes */
|
2006-01-20 15:05:05 +00:00
|
|
|
static void *SWITCH_THREAD_FUNC switch_core_session_thread(switch_thread *thread, void *obj);
|
2005-11-19 20:07:43 +00:00
|
|
|
static void switch_core_standard_on_init(switch_core_session *session);
|
|
|
|
static void switch_core_standard_on_hangup(switch_core_session *session);
|
|
|
|
static void switch_core_standard_on_ring(switch_core_session *session);
|
|
|
|
static void switch_core_standard_on_execute(switch_core_session *session);
|
|
|
|
static void switch_core_standard_on_loopback(switch_core_session *session);
|
|
|
|
static void switch_core_standard_on_transmit(switch_core_session *session);
|
|
|
|
|
2005-12-21 22:25:22 +00:00
|
|
|
|
2005-11-19 20:07:43 +00:00
|
|
|
/* The main runtime obj we keep this hidden for ourselves */
|
|
|
|
static struct switch_core_runtime runtime;
|
|
|
|
|
2006-01-20 15:05:05 +00:00
|
|
|
static void db_pick_path(char *dbname, char *buf, size_t size)
|
2005-12-21 22:25:22 +00:00
|
|
|
{
|
|
|
|
|
|
|
|
memset(buf, 0, size);
|
|
|
|
if (strchr(dbname, '/')) {
|
|
|
|
strncpy(buf, dbname, size);
|
|
|
|
} else {
|
|
|
|
snprintf(buf, size, "%s/%s.db", SWITCH_DB_DIR, dbname);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-01-20 15:05:05 +00:00
|
|
|
SWITCH_DECLARE(switch_core_db *) switch_core_db_open_file(char *filename)
|
2005-12-21 22:25:22 +00:00
|
|
|
{
|
|
|
|
switch_core_db *db;
|
|
|
|
char path[1024];
|
2006-01-03 01:17:59 +00:00
|
|
|
|
2005-12-21 22:25:22 +00:00
|
|
|
db_pick_path(filename, path, sizeof(path));
|
|
|
|
if (switch_core_db_open(path, &db)) {
|
|
|
|
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "SQL ERR [%s]\n", switch_core_db_errmsg(db));
|
|
|
|
switch_core_db_close(db);
|
2006-01-20 15:05:05 +00:00
|
|
|
db = NULL;
|
2005-12-21 22:25:22 +00:00
|
|
|
}
|
|
|
|
return db;
|
|
|
|
}
|
|
|
|
|
2006-02-28 21:21:48 +00:00
|
|
|
SWITCH_DECLARE(switch_status) switch_core_set_console(char *console)
|
2006-02-24 19:11:49 +00:00
|
|
|
{
|
2006-02-28 21:21:48 +00:00
|
|
|
if ((runtime.console = fopen(console, "a")) == 0) {
|
|
|
|
fprintf(stderr, "Cannot open output file %s.\n", console);
|
|
|
|
return SWITCH_STATUS_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
return SWITCH_STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
SWITCH_DECLARE(FILE *) switch_core_get_console(void)
|
|
|
|
{
|
|
|
|
return runtime.console;
|
2006-02-24 19:11:49 +00:00
|
|
|
}
|
|
|
|
|
2005-11-19 20:07:43 +00:00
|
|
|
SWITCH_DECLARE(FILE *) switch_core_data_channel(switch_text_channel channel)
|
|
|
|
{
|
|
|
|
FILE *handle = stdout;
|
|
|
|
|
|
|
|
switch (channel) {
|
2006-01-06 01:34:10 +00:00
|
|
|
case SWITCH_CHANNEL_ID_CONSOLE:
|
|
|
|
case SWITCH_CHANNEL_ID_CONSOLE_CLEAN:
|
|
|
|
handle = runtime.console;
|
|
|
|
break;
|
|
|
|
default:
|
2006-02-24 19:11:49 +00:00
|
|
|
handle = runtime.console;
|
2006-01-06 01:34:10 +00:00
|
|
|
break;
|
2005-11-19 20:07:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return handle;
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef EMBED_PERL
|
|
|
|
/* test frontend to the perl interpreter */
|
|
|
|
SWITCH_DECLARE(switch_status) switch_core_do_perl(char *txt)
|
|
|
|
{
|
|
|
|
PerlInterpreter *my_perl = runtime.my_perl;
|
|
|
|
eval_pv(txt, TRUE);
|
|
|
|
return SWITCH_STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2006-02-07 20:47:15 +00:00
|
|
|
|
|
|
|
SWITCH_DECLARE(int) switch_core_add_state_handler(const switch_state_handler_table *state_handler)
|
|
|
|
{
|
|
|
|
int index = runtime.state_handler_index++;
|
|
|
|
|
|
|
|
if (runtime.state_handler_index >= SWITCH_MAX_STATE_HANDLERS) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
runtime.state_handlers[index] = state_handler;
|
|
|
|
return index;
|
|
|
|
}
|
|
|
|
|
|
|
|
SWITCH_DECLARE(const switch_state_handler_table *) switch_core_get_state_handler(int index)
|
|
|
|
{
|
|
|
|
|
|
|
|
if (index > SWITCH_MAX_STATE_HANDLERS || index > runtime.state_handler_index) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return runtime.state_handlers[index];
|
|
|
|
}
|
|
|
|
|
2006-01-20 15:05:05 +00:00
|
|
|
SWITCH_DECLARE(switch_status) switch_core_session_message_send(char *uuid_str, switch_core_session_message *message)
|
2006-01-09 19:48:20 +00:00
|
|
|
{
|
|
|
|
switch_core_session *session = NULL;
|
|
|
|
|
2006-02-20 00:23:25 +00:00
|
|
|
if ((session = switch_core_hash_find(runtime.session_table, uuid_str)) != 0) {
|
2006-01-09 19:48:20 +00:00
|
|
|
if (switch_channel_get_state(session->channel) < CS_HANGUP) {
|
|
|
|
return switch_core_session_receive_message(session, message);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return SWITCH_STATUS_FALSE;
|
|
|
|
}
|
2005-11-19 20:07:43 +00:00
|
|
|
|
2005-12-22 01:57:32 +00:00
|
|
|
SWITCH_DECLARE(char *) switch_core_session_get_uuid(switch_core_session *session)
|
|
|
|
{
|
|
|
|
return session->uuid_str;
|
|
|
|
}
|
|
|
|
|
2005-11-19 20:07:43 +00:00
|
|
|
SWITCH_DECLARE(switch_status) switch_core_session_set_read_codec(switch_core_session *session, switch_codec *codec)
|
|
|
|
{
|
|
|
|
assert(session != NULL);
|
|
|
|
|
|
|
|
session->read_codec = codec;
|
|
|
|
return SWITCH_STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2006-01-27 01:46:14 +00:00
|
|
|
SWITCH_DECLARE(switch_codec *) switch_core_session_get_read_codec(switch_core_session *session)
|
|
|
|
{
|
|
|
|
return session->read_codec;
|
|
|
|
}
|
2005-11-19 20:07:43 +00:00
|
|
|
|
|
|
|
SWITCH_DECLARE(switch_status) switch_core_session_set_write_codec(switch_core_session *session, switch_codec *codec)
|
|
|
|
{
|
|
|
|
assert(session != NULL);
|
|
|
|
|
|
|
|
session->write_codec = codec;
|
|
|
|
return SWITCH_STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2006-01-27 01:46:14 +00:00
|
|
|
SWITCH_DECLARE(switch_codec *) switch_core_session_get_write_codec(switch_core_session *session)
|
|
|
|
{
|
|
|
|
return session->write_codec;
|
|
|
|
}
|
|
|
|
|
2006-01-20 15:05:05 +00:00
|
|
|
SWITCH_DECLARE(switch_status) switch_core_codec_init(switch_codec *codec, char *codec_name, int rate, int ms,
|
|
|
|
int channels, switch_codec_flag flags,
|
|
|
|
const switch_codec_settings *codec_settings,
|
|
|
|
switch_memory_pool *pool)
|
2005-11-19 20:07:43 +00:00
|
|
|
{
|
|
|
|
const switch_codec_interface *codec_interface;
|
|
|
|
const switch_codec_implementation *iptr, *implementation = NULL;
|
|
|
|
|
|
|
|
assert(codec != NULL);
|
|
|
|
assert(codec_name != NULL);
|
|
|
|
|
|
|
|
memset(codec, 0, sizeof(*codec));
|
|
|
|
|
2006-02-20 00:23:25 +00:00
|
|
|
if ((codec_interface = switch_loadable_module_get_codec_interface(codec_name)) == 0) {
|
2005-11-19 20:07:43 +00:00
|
|
|
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "invalid codec %s!\n", codec_name);
|
|
|
|
return SWITCH_STATUS_GENERR;
|
|
|
|
}
|
|
|
|
|
2006-01-20 15:05:05 +00:00
|
|
|
for (iptr = codec_interface->implementations; iptr; iptr = iptr->next) {
|
|
|
|
if ((!rate || rate == iptr->samples_per_second) &&
|
|
|
|
(!ms || ms == (iptr->microseconds_per_frame / 1000)) &&
|
2005-12-28 20:06:03 +00:00
|
|
|
(!channels || channels == iptr->number_of_channels)) {
|
2006-01-06 01:34:10 +00:00
|
|
|
implementation = iptr;
|
|
|
|
break;
|
2005-11-19 20:07:43 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (implementation) {
|
2005-12-10 01:14:49 +00:00
|
|
|
switch_status status;
|
2005-11-19 20:07:43 +00:00
|
|
|
codec->codec_interface = codec_interface;
|
|
|
|
codec->implementation = implementation;
|
|
|
|
codec->flags = flags;
|
2005-12-26 21:01:22 +00:00
|
|
|
|
|
|
|
if (pool) {
|
|
|
|
codec->memory_pool = pool;
|
|
|
|
} else {
|
|
|
|
if ((status = switch_core_new_memory_pool(&codec->memory_pool)) != SWITCH_STATUS_SUCCESS) {
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
switch_set_flag(codec, SWITCH_CODEC_FLAG_FREE_POOL);
|
2005-12-10 01:14:49 +00:00
|
|
|
}
|
2005-11-19 20:07:43 +00:00
|
|
|
implementation->init(codec, flags, codec_settings);
|
|
|
|
|
|
|
|
return SWITCH_STATUS_SUCCESS;
|
2005-12-30 17:26:38 +00:00
|
|
|
} else {
|
2006-01-20 15:05:05 +00:00
|
|
|
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Codec %s Exists but not then desired implementation.\n",
|
|
|
|
codec_name);
|
2005-11-19 20:07:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return SWITCH_STATUS_NOTIMPL;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
SWITCH_DECLARE(switch_status) switch_core_codec_encode(switch_codec *codec,
|
2006-01-03 01:17:59 +00:00
|
|
|
switch_codec *other_codec,
|
|
|
|
void *decoded_data,
|
|
|
|
size_t decoded_data_len,
|
|
|
|
int decoded_rate,
|
|
|
|
void *encoded_data,
|
2006-01-20 15:05:05 +00:00
|
|
|
size_t *encoded_data_len, int *encoded_rate, unsigned int *flag)
|
2005-11-19 20:07:43 +00:00
|
|
|
{
|
|
|
|
assert(codec != NULL);
|
|
|
|
assert(encoded_data != NULL);
|
|
|
|
assert(decoded_data != NULL);
|
|
|
|
|
|
|
|
if (!codec->implementation) {
|
|
|
|
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Codec is not initilized!\n");
|
|
|
|
return SWITCH_STATUS_GENERR;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!switch_test_flag(codec, SWITCH_CODEC_FLAG_ENCODE)) {
|
|
|
|
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Codec's encoder is not initilized!\n");
|
|
|
|
return SWITCH_STATUS_GENERR;
|
|
|
|
}
|
|
|
|
|
2006-02-09 17:01:32 +00:00
|
|
|
|
2006-01-06 01:34:10 +00:00
|
|
|
return codec->implementation->encode(codec,
|
|
|
|
other_codec,
|
|
|
|
decoded_data,
|
|
|
|
decoded_data_len,
|
2006-01-20 15:05:05 +00:00
|
|
|
decoded_rate, encoded_data, encoded_data_len, encoded_rate, flag);
|
2006-01-06 01:34:10 +00:00
|
|
|
|
2005-11-19 20:07:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
SWITCH_DECLARE(switch_status) switch_core_codec_decode(switch_codec *codec,
|
2006-01-03 01:17:59 +00:00
|
|
|
switch_codec *other_codec,
|
|
|
|
void *encoded_data,
|
|
|
|
size_t encoded_data_len,
|
|
|
|
int encoded_rate,
|
|
|
|
void *decoded_data,
|
2006-01-20 15:05:05 +00:00
|
|
|
size_t *decoded_data_len, int *decoded_rate, unsigned int *flag)
|
2005-11-19 20:07:43 +00:00
|
|
|
{
|
2006-01-12 21:22:20 +00:00
|
|
|
|
2005-11-19 20:07:43 +00:00
|
|
|
assert(codec != NULL);
|
|
|
|
assert(encoded_data != NULL);
|
|
|
|
assert(decoded_data != NULL);
|
|
|
|
|
2006-02-09 17:01:32 +00:00
|
|
|
|
|
|
|
|
2005-11-19 20:07:43 +00:00
|
|
|
if (!codec->implementation) {
|
|
|
|
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Codec is not initilized!\n");
|
|
|
|
return SWITCH_STATUS_GENERR;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!switch_test_flag(codec, SWITCH_CODEC_FLAG_DECODE)) {
|
|
|
|
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Codec's decoder is not initilized!\n");
|
|
|
|
return SWITCH_STATUS_GENERR;
|
|
|
|
}
|
|
|
|
|
2006-02-09 17:01:32 +00:00
|
|
|
|
2006-01-06 01:34:10 +00:00
|
|
|
return codec->implementation->decode(codec,
|
|
|
|
other_codec,
|
|
|
|
encoded_data,
|
|
|
|
encoded_data_len,
|
2006-01-20 15:05:05 +00:00
|
|
|
encoded_rate, decoded_data, decoded_data_len, decoded_rate, flag);
|
2006-01-06 01:34:10 +00:00
|
|
|
|
2005-11-19 20:07:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
SWITCH_DECLARE(switch_status) switch_core_codec_destroy(switch_codec *codec)
|
|
|
|
{
|
|
|
|
assert(codec != NULL);
|
|
|
|
|
|
|
|
if (!codec->implementation) {
|
|
|
|
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Codec is not initilized!\n");
|
|
|
|
return SWITCH_STATUS_GENERR;
|
|
|
|
}
|
|
|
|
|
|
|
|
codec->implementation->destroy(codec);
|
2005-12-26 21:01:22 +00:00
|
|
|
|
|
|
|
if (switch_test_flag(codec, SWITCH_CODEC_FLAG_FREE_POOL)) {
|
|
|
|
switch_core_destroy_memory_pool(&codec->memory_pool);
|
|
|
|
}
|
|
|
|
|
2005-11-19 20:07:43 +00:00
|
|
|
return SWITCH_STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2006-01-20 15:05:05 +00:00
|
|
|
SWITCH_DECLARE(switch_status) switch_core_file_open(switch_file_handle *fh, char *file_path, unsigned int flags,
|
|
|
|
switch_memory_pool *pool)
|
2005-12-27 18:46:12 +00:00
|
|
|
{
|
|
|
|
char *ext;
|
|
|
|
switch_status status;
|
|
|
|
|
2006-02-20 00:23:25 +00:00
|
|
|
if ((ext = strrchr(file_path, '.')) == 0) {
|
2006-01-03 01:17:59 +00:00
|
|
|
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Invalid Format\n");
|
2005-12-27 18:46:12 +00:00
|
|
|
return SWITCH_STATUS_FALSE;
|
|
|
|
}
|
|
|
|
ext++;
|
|
|
|
|
2006-02-20 00:23:25 +00:00
|
|
|
if ((fh->file_interface = switch_loadable_module_get_file_interface(ext)) == 0) {
|
2005-12-27 18:46:12 +00:00
|
|
|
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "invalid file format [%s]!\n", ext);
|
|
|
|
return SWITCH_STATUS_GENERR;
|
|
|
|
}
|
2006-01-03 01:17:59 +00:00
|
|
|
|
2005-12-27 18:46:12 +00:00
|
|
|
fh->flags = flags;
|
|
|
|
if (pool) {
|
|
|
|
fh->memory_pool = pool;
|
|
|
|
} else {
|
|
|
|
if ((status = switch_core_new_memory_pool(&fh->memory_pool)) != SWITCH_STATUS_SUCCESS) {
|
2006-01-03 01:17:59 +00:00
|
|
|
return status;
|
|
|
|
}
|
2006-01-27 16:43:57 +00:00
|
|
|
switch_set_flag(fh, SWITCH_FILE_FLAG_FREE_POOL);
|
2005-12-27 18:46:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return fh->file_interface->file_open(fh, file_path);
|
|
|
|
}
|
|
|
|
|
|
|
|
SWITCH_DECLARE(switch_status) switch_core_file_read(switch_file_handle *fh, void *data, size_t *len)
|
|
|
|
{
|
|
|
|
assert(fh != NULL);
|
2006-01-03 01:17:59 +00:00
|
|
|
|
2006-02-20 06:13:56 +00:00
|
|
|
return fh->file_interface->file_read(fh, data, len);
|
2005-12-27 18:46:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
SWITCH_DECLARE(switch_status) switch_core_file_write(switch_file_handle *fh, void *data, size_t *len)
|
|
|
|
{
|
|
|
|
assert(fh != NULL);
|
2006-01-03 01:17:59 +00:00
|
|
|
|
2006-02-20 06:13:56 +00:00
|
|
|
return fh->file_interface->file_write(fh, data, len);
|
2005-12-27 18:46:12 +00:00
|
|
|
}
|
|
|
|
|
2006-02-28 02:08:42 +00:00
|
|
|
SWITCH_DECLARE(switch_status) switch_core_file_seek(switch_file_handle *fh, unsigned int *cur_pos, int64_t samples,
|
2006-01-20 15:05:05 +00:00
|
|
|
int whence)
|
2005-12-27 18:46:12 +00:00
|
|
|
{
|
|
|
|
return fh->file_interface->file_seek(fh, cur_pos, samples, whence);
|
|
|
|
}
|
|
|
|
|
|
|
|
SWITCH_DECLARE(switch_status) switch_core_file_close(switch_file_handle *fh)
|
|
|
|
{
|
|
|
|
return fh->file_interface->file_close(fh);
|
|
|
|
}
|
|
|
|
|
2006-02-09 16:28:49 +00:00
|
|
|
SWITCH_DECLARE(switch_status) switch_core_directory_open(switch_directory_handle *dh,
|
|
|
|
char *module_name,
|
|
|
|
char *source,
|
|
|
|
char *dsn,
|
|
|
|
char *passwd,
|
|
|
|
switch_memory_pool *pool)
|
|
|
|
{
|
|
|
|
switch_status status;
|
|
|
|
|
2006-02-20 00:23:25 +00:00
|
|
|
if ((dh->directory_interface = switch_loadable_module_get_directory_interface(module_name)) == 0) {
|
2006-02-09 16:28:49 +00:00
|
|
|
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "invalid directory module [%s]!\n", module_name);
|
|
|
|
return SWITCH_STATUS_GENERR;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (pool) {
|
|
|
|
dh->memory_pool = pool;
|
|
|
|
} else {
|
|
|
|
if ((status = switch_core_new_memory_pool(&dh->memory_pool)) != SWITCH_STATUS_SUCCESS) {
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
switch_set_flag(dh, SWITCH_DIRECTORY_FLAG_FREE_POOL);
|
|
|
|
}
|
|
|
|
|
|
|
|
return dh->directory_interface->directory_open(dh, source, dsn, passwd);
|
|
|
|
}
|
|
|
|
|
2006-02-09 22:37:44 +00:00
|
|
|
SWITCH_DECLARE(switch_status) switch_core_directory_query(switch_directory_handle *dh, char *base, char *query)
|
2006-02-09 16:28:49 +00:00
|
|
|
{
|
2006-02-09 22:37:44 +00:00
|
|
|
return dh->directory_interface->directory_query(dh, base, query);
|
2006-02-09 16:28:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
SWITCH_DECLARE(switch_status) switch_core_directory_next(switch_directory_handle *dh)
|
|
|
|
{
|
|
|
|
return dh->directory_interface->directory_next(dh);
|
|
|
|
}
|
|
|
|
|
|
|
|
SWITCH_DECLARE(switch_status) switch_core_directory_next_pair(switch_directory_handle *dh, char **var, char **val)
|
|
|
|
{
|
|
|
|
return dh->directory_interface->directory_next_pair(dh, var, val);
|
|
|
|
}
|
|
|
|
|
|
|
|
SWITCH_DECLARE(switch_status) switch_core_directory_close(switch_directory_handle *dh)
|
|
|
|
{
|
|
|
|
return dh->directory_interface->directory_close(dh);
|
|
|
|
}
|
|
|
|
|
2006-01-27 16:43:57 +00:00
|
|
|
SWITCH_DECLARE(switch_status) switch_core_speech_open(switch_speech_handle *sh,
|
|
|
|
char *module_name,
|
2006-02-26 20:23:23 +00:00
|
|
|
char *voice_name,
|
2006-02-28 05:55:22 +00:00
|
|
|
unsigned int rate,
|
2006-02-27 04:33:58 +00:00
|
|
|
switch_speech_flag flags,
|
2006-01-27 16:43:57 +00:00
|
|
|
switch_memory_pool *pool)
|
|
|
|
{
|
|
|
|
switch_status status;
|
|
|
|
|
2006-02-20 00:23:25 +00:00
|
|
|
if ((sh->speech_interface = switch_loadable_module_get_speech_interface(module_name)) == 0) {
|
2006-01-27 16:43:57 +00:00
|
|
|
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "invalid speech module [%s]!\n", module_name);
|
|
|
|
return SWITCH_STATUS_GENERR;
|
|
|
|
}
|
|
|
|
|
|
|
|
sh->flags = flags;
|
|
|
|
if (pool) {
|
|
|
|
sh->memory_pool = pool;
|
|
|
|
} else {
|
|
|
|
if ((status = switch_core_new_memory_pool(&sh->memory_pool)) != SWITCH_STATUS_SUCCESS) {
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
switch_set_flag(sh, SWITCH_SPEECH_FLAG_FREE_POOL);
|
|
|
|
}
|
|
|
|
|
2006-02-26 20:23:23 +00:00
|
|
|
return sh->speech_interface->speech_open(sh, voice_name, rate, flags);
|
2006-01-27 16:43:57 +00:00
|
|
|
}
|
|
|
|
|
2006-02-27 04:33:58 +00:00
|
|
|
SWITCH_DECLARE(switch_status) switch_core_speech_feed_asr(switch_speech_handle *sh, void *data, unsigned int *len, int rate, switch_speech_flag *flags)
|
2006-01-27 16:43:57 +00:00
|
|
|
{
|
|
|
|
assert(sh != NULL);
|
|
|
|
|
|
|
|
return sh->speech_interface->speech_feed_asr(sh, data, len, rate, flags);
|
|
|
|
}
|
|
|
|
|
2006-02-27 04:33:58 +00:00
|
|
|
SWITCH_DECLARE(switch_status) switch_core_speech_interpret_asr(switch_speech_handle *sh, char *buf, unsigned int buflen, switch_speech_flag *flags)
|
2006-01-27 16:43:57 +00:00
|
|
|
{
|
|
|
|
assert(sh != NULL);
|
|
|
|
|
|
|
|
return sh->speech_interface->speech_interpret_asr(sh, buf, buflen, flags);
|
|
|
|
}
|
|
|
|
|
2006-02-27 04:01:38 +00:00
|
|
|
SWITCH_DECLARE(switch_status) switch_core_speech_feed_tts(switch_speech_handle *sh, char *text, switch_speech_flag *flags)
|
2006-01-27 16:43:57 +00:00
|
|
|
{
|
|
|
|
assert(sh != NULL);
|
|
|
|
|
|
|
|
return sh->speech_interface->speech_feed_tts(sh, text, flags);
|
|
|
|
}
|
|
|
|
|
|
|
|
SWITCH_DECLARE(switch_status) switch_core_speech_read_tts(switch_speech_handle *sh,
|
|
|
|
void *data,
|
2006-02-27 04:48:51 +00:00
|
|
|
size_t *datalen,
|
|
|
|
size_t *rate,
|
2006-02-27 04:01:38 +00:00
|
|
|
switch_speech_flag *flags)
|
2006-01-27 16:43:57 +00:00
|
|
|
{
|
|
|
|
assert(sh != NULL);
|
|
|
|
|
|
|
|
return sh->speech_interface->speech_read_tts(sh, data, datalen, rate, flags);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-02-27 04:01:38 +00:00
|
|
|
SWITCH_DECLARE(switch_status) switch_core_speech_close(switch_speech_handle *sh, switch_speech_flag *flags)
|
2006-01-27 16:43:57 +00:00
|
|
|
{
|
2006-02-21 15:05:18 +00:00
|
|
|
return sh->speech_interface->speech_close(sh, flags);
|
2006-01-27 16:43:57 +00:00
|
|
|
}
|
2005-12-27 18:46:12 +00:00
|
|
|
|
2006-01-20 15:05:05 +00:00
|
|
|
SWITCH_DECLARE(switch_status) switch_core_timer_init(switch_timer *timer, char *timer_name, int interval, int samples,
|
|
|
|
switch_memory_pool *pool)
|
2005-11-19 20:07:43 +00:00
|
|
|
{
|
|
|
|
switch_timer_interface *timer_interface;
|
2005-12-10 01:14:49 +00:00
|
|
|
switch_status status;
|
2005-11-19 20:07:43 +00:00
|
|
|
memset(timer, 0, sizeof(*timer));
|
2006-02-20 00:23:25 +00:00
|
|
|
if ((timer_interface = switch_loadable_module_get_timer_interface(timer_name)) == 0) {
|
2005-11-19 20:07:43 +00:00
|
|
|
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "invalid timer %s!\n", timer_name);
|
|
|
|
return SWITCH_STATUS_GENERR;
|
|
|
|
}
|
|
|
|
|
|
|
|
timer->interval = interval;
|
|
|
|
timer->samples = samples;
|
|
|
|
timer->samplecount = 0;
|
|
|
|
timer->timer_interface = timer_interface;
|
2005-12-26 21:01:22 +00:00
|
|
|
|
|
|
|
if (pool) {
|
|
|
|
timer->memory_pool = pool;
|
|
|
|
} else {
|
|
|
|
if ((status = switch_core_new_memory_pool(&timer->memory_pool)) != SWITCH_STATUS_SUCCESS) {
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
switch_set_flag(timer, SWITCH_TIMER_FLAG_FREE_POOL);
|
2005-12-10 01:14:49 +00:00
|
|
|
}
|
2005-11-19 20:07:43 +00:00
|
|
|
|
|
|
|
timer->timer_interface->timer_init(timer);
|
|
|
|
return SWITCH_STATUS_SUCCESS;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
SWITCH_DECLARE(int) switch_core_timer_next(switch_timer *timer)
|
|
|
|
{
|
|
|
|
if (!timer->timer_interface) {
|
|
|
|
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Timer is not initilized!\n");
|
|
|
|
return SWITCH_STATUS_GENERR;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (timer->timer_interface->timer_next(timer) == SWITCH_STATUS_SUCCESS) {
|
|
|
|
return timer->samplecount;
|
|
|
|
} else {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
SWITCH_DECLARE(switch_status) switch_core_timer_destroy(switch_timer *timer)
|
|
|
|
{
|
|
|
|
if (!timer->timer_interface) {
|
|
|
|
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Timer is not initilized!\n");
|
|
|
|
return SWITCH_STATUS_GENERR;
|
|
|
|
}
|
|
|
|
|
|
|
|
timer->timer_interface->timer_destroy(timer);
|
2005-12-26 21:01:22 +00:00
|
|
|
|
|
|
|
if (switch_test_flag(timer, SWITCH_TIMER_FLAG_FREE_POOL)) {
|
|
|
|
switch_core_destroy_memory_pool(&timer->memory_pool);
|
|
|
|
}
|
|
|
|
|
2005-11-19 20:07:43 +00:00
|
|
|
return SWITCH_STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void *switch_core_service_thread(switch_thread *thread, void *obj)
|
|
|
|
{
|
|
|
|
switch_core_thread_session *data = obj;
|
|
|
|
switch_core_session *session = data->objs[0];
|
2006-01-09 19:48:20 +00:00
|
|
|
int *stream_id_p = data->objs[1];
|
2005-11-19 20:07:43 +00:00
|
|
|
switch_channel *channel;
|
|
|
|
switch_frame *read_frame;
|
2006-01-09 19:48:20 +00:00
|
|
|
int stream_id = *stream_id_p;
|
2005-11-19 20:07:43 +00:00
|
|
|
|
|
|
|
assert(session != NULL);
|
|
|
|
channel = switch_core_session_get_channel(session);
|
|
|
|
assert(channel != NULL);
|
|
|
|
|
2006-01-20 15:05:05 +00:00
|
|
|
while (data->running > 0) {
|
|
|
|
switch (switch_core_session_read_frame(session, &read_frame, -1, stream_id)) {
|
2006-01-06 01:34:10 +00:00
|
|
|
case SWITCH_STATUS_SUCCESS:
|
|
|
|
break;
|
|
|
|
case SWITCH_STATUS_TIMEOUT:
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
data->running = -1;
|
|
|
|
continue;
|
|
|
|
break;
|
2005-11-19 20:07:43 +00:00
|
|
|
}
|
|
|
|
|
2006-01-13 02:05:39 +00:00
|
|
|
switch_yield(10000);
|
2005-11-19 20:07:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
data->running = 0;
|
|
|
|
return NULL;
|
|
|
|
}
|
2006-02-22 22:36:52 +00:00
|
|
|
|
2005-11-19 20:07:43 +00:00
|
|
|
/* Either add a timeout here or make damn sure the thread cannot get hung somehow (my preference) */
|
|
|
|
SWITCH_DECLARE(void) switch_core_thread_session_end(switch_core_thread_session *thread_session)
|
|
|
|
{
|
|
|
|
if (thread_session->running > 0) {
|
|
|
|
thread_session->running = -1;
|
|
|
|
|
2006-01-20 15:05:05 +00:00
|
|
|
while (thread_session->running) {
|
2005-11-19 20:07:43 +00:00
|
|
|
switch_yield(1000);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-01-20 15:05:05 +00:00
|
|
|
SWITCH_DECLARE(void) switch_core_service_session(switch_core_session *session,
|
|
|
|
switch_core_thread_session *thread_session, int stream_id)
|
2005-11-19 20:07:43 +00:00
|
|
|
{
|
|
|
|
thread_session->running = 1;
|
|
|
|
thread_session->objs[0] = session;
|
2006-01-09 18:40:56 +00:00
|
|
|
thread_session->objs[1] = &stream_id;
|
2005-11-19 20:07:43 +00:00
|
|
|
switch_core_session_launch_thread(session, switch_core_service_thread, thread_session);
|
|
|
|
}
|
|
|
|
|
|
|
|
SWITCH_DECLARE(switch_memory_pool *) switch_core_session_get_pool(switch_core_session *session)
|
|
|
|
{
|
|
|
|
return session->pool;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* **ONLY** alloc things with this function that **WILL NOT** outlive
|
2006-01-06 01:34:10 +00:00
|
|
|
the session itself or expect an earth shattering KABOOM!*/
|
2006-01-20 15:05:05 +00:00
|
|
|
SWITCH_DECLARE(void *) switch_core_session_alloc(switch_core_session *session, size_t memory)
|
2005-11-19 20:07:43 +00:00
|
|
|
{
|
|
|
|
void *ptr = NULL;
|
|
|
|
assert(session != NULL);
|
|
|
|
assert(session->pool != NULL);
|
|
|
|
|
2006-02-20 00:23:25 +00:00
|
|
|
if ((ptr = apr_palloc(session->pool, memory)) != 0) {
|
2005-11-19 20:07:43 +00:00
|
|
|
memset(ptr, 0, memory);
|
|
|
|
}
|
|
|
|
return ptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* **ONLY** alloc things with these functions that **WILL NOT** need
|
2006-01-06 01:34:10 +00:00
|
|
|
to be freed *EVER* ie this is for *PERMENANT* memory allocation */
|
2005-11-19 20:07:43 +00:00
|
|
|
|
|
|
|
SWITCH_DECLARE(void *) switch_core_permenant_alloc(size_t memory)
|
|
|
|
{
|
|
|
|
void *ptr = NULL;
|
|
|
|
assert(runtime.memory_pool != NULL);
|
|
|
|
|
2006-02-20 00:23:25 +00:00
|
|
|
if ((ptr = apr_palloc(runtime.memory_pool, memory)) != 0) {
|
2005-11-19 20:07:43 +00:00
|
|
|
memset(ptr, 0, memory);
|
|
|
|
}
|
|
|
|
return ptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
SWITCH_DECLARE(char *) switch_core_permenant_strdup(char *todup)
|
|
|
|
{
|
|
|
|
char *duped = NULL;
|
2005-12-28 07:01:21 +00:00
|
|
|
size_t len;
|
2005-11-19 20:07:43 +00:00
|
|
|
|
|
|
|
assert(runtime.memory_pool != NULL);
|
|
|
|
|
2006-01-20 15:05:05 +00:00
|
|
|
if (!todup)
|
|
|
|
return NULL;
|
2005-12-28 17:11:47 +00:00
|
|
|
|
2005-12-28 05:17:21 +00:00
|
|
|
len = strlen(todup) + 1;
|
2006-02-20 00:23:25 +00:00
|
|
|
if (todup && (duped = apr_palloc(runtime.memory_pool, len)) != 0) {
|
2005-12-28 05:17:21 +00:00
|
|
|
strncpy(duped, todup, len);
|
2005-11-19 20:07:43 +00:00
|
|
|
}
|
|
|
|
return duped;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
SWITCH_DECLARE(char *) switch_core_session_strdup(switch_core_session *session, char *todup)
|
|
|
|
{
|
|
|
|
char *duped = NULL;
|
2005-12-28 07:01:21 +00:00
|
|
|
size_t len;
|
2005-11-19 20:07:43 +00:00
|
|
|
assert(session != NULL);
|
|
|
|
assert(session->pool != NULL);
|
|
|
|
|
2006-03-01 22:55:28 +00:00
|
|
|
if (!todup) {
|
2006-01-20 15:05:05 +00:00
|
|
|
return NULL;
|
2006-03-01 22:55:28 +00:00
|
|
|
}
|
2005-12-28 05:17:21 +00:00
|
|
|
len = strlen(todup) + 1;
|
|
|
|
|
2006-02-20 00:23:25 +00:00
|
|
|
if (todup && (duped = apr_palloc(session->pool, len)) != 0) {
|
2005-12-28 05:17:21 +00:00
|
|
|
strncpy(duped, todup, len);
|
2005-11-19 20:07:43 +00:00
|
|
|
}
|
|
|
|
return duped;
|
|
|
|
}
|
|
|
|
|
2005-12-13 19:53:29 +00:00
|
|
|
|
|
|
|
SWITCH_DECLARE(char *) switch_core_strdup(switch_memory_pool *pool, char *todup)
|
|
|
|
{
|
|
|
|
char *duped = NULL;
|
2005-12-28 07:01:21 +00:00
|
|
|
size_t len;
|
2005-12-13 19:53:29 +00:00
|
|
|
assert(pool != NULL);
|
|
|
|
|
2006-03-01 22:55:28 +00:00
|
|
|
if (!todup) {
|
2006-01-20 15:05:05 +00:00
|
|
|
return NULL;
|
2006-03-01 22:55:28 +00:00
|
|
|
}
|
|
|
|
|
2005-12-28 05:17:21 +00:00
|
|
|
len = strlen(todup) + 1;
|
|
|
|
|
2006-02-20 00:23:25 +00:00
|
|
|
if (todup && (duped = apr_palloc(pool, len)) != 0) {
|
2005-12-28 05:17:21 +00:00
|
|
|
strncpy(duped, todup, len);
|
2005-12-13 19:53:29 +00:00
|
|
|
}
|
|
|
|
return duped;
|
|
|
|
}
|
|
|
|
|
2005-11-19 20:07:43 +00:00
|
|
|
SWITCH_DECLARE(void *) switch_core_session_get_private(switch_core_session *session)
|
|
|
|
{
|
|
|
|
assert(session != NULL);
|
2006-02-26 04:52:34 +00:00
|
|
|
return session->private_info;
|
2005-11-19 20:07:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-02-26 04:52:34 +00:00
|
|
|
SWITCH_DECLARE(switch_status) switch_core_session_set_private(switch_core_session *session, void *private_info)
|
2005-11-19 20:07:43 +00:00
|
|
|
{
|
|
|
|
assert(session != NULL);
|
2006-02-26 04:52:34 +00:00
|
|
|
session->private_info = private_info;
|
2005-11-19 20:07:43 +00:00
|
|
|
return SWITCH_STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2006-02-26 04:52:34 +00:00
|
|
|
SWITCH_DECLARE(int) switch_core_session_add_stream(switch_core_session *session, void *private_info)
|
2006-01-09 18:40:56 +00:00
|
|
|
{
|
2006-02-26 04:52:34 +00:00
|
|
|
session->streams[session->stream_count++] = private_info;
|
2006-01-09 18:40:56 +00:00
|
|
|
return session->stream_count - 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
SWITCH_DECLARE(void *) switch_core_session_get_stream(switch_core_session *session, int index)
|
|
|
|
{
|
|
|
|
return session->streams[index];
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
SWITCH_DECLARE(int) switch_core_session_get_stream_count(switch_core_session *session)
|
|
|
|
{
|
|
|
|
return session->stream_count;
|
|
|
|
}
|
|
|
|
|
2005-11-19 20:07:43 +00:00
|
|
|
SWITCH_DECLARE(switch_status) switch_core_session_outgoing_channel(switch_core_session *session,
|
2006-01-03 01:17:59 +00:00
|
|
|
char *endpoint_name,
|
|
|
|
switch_caller_profile *caller_profile,
|
2006-03-02 14:49:23 +00:00
|
|
|
switch_core_session **new_session,
|
2006-03-02 20:35:15 +00:00
|
|
|
switch_memory_pool *pool)
|
2005-11-19 20:07:43 +00:00
|
|
|
{
|
|
|
|
struct switch_io_event_hook_outgoing_channel *ptr;
|
|
|
|
switch_status status = SWITCH_STATUS_FALSE;
|
|
|
|
const switch_endpoint_interface *endpoint_interface;
|
|
|
|
|
2006-02-20 00:23:25 +00:00
|
|
|
if ((endpoint_interface = switch_loadable_module_get_endpoint_interface(endpoint_name)) == 0) {
|
2005-11-19 20:07:43 +00:00
|
|
|
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Could not locate channel type %s\n", endpoint_name);
|
|
|
|
return SWITCH_STATUS_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (endpoint_interface->io_routines->outgoing_channel) {
|
2006-01-20 15:05:05 +00:00
|
|
|
if ((status =
|
|
|
|
endpoint_interface->io_routines->outgoing_channel(session, caller_profile,
|
2006-03-02 20:35:15 +00:00
|
|
|
new_session, pool)) == SWITCH_STATUS_SUCCESS) {
|
2006-03-01 22:55:28 +00:00
|
|
|
if (session) {
|
|
|
|
for (ptr = session->event_hooks.outgoing_channel; ptr; ptr = ptr->next) {
|
|
|
|
if ((status = ptr->outgoing_channel(session, caller_profile, *new_session)) != SWITCH_STATUS_SUCCESS) {
|
|
|
|
break;
|
|
|
|
}
|
2005-11-19 20:07:43 +00:00
|
|
|
}
|
|
|
|
}
|
2006-02-24 16:47:22 +00:00
|
|
|
} else {
|
|
|
|
return status;
|
2005-11-19 20:07:43 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-12-26 19:09:59 +00:00
|
|
|
if (*new_session) {
|
|
|
|
switch_caller_profile *profile = NULL, *peer_profile = NULL, *cloned_profile = NULL;
|
|
|
|
switch_channel *channel = NULL, *peer_channel = NULL;
|
|
|
|
|
2006-03-01 22:55:28 +00:00
|
|
|
if (session && (channel = switch_core_session_get_channel(session)) != 0) {
|
2005-12-26 19:09:59 +00:00
|
|
|
profile = switch_channel_get_caller_profile(channel);
|
|
|
|
}
|
2006-02-20 00:23:25 +00:00
|
|
|
if ((peer_channel = switch_core_session_get_channel(*new_session)) != 0) {
|
2005-12-26 19:09:59 +00:00
|
|
|
peer_profile = switch_channel_get_caller_profile(peer_channel);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (channel && peer_channel) {
|
|
|
|
if (profile) {
|
2006-02-20 00:23:25 +00:00
|
|
|
if ((cloned_profile = switch_caller_profile_clone(*new_session, profile)) != 0) {
|
2005-12-26 19:09:59 +00:00
|
|
|
switch_channel_set_originator_caller_profile(peer_channel, cloned_profile);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (peer_profile) {
|
2006-03-01 22:55:28 +00:00
|
|
|
if (session && (cloned_profile = switch_caller_profile_clone(session, peer_profile)) != 0) {
|
2005-12-26 19:09:59 +00:00
|
|
|
switch_channel_set_originatee_caller_profile(channel, cloned_profile);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-11-19 20:07:43 +00:00
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
|
|
|
SWITCH_DECLARE(switch_status) switch_core_session_answer_channel(switch_core_session *session)
|
|
|
|
{
|
|
|
|
struct switch_io_event_hook_answer_channel *ptr;
|
|
|
|
switch_status status = SWITCH_STATUS_FALSE;
|
|
|
|
|
|
|
|
assert(session != NULL);
|
|
|
|
if (session->endpoint_interface->io_routines->answer_channel) {
|
|
|
|
if ((status = session->endpoint_interface->io_routines->answer_channel(session)) == SWITCH_STATUS_SUCCESS) {
|
2006-01-20 15:05:05 +00:00
|
|
|
for (ptr = session->event_hooks.answer_channel; ptr; ptr = ptr->next) {
|
2005-11-19 20:07:43 +00:00
|
|
|
if ((status = ptr->answer_channel(session)) != SWITCH_STATUS_SUCCESS) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
status = SWITCH_STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
2006-01-20 15:05:05 +00:00
|
|
|
SWITCH_DECLARE(switch_status) switch_core_session_receive_message(switch_core_session *session,
|
|
|
|
switch_core_session_message *message)
|
2006-01-09 19:48:20 +00:00
|
|
|
{
|
|
|
|
struct switch_io_event_hook_receive_message *ptr;
|
|
|
|
switch_status status = SWITCH_STATUS_FALSE;
|
|
|
|
|
|
|
|
assert(session != NULL);
|
|
|
|
if (session->endpoint_interface->io_routines->receive_message) {
|
2006-01-20 15:05:05 +00:00
|
|
|
if ((status =
|
|
|
|
session->endpoint_interface->io_routines->receive_message(session, message)) == SWITCH_STATUS_SUCCESS) {
|
|
|
|
for (ptr = session->event_hooks.receive_message; ptr; ptr = ptr->next) {
|
2006-01-09 19:48:20 +00:00
|
|
|
if ((status = ptr->receive_message(session, message)) != SWITCH_STATUS_SUCCESS) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
status = SWITCH_STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
2006-01-20 15:05:05 +00:00
|
|
|
SWITCH_DECLARE(switch_status) switch_core_session_read_frame(switch_core_session *session, switch_frame **frame,
|
|
|
|
int timeout, int stream_id)
|
2005-11-19 20:07:43 +00:00
|
|
|
{
|
|
|
|
struct switch_io_event_hook_read_frame *ptr;
|
|
|
|
switch_status status = SWITCH_STATUS_FALSE;
|
|
|
|
int need_codec = 0, perfect = 0;
|
|
|
|
|
|
|
|
|
|
|
|
if (session->endpoint_interface->io_routines->read_frame) {
|
2006-01-09 18:40:56 +00:00
|
|
|
if ((status = session->endpoint_interface->io_routines->read_frame(session,
|
|
|
|
frame,
|
|
|
|
timeout,
|
|
|
|
SWITCH_IO_FLAG_NOOP,
|
|
|
|
stream_id)) == SWITCH_STATUS_SUCCESS) {
|
2006-01-20 15:05:05 +00:00
|
|
|
for (ptr = session->event_hooks.read_frame; ptr; ptr = ptr->next) {
|
|
|
|
if ((status =
|
|
|
|
ptr->read_frame(session, frame, timeout, SWITCH_IO_FLAG_NOOP,
|
|
|
|
stream_id)) != SWITCH_STATUS_SUCCESS) {
|
2005-11-19 20:07:43 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (status != SWITCH_STATUS_SUCCESS || !(*frame)) {
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* if you think this code is redundant.... too bad! I like to understand what I'm doing */
|
2006-01-20 15:05:05 +00:00
|
|
|
if ((session->read_codec && (*frame)->codec
|
|
|
|
&& session->read_codec->implementation != (*frame)->codec->implementation)) {
|
2005-11-19 20:07:43 +00:00
|
|
|
need_codec = TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (session->read_codec && !(*frame)->codec) {
|
|
|
|
need_codec = TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!session->read_codec && (*frame)->codec) {
|
|
|
|
need_codec = TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (status == SWITCH_STATUS_SUCCESS && need_codec) {
|
|
|
|
switch_frame *enc_frame, *read_frame = *frame;
|
|
|
|
|
2006-01-02 17:28:59 +00:00
|
|
|
if (read_frame->codec) {
|
2005-12-13 21:04:03 +00:00
|
|
|
unsigned int flag = 0;
|
2005-12-12 17:50:07 +00:00
|
|
|
session->raw_read_frame.datalen = session->raw_read_frame.buflen;
|
2005-11-19 20:07:43 +00:00
|
|
|
status = switch_core_codec_decode(read_frame->codec,
|
2006-01-06 01:34:10 +00:00
|
|
|
session->read_codec,
|
|
|
|
read_frame->data,
|
|
|
|
read_frame->datalen,
|
|
|
|
session->read_codec->implementation->samples_per_second,
|
|
|
|
session->raw_read_frame.data,
|
2006-01-20 15:05:05 +00:00
|
|
|
&session->raw_read_frame.datalen, &session->raw_read_frame.rate, &flag);
|
2005-11-19 20:07:43 +00:00
|
|
|
|
|
|
|
switch (status) {
|
2006-01-06 01:34:10 +00:00
|
|
|
case SWITCH_STATUS_RESAMPLE:
|
|
|
|
if (!session->read_resampler) {
|
|
|
|
switch_resample_create(&session->read_resampler,
|
|
|
|
read_frame->codec->implementation->samples_per_second,
|
2006-01-12 18:27:20 +00:00
|
|
|
read_frame->codec->implementation->bytes_per_frame * 20,
|
2006-01-06 01:34:10 +00:00
|
|
|
session->read_codec->implementation->samples_per_second,
|
2006-01-20 15:05:05 +00:00
|
|
|
session->read_codec->implementation->bytes_per_frame * 20, session->pool);
|
2006-01-06 01:34:10 +00:00
|
|
|
}
|
|
|
|
case SWITCH_STATUS_SUCCESS:
|
|
|
|
read_frame = &session->raw_read_frame;
|
|
|
|
break;
|
|
|
|
case SWITCH_STATUS_NOOP:
|
|
|
|
status = SWITCH_STATUS_SUCCESS;
|
|
|
|
break;
|
|
|
|
default:
|
2006-01-20 15:05:05 +00:00
|
|
|
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Codec %s decoder error!\n",
|
|
|
|
session->read_codec->codec_interface->interface_name);
|
2006-01-06 01:34:10 +00:00
|
|
|
return status;
|
|
|
|
break;
|
2005-11-19 20:07:43 +00:00
|
|
|
}
|
|
|
|
}
|
2006-01-02 17:28:59 +00:00
|
|
|
if (session->read_resampler) {
|
|
|
|
short *data = read_frame->data;
|
|
|
|
|
2006-01-20 15:05:05 +00:00
|
|
|
session->read_resampler->from_len =
|
|
|
|
switch_short_to_float(data, session->read_resampler->from, (int) read_frame->datalen / 2);
|
|
|
|
session->read_resampler->to_len =
|
|
|
|
switch_resample_process(session->read_resampler, session->read_resampler->from,
|
|
|
|
session->read_resampler->from_len, session->read_resampler->to,
|
|
|
|
(int) session->read_resampler->to_size, 0);
|
2006-01-02 17:28:59 +00:00
|
|
|
switch_float_to_short(session->read_resampler->to, data, read_frame->datalen);
|
|
|
|
read_frame->samples = session->read_resampler->to_len;
|
|
|
|
read_frame->datalen = session->read_resampler->to_len * 2;
|
|
|
|
read_frame->rate = session->read_resampler->to_rate;
|
|
|
|
}
|
2005-11-19 20:07:43 +00:00
|
|
|
|
|
|
|
if (session->read_codec) {
|
|
|
|
if ((*frame)->datalen == session->read_codec->implementation->bytes_per_frame) {
|
|
|
|
perfect = TRUE;
|
|
|
|
} else {
|
2006-01-20 15:05:05 +00:00
|
|
|
if (!session->raw_read_buffer) {
|
2006-02-20 00:23:25 +00:00
|
|
|
size_t bytes = session->read_codec->implementation->bytes_per_frame * 10;
|
2005-11-19 20:07:43 +00:00
|
|
|
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Engaging Read Buffer at %d bytes\n", bytes);
|
|
|
|
switch_buffer_create(session->pool, &session->raw_read_buffer, bytes);
|
|
|
|
}
|
|
|
|
if (!switch_buffer_write(session->raw_read_buffer, read_frame->data, read_frame->datalen)) {
|
|
|
|
return SWITCH_STATUS_MEMERR;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (switch_buffer_inuse(session->raw_read_buffer) >= session->read_codec->implementation->bytes_per_frame) {
|
|
|
|
unsigned int flag = 0;
|
|
|
|
|
|
|
|
if (perfect) {
|
|
|
|
enc_frame = *frame;
|
2006-01-06 01:34:10 +00:00
|
|
|
session->raw_read_frame.rate = (*frame)->rate;
|
2005-11-19 20:07:43 +00:00
|
|
|
} else {
|
|
|
|
session->raw_read_frame.datalen = switch_buffer_read(session->raw_read_buffer,
|
2006-01-06 01:34:10 +00:00
|
|
|
session->raw_read_frame.data,
|
2006-01-20 15:05:05 +00:00
|
|
|
session->read_codec->implementation->
|
|
|
|
bytes_per_frame);
|
2005-12-30 00:00:21 +00:00
|
|
|
session->raw_read_frame.rate = session->read_codec->implementation->samples_per_second;
|
2005-11-19 20:07:43 +00:00
|
|
|
enc_frame = &session->raw_read_frame;
|
|
|
|
}
|
2005-12-12 17:50:07 +00:00
|
|
|
session->enc_read_frame.datalen = session->enc_read_frame.buflen;
|
2005-11-19 20:07:43 +00:00
|
|
|
status = switch_core_codec_encode(session->read_codec,
|
2006-01-06 01:34:10 +00:00
|
|
|
(*frame)->codec,
|
|
|
|
session->raw_read_frame.data,
|
|
|
|
session->raw_read_frame.datalen,
|
|
|
|
(*frame)->codec->implementation->samples_per_second,
|
|
|
|
session->enc_read_frame.data,
|
|
|
|
&session->enc_read_frame.datalen,
|
2006-01-20 15:05:05 +00:00
|
|
|
&session->enc_read_frame.rate, &flag);
|
2005-11-19 20:07:43 +00:00
|
|
|
|
|
|
|
|
|
|
|
switch (status) {
|
2006-01-06 01:34:10 +00:00
|
|
|
case SWITCH_STATUS_RESAMPLE:
|
|
|
|
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "fixme 1\n");
|
|
|
|
case SWITCH_STATUS_SUCCESS:
|
|
|
|
*frame = &session->enc_read_frame;
|
|
|
|
break;
|
|
|
|
case SWITCH_STATUS_NOOP:
|
|
|
|
*frame = &session->raw_read_frame;
|
|
|
|
status = SWITCH_STATUS_SUCCESS;
|
|
|
|
break;
|
|
|
|
default:
|
2006-01-20 15:05:05 +00:00
|
|
|
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Codec %s encoder error!\n",
|
|
|
|
session->read_codec->codec_interface->interface_name);
|
2006-01-06 01:34:10 +00:00
|
|
|
*frame = NULL;
|
|
|
|
status = SWITCH_STATUS_GENERR;
|
|
|
|
break;
|
2005-11-19 20:07:43 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
2006-01-20 15:05:05 +00:00
|
|
|
static switch_status perform_write(switch_core_session *session, switch_frame *frame, int timeout, switch_io_flag flags,
|
|
|
|
int stream_id)
|
|
|
|
{
|
2005-11-19 20:07:43 +00:00
|
|
|
struct switch_io_event_hook_write_frame *ptr;
|
|
|
|
switch_status status = SWITCH_STATUS_FALSE;
|
|
|
|
|
|
|
|
if (session->endpoint_interface->io_routines->write_frame) {
|
2006-01-20 15:05:05 +00:00
|
|
|
if ((status =
|
|
|
|
session->endpoint_interface->io_routines->write_frame(session, frame, timeout, flags,
|
|
|
|
stream_id)) == SWITCH_STATUS_SUCCESS) {
|
|
|
|
for (ptr = session->event_hooks.write_frame; ptr; ptr = ptr->next) {
|
2006-01-09 18:40:56 +00:00
|
|
|
if ((status = ptr->write_frame(session, frame, timeout, flags, stream_id)) != SWITCH_STATUS_SUCCESS) {
|
2005-11-19 20:07:43 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
2006-01-20 15:05:05 +00:00
|
|
|
SWITCH_DECLARE(switch_status) switch_core_session_write_frame(switch_core_session *session, switch_frame *frame,
|
|
|
|
int timeout, int stream_id)
|
2005-11-19 20:07:43 +00:00
|
|
|
{
|
|
|
|
|
|
|
|
switch_status status = SWITCH_STATUS_FALSE;
|
2006-01-12 19:12:39 +00:00
|
|
|
switch_frame *enc_frame = NULL, *write_frame = frame;
|
2005-12-13 21:04:03 +00:00
|
|
|
unsigned int flag = 0, need_codec = 0, perfect = 0;
|
2005-11-19 20:07:43 +00:00
|
|
|
switch_io_flag io_flag = SWITCH_IO_FLAG_NOOP;
|
|
|
|
|
|
|
|
/* if you think this code is redundant.... too bad! I like to understand what I'm doing */
|
|
|
|
if ((session->write_codec && frame->codec && session->write_codec->implementation != frame->codec->implementation)) {
|
|
|
|
need_codec = TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (session->write_codec && !frame->codec) {
|
|
|
|
need_codec = TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!session->write_codec && frame->codec) {
|
|
|
|
need_codec = TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (need_codec) {
|
2006-01-02 17:28:59 +00:00
|
|
|
if (frame->codec) {
|
2005-12-12 17:50:07 +00:00
|
|
|
session->raw_write_frame.datalen = session->raw_write_frame.buflen;
|
2006-02-09 17:01:32 +00:00
|
|
|
|
2005-11-19 20:07:43 +00:00
|
|
|
status = switch_core_codec_decode(frame->codec,
|
2006-01-06 01:34:10 +00:00
|
|
|
session->write_codec,
|
|
|
|
frame->data,
|
|
|
|
frame->datalen,
|
|
|
|
session->write_codec->implementation->samples_per_second,
|
|
|
|
session->raw_write_frame.data,
|
2006-01-20 15:05:05 +00:00
|
|
|
&session->raw_write_frame.datalen, &session->raw_write_frame.rate, &flag);
|
2005-11-19 20:07:43 +00:00
|
|
|
|
|
|
|
switch (status) {
|
2006-01-06 01:34:10 +00:00
|
|
|
case SWITCH_STATUS_RESAMPLE:
|
|
|
|
write_frame = &session->raw_write_frame;
|
|
|
|
if (!session->write_resampler) {
|
|
|
|
status = switch_resample_create(&session->write_resampler,
|
|
|
|
frame->codec->implementation->samples_per_second,
|
2006-01-12 18:27:20 +00:00
|
|
|
frame->codec->implementation->bytes_per_frame * 20,
|
2006-01-06 01:34:10 +00:00
|
|
|
session->write_codec->implementation->samples_per_second,
|
2006-01-12 18:27:20 +00:00
|
|
|
session->write_codec->implementation->bytes_per_frame * 20,
|
2006-01-06 01:34:10 +00:00
|
|
|
session->pool);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case SWITCH_STATUS_SUCCESS:
|
|
|
|
write_frame = &session->raw_write_frame;
|
|
|
|
break;
|
|
|
|
case SWITCH_STATUS_NOOP:
|
|
|
|
write_frame = frame;
|
|
|
|
status = SWITCH_STATUS_SUCCESS;
|
|
|
|
break;
|
|
|
|
default:
|
2006-01-20 15:05:05 +00:00
|
|
|
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Codec %s decoder error!\n",
|
|
|
|
frame->codec->codec_interface->interface_name);
|
2006-01-06 01:34:10 +00:00
|
|
|
return status;
|
|
|
|
break;
|
2005-11-19 20:07:43 +00:00
|
|
|
}
|
2006-01-20 15:05:05 +00:00
|
|
|
}
|
2006-01-02 17:28:59 +00:00
|
|
|
if (session->write_resampler) {
|
|
|
|
short *data = write_frame->data;
|
|
|
|
|
2006-01-20 15:05:05 +00:00
|
|
|
session->write_resampler->from_len =
|
|
|
|
switch_short_to_float(data, session->write_resampler->from, (int) write_frame->datalen / 2);
|
|
|
|
session->write_resampler->to_len =
|
|
|
|
switch_resample_process(session->write_resampler, session->write_resampler->from,
|
|
|
|
session->write_resampler->from_len, session->write_resampler->to,
|
|
|
|
(int) session->write_resampler->to_size, 0);
|
2006-01-06 01:34:10 +00:00
|
|
|
switch_float_to_short(session->write_resampler->to, data, write_frame->datalen * 2);
|
2006-01-02 17:28:59 +00:00
|
|
|
write_frame->samples = session->write_resampler->to_len;
|
|
|
|
write_frame->datalen = session->write_resampler->to_len * 2;
|
|
|
|
write_frame->rate = session->write_resampler->to_rate;
|
|
|
|
}
|
2005-11-19 20:07:43 +00:00
|
|
|
if (session->write_codec) {
|
|
|
|
if (write_frame->datalen == session->write_codec->implementation->bytes_per_frame) {
|
|
|
|
perfect = TRUE;
|
|
|
|
} else {
|
|
|
|
if (!session->raw_write_buffer) {
|
2006-02-20 00:23:25 +00:00
|
|
|
size_t bytes = session->write_codec->implementation->bytes_per_frame * 10;
|
2005-11-19 20:07:43 +00:00
|
|
|
switch_console_printf(SWITCH_CHANNEL_CONSOLE,
|
2006-01-06 01:34:10 +00:00
|
|
|
"Engaging Write Buffer at %d bytes to accomidate %d->%d\n",
|
|
|
|
bytes,
|
2006-01-20 15:05:05 +00:00
|
|
|
write_frame->datalen, session->write_codec->implementation->bytes_per_frame);
|
|
|
|
if ((status =
|
|
|
|
switch_buffer_create(session->pool, &session->raw_write_buffer,
|
|
|
|
bytes)) != SWITCH_STATUS_SUCCESS) {
|
2005-11-19 20:07:43 +00:00
|
|
|
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Write Buffer Failed!\n");
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!(switch_buffer_write(session->raw_write_buffer, write_frame->data, write_frame->datalen))) {
|
|
|
|
return SWITCH_STATUS_MEMERR;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (perfect) {
|
|
|
|
enc_frame = write_frame;
|
2005-12-12 17:50:07 +00:00
|
|
|
session->enc_write_frame.datalen = session->enc_write_frame.buflen;
|
2005-12-30 00:00:21 +00:00
|
|
|
|
2005-11-19 20:07:43 +00:00
|
|
|
status = switch_core_codec_encode(session->write_codec,
|
2006-01-06 01:34:10 +00:00
|
|
|
frame->codec,
|
|
|
|
enc_frame->data,
|
|
|
|
enc_frame->datalen,
|
|
|
|
session->write_codec->implementation->samples_per_second,
|
|
|
|
session->enc_write_frame.data,
|
|
|
|
&session->enc_write_frame.datalen,
|
2006-01-20 15:05:05 +00:00
|
|
|
&session->enc_write_frame.rate, &flag);
|
2005-11-19 20:07:43 +00:00
|
|
|
|
|
|
|
switch (status) {
|
2006-01-06 01:34:10 +00:00
|
|
|
case SWITCH_STATUS_RESAMPLE:
|
|
|
|
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "fixme 2\n");
|
|
|
|
case SWITCH_STATUS_SUCCESS:
|
|
|
|
write_frame = &session->enc_write_frame;
|
|
|
|
break;
|
|
|
|
case SWITCH_STATUS_NOOP:
|
|
|
|
write_frame = enc_frame;
|
|
|
|
status = SWITCH_STATUS_SUCCESS;
|
|
|
|
break;
|
|
|
|
default:
|
2006-01-20 15:05:05 +00:00
|
|
|
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Codec %s encoder error!\n",
|
|
|
|
session->read_codec->codec_interface->interface_name);
|
2006-01-06 01:34:10 +00:00
|
|
|
write_frame = NULL;
|
|
|
|
return status;
|
|
|
|
break;
|
2005-11-19 20:07:43 +00:00
|
|
|
}
|
|
|
|
|
2006-01-09 18:40:56 +00:00
|
|
|
status = perform_write(session, write_frame, timeout, io_flag, stream_id);
|
2005-11-19 20:07:43 +00:00
|
|
|
return status;
|
|
|
|
} else {
|
2006-02-20 00:23:25 +00:00
|
|
|
size_t used = switch_buffer_inuse(session->raw_write_buffer);
|
|
|
|
size_t bytes = session->write_codec->implementation->bytes_per_frame;
|
|
|
|
size_t frames = (used / bytes);
|
2005-11-19 20:07:43 +00:00
|
|
|
|
|
|
|
|
|
|
|
if (frames) {
|
2006-02-20 00:23:25 +00:00
|
|
|
size_t x;
|
2005-11-19 20:07:43 +00:00
|
|
|
for (x = 0; x < frames; x++) {
|
|
|
|
if ((session->raw_write_frame.datalen =
|
2006-02-20 00:23:25 +00:00
|
|
|
switch_buffer_read(session->raw_write_buffer, session->raw_write_frame.data, bytes)) != 0) {
|
2006-01-06 01:34:10 +00:00
|
|
|
|
|
|
|
enc_frame = &session->raw_write_frame;
|
|
|
|
session->raw_write_frame.rate = session->write_codec->implementation->samples_per_second;
|
|
|
|
session->enc_write_frame.datalen = session->enc_write_frame.buflen;
|
|
|
|
status = switch_core_codec_encode(session->write_codec,
|
|
|
|
frame->codec,
|
|
|
|
enc_frame->data,
|
|
|
|
enc_frame->datalen,
|
|
|
|
frame->codec->implementation->samples_per_second,
|
|
|
|
session->enc_write_frame.data,
|
|
|
|
&session->enc_write_frame.datalen,
|
2006-01-20 15:05:05 +00:00
|
|
|
&session->enc_write_frame.rate, &flag);
|
2006-01-06 01:34:10 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
switch (status) {
|
|
|
|
case SWITCH_STATUS_RESAMPLE:
|
|
|
|
write_frame = &session->enc_write_frame;
|
|
|
|
if (!session->read_resampler) {
|
|
|
|
status = switch_resample_create(&session->read_resampler,
|
|
|
|
frame->codec->implementation->samples_per_second,
|
2006-01-12 18:27:20 +00:00
|
|
|
frame->codec->implementation->bytes_per_frame * 20,
|
2006-01-20 15:05:05 +00:00
|
|
|
session->write_codec->implementation->
|
|
|
|
samples_per_second,
|
|
|
|
session->write_codec->implementation->
|
|
|
|
bytes_per_frame * 20, session->pool);
|
2006-01-03 01:17:59 +00:00
|
|
|
}
|
2006-01-06 01:34:10 +00:00
|
|
|
break;
|
|
|
|
case SWITCH_STATUS_SUCCESS:
|
|
|
|
write_frame = &session->enc_write_frame;
|
|
|
|
break;
|
|
|
|
case SWITCH_STATUS_NOOP:
|
|
|
|
write_frame = enc_frame;
|
|
|
|
status = SWITCH_STATUS_SUCCESS;
|
|
|
|
break;
|
|
|
|
default:
|
2006-01-20 15:05:05 +00:00
|
|
|
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Codec %s encoder error!\n",
|
|
|
|
session->read_codec->codec_interface->interface_name);
|
2006-01-06 01:34:10 +00:00
|
|
|
write_frame = NULL;
|
|
|
|
return status;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (session->read_resampler) {
|
|
|
|
short *data = write_frame->data;
|
2006-01-20 15:05:05 +00:00
|
|
|
|
2006-01-06 01:34:10 +00:00
|
|
|
session->read_resampler->from_len = switch_short_to_float(data,
|
|
|
|
session->read_resampler->from,
|
2006-01-20 15:05:05 +00:00
|
|
|
(int) write_frame->datalen /
|
|
|
|
2);
|
|
|
|
session->read_resampler->to_len =
|
|
|
|
switch_resample_process(session->read_resampler, session->read_resampler->from,
|
|
|
|
session->read_resampler->from_len,
|
|
|
|
session->read_resampler->to,
|
|
|
|
(int) session->read_resampler->to_size, 0);
|
2006-01-06 01:34:10 +00:00
|
|
|
switch_float_to_short(session->read_resampler->to, data, write_frame->datalen * 2);
|
|
|
|
write_frame->samples = session->read_resampler->to_len;
|
|
|
|
write_frame->datalen = session->read_resampler->to_len * 2;
|
|
|
|
write_frame->rate = session->read_resampler->to_rate;
|
|
|
|
}
|
2006-01-09 18:40:56 +00:00
|
|
|
status = perform_write(session, write_frame, timeout, io_flag, stream_id);
|
2005-11-19 20:07:43 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
2006-01-09 18:40:56 +00:00
|
|
|
status = perform_write(session, frame, timeout, io_flag, stream_id);
|
2005-11-19 20:07:43 +00:00
|
|
|
}
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
|
|
|
SWITCH_DECLARE(switch_status) switch_core_session_kill_channel(switch_core_session *session, switch_signal sig)
|
|
|
|
{
|
|
|
|
struct switch_io_event_hook_kill_channel *ptr;
|
|
|
|
switch_status status = SWITCH_STATUS_FALSE;
|
|
|
|
|
|
|
|
if (session->endpoint_interface->io_routines->kill_channel) {
|
|
|
|
if ((status = session->endpoint_interface->io_routines->kill_channel(session, sig)) == SWITCH_STATUS_SUCCESS) {
|
2006-01-20 15:05:05 +00:00
|
|
|
for (ptr = session->event_hooks.kill_channel; ptr; ptr = ptr->next) {
|
2005-11-19 20:07:43 +00:00
|
|
|
if ((status = ptr->kill_channel(session, sig)) != SWITCH_STATUS_SUCCESS) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return status;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2006-01-09 18:40:56 +00:00
|
|
|
SWITCH_DECLARE(switch_status) switch_core_session_waitfor_read(switch_core_session *session, int timeout, int stream_id)
|
2005-11-19 20:07:43 +00:00
|
|
|
{
|
|
|
|
struct switch_io_event_hook_waitfor_read *ptr;
|
|
|
|
switch_status status = SWITCH_STATUS_FALSE;
|
|
|
|
|
|
|
|
if (session->endpoint_interface->io_routines->waitfor_read) {
|
2006-01-20 15:05:05 +00:00
|
|
|
if ((status =
|
|
|
|
session->endpoint_interface->io_routines->waitfor_read(session, timeout,
|
|
|
|
stream_id)) == SWITCH_STATUS_SUCCESS) {
|
|
|
|
for (ptr = session->event_hooks.waitfor_read; ptr; ptr = ptr->next) {
|
2006-01-09 18:40:56 +00:00
|
|
|
if ((status = ptr->waitfor_read(session, timeout, stream_id)) != SWITCH_STATUS_SUCCESS) {
|
2005-11-19 20:07:43 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return status;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2006-01-20 15:05:05 +00:00
|
|
|
SWITCH_DECLARE(switch_status) switch_core_session_waitfor_write(switch_core_session *session, int timeout,
|
|
|
|
int stream_id)
|
2005-11-19 20:07:43 +00:00
|
|
|
{
|
|
|
|
struct switch_io_event_hook_waitfor_write *ptr;
|
|
|
|
switch_status status = SWITCH_STATUS_FALSE;
|
|
|
|
|
|
|
|
if (session->endpoint_interface->io_routines->waitfor_write) {
|
2006-01-20 15:05:05 +00:00
|
|
|
if ((status =
|
|
|
|
session->endpoint_interface->io_routines->waitfor_write(session, timeout,
|
|
|
|
stream_id)) == SWITCH_STATUS_SUCCESS) {
|
|
|
|
for (ptr = session->event_hooks.waitfor_write; ptr; ptr = ptr->next) {
|
2006-01-09 18:40:56 +00:00
|
|
|
if ((status = ptr->waitfor_write(session, timeout, stream_id)) != SWITCH_STATUS_SUCCESS) {
|
2005-11-19 20:07:43 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
2005-12-06 21:25:56 +00:00
|
|
|
|
2006-01-20 15:05:05 +00:00
|
|
|
SWITCH_DECLARE(switch_status) switch_core_session_send_dtmf(switch_core_session *session, char *dtmf)
|
2005-12-06 21:25:56 +00:00
|
|
|
{
|
|
|
|
struct switch_io_event_hook_send_dtmf *ptr;
|
|
|
|
switch_status status = SWITCH_STATUS_FALSE;
|
|
|
|
|
|
|
|
if (session->endpoint_interface->io_routines->send_dtmf) {
|
|
|
|
if ((status = session->endpoint_interface->io_routines->send_dtmf(session, dtmf)) == SWITCH_STATUS_SUCCESS) {
|
2006-01-20 15:05:05 +00:00
|
|
|
for (ptr = session->event_hooks.send_dtmf; ptr; ptr = ptr->next) {
|
2005-12-06 21:25:56 +00:00
|
|
|
if ((status = ptr->send_dtmf(session, dtmf)) != SWITCH_STATUS_SUCCESS) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
2006-01-20 15:05:05 +00:00
|
|
|
SWITCH_DECLARE(switch_status) switch_core_session_add_event_hook_outgoing(switch_core_session *session,
|
|
|
|
switch_outgoing_channel_hook outgoing_channel)
|
2005-11-19 20:07:43 +00:00
|
|
|
{
|
|
|
|
switch_io_event_hook_outgoing_channel *hook, *ptr;
|
|
|
|
|
|
|
|
assert(outgoing_channel != NULL);
|
2006-02-20 00:23:25 +00:00
|
|
|
if ((hook = switch_core_session_alloc(session, sizeof(*hook))) != 0) {
|
2005-11-19 20:07:43 +00:00
|
|
|
hook->outgoing_channel = outgoing_channel;
|
|
|
|
if (!session->event_hooks.outgoing_channel) {
|
|
|
|
session->event_hooks.outgoing_channel = hook;
|
|
|
|
} else {
|
2006-01-20 15:05:05 +00:00
|
|
|
for (ptr = session->event_hooks.outgoing_channel; ptr && ptr->next; ptr = ptr->next);
|
2005-11-19 20:07:43 +00:00
|
|
|
ptr->next = hook;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return SWITCH_STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
return SWITCH_STATUS_MEMERR;
|
|
|
|
}
|
|
|
|
|
2006-01-20 15:05:05 +00:00
|
|
|
SWITCH_DECLARE(switch_status) switch_core_session_add_event_hook_answer_channel(switch_core_session *session,
|
|
|
|
switch_answer_channel_hook
|
|
|
|
answer_channel)
|
2005-11-19 20:07:43 +00:00
|
|
|
{
|
|
|
|
switch_io_event_hook_answer_channel *hook, *ptr;
|
|
|
|
|
|
|
|
assert(answer_channel != NULL);
|
2006-02-20 00:23:25 +00:00
|
|
|
if ((hook = switch_core_session_alloc(session, sizeof(*hook))) != 0) {
|
2005-11-19 20:07:43 +00:00
|
|
|
hook->answer_channel = answer_channel;
|
|
|
|
if (!session->event_hooks.answer_channel) {
|
|
|
|
session->event_hooks.answer_channel = hook;
|
|
|
|
} else {
|
2006-01-20 15:05:05 +00:00
|
|
|
for (ptr = session->event_hooks.answer_channel; ptr && ptr->next; ptr = ptr->next);
|
2005-11-19 20:07:43 +00:00
|
|
|
ptr->next = hook;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return SWITCH_STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
return SWITCH_STATUS_MEMERR;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2006-01-20 15:05:05 +00:00
|
|
|
SWITCH_DECLARE(switch_status) switch_core_session_add_event_hook_read_frame(switch_core_session *session,
|
|
|
|
switch_read_frame_hook read_frame)
|
2005-11-19 20:07:43 +00:00
|
|
|
{
|
|
|
|
switch_io_event_hook_read_frame *hook, *ptr;
|
|
|
|
|
|
|
|
assert(read_frame != NULL);
|
2006-02-20 00:23:25 +00:00
|
|
|
if ((hook = switch_core_session_alloc(session, sizeof(*hook))) != 0) {
|
2005-11-19 20:07:43 +00:00
|
|
|
hook->read_frame = read_frame;
|
|
|
|
if (!session->event_hooks.read_frame) {
|
|
|
|
session->event_hooks.read_frame = hook;
|
|
|
|
} else {
|
2006-01-20 15:05:05 +00:00
|
|
|
for (ptr = session->event_hooks.read_frame; ptr && ptr->next; ptr = ptr->next);
|
2005-11-19 20:07:43 +00:00
|
|
|
ptr->next = hook;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return SWITCH_STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
return SWITCH_STATUS_MEMERR;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2006-01-20 15:05:05 +00:00
|
|
|
SWITCH_DECLARE(switch_status) switch_core_session_add_event_hook_write_frame(switch_core_session *session,
|
|
|
|
switch_write_frame_hook write_frame)
|
2005-11-19 20:07:43 +00:00
|
|
|
{
|
|
|
|
switch_io_event_hook_write_frame *hook, *ptr;
|
|
|
|
|
|
|
|
assert(write_frame != NULL);
|
2006-02-20 00:23:25 +00:00
|
|
|
if ((hook = switch_core_session_alloc(session, sizeof(*hook))) != 0) {
|
2005-11-19 20:07:43 +00:00
|
|
|
hook->write_frame = write_frame;
|
|
|
|
if (!session->event_hooks.write_frame) {
|
|
|
|
session->event_hooks.write_frame = hook;
|
|
|
|
} else {
|
2006-01-20 15:05:05 +00:00
|
|
|
for (ptr = session->event_hooks.write_frame; ptr && ptr->next; ptr = ptr->next);
|
2005-11-19 20:07:43 +00:00
|
|
|
ptr->next = hook;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return SWITCH_STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
return SWITCH_STATUS_MEMERR;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2006-01-20 15:05:05 +00:00
|
|
|
SWITCH_DECLARE(switch_status) switch_core_session_add_event_hook_kill_channel(switch_core_session *session,
|
|
|
|
switch_kill_channel_hook kill_channel)
|
2005-11-19 20:07:43 +00:00
|
|
|
{
|
|
|
|
switch_io_event_hook_kill_channel *hook, *ptr;
|
|
|
|
|
|
|
|
assert(kill_channel != NULL);
|
2006-02-20 00:23:25 +00:00
|
|
|
if ((hook = switch_core_session_alloc(session, sizeof(*hook))) != 0) {
|
2005-11-19 20:07:43 +00:00
|
|
|
hook->kill_channel = kill_channel;
|
|
|
|
if (!session->event_hooks.kill_channel) {
|
|
|
|
session->event_hooks.kill_channel = hook;
|
|
|
|
} else {
|
2006-01-20 15:05:05 +00:00
|
|
|
for (ptr = session->event_hooks.kill_channel; ptr && ptr->next; ptr = ptr->next);
|
2005-11-19 20:07:43 +00:00
|
|
|
ptr->next = hook;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return SWITCH_STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
return SWITCH_STATUS_MEMERR;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2006-01-20 15:05:05 +00:00
|
|
|
SWITCH_DECLARE(switch_status) switch_core_session_add_event_hook_waitfor_read(switch_core_session *session,
|
|
|
|
switch_waitfor_read_hook waitfor_read)
|
2005-11-19 20:07:43 +00:00
|
|
|
{
|
|
|
|
switch_io_event_hook_waitfor_read *hook, *ptr;
|
|
|
|
|
|
|
|
assert(waitfor_read != NULL);
|
2006-02-20 00:23:25 +00:00
|
|
|
if ((hook = switch_core_session_alloc(session, sizeof(*hook))) != 0) {
|
2005-11-19 20:07:43 +00:00
|
|
|
hook->waitfor_read = waitfor_read;
|
|
|
|
if (!session->event_hooks.waitfor_read) {
|
|
|
|
session->event_hooks.waitfor_read = hook;
|
|
|
|
} else {
|
2006-01-20 15:05:05 +00:00
|
|
|
for (ptr = session->event_hooks.waitfor_read; ptr && ptr->next; ptr = ptr->next);
|
2005-11-19 20:07:43 +00:00
|
|
|
ptr->next = hook;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return SWITCH_STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
return SWITCH_STATUS_MEMERR;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2006-01-20 15:05:05 +00:00
|
|
|
SWITCH_DECLARE(switch_status) switch_core_session_add_event_hook_waitfor_write(switch_core_session *session,
|
|
|
|
switch_waitfor_write_hook waitfor_write)
|
2005-11-19 20:07:43 +00:00
|
|
|
{
|
|
|
|
switch_io_event_hook_waitfor_write *hook, *ptr;
|
|
|
|
|
|
|
|
assert(waitfor_write != NULL);
|
2006-02-20 00:23:25 +00:00
|
|
|
if ((hook = switch_core_session_alloc(session, sizeof(*hook))) != 0) {
|
2005-11-19 20:07:43 +00:00
|
|
|
hook->waitfor_write = waitfor_write;
|
|
|
|
if (!session->event_hooks.waitfor_write) {
|
|
|
|
session->event_hooks.waitfor_write = hook;
|
|
|
|
} else {
|
2006-01-20 15:05:05 +00:00
|
|
|
for (ptr = session->event_hooks.waitfor_write; ptr && ptr->next; ptr = ptr->next);
|
2005-11-19 20:07:43 +00:00
|
|
|
ptr->next = hook;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return SWITCH_STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
return SWITCH_STATUS_MEMERR;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-01-20 15:05:05 +00:00
|
|
|
SWITCH_DECLARE(switch_status) switch_core_session_add_event_hook_send_dtmf(switch_core_session *session,
|
|
|
|
switch_send_dtmf_hook send_dtmf)
|
2005-12-06 21:25:56 +00:00
|
|
|
{
|
|
|
|
switch_io_event_hook_send_dtmf *hook, *ptr;
|
|
|
|
|
|
|
|
assert(send_dtmf != NULL);
|
2006-02-20 00:23:25 +00:00
|
|
|
if ((hook = switch_core_session_alloc(session, sizeof(*hook))) != 0) {
|
2005-12-06 21:25:56 +00:00
|
|
|
hook->send_dtmf = send_dtmf;
|
|
|
|
if (!session->event_hooks.send_dtmf) {
|
|
|
|
session->event_hooks.send_dtmf = hook;
|
|
|
|
} else {
|
2006-01-20 15:05:05 +00:00
|
|
|
for (ptr = session->event_hooks.send_dtmf; ptr && ptr->next; ptr = ptr->next);
|
2005-12-06 21:25:56 +00:00
|
|
|
ptr->next = hook;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return SWITCH_STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
return SWITCH_STATUS_MEMERR;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-11-19 20:07:43 +00:00
|
|
|
SWITCH_DECLARE(switch_status) switch_core_new_memory_pool(switch_memory_pool **pool)
|
|
|
|
{
|
2005-12-28 05:17:21 +00:00
|
|
|
|
|
|
|
if (runtime.memory_pool == NULL) {
|
|
|
|
return SWITCH_STATUS_MEMERR;
|
|
|
|
}
|
2005-11-19 20:07:43 +00:00
|
|
|
|
2006-03-01 22:55:28 +00:00
|
|
|
if ((apr_pool_create(pool, runtime.memory_pool)) != SWITCH_STATUS_SUCCESS) {
|
2005-11-19 20:07:43 +00:00
|
|
|
*pool = NULL;
|
|
|
|
return SWITCH_STATUS_MEMERR;
|
|
|
|
}
|
|
|
|
return SWITCH_STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
SWITCH_DECLARE(switch_status) switch_core_destroy_memory_pool(switch_memory_pool **pool)
|
|
|
|
{
|
|
|
|
apr_pool_destroy(*pool);
|
|
|
|
return SWITCH_STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
SWITCH_DECLARE(switch_channel *) switch_core_session_get_channel(switch_core_session *session)
|
|
|
|
{
|
|
|
|
return session->channel;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void switch_core_standard_on_init(switch_core_session *session)
|
|
|
|
{
|
2005-12-15 00:45:38 +00:00
|
|
|
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Standard INIT %s\n", switch_channel_get_name(session->channel));
|
2005-11-19 20:07:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void switch_core_standard_on_hangup(switch_core_session *session)
|
|
|
|
{
|
2006-01-03 01:17:59 +00:00
|
|
|
|
2005-12-15 00:45:38 +00:00
|
|
|
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Standard HANGUP %s\n", switch_channel_get_name(session->channel));
|
|
|
|
|
2005-11-19 20:07:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void switch_core_standard_on_ring(switch_core_session *session)
|
|
|
|
{
|
2006-03-02 00:32:45 +00:00
|
|
|
switch_dialplan_interface *dialplan_interface = NULL;
|
2005-11-19 20:07:43 +00:00
|
|
|
switch_caller_profile *caller_profile;
|
|
|
|
switch_caller_extension *extension;
|
|
|
|
|
2005-12-15 00:45:38 +00:00
|
|
|
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Standard RING %s\n", switch_channel_get_name(session->channel));
|
|
|
|
|
2006-02-20 00:23:25 +00:00
|
|
|
if ((caller_profile = switch_channel_get_caller_profile(session->channel)) == 0) {
|
2005-11-19 20:07:43 +00:00
|
|
|
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Can't get profile!\n");
|
|
|
|
switch_channel_set_state(session->channel, CS_HANGUP);
|
|
|
|
} else {
|
2006-03-02 00:32:45 +00:00
|
|
|
if (!switch_strlen_zero(caller_profile->dialplan)) {
|
|
|
|
dialplan_interface = switch_loadable_module_get_dialplan_interface(caller_profile->dialplan);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!dialplan_interface) {
|
|
|
|
if (switch_channel_test_flag(session->channel, CF_OUTBOUND)) {
|
|
|
|
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "No Dialplan, changing state to TRANSMIT\n");
|
|
|
|
switch_channel_set_state(session->channel, CS_TRANSMIT);
|
|
|
|
return;
|
|
|
|
}
|
2005-11-19 20:07:43 +00:00
|
|
|
} else {
|
2006-02-20 00:23:25 +00:00
|
|
|
if ((extension = dialplan_interface->hunt_function(session)) != 0) {
|
2005-11-19 20:07:43 +00:00
|
|
|
switch_channel_set_caller_extension(session->channel, extension);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2006-01-03 01:17:59 +00:00
|
|
|
}
|
2005-11-19 20:07:43 +00:00
|
|
|
|
|
|
|
static void switch_core_standard_on_execute(switch_core_session *session)
|
|
|
|
{
|
|
|
|
switch_caller_extension *extension;
|
|
|
|
const switch_application_interface *application_interface;
|
|
|
|
|
|
|
|
|
|
|
|
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Standard EXECUTE\n");
|
2006-02-20 00:23:25 +00:00
|
|
|
if ((extension = switch_channel_get_caller_extension(session->channel)) == 0) {
|
2005-11-19 20:07:43 +00:00
|
|
|
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "No Extension!\n");
|
|
|
|
switch_channel_set_state(session->channel, CS_HANGUP);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
while (switch_channel_get_state(session->channel) == CS_EXECUTE && extension->current_application) {
|
2006-01-20 15:05:05 +00:00
|
|
|
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Execute %s(%s)\n",
|
|
|
|
extension->current_application->application_name,
|
2006-01-06 01:34:10 +00:00
|
|
|
extension->current_application->application_data);
|
2006-02-20 00:23:25 +00:00
|
|
|
if (
|
2006-01-20 15:05:05 +00:00
|
|
|
(application_interface =
|
2006-02-20 00:23:25 +00:00
|
|
|
switch_loadable_module_get_application_interface(extension->current_application->application_name)) == 0) {
|
2006-01-20 15:05:05 +00:00
|
|
|
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Invalid Application %s\n",
|
|
|
|
extension->current_application->application_name);
|
2005-11-19 20:07:43 +00:00
|
|
|
switch_channel_set_state(session->channel, CS_HANGUP);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!application_interface->application_function) {
|
2006-01-20 15:05:05 +00:00
|
|
|
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "No Function for %s\n",
|
|
|
|
extension->current_application->application_name);
|
2005-11-19 20:07:43 +00:00
|
|
|
switch_channel_set_state(session->channel, CS_HANGUP);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
application_interface->application_function(session, extension->current_application->application_data);
|
|
|
|
extension->current_application = extension->current_application->next;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch_channel_set_state(session->channel, CS_HANGUP);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void switch_core_standard_on_loopback(switch_core_session *session)
|
|
|
|
{
|
|
|
|
switch_channel_state state;
|
|
|
|
switch_frame *frame;
|
2006-01-09 18:40:56 +00:00
|
|
|
int stream_id;
|
2005-11-19 20:07:43 +00:00
|
|
|
|
|
|
|
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Standard LOOPBACK\n");
|
|
|
|
|
|
|
|
while ((state = switch_channel_get_state(session->channel)) == CS_LOOPBACK) {
|
2006-01-20 15:05:05 +00:00
|
|
|
for (stream_id = 0; stream_id < session->stream_count; stream_id++) {
|
2006-01-09 18:40:56 +00:00
|
|
|
if (switch_core_session_read_frame(session, &frame, -1, stream_id) == SWITCH_STATUS_SUCCESS) {
|
|
|
|
switch_core_session_write_frame(session, frame, -1, stream_id);
|
|
|
|
}
|
2005-11-19 20:07:43 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void switch_core_standard_on_transmit(switch_core_session *session)
|
|
|
|
{
|
|
|
|
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Standard TRANSMIT\n");
|
|
|
|
}
|
|
|
|
|
2006-01-05 21:03:22 +00:00
|
|
|
SWITCH_DECLARE(void) switch_core_session_signal_state_change(switch_core_session *session)
|
2005-11-19 20:07:43 +00:00
|
|
|
{
|
|
|
|
switch_thread_cond_signal(session->cond);
|
|
|
|
}
|
|
|
|
|
2006-03-01 22:55:28 +00:00
|
|
|
SWITCH_DECLARE(unsigned int) switch_core_session_runing(switch_core_session *session)
|
|
|
|
{
|
|
|
|
return session->thread_running;
|
|
|
|
}
|
|
|
|
|
2005-11-19 20:07:43 +00:00
|
|
|
SWITCH_DECLARE(void) switch_core_session_run(switch_core_session *session)
|
|
|
|
{
|
|
|
|
switch_channel_state state = CS_NEW, laststate = CS_HANGUP, midstate = CS_DONE;
|
|
|
|
const switch_endpoint_interface *endpoint_interface;
|
2006-02-07 20:47:15 +00:00
|
|
|
const switch_state_handler_table *driver_state_handler = NULL;
|
|
|
|
const switch_state_handler_table *application_state_handler = NULL;
|
2005-11-19 20:07:43 +00:00
|
|
|
|
|
|
|
/*
|
2006-01-20 15:05:05 +00:00
|
|
|
Life of the channel. you have channel and pool in your session
|
|
|
|
everywhere you go you use the session to malloc with
|
|
|
|
switch_core_session_alloc(session, <size>)
|
2005-11-19 20:07:43 +00:00
|
|
|
|
2006-01-20 15:05:05 +00:00
|
|
|
The enpoint module gets the first crack at implementing the state
|
|
|
|
if it wants to, it can cancel the default behaviour by returning SWITCH_STATUS_FALSE
|
2005-11-19 20:07:43 +00:00
|
|
|
|
2006-01-20 15:05:05 +00:00
|
|
|
Next comes the channel's event handler table that can be set by an application
|
|
|
|
which also can veto the next behaviour in line by returning SWITCH_STATUS_FALSE
|
2005-11-19 20:07:43 +00:00
|
|
|
|
2006-01-20 15:05:05 +00:00
|
|
|
Finally the default state behaviour is called.
|
2005-11-19 20:07:43 +00:00
|
|
|
|
|
|
|
|
2006-01-20 15:05:05 +00:00
|
|
|
*/
|
2005-11-19 20:07:43 +00:00
|
|
|
assert(session != NULL);
|
2006-03-01 22:55:28 +00:00
|
|
|
|
|
|
|
session->thread_running = 1;
|
2005-11-19 20:07:43 +00:00
|
|
|
endpoint_interface = session->endpoint_interface;
|
|
|
|
assert(endpoint_interface != NULL);
|
|
|
|
|
2006-02-07 20:47:15 +00:00
|
|
|
driver_state_handler = endpoint_interface->state_handler;
|
|
|
|
assert(driver_state_handler != NULL);
|
2005-11-19 20:07:43 +00:00
|
|
|
|
|
|
|
switch_mutex_lock(session->mutex);
|
|
|
|
|
|
|
|
while ((state = switch_channel_get_state(session->channel)) != CS_DONE) {
|
2005-12-21 22:25:22 +00:00
|
|
|
switch_event *event;
|
2005-11-19 20:07:43 +00:00
|
|
|
|
2005-12-21 22:25:22 +00:00
|
|
|
if (state != laststate) {
|
2006-02-07 20:47:15 +00:00
|
|
|
int index = 0;
|
|
|
|
int proceed = 1;
|
2005-11-19 20:07:43 +00:00
|
|
|
midstate = state;
|
|
|
|
|
2005-12-21 22:25:22 +00:00
|
|
|
if (switch_event_create(&event, SWITCH_EVENT_CHANNEL_STATE) == SWITCH_STATUS_SUCCESS) {
|
|
|
|
switch_channel_event_set_data(session->channel, event);
|
|
|
|
switch_event_fire(&event);
|
|
|
|
}
|
|
|
|
|
2006-01-20 15:05:05 +00:00
|
|
|
switch (state) {
|
|
|
|
case CS_NEW: /* Just created, Waiting for first instructions */
|
2006-01-06 01:34:10 +00:00
|
|
|
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "State NEW\n");
|
|
|
|
break;
|
|
|
|
case CS_DONE:
|
|
|
|
continue;
|
|
|
|
break;
|
2006-01-20 15:05:05 +00:00
|
|
|
case CS_HANGUP: /* Deactivate and end the thread */
|
2006-01-06 01:34:10 +00:00
|
|
|
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "State HANGUP\n");
|
2006-02-07 20:47:15 +00:00
|
|
|
if (!driver_state_handler->on_hangup ||
|
|
|
|
(driver_state_handler->on_hangup &&
|
|
|
|
driver_state_handler->on_hangup(session) == SWITCH_STATUS_SUCCESS &&
|
2006-01-06 01:34:10 +00:00
|
|
|
midstate == switch_channel_get_state(session->channel))) {
|
2006-02-20 00:23:25 +00:00
|
|
|
while((application_state_handler = switch_channel_get_state_handler(session->channel, index++)) != 0) {
|
2006-02-07 20:47:15 +00:00
|
|
|
if (!application_state_handler || !application_state_handler->on_hangup ||
|
|
|
|
(application_state_handler->on_hangup &&
|
|
|
|
application_state_handler->on_hangup(session) == SWITCH_STATUS_SUCCESS &&
|
|
|
|
midstate == switch_channel_get_state(session->channel))) {
|
|
|
|
proceed++;
|
|
|
|
continue;
|
|
|
|
} else {
|
|
|
|
proceed = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
index = 0;
|
2006-02-20 00:23:25 +00:00
|
|
|
while(proceed && (application_state_handler = switch_core_get_state_handler(index++)) != 0) {
|
2006-02-07 20:47:15 +00:00
|
|
|
if (!application_state_handler || !application_state_handler->on_hangup ||
|
|
|
|
(application_state_handler->on_hangup &&
|
|
|
|
application_state_handler->on_hangup(session) == SWITCH_STATUS_SUCCESS &&
|
|
|
|
midstate == switch_channel_get_state(session->channel))) {
|
|
|
|
proceed++;
|
|
|
|
continue;
|
|
|
|
} else {
|
|
|
|
proceed = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (proceed) {
|
2006-01-06 01:34:10 +00:00
|
|
|
switch_core_standard_on_hangup(session);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
switch_channel_set_state(session->channel, CS_DONE);
|
2006-02-13 17:43:49 +00:00
|
|
|
midstate = switch_channel_get_state(session->channel);
|
2006-01-06 01:34:10 +00:00
|
|
|
break;
|
2006-01-20 15:05:05 +00:00
|
|
|
case CS_INIT: /* Basic setup tasks */
|
2006-01-06 01:34:10 +00:00
|
|
|
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "State INIT\n");
|
2006-02-07 20:47:15 +00:00
|
|
|
if (!driver_state_handler->on_init ||
|
|
|
|
(driver_state_handler->on_init &&
|
|
|
|
driver_state_handler->on_init(session) == SWITCH_STATUS_SUCCESS &&
|
2006-01-06 01:34:10 +00:00
|
|
|
midstate == switch_channel_get_state(session->channel))) {
|
2006-02-20 00:23:25 +00:00
|
|
|
while((application_state_handler = switch_channel_get_state_handler(session->channel, index++)) != 0) {
|
2006-02-07 20:47:15 +00:00
|
|
|
if (!application_state_handler || !application_state_handler->on_init ||
|
|
|
|
(application_state_handler->on_init &&
|
|
|
|
application_state_handler->on_init(session) == SWITCH_STATUS_SUCCESS &&
|
|
|
|
midstate == switch_channel_get_state(session->channel))) {
|
|
|
|
proceed++;
|
|
|
|
continue;
|
|
|
|
} else {
|
|
|
|
proceed = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
index = 0;
|
2006-02-20 00:23:25 +00:00
|
|
|
while(proceed && (application_state_handler = switch_core_get_state_handler(index++)) != 0) {
|
2006-02-07 20:47:15 +00:00
|
|
|
if (!application_state_handler || !application_state_handler->on_init ||
|
|
|
|
(application_state_handler->on_init &&
|
|
|
|
application_state_handler->on_init(session) == SWITCH_STATUS_SUCCESS &&
|
|
|
|
midstate == switch_channel_get_state(session->channel))) {
|
|
|
|
proceed++;
|
|
|
|
continue;
|
|
|
|
} else {
|
|
|
|
proceed = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (proceed) {
|
2006-01-06 01:34:10 +00:00
|
|
|
switch_core_standard_on_init(session);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
2006-01-20 15:05:05 +00:00
|
|
|
case CS_RING: /* Look for a dialplan and find something to do */
|
2006-01-06 01:34:10 +00:00
|
|
|
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "State RING\n");
|
2006-02-07 20:47:15 +00:00
|
|
|
if (!driver_state_handler->on_ring ||
|
|
|
|
(driver_state_handler->on_ring &&
|
|
|
|
driver_state_handler->on_ring(session) == SWITCH_STATUS_SUCCESS &&
|
2006-01-06 01:34:10 +00:00
|
|
|
midstate == switch_channel_get_state(session->channel))) {
|
2006-02-20 00:23:25 +00:00
|
|
|
while((application_state_handler = switch_channel_get_state_handler(session->channel, index++)) != 0) {
|
2006-02-07 20:47:15 +00:00
|
|
|
if (!application_state_handler || !application_state_handler->on_ring ||
|
|
|
|
(application_state_handler->on_ring &&
|
|
|
|
application_state_handler->on_ring(session) == SWITCH_STATUS_SUCCESS &&
|
|
|
|
midstate == switch_channel_get_state(session->channel))) {
|
|
|
|
proceed++;
|
|
|
|
continue;
|
|
|
|
} else {
|
|
|
|
proceed = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
index = 0;
|
2006-02-20 00:23:25 +00:00
|
|
|
while(proceed && (application_state_handler = switch_core_get_state_handler(index++)) != 0) {
|
2006-02-07 20:47:15 +00:00
|
|
|
if (!application_state_handler || !application_state_handler->on_ring ||
|
|
|
|
(application_state_handler->on_ring &&
|
|
|
|
application_state_handler->on_ring(session) == SWITCH_STATUS_SUCCESS &&
|
|
|
|
midstate == switch_channel_get_state(session->channel))) {
|
|
|
|
proceed++;
|
|
|
|
continue;
|
|
|
|
} else {
|
|
|
|
proceed = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (proceed) {
|
2006-01-06 01:34:10 +00:00
|
|
|
switch_core_standard_on_ring(session);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
2006-01-20 15:05:05 +00:00
|
|
|
case CS_EXECUTE: /* Execute an Operation */
|
2006-01-06 01:34:10 +00:00
|
|
|
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "State EXECUTE\n");
|
2006-02-07 20:47:15 +00:00
|
|
|
if (!driver_state_handler->on_execute ||
|
|
|
|
(driver_state_handler->on_execute &&
|
|
|
|
driver_state_handler->on_execute(session) == SWITCH_STATUS_SUCCESS &&
|
2006-01-06 01:34:10 +00:00
|
|
|
midstate == switch_channel_get_state(session->channel))) {
|
2006-02-20 00:23:25 +00:00
|
|
|
while((application_state_handler = switch_channel_get_state_handler(session->channel, index++)) != 0) {
|
2006-02-07 20:47:15 +00:00
|
|
|
if (!application_state_handler || !application_state_handler->on_execute ||
|
|
|
|
(application_state_handler->on_execute &&
|
|
|
|
application_state_handler->on_execute(session) == SWITCH_STATUS_SUCCESS &&
|
|
|
|
midstate == switch_channel_get_state(session->channel))) {
|
|
|
|
proceed++;
|
|
|
|
continue;
|
|
|
|
} else {
|
|
|
|
proceed = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
index = 0;
|
2006-02-20 00:23:25 +00:00
|
|
|
while(proceed && (application_state_handler = switch_core_get_state_handler(index++)) != 0) {
|
2006-02-07 20:47:15 +00:00
|
|
|
if (!application_state_handler || !application_state_handler->on_execute ||
|
|
|
|
(application_state_handler->on_execute &&
|
|
|
|
application_state_handler->on_execute(session) == SWITCH_STATUS_SUCCESS &&
|
|
|
|
midstate == switch_channel_get_state(session->channel))) {
|
|
|
|
proceed++;
|
|
|
|
continue;
|
|
|
|
} else {
|
|
|
|
proceed = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (proceed) {
|
2006-01-06 01:34:10 +00:00
|
|
|
switch_core_standard_on_execute(session);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
2006-01-20 15:05:05 +00:00
|
|
|
case CS_LOOPBACK: /* loop all data back to source */
|
2006-01-06 01:34:10 +00:00
|
|
|
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "State LOOPBACK\n");
|
2006-02-07 20:47:15 +00:00
|
|
|
if (!driver_state_handler->on_loopback ||
|
|
|
|
(driver_state_handler->on_loopback &&
|
|
|
|
driver_state_handler->on_loopback(session) == SWITCH_STATUS_SUCCESS &&
|
2006-01-06 01:34:10 +00:00
|
|
|
midstate == switch_channel_get_state(session->channel))) {
|
2006-02-20 00:23:25 +00:00
|
|
|
while((application_state_handler = switch_channel_get_state_handler(session->channel, index++)) != 0) {
|
2006-02-07 20:47:15 +00:00
|
|
|
if (!application_state_handler || !application_state_handler->on_loopback ||
|
|
|
|
(application_state_handler->on_loopback &&
|
|
|
|
application_state_handler->on_loopback(session) == SWITCH_STATUS_SUCCESS &&
|
|
|
|
midstate == switch_channel_get_state(session->channel))) {
|
|
|
|
proceed++;
|
|
|
|
continue;
|
|
|
|
} else {
|
|
|
|
proceed = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
index = 0;
|
2006-02-20 00:23:25 +00:00
|
|
|
while(proceed && (application_state_handler = switch_core_get_state_handler(index++)) != 0) {
|
2006-02-07 20:47:15 +00:00
|
|
|
if (!application_state_handler || !application_state_handler->on_loopback ||
|
|
|
|
(application_state_handler->on_loopback &&
|
|
|
|
application_state_handler->on_loopback(session) == SWITCH_STATUS_SUCCESS &&
|
|
|
|
midstate == switch_channel_get_state(session->channel))) {
|
|
|
|
proceed++;
|
|
|
|
continue;
|
|
|
|
} else {
|
|
|
|
proceed = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (proceed) {
|
2006-01-06 01:34:10 +00:00
|
|
|
switch_core_standard_on_loopback(session);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
2006-01-20 15:05:05 +00:00
|
|
|
case CS_TRANSMIT: /* send/recieve data to/from another channel */
|
2006-01-06 01:34:10 +00:00
|
|
|
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "State TRANSMIT\n");
|
2006-02-07 20:47:15 +00:00
|
|
|
if (!driver_state_handler->on_transmit ||
|
|
|
|
(driver_state_handler->on_transmit &&
|
|
|
|
driver_state_handler->on_transmit(session) == SWITCH_STATUS_SUCCESS &&
|
2006-01-06 01:34:10 +00:00
|
|
|
midstate == switch_channel_get_state(session->channel))) {
|
2006-02-07 20:47:15 +00:00
|
|
|
|
2006-02-20 00:23:25 +00:00
|
|
|
while((application_state_handler = switch_channel_get_state_handler(session->channel, index++)) != 0) {
|
2006-02-07 20:47:15 +00:00
|
|
|
if (!application_state_handler || !application_state_handler->on_transmit ||
|
|
|
|
(application_state_handler->on_transmit &&
|
|
|
|
application_state_handler->on_transmit(session) == SWITCH_STATUS_SUCCESS &&
|
|
|
|
midstate == switch_channel_get_state(session->channel))) {
|
|
|
|
proceed++;
|
|
|
|
continue;
|
|
|
|
} else {
|
|
|
|
proceed = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
index = 0;
|
2006-02-20 00:23:25 +00:00
|
|
|
while(proceed && (application_state_handler = switch_core_get_state_handler(index++)) != 0) {
|
2006-02-07 20:47:15 +00:00
|
|
|
if (!application_state_handler || !application_state_handler->on_transmit ||
|
|
|
|
(application_state_handler->on_transmit &&
|
|
|
|
application_state_handler->on_transmit(session) == SWITCH_STATUS_SUCCESS &&
|
|
|
|
midstate == switch_channel_get_state(session->channel))) {
|
|
|
|
proceed++;
|
|
|
|
continue;
|
|
|
|
} else {
|
|
|
|
proceed = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (proceed) {
|
2006-01-06 01:34:10 +00:00
|
|
|
switch_core_standard_on_transmit(session);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
2005-11-19 20:07:43 +00:00
|
|
|
}
|
|
|
|
|
2006-02-13 17:37:10 +00:00
|
|
|
if (midstate == CS_DONE) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2005-11-19 20:07:43 +00:00
|
|
|
laststate = midstate;
|
|
|
|
}
|
2006-02-13 17:37:10 +00:00
|
|
|
|
|
|
|
|
2005-11-19 20:07:43 +00:00
|
|
|
if (state < CS_DONE && midstate == switch_channel_get_state(session->channel)) {
|
|
|
|
switch_thread_cond_wait(session->cond, session->mutex);
|
2006-02-13 17:37:10 +00:00
|
|
|
}
|
2005-11-19 20:07:43 +00:00
|
|
|
}
|
2006-03-01 22:55:28 +00:00
|
|
|
session->thread_running = 0;
|
2005-11-19 20:07:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
SWITCH_DECLARE(void) switch_core_session_destroy(switch_core_session **session)
|
|
|
|
{
|
|
|
|
switch_memory_pool *pool;
|
|
|
|
|
|
|
|
pool = (*session)->pool;
|
|
|
|
*session = NULL;
|
|
|
|
apr_pool_destroy(pool);
|
|
|
|
pool = NULL;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
SWITCH_DECLARE(switch_status) switch_core_hash_init(switch_hash **hash, switch_memory_pool *pool)
|
|
|
|
{
|
2006-02-20 00:23:25 +00:00
|
|
|
if ((*hash = apr_hash_make(pool)) != 0) {
|
2005-11-19 20:07:43 +00:00
|
|
|
return SWITCH_STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
return SWITCH_STATUS_GENERR;
|
|
|
|
}
|
|
|
|
|
|
|
|
SWITCH_DECLARE(switch_status) switch_core_hash_destroy(switch_hash *hash)
|
|
|
|
{
|
|
|
|
return SWITCH_STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2005-12-14 22:46:09 +00:00
|
|
|
SWITCH_DECLARE(switch_status) switch_core_hash_insert_dup(switch_hash *hash, char *key, void *data)
|
|
|
|
{
|
|
|
|
apr_hash_set(hash, switch_core_strdup(apr_hash_pool_get(hash), key), APR_HASH_KEY_STRING, data);
|
|
|
|
return SWITCH_STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2005-11-19 20:07:43 +00:00
|
|
|
SWITCH_DECLARE(switch_status) switch_core_hash_insert(switch_hash *hash, char *key, void *data)
|
|
|
|
{
|
|
|
|
apr_hash_set(hash, key, APR_HASH_KEY_STRING, data);
|
|
|
|
return SWITCH_STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
SWITCH_DECLARE(switch_status) switch_core_hash_delete(switch_hash *hash, char *key)
|
|
|
|
{
|
|
|
|
apr_hash_set(hash, key, APR_HASH_KEY_STRING, NULL);
|
|
|
|
return SWITCH_STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
SWITCH_DECLARE(void *) switch_core_hash_find(switch_hash *hash, char *key)
|
|
|
|
{
|
|
|
|
return apr_hash_get(hash, key, APR_HASH_KEY_STRING);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* This function abstracts the thread creation for modules by allowing you to pass a function ptr and
|
2006-01-06 01:34:10 +00:00
|
|
|
a void object and trust that that the function will be run in a thread with arg This lets
|
|
|
|
you request and activate a thread without giving up any knowledge about what is in the thread
|
|
|
|
neither the core nor the calling module know anything about each other.
|
2005-11-19 20:07:43 +00:00
|
|
|
|
2006-01-06 01:34:10 +00:00
|
|
|
This thread is expected to never exit until the application exits so the func is responsible
|
|
|
|
to make sure that is the case.
|
2005-11-19 20:07:43 +00:00
|
|
|
|
2006-01-06 01:34:10 +00:00
|
|
|
The typical use for this is so switch_loadable_module.c can start up a thread for each module
|
|
|
|
passing the table of module methods as a session obj into the core without actually allowing
|
|
|
|
the core to have any clue and keeping switch_loadable_module.c from needing any thread code.
|
2005-11-19 20:07:43 +00:00
|
|
|
|
|
|
|
*/
|
|
|
|
|
2006-01-04 01:04:33 +00:00
|
|
|
SWITCH_DECLARE(void) switch_core_launch_thread(switch_thread_start_t func, void *obj, switch_memory_pool *pool)
|
2005-11-19 20:07:43 +00:00
|
|
|
{
|
|
|
|
switch_thread *thread;
|
2006-01-04 01:04:33 +00:00
|
|
|
switch_threadattr_t *thd_attr = NULL;
|
2005-12-22 18:53:33 +00:00
|
|
|
switch_core_thread_session *ts;
|
2006-01-04 01:04:33 +00:00
|
|
|
int mypool;
|
2005-11-19 20:07:43 +00:00
|
|
|
|
2006-01-04 01:04:33 +00:00
|
|
|
mypool = pool ? 0 : 1;
|
2005-12-22 22:17:25 +00:00
|
|
|
|
2006-01-04 01:04:33 +00:00
|
|
|
if (!pool && switch_core_new_memory_pool(&pool) != SWITCH_STATUS_SUCCESS) {
|
2006-01-03 01:17:59 +00:00
|
|
|
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Could not allocate memory pool\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2006-01-04 01:04:33 +00:00
|
|
|
switch_threadattr_create(&thd_attr, pool);
|
|
|
|
switch_threadattr_detach_set(thd_attr, 1);
|
|
|
|
|
2006-02-20 00:23:25 +00:00
|
|
|
if ((ts = switch_core_alloc(pool, sizeof(*ts))) == 0) {
|
2005-12-22 18:53:33 +00:00
|
|
|
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Could not allocate memory\n");
|
|
|
|
} else {
|
2006-01-04 01:04:33 +00:00
|
|
|
if (mypool) {
|
|
|
|
ts->pool = pool;
|
|
|
|
}
|
2005-12-22 18:53:33 +00:00
|
|
|
ts->objs[0] = obj;
|
|
|
|
|
2006-01-20 15:05:05 +00:00
|
|
|
switch_thread_create(&thread, thd_attr, func, ts, pool);
|
2005-12-22 18:53:33 +00:00
|
|
|
}
|
2005-11-19 20:07:43 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
|
2006-01-20 15:05:05 +00:00
|
|
|
static void *SWITCH_THREAD_FUNC switch_core_session_thread(switch_thread *thread, void *obj)
|
2005-11-19 20:07:43 +00:00
|
|
|
{
|
2006-02-13 17:37:10 +00:00
|
|
|
unsigned int id;
|
2005-11-19 20:07:43 +00:00
|
|
|
switch_core_session *session = obj;
|
|
|
|
session->thread = thread;
|
|
|
|
|
2006-02-13 17:37:10 +00:00
|
|
|
id = runtime.session_id++;
|
|
|
|
session->id = id;
|
2005-11-19 20:07:43 +00:00
|
|
|
|
|
|
|
snprintf(session->name, sizeof(session->name), "%ld", session->id);
|
|
|
|
|
2006-01-09 19:48:20 +00:00
|
|
|
switch_core_hash_insert(runtime.session_table, session->uuid_str, session);
|
2005-11-19 20:07:43 +00:00
|
|
|
switch_core_session_run(session);
|
2006-01-09 19:48:20 +00:00
|
|
|
switch_core_hash_delete(runtime.session_table, session->uuid_str);
|
2005-11-19 20:07:43 +00:00
|
|
|
switch_core_session_destroy(&session);
|
2006-02-13 17:37:10 +00:00
|
|
|
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Session %ld Ended\n", id);
|
2005-11-19 20:07:43 +00:00
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
SWITCH_DECLARE(void) switch_core_session_thread_launch(switch_core_session *session)
|
|
|
|
{
|
|
|
|
switch_thread *thread;
|
2005-12-14 20:22:19 +00:00
|
|
|
switch_threadattr_t *thd_attr;;
|
|
|
|
switch_threadattr_create(&thd_attr, session->pool);
|
|
|
|
switch_threadattr_detach_set(thd_attr, 1);
|
2005-11-19 20:07:43 +00:00
|
|
|
|
2006-03-01 22:55:28 +00:00
|
|
|
if (! session->thread_running) {
|
|
|
|
if (switch_thread_create(&thread, thd_attr, switch_core_session_thread, session, session->pool) != SWITCH_STATUS_SUCCESS) {
|
|
|
|
switch_core_session_destroy(&session);
|
|
|
|
}
|
2005-11-19 20:07:43 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-01-20 15:05:05 +00:00
|
|
|
SWITCH_DECLARE(void) switch_core_session_launch_thread(switch_core_session *session, switch_thread_start_t func,
|
|
|
|
void *obj)
|
2005-11-19 20:07:43 +00:00
|
|
|
{
|
|
|
|
switch_thread *thread;
|
2006-01-13 02:05:39 +00:00
|
|
|
switch_threadattr_t *thd_attr = NULL;
|
2005-12-14 20:22:19 +00:00
|
|
|
switch_threadattr_create(&thd_attr, session->pool);
|
|
|
|
switch_threadattr_detach_set(thd_attr, 1);
|
2005-11-19 20:07:43 +00:00
|
|
|
|
2006-01-20 15:05:05 +00:00
|
|
|
switch_thread_create(&thread, thd_attr, func, obj, session->pool);
|
2005-11-19 20:07:43 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
SWITCH_DECLARE(void *) switch_core_alloc(switch_memory_pool *pool, size_t memory)
|
|
|
|
{
|
|
|
|
void *ptr = NULL;
|
|
|
|
assert(pool != NULL);
|
|
|
|
|
2006-02-20 00:23:25 +00:00
|
|
|
if ((ptr = apr_palloc(pool, memory)) != 0) {
|
2005-11-19 20:07:43 +00:00
|
|
|
memset(ptr, 0, memory);
|
|
|
|
}
|
|
|
|
return ptr;
|
|
|
|
}
|
|
|
|
|
2006-01-20 15:05:05 +00:00
|
|
|
SWITCH_DECLARE(switch_core_session *) switch_core_session_request(const switch_endpoint_interface *endpoint_interface,
|
|
|
|
switch_memory_pool *pool)
|
2005-11-19 20:07:43 +00:00
|
|
|
{
|
|
|
|
switch_memory_pool *usepool;
|
|
|
|
switch_core_session *session;
|
2005-12-22 01:57:32 +00:00
|
|
|
switch_uuid_t uuid;
|
2005-11-19 20:07:43 +00:00
|
|
|
|
|
|
|
assert(endpoint_interface != NULL);
|
|
|
|
|
|
|
|
if (pool) {
|
|
|
|
usepool = pool;
|
|
|
|
} else if (switch_core_new_memory_pool(&usepool) != SWITCH_STATUS_SUCCESS) {
|
|
|
|
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Could not allocate memory pool\n");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2006-02-20 00:23:25 +00:00
|
|
|
if ((session = switch_core_alloc(usepool, sizeof(switch_core_session))) == 0) {
|
2005-11-19 20:07:43 +00:00
|
|
|
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Could not allocate session\n");
|
|
|
|
apr_pool_destroy(usepool);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (switch_channel_alloc(&session->channel, usepool) != SWITCH_STATUS_SUCCESS) {
|
|
|
|
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Could not allocate channel structure\n");
|
|
|
|
apr_pool_destroy(usepool);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch_channel_init(session->channel, session, CS_NEW, CF_SEND_AUDIO | CF_RECV_AUDIO);
|
|
|
|
|
|
|
|
/* The session *IS* the pool you may not alter it because you have no idea how
|
2006-01-06 01:34:10 +00:00
|
|
|
its all private it will be passed to the thread run function */
|
2005-11-19 20:07:43 +00:00
|
|
|
|
2005-12-22 01:57:32 +00:00
|
|
|
switch_uuid_get(&uuid);
|
|
|
|
switch_uuid_format(session->uuid_str, &uuid);
|
|
|
|
|
2005-11-19 20:07:43 +00:00
|
|
|
session->pool = usepool;
|
|
|
|
session->endpoint_interface = endpoint_interface;
|
|
|
|
|
|
|
|
session->raw_write_frame.data = session->raw_write_buf;
|
2005-12-12 17:50:07 +00:00
|
|
|
session->raw_write_frame.buflen = sizeof(session->raw_write_buf);
|
2005-11-19 20:07:43 +00:00
|
|
|
session->raw_read_frame.data = session->raw_read_buf;
|
2005-12-12 17:50:07 +00:00
|
|
|
session->raw_read_frame.buflen = sizeof(session->raw_read_buf);
|
2006-01-03 01:17:59 +00:00
|
|
|
|
2005-11-19 20:07:43 +00:00
|
|
|
|
|
|
|
session->enc_write_frame.data = session->enc_write_buf;
|
2005-12-12 17:50:07 +00:00
|
|
|
session->enc_write_frame.buflen = sizeof(session->enc_write_buf);
|
2005-11-19 20:07:43 +00:00
|
|
|
session->enc_read_frame.data = session->enc_read_buf;
|
2005-12-12 17:50:07 +00:00
|
|
|
session->enc_read_frame.buflen = sizeof(session->enc_read_buf);
|
2005-11-19 20:07:43 +00:00
|
|
|
|
2006-01-20 15:05:05 +00:00
|
|
|
switch_mutex_init(&session->mutex, SWITCH_MUTEX_NESTED, session->pool);
|
2005-11-19 20:07:43 +00:00
|
|
|
switch_thread_cond_create(&session->cond, session->pool);
|
2006-01-03 01:17:59 +00:00
|
|
|
|
2005-11-19 20:07:43 +00:00
|
|
|
return session;
|
|
|
|
}
|
|
|
|
|
|
|
|
SWITCH_DECLARE(switch_core_session *) switch_core_session_request_by_name(char *endpoint_name, switch_memory_pool *pool)
|
|
|
|
{
|
|
|
|
const switch_endpoint_interface *endpoint_interface;
|
|
|
|
|
2006-02-20 00:23:25 +00:00
|
|
|
if ((endpoint_interface = switch_loadable_module_get_endpoint_interface(endpoint_name)) == 0) {
|
2005-11-19 20:07:43 +00:00
|
|
|
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Could not locate channel type %s\n", endpoint_name);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return switch_core_session_request(endpoint_interface, pool);
|
|
|
|
}
|
|
|
|
|
2005-12-21 22:25:22 +00:00
|
|
|
|
2006-01-20 15:05:05 +00:00
|
|
|
static void core_event_handler(switch_event *event)
|
2005-12-21 22:25:22 +00:00
|
|
|
{
|
|
|
|
char buf[1024];
|
|
|
|
|
2006-01-20 15:05:05 +00:00
|
|
|
switch (event->event_id) {
|
2006-01-06 01:34:10 +00:00
|
|
|
case SWITCH_EVENT_LOG:
|
|
|
|
return;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
buf[0] = '\0';
|
|
|
|
//switch_event_serialize(event, buf, sizeof(buf), NULL);
|
|
|
|
//switch_console_printf(SWITCH_CHANNEL_CONSOLE, "\nCORE EVENT\n--------------------------------\n%s\n", buf);
|
|
|
|
break;
|
2005-12-21 22:25:22 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-03-01 17:06:10 +00:00
|
|
|
SWITCH_DECLARE(void) switch_core_set_globals(void)
|
2005-11-19 20:07:43 +00:00
|
|
|
{
|
2006-03-01 06:25:56 +00:00
|
|
|
#ifdef WIN32
|
|
|
|
#define BUFSIZE 50
|
|
|
|
char lpPathBuffer[BUFSIZE];
|
|
|
|
DWORD dwBufSize=BUFSIZE;
|
|
|
|
#endif
|
2006-02-28 21:21:48 +00:00
|
|
|
SWITCH_GLOBAL_dirs.base_dir = SWITCH_PREFIX_DIR;
|
|
|
|
SWITCH_GLOBAL_dirs.mod_dir = SWITCH_MOD_DIR;
|
|
|
|
SWITCH_GLOBAL_dirs.conf_dir = SWITCH_CONF_DIR;
|
|
|
|
SWITCH_GLOBAL_dirs.log_dir = SWITCH_LOG_DIR;
|
|
|
|
SWITCH_GLOBAL_dirs.db_dir = SWITCH_DB_DIR;
|
|
|
|
SWITCH_GLOBAL_dirs.script_dir = SWITCH_SCRIPT_DIR;
|
2006-03-01 06:25:56 +00:00
|
|
|
#ifdef SWITCH_TEMP_DIR
|
|
|
|
SWITCH_GLOBAL_dirs.temp_dir = SWITCH_TEMP_DIR;
|
|
|
|
#else
|
|
|
|
#ifdef WIN32
|
|
|
|
GetTempPath(dwBufSize, lpPathBuffer);
|
|
|
|
SWITCH_GLOBAL_dirs.temp_dir = lpPathBuffer;
|
|
|
|
#else
|
|
|
|
SWITCH_GLOBAL_dirs.temp_dir = "/tmp/";
|
|
|
|
#endif
|
|
|
|
#endif
|
2006-03-01 17:06:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
SWITCH_DECLARE(switch_status) switch_core_init(char *console)
|
|
|
|
{
|
|
|
|
|
|
|
|
memset(&runtime, 0, sizeof(runtime));
|
2006-02-28 21:21:48 +00:00
|
|
|
|
2006-03-01 17:06:10 +00:00
|
|
|
switch_core_set_globals();
|
|
|
|
|
2005-11-19 20:07:43 +00:00
|
|
|
#ifdef EMBED_PERL
|
|
|
|
PerlInterpreter *my_perl;
|
|
|
|
#endif
|
2006-02-26 03:13:01 +00:00
|
|
|
if(console) {
|
2006-03-01 17:06:10 +00:00
|
|
|
if (*console != '/') {
|
|
|
|
char path[265];
|
|
|
|
snprintf(path, sizeof(path), "%s%s%s", SWITCH_GLOBAL_dirs.log_dir, SWITCH_PATH_SEPARATOR, console);
|
|
|
|
console = path;
|
|
|
|
}
|
2006-02-28 21:21:48 +00:00
|
|
|
switch_core_set_console(console);
|
2006-02-26 03:13:01 +00:00
|
|
|
} else {
|
|
|
|
runtime.console = stdout;
|
|
|
|
}
|
2005-11-19 20:07:43 +00:00
|
|
|
|
|
|
|
/* INIT APR and Create the pool context */
|
2006-03-01 22:55:28 +00:00
|
|
|
if (apr_initialize() != SWITCH_STATUS_SUCCESS) {
|
2005-11-19 20:07:43 +00:00
|
|
|
apr_terminate();
|
|
|
|
return SWITCH_STATUS_MEMERR;
|
|
|
|
}
|
|
|
|
|
2006-03-01 22:55:28 +00:00
|
|
|
if (apr_pool_create(&runtime.memory_pool, NULL) != SWITCH_STATUS_SUCCESS) {
|
2005-11-19 20:07:43 +00:00
|
|
|
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Could not allocate memory pool\n");
|
|
|
|
switch_core_destroy();
|
|
|
|
return SWITCH_STATUS_MEMERR;
|
|
|
|
}
|
2005-12-28 05:17:21 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
2005-11-19 20:07:43 +00:00
|
|
|
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Allocated memory pool.\n");
|
2005-12-13 19:53:29 +00:00
|
|
|
switch_event_init(runtime.memory_pool);
|
2005-12-21 22:25:22 +00:00
|
|
|
|
2005-12-28 05:17:21 +00:00
|
|
|
assert(runtime.memory_pool != NULL);
|
|
|
|
|
2005-12-21 22:25:22 +00:00
|
|
|
/* Activate SQL database */
|
2006-02-20 00:23:25 +00:00
|
|
|
if ((runtime.db = switch_core_db_handle()) == 0 ) {
|
2005-12-21 22:25:22 +00:00
|
|
|
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Error Opening DB!\n");
|
|
|
|
} else {
|
|
|
|
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Opening DB\n");
|
2006-01-20 15:05:05 +00:00
|
|
|
if (switch_event_bind("core_db", SWITCH_EVENT_ALL, SWITCH_EVENT_SUBCLASS_ANY, core_event_handler, NULL) !=
|
|
|
|
SWITCH_STATUS_SUCCESS) {
|
2005-12-21 22:25:22 +00:00
|
|
|
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Couldn't bind event handler!\n");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-11-19 20:07:43 +00:00
|
|
|
#ifdef EMBED_PERL
|
2006-01-20 15:05:05 +00:00
|
|
|
if (!(my_perl = perl_alloc())) {
|
2005-11-19 20:07:43 +00:00
|
|
|
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Could not allocate perl intrepreter\n");
|
|
|
|
switch_core_destroy();
|
|
|
|
return SWITCH_STATUS_MEMERR;
|
|
|
|
}
|
|
|
|
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Allocated perl intrepreter.\n");
|
|
|
|
|
|
|
|
PERL_SET_CONTEXT(my_perl);
|
|
|
|
perl_construct(my_perl);
|
|
|
|
perl_parse(my_perl, xs_init, 3, embedding, NULL);
|
|
|
|
perl_run(my_perl);
|
|
|
|
runtime.my_perl = my_perl;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
runtime.session_id = 1;
|
|
|
|
|
|
|
|
switch_core_hash_init(&runtime.session_table, runtime.memory_pool);
|
|
|
|
|
|
|
|
time(&runtime.initiated);
|
|
|
|
return SWITCH_STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
SWITCH_DECLARE(switch_status) switch_core_destroy(void)
|
|
|
|
{
|
2005-12-14 20:22:19 +00:00
|
|
|
|
2005-11-19 20:07:43 +00:00
|
|
|
#ifdef EMBED_PERL
|
|
|
|
if (runtime.my_perl) {
|
|
|
|
perl_destruct(runtime.my_perl);
|
|
|
|
perl_free(runtime.my_perl);
|
|
|
|
runtime.my_perl = NULL;
|
|
|
|
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Unallocated perl interpreter.\n");
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2005-12-14 21:29:46 +00:00
|
|
|
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Closing Event Engine.\n");
|
|
|
|
switch_event_shutdown();
|
|
|
|
|
2005-12-21 22:25:22 +00:00
|
|
|
|
|
|
|
switch_core_db_close(runtime.db);
|
|
|
|
|
2005-12-14 21:29:46 +00:00
|
|
|
if (runtime.memory_pool) {
|
|
|
|
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Unallocating memory pool.\n");
|
|
|
|
apr_pool_destroy(runtime.memory_pool);
|
|
|
|
apr_terminate();
|
|
|
|
}
|
2006-02-26 03:13:01 +00:00
|
|
|
|
|
|
|
if(runtime.console != stdout && runtime.console != stderr) {
|
|
|
|
fclose(runtime.console);
|
|
|
|
runtime.console = NULL;
|
|
|
|
}
|
2005-12-14 21:29:46 +00:00
|
|
|
|
2005-11-19 20:07:43 +00:00
|
|
|
return SWITCH_STATUS_SUCCESS;
|
|
|
|
}
|