[Freeswitch-svn] [commit] r4788 - in freeswitch/branches/mikej/sofiasip-upgrade: . src src/include src/mod/applications/mod_commands src/mod/applications/mod_conference src/mod/applications/mod_dptools src/mod/applications/mod_ivrtest src/mod/event_handlers/mod_cdr
Author: mikej Date: Thu Mar 29 00:30:19 2007 New Revision: 4788 Modified: freeswitch/branches/mikej/sofiasip-upgrade/Makefile.am freeswitch/branches/mikej/sofiasip-upgrade/configure.in freeswitch/branches/mikej/sofiasip-upgrade/src/include/switch_am_config.h.in freeswitch/branches/mikej/sofiasip-upgrade/src/include/switch_core.h freeswitch/branches/mikej/sofiasip-upgrade/src/include/switch_ivr.h freeswitch/branches/mikej/sofiasip-upgrade/src/include/switch_platform.h freeswitch/branches/mikej/sofiasip-upgrade/src/include/switch_types.h freeswitch/branches/mikej/sofiasip-upgrade/src/mod/applications/mod_commands/mod_commands.c freeswitch/branches/mikej/sofiasip-upgrade/src/mod/applications/mod_conference/mod_conference.c freeswitch/branches/mikej/sofiasip-upgrade/src/mod/applications/mod_dptools/mod_dptools.c freeswitch/branches/mikej/sofiasip-upgrade/src/mod/applications/mod_ivrtest/mod_ivrtest.c freeswitch/branches/mikej/sofiasip-upgrade/src/mod/event_handlers/mod_cdr/Makefile.am freeswitch/branches/mikej/sofiasip-upgrade/src/switch_channel.c freeswitch/branches/mikej/sofiasip-upgrade/src/switch_core.c freeswitch/branches/mikej/sofiasip-upgrade/src/switch_ivr.c freeswitch/branches/mikej/sofiasip-upgrade/src/switch_resample.c Log: merged changes from trunk revisions 4781-4787. Modified: freeswitch/branches/mikej/sofiasip-upgrade/Makefile.am ============================================================================== --- freeswitch/branches/mikej/sofiasip-upgrade/Makefile.am (original) +++ freeswitch/branches/mikej/sofiasip-upgrade/Makefile.am Thu Mar 29 00:30:19 2007 @@ -80,12 +80,12 @@ CORE_CFLAGS += -I$(switch_srcdir)/libs/pcre CORE_CFLAGS += -I$(switch_srcdir)/libs/srtp/include CORE_CFLAGS += -I$(switch_srcdir)/libs/srtp/crypto/include -CORE_CFLAGS += -I$(switch_srcdir)/libs/libresample/include +CORE_CFLAGS += $(RESAMPLE_CFLAGS) CORE_CFLAGS += -I$(switch_srcdir)/libs/libteletone/src CORE_LIBS = libs/apr/libapr-1.la libs/apr-util/libaprutil-1.la CORE_LIBS += libs/sqlite/libsqlite3.la libs/pcre/libpcre.la -CORE_LIBS += libs/srtp/libsrtp.la libs/libresample/libresample.la +CORE_LIBS += libs/srtp/libsrtp.la $(RESAMPLE_LIB) lib_LTLIBRARIES = libfreeswitch.la libfreeswitch_la_CFLAGS = $(CORE_CFLAGS) $(AM_CFLAGS) @@ -171,9 +171,11 @@ @cd libs/srtp && $(MAKE) @$(TOUCH_TARGET) +if USE_INTREE_RESAMPLE libs/libresample/libresample.la: libs/libresample libs/libresample/.update @cd libs/libresample && $(MAKE) @$(TOUCH_TARGET) +endif core: libfreeswitch.la Modified: freeswitch/branches/mikej/sofiasip-upgrade/configure.in ============================================================================== --- freeswitch/branches/mikej/sofiasip-upgrade/configure.in (original) +++ freeswitch/branches/mikej/sofiasip-upgrade/configure.in Thu Mar 29 00:30:19 2007 @@ -57,9 +57,29 @@ AM_CONDITIONAL([WANT_DEBUG],[test "${enable_debug}" = "yes"]) +# Optional Features + +AC_ARG_ENABLE(resample, +[AC_HELP_STRING([--enable-resample],[build with embedded resamper])],[enable_resample="$enable_resample"],[enable_resample="yes"]) + +# We should add checking for out of tree libresample here +RESAMPLE_LIB= +RESAMPLE_CFLAGS= +if test "${enable_resample}" = "yes"; then + RESAMPLE_LIB="libs/libresample/libresample.la" + RESAMPLE_CFLAGS="-I${switch_srcdir}/libs/libresample/include" +else + AC_DEFINE([DISABLE_RESAMPLE],[],[Disable the embedded resampler]) +fi + +AC_SUBST(RESAMPLE_LIB) +AC_SUBST(RESAMPLE_CFLAGS) + +AM_CONDITIONAL([USE_INTREE_RESAMPLE],[test "${enable_resample}" = "yes"]) + # set defaults for use on all platforms -SWITCH_AM_CFLAGS="-I${switch_srcdir}/src/include -I${prefix}/include" -SWITCH_AM_CXXFLAGS="-I${switch_srcdir}/src/include -I${prefix}/include" +SWITCH_AM_CFLAGS="-I${switch_srcdir}/src/include" +SWITCH_AM_CXXFLAGS="-I${switch_srcdir}/src/include" SWITCH_AM_LDFLAGS="-lm -L/usr/local/lib" #set SOLINK variable based on compiler and host @@ -151,6 +171,7 @@ AC_CHECK_SIZEOF(long, 4) AC_CHECK_SIZEOF(short, 2) AC_CHECK_SIZEOF(long long, 8) +AC_CHECK_SIZEOF(time_t, 4) AC_TYPE_SIZE_T AC_CHECK_TYPE(ssize_t, int) @@ -226,6 +247,16 @@ size_t_fmt='#error Can not determine the proper size for size_t' fi +if test "$ac_cv_sizeof_time_t" = "$ac_cv_sizeof_int"; then + time_t_fmt='#define TIME_T_FMT "d"' +elif test "$ac_cv_sizeof_time_t" = "$ac_cv_sizeof_long"; then + time_t_fmt='#define TIME_T_FMT "ld"' +elif test "$ac_cv_sizeof_time_t" = "$ac_cv_sizeof_long_long"; then + time_t_fmt='#define TIME_T_FMT "lld"' +else + time_t_fmt='#error Can not determine the proper format specifier for time_t of size $ac_cv_sizeof_time_t' +fi + # Basically, we have tried to figure out the correct format strings # for SWITCH types which vary between platforms, but we don't always get # it right. If you find that we don't get it right for your platform, @@ -274,8 +305,7 @@ AC_SUBST(uint64_t_fmt) AC_SUBST(ssize_t_fmt) AC_SUBST(size_t_fmt) - - +AC_SUBST(time_t_fmt) AC_PATH_PROGS(ZCAT, gunzip gzcat gzip zcat) AC_PATH_PROGS(TAR, gtar tar) Modified: freeswitch/branches/mikej/sofiasip-upgrade/src/include/switch_am_config.h.in ============================================================================== --- freeswitch/branches/mikej/sofiasip-upgrade/src/include/switch_am_config.h.in (original) +++ freeswitch/branches/mikej/sofiasip-upgrade/src/include/switch_am_config.h.in Thu Mar 29 00:30:19 2007 @@ -15,5 +15,6 @@ @size_t_fmt@ @int64_t_fmt@ @uint64_t_fmt@ +@time_t_fmt@ #endif Modified: freeswitch/branches/mikej/sofiasip-upgrade/src/include/switch_core.h ============================================================================== --- freeswitch/branches/mikej/sofiasip-upgrade/src/include/switch_core.h (original) +++ freeswitch/branches/mikej/sofiasip-upgrade/src/include/switch_core.h Thu Mar 29 00:30:19 2007 @@ -104,17 +104,68 @@ struct switch_core_runtime; struct switch_core_port_allocator; +struct switch_core_scheduler_task { + time_t created; + time_t runtime; + uint32_t cmd_id; + char *group; + void *cmd_arg; + uint32_t task_id; +}; + + /*! \defgroup core1 Core Library \ingroup FREESWITCH \{ */ - ///\defgroup mb1 Media Bugs ///\ingroup core1 ///\{ + +///\defgroup sched1 Scheduler +///\ingroup core1 +///\{ + + +/*! + \brief Schedule a task in the future + \param runtime the time in epoch seconds to execute the task. + \param func the callback function to execute when the task is executed. + \param desc an arbitrary description of the task. + \param group a group id tag to link multiple tasks to a single entity. + \param cmd_id an arbitrary index number be used in the callback. + \param cmd_arg user data to be passed to the callback. + \param flags flags to alter behaviour + \return the id of the task +*/ +SWITCH_DECLARE(uint32_t) switch_core_scheduler_add_task(time_t task_runtime, + switch_core_scheduler_func_t func, + char *desc, + char *group, + uint32_t cmd_id, + void *cmd_arg, + switch_scheduler_flag_t flags); + +/*! + \brief Delete a scheduled task + \param task_id the id of the task + \return SWITCH_STATUS_SUCCESS if the task was deleted. +*/ +SWITCH_DECLARE(switch_status_t) switch_core_scheduler_del_task_id(uint32_t task_id); + +/*! + \brief Delete a scheduled task based on the group name + \param group the group name + \return SWITCH_STATUS_SUCCESS if any tasks were deleted +*/ +SWITCH_DECLARE(switch_status_t) switch_core_scheduler_del_task_group(char *group); + + +///\} + /*! \brief Add a media bug to the session \param session the session to add the bug to Modified: freeswitch/branches/mikej/sofiasip-upgrade/src/include/switch_ivr.h ============================================================================== --- freeswitch/branches/mikej/sofiasip-upgrade/src/include/switch_ivr.h (original) +++ freeswitch/branches/mikej/sofiasip-upgrade/src/include/switch_ivr.h Thu Mar 29 00:30:19 2007 @@ -332,6 +332,28 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_session_transfer(switch_core_session_t *session, char *extension, char *dialplan, char *context); /*! + \brief Transfer an existing session to another location in the future + \param runtime the time (int epoch seconds) to transfer the call + \param uuid the uuid of the session to transfer + \param extension the new extension + \param dialplan the new dialplan (OPTIONAL, may be NULL) + \param context the new context (OPTIONAL, may be NULL) + \return the id of the task +*/ +SWITCH_DECLARE(uint32_t) switch_ivr_schedule_transfer(time_t runtime, char *uuid, char *extension, char *dialplan, char *context); + + +/*! + \brief Hangup an existing session in the future + \param runtime the time (int epoch seconds) to transfer the call + \param uuid the uuid of the session to hangup + \param cause the hanup cause code + \param bleg hangup up the B-Leg if possible + \return the id of the task +*/ +SWITCH_DECLARE(uint32_t) switch_ivr_schedule_hangup(time_t runtime, char *uuid, switch_call_cause_t cause, switch_bool_t bleg); + +/*! \brief Bridge two existing sessions \param originator_uuid the uuid of the originator \param originatee_uuid the uuid of the originator @@ -384,6 +406,16 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_unhold(switch_core_session_t *session); /*! + \brief Signal the session to broadcast audio in the future + \param runtime when (in epoch time) to run the broadcast + \param uuid the uuid of the session to broadcast on + \param path the path data of the broadcast "/path/to/file.wav [<timer name>]" or "speak:<engine>|<voice>|<Text to say>" + \param flags flags to send to the request (SMF_ECHO_BRIDGED to send the broadcast to both sides of the call) + \return the id of the task +*/ +SWITCH_DECLARE(uint32_t) switch_ivr_schedule_broadcast(time_t runtime, char *uuid, char *path, switch_media_flag_t flags); + +/*! \brief Signal the session to broadcast audio \param uuid the uuid of the session to broadcast on \param path the path data of the broadcast "/path/to/file.wav [<timer name>]" or "speak:<engine>|<voice>|<Text to say>" Modified: freeswitch/branches/mikej/sofiasip-upgrade/src/include/switch_platform.h ============================================================================== --- freeswitch/branches/mikej/sofiasip-upgrade/src/include/switch_platform.h (original) +++ freeswitch/branches/mikej/sofiasip-upgrade/src/include/switch_platform.h Thu Mar 29 00:30:19 2007 @@ -213,6 +213,12 @@ #define SWITCH_INT64_T_FMT "I64d" #define SWITCH_UINT64_T_FMT "I64u" +#ifdef _USE_32BIT_TIME_T +#define TIME_T_FMT "d" +#else +#define TIME_T_FMT SWITCH_INT64_T_FMT +#endif + #else #ifndef SWITCH_SSIZE_T_FMT #define SWITCH_SSIZE_T_FMT (sizeof (switch_ssize_t) == sizeof (long) ? "ld" : sizeof (switch_ssize_t) == sizeof (int) ? "d" : "lld") @@ -230,6 +236,10 @@ #define SWITCH_UINT64_T_FMT (sizeof (long) == 8 ? "lu" : "llu") #endif +#ifndef TIME_T_FMT +#define TIME_T_FMT "ld" +#endif + #endif #define SWITCH_TIME_T_FMT SWITCH_INT64_T_FMT Modified: freeswitch/branches/mikej/sofiasip-upgrade/src/include/switch_types.h ============================================================================== --- freeswitch/branches/mikej/sofiasip-upgrade/src/include/switch_types.h (original) +++ freeswitch/branches/mikej/sofiasip-upgrade/src/include/switch_types.h Thu Mar 29 00:30:19 2007 @@ -168,6 +168,12 @@ } switch_management_action_t; typedef enum { + SSHF_NONE = 0, + SSHF_OWN_THREAD = (1 << 0), + SSHF_FREE_ARG = (1 << 1) +} switch_scheduler_flag_t; + +typedef enum { SMF_NONE = 0, SMF_REBRIDGE = (1 << 0), SMF_ECHO_ALEG = (1 << 1), @@ -910,7 +916,8 @@ SWITCH_CAUSE_LOSE_RACE = 502, SWITCH_CAUSE_MANAGER_REQUEST = 503, SWITCH_CAUSE_BLIND_TRANSFER = 600, - SWITCH_CAUSE_ATTENDED_TRANSFER = 601 + SWITCH_CAUSE_ATTENDED_TRANSFER = 601, + SWITCH_CAUSE_ALLOTTED_TIMEOUT = 602 } switch_call_cause_t; typedef enum { @@ -979,6 +986,8 @@ typedef void (*switch_application_function_t)(switch_core_session_t *, char *); typedef void (*switch_event_callback_t)(switch_event_t *); typedef switch_caller_extension_t *(*switch_dialplan_hunt_function_t)(switch_core_session_t *, void *); +typedef struct switch_core_scheduler_task switch_core_scheduler_task_t; +typedef void (*switch_core_scheduler_func_t)(switch_core_scheduler_task_t *task); typedef switch_status_t (*switch_state_handler_t)(switch_core_session_t *); typedef switch_status_t (*switch_outgoing_channel_hook_t)(switch_core_session_t *, switch_caller_profile_t *, switch_core_session_t *); typedef switch_status_t (*switch_answer_channel_hook_t)(switch_core_session_t *); Modified: freeswitch/branches/mikej/sofiasip-upgrade/src/mod/applications/mod_commands/mod_commands.c ============================================================================== --- freeswitch/branches/mikej/sofiasip-upgrade/src/mod/applications/mod_commands/mod_commands.c (original) +++ freeswitch/branches/mikej/sofiasip-upgrade/src/mod/applications/mod_commands/mod_commands.c Thu Mar 29 00:30:19 2007 @@ -51,6 +51,9 @@ static switch_api_interface_t media_api_interface; static switch_api_interface_t hold_api_interface; static switch_api_interface_t broadcast_api_interface; +static switch_api_interface_t sched_broadcast_api_interface; +static switch_api_interface_t sched_transfer_api_interface; +static switch_api_interface_t sched_hangup_api_interface; static switch_status_t status_function(char *cmd, switch_core_session_t *session, switch_stream_handle_t *stream) { @@ -245,6 +248,89 @@ return SWITCH_STATUS_SUCCESS; } + +static switch_status_t sched_transfer_function(char *cmd, switch_core_session_t *isession, switch_stream_handle_t *stream) +{ + switch_core_session_t *session = NULL; + char *argv[6] = {0}; + int argc = 0; + + if (isession) { + return SWITCH_STATUS_FALSE; + } + + argc = switch_separate_string(cmd, ' ', argv, (sizeof(argv) / sizeof(argv[0]))); + + if (switch_strlen_zero(cmd) || argc < 2 || argc > 5) { + stream->write_function(stream, "USAGE: %s\n", sched_transfer_api_interface.syntax); + } else { + char *uuid = argv[1]; + char *dest = argv[2]; + char *dp = argv[3]; + char *context = argv[4]; + time_t when; + + if (*argv[0] == '+') { + when = time (NULL) + atol(argv[0] + 1); + } else { + when = atol(argv[0]); + } + + if ((session = switch_core_session_locate(uuid))) { + switch_ivr_schedule_transfer(when, uuid, dest, dp, context); + stream->write_function(stream, "OK\n"); + switch_core_session_rwunlock(session); + } else { + stream->write_function(stream, "No Such Channel!\n"); + } + } + + return SWITCH_STATUS_SUCCESS; +} + +static switch_status_t sched_hangup_function(char *cmd, switch_core_session_t *isession, switch_stream_handle_t *stream) +{ + switch_core_session_t *session = NULL; + char *argv[4] = {0}; + int argc = 0; + + if (isession) { + return SWITCH_STATUS_FALSE; + } + + argc = switch_separate_string(cmd, ' ', argv, (sizeof(argv) / sizeof(argv[0]))); + + if (switch_strlen_zero(cmd) || argc < 1) { + stream->write_function(stream, "USAGE: %s\n", sched_hangup_api_interface.syntax); + } else { + char *uuid = argv[1]; + char *cause_str = argv[2]; + time_t when; + switch_call_cause_t cause = SWITCH_CAUSE_ALLOTTED_TIMEOUT; + + if (*argv[0] == '+') { + when = time (NULL) + atol(argv[0] + 1); + } else { + when = atol(argv[0]); + } + + if (cause_str) { + cause = switch_channel_str2cause(cause_str); + } + + if ((session = switch_core_session_locate(uuid))) { + switch_ivr_schedule_hangup(when, uuid, cause, SWITCH_FALSE); + stream->write_function(stream, "OK\n"); + switch_core_session_rwunlock(session); + } else { + stream->write_function(stream, "No Such Channel!\n"); + } + } + + return SWITCH_STATUS_SUCCESS; +} + + static switch_status_t uuid_media_function(char *cmd, switch_core_session_t *isession, switch_stream_handle_t *stream) { char *argv[4] = {0}; @@ -313,6 +399,50 @@ return SWITCH_STATUS_SUCCESS; } + +static switch_status_t sched_broadcast_function(char *cmd, switch_core_session_t *isession, switch_stream_handle_t *stream) +{ + char *argv[4] = {0}; + int argc = 0; + switch_status_t status = SWITCH_STATUS_FALSE; + + if (isession) { + return status; + } + + argc = switch_separate_string(cmd, ' ', argv, (sizeof(argv) / sizeof(argv[0]))); + + if (switch_strlen_zero(cmd) || argc < 3) { + stream->write_function(stream, "USAGE: %s\n", sched_broadcast_api_interface.syntax); + } else { + switch_media_flag_t flags = SMF_NONE; + time_t when; + + if (*argv[0] == '+') { + when = time (NULL) + atol(argv[0] + 1); + } else { + when = atol(argv[0]); + } + + if (argv[3]) { + if (!strcmp(argv[3], "both")) { + flags |= (SMF_ECHO_ALEG | SMF_ECHO_BLEG); + } else if (!strcmp(argv[3], "aleg")) { + flags |= SMF_ECHO_ALEG; + } else if (!strcmp(argv[3], "bleg")) { + flags |= SMF_ECHO_BLEG; + } + } else { + flags |= SMF_ECHO_ALEG; + } + + status = switch_ivr_schedule_broadcast(when, argv[1], argv[2], flags); + stream->write_function(stream, "+OK Message Scheduled\n"); + } + + return SWITCH_STATUS_SUCCESS; +} + static switch_status_t uuid_hold_function(char *cmd, switch_core_session_t *isession, switch_stream_handle_t *stream) { char *argv[4] = {0}; @@ -707,12 +837,36 @@ return SWITCH_STATUS_SUCCESS; } +static switch_api_interface_t sched_transfer_api_interface = { + /*.interface_name */ "sched_transfer", + /*.desc */ "Schedule a broadcast event to a running call", + /*.function */ sched_transfer_function, + /*.syntax */ "[+]<time> <uuid> <extension> [<dialplan>] [<context>]", + /*.next */ NULL +}; + +static switch_api_interface_t sched_broadcast_api_interface = { + /*.interface_name */ "sched_broadcast", + /*.desc */ "Schedule a broadcast event to a running call", + /*.function */ sched_broadcast_function, + /*.syntax */ "[+]<time> <uuid> <path> [aleg|bleg|both]", + /*.next */ &sched_transfer_api_interface +}; + +static switch_api_interface_t sched_hangup_api_interface = { + /*.interface_name */ "sched_hangup", + /*.desc */ "Schedule a running call to hangup", + /*.function */ sched_hangup_function, + /*.syntax */ "[+]<time> <uuid> [<cause>]", + /*.next */ &sched_broadcast_api_interface +}; + static switch_api_interface_t version_api_interface = { /*.interface_name */ "version", /*.desc */ "Show version of the switch", /*.function */ version_function, /*.syntax */ "", - /*.next */ NULL + /*.next */ &sched_hangup_api_interface }; static switch_api_interface_t help_api_interface = { Modified: freeswitch/branches/mikej/sofiasip-upgrade/src/mod/applications/mod_conference/mod_conference.c ============================================================================== --- freeswitch/branches/mikej/sofiasip-upgrade/src/mod/applications/mod_conference/mod_conference.c (original) +++ freeswitch/branches/mikej/sofiasip-upgrade/src/mod/applications/mod_conference/mod_conference.c Thu Mar 29 00:30:19 2007 @@ -4070,12 +4070,15 @@ switch_audio_resampler_t **resampler = read_codec->implementation->samples_per_second > conference->rate ? &member.read_resampler : &member.mux_resampler; - switch_resample_create(resampler, + if (switch_resample_create(resampler, read_codec->implementation->samples_per_second, read_codec->implementation->samples_per_second * 20, conference->rate, conference->rate * 20, - member.pool); + member.pool) != SWITCH_STATUS_SUCCESS){ + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Unable to crete resampler!\n"); + goto done; + } /* Setup an audio buffer for the resampled audio */ if (switch_buffer_create_dynamic(&member.resample_buffer, CONF_DBLOCK_SIZE, CONF_DBUFFER_SIZE, CONF_DBUFFER_MAX) != SWITCH_STATUS_SUCCESS) { Modified: freeswitch/branches/mikej/sofiasip-upgrade/src/mod/applications/mod_dptools/mod_dptools.c ============================================================================== --- freeswitch/branches/mikej/sofiasip-upgrade/src/mod/applications/mod_dptools/mod_dptools.c (original) +++ freeswitch/branches/mikej/sofiasip-upgrade/src/mod/applications/mod_dptools/mod_dptools.c Thu Mar 29 00:30:19 2007 @@ -96,6 +96,99 @@ } } +static void sched_transfer_function(switch_core_session_t *session, char *data) +{ + int argc; + char *argv[4] = {0}; + char *mydata; + + if (data && (mydata = switch_core_session_strdup(session, data))) { + if ((argc = switch_separate_string(mydata, ' ', argv, (sizeof(argv) / sizeof(argv[0])))) >= 2) { + time_t when; + + if (*argv[0] == '+') { + when = time (NULL) + atol(argv[0] + 1); + } else { + when = atol(argv[0]); + } + + switch_ivr_schedule_transfer(when, switch_core_session_get_uuid(session), argv[1], argv[2], argv[3]); + } else { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid Args\n"); + } + } +} + +static void sched_hangup_function(switch_core_session_t *session, char *data) +{ + int argc; + char *argv[5] = {0}; + char *mydata; + + if (data && (mydata = switch_core_session_strdup(session, data))) { + if ((argc = switch_separate_string(mydata, ' ', argv, (sizeof(argv) / sizeof(argv[0])))) >= 1) { + time_t when; + switch_call_cause_t cause = SWITCH_CAUSE_ALLOTTED_TIMEOUT; + switch_bool_t bleg = SWITCH_FALSE; + + if (*argv[0] == '+') { + when = time (NULL) + atol(argv[0] + 1); + } else { + when = atol(argv[0]); + } + + if (argv[1]) { + cause = switch_channel_str2cause(argv[1]); + } + + if (argv[2] && !strcasecmp(argv[2], "bleg")) { + bleg = SWITCH_TRUE; + } + + switch_ivr_schedule_hangup(when, switch_core_session_get_uuid(session), cause, bleg); + } else { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "No time specified.\n"); + } + } +} + + +static void sched_broadcast_function(switch_core_session_t *session, char *data) +{ + int argc; + char *argv[6] = {0}; + char *mydata; + + if (data && (mydata = switch_core_session_strdup(session, data))) { + if ((argc = switch_separate_string(mydata, ' ', argv, (sizeof(argv) / sizeof(argv[0])))) >= 2) { + time_t when; + switch_media_flag_t flags = SMF_NONE; + + if (*argv[0] == '+') { + when = time (NULL) + atol(argv[0] + 1); + } else { + when = atol(argv[0]); + } + + if (argv[2]) { + if (!strcmp(argv[2], "both")) { + flags |= (SMF_ECHO_ALEG | SMF_ECHO_BLEG); + } else if (!strcmp(argv[2], "aleg")) { + flags |= SMF_ECHO_ALEG; + } else if (!strcmp(argv[2], "bleg")) { + flags |= SMF_ECHO_BLEG; + } + } else { + flags |= SMF_ECHO_ALEG; + } + + switch_ivr_schedule_broadcast(when, switch_core_session_get_uuid(session), argv[1], flags); + } else { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid Args\n"); + } + } +} + static void sleep_function(switch_core_session_t *session, char *data) { @@ -509,6 +602,7 @@ } } + static switch_api_interface_t strepoch_api_interface = { /*.interface_name */ "strepoch", /*.desc */ "Convert a date string into epoch time", @@ -541,6 +635,39 @@ /*.next */ &dptools_api_interface }; + + +static switch_application_interface_t sched_transfer_application_interface = { + /*.interface_name */ "sched_transfer", + /*.application_function */ sched_transfer_function, + /*.long_desc */ "Schedule a transfer in the future", + /*.short_desc */ "Schedule a transfer in the future", + /*.syntax */ "[+]<time> <extension> <dialplan> <context>", + /* flags */ SAF_SUPPORT_NOMEDIA, + /*.next */ NULL +}; + +static switch_application_interface_t sched_broadcast_application_interface = { + /*.interface_name */ "sched_broadcast", + /*.application_function */ sched_broadcast_function, + /*.long_desc */ "Schedule a broadcast in the future", + /*.short_desc */ "Schedule a broadcast in the future", + /*.syntax */ "[+]<time> <path> [aleg|bleg|both]", + /* flags */ SAF_SUPPORT_NOMEDIA, + /*.next */ &sched_transfer_application_interface +}; + +static switch_application_interface_t sched_hangup_application_interface = { + /*.interface_name */ "sched_hangup", + /*.application_function */ sched_hangup_function, + /*.long_desc */ "Schedule a hangup in the future", + /*.short_desc */ "Schedule a hangup in the future", + /*.syntax */ "[+]<time> [<cause>]", + /* flags */ SAF_SUPPORT_NOMEDIA, + /*.next */ &sched_broadcast_application_interface +}; + + static const switch_application_interface_t queuedtmf_application_interface = { /*.interface_name */ "queue_dtmf", /*.application_function */ queue_dtmf_function, @@ -548,7 +675,7 @@ /* short_desc */ "Queue dtmf to be sent", /* syntax */ "<dtmf_data>", /* flags */ SAF_SUPPORT_NOMEDIA, - /*.next */ NULL + /*.next */ &sched_hangup_application_interface }; static const switch_application_interface_t redirect_application_interface = { Modified: freeswitch/branches/mikej/sofiasip-upgrade/src/mod/applications/mod_ivrtest/mod_ivrtest.c ============================================================================== --- freeswitch/branches/mikej/sofiasip-upgrade/src/mod/applications/mod_ivrtest/mod_ivrtest.c (original) +++ freeswitch/branches/mikej/sofiasip-upgrade/src/mod/applications/mod_ivrtest/mod_ivrtest.c Thu Mar 29 00:30:19 2007 @@ -233,6 +233,7 @@ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Done\n"); } +#ifdef BUGTEST static switch_bool_t bug_callback(switch_media_bug_t *bug, void *user_data, switch_abc_type_t type) { switch_frame_t *frame; @@ -249,9 +250,11 @@ return SWITCH_TRUE; } +#endif static void bugtest_function(switch_core_session_t *session, char *data) { +#ifdef BUGTEST switch_media_bug_t *bug; switch_channel_t *channel = switch_core_session_get_channel(session); switch_status_t status; @@ -264,6 +267,11 @@ switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER); return; } +#endif + //switch_ivr_schedule_broadcast(time(NULL) + 10, switch_core_session_get_uuid(session), "/Users/anthm/sr8k.wav", SMF_ECHO_ALEG); + //switch_ivr_schedule_transfer(time(NULL) + 10, switch_core_session_get_uuid(session), "2000", NULL, NULL); + //switch_ivr_schedule_hangup(time(NULL) + 10, switch_core_session_get_uuid(session), SWITCH_CAUSE_ALLOTTED_TIMEOUT); + switch_ivr_play_file(session, NULL, data, NULL); } Modified: freeswitch/branches/mikej/sofiasip-upgrade/src/mod/event_handlers/mod_cdr/Makefile.am ============================================================================== --- freeswitch/branches/mikej/sofiasip-upgrade/src/mod/event_handlers/mod_cdr/Makefile.am (original) +++ freeswitch/branches/mikej/sofiasip-upgrade/src/mod/event_handlers/mod_cdr/Makefile.am Thu Mar 29 00:30:19 2007 @@ -1,7 +1,16 @@ #we should set all these vars from configure, no reason to have these in each Makefile.am -LIBTOOL=`if test -z "$(VERBOSE)" ; then echo $(SHELL) $(switch_builddir)/quiet_libtool ;else echo $(switch_builddir)/libtool; fi;` +#LIBTOOL = compile=`echo $<|grep .c`;link=`echo $@|grep .la;echo $@|grep .so;echo $@|grep .dll`; if test -n "$$compile"; then echo Compiling $<;fi; if test -n "$$link"; then echo Creating $@;fi; `if test -z "$(VERBOSE)" ; then echo $(SHELL) $(switch_builddir)/quiet_libtool ;else echo $(switch_builddir)/libtool; fi;` +#LIBTOOL=`if test -z "$(VERBOSE)" ; then echo $(SHELL) $(switch_builddir)/quiet_libtool ;else echo $(switch_builddir)/libtool; fi;` +LIBTOOL = link=`echo $@|grep .la;echo $@|grep .so;echo $@|grep .dll`; \ + if test -n "$$link"; then echo Creating $@;fi; \ + `if test -z "$(VERBOSE)" ; \ + then echo $(SHELL) $(switch_builddir)/quiet_libtool ;\ + else echo $(switch_builddir)/libtool; fi;` + AM_MAKEFLAGS=`test -n "$(VERBOSE)" || echo -s` -LINK_OUTPUT_REDIR=> $(MODNAME).log || error="yes" ; \ + +# Dirty trick to override the link output +LIBS+=> $(MODNAME).log || error="yes" ; \ if test -n "$(VERBOSE)" -o "$$error" = "yes"; then \ cat $(MODNAME).log ; \ fi ;\ @@ -11,8 +20,6 @@ moddir=$(prefix)/mod - - MODNAME=mod_cdr mod_LTLIBRARIES = mod_cdr.la mod_cdr_la_SOURCES = mod_cdr.cpp cdrcontainer.cpp basecdr.cpp baseregistry.cpp pddcdr.cpp csvcdr.cpp xmlcdr.cpp sqlitecdr.cpp @@ -30,12 +37,6 @@ #mod_cdr_la_CFLAGS += -DSWITCH_QUEUE_ENHANCED #mod_cdr_la_LDFLAGS += -lcurl -#Override link target so we can control the output - -$(MODNAME).la: $(mod_cdr_la_OBJECTS) $(mod_cdr_la_DEPENDENCIES) - @echo Creating $(MODNAME).$(DYNAMIC_LIB_EXTEN)... - @$(CXXLINK) -rpath $(moddir) $(mod_cdr_la_LDFLAGS) $(mod_cdr_la_OBJECTS) $(mod_cdr_la_LIBADD) $(LIBS) $(LINK_OUTPUT_REDIR) - #Override the linstall target so we just install the .so/.dylib install-data-am: $(DESTDIR)$(PREFIX)/$(moddir)/$(MODNAME).$(DYNAMIC_LIB_EXTEN) Modified: freeswitch/branches/mikej/sofiasip-upgrade/src/switch_channel.c ============================================================================== --- freeswitch/branches/mikej/sofiasip-upgrade/src/switch_channel.c (original) +++ freeswitch/branches/mikej/sofiasip-upgrade/src/switch_channel.c Thu Mar 29 00:30:19 2007 @@ -95,6 +95,7 @@ { "MANAGER_REQUEST", SWITCH_CAUSE_MANAGER_REQUEST }, { "BLIND_TRANSFER", SWITCH_CAUSE_BLIND_TRANSFER }, { "ATTENDED_TRANSFER", SWITCH_CAUSE_ATTENDED_TRANSFER }, + { "ALLOTTED_TIMEOUT", SWITCH_CAUSE_ALLOTTED_TIMEOUT}, { NULL, 0 } }; Modified: freeswitch/branches/mikej/sofiasip-upgrade/src/switch_core.c ============================================================================== --- freeswitch/branches/mikej/sofiasip-upgrade/src/switch_core.c (original) +++ freeswitch/branches/mikej/sofiasip-upgrade/src/switch_core.c Thu Mar 29 00:30:19 2007 @@ -147,6 +147,19 @@ SWITCH_DECLARE_DATA switch_directories SWITCH_GLOBAL_dirs = {0}; +struct switch_core_scheduler_task_container { + switch_core_scheduler_task_t task; + time_t executed; + int in_thread; + int destroyed; + switch_core_scheduler_func_t func; + switch_memory_pool_t *pool; + uint32_t flags; + char *desc; + struct switch_core_scheduler_task_container *next; +}; +typedef struct switch_core_scheduler_task_container switch_core_scheduler_task_container_t; + struct switch_core_runtime { switch_time_t initiated; uint32_t session_id; @@ -169,6 +182,10 @@ uint32_t shutting_down; uint8_t running; char uuid_str[SWITCH_UUID_FORMATTED_LENGTH + 1]; + switch_core_scheduler_task_container_t *task_list; + switch_mutex_t *task_mutex; + uint32_t task_id; + int task_thread_running; }; /* Prototypes */ @@ -196,6 +213,238 @@ } } +static void send_heartbeat(void) +{ + switch_event_t *event; + switch_core_time_duration_t duration; + + switch_core_measure_time(switch_core_uptime(), &duration); + + if (switch_event_create(&event, SWITCH_EVENT_HEARTBEAT) == SWITCH_STATUS_SUCCESS) { + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Event-Info", "System Ready"); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Up-Time", + "%u year%s, " + "%u day%s, " + "%u hour%s, " + "%u minute%s, " + "%u second%s, " + "%u millisecond%s, " + "%u microsecond%s\n", + duration.yr, duration.yr == 1 ? "" : "s", + duration.day, duration.day == 1 ? "" : "s", + duration.hr, duration.hr == 1 ? "" : "s", + duration.min, duration.min == 1 ? "" : "s", + duration.sec, duration.sec == 1 ? "" : "s", + duration.ms, duration.ms == 1 ? "" : "s", + duration.mms, duration.mms == 1 ? "" : "s" + ); + + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Session-Count", "%u", switch_core_session_count()); + switch_event_fire(&event); + } +} + +static void heartbeat_callback(switch_core_scheduler_task_t *task) +{ + send_heartbeat(); + + /* reschedule this task */ + task->runtime += 20; +} + +static void switch_core_scheduler_execute(switch_core_scheduler_task_container_t *tp) +{ + //switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Executing task %u %s (%s)\n", tp->task.task_id, tp->desc, switch_str_nil(tp->task.group)); + + tp->func(&tp->task); + + if (tp->task.runtime > tp->executed) { + tp->executed = 0; + } else { + tp->destroyed = 1; + } +} + +static void *SWITCH_THREAD_FUNC task_own_thread(switch_thread_t *thread, void *obj) +{ + switch_core_scheduler_task_container_t *tp = (switch_core_scheduler_task_container_t *) obj; + switch_memory_pool_t *pool; + + pool = tp->pool; + tp->pool = NULL; + + switch_core_scheduler_execute(tp); + switch_core_destroy_memory_pool(&pool); + tp->in_thread = 0; + + return NULL; +} + +static int task_thread_loop(int done) +{ + switch_core_scheduler_task_container_t *tofree, *tp, *last = NULL; + + + switch_mutex_lock(runtime.task_mutex); + for (tp = runtime.task_list; tp; tp = tp->next) { + if (done) { + tp->destroyed = 1; + } else { + time_t now = time(NULL); + if (now >= tp->task.runtime && !tp->in_thread) { + tp->executed = now; + if (switch_test_flag(tp, SSHF_OWN_THREAD)) { + switch_thread_t *thread; + switch_threadattr_t *thd_attr; + assert(switch_core_new_memory_pool(&tp->pool) == SWITCH_STATUS_SUCCESS); + switch_threadattr_create(&thd_attr, tp->pool); + switch_threadattr_detach_set(thd_attr, 1); + tp->in_thread = 1; + switch_thread_create(&thread, thd_attr, task_own_thread, tp, tp->pool); + } else { + switch_core_scheduler_execute(tp); + } + } + } + } + switch_mutex_unlock(runtime.task_mutex); + switch_mutex_lock(runtime.task_mutex); + for (tp = runtime.task_list; tp; ) { + if (tp->destroyed && !tp->in_thread) { + tofree = tp; + tp = tp->next; + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Deleting task %u %s (%s)\n", + tofree->task.task_id, tofree->desc, switch_str_nil(tofree->task.group)); + if (last) { + last->next = tofree->next; + } else { + runtime.task_list = tofree->next; + } + switch_safe_free(tofree->task.group); + if (tofree->task.cmd_arg && switch_test_flag(tofree, SSHF_FREE_ARG)) { + free(tofree->task.cmd_arg); + } + switch_safe_free(tofree->desc); + free(tofree); + } else { + last = tp; + tp = tp->next; + } + } + switch_mutex_unlock(runtime.task_mutex); + + return done; +} + +static void *SWITCH_THREAD_FUNC switch_core_task_thread(switch_thread_t *thread, void *obj) +{ + + runtime.task_thread_running = 1; + + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Starting task thread\n"); + while(runtime.task_thread_running == 1) { + if (task_thread_loop(0)) { + break; + } + switch_yield(500000); + } + + task_thread_loop(1); + + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Task thread ending\n"); + runtime.task_thread_running = 0; + + return NULL; +} + +static void switch_core_task_thread_launch(void) +{ + switch_thread_t *thread; + switch_threadattr_t *thd_attr; + switch_threadattr_create(&thd_attr, runtime.memory_pool); + switch_threadattr_detach_set(thd_attr, 1); + switch_thread_create(&thread, thd_attr, switch_core_task_thread, NULL, runtime.memory_pool); +} + +SWITCH_DECLARE(uint32_t) switch_core_scheduler_add_task(time_t task_runtime, + switch_core_scheduler_func_t func, + char *desc, + char *group, + uint32_t cmd_id, + void *cmd_arg, + switch_scheduler_flag_t flags) +{ + switch_core_scheduler_task_container_t *container, *tp; + + switch_mutex_lock(runtime.task_mutex); + assert((container = malloc(sizeof(*container)))); + memset(container, 0, sizeof(*container)); + assert(func); + container->func = func; + time(&container->task.created); + container->task.runtime = task_runtime; + container->task.group = strdup(group ? group : "none"); + container->task.cmd_id = cmd_id; + container->task.cmd_arg = cmd_arg; + container->flags = flags; + container->desc = strdup(desc ? desc : "none"); + + for (tp = runtime.task_list; tp && tp->next; tp = tp->next); + + if (tp) { + tp->next = container; + } else { + runtime.task_list = container; + } + + for (container->task.task_id = 0; !container->task.task_id; container->task.task_id = ++runtime.task_id); + + switch_mutex_unlock(runtime.task_mutex); + + tp = container; + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Added task %u %s (%s) to run at %"TIME_T_FMT"\n", + tp->task.task_id, tp->desc, switch_str_nil(tp->task.group), task_runtime); + + + return container->task.task_id; +} + +SWITCH_DECLARE(switch_status_t) switch_core_scheduler_del_task_id(uint32_t task_id) +{ + switch_core_scheduler_task_container_t *tp; + switch_status_t status = SWITCH_STATUS_FALSE; + + switch_mutex_lock(runtime.task_mutex); + for (tp = runtime.task_list; tp; tp = tp->next) { + if (tp->task.task_id == task_id) { + tp->destroyed++; + status = SWITCH_STATUS_SUCCESS; + break; + } + } + switch_mutex_unlock(runtime.task_mutex); + + return status; +} + +SWITCH_DECLARE(switch_status_t) switch_core_scheduler_del_task_group(char *group) +{ + switch_core_scheduler_task_container_t *tp; + switch_status_t status = SWITCH_STATUS_FALSE; + + switch_mutex_lock(runtime.task_mutex); + for (tp = runtime.task_list; tp; tp = tp->next) { + if (!strcmp(tp->task.group, group)) { + tp->destroyed++; + status = SWITCH_STATUS_SUCCESS; + } + } + switch_mutex_unlock(runtime.task_mutex); + + return status; +} + + static void switch_core_media_bug_destroy(switch_media_bug_t *bug) { switch_buffer_destroy(&bug->raw_read_buffer); @@ -2148,7 +2397,8 @@ } if (!session->read_codec && (*frame)->codec) { - need_codec = TRUE; + status = SWITCH_STATUS_FALSE; + goto done; } if (session->bugs && !need_codec) { @@ -2174,11 +2424,15 @@ switch (status) { case SWITCH_STATUS_RESAMPLE: if (!session->read_resampler) { - switch_resample_create(&session->read_resampler, + if (switch_resample_create(&session->read_resampler, read_frame->codec->implementation->samples_per_second, read_frame->codec->implementation->bytes_per_frame * 20, session->read_codec->implementation->samples_per_second, - session->read_codec->implementation->bytes_per_frame * 20, session->pool); + session->read_codec->implementation->bytes_per_frame * 20, session->pool) != SWITCH_STATUS_SUCCESS) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Unable to allocate resampler\n"); + status = SWITCH_STATUS_FALSE; + goto done; + } } case SWITCH_STATUS_SUCCESS: session->raw_read_frame.samples = session->raw_read_frame.datalen / sizeof(int16_t); @@ -2418,7 +2672,7 @@ } if (!session->write_codec && frame->codec) { - need_codec = TRUE; + return SWITCH_STATUS_FALSE; } if (session->bugs && !need_codec) { @@ -2448,6 +2702,9 @@ session->write_codec->implementation->samples_per_second, session->write_codec->implementation->bytes_per_frame * 20, session->pool); + if (status != SWITCH_STATUS_SUCCESS) { + goto done; + } } break; case SWITCH_STATUS_SUCCESS: @@ -2652,6 +2909,9 @@ session->write_codec->implementation->samples_per_second, session->write_codec->implementation->bytes_per_frame * 20, session->pool); + if (status != SWITCH_STATUS_SUCCESS) { + goto done; + } } break; case SWITCH_STATUS_SUCCESS: @@ -3143,11 +3403,10 @@ switch_event_t *event; const switch_application_interface_t *application_interface; - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Standard EXECUTE\n"); + if ((extension = switch_channel_get_caller_extension(session->channel)) == 0) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "No Extension!\n"); - switch_channel_hangup(session->channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER); + switch_channel_hangup(session->channel, SWITCH_CAUSE_NORMAL_CLEARING); return; } @@ -3721,6 +3980,8 @@ switch_event_t *event; switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Close Channel %s\n", switch_channel_get_name((*session)->channel)); + + switch_core_scheduler_del_task_group((*session)->uuid_str); switch_mutex_lock(runtime.session_table_mutex); switch_core_hash_delete(runtime.session_table, (*session)->uuid_str); @@ -4133,7 +4394,6 @@ char *sqlbuf = (char *) malloc(sql_len); char *sql; switch_size_t newlen; - uint32_t loops = 0; if (!runtime.event_db) { runtime.event_db = switch_core_db_handle(); @@ -4188,38 +4448,6 @@ *sqlbuf = '\0'; } - if (loops++ >= 5000) { - switch_event_t *event; - switch_core_time_duration_t duration; - - switch_core_measure_time(switch_core_uptime(), &duration); - - if (switch_event_create(&event, SWITCH_EVENT_HEARTBEAT) == SWITCH_STATUS_SUCCESS) { - switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Event-Info", "System Ready"); - switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Up-Time", - "%u year%s, " - "%u day%s, " - "%u hour%s, " - "%u minute%s, " - "%u second%s, " - "%u millisecond%s, " - "%u microsecond%s\n", - duration.yr, duration.yr == 1 ? "" : "s", - duration.day, duration.day == 1 ? "" : "s", - duration.hr, duration.hr == 1 ? "" : "s", - duration.min, duration.min == 1 ? "" : "s", - duration.sec, duration.sec == 1 ? "" : "s", - duration.ms, duration.ms == 1 ? "" : "s", - duration.mms, duration.mms == 1 ? "" : "s" - ); - - switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Session-Count", "%u", switch_core_session_count()); - switch_event_fire(&event); - } - - loops = 0; - } - if (nothing_in_queue) { switch_yield(1000); } @@ -4662,11 +4890,17 @@ runtime.running = 1; switch_core_hash_init(&runtime.session_table, runtime.memory_pool); switch_mutex_init(&runtime.session_table_mutex, SWITCH_MUTEX_NESTED, runtime.memory_pool); + switch_mutex_init(&runtime.task_mutex, SWITCH_MUTEX_NESTED, runtime.memory_pool); #ifdef CRASH_PROT switch_core_hash_init(&runtime.stack_table, runtime.memory_pool); #endif + + + switch_core_task_thread_launch(); runtime.initiated = switch_time_now(); + switch_core_scheduler_add_task(time(NULL), heartbeat_callback, "heartbeat", "core", 0, NULL, SSHF_NONE); + switch_uuid_get(&uuid); switch_uuid_format(runtime.uuid_str, &uuid); @@ -4826,11 +5060,28 @@ while (switch_queue_size(runtime.sql_queue) > 0) { switch_yield(10000); } + + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Stopping Task Thread\n"); + if (runtime.task_thread_running == 1) { + int sanity = 0; + + runtime.task_thread_running = -1; + + while(runtime.task_thread_running) { + switch_yield(100000); + if (++sanity > 10) { + break; + } + } + } + switch_core_db_close(runtime.db); switch_core_db_close(runtime.event_db); switch_xml_destroy(); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Finalizing Shutdown.\n"); switch_log_shutdown(); + + if(runtime.console != stdout && runtime.console != stderr) { fclose(runtime.console); Modified: freeswitch/branches/mikej/sofiasip-upgrade/src/switch_ivr.c ============================================================================== --- freeswitch/branches/mikej/sofiasip-upgrade/src/switch_ivr.c (original) +++ freeswitch/branches/mikej/sofiasip-upgrade/src/switch_ivr.c Thu Mar 29 00:30:19 2007 @@ -130,7 +130,7 @@ if (cause_name) { cause = switch_channel_str2cause(cause_name); } - + switch_channel_hangup(channel, cause); } else if (cmd_hash == CMD_NOMEDIA) { char *uuid = switch_event_get_header(event, "nomedia-uuid"); @@ -3240,6 +3240,157 @@ return SWITCH_STATUS_SUCCESS; } +struct hangup_helper { + char uuid_str[SWITCH_UUID_FORMATTED_LENGTH + 1]; + switch_bool_t bleg; + switch_call_cause_t cause; +}; + +static void sch_hangup_callback(switch_core_scheduler_task_t *task) +{ + struct hangup_helper *helper; + switch_core_session_t *session, *other_session; + char *other_uuid; + + assert(task); + + helper = (struct hangup_helper *) task->cmd_arg; + + if ((session = switch_core_session_locate(helper->uuid_str))) { + switch_channel_t *channel = switch_core_session_get_channel(session); + + if (helper->bleg) { + if ((other_uuid = switch_channel_get_variable(channel, SWITCH_BRIDGE_VARIABLE)) && + (other_session = switch_core_session_locate(other_uuid))) { + switch_channel_t *other_channel = switch_core_session_get_channel(other_session); + switch_channel_hangup(other_channel, helper->cause); + switch_core_session_rwunlock(other_session); + } else { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "No channel to hangup\n"); + } + } else { + switch_channel_hangup(channel, helper->cause); + } + + switch_core_session_rwunlock(session); + } +} + +SWITCH_DECLARE(uint32_t) switch_ivr_schedule_hangup(time_t runtime, char *uuid, switch_call_cause_t cause, switch_bool_t bleg) +{ + struct hangup_helper *helper; + size_t len = sizeof(*helper); + + assert((helper = malloc(len))); + memset(helper, 0, len); + + switch_copy_string(helper->uuid_str, uuid, sizeof(helper->uuid_str)); + helper->cause = cause; + helper->bleg = bleg; + + return switch_core_scheduler_add_task(runtime, sch_hangup_callback, (char *)__SWITCH_FUNC__, uuid, 0, helper, SSHF_FREE_ARG); +} + +struct transfer_helper { + char uuid_str[SWITCH_UUID_FORMATTED_LENGTH + 1]; + char *extension; + char *dialplan; + char *context; +}; + +static void sch_transfer_callback(switch_core_scheduler_task_t *task) +{ + struct transfer_helper *helper; + switch_core_session_t *session; + + assert(task); + + helper = (struct transfer_helper *) task->cmd_arg; + + if ((session = switch_core_session_locate(helper->uuid_str))) { + switch_ivr_session_transfer(session, helper->extension, helper->dialplan, helper->context); + switch_core_session_rwunlock(session); + } + +} + +SWITCH_DECLARE(uint32_t) switch_ivr_schedule_transfer(time_t runtime, char *uuid, char *extension, char *dialplan, char *context) +{ + struct transfer_helper *helper; + size_t len = sizeof(*helper); + char *cur = NULL; + + if (extension) { + len += strlen(extension) + 1; + } + + if (dialplan) { + len += strlen(dialplan) + 1; + } + + if (context) { + len += strlen(context) + 1; + } + + assert((helper = malloc(len))); + memset(helper, 0, len); + + switch_copy_string(helper->uuid_str, uuid, sizeof(helper->uuid_str)); + + cur = (char *) helper + sizeof(*helper); + + if (extension) { + helper->extension = cur; + switch_copy_string(helper->extension, extension, strlen(extension) + 1); + cur += strlen(helper->extension) + 1; + } + + if (dialplan) { + helper->dialplan = cur; + switch_copy_string(helper->dialplan, dialplan, strlen(dialplan) + 1); + cur += strlen(helper->dialplan) + 1; + } + + if (context) { + helper->context = cur; + switch_copy_string(helper->context, context, strlen(context)+1); + } + + return switch_core_scheduler_add_task(runtime, sch_transfer_callback, (char *)__SWITCH_FUNC__, uuid, 0, helper, SSHF_FREE_ARG); +} + + +struct broadcast_helper { + char uuid_str[SWITCH_UUID_FORMATTED_LENGTH + 1]; + char *path; + switch_media_flag_t flags; +}; + +static void sch_broadcast_callback(switch_core_scheduler_task_t *task) +{ + struct broadcast_helper *helper; + assert(task); + + helper = (struct broadcast_helper *) task->cmd_arg; + switch_ivr_broadcast(helper->uuid_str, helper->path, helper->flags); +} + +SWITCH_DECLARE(uint32_t) switch_ivr_schedule_broadcast(time_t runtime, char *uuid, char *path, switch_media_flag_t flags) +{ + struct broadcast_helper *helper; + size_t len = sizeof(*helper) + strlen(path) + 1; + + assert((helper = malloc(len))); + memset(helper, 0, len); + + switch_copy_string(helper->uuid_str, uuid, sizeof(helper->uuid_str)); + helper->flags = flags; + helper->path = (char *) helper + sizeof(*helper); + switch_copy_string(helper->path, path, len - sizeof(helper)); + + + return switch_core_scheduler_add_task(runtime, sch_broadcast_callback, (char *)__SWITCH_FUNC__, uuid, 0, helper, SSHF_FREE_ARG); +} SWITCH_DECLARE(switch_status_t) switch_ivr_broadcast(char *uuid, char *path, switch_media_flag_t flags) { @@ -3249,9 +3400,15 @@ switch_event_t *event; switch_core_session_t *other_session = NULL; char *other_uuid = NULL; + char *app = "playback"; + + assert(path); if ((session = switch_core_session_locate(uuid))) { - char *app; + char *cause = NULL; + char *mypath = strdup(path); + char *p; + master = session; channel = switch_core_session_get_channel(session); @@ -3261,11 +3418,17 @@ switch_ivr_media(uuid, SMF_REBRIDGE); } - if (!strncasecmp(path, "speak:", 6)) { - path += 6; - app = "speak"; - } else { - app = "playback"; + if ((p = strchr(mypath, ':'))) { + app = mypath; + *p++ = '\0'; + path = p; + } + + if ((cause = strchr(app, '!'))) { + *cause++ = '\0'; + if (!cause) { + cause = "normal_clearing"; + } } if ((flags & SMF_ECHO_BLEG) && (other_uuid = switch_channel_get_variable(channel, SWITCH_BRIDGE_VARIABLE)) @@ -3299,8 +3462,21 @@ } } + if (cause) { + if (switch_event_create(&event, SWITCH_EVENT_MESSAGE) == SWITCH_STATUS_SUCCESS) { + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "call-command", "execute"); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "execute-app-name", "hangup"); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "execute-app-arg", "%s", cause); + + switch_core_session_queue_private_event(session, &event); + } + } + switch_core_session_rwunlock(session); + switch_safe_free(mypath); } + + return SWITCH_STATUS_SUCCESS; } @@ -3449,11 +3625,16 @@ switch_channel_set_variable(channel, SWITCH_BRIDGE_VARIABLE, NULL); switch_channel_set_variable(other_channel, SWITCH_BRIDGE_VARIABLE, NULL); - switch_channel_hangup(other_channel, switch_channel_get_cause(channel)); + if (switch_channel_get_state(other_channel) < CS_HANGUP && + switch_true(switch_channel_get_variable(other_channel, SWITCH_HANGUP_AFTER_BRIDGE_VARIABLE))) { + switch_channel_hangup(other_channel, switch_channel_get_cause(channel)); + } else { + switch_channel_set_state(other_channel, CS_EXECUTE); + } switch_core_session_rwunlock(other_session); } - + return SWITCH_STATUS_SUCCESS; } Modified: freeswitch/branches/mikej/sofiasip-upgrade/src/switch_resample.c ============================================================================== --- freeswitch/branches/mikej/sofiasip-upgrade/src/switch_resample.c (original) +++ freeswitch/branches/mikej/sofiasip-upgrade/src/switch_resample.c Thu Mar 29 00:30:19 2007 @@ -31,7 +31,12 @@ */ #include <switch.h> #include <switch_resample.h> +#ifndef WIN32 +#include <switch_private.h> +#endif +#ifndef DISABLE_RESAMPLE #include <libresample.h> +#endif #define NORMFACT (float)0x8000 #define MAXSAMPLE (float)0x7FFF #define MAXSAMPLEC (char)0x7F @@ -52,6 +57,10 @@ switch_size_t from_size, int to_rate, uint32_t to_size, switch_memory_pool_t *pool) { +#ifdef DISABLE_RESAMPLE + *new_resampler = NULL; + return SWITCH_STATUS_NOTIMPL; +#else switch_audio_resampler_t *resampler; double lto_rate, lfrom_rate; @@ -75,12 +84,16 @@ *new_resampler = resampler; return SWITCH_STATUS_SUCCESS; +#endif } SWITCH_DECLARE(uint32_t) switch_resample_process(switch_audio_resampler_t *resampler, float *src, int srclen, float *dst, uint32_t dstlen, int last) { +#ifdef DISABLE_RESAMPLE + return 0; +#else int o = 0, srcused = 0, srcpos = 0, out = 0; for (;;) { @@ -99,11 +112,14 @@ } } return out; +#endif } SWITCH_DECLARE(void) switch_resample_destroy(switch_audio_resampler_t *resampler) { +#ifndef DISABLE_RESAMPLE resample_close(resampler->resampler); +#endif }
participants (1)
-
Freeswitch SVN