From 0f133eae2db4d597e34acf56380ab1cc31bf94be Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Fri, 4 Jun 2010 19:03:36 -0500 Subject: [PATCH] add new callstate field to channels table --- src/include/switch_channel.h | 6 ++ src/include/switch_types.h | 12 +++ src/mod/endpoints/mod_sofia/sofia_glue.c | 3 + src/switch_channel.c | 105 +++++++++++++++++++++++ src/switch_core_sqldb.c | 20 +++-- 5 files changed, 139 insertions(+), 7 deletions(-) diff --git a/src/include/switch_channel.h b/src/include/switch_channel.h index 775bf91e92..58b38312f2 100644 --- a/src/include/switch_channel.h +++ b/src/include/switch_channel.h @@ -560,6 +560,12 @@ SWITCH_DECLARE(char *) switch_channel_get_flag_string(switch_channel_t *channel) 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 diff --git a/src/include/switch_types.h b/src/include/switch_types.h index 55cd26c148..02f21a04d3 100644 --- a/src/include/switch_types.h +++ b/src/include/switch_types.h @@ -875,6 +875,16 @@ typedef uint32_t switch_core_session_message_flag_t; #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) @@ -1337,6 +1347,8 @@ typedef enum { 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, diff --git a/src/mod/endpoints/mod_sofia/sofia_glue.c b/src/mod/endpoints/mod_sofia/sofia_glue.c index 0a65752bba..002687884b 100644 --- a/src/mod/endpoints/mod_sofia/sofia_glue.c +++ b/src/mod/endpoints/mod_sofia/sofia_glue.c @@ -3323,6 +3323,7 @@ void sofia_glue_toggle_hold(private_object_t *tech_pvt, int sendonly) 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) { @@ -3349,6 +3350,7 @@ void sofia_glue_toggle_hold(private_object_t *tech_pvt, int sendonly) 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); @@ -3380,6 +3382,7 @@ void sofia_glue_toggle_hold(private_object_t *tech_pvt, int sendonly) 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); } } diff --git a/src/switch_channel.c b/src/switch_channel.c index 2b34c6bd72..49dd06d054 100644 --- a/src/switch_channel.c +++ b/src/switch_channel.c @@ -122,6 +122,7 @@ struct switch_channel { 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]; @@ -139,6 +140,7 @@ struct switch_channel { opaque_channel_flag_t opaque_flags; }; + SWITCH_DECLARE(const char *) switch_channel_cause2str(switch_call_cause_t cause) { uint8_t x; @@ -178,6 +180,68 @@ SWITCH_DECLARE(switch_call_cause_t) switch_channel_get_cause(switch_channel_t *c } +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)) { @@ -537,6 +601,23 @@ SWITCH_DECLARE(void) switch_channel_presence(switch_channel_t *channel, const ch } } +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; @@ -1134,6 +1215,12 @@ SWITCH_DECLARE(void) switch_channel_set_flag_value(switch_channel_t *channel, sw 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) @@ -1221,6 +1308,10 @@ SWITCH_DECLARE(void) switch_channel_clear_flag(switch_channel_t *channel, switch if (flag == CF_OUTBOUND) { switch_channel_set_variable(channel, "is_outbound", NULL); } + + if (flag == CF_LEG_HOLDING) { + switch_channel_set_callstate(channel, CCS_ACTIVE); + } } @@ -1357,11 +1448,21 @@ SWITCH_DECLARE(switch_channel_state_t) switch_channel_perform_set_running_state( 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)); @@ -1622,6 +1723,7 @@ SWITCH_DECLARE(void) switch_channel_event_set_basic_data(switch_channel_t *chann } 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)); @@ -2134,6 +2236,7 @@ SWITCH_DECLARE(switch_channel_state_t) switch_channel_perform_hangup(switch_chan 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)); @@ -2219,6 +2322,7 @@ SWITCH_DECLARE(switch_status_t) switch_channel_perform_mark_pre_answered(switch_ 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); @@ -2360,6 +2464,7 @@ SWITCH_DECLARE(switch_status_t) switch_channel_perform_mark_answered(switch_chan } 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); diff --git a/src/switch_core_sqldb.c b/src/switch_core_sqldb.c index e7a2d2822e..061c77fccc 100644 --- a/src/switch_core_sqldb.c +++ b/src/switch_core_sqldb.c @@ -977,14 +977,15 @@ static void core_event_handler(switch_event_t *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") ); @@ -999,9 +1000,12 @@ static void core_event_handler(switch_event_t *event) 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"), @@ -1009,7 +1013,6 @@ static void core_event_handler(switch_event_t *event) switch_event_get_header_nil(event, "unique-id"), switch_core_get_variable("hostname") ); - break; case SWITCH_EVENT_CHANNEL_STATE: { @@ -1025,10 +1028,11 @@ static void core_event_handler(switch_event_t *event) 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"), @@ -1040,8 +1044,9 @@ static void core_event_handler(switch_event_t *event) 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; } @@ -1186,6 +1191,7 @@ static char create_channels_sql[] = " 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" @@ -1323,7 +1329,7 @@ switch_status_t switch_core_sqldb_start(switch_memory_pool_t *pool, switch_bool_ 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);