2005-11-19 20:07:43 +00:00
|
|
|
/*
|
|
|
|
* FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
|
2011-01-05 16:08:55 +00:00
|
|
|
* Copyright (C) 2005-2011, Anthony Minessale II <anthm@freeswitch.org>
|
2005-11-19 20:07:43 +00:00
|
|
|
*
|
|
|
|
* Version: MPL 1.1
|
|
|
|
*
|
|
|
|
* The contents of this file are subject to the Mozilla Public License Version
|
|
|
|
* 1.1 (the "License"); you may not use this file except in compliance with
|
|
|
|
* the License. You may obtain a copy of the License at
|
|
|
|
* http://www.mozilla.org/MPL/
|
|
|
|
*
|
|
|
|
* Software distributed under the License is distributed on an "AS IS" basis,
|
|
|
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
|
|
|
* for the specific language governing rights and limitations under the
|
|
|
|
* License.
|
|
|
|
*
|
|
|
|
* The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
|
|
|
|
*
|
|
|
|
* The Initial Developer of the Original Code is
|
2009-02-04 21:20:54 +00:00
|
|
|
* Anthony Minessale II <anthm@freeswitch.org>
|
2005-11-19 20:07:43 +00:00
|
|
|
* Portions created by the Initial Developer are Copyright (C)
|
|
|
|
* the Initial Developer. All Rights Reserved.
|
|
|
|
*
|
|
|
|
* Contributor(s):
|
|
|
|
*
|
2009-02-04 21:20:54 +00:00
|
|
|
* Anthony Minessale II <anthm@freeswitch.org>
|
2006-09-18 05:08:55 +00:00
|
|
|
* Michael Jerris <mike@jerris.com>
|
2005-11-19 20:07:43 +00:00
|
|
|
*
|
|
|
|
*
|
|
|
|
* switch_channel.c -- Media Channel Interface
|
|
|
|
*
|
|
|
|
*/
|
2008-01-27 17:36:53 +00:00
|
|
|
|
2006-04-29 01:00:52 +00:00
|
|
|
#include <switch.h>
|
2006-04-29 06:05:03 +00:00
|
|
|
#include <switch_channel.h>
|
2005-11-19 20:07:43 +00:00
|
|
|
|
2006-04-22 18:12:17 +00:00
|
|
|
struct switch_cause_table {
|
|
|
|
const char *name;
|
|
|
|
switch_call_cause_t cause;
|
|
|
|
};
|
|
|
|
|
|
|
|
static struct switch_cause_table CAUSE_CHART[] = {
|
2008-07-03 22:51:09 +00:00
|
|
|
{"NONE", SWITCH_CAUSE_NONE},
|
2008-07-23 14:19:53 +00:00
|
|
|
{"UNALLOCATED_NUMBER", SWITCH_CAUSE_UNALLOCATED_NUMBER},
|
2007-03-29 22:31:56 +00:00
|
|
|
{"NO_ROUTE_TRANSIT_NET", SWITCH_CAUSE_NO_ROUTE_TRANSIT_NET},
|
|
|
|
{"NO_ROUTE_DESTINATION", SWITCH_CAUSE_NO_ROUTE_DESTINATION},
|
|
|
|
{"CHANNEL_UNACCEPTABLE", SWITCH_CAUSE_CHANNEL_UNACCEPTABLE},
|
|
|
|
{"CALL_AWARDED_DELIVERED", SWITCH_CAUSE_CALL_AWARDED_DELIVERED},
|
|
|
|
{"NORMAL_CLEARING", SWITCH_CAUSE_NORMAL_CLEARING},
|
|
|
|
{"USER_BUSY", SWITCH_CAUSE_USER_BUSY},
|
|
|
|
{"NO_USER_RESPONSE", SWITCH_CAUSE_NO_USER_RESPONSE},
|
|
|
|
{"NO_ANSWER", SWITCH_CAUSE_NO_ANSWER},
|
|
|
|
{"SUBSCRIBER_ABSENT", SWITCH_CAUSE_SUBSCRIBER_ABSENT},
|
|
|
|
{"CALL_REJECTED", SWITCH_CAUSE_CALL_REJECTED},
|
|
|
|
{"NUMBER_CHANGED", SWITCH_CAUSE_NUMBER_CHANGED},
|
|
|
|
{"REDIRECTION_TO_NEW_DESTINATION", SWITCH_CAUSE_REDIRECTION_TO_NEW_DESTINATION},
|
|
|
|
{"EXCHANGE_ROUTING_ERROR", SWITCH_CAUSE_EXCHANGE_ROUTING_ERROR},
|
|
|
|
{"DESTINATION_OUT_OF_ORDER", SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER},
|
|
|
|
{"INVALID_NUMBER_FORMAT", SWITCH_CAUSE_INVALID_NUMBER_FORMAT},
|
|
|
|
{"FACILITY_REJECTED", SWITCH_CAUSE_FACILITY_REJECTED},
|
|
|
|
{"RESPONSE_TO_STATUS_ENQUIRY", SWITCH_CAUSE_RESPONSE_TO_STATUS_ENQUIRY},
|
|
|
|
{"NORMAL_UNSPECIFIED", SWITCH_CAUSE_NORMAL_UNSPECIFIED},
|
|
|
|
{"NORMAL_CIRCUIT_CONGESTION", SWITCH_CAUSE_NORMAL_CIRCUIT_CONGESTION},
|
|
|
|
{"NETWORK_OUT_OF_ORDER", SWITCH_CAUSE_NETWORK_OUT_OF_ORDER},
|
|
|
|
{"NORMAL_TEMPORARY_FAILURE", SWITCH_CAUSE_NORMAL_TEMPORARY_FAILURE},
|
|
|
|
{"SWITCH_CONGESTION", SWITCH_CAUSE_SWITCH_CONGESTION},
|
|
|
|
{"ACCESS_INFO_DISCARDED", SWITCH_CAUSE_ACCESS_INFO_DISCARDED},
|
|
|
|
{"REQUESTED_CHAN_UNAVAIL", SWITCH_CAUSE_REQUESTED_CHAN_UNAVAIL},
|
|
|
|
{"PRE_EMPTED", SWITCH_CAUSE_PRE_EMPTED},
|
|
|
|
{"FACILITY_NOT_SUBSCRIBED", SWITCH_CAUSE_FACILITY_NOT_SUBSCRIBED},
|
|
|
|
{"OUTGOING_CALL_BARRED", SWITCH_CAUSE_OUTGOING_CALL_BARRED},
|
|
|
|
{"INCOMING_CALL_BARRED", SWITCH_CAUSE_INCOMING_CALL_BARRED},
|
|
|
|
{"BEARERCAPABILITY_NOTAUTH", SWITCH_CAUSE_BEARERCAPABILITY_NOTAUTH},
|
|
|
|
{"BEARERCAPABILITY_NOTAVAIL", SWITCH_CAUSE_BEARERCAPABILITY_NOTAVAIL},
|
|
|
|
{"SERVICE_UNAVAILABLE", SWITCH_CAUSE_SERVICE_UNAVAILABLE},
|
|
|
|
{"CHAN_NOT_IMPLEMENTED", SWITCH_CAUSE_CHAN_NOT_IMPLEMENTED},
|
|
|
|
{"FACILITY_NOT_IMPLEMENTED", SWITCH_CAUSE_FACILITY_NOT_IMPLEMENTED},
|
|
|
|
{"SERVICE_NOT_IMPLEMENTED", SWITCH_CAUSE_SERVICE_NOT_IMPLEMENTED},
|
|
|
|
{"INVALID_CALL_REFERENCE", SWITCH_CAUSE_INVALID_CALL_REFERENCE},
|
|
|
|
{"INCOMPATIBLE_DESTINATION", SWITCH_CAUSE_INCOMPATIBLE_DESTINATION},
|
|
|
|
{"INVALID_MSG_UNSPECIFIED", SWITCH_CAUSE_INVALID_MSG_UNSPECIFIED},
|
|
|
|
{"MANDATORY_IE_MISSING", SWITCH_CAUSE_MANDATORY_IE_MISSING},
|
|
|
|
{"MESSAGE_TYPE_NONEXIST", SWITCH_CAUSE_MESSAGE_TYPE_NONEXIST},
|
|
|
|
{"WRONG_MESSAGE", SWITCH_CAUSE_WRONG_MESSAGE},
|
|
|
|
{"IE_NONEXIST", SWITCH_CAUSE_IE_NONEXIST},
|
|
|
|
{"INVALID_IE_CONTENTS", SWITCH_CAUSE_INVALID_IE_CONTENTS},
|
|
|
|
{"WRONG_CALL_STATE", SWITCH_CAUSE_WRONG_CALL_STATE},
|
|
|
|
{"RECOVERY_ON_TIMER_EXPIRE", SWITCH_CAUSE_RECOVERY_ON_TIMER_EXPIRE},
|
|
|
|
{"MANDATORY_IE_LENGTH_ERROR", SWITCH_CAUSE_MANDATORY_IE_LENGTH_ERROR},
|
|
|
|
{"PROTOCOL_ERROR", SWITCH_CAUSE_PROTOCOL_ERROR},
|
|
|
|
{"INTERWORKING", SWITCH_CAUSE_INTERWORKING},
|
2008-07-03 22:51:09 +00:00
|
|
|
{"SUCCESS", SWITCH_CAUSE_SUCCESS},
|
2007-03-29 22:31:56 +00:00
|
|
|
{"ORIGINATOR_CANCEL", SWITCH_CAUSE_ORIGINATOR_CANCEL},
|
|
|
|
{"CRASH", SWITCH_CAUSE_CRASH},
|
|
|
|
{"SYSTEM_SHUTDOWN", SWITCH_CAUSE_SYSTEM_SHUTDOWN},
|
|
|
|
{"LOSE_RACE", SWITCH_CAUSE_LOSE_RACE},
|
|
|
|
{"MANAGER_REQUEST", SWITCH_CAUSE_MANAGER_REQUEST},
|
|
|
|
{"BLIND_TRANSFER", SWITCH_CAUSE_BLIND_TRANSFER},
|
|
|
|
{"ATTENDED_TRANSFER", SWITCH_CAUSE_ATTENDED_TRANSFER},
|
|
|
|
{"ALLOTTED_TIMEOUT", SWITCH_CAUSE_ALLOTTED_TIMEOUT},
|
2007-06-08 22:28:32 +00:00
|
|
|
{"USER_CHALLENGE", SWITCH_CAUSE_USER_CHALLENGE},
|
2007-10-31 13:08:45 +00:00
|
|
|
{"MEDIA_TIMEOUT", SWITCH_CAUSE_MEDIA_TIMEOUT},
|
2007-12-08 00:14:21 +00:00
|
|
|
{"PICKED_OFF", SWITCH_CAUSE_PICKED_OFF},
|
2008-08-11 16:12:55 +00:00
|
|
|
{"USER_NOT_REGISTERED", SWITCH_CAUSE_USER_NOT_REGISTERED},
|
2008-10-09 00:38:59 +00:00
|
|
|
{"PROGRESS_TIMEOUT", SWITCH_CAUSE_PROGRESS_TIMEOUT},
|
2007-03-29 22:31:56 +00:00
|
|
|
{NULL, 0}
|
2006-04-22 18:12:17 +00:00
|
|
|
};
|
|
|
|
|
2010-05-03 17:29:56 +00:00
|
|
|
typedef enum {
|
|
|
|
OCF_HANGUP = (1 << 0)
|
|
|
|
} opaque_channel_flag_t;
|
|
|
|
|
2005-11-19 20:07:43 +00:00
|
|
|
struct switch_channel {
|
|
|
|
char *name;
|
2009-02-23 16:31:59 +00:00
|
|
|
switch_call_direction_t direction;
|
2007-12-22 00:32:20 +00:00
|
|
|
switch_queue_t *dtmf_queue;
|
2009-02-23 16:31:59 +00:00
|
|
|
switch_queue_t *dtmf_log_queue;
|
2005-12-06 21:25:56 +00:00
|
|
|
switch_mutex_t *dtmf_mutex;
|
2006-06-22 23:56:09 +00:00
|
|
|
switch_mutex_t *flag_mutex;
|
2009-02-20 18:31:08 +00:00
|
|
|
switch_mutex_t *state_mutex;
|
2006-04-28 19:46:57 +00:00
|
|
|
switch_mutex_t *profile_mutex;
|
2006-04-29 06:05:03 +00:00
|
|
|
switch_core_session_t *session;
|
2006-04-29 23:43:28 +00:00
|
|
|
switch_channel_state_t state;
|
2007-12-08 00:14:21 +00:00
|
|
|
switch_channel_state_t running_state;
|
2010-06-05 00:03:36 +00:00
|
|
|
switch_channel_callstate_t callstate;
|
2009-08-26 17:42:36 +00:00
|
|
|
uint32_t flags[CF_FLAG_MAX];
|
2009-10-14 19:26:10 +00:00
|
|
|
uint32_t caps[CC_FLAG_MAX];
|
2008-12-11 15:20:24 +00:00
|
|
|
uint8_t state_flags[CF_FLAG_MAX];
|
2008-12-04 04:46:10 +00:00
|
|
|
uint32_t private_flags;
|
2006-04-29 06:05:03 +00:00
|
|
|
switch_caller_profile_t *caller_profile;
|
|
|
|
const switch_state_handler_table_t *state_handlers[SWITCH_MAX_STATE_HANDLERS];
|
2006-02-07 20:47:15 +00:00
|
|
|
int state_handler_index;
|
2007-09-29 01:06:08 +00:00
|
|
|
switch_event_t *variables;
|
2006-09-07 03:58:01 +00:00
|
|
|
switch_hash_t *private_hash;
|
2010-07-22 19:37:21 +00:00
|
|
|
switch_hash_t *app_flag_hash;
|
2006-04-21 23:16:26 +00:00
|
|
|
switch_call_cause_t hangup_cause;
|
2007-04-28 21:48:03 +00:00
|
|
|
int vi;
|
2007-12-15 00:39:53 +00:00
|
|
|
int event_count;
|
2008-02-26 23:29:58 +00:00
|
|
|
int profile_index;
|
2010-05-03 17:29:56 +00:00
|
|
|
opaque_channel_flag_t opaque_flags;
|
2005-11-19 20:07:43 +00:00
|
|
|
};
|
|
|
|
|
2010-06-05 00:03:36 +00:00
|
|
|
|
2007-05-12 14:48:14 +00:00
|
|
|
SWITCH_DECLARE(const char *) switch_channel_cause2str(switch_call_cause_t cause)
|
2006-04-22 18:12:17 +00:00
|
|
|
{
|
|
|
|
uint8_t x;
|
2007-05-12 14:48:14 +00:00
|
|
|
const char *str = "UNKNOWN";
|
2006-04-22 18:12:17 +00:00
|
|
|
|
2008-05-27 04:30:03 +00:00
|
|
|
for (x = 0; x < (sizeof(CAUSE_CHART) / sizeof(struct switch_cause_table)) - 1; x++) {
|
2006-04-22 18:12:17 +00:00
|
|
|
if (CAUSE_CHART[x].cause == cause) {
|
2007-05-12 14:48:14 +00:00
|
|
|
str = CAUSE_CHART[x].name;
|
2008-05-21 20:00:00 +00:00
|
|
|
break;
|
2006-04-22 18:12:17 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return str;
|
|
|
|
}
|
|
|
|
|
2007-05-12 14:48:14 +00:00
|
|
|
SWITCH_DECLARE(switch_call_cause_t) switch_channel_str2cause(const char *str)
|
2006-04-22 18:12:17 +00:00
|
|
|
{
|
|
|
|
uint8_t x;
|
2008-07-03 22:51:09 +00:00
|
|
|
switch_call_cause_t cause = SWITCH_CAUSE_NONE;
|
2006-04-22 18:12:17 +00:00
|
|
|
|
2007-07-03 21:05:41 +00:00
|
|
|
if (*str > 47 && *str < 58) {
|
|
|
|
cause = atoi(str);
|
|
|
|
} else {
|
2008-05-21 20:00:00 +00:00
|
|
|
for (x = 0; x < (sizeof(CAUSE_CHART) / sizeof(struct switch_cause_table)) - 1 && CAUSE_CHART[x].name; x++) {
|
2007-07-03 21:05:41 +00:00
|
|
|
if (!strcasecmp(CAUSE_CHART[x].name, str)) {
|
|
|
|
cause = CAUSE_CHART[x].cause;
|
2008-05-21 20:00:00 +00:00
|
|
|
break;
|
2007-07-03 21:05:41 +00:00
|
|
|
}
|
2006-04-22 18:12:17 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return cause;
|
|
|
|
}
|
|
|
|
|
2006-04-29 06:05:03 +00:00
|
|
|
SWITCH_DECLARE(switch_call_cause_t) switch_channel_get_cause(switch_channel_t *channel)
|
2006-04-22 18:12:17 +00:00
|
|
|
{
|
|
|
|
return channel->hangup_cause;
|
|
|
|
}
|
|
|
|
|
2008-11-27 04:02:57 +00:00
|
|
|
|
2010-06-05 00:03:36 +00:00
|
|
|
struct switch_callstate_table {
|
|
|
|
const char *name;
|
|
|
|
switch_channel_callstate_t callstate;
|
|
|
|
};
|
|
|
|
static struct switch_callstate_table STATE_CHART[] = {
|
|
|
|
{"DOWN", CCS_DOWN},
|
|
|
|
{"DIALING", CCS_DIALING},
|
|
|
|
{"RINGING", CCS_RINGING},
|
|
|
|
{"EARLY", CCS_EARLY},
|
|
|
|
{"ACTIVE", CCS_ACTIVE},
|
|
|
|
{"HELD", CCS_HELD},
|
|
|
|
{"HANGUP", CCS_HANGUP},
|
|
|
|
{NULL, 0}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2010-06-07 23:01:02 +00:00
|
|
|
SWITCH_DECLARE(void) switch_channel_perform_set_callstate(switch_channel_t *channel, switch_channel_callstate_t callstate,
|
|
|
|
const char *file, const char *func, int line)
|
2010-06-05 00:03:36 +00:00
|
|
|
{
|
2010-06-07 23:01:02 +00:00
|
|
|
switch_event_t *event;
|
|
|
|
switch_channel_callstate_t o_callstate = channel->callstate;
|
|
|
|
|
|
|
|
if (o_callstate == callstate) return;
|
|
|
|
|
2010-06-05 00:03:36 +00:00
|
|
|
channel->callstate = callstate;
|
2010-06-07 23:01:02 +00:00
|
|
|
|
|
|
|
switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, func, line, switch_channel_get_uuid(channel), SWITCH_LOG_DEBUG,
|
|
|
|
"(%s) Callstate Change %s -> %s\n", channel->name,
|
|
|
|
switch_channel_callstate2str(o_callstate), switch_channel_callstate2str(callstate));
|
|
|
|
|
|
|
|
if (switch_event_create(&event, SWITCH_EVENT_CHANNEL_CALLSTATE) == SWITCH_STATUS_SUCCESS) {
|
|
|
|
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Original-Channel-Call-State", switch_channel_callstate2str(o_callstate));
|
|
|
|
switch_channel_event_set_data(channel, event);
|
|
|
|
switch_event_fire(&event);
|
|
|
|
}
|
2010-06-05 00:03:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
SWITCH_DECLARE(switch_channel_callstate_t) switch_channel_get_callstate(switch_channel_t *channel)
|
|
|
|
{
|
|
|
|
return channel->callstate;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
SWITCH_DECLARE(const char *) switch_channel_callstate2str(switch_channel_callstate_t callstate)
|
|
|
|
{
|
|
|
|
uint8_t x;
|
|
|
|
const char *str = "UNKNOWN";
|
|
|
|
|
|
|
|
for (x = 0; x < (sizeof(STATE_CHART) / sizeof(struct switch_cause_table)) - 1; x++) {
|
|
|
|
if (STATE_CHART[x].callstate == callstate) {
|
|
|
|
str = STATE_CHART[x].name;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return str;
|
|
|
|
}
|
|
|
|
|
|
|
|
SWITCH_DECLARE(switch_call_cause_t) switch_channel_str2callstate(const char *str)
|
|
|
|
{
|
|
|
|
uint8_t x;
|
|
|
|
switch_channel_callstate_t callstate = SWITCH_CAUSE_NONE;
|
|
|
|
|
|
|
|
if (*str > 47 && *str < 58) {
|
|
|
|
callstate = atoi(str);
|
|
|
|
} else {
|
|
|
|
for (x = 0; x < (sizeof(STATE_CHART) / sizeof(struct switch_callstate_table)) - 1 && STATE_CHART[x].name; x++) {
|
|
|
|
if (!strcasecmp(STATE_CHART[x].name, str)) {
|
|
|
|
callstate = STATE_CHART[x].callstate;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return callstate;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2010-02-18 17:26:15 +00:00
|
|
|
SWITCH_DECLARE(void) switch_channel_perform_audio_sync(switch_channel_t *channel, const char *file, const char *func, int line)
|
2008-11-27 04:02:57 +00:00
|
|
|
{
|
|
|
|
if (switch_channel_media_ready(channel)) {
|
2009-10-12 22:23:55 +00:00
|
|
|
switch_core_session_message_t msg = { 0 };
|
2008-11-27 04:02:57 +00:00
|
|
|
msg.message_id = SWITCH_MESSAGE_INDICATE_AUDIO_SYNC;
|
|
|
|
msg.from = channel->name;
|
2010-02-18 17:26:15 +00:00
|
|
|
msg._file = file;
|
|
|
|
msg._func = func;
|
|
|
|
msg._line = line;
|
2008-11-27 04:02:57 +00:00
|
|
|
switch_core_session_receive_message(channel->session, &msg);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2008-09-24 21:19:29 +00:00
|
|
|
SWITCH_DECLARE(switch_call_cause_t) switch_channel_cause_q850(switch_call_cause_t cause)
|
|
|
|
{
|
|
|
|
if (cause <= SWITCH_CAUSE_INTERWORKING) {
|
|
|
|
return cause;
|
|
|
|
} else {
|
|
|
|
return SWITCH_CAUSE_NORMAL_CLEARING;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
SWITCH_DECLARE(switch_call_cause_t) switch_channel_get_cause_q850(switch_channel_t *channel)
|
|
|
|
{
|
|
|
|
return switch_channel_cause_q850(channel->hangup_cause);
|
|
|
|
}
|
|
|
|
|
2006-04-29 06:05:03 +00:00
|
|
|
SWITCH_DECLARE(switch_channel_timetable_t *) switch_channel_get_timetable(switch_channel_t *channel)
|
2006-02-24 22:22:43 +00:00
|
|
|
{
|
2007-03-29 22:31:56 +00:00
|
|
|
switch_channel_timetable_t *times = NULL;
|
2006-12-01 15:26:37 +00:00
|
|
|
|
2007-03-29 22:31:56 +00:00
|
|
|
if (channel->caller_profile) {
|
|
|
|
switch_mutex_lock(channel->profile_mutex);
|
|
|
|
times = channel->caller_profile->times;
|
|
|
|
switch_mutex_unlock(channel->profile_mutex);
|
|
|
|
}
|
2006-12-01 15:26:37 +00:00
|
|
|
|
|
|
|
return times;
|
2006-02-24 22:22:43 +00:00
|
|
|
}
|
2005-11-19 20:07:43 +00:00
|
|
|
|
2009-04-21 17:47:22 +00:00
|
|
|
SWITCH_DECLARE(switch_call_direction_t) switch_channel_direction(switch_channel_t *channel)
|
|
|
|
{
|
|
|
|
return channel->direction;
|
|
|
|
}
|
|
|
|
|
2009-02-23 16:31:59 +00:00
|
|
|
SWITCH_DECLARE(switch_status_t) switch_channel_alloc(switch_channel_t **channel, switch_call_direction_t direction, switch_memory_pool_t *pool)
|
2005-11-19 20:07:43 +00:00
|
|
|
{
|
2007-12-11 19:23:57 +00:00
|
|
|
switch_assert(pool != NULL);
|
2005-11-19 20:07:43 +00:00
|
|
|
|
2006-04-29 06:05:03 +00:00
|
|
|
if (((*channel) = switch_core_alloc(pool, sizeof(switch_channel_t))) == 0) {
|
2005-11-19 20:07:43 +00:00
|
|
|
return SWITCH_STATUS_MEMERR;
|
|
|
|
}
|
2008-01-28 07:26:10 +00:00
|
|
|
|
2009-03-24 23:44:03 +00:00
|
|
|
switch_event_create_plain(&(*channel)->variables, SWITCH_EVENT_CHANNEL_DATA);
|
2008-01-28 07:26:10 +00:00
|
|
|
|
2006-09-07 03:58:01 +00:00
|
|
|
switch_core_hash_init(&(*channel)->private_hash, pool);
|
2009-02-23 16:31:59 +00:00
|
|
|
switch_queue_create(&(*channel)->dtmf_queue, SWITCH_DTMF_LOG_LEN, pool);
|
|
|
|
switch_queue_create(&(*channel)->dtmf_log_queue, SWITCH_DTMF_LOG_LEN, pool);
|
2006-09-08 18:57:24 +00:00
|
|
|
|
2005-12-06 21:25:56 +00:00
|
|
|
switch_mutex_init(&(*channel)->dtmf_mutex, SWITCH_MUTEX_NESTED, pool);
|
2006-06-22 23:56:09 +00:00
|
|
|
switch_mutex_init(&(*channel)->flag_mutex, SWITCH_MUTEX_NESTED, pool);
|
2009-02-20 18:31:08 +00:00
|
|
|
switch_mutex_init(&(*channel)->state_mutex, SWITCH_MUTEX_NESTED, pool);
|
2006-04-28 19:46:57 +00:00
|
|
|
switch_mutex_init(&(*channel)->profile_mutex, SWITCH_MUTEX_NESTED, pool);
|
2008-07-03 22:51:09 +00:00
|
|
|
(*channel)->hangup_cause = SWITCH_CAUSE_NONE;
|
2008-02-26 23:29:58 +00:00
|
|
|
(*channel)->name = "";
|
2009-02-23 16:31:59 +00:00
|
|
|
(*channel)->direction = direction;
|
2010-04-26 09:18:46 +00:00
|
|
|
switch_channel_set_variable(*channel, "direction", switch_channel_direction(*channel) == SWITCH_CALL_DIRECTION_OUTBOUND ? "outbound" : "inbound");
|
2005-12-22 01:57:32 +00:00
|
|
|
|
2005-11-19 20:07:43 +00:00
|
|
|
return SWITCH_STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2006-04-29 06:05:03 +00:00
|
|
|
SWITCH_DECLARE(switch_size_t) switch_channel_has_dtmf(switch_channel_t *channel)
|
2005-11-19 20:07:43 +00:00
|
|
|
{
|
2006-03-30 23:02:50 +00:00
|
|
|
switch_size_t has;
|
2005-11-19 20:07:43 +00:00
|
|
|
|
2005-12-06 21:25:56 +00:00
|
|
|
switch_mutex_lock(channel->dtmf_mutex);
|
2007-12-22 00:32:20 +00:00
|
|
|
has = switch_queue_size(channel->dtmf_queue);
|
2005-12-06 21:25:56 +00:00
|
|
|
switch_mutex_unlock(channel->dtmf_mutex);
|
|
|
|
|
|
|
|
return has;
|
2005-11-19 20:07:43 +00:00
|
|
|
}
|
|
|
|
|
2007-12-22 00:32:20 +00:00
|
|
|
SWITCH_DECLARE(switch_status_t) switch_channel_queue_dtmf(switch_channel_t *channel, const switch_dtmf_t *dtmf)
|
2005-11-19 20:07:43 +00:00
|
|
|
{
|
2006-04-29 23:43:28 +00:00
|
|
|
switch_status_t status;
|
2007-12-22 00:32:20 +00:00
|
|
|
void *pop;
|
2008-02-21 21:38:49 +00:00
|
|
|
switch_dtmf_t new_dtmf;
|
2008-05-27 04:30:03 +00:00
|
|
|
|
2008-02-21 21:38:49 +00:00
|
|
|
switch_assert(dtmf);
|
2005-12-21 22:25:22 +00:00
|
|
|
|
2008-05-27 04:30:03 +00:00
|
|
|
switch_mutex_lock(channel->dtmf_mutex);
|
2008-02-21 21:38:49 +00:00
|
|
|
new_dtmf = *dtmf;
|
2008-05-27 04:30:03 +00:00
|
|
|
|
2007-06-12 21:00:26 +00:00
|
|
|
if ((status = switch_core_session_recv_dtmf(channel->session, dtmf) != SWITCH_STATUS_SUCCESS)) {
|
|
|
|
goto done;
|
|
|
|
}
|
2006-03-30 23:02:50 +00:00
|
|
|
|
2008-02-21 21:38:49 +00:00
|
|
|
if (is_dtmf(new_dtmf.digit)) {
|
2007-12-22 00:32:20 +00:00
|
|
|
switch_dtmf_t *dt;
|
|
|
|
int x = 0;
|
|
|
|
|
2008-04-18 17:03:34 +00:00
|
|
|
if (new_dtmf.duration > switch_core_max_dtmf_duration(0)) {
|
2009-08-13 20:35:02 +00:00
|
|
|
switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_WARNING, "%s EXCESSIVE DTMF DIGIT [%c] LEN [%d]\n",
|
2008-02-21 21:38:49 +00:00
|
|
|
switch_channel_get_name(channel), new_dtmf.digit, new_dtmf.duration);
|
2008-04-18 17:03:34 +00:00
|
|
|
new_dtmf.duration = switch_core_max_dtmf_duration(0);
|
2009-09-16 21:24:22 +00:00
|
|
|
} else if (new_dtmf.duration < switch_core_min_dtmf_duration(0)) {
|
|
|
|
switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_WARNING, "%s SHORT DTMF DIGIT [%c] LEN [%d]\n",
|
|
|
|
switch_channel_get_name(channel), new_dtmf.digit, new_dtmf.duration);
|
|
|
|
new_dtmf.duration = switch_core_min_dtmf_duration(0);
|
2008-02-21 21:38:49 +00:00
|
|
|
} else if (!new_dtmf.duration) {
|
2008-04-18 17:03:34 +00:00
|
|
|
new_dtmf.duration = switch_core_default_dtmf_duration(0);
|
2008-02-21 21:38:49 +00:00
|
|
|
}
|
2008-05-27 04:30:03 +00:00
|
|
|
|
2007-12-22 00:32:20 +00:00
|
|
|
switch_zmalloc(dt, sizeof(*dt));
|
2008-02-21 21:38:49 +00:00
|
|
|
*dt = new_dtmf;
|
|
|
|
|
2007-12-22 00:32:20 +00:00
|
|
|
while (switch_queue_trypush(channel->dtmf_queue, dt) != SWITCH_STATUS_SUCCESS) {
|
2009-02-27 19:29:52 +00:00
|
|
|
if (switch_queue_trypop(channel->dtmf_queue, &pop) == SWITCH_STATUS_SUCCESS) {
|
|
|
|
free(pop);
|
|
|
|
}
|
2007-12-22 00:32:20 +00:00
|
|
|
if (++x > 100) {
|
|
|
|
status = SWITCH_STATUS_FALSE;
|
|
|
|
free(dt);
|
2008-01-28 07:26:10 +00:00
|
|
|
goto done;
|
2007-12-22 00:32:20 +00:00
|
|
|
}
|
2006-05-04 00:07:20 +00:00
|
|
|
}
|
|
|
|
}
|
2008-01-28 07:26:10 +00:00
|
|
|
|
2007-12-22 00:32:20 +00:00
|
|
|
status = SWITCH_STATUS_SUCCESS;
|
2007-06-12 21:00:26 +00:00
|
|
|
|
2008-05-27 04:30:03 +00:00
|
|
|
done:
|
2007-06-12 21:00:26 +00:00
|
|
|
|
2005-12-06 21:25:56 +00:00
|
|
|
switch_mutex_unlock(channel->dtmf_mutex);
|
|
|
|
|
|
|
|
return status;
|
2005-11-19 20:07:43 +00:00
|
|
|
}
|
|
|
|
|
2008-01-12 20:30:48 +00:00
|
|
|
SWITCH_DECLARE(switch_status_t) switch_channel_queue_dtmf_string(switch_channel_t *channel, const char *dtmf_string)
|
|
|
|
{
|
|
|
|
char *p;
|
2010-10-08 18:50:15 +00:00
|
|
|
switch_dtmf_t dtmf = { 0, switch_core_default_dtmf_duration(0), 0};
|
2008-01-12 20:30:48 +00:00
|
|
|
int sent = 0, dur;
|
|
|
|
char *string;
|
|
|
|
int i, argc;
|
|
|
|
char *argv[256];
|
|
|
|
|
2009-10-23 16:03:42 +00:00
|
|
|
if (zstr(dtmf_string)) {
|
2008-01-12 20:30:48 +00:00
|
|
|
return SWITCH_STATUS_FALSE;
|
|
|
|
}
|
|
|
|
|
2010-10-08 18:50:15 +00:00
|
|
|
if (*dtmf_string == '!') {
|
|
|
|
dtmf_string++;
|
|
|
|
dtmf.flags = DTMF_FLAG_SKIP_PROCESS;
|
|
|
|
}
|
|
|
|
|
2008-01-12 20:30:48 +00:00
|
|
|
string = switch_core_session_strdup(channel->session, dtmf_string);
|
|
|
|
argc = switch_separate_string(string, '+', argv, (sizeof(argv) / sizeof(argv[0])));
|
2008-01-28 07:26:10 +00:00
|
|
|
|
2008-05-27 04:30:03 +00:00
|
|
|
for (i = 0; i < argc; i++) {
|
2008-04-18 17:03:34 +00:00
|
|
|
dtmf.duration = switch_core_default_dtmf_duration(0);
|
|
|
|
dur = switch_core_default_dtmf_duration(0) / 8;
|
2008-01-12 20:30:48 +00:00
|
|
|
if ((p = strchr(argv[i], '@'))) {
|
|
|
|
*p++ = '\0';
|
|
|
|
if ((dur = atoi(p)) > 50) {
|
|
|
|
dtmf.duration = dur * 8;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-04-18 17:03:34 +00:00
|
|
|
if (dtmf.duration > switch_core_max_dtmf_duration(0)) {
|
2009-08-13 20:35:02 +00:00
|
|
|
switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_WARNING, "EXCESSIVE DTMF DIGIT LEN %c %d\n", dtmf.digit, dtmf.duration);
|
2008-04-18 17:03:34 +00:00
|
|
|
dtmf.duration = switch_core_max_dtmf_duration(0);
|
2009-09-16 21:24:22 +00:00
|
|
|
} else if (dtmf.duration < switch_core_min_dtmf_duration(0)) {
|
|
|
|
switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_WARNING, "SHORT DTMF DIGIT LEN %c %d\n", dtmf.digit, dtmf.duration);
|
|
|
|
dtmf.duration = switch_core_min_dtmf_duration(0);
|
2008-02-21 21:38:49 +00:00
|
|
|
} else if (!dtmf.duration) {
|
2008-04-18 17:03:34 +00:00
|
|
|
dtmf.duration = switch_core_default_dtmf_duration(0);
|
2008-02-21 21:38:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-01-12 20:30:48 +00:00
|
|
|
for (p = argv[i]; p && *p; p++) {
|
|
|
|
if (is_dtmf(*p)) {
|
|
|
|
dtmf.digit = *p;
|
|
|
|
if (switch_channel_queue_dtmf(channel, &dtmf) == SWITCH_STATUS_SUCCESS) {
|
2009-08-13 20:35:02 +00:00
|
|
|
switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_DEBUG, "%s Queue dtmf\ndigit=%c ms=%u samples=%u\n",
|
2008-05-27 04:30:03 +00:00
|
|
|
switch_channel_get_name(channel), dtmf.digit, dur, dtmf.duration);
|
2008-01-12 20:30:48 +00:00
|
|
|
sent++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2008-01-28 07:26:10 +00:00
|
|
|
|
2008-01-12 20:30:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return sent ? SWITCH_STATUS_SUCCESS : SWITCH_STATUS_FALSE;
|
|
|
|
}
|
|
|
|
|
2007-12-22 00:32:20 +00:00
|
|
|
SWITCH_DECLARE(switch_status_t) switch_channel_dequeue_dtmf(switch_channel_t *channel, switch_dtmf_t *dtmf)
|
2005-11-19 20:07:43 +00:00
|
|
|
{
|
2006-04-29 01:00:52 +00:00
|
|
|
switch_event_t *event;
|
2007-12-22 00:32:20 +00:00
|
|
|
void *pop;
|
|
|
|
switch_dtmf_t *dt;
|
|
|
|
switch_status_t status = SWITCH_STATUS_FALSE;
|
2005-11-19 20:07:43 +00:00
|
|
|
|
2005-12-06 21:25:56 +00:00
|
|
|
switch_mutex_lock(channel->dtmf_mutex);
|
2007-12-22 00:32:20 +00:00
|
|
|
|
|
|
|
if (switch_queue_trypop(channel->dtmf_queue, &pop) == SWITCH_STATUS_SUCCESS) {
|
|
|
|
dt = (switch_dtmf_t *) pop;
|
|
|
|
*dtmf = *dt;
|
2009-02-23 16:31:59 +00:00
|
|
|
|
|
|
|
if (switch_queue_trypush(channel->dtmf_log_queue, dt) != SWITCH_STATUS_SUCCESS) {
|
2010-02-06 03:38:24 +00:00
|
|
|
free(dt);
|
2009-02-23 16:31:59 +00:00
|
|
|
}
|
2010-02-06 03:38:24 +00:00
|
|
|
|
2009-02-23 16:31:59 +00:00
|
|
|
dt = NULL;
|
2008-02-21 21:38:49 +00:00
|
|
|
|
2008-04-18 17:03:34 +00:00
|
|
|
if (dtmf->duration > switch_core_max_dtmf_duration(0)) {
|
2009-08-13 20:35:02 +00:00
|
|
|
switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_WARNING, "%s EXCESSIVE DTMF DIGIT [%c] LEN [%d]\n",
|
2008-02-21 21:38:49 +00:00
|
|
|
switch_channel_get_name(channel), dtmf->digit, dtmf->duration);
|
2008-04-18 17:03:34 +00:00
|
|
|
dtmf->duration = switch_core_max_dtmf_duration(0);
|
2009-09-16 21:24:22 +00:00
|
|
|
} else if (dtmf->duration < switch_core_min_dtmf_duration(0)) {
|
|
|
|
switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_WARNING, "%s SHORT DTMF DIGIT [%c] LEN [%d]\n",
|
|
|
|
switch_channel_get_name(channel), dtmf->digit, dtmf->duration);
|
|
|
|
dtmf->duration = switch_core_min_dtmf_duration(0);
|
2008-02-21 21:38:49 +00:00
|
|
|
} else if (!dtmf->duration) {
|
2008-04-18 17:03:34 +00:00
|
|
|
dtmf->duration = switch_core_default_dtmf_duration(0);
|
2008-02-21 21:38:49 +00:00
|
|
|
}
|
|
|
|
|
2007-12-22 00:32:20 +00:00
|
|
|
status = SWITCH_STATUS_SUCCESS;
|
2005-11-19 20:07:43 +00:00
|
|
|
}
|
2005-12-06 21:25:56 +00:00
|
|
|
switch_mutex_unlock(channel->dtmf_mutex);
|
2008-01-28 07:26:10 +00:00
|
|
|
|
2007-12-22 00:32:20 +00:00
|
|
|
if (status == SWITCH_STATUS_SUCCESS && switch_event_create(&event, SWITCH_EVENT_DTMF) == SWITCH_STATUS_SUCCESS) {
|
2005-12-21 22:25:22 +00:00
|
|
|
switch_channel_event_set_data(channel, event);
|
2007-12-22 00:32:20 +00:00
|
|
|
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "DTMF-Digit", "%c", dtmf->digit);
|
|
|
|
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "DTMF-Duration", "%u", dtmf->duration);
|
2009-02-21 23:19:58 +00:00
|
|
|
if (switch_channel_test_flag(channel, CF_DIVERT_EVENTS)) {
|
|
|
|
switch_core_session_queue_event(channel->session, &event);
|
|
|
|
} else {
|
|
|
|
switch_event_fire(&event);
|
|
|
|
}
|
2005-12-21 22:25:22 +00:00
|
|
|
}
|
2005-12-06 21:25:56 +00:00
|
|
|
|
2007-12-22 00:32:20 +00:00
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
|
|
|
SWITCH_DECLARE(switch_size_t) switch_channel_dequeue_dtmf_string(switch_channel_t *channel, char *dtmf_str, switch_size_t len)
|
|
|
|
{
|
|
|
|
switch_size_t x = 0;
|
2008-05-27 04:30:03 +00:00
|
|
|
switch_dtmf_t dtmf = { 0 };
|
2007-12-22 00:32:20 +00:00
|
|
|
|
|
|
|
memset(dtmf_str, 0, len);
|
|
|
|
|
2008-05-27 04:30:03 +00:00
|
|
|
while (x < len - 1 && switch_channel_dequeue_dtmf(channel, &dtmf) == SWITCH_STATUS_SUCCESS) {
|
2007-12-22 00:32:20 +00:00
|
|
|
dtmf_str[x++] = dtmf.digit;
|
|
|
|
}
|
|
|
|
|
|
|
|
return x;
|
2005-11-19 20:07:43 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
|
2007-12-22 00:32:20 +00:00
|
|
|
SWITCH_DECLARE(void) switch_channel_flush_dtmf(switch_channel_t *channel)
|
|
|
|
{
|
|
|
|
void *pop;
|
2009-02-21 22:50:35 +00:00
|
|
|
|
2007-12-22 00:32:20 +00:00
|
|
|
switch_mutex_lock(channel->dtmf_mutex);
|
2008-05-27 04:30:03 +00:00
|
|
|
while (switch_queue_trypop(channel->dtmf_queue, &pop) == SWITCH_STATUS_SUCCESS) {
|
2009-02-23 16:31:59 +00:00
|
|
|
switch_dtmf_t *dt = (switch_dtmf_t *) pop;
|
|
|
|
if (channel->state >= CS_HANGUP || switch_queue_trypush(channel->dtmf_log_queue, dt) != SWITCH_STATUS_SUCCESS) {
|
|
|
|
free(dt);
|
|
|
|
}
|
2007-12-22 00:32:20 +00:00
|
|
|
}
|
|
|
|
switch_mutex_unlock(channel->dtmf_mutex);
|
|
|
|
}
|
|
|
|
|
2006-09-08 18:57:24 +00:00
|
|
|
SWITCH_DECLARE(void) switch_channel_uninit(switch_channel_t *channel)
|
|
|
|
{
|
2009-02-23 16:31:59 +00:00
|
|
|
void *pop;
|
2007-12-22 02:15:50 +00:00
|
|
|
switch_channel_flush_dtmf(channel);
|
2009-02-23 16:31:59 +00:00
|
|
|
while (switch_queue_trypop(channel->dtmf_log_queue, &pop) == SWITCH_STATUS_SUCCESS) {
|
|
|
|
switch_safe_free(pop);
|
|
|
|
}
|
2007-09-29 01:06:08 +00:00
|
|
|
switch_core_hash_destroy(&channel->private_hash);
|
2010-07-23 05:36:40 +00:00
|
|
|
if (channel->app_flag_hash) {
|
|
|
|
switch_core_hash_destroy(&channel->app_flag_hash);
|
|
|
|
}
|
2008-10-30 22:40:39 +00:00
|
|
|
switch_mutex_lock(channel->profile_mutex);
|
2007-09-29 01:06:08 +00:00
|
|
|
switch_event_destroy(&channel->variables);
|
2008-10-30 22:40:39 +00:00
|
|
|
switch_mutex_unlock(channel->profile_mutex);
|
2006-09-08 18:57:24 +00:00
|
|
|
}
|
|
|
|
|
2007-03-30 00:15:25 +00:00
|
|
|
SWITCH_DECLARE(switch_status_t) switch_channel_init(switch_channel_t *channel, switch_core_session_t *session, switch_channel_state_t state,
|
2008-12-11 15:20:24 +00:00
|
|
|
switch_channel_flag_t flag)
|
2005-11-19 20:07:43 +00:00
|
|
|
{
|
2007-12-11 19:23:57 +00:00
|
|
|
switch_assert(channel != NULL);
|
2005-11-19 20:07:43 +00:00
|
|
|
channel->state = state;
|
2008-12-11 15:20:24 +00:00
|
|
|
switch_channel_set_flag(channel, flag);
|
2005-11-19 20:07:43 +00:00
|
|
|
channel->session = session;
|
2007-12-19 23:24:55 +00:00
|
|
|
channel->running_state = CS_NONE;
|
2005-11-19 20:07:43 +00:00
|
|
|
return SWITCH_STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2010-06-18 18:39:55 +00:00
|
|
|
SWITCH_DECLARE(void) switch_channel_perform_presence(switch_channel_t *channel, const char *rpid, const char *status, const char *id,
|
|
|
|
const char *file, const char *func, int line)
|
2006-10-21 04:58:15 +00:00
|
|
|
{
|
|
|
|
switch_event_t *event;
|
|
|
|
switch_event_types_t type = SWITCH_EVENT_PRESENCE_IN;
|
2009-12-24 05:44:23 +00:00
|
|
|
const char *call_info = NULL;
|
2006-10-21 04:58:15 +00:00
|
|
|
|
|
|
|
if (!status) {
|
|
|
|
type = SWITCH_EVENT_PRESENCE_OUT;
|
|
|
|
}
|
|
|
|
|
2008-08-25 16:30:28 +00:00
|
|
|
if (!id) {
|
|
|
|
id = switch_channel_get_variable(channel, "presence_id");
|
|
|
|
}
|
|
|
|
|
2006-10-21 04:58:15 +00:00
|
|
|
if (!id) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2009-12-24 05:44:23 +00:00
|
|
|
call_info = switch_channel_get_variable(channel, "presence_call_info");
|
|
|
|
|
2006-10-21 04:58:15 +00:00
|
|
|
if (switch_event_create(&event, type) == SWITCH_STATUS_SUCCESS) {
|
2007-12-15 00:39:53 +00:00
|
|
|
switch_channel_event_set_data(channel, event);
|
2008-08-16 02:17:09 +00:00
|
|
|
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "proto", __FILE__);
|
|
|
|
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "login", __FILE__);
|
|
|
|
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "from", id);
|
2006-10-21 04:58:15 +00:00
|
|
|
if (type == SWITCH_EVENT_PRESENCE_IN) {
|
|
|
|
if (!rpid) {
|
|
|
|
rpid = "unknown";
|
|
|
|
}
|
2008-08-16 02:17:09 +00:00
|
|
|
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "rpid", rpid);
|
|
|
|
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "status", status);
|
2006-10-21 04:58:15 +00:00
|
|
|
}
|
2008-08-16 02:17:09 +00:00
|
|
|
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "event_type", "presence");
|
|
|
|
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "alt_event_type", "dialog");
|
2010-02-06 03:38:24 +00:00
|
|
|
|
2009-12-24 05:44:23 +00:00
|
|
|
if (call_info) {
|
|
|
|
char *call_info_state = "active";
|
|
|
|
|
|
|
|
if (!switch_channel_up(channel)) {
|
|
|
|
call_info_state = "idle";
|
2010-01-13 01:40:11 +00:00
|
|
|
} else if (!strcasecmp(status, "hold-private")) {
|
|
|
|
call_info_state = "held-private";
|
2010-01-15 00:31:43 +00:00
|
|
|
} else if (!strcasecmp(status, "hold")) {
|
|
|
|
call_info_state = "held";
|
2009-12-24 05:44:23 +00:00
|
|
|
} else if (!switch_channel_test_flag(channel, CF_ANSWERED)) {
|
|
|
|
if (channel->direction == SWITCH_CALL_DIRECTION_OUTBOUND) {
|
|
|
|
call_info_state = "progressing";
|
|
|
|
} else {
|
|
|
|
call_info_state = "alerting";
|
|
|
|
}
|
|
|
|
}
|
2010-01-07 06:09:35 +00:00
|
|
|
|
2009-12-24 05:44:23 +00:00
|
|
|
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "presence-call-info-state", call_info_state);
|
|
|
|
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "presence-call-info", call_info);
|
|
|
|
}
|
|
|
|
|
|
|
|
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "presence-call-direction",
|
|
|
|
channel->direction == SWITCH_CALL_DIRECTION_OUTBOUND ? "outbound" : "inbound");
|
|
|
|
|
2010-06-18 18:39:55 +00:00
|
|
|
|
2007-12-15 00:39:53 +00:00
|
|
|
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "event_count", "%d", channel->event_count++);
|
2010-06-18 18:39:55 +00:00
|
|
|
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Presence-Calling-File", file);
|
|
|
|
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Presence-Calling-Function", func);
|
|
|
|
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Presence-Calling-Line", "%d", line);
|
2006-10-21 04:58:15 +00:00
|
|
|
switch_event_fire(&event);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-06-05 00:03:36 +00:00
|
|
|
SWITCH_DECLARE(void) switch_channel_mark_hold(switch_channel_t *channel, switch_bool_t on)
|
|
|
|
{
|
|
|
|
switch_event_t *event;
|
|
|
|
|
|
|
|
if (on) {
|
|
|
|
switch_channel_set_flag(channel, CF_LEG_HOLDING);
|
|
|
|
} else {
|
|
|
|
switch_channel_clear_flag(channel, CF_LEG_HOLDING);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (switch_event_create(&event, on ? SWITCH_EVENT_CHANNEL_HOLD : SWITCH_EVENT_CHANNEL_UNHOLD) == SWITCH_STATUS_SUCCESS) {
|
|
|
|
switch_channel_event_set_data(channel, event);
|
|
|
|
switch_event_fire(&event);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2010-02-06 03:38:24 +00:00
|
|
|
SWITCH_DECLARE(const char *) switch_channel_get_variable_dup(switch_channel_t *channel, const char *varname, switch_bool_t dup)
|
2005-11-19 20:07:43 +00:00
|
|
|
{
|
2009-03-21 16:47:57 +00:00
|
|
|
const char *v = NULL, *r = NULL;
|
2007-12-11 19:23:57 +00:00
|
|
|
switch_assert(channel != NULL);
|
2006-10-20 06:55:30 +00:00
|
|
|
|
2007-04-28 21:48:03 +00:00
|
|
|
switch_mutex_lock(channel->profile_mutex);
|
2009-03-17 13:25:02 +00:00
|
|
|
if (!channel->variables || !(v = switch_event_get_header(channel->variables, varname))) {
|
2009-12-08 01:20:22 +00:00
|
|
|
switch_caller_profile_t *cp = channel->caller_profile;
|
2008-01-28 07:26:10 +00:00
|
|
|
|
2007-12-06 19:51:55 +00:00
|
|
|
if (cp) {
|
|
|
|
if (!strncmp(varname, "aleg_", 5)) {
|
|
|
|
cp = cp->originator_caller_profile;
|
|
|
|
varname += 5;
|
|
|
|
} else if (!strncmp(varname, "bleg_", 5)) {
|
|
|
|
cp = cp->originatee_caller_profile;
|
|
|
|
varname += 5;
|
2006-11-09 05:39:04 +00:00
|
|
|
}
|
|
|
|
}
|
2007-12-06 19:51:55 +00:00
|
|
|
|
|
|
|
if (!cp || !(v = switch_caller_get_field_by_name(cp, varname))) {
|
|
|
|
v = switch_core_get_variable(varname);
|
|
|
|
}
|
2006-10-20 06:55:30 +00:00
|
|
|
}
|
2009-03-20 01:50:50 +00:00
|
|
|
|
2010-02-06 03:38:24 +00:00
|
|
|
if (dup) {
|
|
|
|
if (v)
|
|
|
|
r = switch_core_session_strdup(channel->session, v);
|
|
|
|
} else {
|
|
|
|
r = v;
|
|
|
|
}
|
|
|
|
|
2007-04-28 21:48:03 +00:00
|
|
|
switch_mutex_unlock(channel->profile_mutex);
|
2007-03-29 22:31:56 +00:00
|
|
|
|
2009-03-21 16:47:57 +00:00
|
|
|
return r;
|
2005-11-19 20:07:43 +00:00
|
|
|
}
|
|
|
|
|
2008-02-07 22:42:27 +00:00
|
|
|
SWITCH_DECLARE(const char *) switch_channel_get_variable_partner(switch_channel_t *channel, const char *varname)
|
|
|
|
{
|
|
|
|
const char *uuid;
|
2009-03-21 16:47:57 +00:00
|
|
|
const char *val = NULL, *r = NULL;
|
2008-02-07 22:42:27 +00:00
|
|
|
switch_assert(channel != NULL);
|
2010-02-06 03:38:24 +00:00
|
|
|
|
2009-10-23 16:03:42 +00:00
|
|
|
if (!zstr(varname)) {
|
2008-02-07 22:42:27 +00:00
|
|
|
if ((uuid = switch_channel_get_variable(channel, SWITCH_SIGNAL_BOND_VARIABLE))) {
|
|
|
|
switch_core_session_t *session;
|
|
|
|
if ((session = switch_core_session_locate(uuid))) {
|
|
|
|
switch_channel_t *tchannel = switch_core_session_get_channel(session);
|
|
|
|
val = switch_channel_get_variable(tchannel, varname);
|
|
|
|
switch_core_session_rwunlock(session);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-02-06 03:38:24 +00:00
|
|
|
if (val)
|
|
|
|
r = switch_core_session_strdup(channel->session, val);
|
2009-03-20 01:50:50 +00:00
|
|
|
|
2009-03-21 16:47:57 +00:00
|
|
|
return r;
|
2008-02-07 22:42:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-04-28 21:48:03 +00:00
|
|
|
SWITCH_DECLARE(void) switch_channel_variable_last(switch_channel_t *channel)
|
|
|
|
{
|
2007-12-11 19:23:57 +00:00
|
|
|
switch_assert(channel != NULL);
|
2007-10-09 15:29:18 +00:00
|
|
|
if (!channel->vi) {
|
|
|
|
return;
|
2007-04-28 21:48:03 +00:00
|
|
|
}
|
2007-10-09 15:29:18 +00:00
|
|
|
channel->vi = 0;
|
|
|
|
switch_mutex_unlock(channel->profile_mutex);
|
2008-01-28 07:26:10 +00:00
|
|
|
|
2007-04-28 21:48:03 +00:00
|
|
|
}
|
|
|
|
|
2007-09-29 01:06:08 +00:00
|
|
|
SWITCH_DECLARE(switch_event_header_t *) switch_channel_variable_first(switch_channel_t *channel)
|
2006-06-13 01:49:18 +00:00
|
|
|
{
|
2007-10-09 15:29:18 +00:00
|
|
|
switch_event_header_t *hi = NULL;
|
|
|
|
|
2007-12-11 19:23:57 +00:00
|
|
|
switch_assert(channel != NULL);
|
2007-10-09 15:29:18 +00:00
|
|
|
switch_mutex_lock(channel->profile_mutex);
|
|
|
|
if ((hi = channel->variables->headers)) {
|
|
|
|
channel->vi = 1;
|
|
|
|
} else {
|
|
|
|
switch_mutex_unlock(channel->profile_mutex);
|
2007-04-28 21:48:03 +00:00
|
|
|
}
|
|
|
|
|
2007-10-09 15:29:18 +00:00
|
|
|
return hi;
|
2006-06-13 01:49:18 +00:00
|
|
|
}
|
|
|
|
|
2007-05-12 14:48:14 +00:00
|
|
|
SWITCH_DECLARE(switch_status_t) switch_channel_set_private(switch_channel_t *channel, const char *key, const void *private_info)
|
2005-11-19 20:07:43 +00:00
|
|
|
{
|
2007-12-11 19:23:57 +00:00
|
|
|
switch_assert(channel != NULL);
|
2007-09-29 01:06:08 +00:00
|
|
|
switch_core_hash_insert_locked(channel->private_hash, key, private_info, channel->profile_mutex);
|
2005-11-19 20:07:43 +00:00
|
|
|
return SWITCH_STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2007-05-12 14:48:14 +00:00
|
|
|
SWITCH_DECLARE(void *) switch_channel_get_private(switch_channel_t *channel, const char *key)
|
2005-11-19 20:07:43 +00:00
|
|
|
{
|
2007-04-28 21:48:03 +00:00
|
|
|
void *val;
|
2007-12-11 19:23:57 +00:00
|
|
|
switch_assert(channel != NULL);
|
2007-10-09 15:29:18 +00:00
|
|
|
val = switch_core_hash_find_locked(channel->private_hash, key, channel->profile_mutex);
|
2007-04-28 21:48:03 +00:00
|
|
|
return val;
|
2005-11-19 20:07:43 +00:00
|
|
|
}
|
|
|
|
|
2010-02-03 19:19:10 +00:00
|
|
|
SWITCH_DECLARE(void *) switch_channel_get_private_partner(switch_channel_t *channel, const char *key)
|
|
|
|
{
|
|
|
|
const char *uuid;
|
|
|
|
void *val = NULL;
|
|
|
|
|
|
|
|
switch_assert(channel != NULL);
|
|
|
|
|
|
|
|
if ((uuid = switch_channel_get_variable(channel, SWITCH_SIGNAL_BOND_VARIABLE))) {
|
|
|
|
switch_core_session_t *session;
|
|
|
|
if ((session = switch_core_session_locate(uuid))) {
|
|
|
|
val = switch_core_hash_find_locked(channel->private_hash, key, channel->profile_mutex);
|
|
|
|
switch_core_session_rwunlock(session);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return val;
|
|
|
|
}
|
|
|
|
|
2007-05-12 14:48:14 +00:00
|
|
|
SWITCH_DECLARE(switch_status_t) switch_channel_set_name(switch_channel_t *channel, const char *name)
|
2005-11-19 20:07:43 +00:00
|
|
|
{
|
2008-02-26 23:29:58 +00:00
|
|
|
const char *old = NULL;
|
|
|
|
|
2007-12-11 19:23:57 +00:00
|
|
|
switch_assert(channel != NULL);
|
2009-10-23 16:03:42 +00:00
|
|
|
if (!zstr(channel->name)) {
|
2008-02-26 23:29:58 +00:00
|
|
|
old = channel->name;
|
|
|
|
}
|
2005-11-19 20:07:43 +00:00
|
|
|
channel->name = NULL;
|
|
|
|
if (name) {
|
2006-04-28 19:46:57 +00:00
|
|
|
char *uuid = switch_core_session_get_uuid(channel->session);
|
2005-11-19 20:07:43 +00:00
|
|
|
channel->name = switch_core_session_strdup(channel->session, name);
|
2007-12-06 19:51:55 +00:00
|
|
|
switch_channel_set_variable(channel, SWITCH_CHANNEL_NAME_VARIABLE, name);
|
2008-02-26 23:29:58 +00:00
|
|
|
if (old) {
|
2009-08-13 20:35:02 +00:00
|
|
|
switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_NOTICE, "Rename Channel %s->%s [%s]\n", old, name, uuid);
|
2008-02-26 23:29:58 +00:00
|
|
|
} else {
|
2009-08-13 20:35:02 +00:00
|
|
|
switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_NOTICE, "New Channel %s [%s]\n", name, uuid);
|
2008-02-26 23:29:58 +00:00
|
|
|
}
|
2005-11-19 20:07:43 +00:00
|
|
|
}
|
|
|
|
return SWITCH_STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2006-04-29 06:05:03 +00:00
|
|
|
SWITCH_DECLARE(char *) switch_channel_get_name(switch_channel_t *channel)
|
2005-11-19 20:07:43 +00:00
|
|
|
{
|
2007-12-11 19:23:57 +00:00
|
|
|
switch_assert(channel != NULL);
|
2009-10-23 16:03:42 +00:00
|
|
|
return (!zstr(channel->name)) ? channel->name : "N/A";
|
2005-11-19 20:07:43 +00:00
|
|
|
}
|
|
|
|
|
2009-10-19 19:58:23 +00:00
|
|
|
SWITCH_DECLARE(switch_status_t) switch_channel_set_profile_var(switch_channel_t *channel, const char *name, const char *val)
|
|
|
|
{
|
|
|
|
char *v;
|
|
|
|
switch_status_t status = SWITCH_STATUS_SUCCESS;
|
|
|
|
|
|
|
|
switch_mutex_lock(channel->profile_mutex);
|
|
|
|
|
2009-10-23 16:03:42 +00:00
|
|
|
if (!zstr(val)) {
|
2009-10-19 19:58:23 +00:00
|
|
|
v = switch_core_strdup(channel->caller_profile->pool, val);
|
|
|
|
} else {
|
|
|
|
v = SWITCH_BLANK_STRING;
|
|
|
|
}
|
2010-02-06 03:38:24 +00:00
|
|
|
|
2009-10-19 19:58:23 +00:00
|
|
|
if (!strcasecmp(name, "dialplan")) {
|
|
|
|
channel->caller_profile->dialplan = v;
|
|
|
|
} else if (!strcasecmp(name, "username")) {
|
|
|
|
channel->caller_profile->username = v;
|
|
|
|
} else if (!strcasecmp(name, "caller_id_name")) {
|
|
|
|
channel->caller_profile->caller_id_name = v;
|
|
|
|
} else if (!strcasecmp(name, "caller_id_number")) {
|
|
|
|
channel->caller_profile->caller_id_number = v;
|
|
|
|
} else if (!strcasecmp(name, "callee_id_name")) {
|
|
|
|
channel->caller_profile->callee_id_name = v;
|
|
|
|
} else if (!strcasecmp(name, "callee_id_number")) {
|
|
|
|
channel->caller_profile->callee_id_number = v;
|
|
|
|
} else if (val && !strcasecmp(name, "caller_ton")) {
|
|
|
|
channel->caller_profile->caller_ton = (uint8_t) atoi(v);
|
|
|
|
} else if (val && !strcasecmp(name, "caller_numplan")) {
|
|
|
|
channel->caller_profile->caller_numplan = (uint8_t) atoi(v);
|
|
|
|
} else if (val && !strcasecmp(name, "destination_number_ton")) {
|
|
|
|
channel->caller_profile->destination_number_ton = (uint8_t) atoi(v);
|
|
|
|
} else if (val && !strcasecmp(name, "destination_number_numplan")) {
|
|
|
|
channel->caller_profile->destination_number_numplan = (uint8_t) atoi(v);
|
|
|
|
} else if (!strcasecmp(name, "ani")) {
|
|
|
|
channel->caller_profile->ani = v;
|
|
|
|
} else if (!strcasecmp(name, "aniii")) {
|
|
|
|
channel->caller_profile->aniii = v;
|
|
|
|
} else if (!strcasecmp(name, "network_addr")) {
|
|
|
|
channel->caller_profile->network_addr = v;
|
|
|
|
} else if (!strcasecmp(name, "rdnis")) {
|
|
|
|
channel->caller_profile->rdnis = v;
|
|
|
|
} else if (!strcasecmp(name, "destination_number")) {
|
|
|
|
channel->caller_profile->destination_number = v;
|
|
|
|
} else if (!strcasecmp(name, "uuid")) {
|
|
|
|
channel->caller_profile->uuid = v;
|
|
|
|
} else if (!strcasecmp(name, "source")) {
|
|
|
|
channel->caller_profile->source = v;
|
|
|
|
} else if (!strcasecmp(name, "context")) {
|
|
|
|
channel->caller_profile->context = v;
|
|
|
|
} else if (!strcasecmp(name, "chan_name")) {
|
|
|
|
channel->caller_profile->chan_name = v;
|
|
|
|
} else {
|
|
|
|
status = SWITCH_STATUS_FALSE;
|
|
|
|
}
|
|
|
|
switch_mutex_unlock(channel->profile_mutex);
|
|
|
|
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
2010-10-01 22:26:03 +00:00
|
|
|
|
|
|
|
SWITCH_DECLARE(void) switch_channel_process_export(switch_channel_t *channel, switch_channel_t *peer_channel,
|
|
|
|
switch_event_t *var_event, const char *export_varname)
|
2010-04-01 19:49:32 +00:00
|
|
|
{
|
|
|
|
|
2010-10-01 22:26:03 +00:00
|
|
|
const char *export_vars = switch_channel_get_variable(channel, export_varname);
|
|
|
|
char *cptmp = switch_core_session_strdup(channel->session, export_vars);
|
|
|
|
int argc;
|
|
|
|
char *argv[256];
|
|
|
|
|
|
|
|
if (zstr(export_vars)) return;
|
|
|
|
|
|
|
|
|
|
|
|
if (var_event) {
|
|
|
|
switch_event_del_header(var_event, export_varname);
|
|
|
|
switch_event_add_header_string(var_event, SWITCH_STACK_BOTTOM, export_varname, export_vars);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (peer_channel) {
|
|
|
|
switch_channel_set_variable(peer_channel, export_varname, export_vars);
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((argc = switch_separate_string(cptmp, ',', argv, (sizeof(argv) / sizeof(argv[0]))))) {
|
|
|
|
int x;
|
2010-04-07 19:02:00 +00:00
|
|
|
|
2010-10-01 22:26:03 +00:00
|
|
|
for (x = 0; x < argc; x++) {
|
|
|
|
const char *vval;
|
|
|
|
if ((vval = switch_channel_get_variable(channel, argv[x]))) {
|
|
|
|
char *vvar = argv[x];
|
|
|
|
if (!strncasecmp(vvar, "nolocal:", 8)) {
|
|
|
|
vvar += 8;
|
|
|
|
}
|
|
|
|
if (var_event) {
|
|
|
|
switch_event_del_header(var_event, vvar);
|
|
|
|
switch_event_add_header_string(var_event, SWITCH_STACK_BOTTOM, vvar, vval);
|
|
|
|
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(channel->session), SWITCH_LOG_DEBUG,
|
|
|
|
"%s EXPORTING[%s] [%s]=[%s] to event\n",
|
|
|
|
switch_channel_get_name(channel),
|
|
|
|
export_varname,
|
|
|
|
vvar, vval);
|
|
|
|
}
|
|
|
|
if (peer_channel) {
|
|
|
|
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(channel->session), SWITCH_LOG_DEBUG,
|
|
|
|
"%s EXPORTING[%s] [%s]=[%s] to %s\n",
|
|
|
|
switch_channel_get_name(channel),
|
|
|
|
export_varname,
|
|
|
|
vvar, vval, switch_channel_get_name(peer_channel));
|
|
|
|
switch_channel_set_variable(peer_channel, vvar, vval);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2010-04-01 19:49:32 +00:00
|
|
|
}
|
|
|
|
|
2010-10-01 22:26:03 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
SWITCH_DECLARE(switch_status_t) switch_channel_export_variable_var_check(switch_channel_t *channel,
|
|
|
|
const char *varname, const char *val,
|
|
|
|
const char *export_varname, switch_bool_t var_check)
|
|
|
|
{
|
|
|
|
char *var_name = NULL;
|
|
|
|
const char *exports;
|
|
|
|
char *var, *new_exports, *new_exports_d = NULL;
|
|
|
|
int local = 1;
|
|
|
|
|
|
|
|
exports = switch_channel_get_variable(channel, export_varname);
|
|
|
|
|
|
|
|
var = switch_core_session_strdup(channel->session, varname);
|
|
|
|
|
|
|
|
if (var) {
|
|
|
|
if (!strncasecmp(var, "nolocal:", 8)) {
|
|
|
|
var_name = var + 8;
|
|
|
|
local = 0;
|
|
|
|
} else {
|
|
|
|
var_name = var;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(channel->session), SWITCH_LOG_DEBUG, "EXPORT (%s) %s[%s]=[%s]\n",
|
|
|
|
export_varname, local ? "" : "(REMOTE ONLY) ",
|
|
|
|
var_name ? var_name : "", val ? val : "UNDEF");
|
|
|
|
|
|
|
|
|
|
|
|
switch_channel_set_variable_var_check(channel, var, val, var_check);
|
|
|
|
|
|
|
|
if (var && val) {
|
2010-04-01 19:49:32 +00:00
|
|
|
if (exports) {
|
2010-10-01 22:26:03 +00:00
|
|
|
new_exports_d = switch_mprintf("%s,%s", exports, var);
|
|
|
|
new_exports = new_exports_d;
|
2010-04-01 19:49:32 +00:00
|
|
|
} else {
|
2010-10-01 22:26:03 +00:00
|
|
|
new_exports = var;
|
2010-04-01 19:49:32 +00:00
|
|
|
}
|
2010-10-01 22:26:03 +00:00
|
|
|
|
|
|
|
switch_channel_set_variable(channel, export_varname, new_exports);
|
|
|
|
|
|
|
|
switch_safe_free(new_exports_d);
|
2010-04-01 19:49:32 +00:00
|
|
|
}
|
|
|
|
|
2010-10-01 22:26:03 +00:00
|
|
|
return SWITCH_STATUS_SUCCESS;
|
2010-04-01 19:49:32 +00:00
|
|
|
}
|
|
|
|
|
2010-10-01 22:26:03 +00:00
|
|
|
SWITCH_DECLARE(switch_status_t) switch_channel_export_variable_printf(switch_channel_t *channel, const char *varname,
|
|
|
|
const char *export_varname, const char *fmt, ...)
|
2010-04-07 18:55:55 +00:00
|
|
|
{
|
|
|
|
switch_status_t status = SWITCH_STATUS_FALSE;
|
|
|
|
char *data = NULL;
|
|
|
|
va_list ap;
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
switch_assert(channel != NULL);
|
|
|
|
|
|
|
|
va_start(ap, fmt);
|
|
|
|
ret = switch_vasprintf(&data, fmt, ap);
|
|
|
|
va_end(ap);
|
|
|
|
|
|
|
|
if (ret == -1) {
|
|
|
|
return SWITCH_STATUS_FALSE;
|
|
|
|
}
|
|
|
|
|
2010-10-01 22:26:03 +00:00
|
|
|
status = switch_channel_export_variable(channel, varname, export_varname, data);
|
2010-04-07 18:55:55 +00:00
|
|
|
|
|
|
|
free(data);
|
|
|
|
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
2010-02-06 03:38:24 +00:00
|
|
|
SWITCH_DECLARE(switch_status_t) switch_channel_set_variable_var_check(switch_channel_t *channel,
|
2009-01-21 21:34:31 +00:00
|
|
|
const char *varname, const char *value, switch_bool_t var_check)
|
2005-11-19 20:07:43 +00:00
|
|
|
{
|
2009-03-25 20:07:40 +00:00
|
|
|
switch_status_t status = SWITCH_STATUS_FALSE;
|
2010-02-06 03:38:24 +00:00
|
|
|
|
2007-12-11 19:23:57 +00:00
|
|
|
switch_assert(channel != NULL);
|
2008-01-28 07:26:10 +00:00
|
|
|
|
2009-03-25 20:07:40 +00:00
|
|
|
switch_mutex_lock(channel->profile_mutex);
|
2009-10-23 16:03:42 +00:00
|
|
|
if (channel->variables && !zstr(varname)) {
|
2010-10-01 22:26:03 +00:00
|
|
|
|
2007-10-02 19:58:06 +00:00
|
|
|
switch_event_del_header(channel->variables, varname);
|
2009-10-23 16:03:42 +00:00
|
|
|
if (!zstr(value)) {
|
2009-01-21 21:34:31 +00:00
|
|
|
int ok = 1;
|
2010-02-06 03:38:24 +00:00
|
|
|
|
2009-01-21 21:34:31 +00:00
|
|
|
if (var_check) {
|
2009-01-22 03:42:22 +00:00
|
|
|
ok = !switch_string_var_check_const(value);
|
2009-01-21 21:34:31 +00:00
|
|
|
}
|
|
|
|
if (ok) {
|
|
|
|
switch_event_add_header_string(channel->variables, SWITCH_STACK_BOTTOM, varname, value);
|
|
|
|
} else {
|
2009-08-13 20:35:02 +00:00
|
|
|
switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_CRIT, "Invalid data (${%s} contains a variable)\n", varname);
|
2009-01-21 21:34:31 +00:00
|
|
|
}
|
2008-05-27 04:30:03 +00:00
|
|
|
}
|
2009-03-25 20:07:40 +00:00
|
|
|
status = SWITCH_STATUS_SUCCESS;
|
2007-02-19 22:57:27 +00:00
|
|
|
}
|
2009-03-25 20:07:40 +00:00
|
|
|
switch_mutex_unlock(channel->profile_mutex);
|
2007-02-19 22:57:27 +00:00
|
|
|
|
2009-03-25 20:07:40 +00:00
|
|
|
return status;
|
2007-02-19 22:57:27 +00:00
|
|
|
}
|
|
|
|
|
2008-09-29 17:48:43 +00:00
|
|
|
switch_status_t switch_event_base_add_header(switch_event_t *event, switch_stack_t stack, const char *header_name, char *data);
|
|
|
|
|
2010-01-30 02:55:49 +00:00
|
|
|
SWITCH_DECLARE(switch_status_t) switch_channel_set_variable_printf(switch_channel_t *channel, const char *varname, const char *fmt, ...)
|
2008-09-29 17:48:43 +00:00
|
|
|
{
|
|
|
|
int ret = 0;
|
|
|
|
char *data;
|
|
|
|
va_list ap;
|
2009-03-25 20:07:40 +00:00
|
|
|
switch_status_t status = SWITCH_STATUS_FALSE;
|
|
|
|
|
2008-09-29 17:48:43 +00:00
|
|
|
switch_assert(channel != NULL);
|
|
|
|
|
2009-03-25 20:07:40 +00:00
|
|
|
switch_mutex_lock(channel->profile_mutex);
|
2009-10-23 16:03:42 +00:00
|
|
|
if (channel->variables && !zstr(varname)) {
|
2008-09-29 17:48:43 +00:00
|
|
|
switch_event_del_header(channel->variables, varname);
|
|
|
|
|
|
|
|
va_start(ap, fmt);
|
|
|
|
ret = switch_vasprintf(&data, fmt, ap);
|
|
|
|
va_end(ap);
|
|
|
|
|
|
|
|
if (ret == -1) {
|
|
|
|
switch_mutex_unlock(channel->profile_mutex);
|
|
|
|
return SWITCH_STATUS_MEMERR;
|
|
|
|
}
|
|
|
|
|
2010-01-30 02:55:49 +00:00
|
|
|
status = switch_channel_set_variable(channel, varname, data);
|
|
|
|
free(data);
|
|
|
|
}
|
|
|
|
switch_mutex_unlock(channel->profile_mutex);
|
2010-02-06 03:38:24 +00:00
|
|
|
|
2010-01-30 02:55:49 +00:00
|
|
|
return status;
|
|
|
|
}
|
2008-09-29 17:48:43 +00:00
|
|
|
|
2010-01-30 02:55:49 +00:00
|
|
|
|
|
|
|
SWITCH_DECLARE(switch_status_t) switch_channel_set_variable_name_printf(switch_channel_t *channel, const char *val, const char *fmt, ...)
|
|
|
|
{
|
|
|
|
int ret = 0;
|
|
|
|
char *varname;
|
|
|
|
va_list ap;
|
|
|
|
switch_status_t status = SWITCH_STATUS_FALSE;
|
|
|
|
|
|
|
|
switch_assert(channel != NULL);
|
|
|
|
|
|
|
|
switch_mutex_lock(channel->profile_mutex);
|
|
|
|
|
|
|
|
va_start(ap, fmt);
|
|
|
|
ret = switch_vasprintf(&varname, fmt, ap);
|
|
|
|
va_end(ap);
|
2010-02-06 03:38:24 +00:00
|
|
|
|
2010-01-30 02:55:49 +00:00
|
|
|
if (ret == -1) {
|
|
|
|
switch_mutex_unlock(channel->profile_mutex);
|
|
|
|
return SWITCH_STATUS_MEMERR;
|
2008-09-29 17:48:43 +00:00
|
|
|
}
|
2010-02-06 03:38:24 +00:00
|
|
|
|
2010-01-30 02:55:49 +00:00
|
|
|
status = switch_channel_set_variable(channel, varname, val);
|
|
|
|
|
|
|
|
free(varname);
|
|
|
|
|
2009-03-25 20:07:40 +00:00
|
|
|
switch_mutex_unlock(channel->profile_mutex);
|
2008-09-29 17:48:43 +00:00
|
|
|
|
2009-03-25 20:07:40 +00:00
|
|
|
return status;
|
2008-09-29 17:48:43 +00:00
|
|
|
}
|
|
|
|
|
2007-12-20 21:42:00 +00:00
|
|
|
|
2010-02-06 03:38:24 +00:00
|
|
|
SWITCH_DECLARE(switch_status_t) switch_channel_set_variable_partner_var_check(switch_channel_t *channel,
|
2009-01-21 21:34:31 +00:00
|
|
|
const char *varname, const char *value, switch_bool_t var_check)
|
2007-12-20 21:42:00 +00:00
|
|
|
{
|
|
|
|
const char *uuid;
|
|
|
|
switch_assert(channel != NULL);
|
2008-01-28 07:26:10 +00:00
|
|
|
|
2009-10-23 16:03:42 +00:00
|
|
|
if (!zstr(varname)) {
|
2007-12-20 21:42:00 +00:00
|
|
|
if ((uuid = switch_channel_get_variable(channel, SWITCH_SIGNAL_BOND_VARIABLE))) {
|
|
|
|
switch_core_session_t *session;
|
|
|
|
if ((session = switch_core_session_locate(uuid))) {
|
|
|
|
switch_channel_t *tchannel = switch_core_session_get_channel(session);
|
2009-01-21 21:34:31 +00:00
|
|
|
switch_channel_set_variable_var_check(tchannel, varname, value, var_check);
|
2007-12-20 21:42:00 +00:00
|
|
|
switch_core_session_rwunlock(session);
|
|
|
|
}
|
|
|
|
return SWITCH_STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return SWITCH_STATUS_FALSE;
|
|
|
|
}
|
|
|
|
|
2008-12-11 15:20:24 +00:00
|
|
|
SWITCH_DECLARE(uint32_t) switch_channel_test_flag(switch_channel_t *channel, switch_channel_flag_t flag)
|
2005-11-19 20:07:43 +00:00
|
|
|
{
|
2010-02-06 03:38:24 +00:00
|
|
|
uint32_t r = 0;
|
|
|
|
|
2007-12-11 19:23:57 +00:00
|
|
|
switch_assert(channel != NULL);
|
2010-02-06 03:38:24 +00:00
|
|
|
|
|
|
|
switch_mutex_lock(channel->flag_mutex);
|
|
|
|
r = channel->flags[flag];
|
|
|
|
switch_mutex_unlock(channel->flag_mutex);
|
|
|
|
|
|
|
|
return r;
|
2005-11-19 20:07:43 +00:00
|
|
|
}
|
|
|
|
|
2008-12-11 15:20:24 +00:00
|
|
|
SWITCH_DECLARE(switch_bool_t) switch_channel_set_flag_partner(switch_channel_t *channel, switch_channel_flag_t flag)
|
2007-03-30 22:13:19 +00:00
|
|
|
{
|
2007-11-01 11:28:26 +00:00
|
|
|
const char *uuid;
|
2007-03-30 22:13:19 +00:00
|
|
|
|
2007-12-11 19:23:57 +00:00
|
|
|
switch_assert(channel != NULL);
|
2007-03-30 22:13:19 +00:00
|
|
|
|
2007-05-09 19:44:15 +00:00
|
|
|
if ((uuid = switch_channel_get_variable(channel, SWITCH_SIGNAL_BOND_VARIABLE))) {
|
2007-03-30 22:13:19 +00:00
|
|
|
switch_core_session_t *session;
|
|
|
|
if ((session = switch_core_session_locate(uuid))) {
|
2008-12-11 15:20:24 +00:00
|
|
|
switch_channel_set_flag(switch_core_session_get_channel(session), flag);
|
2007-03-30 22:13:19 +00:00
|
|
|
switch_core_session_rwunlock(session);
|
|
|
|
return SWITCH_TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return SWITCH_FALSE;
|
|
|
|
}
|
|
|
|
|
2009-04-23 13:15:03 +00:00
|
|
|
SWITCH_DECLARE(uint32_t) switch_channel_test_flag_partner(switch_channel_t *channel, switch_channel_flag_t flag)
|
|
|
|
{
|
|
|
|
const char *uuid;
|
|
|
|
int r = 0;
|
2010-02-06 03:38:24 +00:00
|
|
|
|
2009-04-23 13:15:03 +00:00
|
|
|
switch_assert(channel != NULL);
|
|
|
|
|
|
|
|
if ((uuid = switch_channel_get_variable(channel, SWITCH_SIGNAL_BOND_VARIABLE))) {
|
|
|
|
switch_core_session_t *session;
|
|
|
|
if ((session = switch_core_session_locate(uuid))) {
|
|
|
|
r = switch_channel_test_flag(switch_core_session_get_channel(session), flag);
|
|
|
|
switch_core_session_rwunlock(session);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
2008-12-11 15:20:24 +00:00
|
|
|
SWITCH_DECLARE(switch_bool_t) switch_channel_clear_flag_partner(switch_channel_t *channel, switch_channel_flag_t flag)
|
2007-03-30 22:13:19 +00:00
|
|
|
{
|
2007-11-01 11:28:26 +00:00
|
|
|
const char *uuid;
|
2007-03-30 22:13:19 +00:00
|
|
|
|
2007-12-11 19:23:57 +00:00
|
|
|
switch_assert(channel != NULL);
|
2007-03-30 22:13:19 +00:00
|
|
|
|
2007-05-09 19:44:15 +00:00
|
|
|
if ((uuid = switch_channel_get_variable(channel, SWITCH_SIGNAL_BOND_VARIABLE))) {
|
2007-03-30 22:13:19 +00:00
|
|
|
switch_core_session_t *session;
|
|
|
|
if ((session = switch_core_session_locate(uuid))) {
|
2008-12-11 15:20:24 +00:00
|
|
|
switch_channel_clear_flag(switch_core_session_get_channel(session), flag);
|
2007-03-30 22:13:19 +00:00
|
|
|
switch_core_session_rwunlock(session);
|
|
|
|
return SWITCH_TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return SWITCH_FALSE;
|
|
|
|
}
|
|
|
|
|
2007-12-08 00:14:21 +00:00
|
|
|
SWITCH_DECLARE(void) switch_channel_wait_for_state(switch_channel_t *channel, switch_channel_t *other_channel, switch_channel_state_t want_state)
|
|
|
|
{
|
2010-07-16 01:36:54 +00:00
|
|
|
switch_channel_state_t state, mystate;
|
2008-01-28 07:26:10 +00:00
|
|
|
|
2008-05-27 04:30:03 +00:00
|
|
|
for (;;) {
|
2010-07-16 01:36:54 +00:00
|
|
|
if (other_channel) {
|
|
|
|
state = switch_channel_get_running_state(other_channel);
|
|
|
|
}
|
2007-12-08 00:14:21 +00:00
|
|
|
mystate = switch_channel_get_running_state(channel);
|
2008-01-28 07:26:10 +00:00
|
|
|
|
2010-02-06 03:38:24 +00:00
|
|
|
if ((channel->state == channel->running_state && channel->running_state == want_state) ||
|
2010-07-16 01:36:54 +00:00
|
|
|
(other_channel && other_channel->state >= CS_HANGUP) || channel->state >= CS_HANGUP) {
|
2007-12-08 00:14:21 +00:00
|
|
|
break;
|
|
|
|
}
|
2010-07-16 01:36:54 +00:00
|
|
|
switch_yield(20000);
|
2007-12-08 00:14:21 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-05-07 17:27:15 +00:00
|
|
|
|
|
|
|
SWITCH_DECLARE(void) switch_channel_wait_for_state_timeout(switch_channel_t *other_channel, switch_channel_state_t want_state, uint32_t timeout)
|
|
|
|
{
|
|
|
|
switch_channel_state_t state;
|
|
|
|
uint32_t count = 0;
|
|
|
|
|
|
|
|
for (;;) {
|
|
|
|
state = switch_channel_get_running_state(other_channel);
|
|
|
|
|
|
|
|
if (state >= want_state) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
switch_cond_next();
|
|
|
|
if (++count >= timeout) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-02-06 03:38:24 +00:00
|
|
|
SWITCH_DECLARE(switch_status_t) switch_channel_wait_for_flag(switch_channel_t *channel,
|
|
|
|
switch_channel_flag_t want_flag,
|
|
|
|
switch_bool_t pres, uint32_t to, switch_channel_t *super_channel)
|
2008-01-05 20:44:54 +00:00
|
|
|
{
|
2010-02-06 03:38:24 +00:00
|
|
|
|
2008-01-05 20:44:54 +00:00
|
|
|
if (to) {
|
|
|
|
to++;
|
|
|
|
}
|
|
|
|
|
2008-05-27 04:30:03 +00:00
|
|
|
for (;;) {
|
2008-01-05 22:17:26 +00:00
|
|
|
if (pres) {
|
2008-12-11 15:20:24 +00:00
|
|
|
if (switch_channel_test_flag(channel, want_flag)) {
|
2008-01-05 22:17:26 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
} else {
|
2008-12-11 15:20:24 +00:00
|
|
|
if (!switch_channel_test_flag(channel, want_flag)) {
|
2008-01-05 22:17:26 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-11-14 23:31:21 +00:00
|
|
|
switch_cond_next();
|
2008-09-09 16:31:53 +00:00
|
|
|
|
|
|
|
if (super_channel && !switch_channel_ready(super_channel)) {
|
|
|
|
return SWITCH_STATUS_FALSE;
|
|
|
|
}
|
|
|
|
|
2009-03-04 04:19:33 +00:00
|
|
|
if (switch_channel_down(channel)) {
|
2008-09-09 16:31:53 +00:00
|
|
|
return SWITCH_STATUS_FALSE;
|
|
|
|
}
|
|
|
|
|
2008-01-05 20:44:54 +00:00
|
|
|
if (to && !--to) {
|
|
|
|
return SWITCH_STATUS_TIMEOUT;
|
|
|
|
}
|
|
|
|
}
|
2008-01-28 07:26:10 +00:00
|
|
|
|
2008-01-05 20:44:54 +00:00
|
|
|
return SWITCH_STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2009-10-14 19:26:10 +00:00
|
|
|
|
2010-02-06 03:38:24 +00:00
|
|
|
SWITCH_DECLARE(void) switch_channel_set_cap_value(switch_channel_t *channel, switch_channel_cap_t cap, uint32_t value)
|
2009-10-14 19:26:10 +00:00
|
|
|
{
|
|
|
|
switch_assert(channel);
|
|
|
|
switch_assert(channel->flag_mutex);
|
|
|
|
|
|
|
|
switch_mutex_lock(channel->flag_mutex);
|
2010-02-06 03:38:24 +00:00
|
|
|
channel->caps[cap] = value;
|
2009-10-14 19:26:10 +00:00
|
|
|
switch_mutex_unlock(channel->flag_mutex);
|
|
|
|
}
|
|
|
|
|
|
|
|
SWITCH_DECLARE(void) switch_channel_clear_cap(switch_channel_t *channel, switch_channel_cap_t cap)
|
|
|
|
{
|
|
|
|
switch_assert(channel != NULL);
|
|
|
|
switch_assert(channel->flag_mutex);
|
|
|
|
|
|
|
|
switch_mutex_lock(channel->flag_mutex);
|
|
|
|
channel->caps[cap] = 0;
|
|
|
|
switch_mutex_unlock(channel->flag_mutex);
|
|
|
|
}
|
|
|
|
|
|
|
|
SWITCH_DECLARE(uint32_t) switch_channel_test_cap(switch_channel_t *channel, switch_channel_cap_t cap)
|
|
|
|
{
|
|
|
|
switch_assert(channel != NULL);
|
|
|
|
return channel->caps[cap] ? 1 : 0;
|
|
|
|
}
|
|
|
|
|
2010-02-06 03:38:24 +00:00
|
|
|
SWITCH_DECLARE(char *) switch_channel_get_flag_string(switch_channel_t *channel)
|
|
|
|
{
|
|
|
|
switch_stream_handle_t stream = { 0 };
|
|
|
|
char *r;
|
|
|
|
int i = 0;
|
|
|
|
|
|
|
|
SWITCH_STANDARD_STREAM(stream);
|
|
|
|
|
|
|
|
switch_mutex_lock(channel->flag_mutex);
|
|
|
|
for (i = 0; i < CF_FLAG_MAX; i++) {
|
|
|
|
if (channel->flags[i]) {
|
|
|
|
stream.write_function(&stream, "%d=%d;", i, channel->flags[i]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
switch_mutex_unlock(channel->flag_mutex);
|
|
|
|
|
|
|
|
r = (char *) stream.data;
|
|
|
|
|
|
|
|
if (end_of(r) == ';') {
|
|
|
|
end_of(r) = '\0';
|
|
|
|
}
|
|
|
|
|
|
|
|
return r;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
SWITCH_DECLARE(char *) switch_channel_get_cap_string(switch_channel_t *channel)
|
|
|
|
{
|
|
|
|
switch_stream_handle_t stream = { 0 };
|
|
|
|
char *r;
|
|
|
|
int i = 0;
|
|
|
|
|
|
|
|
SWITCH_STANDARD_STREAM(stream);
|
|
|
|
|
|
|
|
switch_mutex_lock(channel->flag_mutex);
|
|
|
|
for (i = 0; i < CC_FLAG_MAX; i++) {
|
|
|
|
if (channel->caps[i]) {
|
|
|
|
stream.write_function(&stream, "%d=%d;", i, channel->caps[i]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
switch_mutex_unlock(channel->flag_mutex);
|
|
|
|
|
|
|
|
r = (char *) stream.data;
|
|
|
|
|
|
|
|
if (end_of(r) == ';') {
|
|
|
|
end_of(r) = '\0';
|
|
|
|
}
|
|
|
|
|
|
|
|
return r;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
SWITCH_DECLARE(void) switch_channel_set_flag_value(switch_channel_t *channel, switch_channel_flag_t flag, uint32_t value)
|
2005-11-19 20:07:43 +00:00
|
|
|
{
|
2010-07-16 16:43:14 +00:00
|
|
|
int HELD = 0;
|
|
|
|
|
2008-12-11 15:20:24 +00:00
|
|
|
switch_assert(channel);
|
|
|
|
switch_assert(channel->flag_mutex);
|
|
|
|
|
|
|
|
switch_mutex_lock(channel->flag_mutex);
|
2010-06-24 15:09:39 +00:00
|
|
|
if (flag == CF_LEG_HOLDING && !channel->flags[flag] && channel->flags[CF_ANSWERED]) {
|
2010-07-16 16:43:14 +00:00
|
|
|
HELD = 1;
|
2010-06-24 15:09:39 +00:00
|
|
|
}
|
2010-02-06 03:38:24 +00:00
|
|
|
channel->flags[flag] = value;
|
2008-12-11 15:20:24 +00:00
|
|
|
switch_mutex_unlock(channel->flag_mutex);
|
|
|
|
|
2010-07-16 16:43:14 +00:00
|
|
|
if (HELD) {
|
|
|
|
switch_channel_set_callstate(channel, CCS_HELD);
|
|
|
|
}
|
|
|
|
|
2008-12-11 15:20:24 +00:00
|
|
|
if (flag == CF_OUTBOUND) {
|
2008-10-22 18:32:54 +00:00
|
|
|
switch_channel_set_variable(channel, "is_outbound", "true");
|
|
|
|
}
|
2010-06-05 00:03:36 +00:00
|
|
|
|
2010-10-13 21:17:36 +00:00
|
|
|
if (flag == CF_RECOVERED) {
|
|
|
|
switch_channel_set_variable(channel, "recovered", "true");
|
|
|
|
}
|
|
|
|
|
2005-11-19 20:07:43 +00:00
|
|
|
}
|
|
|
|
|
2009-08-26 17:42:36 +00:00
|
|
|
SWITCH_DECLARE(void) switch_channel_set_flag_recursive(switch_channel_t *channel, switch_channel_flag_t flag)
|
|
|
|
{
|
|
|
|
switch_assert(channel);
|
|
|
|
switch_assert(channel->flag_mutex);
|
|
|
|
|
|
|
|
switch_mutex_lock(channel->flag_mutex);
|
|
|
|
channel->flags[flag]++;
|
|
|
|
switch_mutex_unlock(channel->flag_mutex);
|
|
|
|
|
|
|
|
if (flag == CF_OUTBOUND) {
|
|
|
|
switch_channel_set_variable(channel, "is_outbound", "true");
|
|
|
|
}
|
2010-10-13 21:17:36 +00:00
|
|
|
|
|
|
|
if (flag == CF_RECOVERED) {
|
|
|
|
switch_channel_set_variable(channel, "recovered", "true");
|
|
|
|
}
|
2009-08-26 17:42:36 +00:00
|
|
|
}
|
|
|
|
|
2008-12-04 04:46:10 +00:00
|
|
|
|
|
|
|
SWITCH_DECLARE(void) switch_channel_set_private_flag(switch_channel_t *channel, uint32_t flags)
|
|
|
|
{
|
|
|
|
switch_assert(channel != NULL);
|
|
|
|
switch_mutex_lock(channel->flag_mutex);
|
|
|
|
channel->private_flags |= flags;
|
|
|
|
switch_mutex_unlock(channel->flag_mutex);
|
|
|
|
}
|
|
|
|
|
|
|
|
SWITCH_DECLARE(void) switch_channel_clear_private_flag(switch_channel_t *channel, uint32_t flags)
|
|
|
|
{
|
|
|
|
switch_assert(channel != NULL);
|
|
|
|
switch_mutex_lock(channel->flag_mutex);
|
|
|
|
channel->private_flags &= ~flags;
|
|
|
|
switch_mutex_unlock(channel->flag_mutex);
|
|
|
|
}
|
|
|
|
|
|
|
|
SWITCH_DECLARE(int) switch_channel_test_private_flag(switch_channel_t *channel, uint32_t flags)
|
|
|
|
{
|
|
|
|
switch_assert(channel != NULL);
|
|
|
|
return (channel->private_flags & flags);
|
|
|
|
}
|
|
|
|
|
2010-07-22 19:37:21 +00:00
|
|
|
SWITCH_DECLARE(void) switch_channel_set_app_flag_key(const char *key, switch_channel_t *channel, uint32_t flags)
|
2009-01-22 14:01:15 +00:00
|
|
|
{
|
2010-07-22 19:37:21 +00:00
|
|
|
uint32_t *flagp = NULL;
|
2010-09-15 23:57:54 +00:00
|
|
|
switch_byte_t new = 0;
|
|
|
|
|
2009-01-22 14:01:15 +00:00
|
|
|
switch_assert(channel != NULL);
|
|
|
|
switch_mutex_lock(channel->flag_mutex);
|
2010-09-15 23:57:54 +00:00
|
|
|
|
|
|
|
if (!channel->app_flag_hash) {
|
2010-07-22 19:37:21 +00:00
|
|
|
switch_core_hash_init(&channel->app_flag_hash, switch_core_session_get_pool(channel->session));
|
2010-09-15 23:57:54 +00:00
|
|
|
new++;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (new || !(flagp = switch_core_hash_find(channel->app_flag_hash, key))) {
|
2010-07-22 19:37:21 +00:00
|
|
|
flagp = switch_core_session_alloc(channel->session, sizeof(uint32_t));
|
|
|
|
switch_core_hash_insert(channel->app_flag_hash, key, flagp);
|
|
|
|
}
|
|
|
|
|
2010-09-15 23:57:54 +00:00
|
|
|
switch_assert(flagp);
|
|
|
|
*flagp |= flags;
|
|
|
|
|
2009-01-22 14:01:15 +00:00
|
|
|
switch_mutex_unlock(channel->flag_mutex);
|
|
|
|
}
|
|
|
|
|
2010-07-22 19:37:21 +00:00
|
|
|
SWITCH_DECLARE(void) switch_channel_clear_app_flag_key(const char *key, switch_channel_t *channel, uint32_t flags)
|
2009-01-22 14:01:15 +00:00
|
|
|
{
|
2010-07-22 19:37:21 +00:00
|
|
|
uint32_t *flagp = NULL;
|
|
|
|
|
2009-01-22 14:01:15 +00:00
|
|
|
switch_assert(channel != NULL);
|
|
|
|
switch_mutex_lock(channel->flag_mutex);
|
2010-07-22 19:37:21 +00:00
|
|
|
if (channel->app_flag_hash && (flagp = switch_core_hash_find(channel->app_flag_hash, key))) {
|
|
|
|
if (!flags) {
|
|
|
|
*flagp = 0;
|
|
|
|
} else {
|
|
|
|
*flagp &= ~flags;
|
|
|
|
}
|
2009-01-22 14:01:15 +00:00
|
|
|
}
|
|
|
|
switch_mutex_unlock(channel->flag_mutex);
|
|
|
|
}
|
|
|
|
|
2010-07-22 19:37:21 +00:00
|
|
|
SWITCH_DECLARE(int) switch_channel_test_app_flag_key(const char *key, switch_channel_t *channel, uint32_t flags)
|
2009-01-22 14:01:15 +00:00
|
|
|
{
|
2010-07-22 19:37:21 +00:00
|
|
|
int r = 0;
|
|
|
|
uint32_t *flagp = NULL;
|
2009-01-22 14:01:15 +00:00
|
|
|
switch_assert(channel != NULL);
|
2010-07-22 19:37:21 +00:00
|
|
|
|
|
|
|
switch_mutex_lock(channel->flag_mutex);
|
|
|
|
if (channel->app_flag_hash && (flagp = switch_core_hash_find(channel->app_flag_hash, key))) {
|
|
|
|
r = (*flagp & flags);
|
|
|
|
}
|
|
|
|
switch_mutex_unlock(channel->flag_mutex);
|
|
|
|
|
|
|
|
|
|
|
|
return r;
|
2009-01-22 14:01:15 +00:00
|
|
|
}
|
|
|
|
|
2008-12-11 15:20:24 +00:00
|
|
|
SWITCH_DECLARE(void) switch_channel_set_state_flag(switch_channel_t *channel, switch_channel_flag_t flag)
|
2006-09-19 02:18:24 +00:00
|
|
|
{
|
2007-12-11 19:23:57 +00:00
|
|
|
switch_assert(channel != NULL);
|
2006-09-19 02:18:24 +00:00
|
|
|
|
|
|
|
switch_mutex_lock(channel->flag_mutex);
|
2008-12-11 15:20:24 +00:00
|
|
|
channel->state_flags[0] = 1;
|
|
|
|
channel->state_flags[flag] = 1;
|
2006-09-19 02:18:24 +00:00
|
|
|
switch_mutex_unlock(channel->flag_mutex);
|
|
|
|
}
|
|
|
|
|
2008-12-11 15:20:24 +00:00
|
|
|
SWITCH_DECLARE(void) switch_channel_clear_flag(switch_channel_t *channel, switch_channel_flag_t flag)
|
2005-11-19 20:07:43 +00:00
|
|
|
{
|
2010-07-16 16:43:14 +00:00
|
|
|
int ACTIVE = 0;
|
|
|
|
|
2007-12-11 19:23:57 +00:00
|
|
|
switch_assert(channel != NULL);
|
2008-12-11 15:20:24 +00:00
|
|
|
switch_assert(channel->flag_mutex);
|
|
|
|
|
|
|
|
switch_mutex_lock(channel->flag_mutex);
|
2010-06-24 15:09:39 +00:00
|
|
|
if (flag == CF_LEG_HOLDING && channel->flags[flag] && channel->flags[CF_ANSWERED]) {
|
2010-07-16 16:43:14 +00:00
|
|
|
ACTIVE = 1;
|
2010-06-24 15:09:39 +00:00
|
|
|
}
|
2008-12-11 15:20:24 +00:00
|
|
|
channel->flags[flag] = 0;
|
|
|
|
switch_mutex_unlock(channel->flag_mutex);
|
2010-02-06 03:38:24 +00:00
|
|
|
|
2010-07-16 16:43:14 +00:00
|
|
|
if (ACTIVE) {
|
|
|
|
switch_channel_set_callstate(channel, CCS_ACTIVE);
|
|
|
|
}
|
|
|
|
|
2008-12-11 15:20:24 +00:00
|
|
|
if (flag == CF_OUTBOUND) {
|
2008-10-22 18:32:54 +00:00
|
|
|
switch_channel_set_variable(channel, "is_outbound", NULL);
|
|
|
|
}
|
2010-10-13 21:17:36 +00:00
|
|
|
|
|
|
|
if (flag == CF_RECOVERED) {
|
|
|
|
switch_channel_set_variable(channel, "recovered", NULL);
|
|
|
|
}
|
2005-11-19 20:07:43 +00:00
|
|
|
}
|
|
|
|
|
2009-08-26 17:42:36 +00:00
|
|
|
|
|
|
|
SWITCH_DECLARE(void) switch_channel_clear_flag_recursive(switch_channel_t *channel, switch_channel_flag_t flag)
|
|
|
|
{
|
|
|
|
switch_assert(channel != NULL);
|
|
|
|
switch_assert(channel->flag_mutex);
|
|
|
|
|
|
|
|
switch_mutex_lock(channel->flag_mutex);
|
|
|
|
if (channel->flags[flag]) {
|
|
|
|
channel->flags[flag]--;
|
|
|
|
}
|
|
|
|
switch_mutex_unlock(channel->flag_mutex);
|
2010-02-06 03:38:24 +00:00
|
|
|
|
2009-08-26 17:42:36 +00:00
|
|
|
if (flag == CF_OUTBOUND) {
|
|
|
|
switch_channel_set_variable(channel, "is_outbound", NULL);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-04-29 23:43:28 +00:00
|
|
|
SWITCH_DECLARE(switch_channel_state_t) switch_channel_get_state(switch_channel_t *channel)
|
2005-11-19 20:07:43 +00:00
|
|
|
{
|
2006-09-16 00:43:58 +00:00
|
|
|
switch_channel_state_t state;
|
2007-12-11 19:23:57 +00:00
|
|
|
switch_assert(channel != NULL);
|
2006-09-16 00:43:58 +00:00
|
|
|
|
|
|
|
state = channel->state;
|
|
|
|
|
|
|
|
return state;
|
2005-11-19 20:07:43 +00:00
|
|
|
}
|
|
|
|
|
2007-12-08 00:14:21 +00:00
|
|
|
SWITCH_DECLARE(switch_channel_state_t) switch_channel_get_running_state(switch_channel_t *channel)
|
|
|
|
{
|
|
|
|
switch_channel_state_t state;
|
2007-12-11 19:23:57 +00:00
|
|
|
switch_assert(channel != NULL);
|
2007-12-08 00:14:21 +00:00
|
|
|
|
|
|
|
state = channel->running_state;
|
|
|
|
|
|
|
|
return state;
|
|
|
|
}
|
|
|
|
|
2010-06-03 02:57:16 +00:00
|
|
|
SWITCH_DECLARE(int) switch_channel_state_change_pending(switch_channel_t *channel)
|
|
|
|
{
|
|
|
|
return channel->running_state != channel->state;
|
|
|
|
}
|
|
|
|
|
2010-02-06 03:38:24 +00:00
|
|
|
SWITCH_DECLARE(int) switch_channel_test_ready(switch_channel_t *channel, switch_bool_t check_ready, switch_bool_t check_media)
|
2006-03-01 22:55:28 +00:00
|
|
|
{
|
2009-02-10 19:09:06 +00:00
|
|
|
int ret = 0;
|
2007-03-30 22:13:19 +00:00
|
|
|
|
2007-12-11 19:23:57 +00:00
|
|
|
switch_assert(channel != NULL);
|
2008-01-28 07:26:10 +00:00
|
|
|
|
2010-02-06 03:38:24 +00:00
|
|
|
if (check_media) {
|
|
|
|
ret = ((switch_channel_test_flag(channel, CF_ANSWERED) ||
|
|
|
|
switch_channel_test_flag(channel, CF_EARLY_MEDIA)) && !switch_channel_test_flag(channel, CF_PROXY_MODE) &&
|
2009-02-10 19:09:06 +00:00
|
|
|
switch_core_session_get_read_codec(channel->session) && switch_core_session_get_write_codec(channel->session));
|
2010-06-03 02:57:16 +00:00
|
|
|
|
2009-02-10 19:09:06 +00:00
|
|
|
|
2010-02-06 03:38:24 +00:00
|
|
|
if (!ret)
|
|
|
|
return ret;
|
2009-02-10 19:09:06 +00:00
|
|
|
}
|
2010-02-06 03:38:24 +00:00
|
|
|
|
|
|
|
if (!check_ready)
|
|
|
|
return ret;
|
|
|
|
|
2009-02-10 19:09:06 +00:00
|
|
|
ret = 0;
|
|
|
|
|
2008-05-27 04:30:03 +00:00
|
|
|
if (!channel->hangup_cause && channel->state > CS_ROUTING && channel->state < CS_HANGUP && channel->state != CS_RESET &&
|
2010-06-03 02:57:16 +00:00
|
|
|
!switch_channel_test_flag(channel, CF_TRANSFER) && !switch_channel_test_flag(channel, CF_NOT_READY) &&
|
|
|
|
!switch_channel_state_change_pending(channel)) {
|
2008-05-27 04:30:03 +00:00
|
|
|
ret++;
|
2007-03-30 22:13:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
2006-03-01 22:55:28 +00:00
|
|
|
}
|
|
|
|
|
2005-12-21 22:25:22 +00:00
|
|
|
static const char *state_names[] = {
|
|
|
|
"CS_NEW",
|
|
|
|
"CS_INIT",
|
2008-05-05 15:30:55 +00:00
|
|
|
"CS_ROUTING",
|
|
|
|
"CS_SOFT_EXECUTE",
|
2005-12-21 22:25:22 +00:00
|
|
|
"CS_EXECUTE",
|
2008-05-05 15:30:55 +00:00
|
|
|
"CS_EXCHANGE_MEDIA",
|
2007-12-13 22:17:20 +00:00
|
|
|
"CS_PARK",
|
2008-05-05 15:30:55 +00:00
|
|
|
"CS_CONSUME_MEDIA",
|
2006-10-31 21:38:06 +00:00
|
|
|
"CS_HIBERNATE",
|
2007-07-03 02:10:35 +00:00
|
|
|
"CS_RESET",
|
2005-12-21 22:25:22 +00:00
|
|
|
"CS_HANGUP",
|
2009-03-04 04:19:33 +00:00
|
|
|
"CS_REPORTING",
|
2009-04-10 17:43:18 +00:00
|
|
|
"CS_DESTROY",
|
2006-06-06 23:07:37 +00:00
|
|
|
NULL
|
2005-12-21 22:25:22 +00:00
|
|
|
};
|
|
|
|
|
2006-04-29 23:43:28 +00:00
|
|
|
SWITCH_DECLARE(const char *) switch_channel_state_name(switch_channel_state_t state)
|
2005-12-21 22:25:22 +00:00
|
|
|
{
|
|
|
|
return state_names[state];
|
|
|
|
}
|
|
|
|
|
2006-06-06 23:07:37 +00:00
|
|
|
|
2007-05-12 14:48:14 +00:00
|
|
|
SWITCH_DECLARE(switch_channel_state_t) switch_channel_name_state(const char *name)
|
2006-06-06 23:07:37 +00:00
|
|
|
{
|
|
|
|
uint32_t x = 0;
|
2007-03-29 22:31:56 +00:00
|
|
|
for (x = 0; state_names[x]; x++) {
|
2006-06-06 23:07:37 +00:00
|
|
|
if (!strcasecmp(state_names[x], name)) {
|
|
|
|
return (switch_channel_state_t) x;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-04-10 17:43:18 +00:00
|
|
|
return CS_DESTROY;
|
2006-06-06 23:07:37 +00:00
|
|
|
}
|
|
|
|
|
2008-03-08 21:07:15 +00:00
|
|
|
SWITCH_DECLARE(switch_channel_state_t) switch_channel_perform_set_running_state(switch_channel_t *channel, switch_channel_state_t state,
|
2007-12-08 00:14:21 +00:00
|
|
|
const char *file, const char *func, int line)
|
|
|
|
{
|
2008-12-11 15:20:24 +00:00
|
|
|
int x;
|
2009-02-20 18:31:08 +00:00
|
|
|
switch_mutex_lock(channel->state_mutex);
|
2010-02-06 03:38:24 +00:00
|
|
|
switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, func, line, switch_channel_get_uuid(channel), SWITCH_LOG_DEBUG, "(%s) Running State Change %s\n",
|
|
|
|
channel->name, state_names[state]);
|
2008-03-08 21:07:15 +00:00
|
|
|
channel->running_state = state;
|
2007-12-08 00:14:21 +00:00
|
|
|
|
2008-12-11 15:20:24 +00:00
|
|
|
if (channel->state_flags[0]) {
|
2010-02-06 03:38:24 +00:00
|
|
|
for (x = 1; x < CF_FLAG_MAX; x++) {
|
2008-12-11 15:20:24 +00:00
|
|
|
if (channel->state_flags[x]) {
|
|
|
|
channel->flags[x] = 1;
|
|
|
|
channel->state_flags[x] = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
channel->state_flags[0] = 0;
|
2007-12-19 23:24:55 +00:00
|
|
|
}
|
2008-01-28 07:26:10 +00:00
|
|
|
|
2008-12-11 15:20:24 +00:00
|
|
|
switch_channel_clear_flag(channel, CF_TAGGED);
|
2008-05-15 15:57:29 +00:00
|
|
|
|
2010-08-23 22:02:06 +00:00
|
|
|
if (channel->state == CS_ROUTING || channel->state == CS_HANGUP) {
|
2009-03-17 13:25:02 +00:00
|
|
|
switch_channel_presence(channel, "unknown", (const char *) state_names[state], NULL);
|
2007-12-15 00:39:53 +00:00
|
|
|
}
|
2008-01-28 07:26:10 +00:00
|
|
|
|
2009-08-26 21:53:43 +00:00
|
|
|
if (state <= CS_DESTROY) {
|
2007-12-08 00:14:21 +00:00
|
|
|
switch_event_t *event;
|
2010-06-05 00:03:36 +00:00
|
|
|
|
2010-06-07 23:01:02 +00:00
|
|
|
if (state < CS_HANGUP) {
|
|
|
|
if (state == CS_ROUTING) {
|
|
|
|
switch_channel_set_callstate(channel, CCS_RINGING);
|
|
|
|
} else if (switch_channel_test_flag(channel, CF_ANSWERED)) {
|
|
|
|
switch_channel_set_callstate(channel, CCS_ACTIVE);
|
|
|
|
} else if (switch_channel_test_flag(channel, CF_EARLY_MEDIA)) {
|
|
|
|
switch_channel_set_callstate(channel, CCS_EARLY);
|
|
|
|
}
|
2010-06-05 00:03:36 +00:00
|
|
|
}
|
|
|
|
|
2007-12-08 00:14:21 +00:00
|
|
|
if (switch_event_create(&event, SWITCH_EVENT_CHANNEL_STATE) == SWITCH_STATUS_SUCCESS) {
|
2008-05-05 15:30:55 +00:00
|
|
|
if (state == CS_ROUTING) {
|
2007-12-08 00:14:21 +00:00
|
|
|
switch_channel_event_set_data(channel, event);
|
|
|
|
} else {
|
2009-03-17 13:25:02 +00:00
|
|
|
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Channel-State", switch_channel_state_name(state));
|
2010-06-05 00:03:36 +00:00
|
|
|
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Channel-Call-State", switch_channel_callstate2str(channel->callstate));
|
2009-03-17 13:25:02 +00:00
|
|
|
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Channel-State-Number", "%d", state);
|
2008-08-16 02:17:09 +00:00
|
|
|
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Channel-Name", channel->name);
|
|
|
|
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Unique-ID", switch_core_session_get_uuid(channel->session));
|
|
|
|
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Call-Direction",
|
2009-02-24 00:05:19 +00:00
|
|
|
channel->direction == SWITCH_CALL_DIRECTION_OUTBOUND ? "outbound" : "inbound");
|
|
|
|
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Presence-Call-Direction",
|
|
|
|
channel->direction == SWITCH_CALL_DIRECTION_OUTBOUND ? "outbound" : "inbound");
|
2010-08-19 17:09:21 +00:00
|
|
|
|
|
|
|
if (switch_channel_down(channel)) {
|
|
|
|
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Answer-State", "hangup");
|
|
|
|
} else if (switch_channel_test_flag(channel, CF_ANSWERED)) {
|
2008-08-16 02:17:09 +00:00
|
|
|
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Answer-State", "answered");
|
2007-12-15 00:39:53 +00:00
|
|
|
} else if (switch_channel_test_flag(channel, CF_EARLY_MEDIA)) {
|
2008-08-16 02:17:09 +00:00
|
|
|
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Answer-State", "early");
|
2007-12-15 00:39:53 +00:00
|
|
|
} else {
|
2008-08-16 02:17:09 +00:00
|
|
|
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Answer-State", "ringing");
|
2007-12-15 00:39:53 +00:00
|
|
|
}
|
2007-12-08 00:14:21 +00:00
|
|
|
}
|
|
|
|
switch_event_fire(&event);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-02-20 18:31:08 +00:00
|
|
|
switch_mutex_unlock(channel->state_mutex);
|
2007-12-08 00:14:21 +00:00
|
|
|
|
|
|
|
return SWITCH_STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2006-04-29 23:43:28 +00:00
|
|
|
SWITCH_DECLARE(switch_channel_state_t) switch_channel_perform_set_state(switch_channel_t *channel,
|
2007-03-30 00:13:31 +00:00
|
|
|
const char *file, const char *func, int line, switch_channel_state_t state)
|
2005-11-19 20:07:43 +00:00
|
|
|
{
|
2006-04-29 23:43:28 +00:00
|
|
|
switch_channel_state_t last_state;
|
2005-11-19 20:07:43 +00:00
|
|
|
int ok = 0;
|
2005-12-21 22:25:22 +00:00
|
|
|
|
2007-12-11 19:23:57 +00:00
|
|
|
switch_assert(channel != NULL);
|
2009-04-10 17:43:18 +00:00
|
|
|
switch_assert(state <= CS_DESTROY);
|
2009-02-20 18:31:08 +00:00
|
|
|
switch_mutex_lock(channel->state_mutex);
|
2006-09-16 00:43:58 +00:00
|
|
|
|
2005-11-19 20:07:43 +00:00
|
|
|
last_state = channel->state;
|
2009-04-10 17:43:18 +00:00
|
|
|
switch_assert(last_state <= CS_DESTROY);
|
2005-11-19 20:07:43 +00:00
|
|
|
|
|
|
|
if (last_state == state) {
|
2006-09-16 00:43:58 +00:00
|
|
|
goto done;
|
2005-11-19 20:07:43 +00:00
|
|
|
}
|
|
|
|
|
2006-02-13 17:37:10 +00:00
|
|
|
if (last_state >= CS_HANGUP && state < last_state) {
|
2006-09-16 00:43:58 +00:00
|
|
|
goto done;
|
2005-12-06 17:18:56 +00:00
|
|
|
}
|
2007-03-29 22:31:56 +00:00
|
|
|
|
2005-11-19 20:07:43 +00:00
|
|
|
/* STUB for more dev
|
2008-05-27 04:30:03 +00:00
|
|
|
case CS_INIT:
|
|
|
|
switch(state) {
|
|
|
|
|
|
|
|
case CS_NEW:
|
|
|
|
case CS_INIT:
|
|
|
|
case CS_EXCHANGE_MEDIA:
|
|
|
|
case CS_SOFT_EXECUTE:
|
|
|
|
case CS_ROUTING:
|
|
|
|
case CS_EXECUTE:
|
|
|
|
case CS_HANGUP:
|
2009-04-10 17:43:18 +00:00
|
|
|
case CS_DESTROY:
|
2008-05-27 04:30:03 +00:00
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
*/
|
2006-01-20 15:05:05 +00:00
|
|
|
|
2008-05-27 04:30:03 +00:00
|
|
|
switch (last_state) {
|
2006-01-20 02:02:03 +00:00
|
|
|
case CS_NEW:
|
2008-05-27 04:30:03 +00:00
|
|
|
case CS_RESET:
|
|
|
|
switch (state) {
|
|
|
|
default:
|
|
|
|
ok++;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2006-01-20 02:02:03 +00:00
|
|
|
case CS_INIT:
|
2008-05-27 04:30:03 +00:00
|
|
|
switch (state) {
|
|
|
|
case CS_EXCHANGE_MEDIA:
|
|
|
|
case CS_SOFT_EXECUTE:
|
|
|
|
case CS_ROUTING:
|
|
|
|
case CS_EXECUTE:
|
|
|
|
case CS_PARK:
|
|
|
|
case CS_CONSUME_MEDIA:
|
|
|
|
case CS_HIBERNATE:
|
|
|
|
case CS_RESET:
|
|
|
|
ok++;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2008-05-05 15:30:55 +00:00
|
|
|
case CS_EXCHANGE_MEDIA:
|
2008-05-27 04:30:03 +00:00
|
|
|
switch (state) {
|
|
|
|
case CS_SOFT_EXECUTE:
|
|
|
|
case CS_ROUTING:
|
|
|
|
case CS_EXECUTE:
|
|
|
|
case CS_PARK:
|
|
|
|
case CS_CONSUME_MEDIA:
|
|
|
|
case CS_HIBERNATE:
|
|
|
|
case CS_RESET:
|
|
|
|
ok++;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2008-05-05 15:30:55 +00:00
|
|
|
case CS_SOFT_EXECUTE:
|
2008-05-27 04:30:03 +00:00
|
|
|
switch (state) {
|
|
|
|
case CS_EXCHANGE_MEDIA:
|
|
|
|
case CS_ROUTING:
|
|
|
|
case CS_EXECUTE:
|
|
|
|
case CS_PARK:
|
|
|
|
case CS_CONSUME_MEDIA:
|
|
|
|
case CS_HIBERNATE:
|
|
|
|
case CS_RESET:
|
|
|
|
ok++;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case CS_PARK:
|
|
|
|
switch (state) {
|
|
|
|
case CS_EXCHANGE_MEDIA:
|
|
|
|
case CS_ROUTING:
|
|
|
|
case CS_EXECUTE:
|
|
|
|
case CS_SOFT_EXECUTE:
|
|
|
|
case CS_HIBERNATE:
|
|
|
|
case CS_RESET:
|
|
|
|
case CS_CONSUME_MEDIA:
|
|
|
|
ok++;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case CS_CONSUME_MEDIA:
|
|
|
|
switch (state) {
|
|
|
|
case CS_EXCHANGE_MEDIA:
|
|
|
|
case CS_ROUTING:
|
|
|
|
case CS_EXECUTE:
|
|
|
|
case CS_SOFT_EXECUTE:
|
|
|
|
case CS_HIBERNATE:
|
|
|
|
case CS_RESET:
|
|
|
|
case CS_PARK:
|
|
|
|
ok++;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case CS_HIBERNATE:
|
|
|
|
switch (state) {
|
|
|
|
case CS_EXCHANGE_MEDIA:
|
|
|
|
case CS_INIT:
|
|
|
|
case CS_ROUTING:
|
|
|
|
case CS_EXECUTE:
|
|
|
|
case CS_SOFT_EXECUTE:
|
|
|
|
case CS_PARK:
|
|
|
|
case CS_CONSUME_MEDIA:
|
|
|
|
case CS_RESET:
|
|
|
|
ok++;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2008-05-05 15:30:55 +00:00
|
|
|
case CS_ROUTING:
|
2008-05-27 04:30:03 +00:00
|
|
|
switch (state) {
|
|
|
|
case CS_EXCHANGE_MEDIA:
|
|
|
|
case CS_EXECUTE:
|
|
|
|
case CS_SOFT_EXECUTE:
|
|
|
|
case CS_PARK:
|
|
|
|
case CS_CONSUME_MEDIA:
|
|
|
|
case CS_HIBERNATE:
|
|
|
|
case CS_RESET:
|
|
|
|
ok++;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2005-11-19 20:07:43 +00:00
|
|
|
case CS_EXECUTE:
|
2008-05-27 04:30:03 +00:00
|
|
|
switch (state) {
|
|
|
|
case CS_EXCHANGE_MEDIA:
|
|
|
|
case CS_SOFT_EXECUTE:
|
|
|
|
case CS_ROUTING:
|
|
|
|
case CS_PARK:
|
|
|
|
case CS_CONSUME_MEDIA:
|
|
|
|
case CS_HIBERNATE:
|
|
|
|
case CS_RESET:
|
|
|
|
ok++;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2005-11-19 20:07:43 +00:00
|
|
|
case CS_HANGUP:
|
2009-03-04 04:19:33 +00:00
|
|
|
switch (state) {
|
|
|
|
case CS_REPORTING:
|
2009-04-10 17:43:18 +00:00
|
|
|
case CS_DESTROY:
|
2009-03-04 04:19:33 +00:00
|
|
|
ok++;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case CS_REPORTING:
|
2008-05-27 04:30:03 +00:00
|
|
|
switch (state) {
|
2009-04-10 17:43:18 +00:00
|
|
|
case CS_DESTROY:
|
2008-05-27 04:30:03 +00:00
|
|
|
ok++;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
2005-11-19 20:07:43 +00:00
|
|
|
|
|
|
|
default:
|
2008-05-27 04:30:03 +00:00
|
|
|
break;
|
2005-11-19 20:07:43 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ok) {
|
2009-08-13 20:35:02 +00:00
|
|
|
switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, func, line, switch_channel_get_uuid(channel), SWITCH_LOG_DEBUG, "(%s) State Change %s -> %s\n",
|
2008-05-27 04:30:03 +00:00
|
|
|
channel->name, state_names[last_state], state_names[state]);
|
2009-03-20 01:50:50 +00:00
|
|
|
|
2005-11-19 20:07:43 +00:00
|
|
|
channel->state = state;
|
2006-04-22 18:12:17 +00:00
|
|
|
|
2007-01-26 20:39:45 +00:00
|
|
|
if (state == CS_HANGUP && !channel->hangup_cause) {
|
2006-04-22 18:12:17 +00:00
|
|
|
channel->hangup_cause = SWITCH_CAUSE_NORMAL_CLEARING;
|
|
|
|
}
|
2007-03-29 22:31:56 +00:00
|
|
|
|
2009-08-26 21:53:43 +00:00
|
|
|
if (state <= CS_DESTROY) {
|
2006-03-22 17:05:16 +00:00
|
|
|
switch_core_session_signal_state_change(channel->session);
|
|
|
|
}
|
2005-11-19 20:07:43 +00:00
|
|
|
} else {
|
2009-08-13 20:35:02 +00:00
|
|
|
switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, func, line, switch_channel_get_uuid(channel), SWITCH_LOG_WARNING,
|
2008-10-10 03:22:34 +00:00
|
|
|
"(%s) Invalid State Change %s -> %s\n", channel->name, state_names[last_state], state_names[state]);
|
2007-03-04 01:46:08 +00:00
|
|
|
/* we won't tolerate an invalid state change so we can make sure we are as robust as a nice cup of dark coffee! */
|
2008-03-08 21:07:15 +00:00
|
|
|
/* not cool lets crash this bad boy and figure out wtf is going on */
|
|
|
|
switch_assert(channel->state >= CS_HANGUP);
|
2005-11-19 20:07:43 +00:00
|
|
|
}
|
2008-05-27 04:30:03 +00:00
|
|
|
done:
|
2007-03-29 22:31:56 +00:00
|
|
|
|
2009-02-20 18:31:08 +00:00
|
|
|
switch_mutex_unlock(channel->state_mutex);
|
2005-11-19 20:07:43 +00:00
|
|
|
return channel->state;
|
|
|
|
}
|
|
|
|
|
2009-01-05 20:43:53 +00:00
|
|
|
SWITCH_DECLARE(void) switch_channel_event_set_basic_data(switch_channel_t *channel, switch_event_t *event)
|
2005-12-21 22:25:22 +00:00
|
|
|
{
|
2006-12-01 15:26:37 +00:00
|
|
|
switch_caller_profile_t *caller_profile, *originator_caller_profile = NULL, *originatee_caller_profile = NULL;
|
2010-02-06 03:38:24 +00:00
|
|
|
switch_codec_implementation_t impl = { 0 };
|
2006-04-04 21:26:21 +00:00
|
|
|
char state_num[25];
|
2009-11-17 00:12:54 +00:00
|
|
|
const char *v;
|
2010-02-06 03:38:24 +00:00
|
|
|
|
2007-06-24 04:06:05 +00:00
|
|
|
switch_mutex_lock(channel->profile_mutex);
|
|
|
|
|
2009-12-08 01:20:22 +00:00
|
|
|
if ((caller_profile = channel->caller_profile)) {
|
2007-03-29 22:31:56 +00:00
|
|
|
originator_caller_profile = caller_profile->originator_caller_profile;
|
|
|
|
originatee_caller_profile = caller_profile->originatee_caller_profile;
|
|
|
|
}
|
2006-01-03 01:17:59 +00:00
|
|
|
|
2008-08-16 02:17:09 +00:00
|
|
|
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Channel-State", switch_channel_state_name(channel->state));
|
2010-06-05 00:03:36 +00:00
|
|
|
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Channel-Call-State", switch_channel_callstate2str(channel->callstate));
|
2007-12-12 21:53:32 +00:00
|
|
|
switch_snprintf(state_num, sizeof(state_num), "%d", channel->state);
|
2008-08-16 02:17:09 +00:00
|
|
|
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Channel-State-Number", state_num);
|
|
|
|
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Channel-Name", switch_channel_get_name(channel));
|
|
|
|
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Unique-ID", switch_core_session_get_uuid(channel->session));
|
2010-02-06 03:38:24 +00:00
|
|
|
|
2009-02-24 00:05:19 +00:00
|
|
|
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Call-Direction",
|
|
|
|
channel->direction == SWITCH_CALL_DIRECTION_OUTBOUND ? "outbound" : "inbound");
|
|
|
|
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Presence-Call-Direction",
|
|
|
|
channel->direction == SWITCH_CALL_DIRECTION_OUTBOUND ? "outbound" : "inbound");
|
|
|
|
|
2009-11-17 00:12:54 +00:00
|
|
|
if ((v = switch_channel_get_variable(channel, "presence_id"))) {
|
|
|
|
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Channel-Presence-ID", v);
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((v = switch_channel_get_variable(channel, "presence_data"))) {
|
|
|
|
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Channel-Presence-Data", v);
|
|
|
|
}
|
|
|
|
|
2010-07-13 05:47:41 +00:00
|
|
|
|
|
|
|
if ((v = switch_channel_get_variable(channel, "presence_data_cols"))) {
|
|
|
|
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Presence-Data-Cols", v);
|
|
|
|
}
|
|
|
|
|
2010-06-25 18:19:53 +00:00
|
|
|
if ((v = switch_channel_get_variable(channel, "call_uuid"))) {
|
|
|
|
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Channel-Call-UUID", v);
|
|
|
|
}
|
2007-03-29 22:31:56 +00:00
|
|
|
|
2010-08-19 17:09:21 +00:00
|
|
|
if (switch_channel_down(channel)) {
|
|
|
|
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Answer-State", "hangup");
|
|
|
|
} else if (switch_channel_test_flag(channel, CF_ANSWERED)) {
|
2008-08-16 02:17:09 +00:00
|
|
|
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Answer-State", "answered");
|
2007-12-15 00:39:53 +00:00
|
|
|
} else if (switch_channel_test_flag(channel, CF_EARLY_MEDIA)) {
|
2008-08-16 02:17:09 +00:00
|
|
|
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Answer-State", "early");
|
2007-12-15 00:39:53 +00:00
|
|
|
} else {
|
2008-08-16 02:17:09 +00:00
|
|
|
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Answer-State", "ringing");
|
2007-12-15 00:39:53 +00:00
|
|
|
}
|
|
|
|
|
2009-03-20 01:50:50 +00:00
|
|
|
switch_core_session_get_read_impl(channel->session, &impl);
|
|
|
|
|
|
|
|
if (impl.iananame) {
|
|
|
|
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Channel-Read-Codec-Name", impl.iananame);
|
|
|
|
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Channel-Read-Codec-Rate", "%u", impl.actual_samples_per_second);
|
2010-09-29 21:52:34 +00:00
|
|
|
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Channel-Read-Codec-Bit-Rate", "%d", impl.bits_per_second);
|
2006-07-20 03:55:07 +00:00
|
|
|
}
|
2007-03-29 22:31:56 +00:00
|
|
|
|
2009-03-20 01:50:50 +00:00
|
|
|
switch_core_session_get_write_impl(channel->session, &impl);
|
|
|
|
|
|
|
|
if (impl.iananame) {
|
|
|
|
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Channel-Write-Codec-Name", impl.iananame);
|
|
|
|
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Channel-Write-Codec-Rate", "%u", impl.actual_samples_per_second);
|
2010-09-29 21:52:34 +00:00
|
|
|
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Channel-Write-Codec-Bit-Rate", "%d", impl.bits_per_second);
|
2006-07-20 03:55:07 +00:00
|
|
|
}
|
2009-01-05 20:43:53 +00:00
|
|
|
|
2008-10-08 14:22:55 +00:00
|
|
|
/* Index Caller's Profile */
|
|
|
|
if (caller_profile) {
|
|
|
|
switch_caller_profile_event_set_data(caller_profile, "Caller", event);
|
|
|
|
}
|
2010-02-06 03:38:24 +00:00
|
|
|
|
2008-10-08 14:22:55 +00:00
|
|
|
if (originator_caller_profile && originatee_caller_profile) {
|
|
|
|
/* Index Originator's Profile */
|
|
|
|
switch_caller_profile_event_set_data(originator_caller_profile, "Originator", event);
|
2010-02-06 03:38:24 +00:00
|
|
|
|
2008-10-08 14:22:55 +00:00
|
|
|
/* Index Originatee's Profile */
|
|
|
|
switch_caller_profile_event_set_data(originatee_caller_profile, "Originatee", event);
|
|
|
|
} else {
|
|
|
|
/* Index Originator's Profile */
|
|
|
|
if (originator_caller_profile) {
|
2010-08-17 22:26:36 +00:00
|
|
|
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Other-Type", "originator");
|
2008-10-08 14:22:55 +00:00
|
|
|
switch_caller_profile_event_set_data(originator_caller_profile, "Other-Leg", event);
|
|
|
|
} else if (originatee_caller_profile) { /* Index Originatee's Profile */
|
2010-08-17 22:26:36 +00:00
|
|
|
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Other-Type", "originatee");
|
2008-10-08 14:22:55 +00:00
|
|
|
switch_caller_profile_event_set_data(originatee_caller_profile, "Other-Leg", event);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-01-05 20:51:45 +00:00
|
|
|
switch_mutex_unlock(channel->profile_mutex);
|
2009-01-05 20:43:53 +00:00
|
|
|
}
|
2005-12-21 22:25:22 +00:00
|
|
|
|
2009-01-05 20:43:53 +00:00
|
|
|
SWITCH_DECLARE(void) switch_channel_event_set_extended_data(switch_channel_t *channel, switch_event_t *event)
|
|
|
|
{
|
|
|
|
switch_event_header_t *hi;
|
2010-11-17 18:17:27 +00:00
|
|
|
int global_verbose_events = -1;
|
2009-01-05 20:43:53 +00:00
|
|
|
|
2009-01-05 20:51:45 +00:00
|
|
|
switch_mutex_lock(channel->profile_mutex);
|
2010-02-06 03:38:24 +00:00
|
|
|
|
2010-07-13 05:47:41 +00:00
|
|
|
switch_core_session_ctl(SCSC_VERBOSE_EVENTS, &global_verbose_events);
|
2010-04-27 21:52:29 +00:00
|
|
|
|
2010-07-13 05:47:41 +00:00
|
|
|
if (global_verbose_events ||
|
|
|
|
switch_channel_test_flag(channel, CF_VERBOSE_EVENTS) ||
|
|
|
|
switch_event_get_header(event, "presence-data-cols") ||
|
2010-03-03 03:20:27 +00:00
|
|
|
event->event_id == SWITCH_EVENT_CHANNEL_CREATE ||
|
2008-10-02 15:38:45 +00:00
|
|
|
event->event_id == SWITCH_EVENT_CHANNEL_ORIGINATE ||
|
2008-11-04 16:46:33 +00:00
|
|
|
event->event_id == SWITCH_EVENT_CHANNEL_UUID ||
|
2008-10-02 15:38:45 +00:00
|
|
|
event->event_id == SWITCH_EVENT_CHANNEL_ANSWER ||
|
2009-01-08 16:41:32 +00:00
|
|
|
event->event_id == SWITCH_EVENT_CHANNEL_PARK ||
|
|
|
|
event->event_id == SWITCH_EVENT_CHANNEL_UNPARK ||
|
2009-01-08 16:43:07 +00:00
|
|
|
event->event_id == SWITCH_EVENT_CHANNEL_BRIDGE ||
|
|
|
|
event->event_id == SWITCH_EVENT_CHANNEL_UNBRIDGE ||
|
2008-10-02 15:38:45 +00:00
|
|
|
event->event_id == SWITCH_EVENT_CHANNEL_PROGRESS ||
|
|
|
|
event->event_id == SWITCH_EVENT_CHANNEL_PROGRESS_MEDIA ||
|
2008-10-02 17:10:05 +00:00
|
|
|
event->event_id == SWITCH_EVENT_CHANNEL_HANGUP ||
|
2009-06-01 12:45:56 +00:00
|
|
|
event->event_id == SWITCH_EVENT_CHANNEL_HANGUP_COMPLETE ||
|
2008-10-02 17:10:05 +00:00
|
|
|
event->event_id == SWITCH_EVENT_REQUEST_PARAMS ||
|
2008-10-02 20:52:42 +00:00
|
|
|
event->event_id == SWITCH_EVENT_CHANNEL_DATA ||
|
2008-12-08 17:17:29 +00:00
|
|
|
event->event_id == SWITCH_EVENT_CHANNEL_EXECUTE_COMPLETE ||
|
2008-10-08 14:22:55 +00:00
|
|
|
event->event_id == SWITCH_EVENT_SESSION_HEARTBEAT ||
|
2009-04-21 14:57:43 +00:00
|
|
|
event->event_id == SWITCH_EVENT_API ||
|
2009-08-21 22:29:44 +00:00
|
|
|
event->event_id == SWITCH_EVENT_RECORD_START ||
|
2010-03-02 01:11:15 +00:00
|
|
|
event->event_id == SWITCH_EVENT_RECORD_STOP ||
|
|
|
|
event->event_id == SWITCH_EVENT_CALL_UPDATE ||
|
|
|
|
event->event_id == SWITCH_EVENT_MEDIA_BUG_START ||
|
|
|
|
event->event_id == SWITCH_EVENT_MEDIA_BUG_STOP ||
|
|
|
|
event->event_id == SWITCH_EVENT_CUSTOM) {
|
2008-10-02 15:38:45 +00:00
|
|
|
|
|
|
|
/* Index Variables */
|
|
|
|
if (channel->variables) {
|
|
|
|
for (hi = channel->variables->headers; hi; hi = hi->next) {
|
|
|
|
char buf[1024];
|
|
|
|
char *vvar = NULL, *vval = NULL;
|
2010-02-06 03:38:24 +00:00
|
|
|
|
2008-10-02 15:38:45 +00:00
|
|
|
vvar = (char *) hi->name;
|
|
|
|
vval = (char *) hi->value;
|
2010-11-17 18:17:27 +00:00
|
|
|
|
2008-10-02 15:38:45 +00:00
|
|
|
switch_assert(vvar && vval);
|
|
|
|
switch_snprintf(buf, sizeof(buf), "variable_%s", vvar);
|
|
|
|
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, buf, vval);
|
|
|
|
}
|
2008-03-11 03:45:16 +00:00
|
|
|
}
|
2005-12-21 22:25:22 +00:00
|
|
|
}
|
2008-10-02 15:38:45 +00:00
|
|
|
|
2007-06-24 04:06:05 +00:00
|
|
|
switch_mutex_unlock(channel->profile_mutex);
|
2005-12-21 22:25:22 +00:00
|
|
|
}
|
|
|
|
|
2009-01-05 20:43:53 +00:00
|
|
|
|
|
|
|
SWITCH_DECLARE(void) switch_channel_event_set_data(switch_channel_t *channel, switch_event_t *event)
|
|
|
|
{
|
2009-01-05 20:51:45 +00:00
|
|
|
switch_mutex_lock(channel->profile_mutex);
|
2009-01-05 20:43:53 +00:00
|
|
|
switch_channel_event_set_basic_data(channel, event);
|
|
|
|
switch_channel_event_set_extended_data(channel, event);
|
2009-01-05 20:51:45 +00:00
|
|
|
switch_mutex_unlock(channel->profile_mutex);
|
2009-01-05 20:43:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2007-03-30 00:13:31 +00:00
|
|
|
SWITCH_DECLARE(void) switch_channel_set_caller_profile(switch_channel_t *channel, switch_caller_profile_t *caller_profile)
|
2005-11-19 20:07:43 +00:00
|
|
|
{
|
2007-09-12 22:36:26 +00:00
|
|
|
char *uuid = NULL;
|
2007-12-11 19:23:57 +00:00
|
|
|
switch_assert(channel != NULL);
|
|
|
|
switch_assert(channel->session != NULL);
|
2006-04-28 19:46:57 +00:00
|
|
|
switch_mutex_lock(channel->profile_mutex);
|
2007-12-11 19:23:57 +00:00
|
|
|
switch_assert(caller_profile != NULL);
|
2008-01-28 07:26:10 +00:00
|
|
|
|
2010-08-17 22:26:36 +00:00
|
|
|
caller_profile->direction = channel->direction;
|
2007-09-12 22:36:26 +00:00
|
|
|
uuid = switch_core_session_get_uuid(channel->session);
|
2008-01-28 07:26:10 +00:00
|
|
|
|
2007-09-12 22:36:26 +00:00
|
|
|
if (!caller_profile->uuid || strcasecmp(caller_profile->uuid, uuid)) {
|
|
|
|
caller_profile->uuid = switch_core_session_strdup(channel->session, uuid);
|
2006-02-22 02:50:33 +00:00
|
|
|
}
|
|
|
|
|
2007-09-12 22:36:26 +00:00
|
|
|
if (!caller_profile->chan_name || strcasecmp(caller_profile->chan_name, channel->name)) {
|
2006-02-22 02:50:33 +00:00
|
|
|
caller_profile->chan_name = switch_core_session_strdup(channel->session, channel->name);
|
|
|
|
}
|
|
|
|
|
2006-05-10 03:23:05 +00:00
|
|
|
if (!caller_profile->context) {
|
2007-09-12 22:36:26 +00:00
|
|
|
caller_profile->context = switch_core_session_strdup(channel->session, "default");
|
2006-05-10 03:23:05 +00:00
|
|
|
}
|
|
|
|
|
2006-04-04 21:26:21 +00:00
|
|
|
if (!channel->caller_profile) {
|
2006-04-29 01:00:52 +00:00
|
|
|
switch_event_t *event;
|
2006-04-04 21:26:21 +00:00
|
|
|
|
|
|
|
if (switch_event_create(&event, SWITCH_EVENT_CHANNEL_CREATE) == SWITCH_STATUS_SUCCESS) {
|
|
|
|
switch_channel_event_set_data(channel, event);
|
|
|
|
switch_event_fire(&event);
|
|
|
|
}
|
2007-03-29 22:31:56 +00:00
|
|
|
}
|
|
|
|
|
2010-02-06 03:38:24 +00:00
|
|
|
if (!caller_profile->times) {
|
|
|
|
caller_profile->times = (switch_channel_timetable_t *) switch_core_session_alloc(channel->session, sizeof(*caller_profile->times));
|
|
|
|
caller_profile->times->profile_created = switch_micro_time_now();
|
|
|
|
}
|
2006-12-01 15:26:37 +00:00
|
|
|
|
2007-03-29 22:31:56 +00:00
|
|
|
if (channel->caller_profile && channel->caller_profile->times) {
|
2007-12-20 17:27:11 +00:00
|
|
|
channel->caller_profile->times->transferred = caller_profile->times->profile_created;
|
2007-03-29 22:31:56 +00:00
|
|
|
caller_profile->times->answered = channel->caller_profile->times->answered;
|
2008-05-24 01:43:12 +00:00
|
|
|
caller_profile->times->progress = channel->caller_profile->times->progress;
|
|
|
|
caller_profile->times->progress_media = channel->caller_profile->times->progress_media;
|
2007-12-20 17:27:11 +00:00
|
|
|
caller_profile->times->created = channel->caller_profile->times->created;
|
|
|
|
caller_profile->times->hungup = channel->caller_profile->times->hungup;
|
2008-08-13 21:46:06 +00:00
|
|
|
if (channel->caller_profile->caller_extension) {
|
|
|
|
switch_caller_extension_clone(&caller_profile->caller_extension, channel->caller_profile->caller_extension, caller_profile->pool);
|
|
|
|
}
|
2007-12-20 18:04:07 +00:00
|
|
|
} else {
|
2009-01-25 21:23:07 +00:00
|
|
|
caller_profile->times->created = switch_micro_time_now();
|
2007-03-29 22:31:56 +00:00
|
|
|
}
|
2006-04-04 21:26:21 +00:00
|
|
|
|
2010-08-17 22:26:36 +00:00
|
|
|
|
2006-04-28 19:46:57 +00:00
|
|
|
caller_profile->next = channel->caller_profile;
|
2005-11-19 20:07:43 +00:00
|
|
|
channel->caller_profile = caller_profile;
|
2008-02-26 23:29:58 +00:00
|
|
|
caller_profile->profile_index = switch_core_sprintf(caller_profile->pool, "%d", ++channel->profile_index);
|
2008-05-27 04:30:03 +00:00
|
|
|
|
2006-04-28 19:46:57 +00:00
|
|
|
switch_mutex_unlock(channel->profile_mutex);
|
2005-11-19 20:07:43 +00:00
|
|
|
}
|
|
|
|
|
2006-04-29 06:05:03 +00:00
|
|
|
SWITCH_DECLARE(switch_caller_profile_t *) switch_channel_get_caller_profile(switch_channel_t *channel)
|
2005-11-19 20:07:43 +00:00
|
|
|
{
|
2006-04-29 06:05:03 +00:00
|
|
|
switch_caller_profile_t *profile;
|
2007-12-11 19:23:57 +00:00
|
|
|
switch_assert(channel != NULL);
|
2006-04-28 19:46:57 +00:00
|
|
|
switch_mutex_lock(channel->profile_mutex);
|
2009-06-05 01:46:09 +00:00
|
|
|
if ((profile = channel->caller_profile) && profile->hunt_caller_profile) {
|
|
|
|
profile = profile->hunt_caller_profile;
|
|
|
|
}
|
2006-04-28 19:46:57 +00:00
|
|
|
switch_mutex_unlock(channel->profile_mutex);
|
|
|
|
return profile;
|
2005-11-19 20:07:43 +00:00
|
|
|
}
|
|
|
|
|
2007-03-30 00:13:31 +00:00
|
|
|
SWITCH_DECLARE(void) switch_channel_set_originator_caller_profile(switch_channel_t *channel, switch_caller_profile_t *caller_profile)
|
2005-11-19 20:07:43 +00:00
|
|
|
{
|
2007-12-11 19:23:57 +00:00
|
|
|
switch_assert(channel != NULL);
|
2007-12-11 19:54:04 +00:00
|
|
|
switch_assert(channel->caller_profile != NULL);
|
2007-09-29 01:06:08 +00:00
|
|
|
switch_mutex_lock(channel->profile_mutex);
|
2008-10-22 18:32:54 +00:00
|
|
|
|
|
|
|
if (!caller_profile->times) {
|
|
|
|
caller_profile->times = (switch_channel_timetable_t *) switch_core_alloc(caller_profile->pool, sizeof(*caller_profile->times));
|
|
|
|
}
|
|
|
|
|
2007-03-29 22:31:56 +00:00
|
|
|
if (channel->caller_profile) {
|
|
|
|
caller_profile->next = channel->caller_profile->originator_caller_profile;
|
|
|
|
channel->caller_profile->originator_caller_profile = caller_profile;
|
|
|
|
}
|
2007-12-11 19:23:57 +00:00
|
|
|
switch_assert(channel->caller_profile->originator_caller_profile->next != channel->caller_profile->originator_caller_profile);
|
2007-09-29 01:06:08 +00:00
|
|
|
switch_mutex_unlock(channel->profile_mutex);
|
2005-11-19 20:07:43 +00:00
|
|
|
}
|
|
|
|
|
2009-06-05 01:05:11 +00:00
|
|
|
SWITCH_DECLARE(void) switch_channel_set_hunt_caller_profile(switch_channel_t *channel, switch_caller_profile_t *caller_profile)
|
|
|
|
{
|
|
|
|
switch_assert(channel != NULL);
|
|
|
|
switch_assert(channel->caller_profile != NULL);
|
|
|
|
|
|
|
|
switch_mutex_lock(channel->profile_mutex);
|
2010-08-18 00:26:19 +00:00
|
|
|
|
2009-06-05 01:05:11 +00:00
|
|
|
channel->caller_profile->hunt_caller_profile = NULL;
|
|
|
|
if (channel->caller_profile && caller_profile) {
|
2010-08-18 00:26:19 +00:00
|
|
|
caller_profile->direction = channel->direction;
|
2009-06-05 01:05:11 +00:00
|
|
|
channel->caller_profile->hunt_caller_profile = caller_profile;
|
|
|
|
}
|
|
|
|
switch_mutex_unlock(channel->profile_mutex);
|
|
|
|
}
|
|
|
|
|
2010-09-08 18:19:56 +00:00
|
|
|
SWITCH_DECLARE(void) switch_channel_set_origination_caller_profile(switch_channel_t *channel, switch_caller_profile_t *caller_profile)
|
|
|
|
{
|
|
|
|
switch_assert(channel != NULL);
|
|
|
|
switch_assert(channel->caller_profile != NULL);
|
|
|
|
|
|
|
|
switch_mutex_lock(channel->profile_mutex);
|
|
|
|
|
|
|
|
if (channel->caller_profile) {
|
|
|
|
caller_profile->next = channel->caller_profile->origination_caller_profile;
|
|
|
|
channel->caller_profile->origination_caller_profile = caller_profile;
|
|
|
|
}
|
|
|
|
switch_assert(channel->caller_profile->origination_caller_profile->next != channel->caller_profile->origination_caller_profile);
|
|
|
|
switch_mutex_unlock(channel->profile_mutex);
|
|
|
|
}
|
|
|
|
|
|
|
|
SWITCH_DECLARE(switch_caller_profile_t *) switch_channel_get_origination_caller_profile(switch_channel_t *channel)
|
|
|
|
{
|
|
|
|
switch_caller_profile_t *profile = NULL;
|
|
|
|
switch_assert(channel != NULL);
|
|
|
|
|
|
|
|
switch_mutex_lock(channel->profile_mutex);
|
|
|
|
if (channel->caller_profile) {
|
|
|
|
profile = channel->caller_profile->origination_caller_profile;
|
|
|
|
}
|
|
|
|
switch_mutex_unlock(channel->profile_mutex);
|
|
|
|
|
|
|
|
return profile;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-03-30 00:13:31 +00:00
|
|
|
SWITCH_DECLARE(void) switch_channel_set_originatee_caller_profile(switch_channel_t *channel, switch_caller_profile_t *caller_profile)
|
2005-12-26 19:09:59 +00:00
|
|
|
{
|
2007-12-11 19:23:57 +00:00
|
|
|
switch_assert(channel != NULL);
|
2007-12-11 19:54:04 +00:00
|
|
|
switch_assert(channel->caller_profile != NULL);
|
2007-09-29 01:06:08 +00:00
|
|
|
|
|
|
|
switch_mutex_lock(channel->profile_mutex);
|
2010-08-17 22:26:36 +00:00
|
|
|
|
2007-03-29 22:31:56 +00:00
|
|
|
if (channel->caller_profile) {
|
|
|
|
caller_profile->next = channel->caller_profile->originatee_caller_profile;
|
|
|
|
channel->caller_profile->originatee_caller_profile = caller_profile;
|
|
|
|
}
|
2007-12-11 19:23:57 +00:00
|
|
|
switch_assert(channel->caller_profile->originatee_caller_profile->next != channel->caller_profile->originatee_caller_profile);
|
2008-05-27 04:30:03 +00:00
|
|
|
switch_mutex_unlock(channel->profile_mutex);
|
2005-12-26 19:09:59 +00:00
|
|
|
}
|
|
|
|
|
2006-04-29 06:05:03 +00:00
|
|
|
SWITCH_DECLARE(switch_caller_profile_t *) switch_channel_get_originator_caller_profile(switch_channel_t *channel)
|
2005-11-19 20:07:43 +00:00
|
|
|
{
|
2006-12-01 15:26:37 +00:00
|
|
|
switch_caller_profile_t *profile = NULL;
|
2007-12-11 19:23:57 +00:00
|
|
|
switch_assert(channel != NULL);
|
2006-04-28 19:46:57 +00:00
|
|
|
|
2007-09-29 01:06:08 +00:00
|
|
|
switch_mutex_lock(channel->profile_mutex);
|
2010-08-17 22:26:36 +00:00
|
|
|
|
2007-03-29 22:31:56 +00:00
|
|
|
if (channel->caller_profile) {
|
|
|
|
profile = channel->caller_profile->originator_caller_profile;
|
|
|
|
}
|
2007-09-29 01:06:08 +00:00
|
|
|
switch_mutex_unlock(channel->profile_mutex);
|
2008-01-28 07:26:10 +00:00
|
|
|
|
2006-04-28 19:46:57 +00:00
|
|
|
return profile;
|
2005-11-19 20:07:43 +00:00
|
|
|
}
|
|
|
|
|
2006-04-29 06:05:03 +00:00
|
|
|
SWITCH_DECLARE(switch_caller_profile_t *) switch_channel_get_originatee_caller_profile(switch_channel_t *channel)
|
2005-12-26 19:09:59 +00:00
|
|
|
{
|
2006-12-01 15:26:37 +00:00
|
|
|
switch_caller_profile_t *profile = NULL;
|
2007-12-11 19:23:57 +00:00
|
|
|
switch_assert(channel != NULL);
|
2006-04-28 19:46:57 +00:00
|
|
|
|
2007-09-29 01:06:08 +00:00
|
|
|
switch_mutex_lock(channel->profile_mutex);
|
2007-03-29 22:31:56 +00:00
|
|
|
if (channel->caller_profile) {
|
|
|
|
profile = channel->caller_profile->originatee_caller_profile;
|
|
|
|
}
|
2007-09-29 01:06:08 +00:00
|
|
|
switch_mutex_unlock(channel->profile_mutex);
|
2008-01-28 07:26:10 +00:00
|
|
|
|
2006-04-28 19:46:57 +00:00
|
|
|
return profile;
|
2005-12-26 19:09:59 +00:00
|
|
|
}
|
|
|
|
|
2006-12-01 15:26:37 +00:00
|
|
|
SWITCH_DECLARE(char *) switch_channel_get_uuid(switch_channel_t *channel)
|
|
|
|
{
|
2007-12-11 19:23:57 +00:00
|
|
|
switch_assert(channel != NULL);
|
|
|
|
switch_assert(channel->session != NULL);
|
2006-12-01 15:26:37 +00:00
|
|
|
return switch_core_session_get_uuid(channel->session);
|
|
|
|
}
|
|
|
|
|
2007-03-30 00:13:31 +00:00
|
|
|
SWITCH_DECLARE(int) switch_channel_add_state_handler(switch_channel_t *channel, const switch_state_handler_table_t *state_handler)
|
2005-11-19 20:07:43 +00:00
|
|
|
{
|
2006-08-15 21:38:24 +00:00
|
|
|
int x, index;
|
2006-02-07 22:58:56 +00:00
|
|
|
|
2007-12-11 19:23:57 +00:00
|
|
|
switch_assert(channel != NULL);
|
2009-02-20 18:31:08 +00:00
|
|
|
switch_mutex_lock(channel->state_mutex);
|
2006-08-15 21:38:24 +00:00
|
|
|
for (x = 0; x < SWITCH_MAX_STATE_HANDLERS; x++) {
|
|
|
|
if (channel->state_handlers[x] == state_handler) {
|
2006-10-04 23:11:11 +00:00
|
|
|
index = x;
|
|
|
|
goto end;
|
2006-08-15 21:38:24 +00:00
|
|
|
}
|
|
|
|
}
|
2006-02-07 22:58:56 +00:00
|
|
|
index = channel->state_handler_index++;
|
2006-02-07 20:47:15 +00:00
|
|
|
|
|
|
|
if (channel->state_handler_index >= SWITCH_MAX_STATE_HANDLERS) {
|
2006-10-04 23:11:11 +00:00
|
|
|
index = -1;
|
|
|
|
goto end;
|
2006-02-07 20:47:15 +00:00
|
|
|
}
|
2007-03-29 22:31:56 +00:00
|
|
|
|
2006-02-07 20:47:15 +00:00
|
|
|
channel->state_handlers[index] = state_handler;
|
2006-10-04 23:11:11 +00:00
|
|
|
|
2008-05-27 04:30:03 +00:00
|
|
|
end:
|
2009-02-20 18:31:08 +00:00
|
|
|
switch_mutex_unlock(channel->state_mutex);
|
2006-02-07 20:47:15 +00:00
|
|
|
return index;
|
2005-11-19 20:07:43 +00:00
|
|
|
}
|
|
|
|
|
2007-03-30 00:13:31 +00:00
|
|
|
SWITCH_DECLARE(const switch_state_handler_table_t *) switch_channel_get_state_handler(switch_channel_t *channel, int index)
|
2005-11-19 20:07:43 +00:00
|
|
|
{
|
2006-10-04 23:11:11 +00:00
|
|
|
const switch_state_handler_table_t *h = NULL;
|
|
|
|
|
2007-12-11 19:23:57 +00:00
|
|
|
switch_assert(channel != NULL);
|
2006-02-07 20:47:15 +00:00
|
|
|
|
2007-12-17 20:44:48 +00:00
|
|
|
if (index >= SWITCH_MAX_STATE_HANDLERS || index > channel->state_handler_index) {
|
2006-02-07 20:47:15 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2009-02-20 18:31:08 +00:00
|
|
|
switch_mutex_lock(channel->state_mutex);
|
2006-10-04 23:11:11 +00:00
|
|
|
h = channel->state_handlers[index];
|
2009-02-20 18:31:08 +00:00
|
|
|
switch_mutex_unlock(channel->state_mutex);
|
2006-10-04 23:11:11 +00:00
|
|
|
|
|
|
|
return h;
|
2005-11-19 20:07:43 +00:00
|
|
|
}
|
|
|
|
|
2007-03-30 00:13:31 +00:00
|
|
|
SWITCH_DECLARE(void) switch_channel_clear_state_handler(switch_channel_t *channel, const switch_state_handler_table_t *state_handler)
|
2006-04-25 18:02:12 +00:00
|
|
|
{
|
2006-10-04 23:11:11 +00:00
|
|
|
int index, i = channel->state_handler_index;
|
2007-03-29 22:31:56 +00:00
|
|
|
const switch_state_handler_table_t *new_handlers[SWITCH_MAX_STATE_HANDLERS] = { 0 };
|
2006-04-25 18:02:12 +00:00
|
|
|
|
2008-05-15 21:08:42 +00:00
|
|
|
switch_assert(channel != NULL);
|
2006-10-04 23:11:11 +00:00
|
|
|
|
2009-02-20 18:31:08 +00:00
|
|
|
switch_mutex_lock(channel->state_mutex);
|
2006-10-04 23:11:11 +00:00
|
|
|
channel->state_handler_index = 0;
|
2006-04-25 18:02:12 +00:00
|
|
|
|
2006-08-17 00:53:09 +00:00
|
|
|
if (state_handler) {
|
2006-10-04 23:11:11 +00:00
|
|
|
for (index = 0; index < i; index++) {
|
2006-08-17 00:53:09 +00:00
|
|
|
if (channel->state_handlers[index] != state_handler) {
|
2006-10-04 23:11:11 +00:00
|
|
|
new_handlers[channel->state_handler_index++] = channel->state_handlers[index];
|
2006-08-17 00:53:09 +00:00
|
|
|
}
|
2006-04-25 18:02:12 +00:00
|
|
|
}
|
2009-11-04 21:07:18 +00:00
|
|
|
} else {
|
|
|
|
for (index = 0; index < i; index++) {
|
2009-12-07 19:07:53 +00:00
|
|
|
if (channel->state_handlers[index] && switch_test_flag(channel->state_handlers[index], SSH_FLAG_STICKY)) {
|
2009-11-04 21:07:18 +00:00
|
|
|
new_handlers[channel->state_handler_index++] = channel->state_handlers[index];
|
|
|
|
}
|
|
|
|
}
|
2006-04-25 18:02:12 +00:00
|
|
|
}
|
2009-11-04 21:07:18 +00:00
|
|
|
|
2006-04-26 18:37:03 +00:00
|
|
|
for (index = 0; index < SWITCH_MAX_STATE_HANDLERS; index++) {
|
|
|
|
channel->state_handlers[index] = NULL;
|
|
|
|
}
|
2006-09-19 15:33:02 +00:00
|
|
|
|
2009-11-04 22:55:33 +00:00
|
|
|
if (channel->state_handler_index > 0) {
|
2006-10-04 23:11:11 +00:00
|
|
|
for (index = 0; index < channel->state_handler_index; index++) {
|
|
|
|
channel->state_handlers[index] = new_handlers[index];
|
2006-08-17 00:53:09 +00:00
|
|
|
}
|
2006-04-25 18:02:12 +00:00
|
|
|
}
|
|
|
|
|
2009-02-20 18:31:08 +00:00
|
|
|
switch_mutex_unlock(channel->state_mutex);
|
2006-04-25 18:02:12 +00:00
|
|
|
}
|
|
|
|
|
2009-10-09 22:28:31 +00:00
|
|
|
SWITCH_DECLARE(void) switch_channel_restart(switch_channel_t *channel)
|
|
|
|
{
|
|
|
|
switch_channel_set_state(channel, CS_RESET);
|
|
|
|
switch_channel_wait_for_state_timeout(channel, CS_RESET, 5000);
|
|
|
|
switch_channel_set_state(channel, CS_EXECUTE);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* XXX This is a somewhat simple operation. Were essentially taking the extension that one channel
|
|
|
|
was executing and generating a new extension for another channel that starts out where the
|
|
|
|
original one left off with an optional forward offset. Since all we are really doing is
|
|
|
|
copying a few basic pool-allocated structures from one channel to another there really is
|
|
|
|
not much to worry about here in terms of threading since we use read-write locks.
|
|
|
|
While the features are nice, they only really are needed in one specific crazy attended
|
|
|
|
transfer scenario where one channel was in the middle of calling a particular extension
|
|
|
|
when it was rudely cut off by a transfer key press. XXX */
|
|
|
|
|
2009-10-09 20:48:24 +00:00
|
|
|
SWITCH_DECLARE(switch_status_t) switch_channel_caller_extension_masquerade(switch_channel_t *orig_channel, switch_channel_t *new_channel, uint32_t offset)
|
|
|
|
{
|
|
|
|
switch_caller_profile_t *caller_profile;
|
|
|
|
switch_caller_extension_t *extension = NULL, *orig_extension = NULL;
|
|
|
|
switch_caller_application_t *ap;
|
|
|
|
switch_status_t status = SWITCH_STATUS_FALSE;
|
|
|
|
switch_event_header_t *hi = NULL;
|
|
|
|
const char *no_copy = switch_channel_get_variable(orig_channel, "attended_transfer_no_copy");
|
|
|
|
char *dup;
|
|
|
|
int i, argc = 0;
|
|
|
|
char *argv[128];
|
|
|
|
|
|
|
|
if (no_copy) {
|
|
|
|
dup = switch_core_session_strdup(new_channel->session, no_copy);
|
|
|
|
argc = switch_separate_string(dup, ',', argv, (sizeof(argv) / sizeof(argv[0])));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
switch_mutex_lock(orig_channel->profile_mutex);
|
|
|
|
switch_mutex_lock(new_channel->profile_mutex);
|
2010-02-06 03:38:24 +00:00
|
|
|
|
|
|
|
|
2009-10-09 20:48:24 +00:00
|
|
|
caller_profile = switch_caller_profile_clone(new_channel->session, new_channel->caller_profile);
|
|
|
|
switch_assert(caller_profile);
|
|
|
|
extension = switch_caller_extension_new(new_channel->session, caller_profile->destination_number, caller_profile->destination_number);
|
|
|
|
orig_extension = switch_channel_get_caller_extension(orig_channel);
|
2010-02-06 03:38:24 +00:00
|
|
|
|
|
|
|
|
2009-10-09 20:48:24 +00:00
|
|
|
if (extension && orig_extension) {
|
2010-02-06 03:38:24 +00:00
|
|
|
for (ap = orig_extension->current_application; ap && offset > 0; offset--) {
|
2009-10-09 20:48:24 +00:00
|
|
|
ap = ap->next;
|
|
|
|
}
|
2010-02-06 03:38:24 +00:00
|
|
|
|
2009-10-09 20:48:24 +00:00
|
|
|
for (; ap; ap = ap->next) {
|
|
|
|
switch_caller_extension_add_application(new_channel->session, extension, ap->application_name, ap->application_data);
|
|
|
|
}
|
2010-02-06 03:38:24 +00:00
|
|
|
|
2009-10-09 20:48:24 +00:00
|
|
|
caller_profile->destination_number = switch_core_strdup(caller_profile->pool, orig_channel->caller_profile->destination_number);
|
|
|
|
switch_channel_set_caller_profile(new_channel, caller_profile);
|
|
|
|
switch_channel_set_caller_extension(new_channel, extension);
|
|
|
|
|
|
|
|
for (hi = orig_channel->variables->headers; hi; hi = hi->next) {
|
|
|
|
int ok = 1;
|
|
|
|
for (i = 0; i < argc; i++) {
|
|
|
|
if (!strcasecmp(argv[i], hi->name)) {
|
|
|
|
ok = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2010-02-06 03:38:24 +00:00
|
|
|
|
|
|
|
if (!ok)
|
|
|
|
continue;
|
2009-10-09 20:48:24 +00:00
|
|
|
|
|
|
|
switch_channel_set_variable(new_channel, hi->name, hi->value);
|
|
|
|
}
|
|
|
|
|
|
|
|
status = SWITCH_STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
switch_mutex_unlock(new_channel->profile_mutex);
|
|
|
|
switch_mutex_unlock(orig_channel->profile_mutex);
|
|
|
|
|
|
|
|
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
2010-12-17 20:35:53 +00:00
|
|
|
SWITCH_DECLARE(void) switch_channel_sort_cid(switch_channel_t *channel, switch_bool_t in)
|
|
|
|
{
|
|
|
|
|
|
|
|
if (in) {
|
|
|
|
if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND && !switch_channel_test_flag(channel, CF_DIALPLAN)) {
|
|
|
|
switch_channel_set_flag(channel, CF_DIALPLAN);
|
|
|
|
|
|
|
|
switch_mutex_lock(channel->profile_mutex);
|
|
|
|
if (channel->caller_profile->callee_id_name) {
|
|
|
|
switch_channel_set_variable(channel, "pre_transfer_caller_id_name", channel->caller_profile->caller_id_name);
|
|
|
|
channel->caller_profile->caller_id_name = switch_core_strdup(channel->caller_profile->pool, channel->caller_profile->callee_id_name);
|
|
|
|
}
|
|
|
|
channel->caller_profile->callee_id_name = SWITCH_BLANK_STRING;
|
|
|
|
|
|
|
|
if (channel->caller_profile->callee_id_number) {
|
|
|
|
switch_channel_set_variable(channel, "pre_transfer_caller_id_number", channel->caller_profile->caller_id_number);
|
|
|
|
channel->caller_profile->caller_id_number = switch_core_strdup(channel->caller_profile->pool, channel->caller_profile->callee_id_number);
|
|
|
|
}
|
|
|
|
channel->caller_profile->callee_id_number = SWITCH_BLANK_STRING;
|
|
|
|
switch_mutex_unlock(channel->profile_mutex);
|
|
|
|
}
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND && switch_channel_test_flag(channel, CF_DIALPLAN)) {
|
|
|
|
switch_channel_clear_flag(channel, CF_DIALPLAN);
|
|
|
|
switch_mutex_lock(channel->profile_mutex);
|
|
|
|
channel->caller_profile->callee_id_name = SWITCH_BLANK_STRING;
|
|
|
|
channel->caller_profile->callee_id_number = SWITCH_BLANK_STRING;
|
|
|
|
switch_mutex_unlock(channel->profile_mutex);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-03-30 00:13:31 +00:00
|
|
|
SWITCH_DECLARE(void) switch_channel_set_caller_extension(switch_channel_t *channel, switch_caller_extension_t *caller_extension)
|
2005-11-19 20:07:43 +00:00
|
|
|
{
|
2007-12-11 19:23:57 +00:00
|
|
|
switch_assert(channel != NULL);
|
2006-06-03 17:06:06 +00:00
|
|
|
|
2010-12-17 20:35:53 +00:00
|
|
|
switch_channel_sort_cid(channel, SWITCH_TRUE);
|
|
|
|
|
2006-06-03 17:06:06 +00:00
|
|
|
switch_mutex_lock(channel->profile_mutex);
|
2007-02-07 17:19:06 +00:00
|
|
|
caller_extension->next = channel->caller_profile->caller_extension;
|
|
|
|
channel->caller_profile->caller_extension = caller_extension;
|
2006-06-03 17:06:06 +00:00
|
|
|
switch_mutex_unlock(channel->profile_mutex);
|
2005-11-19 20:07:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-04-29 06:05:03 +00:00
|
|
|
SWITCH_DECLARE(switch_caller_extension_t *) switch_channel_get_caller_extension(switch_channel_t *channel)
|
2005-11-19 20:07:43 +00:00
|
|
|
{
|
2007-03-29 22:31:56 +00:00
|
|
|
switch_caller_extension_t *extension = NULL;
|
2005-11-19 20:07:43 +00:00
|
|
|
|
2007-12-11 19:23:57 +00:00
|
|
|
switch_assert(channel != NULL);
|
2007-02-07 17:19:06 +00:00
|
|
|
switch_mutex_lock(channel->profile_mutex);
|
2007-03-28 12:30:20 +00:00
|
|
|
if (channel->caller_profile) {
|
|
|
|
extension = channel->caller_profile->caller_extension;
|
|
|
|
}
|
2007-03-29 22:31:56 +00:00
|
|
|
switch_mutex_unlock(channel->profile_mutex);
|
|
|
|
return extension;
|
2005-11-19 20:07:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-03-25 20:07:40 +00:00
|
|
|
SWITCH_DECLARE(void) switch_channel_set_hangup_time(switch_channel_t *channel)
|
|
|
|
{
|
|
|
|
if (channel->caller_profile && channel->caller_profile->times && !channel->caller_profile->times->hungup) {
|
|
|
|
switch_mutex_lock(channel->profile_mutex);
|
|
|
|
channel->caller_profile->times->hungup = switch_micro_time_now();
|
|
|
|
switch_mutex_unlock(channel->profile_mutex);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-03-29 22:31:56 +00:00
|
|
|
SWITCH_DECLARE(switch_channel_state_t) switch_channel_perform_hangup(switch_channel_t *channel,
|
2007-03-30 00:13:31 +00:00
|
|
|
const char *file, const char *func, int line, switch_call_cause_t hangup_cause)
|
2005-11-19 20:07:43 +00:00
|
|
|
{
|
2010-05-03 17:29:56 +00:00
|
|
|
int ok = 0;
|
|
|
|
|
2007-12-11 19:23:57 +00:00
|
|
|
switch_assert(channel != NULL);
|
2009-03-04 04:19:33 +00:00
|
|
|
|
2010-05-03 17:29:56 +00:00
|
|
|
/* one per customer */
|
|
|
|
switch_mutex_lock(channel->state_mutex);
|
|
|
|
if (!(channel->opaque_flags & OCF_HANGUP)) {
|
|
|
|
channel->opaque_flags |= OCF_HANGUP;
|
|
|
|
ok = 1;
|
|
|
|
}
|
|
|
|
switch_mutex_unlock(channel->state_mutex);
|
|
|
|
|
|
|
|
if (!ok) {
|
|
|
|
return channel->state;
|
|
|
|
}
|
|
|
|
|
2009-03-04 04:19:33 +00:00
|
|
|
switch_channel_clear_flag(channel, CF_BLOCK_STATE);
|
2010-02-06 03:38:24 +00:00
|
|
|
|
2006-04-03 14:53:34 +00:00
|
|
|
if (channel->state < CS_HANGUP) {
|
2009-10-07 04:30:19 +00:00
|
|
|
switch_channel_state_t last_state;
|
2009-05-29 17:18:03 +00:00
|
|
|
switch_event_t *event;
|
2008-01-28 07:26:10 +00:00
|
|
|
|
2009-03-20 01:50:50 +00:00
|
|
|
switch_mutex_lock(channel->state_mutex);
|
2009-10-07 04:30:19 +00:00
|
|
|
last_state = channel->state;
|
2005-11-19 20:07:43 +00:00
|
|
|
channel->state = CS_HANGUP;
|
2009-03-20 01:50:50 +00:00
|
|
|
switch_mutex_unlock(channel->state_mutex);
|
|
|
|
|
2010-05-03 17:29:56 +00:00
|
|
|
|
|
|
|
if (hangup_cause == SWITCH_CAUSE_LOSE_RACE) {
|
|
|
|
switch_channel_set_variable(channel, "presence_call_info", NULL);
|
|
|
|
}
|
|
|
|
|
2010-06-05 00:03:36 +00:00
|
|
|
switch_channel_set_callstate(channel, CCS_HANGUP);
|
2006-04-22 03:05:25 +00:00
|
|
|
channel->hangup_cause = hangup_cause;
|
2009-08-13 20:35:02 +00:00
|
|
|
switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, func, line, switch_channel_get_uuid(channel), SWITCH_LOG_NOTICE, "Hangup %s [%s] [%s]\n",
|
2008-05-27 04:30:03 +00:00
|
|
|
channel->name, state_names[last_state], switch_channel_cause2str(channel->hangup_cause));
|
2006-10-21 04:58:15 +00:00
|
|
|
|
2010-04-23 17:14:37 +00:00
|
|
|
|
2010-05-03 17:29:56 +00:00
|
|
|
if (!switch_core_session_running(channel->session) && !switch_core_session_started(channel->session)) {
|
2010-04-23 17:14:37 +00:00
|
|
|
switch_core_session_thread_launch(channel->session);
|
|
|
|
}
|
|
|
|
|
2009-05-29 17:18:03 +00:00
|
|
|
if (switch_event_create(&event, SWITCH_EVENT_CHANNEL_HANGUP) == SWITCH_STATUS_SUCCESS) {
|
|
|
|
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Hangup-Cause", switch_channel_cause2str(hangup_cause));
|
|
|
|
switch_channel_event_set_data(channel, event);
|
|
|
|
switch_event_fire(&event);
|
|
|
|
}
|
|
|
|
|
2006-03-22 17:05:16 +00:00
|
|
|
switch_core_session_kill_channel(channel->session, SWITCH_SIG_KILL);
|
2006-09-16 00:43:58 +00:00
|
|
|
switch_core_session_signal_state_change(channel->session);
|
2009-12-11 00:28:54 +00:00
|
|
|
switch_core_session_hangup_state(channel->session, SWITCH_FALSE);
|
2005-11-19 20:07:43 +00:00
|
|
|
}
|
2006-09-16 00:43:58 +00:00
|
|
|
|
2005-11-19 20:07:43 +00:00
|
|
|
return channel->state;
|
|
|
|
}
|
|
|
|
|
2010-06-15 20:48:12 +00:00
|
|
|
SWITCH_DECLARE(switch_status_t) switch_channel_perform_mark_ring_ready_value(switch_channel_t *channel,
|
|
|
|
switch_ring_ready_t rv,
|
|
|
|
const char *file, const char *func, int line)
|
2007-02-13 02:32:10 +00:00
|
|
|
{
|
2008-06-05 20:45:03 +00:00
|
|
|
const char *var;
|
|
|
|
char *app;
|
2008-10-02 15:38:45 +00:00
|
|
|
switch_event_t *event;
|
2008-06-05 20:45:03 +00:00
|
|
|
|
2010-02-06 03:38:24 +00:00
|
|
|
if (!switch_channel_test_flag(channel, CF_RING_READY) && !switch_channel_test_flag(channel, CF_EARLY_MEDIA &&
|
2010-01-22 21:04:50 +00:00
|
|
|
!switch_channel_test_flag(channel, CF_ANSWERED))) {
|
2009-08-13 20:35:02 +00:00
|
|
|
switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, func, line, switch_channel_get_uuid(channel), SWITCH_LOG_NOTICE, "Ring-Ready %s!\n", channel->name);
|
2010-06-15 20:48:12 +00:00
|
|
|
switch_channel_set_flag_value(channel, CF_RING_READY, rv);
|
2008-05-24 02:03:16 +00:00
|
|
|
if (channel->caller_profile && channel->caller_profile->times) {
|
|
|
|
switch_mutex_lock(channel->profile_mutex);
|
2009-01-25 21:23:07 +00:00
|
|
|
channel->caller_profile->times->progress = switch_micro_time_now();
|
2008-10-22 18:32:54 +00:00
|
|
|
if (channel->caller_profile->originator_caller_profile) {
|
|
|
|
switch_core_session_t *other_session;
|
|
|
|
if ((other_session = switch_core_session_locate(channel->caller_profile->originator_caller_profile->uuid))) {
|
|
|
|
switch_channel_t *other_channel;
|
|
|
|
other_channel = switch_core_session_get_channel(other_session);
|
|
|
|
if (other_channel->caller_profile) {
|
|
|
|
other_channel->caller_profile->times->progress = channel->caller_profile->times->progress;
|
|
|
|
}
|
|
|
|
switch_core_session_rwunlock(other_session);
|
|
|
|
}
|
|
|
|
channel->caller_profile->originator_caller_profile->times->progress = channel->caller_profile->times->progress;
|
|
|
|
}
|
2008-05-24 02:03:16 +00:00
|
|
|
switch_mutex_unlock(channel->profile_mutex);
|
|
|
|
}
|
2008-06-05 20:45:03 +00:00
|
|
|
|
2008-10-02 15:38:45 +00:00
|
|
|
if (switch_event_create(&event, SWITCH_EVENT_CHANNEL_PROGRESS) == SWITCH_STATUS_SUCCESS) {
|
|
|
|
switch_channel_event_set_data(channel, event);
|
|
|
|
switch_event_fire(&event);
|
|
|
|
}
|
|
|
|
|
2008-06-05 20:45:03 +00:00
|
|
|
var = switch_channel_get_variable(channel, SWITCH_CHANNEL_EXECUTE_ON_RING_VARIABLE);
|
|
|
|
if (var) {
|
|
|
|
char *arg = NULL;
|
|
|
|
app = switch_core_session_strdup(channel->session, var);
|
|
|
|
if ((arg = strchr(app, ' '))) {
|
|
|
|
*arg++ = '\0';
|
|
|
|
}
|
2010-11-30 17:01:54 +00:00
|
|
|
|
|
|
|
if (switch_core_session_in_thread(channel->session)) {
|
|
|
|
switch_core_session_execute_application(channel->session, app, arg);
|
|
|
|
} else {
|
|
|
|
switch_core_session_execute_application_async(channel->session, app, arg);
|
|
|
|
}
|
2008-06-05 20:45:03 +00:00
|
|
|
}
|
|
|
|
|
2007-02-13 02:32:10 +00:00
|
|
|
return SWITCH_STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
return SWITCH_STATUS_FALSE;
|
|
|
|
}
|
|
|
|
|
2007-03-30 00:13:31 +00:00
|
|
|
SWITCH_DECLARE(switch_status_t) switch_channel_perform_mark_pre_answered(switch_channel_t *channel, const char *file, const char *func, int line)
|
2007-02-09 01:34:01 +00:00
|
|
|
{
|
2007-03-29 22:31:56 +00:00
|
|
|
switch_event_t *event;
|
2009-10-29 05:47:17 +00:00
|
|
|
const char *var = NULL;
|
|
|
|
char *app;
|
2007-02-09 01:34:01 +00:00
|
|
|
|
2010-01-22 21:04:50 +00:00
|
|
|
if (!switch_channel_test_flag(channel, CF_EARLY_MEDIA) && !switch_channel_test_flag(channel, CF_ANSWERED)) {
|
2007-11-01 11:28:26 +00:00
|
|
|
const char *uuid;
|
2007-03-29 22:31:56 +00:00
|
|
|
switch_core_session_t *other_session;
|
|
|
|
|
2009-08-13 20:35:02 +00:00
|
|
|
switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, func, line, switch_channel_get_uuid(channel), SWITCH_LOG_NOTICE, "Pre-Answer %s!\n", channel->name);
|
2007-03-29 22:31:56 +00:00
|
|
|
switch_channel_set_flag(channel, CF_EARLY_MEDIA);
|
2010-06-05 00:03:36 +00:00
|
|
|
switch_channel_set_callstate(channel, CCS_EARLY);
|
2008-10-21 19:18:40 +00:00
|
|
|
switch_channel_set_variable(channel, SWITCH_ENDPOINT_DISPOSITION_VARIABLE, "EARLY MEDIA");
|
2008-10-02 15:38:45 +00:00
|
|
|
if (switch_event_create(&event, SWITCH_EVENT_CHANNEL_PROGRESS_MEDIA) == SWITCH_STATUS_SUCCESS) {
|
2007-03-29 22:31:56 +00:00
|
|
|
switch_channel_event_set_data(channel, event);
|
|
|
|
switch_event_fire(&event);
|
|
|
|
}
|
2010-02-06 03:38:24 +00:00
|
|
|
|
2008-05-24 01:43:12 +00:00
|
|
|
if (channel->caller_profile && channel->caller_profile->times) {
|
|
|
|
switch_mutex_lock(channel->profile_mutex);
|
2009-01-25 21:23:07 +00:00
|
|
|
channel->caller_profile->times->progress_media = switch_micro_time_now();
|
2008-10-22 18:32:54 +00:00
|
|
|
if (channel->caller_profile->originator_caller_profile) {
|
2008-10-23 01:39:04 +00:00
|
|
|
switch_core_session_t *osession;
|
|
|
|
if ((osession = switch_core_session_locate(channel->caller_profile->originator_caller_profile->uuid))) {
|
2008-10-22 18:32:54 +00:00
|
|
|
switch_channel_t *other_channel;
|
2008-10-23 01:39:04 +00:00
|
|
|
other_channel = switch_core_session_get_channel(osession);
|
2008-10-22 18:32:54 +00:00
|
|
|
if (other_channel->caller_profile) {
|
|
|
|
other_channel->caller_profile->times->progress_media = channel->caller_profile->times->progress_media;
|
|
|
|
}
|
2008-10-23 01:39:04 +00:00
|
|
|
switch_core_session_rwunlock(osession);
|
2008-10-22 18:32:54 +00:00
|
|
|
}
|
|
|
|
channel->caller_profile->originator_caller_profile->times->progress_media = channel->caller_profile->times->progress_media;
|
|
|
|
}
|
2008-05-24 01:43:12 +00:00
|
|
|
switch_mutex_unlock(channel->profile_mutex);
|
|
|
|
}
|
|
|
|
|
2010-02-06 03:38:24 +00:00
|
|
|
if (((var = switch_channel_get_variable(channel, SWITCH_CHANNEL_EXECUTE_ON_PRE_ANSWER_VARIABLE)) ||
|
2009-10-29 05:47:17 +00:00
|
|
|
(var = switch_channel_get_variable(channel, SWITCH_CHANNEL_EXECUTE_ON_MEDIA_VARIABLE))) && !zstr(var)) {
|
|
|
|
char *arg = NULL;
|
|
|
|
app = switch_core_session_strdup(channel->session, var);
|
|
|
|
if ((arg = strchr(app, ' '))) {
|
|
|
|
*arg++ = '\0';
|
|
|
|
}
|
2010-11-30 17:01:54 +00:00
|
|
|
|
|
|
|
if (switch_core_session_in_thread(channel->session)) {
|
|
|
|
switch_core_session_execute_application(channel->session, app, arg);
|
|
|
|
} else {
|
|
|
|
switch_core_session_execute_application_async(channel->session, app, arg);
|
|
|
|
}
|
2009-10-29 05:47:17 +00:00
|
|
|
}
|
|
|
|
|
2010-10-05 14:59:13 +00:00
|
|
|
if ((var = switch_channel_get_variable(channel, SWITCH_PASSTHRU_PTIME_MISMATCH_VARIABLE))) {
|
|
|
|
switch_channel_set_flag(channel, CF_PASSTHRU_PTIME_MISMATCH);
|
|
|
|
}
|
|
|
|
|
2007-03-29 22:31:56 +00:00
|
|
|
/* if we're the child of another channel and the other channel is in a blocking read they will never realize we have answered so send
|
2008-05-27 04:30:03 +00:00
|
|
|
a SWITCH_SIG_BREAK to interrupt any blocking reads on that channel
|
|
|
|
*/
|
2007-03-29 22:31:56 +00:00
|
|
|
if ((uuid = switch_channel_get_variable(channel, SWITCH_ORIGINATOR_VARIABLE))
|
|
|
|
&& (other_session = switch_core_session_locate(uuid))) {
|
2008-05-27 04:30:03 +00:00
|
|
|
switch_core_session_kill_channel(other_session, SWITCH_SIG_BREAK);
|
|
|
|
switch_core_session_rwunlock(other_session);
|
2007-03-29 22:31:56 +00:00
|
|
|
}
|
2010-08-23 22:02:06 +00:00
|
|
|
|
2007-03-29 22:31:56 +00:00
|
|
|
return SWITCH_STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
return SWITCH_STATUS_FALSE;
|
2007-02-09 01:34:01 +00:00
|
|
|
}
|
|
|
|
|
2007-03-30 00:13:31 +00:00
|
|
|
SWITCH_DECLARE(switch_status_t) switch_channel_perform_pre_answer(switch_channel_t *channel, const char *file, const char *func, int line)
|
2006-03-03 16:57:21 +00:00
|
|
|
{
|
2009-10-12 22:23:55 +00:00
|
|
|
switch_core_session_message_t msg = { 0 };
|
2009-01-20 18:36:02 +00:00
|
|
|
switch_status_t status = SWITCH_STATUS_SUCCESS;
|
2007-03-29 22:31:56 +00:00
|
|
|
|
2007-12-11 19:23:57 +00:00
|
|
|
switch_assert(channel != NULL);
|
2006-03-21 00:20:24 +00:00
|
|
|
|
2007-03-12 20:17:34 +00:00
|
|
|
if (channel->hangup_cause || channel->state >= CS_HANGUP) {
|
2006-03-21 00:20:24 +00:00
|
|
|
return SWITCH_STATUS_FALSE;
|
|
|
|
}
|
|
|
|
|
2006-07-10 19:51:19 +00:00
|
|
|
if (switch_channel_test_flag(channel, CF_ANSWERED)) {
|
|
|
|
return SWITCH_STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2006-10-08 15:51:10 +00:00
|
|
|
if (switch_channel_test_flag(channel, CF_EARLY_MEDIA)) {
|
|
|
|
return SWITCH_STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2010-12-16 02:59:23 +00:00
|
|
|
if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_INBOUND) {
|
2009-01-20 18:36:02 +00:00
|
|
|
msg.message_id = SWITCH_MESSAGE_INDICATE_PROGRESS;
|
|
|
|
msg.from = channel->name;
|
|
|
|
status = switch_core_session_perform_receive_message(channel->session, &msg, file, func, line);
|
2009-01-19 16:25:49 +00:00
|
|
|
}
|
|
|
|
|
2006-03-03 17:49:22 +00:00
|
|
|
if (status == SWITCH_STATUS_SUCCESS) {
|
2008-02-20 03:57:01 +00:00
|
|
|
switch_channel_perform_mark_pre_answered(channel, file, func, line);
|
|
|
|
} else {
|
|
|
|
switch_channel_hangup(channel, SWITCH_CAUSE_INCOMPATIBLE_DESTINATION);
|
2006-03-03 17:49:22 +00:00
|
|
|
}
|
2006-03-03 16:57:21 +00:00
|
|
|
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
2010-06-15 20:48:12 +00:00
|
|
|
SWITCH_DECLARE(switch_status_t) switch_channel_perform_ring_ready_value(switch_channel_t *channel, switch_ring_ready_t rv,
|
|
|
|
const char *file, const char *func, int line)
|
2006-10-25 04:28:49 +00:00
|
|
|
{
|
2009-10-12 22:23:55 +00:00
|
|
|
switch_core_session_message_t msg = { 0 };
|
2009-01-20 18:36:02 +00:00
|
|
|
switch_status_t status = SWITCH_STATUS_SUCCESS;
|
2007-03-29 22:31:56 +00:00
|
|
|
|
2007-12-11 19:23:57 +00:00
|
|
|
switch_assert(channel != NULL);
|
2006-10-25 04:28:49 +00:00
|
|
|
|
2007-03-12 20:17:34 +00:00
|
|
|
if (channel->hangup_cause || channel->state >= CS_HANGUP) {
|
2006-10-25 04:28:49 +00:00
|
|
|
return SWITCH_STATUS_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (switch_channel_test_flag(channel, CF_ANSWERED)) {
|
|
|
|
return SWITCH_STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (switch_channel_test_flag(channel, CF_EARLY_MEDIA)) {
|
|
|
|
return SWITCH_STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2010-12-16 02:59:23 +00:00
|
|
|
if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_INBOUND) {
|
2009-01-20 18:36:02 +00:00
|
|
|
msg.message_id = SWITCH_MESSAGE_INDICATE_RINGING;
|
|
|
|
msg.from = channel->name;
|
2010-06-15 20:48:12 +00:00
|
|
|
msg.numeric_arg = rv;
|
2009-01-20 18:36:02 +00:00
|
|
|
status = switch_core_session_perform_receive_message(channel->session, &msg, file, func, line);
|
2009-01-19 16:25:49 +00:00
|
|
|
}
|
2010-02-06 03:38:24 +00:00
|
|
|
|
2006-10-25 04:28:49 +00:00
|
|
|
if (status == SWITCH_STATUS_SUCCESS) {
|
2009-08-13 20:35:02 +00:00
|
|
|
switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, func, line, switch_channel_get_uuid(channel), SWITCH_LOG_NOTICE, "Ring Ready %s!\n", channel->name);
|
2010-06-15 20:48:12 +00:00
|
|
|
switch_channel_perform_mark_ring_ready_value(channel, rv, file, func, line);
|
2008-02-20 03:57:01 +00:00
|
|
|
} else {
|
|
|
|
switch_channel_hangup(channel, SWITCH_CAUSE_INCOMPATIBLE_DESTINATION);
|
2006-10-25 04:28:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
2007-03-30 00:13:31 +00:00
|
|
|
SWITCH_DECLARE(switch_status_t) switch_channel_perform_mark_answered(switch_channel_t *channel, const char *file, const char *func, int line)
|
2006-12-05 23:08:14 +00:00
|
|
|
{
|
2007-03-29 22:31:56 +00:00
|
|
|
switch_event_t *event;
|
2007-11-01 11:28:26 +00:00
|
|
|
const char *uuid;
|
2007-03-29 22:31:56 +00:00
|
|
|
switch_core_session_t *other_session;
|
2008-06-05 19:36:33 +00:00
|
|
|
const char *var;
|
|
|
|
char *app;
|
2006-12-05 23:08:14 +00:00
|
|
|
|
2007-12-11 19:23:57 +00:00
|
|
|
switch_assert(channel != NULL);
|
2006-12-05 23:08:14 +00:00
|
|
|
|
2007-03-12 20:17:34 +00:00
|
|
|
if (channel->hangup_cause || channel->state >= CS_HANGUP) {
|
2006-12-05 23:08:14 +00:00
|
|
|
return SWITCH_STATUS_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (switch_channel_test_flag(channel, CF_ANSWERED)) {
|
|
|
|
return SWITCH_STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2007-03-29 22:31:56 +00:00
|
|
|
if (channel->caller_profile && channel->caller_profile->times) {
|
|
|
|
switch_mutex_lock(channel->profile_mutex);
|
2009-01-25 21:23:07 +00:00
|
|
|
channel->caller_profile->times->answered = switch_micro_time_now();
|
2007-03-29 22:31:56 +00:00
|
|
|
switch_mutex_unlock(channel->profile_mutex);
|
|
|
|
}
|
|
|
|
|
|
|
|
switch_channel_set_flag(channel, CF_ANSWERED);
|
2010-06-05 00:03:36 +00:00
|
|
|
switch_channel_set_callstate(channel, CCS_ACTIVE);
|
2007-03-29 22:31:56 +00:00
|
|
|
|
|
|
|
if (switch_event_create(&event, SWITCH_EVENT_CHANNEL_ANSWER) == SWITCH_STATUS_SUCCESS) {
|
|
|
|
switch_channel_event_set_data(channel, event);
|
|
|
|
switch_event_fire(&event);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* if we're the child of another channel and the other channel is in a blocking read they will never realize we have answered so send
|
2008-05-27 04:30:03 +00:00
|
|
|
a SWITCH_SIG_BREAK to interrupt any blocking reads on that channel
|
|
|
|
*/
|
2007-03-29 22:31:56 +00:00
|
|
|
if ((uuid = switch_channel_get_variable(channel, SWITCH_ORIGINATOR_VARIABLE))
|
|
|
|
&& (other_session = switch_core_session_locate(uuid))) {
|
2008-05-27 04:30:03 +00:00
|
|
|
switch_core_session_kill_channel(other_session, SWITCH_SIG_BREAK);
|
|
|
|
switch_core_session_rwunlock(other_session);
|
2007-03-29 22:31:56 +00:00
|
|
|
}
|
|
|
|
|
2010-10-05 14:59:13 +00:00
|
|
|
if ((var = switch_channel_get_variable(channel, SWITCH_PASSTHRU_PTIME_MISMATCH_VARIABLE))) {
|
|
|
|
switch_channel_set_flag(channel, CF_PASSTHRU_PTIME_MISMATCH);
|
|
|
|
}
|
|
|
|
|
2008-10-07 21:03:37 +00:00
|
|
|
if ((var = switch_channel_get_variable(channel, SWITCH_ENABLE_HEARTBEAT_EVENTS_VARIABLE))) {
|
|
|
|
uint32_t seconds = 60;
|
|
|
|
int tmp;
|
|
|
|
|
|
|
|
if (switch_is_number(var)) {
|
|
|
|
tmp = atoi(var);
|
2008-10-07 21:42:31 +00:00
|
|
|
if (tmp > 0) {
|
2008-10-07 21:03:37 +00:00
|
|
|
seconds = tmp;
|
|
|
|
}
|
|
|
|
} else if (!switch_true(var)) {
|
|
|
|
seconds = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (seconds) {
|
|
|
|
switch_core_session_enable_heartbeat(channel->session, seconds);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-10-21 19:18:40 +00:00
|
|
|
switch_channel_set_variable(channel, SWITCH_ENDPOINT_DISPOSITION_VARIABLE, "ANSWER");
|
2010-02-06 03:38:24 +00:00
|
|
|
switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, func, line, switch_channel_get_uuid(channel), SWITCH_LOG_NOTICE, "Channel [%s] has been answered\n",
|
|
|
|
channel->name);
|
2009-10-29 05:47:17 +00:00
|
|
|
|
2010-02-06 03:38:24 +00:00
|
|
|
if (((var = switch_channel_get_variable(channel, SWITCH_CHANNEL_EXECUTE_ON_ANSWER_VARIABLE)) ||
|
|
|
|
(!switch_channel_test_flag(channel, CF_EARLY_MEDIA) && (var = switch_channel_get_variable(channel, SWITCH_CHANNEL_EXECUTE_ON_MEDIA_VARIABLE))))
|
2009-10-29 05:47:17 +00:00
|
|
|
&& !zstr(var)) {
|
2008-06-05 19:36:33 +00:00
|
|
|
char *arg = NULL;
|
2010-03-03 02:34:55 +00:00
|
|
|
char *colon = NULL;
|
2007-03-29 22:31:56 +00:00
|
|
|
|
2008-06-05 19:36:33 +00:00
|
|
|
app = switch_core_session_strdup(channel->session, var);
|
2010-02-06 03:38:24 +00:00
|
|
|
|
2010-03-03 02:34:55 +00:00
|
|
|
arg = strchr(app, ' ');
|
|
|
|
colon = strchr(app, ':');
|
|
|
|
if (colon && (!arg || arg > colon) && *(colon + 1) == ':') {
|
2009-08-13 20:35:02 +00:00
|
|
|
switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_DEBUG, "%s execute on answer: %s (BROADCAST)\n", channel->name, app);
|
2009-05-20 13:02:41 +00:00
|
|
|
switch_ivr_broadcast(switch_core_session_get_uuid(channel->session), app, SMF_NONE);
|
|
|
|
} else {
|
2010-03-03 02:34:55 +00:00
|
|
|
if (arg) {
|
2009-05-20 13:02:41 +00:00
|
|
|
*arg++ = '\0';
|
|
|
|
}
|
2010-02-06 03:38:24 +00:00
|
|
|
switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_DEBUG, "%s execute on answer: %s(%s)\n", channel->name, app,
|
|
|
|
switch_str_nil(arg));
|
2010-11-30 17:01:54 +00:00
|
|
|
|
|
|
|
if (switch_core_session_in_thread(channel->session)) {
|
|
|
|
switch_core_session_execute_application(channel->session, app, arg);
|
|
|
|
} else {
|
|
|
|
switch_core_session_execute_application_async(channel->session, app, arg);
|
|
|
|
}
|
2008-06-05 19:36:33 +00:00
|
|
|
}
|
|
|
|
}
|
2008-11-27 02:41:08 +00:00
|
|
|
|
2009-10-23 16:03:42 +00:00
|
|
|
if ((var = switch_channel_get_variable(channel, SWITCH_CHANNEL_API_ON_ANSWER_VARIABLE)) && !zstr(var)) {
|
2009-10-23 15:01:34 +00:00
|
|
|
switch_stream_handle_t stream = { 0 };
|
|
|
|
char *arg = NULL;
|
|
|
|
|
|
|
|
app = switch_core_session_strdup(channel->session, var);
|
|
|
|
if ((arg = strchr(app, ' '))) {
|
|
|
|
*arg++ = '\0';
|
|
|
|
}
|
|
|
|
|
|
|
|
SWITCH_STANDARD_STREAM(stream);
|
|
|
|
switch_api_execute(app, arg, NULL, &stream);
|
|
|
|
|
2010-02-06 03:38:24 +00:00
|
|
|
switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_DEBUG, "%s api on answer: %s(%s)\n%s\n",
|
|
|
|
channel->name, app, switch_str_nil(arg), (char *) stream.data);
|
2009-10-23 15:01:34 +00:00
|
|
|
free(stream.data);
|
|
|
|
}
|
|
|
|
|
2009-12-24 05:44:23 +00:00
|
|
|
switch_channel_presence(channel, "unknown", "answered", NULL);
|
|
|
|
|
2008-11-27 04:02:57 +00:00
|
|
|
switch_channel_audio_sync(channel);
|
2008-11-27 02:41:08 +00:00
|
|
|
|
2007-03-29 22:31:56 +00:00
|
|
|
return SWITCH_STATUS_SUCCESS;
|
2006-12-05 23:08:14 +00:00
|
|
|
}
|
|
|
|
|
2007-03-30 00:13:31 +00:00
|
|
|
SWITCH_DECLARE(switch_status_t) switch_channel_perform_answer(switch_channel_t *channel, const char *file, const char *func, int line)
|
2005-11-19 20:07:43 +00:00
|
|
|
{
|
2009-10-12 22:23:55 +00:00
|
|
|
switch_core_session_message_t msg = { 0 };
|
2009-01-20 18:36:02 +00:00
|
|
|
switch_status_t status = SWITCH_STATUS_SUCCESS;
|
2007-04-16 16:53:30 +00:00
|
|
|
|
2007-12-11 19:23:57 +00:00
|
|
|
switch_assert(channel != NULL);
|
2005-11-19 20:07:43 +00:00
|
|
|
|
2010-12-16 02:59:23 +00:00
|
|
|
if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) {
|
2010-03-11 20:41:46 +00:00
|
|
|
return SWITCH_STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2007-03-12 20:17:34 +00:00
|
|
|
if (channel->hangup_cause || channel->state >= CS_HANGUP) {
|
2006-03-21 00:20:24 +00:00
|
|
|
return SWITCH_STATUS_FALSE;
|
2009-01-19 16:00:11 +00:00
|
|
|
}
|
|
|
|
|
2009-01-19 16:25:49 +00:00
|
|
|
if (switch_channel_test_flag(channel, CF_ANSWERED)) {
|
|
|
|
return SWITCH_STATUS_SUCCESS;
|
2006-03-21 00:20:24 +00:00
|
|
|
}
|
2010-03-11 20:41:46 +00:00
|
|
|
|
|
|
|
msg.message_id = SWITCH_MESSAGE_INDICATE_ANSWER;
|
|
|
|
msg.from = channel->name;
|
|
|
|
status = switch_core_session_perform_receive_message(channel->session, &msg, file, func, line);
|
2010-02-06 03:38:24 +00:00
|
|
|
|
2006-06-06 23:49:02 +00:00
|
|
|
|
2007-04-16 16:53:30 +00:00
|
|
|
if (status == SWITCH_STATUS_SUCCESS) {
|
2008-02-20 03:57:01 +00:00
|
|
|
switch_channel_perform_mark_answered(channel, file, func, line);
|
|
|
|
} else {
|
|
|
|
switch_channel_hangup(channel, SWITCH_CAUSE_INCOMPATIBLE_DESTINATION);
|
2005-11-19 20:07:43 +00:00
|
|
|
}
|
|
|
|
|
2008-02-20 03:57:01 +00:00
|
|
|
return status;
|
2005-11-19 20:07:43 +00:00
|
|
|
}
|
2006-10-07 19:54:04 +00:00
|
|
|
|
2006-12-07 00:36:00 +00:00
|
|
|
#define resize(l) {\
|
2008-01-28 07:26:10 +00:00
|
|
|
char *dp;\
|
|
|
|
olen += (len + l + block);\
|
|
|
|
cpos = c - data;\
|
|
|
|
if ((dp = realloc(data, olen))) {\
|
|
|
|
data = dp;\
|
|
|
|
c = data + cpos;\
|
|
|
|
memset(c, 0, olen - cpos);\
|
|
|
|
}} \
|
2006-12-07 00:36:00 +00:00
|
|
|
|
2007-12-05 20:23:50 +00:00
|
|
|
SWITCH_DECLARE(char *) switch_channel_expand_variables(switch_channel_t *channel, const char *in)
|
2006-10-07 19:54:04 +00:00
|
|
|
{
|
2007-12-05 20:23:50 +00:00
|
|
|
char *p, *c = NULL;
|
2008-08-11 15:37:50 +00:00
|
|
|
char *data, *indup, *endof_indup;
|
Ringback (sponsored by Front Logic)
This addition lets you set artifical ringback on a channel
that is waiting for an originated call to be answered.
the syntax is
<action application="set" data="ringback=[data]"/>
where data is either the full path to an audio file
or a teletone generation script..
syntax of teletone scripts
LEGEND:
0-9,a-d,*,# (standard dtmf tones)
variables: c,r,d,v,>,<,+,w,l,L,%
c (channels) - Sets the number of channels.
r (rate) - Sets the sample rate.
d (duration) - Sets the default tone duration.
v (volume) - Sets the default volume.
> (decrease vol) - factor to decrease volume by per frame (0 for even decrease across duration).
< (increase vol) - factor to increase volume by per frame (0 for even increase across duration).
+ (step) - factor to step by used by < and >.
w (wait) - default silence after each tone.
l (loops) - number of times to repeat each tone in the script.
L (LOOPS) - number of times to repeat the the whole script.
% (manual tone) - a generic tone specified by a duration, a wait and a list of frequencies.
standard tones can have custom duration per use with the () modifier
7(1000, 500) to generate DTMF 7 for 1 second then pause .5 seconds
EXAMPLES
UK Ring Tone [400+450 hz on for 400ms off for 200ms then 400+450 hz on for 400ms off for 2200ms]
%(400,200,400,450);%(400,2200,400,450)
US Ring Tone [440+480 hz on for 2000ms off for 4000ms]
%(2000,4000,440,480)
ATT BONG [volume level 4000, even decay, step by 2, # key for 60ms with no wait, volume level 2000, 350+440hz {us dialtone} for 940ms
v=4000;>=0;+=2;#(60,0);v=2000;%(940,0,350,440)
SIT Tone 913.8 hz for 274 ms with no wait, 1370.6 hz for 274 ms with no wait, 1776.7 hz for 380ms with no wait
%(274,0,913.8);%(274,0,1370.6);%(380,0,1776.7)
ATTN TONE (phone's off the hook!) 1400+2060+2450+2600 hz for 100ms with 100ms wait
%(100,100,1400,2060,2450,2600)
git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@3408 d0543943-73ff-0310-b7d9-9358b9ac24b2
2006-11-19 01:05:06 +00:00
|
|
|
size_t sp = 0, len = 0, olen = 0, vtype = 0, br = 0, cpos, block = 128;
|
2008-06-06 13:43:41 +00:00
|
|
|
char *cloned_sub_val = NULL, *sub_val = NULL;
|
2007-11-01 11:28:26 +00:00
|
|
|
char *func_val = NULL;
|
2007-04-21 14:17:43 +00:00
|
|
|
int nv = 0;
|
2006-10-07 19:54:04 +00:00
|
|
|
|
2009-10-23 16:03:42 +00:00
|
|
|
if (zstr(in)) {
|
2008-05-27 04:30:03 +00:00
|
|
|
return (char *) in;
|
2008-03-11 23:49:06 +00:00
|
|
|
}
|
|
|
|
|
2009-04-14 15:24:30 +00:00
|
|
|
nv = switch_string_var_check_const(in) || switch_string_has_escaped_data(in);
|
2008-01-28 07:26:10 +00:00
|
|
|
|
2007-10-23 01:29:37 +00:00
|
|
|
if (!nv) {
|
2008-05-27 04:30:03 +00:00
|
|
|
return (char *) in;
|
2006-10-07 19:54:04 +00:00
|
|
|
}
|
|
|
|
|
2008-05-27 04:30:03 +00:00
|
|
|
|
2007-10-23 01:29:37 +00:00
|
|
|
nv = 0;
|
|
|
|
olen = strlen(in) + 1;
|
2006-10-07 19:54:04 +00:00
|
|
|
indup = strdup(in);
|
2008-08-11 20:43:19 +00:00
|
|
|
endof_indup = end_of_p(indup) + 1;
|
2006-10-07 19:54:04 +00:00
|
|
|
|
|
|
|
if ((data = malloc(olen))) {
|
|
|
|
memset(data, 0, olen);
|
|
|
|
c = data;
|
2008-08-11 15:37:50 +00:00
|
|
|
for (p = indup; p && p < endof_indup && *p; p++) {
|
2006-10-07 19:54:04 +00:00
|
|
|
vtype = 0;
|
2008-01-28 07:26:10 +00:00
|
|
|
|
2007-04-21 14:17:43 +00:00
|
|
|
if (*p == '\\') {
|
|
|
|
if (*(p + 1) == '$') {
|
|
|
|
nv = 1;
|
2009-05-21 20:10:24 +00:00
|
|
|
p++;
|
2010-03-03 18:31:19 +00:00
|
|
|
} else if (*(p + 1) == '\'') {
|
|
|
|
p++;
|
|
|
|
continue;
|
2007-04-21 14:23:12 +00:00
|
|
|
} else if (*(p + 1) == '\\') {
|
|
|
|
*c++ = *p++;
|
|
|
|
len++;
|
|
|
|
continue;
|
2007-04-21 14:17:43 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (*p == '$' && !nv) {
|
2008-05-27 04:30:03 +00:00
|
|
|
if (*(p + 1)) {
|
|
|
|
if (*(p + 1) == '{') {
|
2007-10-18 21:36:57 +00:00
|
|
|
vtype = 1;
|
|
|
|
} else {
|
|
|
|
nv = 1;
|
2007-10-17 18:26:08 +00:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
nv = 1;
|
2007-03-29 22:31:56 +00:00
|
|
|
}
|
2006-10-07 19:54:04 +00:00
|
|
|
}
|
2006-12-07 00:36:00 +00:00
|
|
|
|
2007-04-21 14:17:43 +00:00
|
|
|
if (nv) {
|
|
|
|
*c++ = *p;
|
|
|
|
len++;
|
|
|
|
nv = 0;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2006-10-07 19:54:04 +00:00
|
|
|
if (vtype) {
|
|
|
|
char *s = p, *e, *vname, *vval = NULL;
|
2006-10-08 04:37:03 +00:00
|
|
|
size_t nlen;
|
2006-12-07 00:36:00 +00:00
|
|
|
|
2006-10-07 19:54:04 +00:00
|
|
|
s++;
|
2006-12-07 00:36:00 +00:00
|
|
|
|
2006-11-20 02:01:21 +00:00
|
|
|
if (vtype == 1 && *s == '{') {
|
2006-10-07 19:54:04 +00:00
|
|
|
br = 1;
|
|
|
|
s++;
|
|
|
|
}
|
|
|
|
|
|
|
|
e = s;
|
|
|
|
vname = s;
|
|
|
|
while (*e) {
|
|
|
|
if (br == 1 && *e == '}') {
|
|
|
|
br = 0;
|
|
|
|
*e++ = '\0';
|
|
|
|
break;
|
|
|
|
}
|
2007-11-07 02:14:57 +00:00
|
|
|
|
|
|
|
if (br > 0) {
|
|
|
|
if (e != s && *e == '{') {
|
|
|
|
br++;
|
|
|
|
} else if (br > 1 && *e == '}') {
|
|
|
|
br--;
|
|
|
|
}
|
|
|
|
}
|
2008-01-28 07:26:10 +00:00
|
|
|
|
2006-10-07 19:54:04 +00:00
|
|
|
e++;
|
|
|
|
}
|
2008-08-11 15:37:50 +00:00
|
|
|
p = e > endof_indup ? endof_indup : e;
|
2008-01-28 07:26:10 +00:00
|
|
|
|
2010-10-08 20:59:22 +00:00
|
|
|
if ((vval = strchr(vname, '(')) || (vval = strchr(vname, ' '))) {
|
|
|
|
if (*vval == '(') br = 1;
|
2007-10-18 21:36:57 +00:00
|
|
|
e = vval - 1;
|
|
|
|
*vval++ = '\0';
|
2008-05-27 04:30:03 +00:00
|
|
|
while (*e == ' ') {
|
2007-10-18 21:36:57 +00:00
|
|
|
*e-- = '\0';
|
|
|
|
}
|
2007-11-08 23:46:26 +00:00
|
|
|
e = vval;
|
2010-10-08 20:59:22 +00:00
|
|
|
|
2008-05-27 04:30:03 +00:00
|
|
|
while (e && *e) {
|
2007-11-08 23:46:26 +00:00
|
|
|
if (*e == '(') {
|
|
|
|
br++;
|
|
|
|
} else if (br > 1 && *e == ')') {
|
|
|
|
br--;
|
|
|
|
} else if (br == 1 && *e == ')') {
|
|
|
|
*e = '\0';
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
e++;
|
2007-10-18 21:36:57 +00:00
|
|
|
}
|
2007-11-08 23:46:26 +00:00
|
|
|
|
2007-10-18 21:36:57 +00:00
|
|
|
vtype = 2;
|
|
|
|
}
|
2007-03-29 22:31:56 +00:00
|
|
|
|
2006-10-07 19:54:04 +00:00
|
|
|
if (vtype == 1) {
|
2007-11-07 18:28:33 +00:00
|
|
|
char *expanded = NULL;
|
2007-11-09 19:25:46 +00:00
|
|
|
int offset = 0;
|
|
|
|
int ooffset = 0;
|
2007-12-17 22:52:32 +00:00
|
|
|
char *ptr;
|
2007-11-09 19:25:46 +00:00
|
|
|
|
2008-05-27 04:30:03 +00:00
|
|
|
if ((expanded = switch_channel_expand_variables(channel, (char *) vname)) == vname) {
|
2007-11-07 18:28:33 +00:00
|
|
|
expanded = NULL;
|
|
|
|
} else {
|
|
|
|
vname = expanded;
|
|
|
|
}
|
2007-12-17 22:52:32 +00:00
|
|
|
if ((ptr = strchr(vname, ':'))) {
|
|
|
|
*ptr++ = '\0';
|
|
|
|
offset = atoi(ptr);
|
|
|
|
if ((ptr = strchr(ptr, ':'))) {
|
|
|
|
ptr++;
|
|
|
|
ooffset = atoi(ptr);
|
2007-11-09 19:25:46 +00:00
|
|
|
}
|
|
|
|
}
|
2008-01-28 07:26:10 +00:00
|
|
|
|
2008-06-06 13:43:41 +00:00
|
|
|
if ((sub_val = (char *) switch_channel_get_variable(channel, vname))) {
|
2008-03-12 15:17:18 +00:00
|
|
|
if (offset || ooffset) {
|
|
|
|
cloned_sub_val = strdup(sub_val);
|
|
|
|
switch_assert(cloned_sub_val);
|
|
|
|
sub_val = cloned_sub_val;
|
|
|
|
}
|
2007-11-09 19:25:46 +00:00
|
|
|
|
2008-03-12 15:17:18 +00:00
|
|
|
if (offset >= 0) {
|
2010-02-06 03:38:24 +00:00
|
|
|
if ((size_t) offset > strlen(sub_val)) {
|
2008-06-06 13:43:41 +00:00
|
|
|
*sub_val = '\0';
|
|
|
|
} else {
|
|
|
|
sub_val += offset;
|
|
|
|
}
|
2008-05-27 04:30:03 +00:00
|
|
|
} else if ((size_t) abs(offset) <= strlen(sub_val)) {
|
2008-03-12 15:17:18 +00:00
|
|
|
sub_val = cloned_sub_val + (strlen(cloned_sub_val) + offset);
|
|
|
|
}
|
2007-11-09 19:25:46 +00:00
|
|
|
|
2008-05-27 04:30:03 +00:00
|
|
|
if (ooffset > 0 && (size_t) ooffset < strlen(sub_val)) {
|
|
|
|
if ((ptr = (char *) sub_val + ooffset)) {
|
2008-03-12 15:17:18 +00:00
|
|
|
*ptr = '\0';
|
|
|
|
}
|
2007-11-09 19:25:46 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-11-07 18:28:33 +00:00
|
|
|
switch_safe_free(expanded);
|
2006-10-07 19:54:04 +00:00
|
|
|
} else {
|
2007-03-29 22:31:56 +00:00
|
|
|
switch_stream_handle_t stream = { 0 };
|
2007-11-07 18:28:33 +00:00
|
|
|
char *expanded = NULL;
|
2006-10-07 19:54:04 +00:00
|
|
|
|
|
|
|
SWITCH_STANDARD_STREAM(stream);
|
2007-03-29 22:31:56 +00:00
|
|
|
|
2006-10-07 19:54:04 +00:00
|
|
|
if (stream.data) {
|
2007-11-07 18:34:56 +00:00
|
|
|
char *expanded_vname = NULL;
|
2007-11-08 23:46:26 +00:00
|
|
|
|
2008-05-27 04:30:03 +00:00
|
|
|
if ((expanded_vname = switch_channel_expand_variables(channel, (char *) vname)) == vname) {
|
2007-11-07 18:34:56 +00:00
|
|
|
expanded_vname = NULL;
|
|
|
|
} else {
|
|
|
|
vname = expanded_vname;
|
|
|
|
}
|
2007-11-07 02:14:57 +00:00
|
|
|
|
2007-11-07 00:00:51 +00:00
|
|
|
if ((expanded = switch_channel_expand_variables(channel, vval)) == vval) {
|
|
|
|
expanded = NULL;
|
|
|
|
} else {
|
|
|
|
vval = expanded;
|
|
|
|
}
|
|
|
|
|
2006-10-07 19:54:04 +00:00
|
|
|
if (switch_api_execute(vname, vval, channel->session, &stream) == SWITCH_STATUS_SUCCESS) {
|
|
|
|
func_val = stream.data;
|
|
|
|
sub_val = func_val;
|
2007-11-07 01:33:31 +00:00
|
|
|
} else {
|
|
|
|
free(stream.data);
|
2006-10-07 19:54:04 +00:00
|
|
|
}
|
2008-01-28 07:26:10 +00:00
|
|
|
|
2007-11-07 00:00:51 +00:00
|
|
|
switch_safe_free(expanded);
|
2007-11-07 18:34:56 +00:00
|
|
|
switch_safe_free(expanded_vname);
|
2008-01-28 07:26:10 +00:00
|
|
|
|
2006-10-07 19:54:04 +00:00
|
|
|
} else {
|
2009-08-13 20:35:02 +00:00
|
|
|
switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_CRIT, "Memory Error!\n");
|
2006-10-07 19:54:04 +00:00
|
|
|
free(data);
|
|
|
|
free(indup);
|
2008-05-27 04:30:03 +00:00
|
|
|
return (char *) in;
|
2006-10-07 19:54:04 +00:00
|
|
|
}
|
|
|
|
}
|
2006-11-26 20:06:04 +00:00
|
|
|
if ((nlen = sub_val ? strlen(sub_val) : 0)) {
|
|
|
|
if (len + nlen >= olen) {
|
2007-03-29 22:31:56 +00:00
|
|
|
resize(nlen);
|
2006-11-26 20:06:04 +00:00
|
|
|
}
|
|
|
|
|
Ringback (sponsored by Front Logic)
This addition lets you set artifical ringback on a channel
that is waiting for an originated call to be answered.
the syntax is
<action application="set" data="ringback=[data]"/>
where data is either the full path to an audio file
or a teletone generation script..
syntax of teletone scripts
LEGEND:
0-9,a-d,*,# (standard dtmf tones)
variables: c,r,d,v,>,<,+,w,l,L,%
c (channels) - Sets the number of channels.
r (rate) - Sets the sample rate.
d (duration) - Sets the default tone duration.
v (volume) - Sets the default volume.
> (decrease vol) - factor to decrease volume by per frame (0 for even decrease across duration).
< (increase vol) - factor to increase volume by per frame (0 for even increase across duration).
+ (step) - factor to step by used by < and >.
w (wait) - default silence after each tone.
l (loops) - number of times to repeat each tone in the script.
L (LOOPS) - number of times to repeat the the whole script.
% (manual tone) - a generic tone specified by a duration, a wait and a list of frequencies.
standard tones can have custom duration per use with the () modifier
7(1000, 500) to generate DTMF 7 for 1 second then pause .5 seconds
EXAMPLES
UK Ring Tone [400+450 hz on for 400ms off for 200ms then 400+450 hz on for 400ms off for 2200ms]
%(400,200,400,450);%(400,2200,400,450)
US Ring Tone [440+480 hz on for 2000ms off for 4000ms]
%(2000,4000,440,480)
ATT BONG [volume level 4000, even decay, step by 2, # key for 60ms with no wait, volume level 2000, 350+440hz {us dialtone} for 940ms
v=4000;>=0;+=2;#(60,0);v=2000;%(940,0,350,440)
SIT Tone 913.8 hz for 274 ms with no wait, 1370.6 hz for 274 ms with no wait, 1776.7 hz for 380ms with no wait
%(274,0,913.8);%(274,0,1370.6);%(380,0,1776.7)
ATTN TONE (phone's off the hook!) 1400+2060+2450+2600 hz for 100ms with 100ms wait
%(100,100,1400,2060,2450,2600)
git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@3408 d0543943-73ff-0310-b7d9-9358b9ac24b2
2006-11-19 01:05:06 +00:00
|
|
|
len += nlen;
|
|
|
|
strcat(c, sub_val);
|
|
|
|
c += nlen;
|
2006-10-07 19:54:04 +00:00
|
|
|
}
|
2007-03-29 22:31:56 +00:00
|
|
|
|
Ringback (sponsored by Front Logic)
This addition lets you set artifical ringback on a channel
that is waiting for an originated call to be answered.
the syntax is
<action application="set" data="ringback=[data]"/>
where data is either the full path to an audio file
or a teletone generation script..
syntax of teletone scripts
LEGEND:
0-9,a-d,*,# (standard dtmf tones)
variables: c,r,d,v,>,<,+,w,l,L,%
c (channels) - Sets the number of channels.
r (rate) - Sets the sample rate.
d (duration) - Sets the default tone duration.
v (volume) - Sets the default volume.
> (decrease vol) - factor to decrease volume by per frame (0 for even decrease across duration).
< (increase vol) - factor to increase volume by per frame (0 for even increase across duration).
+ (step) - factor to step by used by < and >.
w (wait) - default silence after each tone.
l (loops) - number of times to repeat each tone in the script.
L (LOOPS) - number of times to repeat the the whole script.
% (manual tone) - a generic tone specified by a duration, a wait and a list of frequencies.
standard tones can have custom duration per use with the () modifier
7(1000, 500) to generate DTMF 7 for 1 second then pause .5 seconds
EXAMPLES
UK Ring Tone [400+450 hz on for 400ms off for 200ms then 400+450 hz on for 400ms off for 2200ms]
%(400,200,400,450);%(400,2200,400,450)
US Ring Tone [440+480 hz on for 2000ms off for 4000ms]
%(2000,4000,440,480)
ATT BONG [volume level 4000, even decay, step by 2, # key for 60ms with no wait, volume level 2000, 350+440hz {us dialtone} for 940ms
v=4000;>=0;+=2;#(60,0);v=2000;%(940,0,350,440)
SIT Tone 913.8 hz for 274 ms with no wait, 1370.6 hz for 274 ms with no wait, 1776.7 hz for 380ms with no wait
%(274,0,913.8);%(274,0,1370.6);%(380,0,1776.7)
ATTN TONE (phone's off the hook!) 1400+2060+2450+2600 hz for 100ms with 100ms wait
%(100,100,1400,2060,2450,2600)
git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@3408 d0543943-73ff-0310-b7d9-9358b9ac24b2
2006-11-19 01:05:06 +00:00
|
|
|
switch_safe_free(func_val);
|
2007-11-09 19:25:46 +00:00
|
|
|
switch_safe_free(cloned_sub_val);
|
2007-03-29 22:31:56 +00:00
|
|
|
sub_val = NULL;
|
|
|
|
vname = NULL;
|
|
|
|
vtype = 0;
|
2007-11-09 19:25:46 +00:00
|
|
|
br = 0;
|
2007-03-29 22:31:56 +00:00
|
|
|
}
|
|
|
|
if (len + 1 >= olen) {
|
|
|
|
resize(1);
|
2006-10-07 19:54:04 +00:00
|
|
|
}
|
2006-12-07 00:36:00 +00:00
|
|
|
|
2006-10-07 19:54:04 +00:00
|
|
|
if (sp) {
|
|
|
|
*c++ = ' ';
|
|
|
|
sp = 0;
|
Ringback (sponsored by Front Logic)
This addition lets you set artifical ringback on a channel
that is waiting for an originated call to be answered.
the syntax is
<action application="set" data="ringback=[data]"/>
where data is either the full path to an audio file
or a teletone generation script..
syntax of teletone scripts
LEGEND:
0-9,a-d,*,# (standard dtmf tones)
variables: c,r,d,v,>,<,+,w,l,L,%
c (channels) - Sets the number of channels.
r (rate) - Sets the sample rate.
d (duration) - Sets the default tone duration.
v (volume) - Sets the default volume.
> (decrease vol) - factor to decrease volume by per frame (0 for even decrease across duration).
< (increase vol) - factor to increase volume by per frame (0 for even increase across duration).
+ (step) - factor to step by used by < and >.
w (wait) - default silence after each tone.
l (loops) - number of times to repeat each tone in the script.
L (LOOPS) - number of times to repeat the the whole script.
% (manual tone) - a generic tone specified by a duration, a wait and a list of frequencies.
standard tones can have custom duration per use with the () modifier
7(1000, 500) to generate DTMF 7 for 1 second then pause .5 seconds
EXAMPLES
UK Ring Tone [400+450 hz on for 400ms off for 200ms then 400+450 hz on for 400ms off for 2200ms]
%(400,200,400,450);%(400,2200,400,450)
US Ring Tone [440+480 hz on for 2000ms off for 4000ms]
%(2000,4000,440,480)
ATT BONG [volume level 4000, even decay, step by 2, # key for 60ms with no wait, volume level 2000, 350+440hz {us dialtone} for 940ms
v=4000;>=0;+=2;#(60,0);v=2000;%(940,0,350,440)
SIT Tone 913.8 hz for 274 ms with no wait, 1370.6 hz for 274 ms with no wait, 1776.7 hz for 380ms with no wait
%(274,0,913.8);%(274,0,1370.6);%(380,0,1776.7)
ATTN TONE (phone's off the hook!) 1400+2060+2450+2600 hz for 100ms with 100ms wait
%(100,100,1400,2060,2450,2600)
git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@3408 d0543943-73ff-0310-b7d9-9358b9ac24b2
2006-11-19 01:05:06 +00:00
|
|
|
len++;
|
2006-10-07 19:54:04 +00:00
|
|
|
}
|
Ringback (sponsored by Front Logic)
This addition lets you set artifical ringback on a channel
that is waiting for an originated call to be answered.
the syntax is
<action application="set" data="ringback=[data]"/>
where data is either the full path to an audio file
or a teletone generation script..
syntax of teletone scripts
LEGEND:
0-9,a-d,*,# (standard dtmf tones)
variables: c,r,d,v,>,<,+,w,l,L,%
c (channels) - Sets the number of channels.
r (rate) - Sets the sample rate.
d (duration) - Sets the default tone duration.
v (volume) - Sets the default volume.
> (decrease vol) - factor to decrease volume by per frame (0 for even decrease across duration).
< (increase vol) - factor to increase volume by per frame (0 for even increase across duration).
+ (step) - factor to step by used by < and >.
w (wait) - default silence after each tone.
l (loops) - number of times to repeat each tone in the script.
L (LOOPS) - number of times to repeat the the whole script.
% (manual tone) - a generic tone specified by a duration, a wait and a list of frequencies.
standard tones can have custom duration per use with the () modifier
7(1000, 500) to generate DTMF 7 for 1 second then pause .5 seconds
EXAMPLES
UK Ring Tone [400+450 hz on for 400ms off for 200ms then 400+450 hz on for 400ms off for 2200ms]
%(400,200,400,450);%(400,2200,400,450)
US Ring Tone [440+480 hz on for 2000ms off for 4000ms]
%(2000,4000,440,480)
ATT BONG [volume level 4000, even decay, step by 2, # key for 60ms with no wait, volume level 2000, 350+440hz {us dialtone} for 940ms
v=4000;>=0;+=2;#(60,0);v=2000;%(940,0,350,440)
SIT Tone 913.8 hz for 274 ms with no wait, 1370.6 hz for 274 ms with no wait, 1776.7 hz for 380ms with no wait
%(274,0,913.8);%(274,0,1370.6);%(380,0,1776.7)
ATTN TONE (phone's off the hook!) 1400+2060+2450+2600 hz for 100ms with 100ms wait
%(100,100,1400,2060,2450,2600)
git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@3408 d0543943-73ff-0310-b7d9-9358b9ac24b2
2006-11-19 01:05:06 +00:00
|
|
|
|
2006-12-06 17:19:07 +00:00
|
|
|
if (*p == '$') {
|
Ringback (sponsored by Front Logic)
This addition lets you set artifical ringback on a channel
that is waiting for an originated call to be answered.
the syntax is
<action application="set" data="ringback=[data]"/>
where data is either the full path to an audio file
or a teletone generation script..
syntax of teletone scripts
LEGEND:
0-9,a-d,*,# (standard dtmf tones)
variables: c,r,d,v,>,<,+,w,l,L,%
c (channels) - Sets the number of channels.
r (rate) - Sets the sample rate.
d (duration) - Sets the default tone duration.
v (volume) - Sets the default volume.
> (decrease vol) - factor to decrease volume by per frame (0 for even decrease across duration).
< (increase vol) - factor to increase volume by per frame (0 for even increase across duration).
+ (step) - factor to step by used by < and >.
w (wait) - default silence after each tone.
l (loops) - number of times to repeat each tone in the script.
L (LOOPS) - number of times to repeat the the whole script.
% (manual tone) - a generic tone specified by a duration, a wait and a list of frequencies.
standard tones can have custom duration per use with the () modifier
7(1000, 500) to generate DTMF 7 for 1 second then pause .5 seconds
EXAMPLES
UK Ring Tone [400+450 hz on for 400ms off for 200ms then 400+450 hz on for 400ms off for 2200ms]
%(400,200,400,450);%(400,2200,400,450)
US Ring Tone [440+480 hz on for 2000ms off for 4000ms]
%(2000,4000,440,480)
ATT BONG [volume level 4000, even decay, step by 2, # key for 60ms with no wait, volume level 2000, 350+440hz {us dialtone} for 940ms
v=4000;>=0;+=2;#(60,0);v=2000;%(940,0,350,440)
SIT Tone 913.8 hz for 274 ms with no wait, 1370.6 hz for 274 ms with no wait, 1776.7 hz for 380ms with no wait
%(274,0,913.8);%(274,0,1370.6);%(380,0,1776.7)
ATTN TONE (phone's off the hook!) 1400+2060+2450+2600 hz for 100ms with 100ms wait
%(100,100,1400,2060,2450,2600)
git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@3408 d0543943-73ff-0310-b7d9-9358b9ac24b2
2006-11-19 01:05:06 +00:00
|
|
|
p--;
|
|
|
|
} else {
|
|
|
|
*c++ = *p;
|
|
|
|
len++;
|
2007-03-29 22:31:56 +00:00
|
|
|
}
|
2006-10-07 19:54:04 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
free(indup);
|
2008-01-28 07:26:10 +00:00
|
|
|
|
2006-10-07 19:54:04 +00:00
|
|
|
return data;
|
|
|
|
}
|
2006-11-27 22:30:48 +00:00
|
|
|
|
2007-11-17 00:26:28 +00:00
|
|
|
SWITCH_DECLARE(char *) switch_channel_build_param_string(switch_channel_t *channel, switch_caller_profile_t *caller_profile, const char *prefix)
|
2007-11-16 19:11:16 +00:00
|
|
|
{
|
|
|
|
switch_stream_handle_t stream = { 0 };
|
|
|
|
switch_size_t encode_len = 1024, new_len = 0;
|
|
|
|
char *encode_buf = NULL;
|
2008-05-27 04:30:03 +00:00
|
|
|
const char *prof[12] = { 0 }, *prof_names[12] = {
|
|
|
|
0};
|
2007-11-16 19:11:16 +00:00
|
|
|
char *e = NULL;
|
|
|
|
switch_event_header_t *hi;
|
|
|
|
uint32_t x = 0;
|
|
|
|
|
|
|
|
SWITCH_STANDARD_STREAM(stream);
|
|
|
|
|
2007-11-17 00:26:28 +00:00
|
|
|
if (prefix) {
|
|
|
|
stream.write_function(&stream, "%s&", prefix);
|
|
|
|
}
|
|
|
|
|
2007-11-16 19:11:16 +00:00
|
|
|
encode_buf = malloc(encode_len);
|
2007-12-11 19:23:57 +00:00
|
|
|
switch_assert(encode_buf);
|
2007-11-16 19:11:16 +00:00
|
|
|
|
|
|
|
if (!caller_profile) {
|
|
|
|
caller_profile = switch_channel_get_caller_profile(channel);
|
|
|
|
}
|
|
|
|
|
2007-12-11 19:23:57 +00:00
|
|
|
switch_assert(caller_profile != NULL);
|
2008-01-28 07:26:10 +00:00
|
|
|
|
2007-11-16 19:11:16 +00:00
|
|
|
prof[0] = caller_profile->context;
|
|
|
|
prof[1] = caller_profile->destination_number;
|
|
|
|
prof[2] = caller_profile->caller_id_name;
|
|
|
|
prof[3] = caller_profile->caller_id_number;
|
|
|
|
prof[4] = caller_profile->network_addr;
|
|
|
|
prof[5] = caller_profile->ani;
|
|
|
|
prof[6] = caller_profile->aniii;
|
|
|
|
prof[7] = caller_profile->rdnis;
|
|
|
|
prof[8] = caller_profile->source;
|
|
|
|
prof[9] = caller_profile->chan_name;
|
|
|
|
prof[10] = caller_profile->uuid;
|
2008-01-28 07:26:10 +00:00
|
|
|
|
2007-11-16 19:11:16 +00:00
|
|
|
prof_names[0] = "context";
|
|
|
|
prof_names[1] = "destination_number";
|
|
|
|
prof_names[2] = "caller_id_name";
|
|
|
|
prof_names[3] = "caller_id_number";
|
|
|
|
prof_names[4] = "network_addr";
|
|
|
|
prof_names[5] = "ani";
|
|
|
|
prof_names[6] = "aniii";
|
|
|
|
prof_names[7] = "rdnis";
|
|
|
|
prof_names[8] = "source";
|
|
|
|
prof_names[9] = "chan_name";
|
|
|
|
prof_names[10] = "uuid";
|
|
|
|
|
|
|
|
for (x = 0; prof[x]; x++) {
|
2009-10-23 16:03:42 +00:00
|
|
|
if (zstr(prof[x])) {
|
2007-11-16 19:11:16 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
new_len = (strlen(prof[x]) * 3) + 1;
|
|
|
|
if (encode_len < new_len) {
|
|
|
|
char *tmp;
|
2010-10-01 22:26:03 +00:00
|
|
|
|
2007-11-16 19:11:16 +00:00
|
|
|
encode_len = new_len;
|
|
|
|
|
|
|
|
if (!(tmp = realloc(encode_buf, encode_len))) {
|
|
|
|
abort();
|
|
|
|
}
|
|
|
|
|
|
|
|
encode_buf = tmp;
|
|
|
|
}
|
2008-05-21 21:31:17 +00:00
|
|
|
switch_url_encode(prof[x], encode_buf, encode_len);
|
2007-11-16 19:11:16 +00:00
|
|
|
stream.write_function(&stream, "%s=%s&", prof_names[x], encode_buf);
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((hi = switch_channel_variable_first(channel))) {
|
|
|
|
for (; hi; hi = hi->next) {
|
|
|
|
char *var = hi->name;
|
|
|
|
char *val = hi->value;
|
2008-01-28 07:26:10 +00:00
|
|
|
|
2007-11-16 19:11:16 +00:00
|
|
|
new_len = (strlen((char *) var) * 3) + 1;
|
|
|
|
if (encode_len < new_len) {
|
|
|
|
char *tmp;
|
2008-01-28 07:26:10 +00:00
|
|
|
|
2007-11-16 19:11:16 +00:00
|
|
|
encode_len = new_len;
|
2008-01-28 07:26:10 +00:00
|
|
|
|
2007-11-16 19:11:16 +00:00
|
|
|
tmp = realloc(encode_buf, encode_len);
|
2007-12-11 19:23:57 +00:00
|
|
|
switch_assert(tmp);
|
2007-11-16 19:11:16 +00:00
|
|
|
encode_buf = tmp;
|
|
|
|
}
|
|
|
|
|
2008-05-21 21:31:17 +00:00
|
|
|
switch_url_encode((char *) val, encode_buf, encode_len);
|
2007-11-16 19:11:16 +00:00
|
|
|
stream.write_function(&stream, "%s=%s&", (char *) var, encode_buf);
|
|
|
|
|
|
|
|
}
|
|
|
|
switch_channel_variable_last(channel);
|
|
|
|
}
|
|
|
|
|
|
|
|
e = (char *) stream.data + (strlen((char *) stream.data) - 1);
|
|
|
|
|
|
|
|
if (e && *e == '&') {
|
|
|
|
*e = '\0';
|
|
|
|
}
|
|
|
|
|
|
|
|
switch_safe_free(encode_buf);
|
|
|
|
|
|
|
|
return stream.data;
|
|
|
|
}
|
|
|
|
|
2009-10-21 18:48:28 +00:00
|
|
|
SWITCH_DECLARE(switch_status_t) switch_channel_pass_callee_id(switch_channel_t *channel, switch_channel_t *other_channel)
|
|
|
|
{
|
|
|
|
int x = 0;
|
|
|
|
|
|
|
|
switch_assert(channel);
|
|
|
|
switch_assert(other_channel);
|
|
|
|
|
|
|
|
switch_mutex_lock(channel->profile_mutex);
|
|
|
|
switch_mutex_lock(other_channel->profile_mutex);
|
|
|
|
|
2009-10-23 16:03:42 +00:00
|
|
|
if (!zstr(channel->caller_profile->callee_id_name)) {
|
2010-05-13 02:23:09 +00:00
|
|
|
other_channel->caller_profile->callee_id_name = switch_core_strdup(other_channel->caller_profile->pool, channel->caller_profile->callee_id_name);
|
2009-10-21 18:48:28 +00:00
|
|
|
x++;
|
|
|
|
}
|
|
|
|
|
2009-10-23 16:03:42 +00:00
|
|
|
if (!zstr(channel->caller_profile->callee_id_number)) {
|
2010-05-13 02:23:09 +00:00
|
|
|
other_channel->caller_profile->callee_id_number = switch_core_strdup(other_channel->caller_profile->pool, channel->caller_profile->callee_id_number);
|
2009-10-21 18:48:28 +00:00
|
|
|
x++;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch_mutex_unlock(other_channel->profile_mutex);
|
|
|
|
switch_mutex_unlock(channel->profile_mutex);
|
|
|
|
|
|
|
|
return x ? SWITCH_STATUS_SUCCESS : SWITCH_STATUS_FALSE;
|
|
|
|
}
|
|
|
|
|
2008-07-17 19:46:25 +00:00
|
|
|
SWITCH_DECLARE(switch_status_t) switch_channel_get_variables(switch_channel_t *channel, switch_event_t **event)
|
|
|
|
{
|
|
|
|
switch_status_t status;
|
|
|
|
switch_mutex_lock(channel->profile_mutex);
|
|
|
|
status = switch_event_dup(event, channel->variables);
|
2008-11-03 15:45:38 +00:00
|
|
|
switch_mutex_unlock(channel->profile_mutex);
|
2008-07-17 19:46:25 +00:00
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
2010-02-06 03:38:24 +00:00
|
|
|
SWITCH_DECLARE(switch_core_session_t *) switch_channel_get_session(switch_channel_t *channel)
|
2010-01-20 19:19:48 +00:00
|
|
|
{
|
|
|
|
switch_assert(channel);
|
|
|
|
return channel->session;
|
|
|
|
}
|
|
|
|
|
2007-12-20 18:04:07 +00:00
|
|
|
SWITCH_DECLARE(switch_status_t) switch_channel_set_timestamps(switch_channel_t *channel)
|
|
|
|
{
|
|
|
|
switch_status_t status = SWITCH_STATUS_SUCCESS;
|
|
|
|
const char *cid_buf = NULL;
|
|
|
|
switch_caller_profile_t *caller_profile, *ocp;
|
|
|
|
switch_app_log_t *app_log, *ap;
|
|
|
|
char *last_app = NULL, *last_arg = NULL;
|
2010-07-20 20:22:19 +00:00
|
|
|
char start[80] = "", resurrect[80] = "", answer[80] = "", progress[80] = "", progress_media[80] = "", end[80] = "", tmp[80] = "",
|
|
|
|
profile_start[80] = "";
|
2008-05-24 03:24:12 +00:00
|
|
|
int32_t duration = 0, legbillsec = 0, billsec = 0, mduration = 0, billmsec = 0, legbillmsec = 0, progressmsec = 0, progress_mediamsec = 0;
|
2009-08-24 17:12:36 +00:00
|
|
|
int32_t answersec = 0, answermsec = 0;
|
|
|
|
switch_time_t answerusec = 0;
|
2008-05-24 03:24:12 +00:00
|
|
|
switch_time_t uduration = 0, legbillusec = 0, billusec = 0, progresssec = 0, progressusec = 0, progress_mediasec = 0, progress_mediausec = 0;
|
2010-02-06 03:38:24 +00:00
|
|
|
time_t tt_created = 0, tt_answered = 0, tt_resurrected = 0,
|
|
|
|
tt_progress = 0, tt_progress_media = 0, tt_hungup = 0, mtt_created = 0, mtt_answered = 0, mtt_resurrected = 0,
|
|
|
|
mtt_hungup = 0, tt_prof_created, mtt_prof_created, mtt_progress = 0, mtt_progress_media = 0;
|
2009-02-23 16:31:59 +00:00
|
|
|
void *pop;
|
2010-02-06 03:38:24 +00:00
|
|
|
char dtstr[SWITCH_DTMF_LOG_LEN + 1] = "";
|
2009-02-23 16:31:59 +00:00
|
|
|
int x = 0;
|
2007-12-20 18:04:07 +00:00
|
|
|
|
2009-12-08 01:20:22 +00:00
|
|
|
switch_mutex_lock(channel->profile_mutex);
|
|
|
|
|
2009-05-12 14:54:34 +00:00
|
|
|
if (switch_channel_test_flag(channel, CF_TIMESTAMP_SET)) {
|
2010-03-04 23:03:51 +00:00
|
|
|
switch_mutex_unlock(channel->profile_mutex);
|
2009-05-12 14:54:34 +00:00
|
|
|
return SWITCH_STATUS_FALSE;
|
|
|
|
}
|
2010-02-06 03:38:24 +00:00
|
|
|
|
2009-12-08 01:20:22 +00:00
|
|
|
if (!(caller_profile = channel->caller_profile) || !channel->variables) {
|
2010-03-04 23:03:51 +00:00
|
|
|
switch_mutex_unlock(channel->profile_mutex);
|
2008-03-11 21:32:56 +00:00
|
|
|
return SWITCH_STATUS_FALSE;
|
|
|
|
}
|
2007-12-20 18:04:07 +00:00
|
|
|
|
2010-03-04 23:03:51 +00:00
|
|
|
switch_channel_set_flag(channel, CF_TIMESTAMP_SET);
|
|
|
|
|
2008-03-14 20:08:58 +00:00
|
|
|
if ((app_log = switch_core_session_get_app_log(channel->session))) {
|
|
|
|
for (ap = app_log; ap && ap->next; ap = ap->next);
|
|
|
|
last_app = ap->app;
|
|
|
|
last_arg = ap->arg;
|
|
|
|
}
|
2008-05-27 04:30:03 +00:00
|
|
|
|
2007-12-20 18:04:07 +00:00
|
|
|
if (!(ocp = switch_channel_get_originatee_caller_profile(channel))) {
|
|
|
|
ocp = switch_channel_get_originator_caller_profile(channel);
|
|
|
|
}
|
|
|
|
|
2009-10-23 16:03:42 +00:00
|
|
|
if (!zstr(caller_profile->caller_id_name)) {
|
2008-05-27 04:30:03 +00:00
|
|
|
cid_buf = switch_core_session_sprintf(channel->session, "\"%s\" <%s>", caller_profile->caller_id_name,
|
2008-03-11 21:32:56 +00:00
|
|
|
switch_str_nil(caller_profile->caller_id_number));
|
2007-12-20 18:04:07 +00:00
|
|
|
} else {
|
|
|
|
cid_buf = caller_profile->caller_id_number;
|
|
|
|
}
|
|
|
|
|
2009-02-23 16:31:59 +00:00
|
|
|
while (x < SWITCH_DTMF_LOG_LEN && switch_queue_trypop(channel->dtmf_log_queue, &pop) == SWITCH_STATUS_SUCCESS) {
|
|
|
|
switch_dtmf_t *dt = (switch_dtmf_t *) pop;
|
|
|
|
|
|
|
|
if (dt) {
|
|
|
|
dtstr[x++] = dt->digit;
|
|
|
|
free(dt);
|
|
|
|
dt = NULL;
|
|
|
|
}
|
|
|
|
}
|
2010-02-06 03:38:24 +00:00
|
|
|
|
2009-02-23 16:31:59 +00:00
|
|
|
if (x) {
|
|
|
|
switch_channel_set_variable(channel, "digits_dialed", dtstr);
|
|
|
|
} else {
|
|
|
|
switch_channel_set_variable(channel, "digits_dialed", "none");
|
|
|
|
}
|
|
|
|
|
2007-12-20 18:04:07 +00:00
|
|
|
if (caller_profile->times) {
|
|
|
|
switch_time_exp_t tm;
|
|
|
|
switch_size_t retsize;
|
|
|
|
const char *fmt = "%Y-%m-%d %T";
|
|
|
|
|
|
|
|
switch_time_exp_lt(&tm, caller_profile->times->created);
|
2008-10-12 21:51:51 +00:00
|
|
|
switch_strftime_nocheck(start, &retsize, sizeof(start), fmt, &tm);
|
2007-12-20 18:04:07 +00:00
|
|
|
switch_channel_set_variable(channel, "start_stamp", start);
|
|
|
|
|
|
|
|
switch_time_exp_lt(&tm, caller_profile->times->profile_created);
|
2008-10-12 21:51:51 +00:00
|
|
|
switch_strftime_nocheck(profile_start, &retsize, sizeof(profile_start), fmt, &tm);
|
2007-12-20 18:04:07 +00:00
|
|
|
switch_channel_set_variable(channel, "profile_start_stamp", profile_start);
|
|
|
|
|
2008-02-26 21:55:59 +00:00
|
|
|
if (caller_profile->times->answered) {
|
|
|
|
switch_time_exp_lt(&tm, caller_profile->times->answered);
|
2008-10-12 21:51:51 +00:00
|
|
|
switch_strftime_nocheck(answer, &retsize, sizeof(answer), fmt, &tm);
|
2008-02-26 21:55:59 +00:00
|
|
|
switch_channel_set_variable(channel, "answer_stamp", answer);
|
|
|
|
}
|
2007-12-20 18:04:07 +00:00
|
|
|
|
2010-02-06 03:38:24 +00:00
|
|
|
if (caller_profile->times->resurrected) {
|
|
|
|
switch_time_exp_lt(&tm, caller_profile->times->resurrected);
|
2010-07-20 20:22:19 +00:00
|
|
|
switch_strftime_nocheck(resurrect, &retsize, sizeof(resurrect), fmt, &tm);
|
2010-02-06 03:38:24 +00:00
|
|
|
switch_channel_set_variable(channel, "resurrect_stamp", resurrect);
|
|
|
|
}
|
|
|
|
|
2008-05-24 01:43:12 +00:00
|
|
|
if (caller_profile->times->progress) {
|
|
|
|
switch_time_exp_lt(&tm, caller_profile->times->progress);
|
2008-10-12 21:51:51 +00:00
|
|
|
switch_strftime_nocheck(progress, &retsize, sizeof(progress), fmt, &tm);
|
2008-05-24 01:43:12 +00:00
|
|
|
switch_channel_set_variable(channel, "progress_stamp", progress);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (caller_profile->times->progress_media) {
|
|
|
|
switch_time_exp_lt(&tm, caller_profile->times->progress_media);
|
2008-10-12 21:51:51 +00:00
|
|
|
switch_strftime_nocheck(progress_media, &retsize, sizeof(progress_media), fmt, &tm);
|
2008-05-24 01:43:12 +00:00
|
|
|
switch_channel_set_variable(channel, "progress_media_stamp", progress_media);
|
|
|
|
}
|
|
|
|
|
2007-12-20 18:04:07 +00:00
|
|
|
switch_time_exp_lt(&tm, caller_profile->times->hungup);
|
2008-10-12 21:51:51 +00:00
|
|
|
switch_strftime_nocheck(end, &retsize, sizeof(end), fmt, &tm);
|
2007-12-20 18:04:07 +00:00
|
|
|
switch_channel_set_variable(channel, "end_stamp", end);
|
|
|
|
|
|
|
|
tt_created = (time_t) (caller_profile->times->created / 1000000);
|
|
|
|
mtt_created = (time_t) (caller_profile->times->created / 1000);
|
|
|
|
switch_snprintf(tmp, sizeof(tmp), "%" TIME_T_FMT, tt_created);
|
|
|
|
switch_channel_set_variable(channel, "start_epoch", tmp);
|
|
|
|
switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT, caller_profile->times->created);
|
|
|
|
switch_channel_set_variable(channel, "start_uepoch", tmp);
|
|
|
|
|
2010-07-20 20:22:19 +00:00
|
|
|
tt_prof_created = (time_t) (caller_profile->times->profile_created / 1000000);
|
|
|
|
mtt_prof_created = (time_t) (caller_profile->times->profile_created / 1000);
|
2007-12-20 18:04:07 +00:00
|
|
|
switch_snprintf(tmp, sizeof(tmp), "%" TIME_T_FMT, tt_prof_created);
|
|
|
|
switch_channel_set_variable(channel, "profile_start_epoch", tmp);
|
|
|
|
switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT, caller_profile->times->profile_created);
|
|
|
|
switch_channel_set_variable(channel, "profile_start_uepoch", tmp);
|
2008-01-28 07:26:10 +00:00
|
|
|
|
2007-12-20 18:04:07 +00:00
|
|
|
tt_answered = (time_t) (caller_profile->times->answered / 1000000);
|
|
|
|
mtt_answered = (time_t) (caller_profile->times->answered / 1000);
|
|
|
|
switch_snprintf(tmp, sizeof(tmp), "%" TIME_T_FMT, tt_answered);
|
|
|
|
switch_channel_set_variable(channel, "answer_epoch", tmp);
|
|
|
|
switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT, caller_profile->times->answered);
|
2008-05-27 04:30:03 +00:00
|
|
|
switch_channel_set_variable(channel, "answer_uepoch", tmp);
|
2007-12-20 18:04:07 +00:00
|
|
|
|
2010-02-06 03:38:24 +00:00
|
|
|
tt_resurrected = (time_t) (caller_profile->times->resurrected / 1000000);
|
|
|
|
mtt_resurrected = (time_t) (caller_profile->times->resurrected / 1000);
|
|
|
|
switch_snprintf(tmp, sizeof(tmp), "%" TIME_T_FMT, tt_resurrected);
|
|
|
|
switch_channel_set_variable(channel, "resurrect_epoch", tmp);
|
|
|
|
switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT, caller_profile->times->resurrected);
|
|
|
|
switch_channel_set_variable(channel, "resurrect_uepoch", tmp);
|
|
|
|
|
2008-05-24 01:43:12 +00:00
|
|
|
tt_progress = (time_t) (caller_profile->times->progress / 1000000);
|
|
|
|
mtt_progress = (time_t) (caller_profile->times->progress / 1000);
|
|
|
|
switch_snprintf(tmp, sizeof(tmp), "%" TIME_T_FMT, tt_progress);
|
2009-01-14 13:36:32 +00:00
|
|
|
switch_channel_set_variable(channel, "progress_epoch", tmp);
|
2008-05-24 01:43:12 +00:00
|
|
|
switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT, caller_profile->times->progress);
|
2009-01-14 13:36:32 +00:00
|
|
|
switch_channel_set_variable(channel, "progress_uepoch", tmp);
|
2008-05-24 01:43:12 +00:00
|
|
|
|
|
|
|
tt_progress_media = (time_t) (caller_profile->times->progress_media / 1000000);
|
|
|
|
mtt_progress_media = (time_t) (caller_profile->times->progress_media / 1000);
|
|
|
|
switch_snprintf(tmp, sizeof(tmp), "%" TIME_T_FMT, tt_progress_media);
|
2009-01-14 13:36:32 +00:00
|
|
|
switch_channel_set_variable(channel, "progress_media_epoch", tmp);
|
2008-05-24 01:43:12 +00:00
|
|
|
switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT, caller_profile->times->progress_media);
|
2009-01-14 13:36:32 +00:00
|
|
|
switch_channel_set_variable(channel, "progress_media_uepoch", tmp);
|
2008-05-24 01:43:12 +00:00
|
|
|
|
2007-12-20 18:04:07 +00:00
|
|
|
tt_hungup = (time_t) (caller_profile->times->hungup / 1000000);
|
|
|
|
mtt_hungup = (time_t) (caller_profile->times->hungup / 1000);
|
|
|
|
switch_snprintf(tmp, sizeof(tmp), "%" TIME_T_FMT, tt_hungup);
|
|
|
|
switch_channel_set_variable(channel, "end_epoch", tmp);
|
|
|
|
switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT, caller_profile->times->hungup);
|
|
|
|
switch_channel_set_variable(channel, "end_uepoch", tmp);
|
|
|
|
|
2008-05-27 04:30:03 +00:00
|
|
|
duration = (int32_t) (tt_hungup - tt_created);
|
|
|
|
mduration = (int32_t) (mtt_hungup - mtt_created);
|
2010-07-20 20:22:19 +00:00
|
|
|
uduration = caller_profile->times->hungup - caller_profile->times->created;
|
2008-01-28 07:26:10 +00:00
|
|
|
|
2007-12-20 18:04:07 +00:00
|
|
|
if (caller_profile->times->answered) {
|
2008-05-27 04:30:03 +00:00
|
|
|
billsec = (int32_t) (tt_hungup - tt_answered);
|
|
|
|
billmsec = (int32_t) (mtt_hungup - mtt_answered);
|
2007-12-20 18:04:07 +00:00
|
|
|
billusec = caller_profile->times->hungup - caller_profile->times->answered;
|
|
|
|
|
2008-05-27 04:30:03 +00:00
|
|
|
legbillsec = (int32_t) (tt_hungup - tt_prof_created);
|
|
|
|
legbillmsec = (int32_t) (mtt_hungup - mtt_prof_created);
|
2007-12-20 18:04:07 +00:00
|
|
|
legbillusec = caller_profile->times->hungup - caller_profile->times->profile_created;
|
2009-08-24 17:12:36 +00:00
|
|
|
|
|
|
|
answersec = (int32_t) (tt_answered - tt_prof_created);
|
|
|
|
answermsec = (int32_t) (mtt_answered - mtt_prof_created);
|
|
|
|
answerusec = caller_profile->times->answered - caller_profile->times->profile_created;
|
2007-12-20 18:04:07 +00:00
|
|
|
}
|
2008-05-24 03:24:12 +00:00
|
|
|
|
|
|
|
if (caller_profile->times->progress) {
|
2008-05-27 04:30:03 +00:00
|
|
|
progresssec = (int32_t) (tt_progress - tt_created);
|
|
|
|
progressmsec = (int32_t) (mtt_progress - mtt_created);
|
2008-05-24 03:24:12 +00:00
|
|
|
progressusec = caller_profile->times->progress - caller_profile->times->created;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (caller_profile->times->progress_media) {
|
2009-02-12 20:10:51 +00:00
|
|
|
progress_mediasec = (int32_t) (tt_progress_media - tt_created);
|
|
|
|
progress_mediamsec = (int32_t) (mtt_progress_media - mtt_created);
|
|
|
|
progress_mediausec = caller_profile->times->progress_media - caller_profile->times->created;
|
2008-05-24 03:24:12 +00:00
|
|
|
}
|
|
|
|
|
2007-12-20 18:04:07 +00:00
|
|
|
}
|
2008-01-27 17:36:53 +00:00
|
|
|
|
2007-12-20 18:04:07 +00:00
|
|
|
switch_channel_set_variable(channel, "last_app", last_app);
|
|
|
|
switch_channel_set_variable(channel, "last_arg", last_arg);
|
|
|
|
switch_channel_set_variable(channel, "caller_id", cid_buf);
|
|
|
|
|
|
|
|
switch_snprintf(tmp, sizeof(tmp), "%d", duration);
|
|
|
|
switch_channel_set_variable(channel, "duration", tmp);
|
|
|
|
|
|
|
|
switch_snprintf(tmp, sizeof(tmp), "%d", billsec);
|
|
|
|
switch_channel_set_variable(channel, "billsec", tmp);
|
|
|
|
|
2010-07-20 20:22:19 +00:00
|
|
|
switch_snprintf(tmp, sizeof(tmp), "%d", progresssec);
|
2008-05-24 03:24:12 +00:00
|
|
|
switch_channel_set_variable(channel, "progresssec", tmp);
|
|
|
|
|
2010-07-20 20:22:19 +00:00
|
|
|
switch_snprintf(tmp, sizeof(tmp), "%d", answersec);
|
2009-08-24 17:12:36 +00:00
|
|
|
switch_channel_set_variable(channel, "answersec", tmp);
|
|
|
|
|
2010-07-20 20:22:19 +00:00
|
|
|
switch_snprintf(tmp, sizeof(tmp), "%d", progress_mediasec);
|
2008-05-24 03:24:12 +00:00
|
|
|
switch_channel_set_variable(channel, "progress_mediasec", tmp);
|
|
|
|
|
2007-12-20 18:04:07 +00:00
|
|
|
switch_snprintf(tmp, sizeof(tmp), "%d", legbillsec);
|
|
|
|
switch_channel_set_variable(channel, "flow_billsec", tmp);
|
2008-01-28 07:26:10 +00:00
|
|
|
|
2007-12-20 18:04:07 +00:00
|
|
|
switch_snprintf(tmp, sizeof(tmp), "%d", mduration);
|
|
|
|
switch_channel_set_variable(channel, "mduration", tmp);
|
|
|
|
|
|
|
|
switch_snprintf(tmp, sizeof(tmp), "%d", billmsec);
|
|
|
|
switch_channel_set_variable(channel, "billmsec", tmp);
|
|
|
|
|
2008-05-24 03:24:12 +00:00
|
|
|
switch_snprintf(tmp, sizeof(tmp), "%d", progressmsec);
|
|
|
|
switch_channel_set_variable(channel, "progressmsec", tmp);
|
|
|
|
|
2009-08-24 17:12:36 +00:00
|
|
|
switch_snprintf(tmp, sizeof(tmp), "%d", answermsec);
|
|
|
|
switch_channel_set_variable(channel, "answermsec", tmp);
|
|
|
|
|
2010-07-20 20:22:19 +00:00
|
|
|
switch_snprintf(tmp, sizeof(tmp), "%d", progress_mediamsec);
|
2008-05-24 03:24:12 +00:00
|
|
|
switch_channel_set_variable(channel, "progress_mediamsec", tmp);
|
|
|
|
|
2007-12-20 18:04:07 +00:00
|
|
|
switch_snprintf(tmp, sizeof(tmp), "%d", legbillmsec);
|
|
|
|
switch_channel_set_variable(channel, "flow_billmsec", tmp);
|
|
|
|
|
|
|
|
switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT, uduration);
|
|
|
|
switch_channel_set_variable(channel, "uduration", tmp);
|
|
|
|
|
|
|
|
switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT, billusec);
|
|
|
|
switch_channel_set_variable(channel, "billusec", tmp);
|
|
|
|
|
2008-05-24 03:24:12 +00:00
|
|
|
switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT, progressusec);
|
|
|
|
switch_channel_set_variable(channel, "progressusec", tmp);
|
|
|
|
|
2009-08-24 17:12:36 +00:00
|
|
|
switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT, answerusec);
|
|
|
|
switch_channel_set_variable(channel, "answerusec", tmp);
|
|
|
|
|
2008-05-24 03:24:12 +00:00
|
|
|
switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT, progress_mediausec);
|
|
|
|
switch_channel_set_variable(channel, "progress_mediausec", tmp);
|
|
|
|
|
2007-12-20 18:04:07 +00:00
|
|
|
switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT, legbillusec);
|
|
|
|
switch_channel_set_variable(channel, "flow_billusec", tmp);
|
2010-02-06 03:38:24 +00:00
|
|
|
|
2009-12-08 01:20:22 +00:00
|
|
|
switch_mutex_unlock(channel->profile_mutex);
|
|
|
|
|
2007-12-20 18:04:07 +00:00
|
|
|
return status;
|
|
|
|
}
|
2007-11-16 19:11:16 +00:00
|
|
|
|
2006-11-27 22:30:48 +00:00
|
|
|
/* For Emacs:
|
|
|
|
* Local Variables:
|
|
|
|
* mode:c
|
2008-02-03 22:14:57 +00:00
|
|
|
* indent-tabs-mode:t
|
2006-11-27 22:30:48 +00:00
|
|
|
* tab-width:4
|
|
|
|
* c-basic-offset:4
|
|
|
|
* End:
|
|
|
|
* For VIM:
|
2008-07-03 19:12:26 +00:00
|
|
|
* vim:set softtabstop=4 shiftwidth=4 tabstop=4:
|
2006-11-27 22:30:48 +00:00
|
|
|
*/
|