SWITCH_DECLARE(char *) switch_channel_get_cap_string(switch_channel_t *channel);
SWITCH_DECLARE(int) switch_channel_state_change_pending(switch_channel_t *channel);
+SWITCH_DECLARE(void) switch_channel_set_callstate(switch_channel_t *channel, switch_channel_callstate_t callstate);
+SWITCH_DECLARE(switch_channel_callstate_t) switch_channel_get_callstate(switch_channel_t *channel);
+SWITCH_DECLARE(const char *) switch_channel_callstate2str(switch_channel_callstate_t callstate);
+SWITCH_DECLARE(switch_call_cause_t) switch_channel_str2callstate(const char *str);
+SWITCH_DECLARE(void) switch_channel_mark_hold(switch_channel_t *channel, switch_bool_t on);
+
/** @} */
SWITCH_END_EXTERN_C
#define SWITCH_CHANNEL_CHANNEL_LOG(x) SWITCH_CHANNEL_ID_SESSION, __FILE__, __SWITCH_FUNC__, __LINE__, (const char*)switch_channel_get_session(x)
#define SWITCH_CHANNEL_UUID_LOG(x) SWITCH_CHANNEL_ID_LOG, __FILE__, __SWITCH_FUNC__, __LINE__, (x)
+typedef enum {
+ CCS_DOWN,
+ CCS_DIALING,
+ CCS_RINGING,
+ CCS_EARLY,
+ CCS_ACTIVE,
+ CCS_HELD,
+ CCS_HANGUP
+} switch_channel_callstate_t;
+
/*!
\enum switch_channel_state_t
\brief Channel States (these are the defaults, CS_SOFT_EXECUTE, CS_EXCHANGE_MEDIA, and CS_CONSUME_MEDIA are often overridden by specific apps)
SWITCH_EVENT_CHANNEL_HANGUP_COMPLETE,
SWITCH_EVENT_CHANNEL_EXECUTE,
SWITCH_EVENT_CHANNEL_EXECUTE_COMPLETE,
+ SWITCH_EVENT_CHANNEL_HOLD,
+ SWITCH_EVENT_CHANNEL_UNHOLD,
SWITCH_EVENT_CHANNEL_BRIDGE,
SWITCH_EVENT_CHANNEL_UNBRIDGE,
SWITCH_EVENT_CHANNEL_PROGRESS,
sofia_set_flag_locked(tech_pvt, TFLAG_SIP_HOLD);
switch_channel_set_flag(tech_pvt->channel, CF_LEG_HOLDING);
+ switch_channel_mark_hold(tech_pvt->channel, SWITCH_TRUE);
switch_channel_presence(tech_pvt->channel, "unknown", msg, NULL);
if (tech_pvt->max_missed_hold_packets) {
if (sofia_test_flag(tech_pvt, TFLAG_HOLD_LOCK)) {
sofia_set_flag(tech_pvt, TFLAG_SIP_HOLD);
switch_channel_set_flag(tech_pvt->channel, CF_LEG_HOLDING);
+ switch_channel_mark_hold(tech_pvt->channel, SWITCH_TRUE);
}
sofia_clear_flag_locked(tech_pvt, TFLAG_HOLD_LOCK);
sofia_clear_flag_locked(tech_pvt, TFLAG_SIP_HOLD);
switch_channel_clear_flag(tech_pvt->channel, CF_LEG_HOLDING);
+ switch_channel_mark_hold(tech_pvt->channel, SWITCH_FALSE);
switch_channel_presence(tech_pvt->channel, "unknown", "unhold", NULL);
}
}
switch_core_session_t *session;
switch_channel_state_t state;
switch_channel_state_t running_state;
+ switch_channel_callstate_t callstate;
uint32_t flags[CF_FLAG_MAX];
uint32_t caps[CC_FLAG_MAX];
uint8_t state_flags[CF_FLAG_MAX];
opaque_channel_flag_t opaque_flags;
};
+
SWITCH_DECLARE(const char *) switch_channel_cause2str(switch_call_cause_t cause)
{
uint8_t x;
}
+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}
+};
+
+
+SWITCH_DECLARE(void) switch_channel_set_callstate(switch_channel_t *channel, switch_channel_callstate_t callstate)
+{
+ channel->callstate = callstate;
+}
+
+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;
+}
+
+
+
SWITCH_DECLARE(void) switch_channel_perform_audio_sync(switch_channel_t *channel, const char *file, const char *func, int line)
{
if (switch_channel_media_ready(channel)) {
}
}
+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);
+ }
+
+}
+
SWITCH_DECLARE(const char *) switch_channel_get_variable_dup(switch_channel_t *channel, const char *varname, switch_bool_t dup)
{
const char *v = NULL, *r = NULL;
if (flag == CF_OUTBOUND) {
switch_channel_set_variable(channel, "is_outbound", "true");
}
+
+ if (flag == CF_LEG_HOLDING) {
+ switch_channel_set_callstate(channel, CCS_HELD);
+ }
+
+
}
SWITCH_DECLARE(void) switch_channel_set_flag_recursive(switch_channel_t *channel, switch_channel_flag_t flag)
if (flag == CF_OUTBOUND) {
switch_channel_set_variable(channel, "is_outbound", NULL);
}
+
+ if (flag == CF_LEG_HOLDING) {
+ switch_channel_set_callstate(channel, CCS_ACTIVE);
+ }
}
if (state <= CS_DESTROY) {
switch_event_t *event;
+
+ 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);
+ }
+
if (switch_event_create(&event, SWITCH_EVENT_CHANNEL_STATE) == SWITCH_STATUS_SUCCESS) {
if (state == CS_ROUTING) {
switch_channel_event_set_data(channel, event);
} else {
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Channel-State", switch_channel_state_name(state));
+ switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Channel-Call-State", switch_channel_callstate2str(channel->callstate));
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Channel-State-Number", "%d", state);
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, "Channel-State", switch_channel_state_name(channel->state));
+ switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Channel-Call-State", switch_channel_callstate2str(channel->callstate));
switch_snprintf(state_num, sizeof(state_num), "%d", channel->state);
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_channel_set_variable(channel, "presence_call_info", NULL);
}
+ switch_channel_set_callstate(channel, CCS_HANGUP);
channel->hangup_cause = hangup_cause;
switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, func, line, switch_channel_get_uuid(channel), SWITCH_LOG_NOTICE, "Hangup %s [%s] [%s]\n",
channel->name, state_names[last_state], switch_channel_cause2str(channel->hangup_cause));
switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, func, line, switch_channel_get_uuid(channel), SWITCH_LOG_NOTICE, "Pre-Answer %s!\n", channel->name);
switch_channel_set_flag(channel, CF_EARLY_MEDIA);
+ switch_channel_set_callstate(channel, CCS_EARLY);
switch_channel_set_variable(channel, SWITCH_ENDPOINT_DISPOSITION_VARIABLE, "EARLY MEDIA");
if (switch_event_create(&event, SWITCH_EVENT_CHANNEL_PROGRESS_MEDIA) == SWITCH_STATUS_SUCCESS) {
switch_channel_event_set_data(channel, event);
}
switch_channel_set_flag(channel, CF_ANSWERED);
+ switch_channel_set_callstate(channel, CCS_ACTIVE);
if (switch_event_create(&event, SWITCH_EVENT_CHANNEL_ANSWER) == SWITCH_STATUS_SUCCESS) {
switch_channel_event_set_data(channel, event);
break;
}
case SWITCH_EVENT_CHANNEL_CREATE:
- sql = switch_mprintf("insert into channels (uuid,direction,created,created_epoch, name,state,dialplan,context,hostname) "
- "values('%q','%q','%q','%ld','%q','%q','%q','%q','%q')",
+ sql = switch_mprintf("insert into channels (uuid,direction,created,created_epoch, name,state,callstate,dialplan,context,hostname) "
+ "values('%q','%q','%q','%ld','%q','%q','%q','%q','%q','%q')",
switch_event_get_header_nil(event, "unique-id"),
switch_event_get_header_nil(event, "call-direction"),
switch_event_get_header_nil(event, "event-date-local"),
(long) switch_epoch_time_now(NULL),
switch_event_get_header_nil(event, "channel-name"),
switch_event_get_header_nil(event, "channel-state"),
+ switch_event_get_header_nil(event, "channel-call-state"),
switch_event_get_header_nil(event, "caller-dialplan"),
switch_event_get_header_nil(event, "caller-context"), switch_core_get_variable("hostname")
);
switch_event_get_header_nil(event, "channel-write-codec-rate"),
switch_event_get_header_nil(event, "unique-id"), switch_core_get_variable("hostname"));
break;
+ case SWITCH_EVENT_CHANNEL_HOLD:
+ case SWITCH_EVENT_CHANNEL_UNHOLD:
case SWITCH_EVENT_CHANNEL_EXECUTE:
- sql = switch_mprintf("update channels set application='%q',application_data='%q',"
+ sql = switch_mprintf("update channels set callstate='%q',application='%q',application_data='%q',"
"presence_id='%q',presence_data='%q' where uuid='%q' and hostname='%q'",
+ switch_event_get_header_nil(event, "channel-call-state"),
switch_event_get_header_nil(event, "application"),
switch_event_get_header_nil(event, "application-data"),
switch_event_get_header_nil(event, "channel-presence-id"),
switch_event_get_header_nil(event, "unique-id"), switch_core_get_variable("hostname")
);
-
break;
case SWITCH_EVENT_CHANNEL_STATE:
{
case CS_DESTROY:
break;
case CS_ROUTING:
- sql = switch_mprintf("update channels set state='%s',cid_name='%q',cid_num='%q',"
+ sql = switch_mprintf("update channels set state='%s',callstate='%q',cid_name='%q',cid_num='%q',"
"ip_addr='%s',dest='%q',dialplan='%q',context='%q',presence_id='%q',presence_data='%q' "
"where uuid='%s' and hostname='%q'",
switch_event_get_header_nil(event, "channel-state"),
+ switch_event_get_header_nil(event, "channel-call-state"),
switch_event_get_header_nil(event, "caller-caller-id-name"),
switch_event_get_header_nil(event, "caller-caller-id-number"),
switch_event_get_header_nil(event, "caller-network-addr"),
switch_event_get_header_nil(event, "unique-id"), switch_core_get_variable("hostname"));
break;
default:
- sql = switch_mprintf("update channels set state='%s' where uuid='%s' and hostname='%q'",
+ sql = switch_mprintf("update channels set state='%s',callstate='%s' where uuid='%s' and hostname='%q'",
switch_event_get_header_nil(event, "channel-state"),
+ switch_event_get_header_nil(event, "channel-call-state"),
switch_event_get_header_nil(event, "unique-id"), switch_core_get_variable("hostname"));
break;
}
" created_epoch INTEGER,\n"
" name VARCHAR(1024),\n"
" state VARCHAR(64),\n"
+ " callstate VARCHAR(64),\n"
" cid_name VARCHAR(1024),\n"
" cid_num VARCHAR(256),\n"
" ip_addr VARCHAR(256),\n"
case SCDB_TYPE_ODBC:
{
char *err;
- switch_cache_db_test_reactive(dbh, "select hostname from channels", "DROP TABLE channels", create_channels_sql);
+ switch_cache_db_test_reactive(dbh, "select callstate from channels", "DROP TABLE channels", create_channels_sql);
switch_cache_db_test_reactive(dbh, "select hostname from calls", "DROP TABLE calls", create_calls_sql);
switch_cache_db_test_reactive(dbh, "select ikey from interfaces", "DROP TABLE interfaces", create_interfaces_sql);
switch_cache_db_test_reactive(dbh, "select hostname from tasks", "DROP TABLE tasks", create_tasks_sql);