diff --git a/conf/autoload_configs/callcenter.conf.xml b/conf/autoload_configs/callcenter.conf.xml
index 156ed374ca..e764d17f15 100644
--- a/conf/autoload_configs/callcenter.conf.xml
+++ b/conf/autoload_configs/callcenter.conf.xml
@@ -10,6 +10,8 @@
       <param name="moh-sound" value="$${hold_music}"/>
       <!--<param name="record-template" value="$${base_dir}/recordings/${strftime(%Y-%m-%d-%H-%M-%S)}.${destination_number}.${caller_id_number}.${uuid}.wav"/>-->
       <param name="time-base-score" value="system"/>
+      <param name="max-wait-time" value="0"/>
+      <param name="max-wait-time-with-no-agent" value="0"/>
       <param name="tier-rules-apply" value="false"/>
       <param name="tier-rule-wait-second" value="300"/>
       <param name="tier-rule-wait-multiply-level" value="true"/>
diff --git a/src/mod/applications/mod_callcenter/mod_callcenter.c b/src/mod/applications/mod_callcenter/mod_callcenter.c
index e56309d005..e08757ba38 100644
--- a/src/mod/applications/mod_callcenter/mod_callcenter.c
+++ b/src/mod/applications/mod_callcenter/mod_callcenter.c
@@ -37,6 +37,7 @@
 #define CC_AGENT_TYPE_UUID_STANDBY "uuid-standby"
 #define CC_SQLITE_DB_NAME "callcenter"
 
+#define CC_MAX_TIME_DIFF_CHECK 5
 /* TODO
    drop caller if no agent login
    dont allow new caller
@@ -53,6 +54,16 @@ SWITCH_MODULE_DEFINITION(mod_callcenter, mod_callcenter_load, mod_callcenter_shu
 
 static const char *global_cf = "callcenter.conf";
 
+struct cc_status_table {
+	const char *name;
+	int status;
+};
+
+struct cc_state_table {
+	const char *name;
+	int state;
+};
+
 typedef enum {
 	CC_STATUS_SUCCESS,
 	CC_STATUS_FALSE,
@@ -77,12 +88,7 @@ typedef enum {
 	CC_TIER_STATE_STANDBY = 5
 } cc_tier_state_t;
 
-struct cc_tier_state_table {
-	const char *name;
-	cc_tier_state_t state;
-};
-
-static struct cc_tier_state_table STATE_CHART[] = {
+static struct cc_state_table STATE_CHART[] = {
 	{"Unknown", CC_TIER_STATE_UNKNOWN},
 	{"No Answer", CC_TIER_STATE_NO_ANSWER},
 	{"Ready", CC_TIER_STATE_READY},
@@ -101,12 +107,7 @@ typedef enum {
 	CC_AGENT_STATUS_ON_BREAK = 4
 } cc_agent_status_t;
 
-struct cc_agent_status_table {
-	const char *name;
-	cc_agent_status_t status;
-};
-
-static struct cc_agent_status_table AGENT_STATUS_CHART[] = {
+static struct cc_status_table AGENT_STATUS_CHART[] = {
 	{"Unknown", CC_AGENT_STATUS_UNKNOWN},
 	{"Logged Out", CC_AGENT_STATUS_LOGGED_OUT},
 	{"Available", CC_AGENT_STATUS_AVAILABLE},
@@ -124,12 +125,7 @@ typedef enum {
 	CC_AGENT_STATE_IDLE = 4
 } cc_agent_state_t;
 
-struct cc_agent_state_table {
-	const char *name;
-	cc_agent_state_t state;
-};
-
-static struct cc_agent_state_table AGENT_STATE_CHART[] = {
+static struct cc_state_table AGENT_STATE_CHART[] = {
 	{"Unknown", CC_AGENT_STATE_UNKNOWN},
 	{"Waiting", CC_AGENT_STATE_WAITING},
 	{"Receiving", CC_AGENT_STATE_RECEIVING},
@@ -147,12 +143,7 @@ typedef enum {
 	CC_MEMBER_STATE_ABANDONED = 4
 } cc_member_state_t;
 
-struct cc_member_state_table {
-	const char *name;
-	cc_member_state_t state;
-};
-
-static struct cc_member_state_table MEMBER_STATE_CHART[] = {
+static struct cc_state_table MEMBER_STATE_CHART[] = {
 	{"Unknown", CC_MEMBER_STATE_UNKNOWN},
 	{"Waiting", CC_MEMBER_STATE_WAITING},
 	{"Trying", CC_MEMBER_STATE_TRYING},
@@ -162,10 +153,24 @@ static struct cc_member_state_table MEMBER_STATE_CHART[] = {
 
 };
 
-/*static char queues_sql[] =
-  "CREATE TABLE queues (\n"
-  "   name	  VARCHAR(255)\n" ");\n";
- */
+struct cc_member_cancel_reason_table {
+	const char *name;
+	int reason;
+};
+
+typedef enum {
+	CC_MEMBER_CANCEL_REASON_NONE,
+	CC_MEMBER_CANCEL_REASON_TIMEOUT,
+	CC_MEMBER_CANCEL_REASON_NO_AGENT_TIMEOUT
+} cc_member_cancel_reason_t;
+
+static struct cc_member_cancel_reason_table MEMBER_CANCEL_REASON_CHART[] = {
+	{"NONE", CC_MEMBER_CANCEL_REASON_NONE},
+	{"TIMEOUT", CC_MEMBER_CANCEL_REASON_TIMEOUT},
+	{"NO_AGENT_TIMEOUT", CC_MEMBER_CANCEL_REASON_NO_AGENT_TIMEOUT},
+	{NULL, 0}
+};
+
 static char members_sql[] =
 "CREATE TABLE members (\n"
 "   queue	     VARCHAR(255),\n"
@@ -222,7 +227,6 @@ static char agents_sql[] =
 "   ready_time INTEGER NOT NULL DEFAULT 0\n"
 ");\n";
 
-
 static char tiers_sql[] =
 "CREATE TABLE tiers (\n"
 "   queue    VARCHAR(255),\n"
@@ -247,7 +251,7 @@ const char * cc_tier_state2str(cc_tier_state_t state)
 	uint8_t x;
 	const char *str = "Unknown";
 
-	for (x = 0; x < (sizeof(STATE_CHART) / sizeof(struct cc_tier_state_table)) - 1; x++) {
+	for (x = 0; x < (sizeof(STATE_CHART) / sizeof(struct cc_state_table)) - 1; x++) {
 		if (STATE_CHART[x].state == state) {
 			str = STATE_CHART[x].name;
 			break;
@@ -262,7 +266,7 @@ cc_tier_state_t cc_tier_str2state(const char *str)
 	uint8_t x;
 	cc_tier_state_t state = CC_TIER_STATE_UNKNOWN;
 
-	for (x = 0; x < (sizeof(STATE_CHART) / sizeof(struct cc_tier_state_table)) - 1 && STATE_CHART[x].name; x++) {
+	for (x = 0; x < (sizeof(STATE_CHART) / sizeof(struct cc_state_table)) - 1 && STATE_CHART[x].name; x++) {
 		if (!strcasecmp(STATE_CHART[x].name, str)) {
 			state = STATE_CHART[x].state;
 			break;
@@ -271,12 +275,41 @@ cc_tier_state_t cc_tier_str2state(const char *str)
 	return state;
 }
 
+const char * cc_member_cancel_reason2str(cc_member_cancel_reason_t reason)
+{
+	uint8_t x;
+	const char *str = "NONE";
+
+	for (x = 0; x < (sizeof(MEMBER_CANCEL_REASON_CHART) / sizeof(struct cc_member_cancel_reason_table)) - 1; x++) {
+		if (MEMBER_CANCEL_REASON_CHART[x].reason == reason) {
+			str = MEMBER_CANCEL_REASON_CHART[x].name;
+			break;
+		}
+	}
+
+	return str;
+}
+
+cc_member_cancel_reason_t cc_member_cancel_str2reason(const char *str)
+{
+	uint8_t x;
+	cc_member_cancel_reason_t reason = CC_MEMBER_CANCEL_REASON_NONE;
+
+	for (x = 0; x < (sizeof(MEMBER_CANCEL_REASON_CHART) / sizeof(struct cc_member_cancel_reason_table)) - 1 && MEMBER_CANCEL_REASON_CHART[x].name; x++) {
+		if (!strcasecmp(MEMBER_CANCEL_REASON_CHART[x].name, str)) {
+			reason = MEMBER_CANCEL_REASON_CHART[x].reason;
+			break;
+		}
+	}
+	return reason;
+}
+
 const char * cc_agent_status2str(cc_agent_status_t status)
 {
 	uint8_t x;
 	const char *str = "Unknown";
 
-	for (x = 0; x < (sizeof(AGENT_STATUS_CHART) / sizeof(struct cc_agent_status_table)) - 1; x++) {
+	for (x = 0; x < (sizeof(AGENT_STATUS_CHART) / sizeof(struct cc_status_table)) - 1; x++) {
 		if (AGENT_STATUS_CHART[x].status == status) {
 			str = AGENT_STATUS_CHART[x].name;
 			break;
@@ -291,7 +324,7 @@ cc_agent_status_t cc_agent_str2status(const char *str)
 	uint8_t x;
 	cc_agent_status_t status = CC_AGENT_STATUS_UNKNOWN;
 
-	for (x = 0; x < (sizeof(AGENT_STATUS_CHART) / sizeof(struct cc_agent_status_table)) - 1 && AGENT_STATUS_CHART[x].name; x++) {
+	for (x = 0; x < (sizeof(AGENT_STATUS_CHART) / sizeof(struct cc_status_table)) - 1 && AGENT_STATUS_CHART[x].name; x++) {
 		if (!strcasecmp(AGENT_STATUS_CHART[x].name, str)) {
 			status = AGENT_STATUS_CHART[x].status;
 			break;
@@ -305,7 +338,7 @@ const char * cc_agent_state2str(cc_agent_state_t state)
 	uint8_t x;
 	const char *str = "Unknown";
 
-	for (x = 0; x < (sizeof(AGENT_STATE_CHART) / sizeof(struct cc_agent_state_table)) - 1; x++) {
+	for (x = 0; x < (sizeof(AGENT_STATE_CHART) / sizeof(struct cc_state_table)) - 1; x++) {
 		if (AGENT_STATE_CHART[x].state == state) {
 			str = AGENT_STATE_CHART[x].name;
 			break;
@@ -320,7 +353,7 @@ cc_agent_state_t cc_agent_str2state(const char *str)
 	uint8_t x;
 	cc_agent_state_t state = CC_AGENT_STATE_UNKNOWN;
 
-	for (x = 0; x < (sizeof(AGENT_STATE_CHART) / sizeof(struct cc_agent_state_table)) - 1 && AGENT_STATE_CHART[x].name; x++) {
+	for (x = 0; x < (sizeof(AGENT_STATE_CHART) / sizeof(struct cc_state_table)) - 1 && AGENT_STATE_CHART[x].name; x++) {
 		if (!strcasecmp(AGENT_STATE_CHART[x].name, str)) {
 			state = AGENT_STATE_CHART[x].state;
 			break;
@@ -334,7 +367,7 @@ const char * cc_member_state2str(cc_member_state_t state)
 	uint8_t x;
 	const char *str = "Unknown";
 
-	for (x = 0; x < (sizeof(MEMBER_STATE_CHART) / sizeof(struct cc_member_state_table)) - 1; x++) {
+	for (x = 0; x < (sizeof(MEMBER_STATE_CHART) / sizeof(struct cc_state_table)) - 1; x++) {
 		if (MEMBER_STATE_CHART[x].state == state) {
 			str = MEMBER_STATE_CHART[x].name;
 			break;
@@ -349,7 +382,7 @@ cc_member_state_t cc_member_str2state(const char *str)
 	uint8_t x;
 	cc_member_state_t state = CC_MEMBER_STATE_UNKNOWN;
 
-	for (x = 0; x < (sizeof(MEMBER_STATE_CHART) / sizeof(struct cc_member_state_table)) - 1 && MEMBER_STATE_CHART[x].name; x++) {
+	for (x = 0; x < (sizeof(MEMBER_STATE_CHART) / sizeof(struct cc_state_table)) - 1 && MEMBER_STATE_CHART[x].name; x++) {
 		if (!strcasecmp(MEMBER_STATE_CHART[x].name, str)) {
 			state = MEMBER_STATE_CHART[x].state;
 			break;
@@ -384,19 +417,27 @@ struct cc_queue {
 	char *moh;
 	char *record_template;
 	char *time_base_score;
+
 	switch_bool_t tier_rules_apply;
 	uint32_t tier_rule_wait_second;
 	switch_bool_t tier_rule_wait_multiply_level;
 	switch_bool_t tier_rule_no_agent_no_wait;
+
 	uint32_t discard_abandoned_after;
 	switch_bool_t abandoned_resume_allowed;
 
+	uint32_t max_wait_time;
+	uint32_t max_wait_time_with_no_agent;
+
 	switch_mutex_t *mutex;
 
 	switch_thread_rwlock_t *rwlock;
 	switch_memory_pool_t *pool;
 	uint32_t flags;
 
+	switch_time_t last_agent_exist;
+	switch_time_t last_agent_exist_check;
+
 	switch_xml_config_item_t config[CC_QUEUE_CONFIGITEM_COUNT];
 	switch_xml_config_string_options_t config_str_pool;
 
@@ -488,6 +529,7 @@ cc_queue_t *queue_set_config(cc_queue_t *queue)
 	SWITCH_CONFIG_SET_ITEM(queue->config[i++], "moh-sound", SWITCH_CONFIG_STRING, 0, &queue->moh, NULL, &queue->config_str_pool, NULL, NULL);
 	SWITCH_CONFIG_SET_ITEM(queue->config[i++], "record-template", SWITCH_CONFIG_STRING, 0, &queue->record_template, NULL, &queue->config_str_pool, NULL, NULL);
 	SWITCH_CONFIG_SET_ITEM(queue->config[i++], "time-base-score", SWITCH_CONFIG_STRING, 0, &queue->time_base_score, "queue", &queue->config_str_pool, NULL, NULL);
+
 	SWITCH_CONFIG_SET_ITEM(queue->config[i++], "tier-rules-apply", SWITCH_CONFIG_BOOL, 0, &queue->tier_rules_apply, SWITCH_FALSE, NULL, NULL, NULL);
 	SWITCH_CONFIG_SET_ITEM(queue->config[i++], "tier-rule-wait-second", SWITCH_CONFIG_INT, 0, &queue->tier_rule_wait_second, 0, &config_int_0_86400, NULL, NULL);
 	SWITCH_CONFIG_SET_ITEM(queue->config[i++], "tier-rule-wait-multiply-level", SWITCH_CONFIG_BOOL, 0, &queue->tier_rule_wait_multiply_level, SWITCH_FALSE, NULL, NULL, NULL);
@@ -495,6 +537,9 @@ cc_queue_t *queue_set_config(cc_queue_t *queue)
 	SWITCH_CONFIG_SET_ITEM(queue->config[i++], "discard-abandoned-after", SWITCH_CONFIG_INT, 0, &queue->discard_abandoned_after, 60, &config_int_0_86400, NULL, NULL);
 	SWITCH_CONFIG_SET_ITEM(queue->config[i++], "abandoned-resume-allowed", SWITCH_CONFIG_BOOL, 0, &queue->abandoned_resume_allowed, SWITCH_FALSE, NULL, NULL, NULL);
 
+	SWITCH_CONFIG_SET_ITEM(queue->config[i++], "max-wait-time", SWITCH_CONFIG_INT, 0, &queue->max_wait_time, 0, &config_int_0_86400, NULL, NULL);
+	SWITCH_CONFIG_SET_ITEM(queue->config[i++], "max-wait-time-with-no-agent", SWITCH_CONFIG_INT, 0, &queue->max_wait_time_with_no_agent, 0, &config_int_0_86400, NULL, NULL);
+
 	switch_assert(i < CC_QUEUE_CONFIGITEM_COUNT);
 
 	return queue;
@@ -646,6 +691,9 @@ static cc_queue_t *load_queue(const char *queue_name)
 		switch_thread_rwlock_create(&queue->rwlock, pool);
 		queue->name = switch_core_strdup(pool, queue_name);
 
+		queue->last_agent_exist = 0;
+		queue->last_agent_exist_check = 0;
+
 		if (!(dbh = cc_get_db_handle())) {
 			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Cannot open DB!\n");
 			goto end;
@@ -702,7 +750,7 @@ static cc_queue_t *get_queue(const char *queue_name)
 
 struct call_helper {
 	const char *member_uuid;
-	const char *queue;
+	const char *queue_name;
 	const char *queue_strategy;
 	const char *member_joined_epoch;
 	const char *member_caller_name;
@@ -744,7 +792,7 @@ int cc_queue_count(const char *queue)
 		count = atoi(res);
 
 		if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, CALLCENTER_EVENT) == SWITCH_STATUS_SUCCESS) {
-			switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Name", queue);
+			switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Queue", queue);
 			switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Action", "members-count");
 			switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Count", res);
 			switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Selection", event_name);
@@ -827,7 +875,7 @@ cc_agent_status_t cc_agent_get(const char *key, const char *agent, char *ret_res
 		result = CC_STATUS_SUCCESS;
 
 		if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, CALLCENTER_EVENT) == SWITCH_STATUS_SUCCESS) {
-			switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Name", agent);
+			switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Agent", agent);
 			switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Action", "agent-status-get");
 			switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Agent-Status", res);
 			switch_event_fire(&event);
@@ -894,7 +942,7 @@ cc_status_t cc_agent_update(const char *key, const char *value, const char *agen
 			result = CC_STATUS_SUCCESS;
 
 			if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, CALLCENTER_EVENT) == SWITCH_STATUS_SUCCESS) {
-				switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Name", agent);
+				switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Agent", agent);
 				switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Action", "agent-status-change");
 				switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Agent-Status", value);
 				switch_event_fire(&event);
@@ -918,7 +966,7 @@ cc_status_t cc_agent_update(const char *key, const char *value, const char *agen
 			result = CC_STATUS_SUCCESS;
 
 			if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, CALLCENTER_EVENT) == SWITCH_STATUS_SUCCESS) {
-				switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Name", agent);
+				switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Agent", agent);
 				switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Action", "agent-state-change");
 				switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Agent-State", value);
 				switch_event_fire(&event);
@@ -1118,13 +1166,13 @@ done:
 	return result;
 }
 
-cc_status_t cc_tier_del(const char *queue, const char *agent)
+cc_status_t cc_tier_del(const char *queue_name, const char *agent)
 {
 	cc_status_t result = CC_STATUS_SUCCESS;
 	char *sql;
 
-	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Deleted tier Agent %s in Queue %s\n", agent, queue);
-	sql = switch_mprintf("DELETE FROM tiers WHERE queue = '%q' AND agent = '%q';", queue, agent);
+	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Deleted tier Agent %s in Queue %s\n", agent, queue_name);
+	sql = switch_mprintf("DELETE FROM tiers WHERE queue = '%q' AND agent = '%q';", queue_name, agent);
 	cc_execute_sql(NULL, sql, NULL);
 	switch_safe_free(sql);
 
@@ -1307,7 +1355,7 @@ static void *SWITCH_THREAD_FUNC outbound_agent_thread_run(switch_thread_t *threa
 	}
 	if (!strcasecmp(h->agent_type, CC_AGENT_TYPE_CALLBACK)) {
 		switch_event_create(&ovars, SWITCH_EVENT_REQUEST_PARAMS);
-		switch_event_add_header(ovars, SWITCH_STACK_BOTTOM, "cc_queue", "%s", h->queue);
+		switch_event_add_header(ovars, SWITCH_STACK_BOTTOM, "cc_queue", "%s", h->queue_name);
 		switch_event_add_header(ovars, SWITCH_STACK_BOTTOM, "cc_member_uuid", "%s", h->member_uuid);
 		switch_event_add_header(ovars, SWITCH_STACK_BOTTOM, "cc_member_pre_answer_uuid", "%s", h->member_uuid);
 		switch_event_add_header(ovars, SWITCH_STACK_BOTTOM, "cc_agent", "%s", h->agent_name);
@@ -1327,7 +1375,7 @@ static void *SWITCH_THREAD_FUNC outbound_agent_thread_run(switch_thread_t *threa
 			switch_event_t *event;
 			const char *cc_warning_tone = switch_channel_get_variable(agent_channel, "cc_warning_tone");
 
-			switch_channel_set_variable(agent_channel, "cc_queue", h->queue);
+			switch_channel_set_variable(agent_channel, "cc_queue", h->queue_name);
 			switch_channel_set_variable(agent_channel, "cc_agent", h->agent_name);
 			switch_channel_set_variable(agent_channel, "cc_agent_type", h->agent_type);
 			switch_channel_set_variable(agent_channel, "cc_member_uuid", h->member_uuid);
@@ -1384,7 +1432,7 @@ static void *SWITCH_THREAD_FUNC outbound_agent_thread_run(switch_thread_t *threa
 
 		if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, CALLCENTER_EVENT) == SWITCH_STATUS_SUCCESS) {
 			switch_channel_event_set_data(agent_channel, event);
-			switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Name", h->queue);
+			switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Queue", h->queue_name);
 			switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Action", "bridge-agent-start");
 			switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Agent", h->agent_name);
 			switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Agent-System", h->agent_system);
@@ -1407,11 +1455,7 @@ static void *SWITCH_THREAD_FUNC outbound_agent_thread_run(switch_thread_t *threa
 		switch_safe_free(sql);
 
 		/* Change the agents Status in the tiers */
-		sql = switch_mprintf("UPDATE tiers SET state = '%q' WHERE agent = '%q' AND queue = '%q'",
-				cc_tier_state2str(CC_TIER_STATE_ACTIVE_INBOUND), h->agent_name, h->queue);
-		cc_execute_sql(NULL, sql, NULL);
-		switch_safe_free(sql);
-
+		cc_tier_update("state", cc_tier_state2str(CC_TIER_STATE_ACTIVE_INBOUND), h->queue_name, h->agent_name);
 		cc_agent_update("state", cc_agent_state2str(CC_AGENT_STATE_IN_A_QUEUE_CALL), h->agent_name);
 
 		/* Record session if record-template is provided */
@@ -1424,10 +1468,13 @@ static void *SWITCH_THREAD_FUNC outbound_agent_thread_run(switch_thread_t *threa
 			}					
 		}
 
-		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Agent %s answered \"%s\" (%s) from queue %s%s\n",
-				h->agent_name, h->member_caller_name, h->member_caller_number, h->queue, (h->record_template?" (Recorded)":""));
+		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Agent %s answered \"%s\" <%s> from queue %s%s\n",
+				h->agent_name, h->member_caller_name, h->member_caller_number, h->queue_name, (h->record_template?" (Recorded)":""));
 		switch_ivr_uuid_bridge(h->member_uuid, switch_core_session_get_uuid(agent_session));
 
+		/* This is used for the waiting caller to quit waiting for a agent */
+		switch_channel_set_variable(member_channel, "cc_agent_uuid", agent_uuid);
+
 		/* Wait until the member hangup or the agent hangup.  This will quit also if the agent transfer the call */
 		while(switch_channel_up(member_channel) && switch_channel_up(agent_channel) && globals.running) {
 			switch_yield(100000);
@@ -1436,7 +1483,7 @@ static void *SWITCH_THREAD_FUNC outbound_agent_thread_run(switch_thread_t *threa
 
 		if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, CALLCENTER_EVENT) == SWITCH_STATUS_SUCCESS) {
 			switch_channel_event_set_data(agent_channel, event);
-			switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Name", h->queue);
+			switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Queue", h->queue_name);
 			switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Action", "bridge-agent-end");
 			switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Agent", h->agent_name);
 			switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Agent-System", h->agent_system);
@@ -1452,7 +1499,7 @@ static void *SWITCH_THREAD_FUNC outbound_agent_thread_run(switch_thread_t *threa
 		/* Update Agents Items */
 		/* Do not remove uuid of the agent if we are a standby agent */
 		sql = switch_mprintf("UPDATE agents SET %q last_bridge_end = %ld, talk_time = talk_time + (%ld-last_bridge_start) WHERE name = '%q' AND system = '%q';"
-				, (strcasecmp(h->agent_type, "uuid-standby")?"uuid = '',":""),  (long) switch_epoch_time_now(NULL), (long) switch_epoch_time_now(NULL), h->agent_name, h->agent_system);
+				, (strcasecmp(h->agent_type, CC_AGENT_TYPE_UUID_STANDBY)?"uuid = '',":""),  (long) switch_epoch_time_now(NULL), (long) switch_epoch_time_now(NULL), h->agent_name, h->agent_system);
 		cc_execute_sql(NULL, sql, NULL);
 		switch_safe_free(sql);
 
@@ -1464,7 +1511,7 @@ static void *SWITCH_THREAD_FUNC outbound_agent_thread_run(switch_thread_t *threa
 		/* Caller off event */
 		if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, CALLCENTER_EVENT) == SWITCH_STATUS_SUCCESS) {
 			switch_channel_event_set_data(member_channel, event);
-			switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Name", h->queue);
+			switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Queue", h->queue_name);
 			switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Action", "member-queue-end");
 			switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Cause", "Terminated");
 			switch_event_add_header(event, SWITCH_STACK_BOTTOM, "CC-Agent-Answer-Time", "%ld",  (long) (t_agent_answered - t_agent_called));
@@ -1472,8 +1519,10 @@ static void *SWITCH_THREAD_FUNC outbound_agent_thread_run(switch_thread_t *threa
 			switch_event_add_header(event, SWITCH_STACK_BOTTOM, "CC-Talk-Time", "%ld",  (long) (switch_epoch_time_now(NULL) - t_agent_answered));
 			switch_event_add_header(event, SWITCH_STACK_BOTTOM, "CC-Total-Time", "%ld",  (long) (switch_epoch_time_now(NULL) - t_member_called));
 			switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Caller-UUID", h->member_uuid);
-			switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Caller-CID-Name", switch_str_nil(switch_channel_get_variable(member_channel, "caller_id_name")));
-			switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Caller-CID-Number", switch_str_nil(switch_channel_get_variable(member_channel, "caller_id_number")));
+			switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Caller-CID-Name",
+					switch_str_nil(switch_channel_get_variable(member_channel, "caller_id_name")));
+			switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Caller-CID-Number",
+					switch_str_nil(switch_channel_get_variable(member_channel, "caller_id_number")));
 			switch_event_fire(&event);
 		}
 
@@ -1538,8 +1587,8 @@ done:
 	sql = switch_mprintf(
 			"UPDATE tiers SET state = '%q' WHERE agent = '%q' AND queue = '%q' AND (state = '%q' OR state = '%q' OR state = '%q');"
 			"UPDATE tiers SET state = '%q' WHERE agent = '%q' AND NOT queue = '%q' AND state = '%q'"
-			, cc_tier_state2str(tiers_state), h->agent_name, h->queue, cc_tier_state2str(CC_TIER_STATE_ACTIVE_INBOUND), cc_tier_state2str(CC_TIER_STATE_STANDBY), cc_tier_state2str(CC_TIER_STATE_OFFERING),
-			cc_tier_state2str(CC_TIER_STATE_READY), h->agent_name, h->queue, cc_tier_state2str(CC_TIER_STATE_STANDBY));
+			, cc_tier_state2str(tiers_state), h->agent_name, h->queue_name, cc_tier_state2str(CC_TIER_STATE_ACTIVE_INBOUND), cc_tier_state2str(CC_TIER_STATE_STANDBY), cc_tier_state2str(CC_TIER_STATE_OFFERING),
+			cc_tier_state2str(CC_TIER_STATE_READY), h->agent_name, h->queue_name, cc_tier_state2str(CC_TIER_STATE_STANDBY));
 	cc_execute_sql(NULL, sql, NULL);
 	switch_safe_free(sql);
 
@@ -1567,7 +1616,7 @@ done:
 }
 
 struct agent_callback {
-	const char *queue;
+	const char *queue_name;
 	const char *system;
 	const char *uuid;
 	const char *caller_number;
@@ -1579,6 +1628,7 @@ struct agent_callback {
 	uint32_t tier_rule_wait_second;
 	switch_bool_t tier_rule_wait_multiply_level;
 	switch_bool_t tier_rule_no_agent_no_wait;
+	switch_bool_t agent_found;
 
 	int tier;
 	int tier_agent_available;
@@ -1602,6 +1652,8 @@ static int agents_callback(void *pArg, int argc, char **argv, char **columnNames
 
 	switch_bool_t contact_agent = SWITCH_TRUE;
 
+	cbt->agent_found = SWITCH_TRUE;
+
 	/* Check if we switch to a different tier, if so, check if we should continue further for that member */
 
 	if (cbt->tier_rules_apply == SWITCH_TRUE && atoi(agent_tier_level) > cbt->tier) {
@@ -1700,7 +1752,7 @@ static int agents_callback(void *pArg, int argc, char **argv, char **columnNames
 				h->member_joined_epoch = switch_core_strdup(h->pool, cbt->joined_epoch); 
 				h->member_caller_name = switch_core_strdup(h->pool, cbt->caller_name);
 				h->member_caller_number = switch_core_strdup(h->pool, cbt->caller_number);
-				h->queue = switch_core_strdup(h->pool, cbt->queue);
+				h->queue_name = switch_core_strdup(h->pool, cbt->queue_name);
 				h->record_template = switch_core_strdup(h->pool, cbt->record_template);
 				h->no_answer_count = atoi(argv[4]);
 				h->max_no_answer = atoi(argv[5]);
@@ -1713,8 +1765,8 @@ static int agents_callback(void *pArg, int argc, char **argv, char **columnNames
 				sql = switch_mprintf(
 						"UPDATE tiers SET state = '%q' WHERE agent = '%q' AND queue = '%q';"
 						"UPDATE tiers SET state = '%q' WHERE agent = '%q' AND NOT queue = '%q' AND state = '%q';",
-						cc_tier_state2str(CC_TIER_STATE_OFFERING), h->agent_name, h->queue,
-						cc_tier_state2str(CC_TIER_STATE_STANDBY), h->agent_name, h->queue, cc_tier_state2str(CC_TIER_STATE_READY));
+						cc_tier_state2str(CC_TIER_STATE_OFFERING), h->agent_name, h->queue_name,
+						cc_tier_state2str(CC_TIER_STATE_STANDBY), h->agent_name, h->queue_name, cc_tier_state2str(CC_TIER_STATE_READY));
 				cc_execute_sql(NULL, sql, NULL);
 				switch_safe_free(sql);
 
@@ -1796,9 +1848,10 @@ static int members_callback(void *pArg, int argc, char **argv, char **columnName
 	cbt.caller_number = argv[2];
 	cbt.caller_name = argv[3];
 	cbt.joined_epoch = argv[4];
-	cbt.queue = argv[0];
+	cbt.queue_name = argv[0];
 	cbt.strategy = queue_strategy;
 	cbt.record_template = queue_record_template;
+	cbt.agent_found = SWITCH_FALSE;
 	
 	if (!strcasecmp(queue->strategy, "longest-idle-agent")) {
 		sql_order_by = switch_mprintf("level, agents.last_offered_call, position");
@@ -1832,6 +1885,18 @@ static int members_callback(void *pArg, int argc, char **argv, char **columnName
 	switch_safe_free(sql);
 	switch_safe_free(sql_order_by);
 
+	/* We update a field in the queue struct so we can kick caller out if waiting for too long with no agent */
+	if (!argv[0] || !(queue = get_queue(argv[0]))) {
+		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Queue %s not found locally, skip this member\n", argv[0]);
+		goto end;
+	} else {
+		queue->last_agent_exist_check = switch_epoch_time_now(NULL);
+		if (cbt.agent_found) {
+			queue->last_agent_exist = queue->last_agent_exist_check;
+		}
+		queue_rwunlock(queue);
+	}
+
 end:
 	switch_safe_free(queue_name);
 	switch_safe_free(queue_strategy);
@@ -1911,30 +1976,53 @@ void cc_agent_dispatch_thread_start(void)
 	switch_thread_create(&thread, thd_attr, cc_agent_dispatch_thread_run, NULL, globals.pool);
 }
 
-struct member_helper {
-	const char *uuid;
+struct member_thread_helper {
+	const char *member_uuid;
+	const char *queue_name;
+	switch_time_t t_member_called;
+	cc_member_cancel_reason_t member_cancel_reason;
+
 	int running;
 	switch_memory_pool_t *pool;
 };
 
 void *SWITCH_THREAD_FUNC cc_member_thread_run(switch_thread_t *thread, void *obj)
 {
-	struct member_helper *m = (struct member_helper *) obj;
-	switch_core_session_t *member_session = switch_core_session_locate(m->uuid);
-	switch_channel_t *channel = NULL;
+	struct member_thread_helper *m = (struct member_thread_helper *) obj;
+	switch_core_session_t *member_session = switch_core_session_locate(m->member_uuid);
+	switch_channel_t *member_channel = NULL;
 
 	switch_mutex_lock(globals.mutex);
 	globals.threads++;
 	switch_mutex_unlock(globals.mutex);
 
 	if (member_session) {
-		channel = switch_core_session_get_channel(member_session);
+		member_channel = switch_core_session_get_channel(member_session);
 	} else {
 		switch_core_destroy_memory_pool(&m->pool);
 		return NULL;
 	}
 
-	while(switch_channel_ready(channel) && m->running && globals.running) {
+	while(switch_channel_ready(member_channel) && m->running && globals.running) {
+		cc_queue_t *queue = NULL;
+
+		if (!m->queue_name || !(queue = get_queue(m->queue_name))) {
+			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Queue %s not found\n", m->queue_name);
+			break;
+		}
+		/* Make the Caller Leave if he went over his max wait time */
+		if (queue->max_wait_time > 0 && queue->max_wait_time <= switch_epoch_time_now(NULL) - m->t_member_called) {
+			m->member_cancel_reason = CC_MEMBER_CANCEL_REASON_TIMEOUT;
+			switch_channel_set_flag_value(member_channel, CF_BREAK, 2);
+		}
+
+		/* Will drop the caller if no agent was found for more than X secondes */
+		if (queue->max_wait_time_with_no_agent > 0 && m->t_member_called < queue->last_agent_exist_check - CC_MAX_TIME_DIFF_CHECK &&
+				queue->last_agent_exist_check - queue->last_agent_exist >= queue->max_wait_time_with_no_agent) {
+			m->member_cancel_reason = CC_MEMBER_CANCEL_REASON_NO_AGENT_TIMEOUT;
+			switch_channel_set_flag_value(member_channel, CF_BREAK, 2);
+		}
+
 		/* TODO Go thought the list of phrases */
 		/* SAMPLE CODE to playback something over the MOH
 
@@ -1949,8 +2037,12 @@ void *SWITCH_THREAD_FUNC cc_member_thread_run(switch_thread_t *thread, void *obj
 
 		/* If Agent Logoff, we might need to recalculare score based on skill */
 		/* Play Announcement in order */
-		switch_yield(100000);
+
+		queue_rwunlock(queue);
+
+		switch_yield(500000);
 	}
+
 	switch_core_session_rwunlock(member_session);
 	switch_core_destroy_memory_pool(&m->pool);
 
@@ -1971,26 +2063,27 @@ SWITCH_STANDARD_APP(callcenter_function)
 	char *mydata = NULL;
 	cc_queue_t *queue = NULL;
 	const char *queue_name = NULL;
-	switch_channel_t *member_channel = switch_core_session_get_channel(session);
+	switch_core_session_t *member_session = session;
+	switch_channel_t *member_channel = switch_core_session_get_channel(member_session);
 	char *sql = NULL;
-	char *uuid = switch_core_session_get_uuid(session);
-	switch_input_args_t args = { 0 };
-	struct member_helper *h = NULL;
+	char *member_uuid = switch_core_session_get_uuid(member_session);
+	struct member_thread_helper *h = NULL;
 	switch_thread_t *thread;
 	switch_threadattr_t *thd_attr = NULL;
 	switch_memory_pool_t *pool;
-	int cc_base_score_int = 0;
 	switch_channel_timetable_t *times = NULL;
-	const char *cc_base_score = switch_channel_get_variable(member_channel, "cc_base_score");
 	const char *cc_moh_override = switch_channel_get_variable(member_channel, "cc_moh_override");
+	const char *cc_base_score = switch_channel_get_variable(member_channel, "cc_base_score");
+	int cc_base_score_int = 0;
 	const char *cur_moh = NULL;
 	char start_epoch[64];
 	switch_event_t *event;
 	switch_time_t t_member_called = switch_epoch_time_now(NULL);
 	long abandoned_epoch = 0;
+	const char *agent_uuid = NULL;
 
 	if (!zstr(data)) {
-		mydata = switch_core_session_strdup(session, data);
+		mydata = switch_core_session_strdup(member_session, data);
 		argc = switch_separate_string(mydata, ' ', argv, (sizeof(argv) / sizeof(argv[0])));
 	} else {
 		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "No Queue name provided\n");
@@ -2013,7 +2106,7 @@ SWITCH_STANDARD_APP(callcenter_function)
 	times = switch_channel_get_timetable(member_channel);
 	switch_snprintf(start_epoch, sizeof(start_epoch), "%" SWITCH_TIME_T_FMT, times->answered / 1000000);
 
-	/* Check of we have a queued abandoned member we can resume from */
+	/* Check if we support and have a queued abandoned member we can resume from */
 	if (queue->abandoned_resume_allowed == SWITCH_TRUE) {
 		char res[256];
 
@@ -2037,9 +2130,9 @@ SWITCH_STANDARD_APP(callcenter_function)
 
 	if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, CALLCENTER_EVENT) == SWITCH_STATUS_SUCCESS) {
 		switch_channel_event_set_data(member_channel, event);
-		switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Name", queue_name);
+		switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Queue", queue_name);
 		switch_event_add_header(event, SWITCH_STACK_BOTTOM, "CC-Action", "member-queue-%s", (abandoned_epoch==0?"start":"resume"));
-		switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Caller-UUID", uuid);
+		switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Caller-UUID", member_uuid);
 		switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Caller-CID-Name", switch_str_nil(switch_channel_get_variable(member_channel, "caller_id_name")));
 		switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Caller-CID-Number", switch_str_nil(switch_channel_get_variable(member_channel, "caller_id_number")));
 		switch_event_fire(&event);
@@ -2054,7 +2147,7 @@ SWITCH_STANDARD_APP(callcenter_function)
 				" (queue,system,uuid,system_epoch,joined_epoch,base_score,skill_score,caller_number,caller_name,serving_agent,serving_system,state)"
 				" VALUES('%q','single_box','%q','%q','%ld','%d','%d','%q','%q','%q','','%q')", 
 				queue_name,
-				uuid,
+				member_uuid,
 				start_epoch,
 				(long) switch_epoch_time_now(NULL),
 				cc_base_score_int,
@@ -2069,12 +2162,12 @@ SWITCH_STANDARD_APP(callcenter_function)
 		char res[256];
 		/* Update abandoned member */
 		sql = switch_mprintf("UPDATE members SET uuid = '%q', state = '%q', rejoined_epoch = '%ld' WHERE caller_number = '%q' AND abandoned_epoch = '%ld' AND state = '%q' AND queue = '%q'",
-				uuid, cc_member_state2str(CC_MEMBER_STATE_WAITING), (long) switch_epoch_time_now(NULL), switch_str_nil(switch_channel_get_variable(member_channel, "caller_id_number")), abandoned_epoch, cc_member_state2str(CC_MEMBER_STATE_ABANDONED), queue_name); 
+				member_uuid, cc_member_state2str(CC_MEMBER_STATE_WAITING), (long) switch_epoch_time_now(NULL), switch_str_nil(switch_channel_get_variable(member_channel, "caller_id_number")), abandoned_epoch, cc_member_state2str(CC_MEMBER_STATE_ABANDONED), queue_name); 
 		cc_execute_sql(queue, sql, NULL);
 		switch_safe_free(sql);
 
 		/* Confirm we took that member in */
-		sql = switch_mprintf("SELECT abandoned_epoch FROM members WHERE uuid = '%q' AND state = '%q' AND queue = '%q'", uuid, cc_member_state2str(CC_MEMBER_STATE_WAITING), queue_name);
+		sql = switch_mprintf("SELECT abandoned_epoch FROM members WHERE uuid = '%q' AND state = '%q' AND queue = '%q'", member_uuid, cc_member_state2str(CC_MEMBER_STATE_WAITING), queue_name);
 		cc_execute_sql2str(NULL, NULL, sql, res, sizeof(res));
 		switch_safe_free(sql);
 
@@ -2092,9 +2185,14 @@ SWITCH_STANDARD_APP(callcenter_function)
 	/* Start Thread that will playback different prompt to the channel */
 	switch_core_new_memory_pool(&pool);
 	h = switch_core_alloc(pool, sizeof(*h));
+
 	h->pool = pool;
-	h->uuid = switch_core_strdup(h->pool, uuid);
+	h->member_uuid = switch_core_strdup(h->pool, member_uuid);
+	h->queue_name = switch_core_strdup(h->pool, queue_name);
+	h->t_member_called = t_member_called;
+	h->member_cancel_reason = CC_MEMBER_CANCEL_REASON_NONE;
 	h->running = 1;
+
 	switch_threadattr_create(&thd_attr, h->pool);
 	switch_threadattr_detach_set(thd_attr, 1);
 	switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE);
@@ -2104,16 +2202,37 @@ SWITCH_STANDARD_APP(callcenter_function)
 	/* TODO Add DTMF callback support */
 	/* TODO add MOH infitite loop */	
 	if (cc_moh_override) {
-		cur_moh = switch_core_session_strdup(session, cc_moh_override);
+		cur_moh = switch_core_session_strdup(member_session, cc_moh_override);
 	} else {
-		cur_moh = switch_core_session_strdup(session, queue->moh);
+		cur_moh = switch_core_session_strdup(member_session, queue->moh);
 	}
 	queue_rwunlock(queue);
 
-	if (cur_moh) {
-		switch_ivr_play_file(session, NULL, cur_moh, &args);
-	} else {
-		switch_ivr_collect_digits_callback(session, &args, 0, 0);
+	while (switch_channel_ready(member_channel)) {
+		switch_input_args_t args = { 0 };
+
+		/* An agent was found, time to exit and let the bridge do it job */
+		if ((agent_uuid = switch_channel_get_variable(member_channel, "cc_agent_uuid"))) {
+			break;
+		}
+		/* If the member thread set a different reason, we monitor it so we can quit the wait */
+		if (h->member_cancel_reason != CC_MEMBER_CANCEL_REASON_NONE) {
+			break;
+		}
+
+		switch_core_session_flush_private_events(member_session);
+
+		if (cur_moh) {
+			switch_status_t status = switch_ivr_play_file(member_session, NULL, cur_moh, &args);
+
+			if (!SWITCH_READ_ACCEPTABLE(status)) {
+				break;
+			}
+
+		} else {
+			switch_ivr_collect_digits_callback(session, &args, 0, 0);
+		}
+
 	}
 
 	/* Stop Member Thread */
@@ -2123,33 +2242,42 @@ SWITCH_STANDARD_APP(callcenter_function)
 
 	/* Hangup any agents been callback */
 	if (!switch_channel_up(member_channel)) { /* If channel is still up, it mean that the member didn't hangup, so we should leave the agent alone */
-		switch_core_session_hupall_matching_var("cc_member_uuid", uuid, SWITCH_CAUSE_ORIGINATOR_CANCEL);
+		switch_core_session_hupall_matching_var("cc_member_uuid", member_uuid, SWITCH_CAUSE_ORIGINATOR_CANCEL);
 		sql = switch_mprintf("UPDATE members SET state = '%q', uuid = '', abandoned_epoch = '%ld' WHERE system = 'single_box' AND uuid = '%q'",
-				cc_member_state2str(CC_MEMBER_STATE_ABANDONED), (long) switch_epoch_time_now(NULL), uuid);
+				cc_member_state2str(CC_MEMBER_STATE_ABANDONED), (long) switch_epoch_time_now(NULL), member_uuid);
 				cc_execute_sql(NULL, sql, NULL);
 		switch_safe_free(sql);
 
+		/* Generate an Event and update some channel variable */
 		if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, CALLCENTER_EVENT) == SWITCH_STATUS_SUCCESS) {
 			switch_channel_event_set_data(member_channel, event);
-			switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Name", queue_name);
+			switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Queue", queue_name);
 			switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Action", "member-queue-end");
 			switch_event_add_header(event, SWITCH_STACK_BOTTOM, "CC-Wait-Time", "%ld", (long) (switch_epoch_time_now(NULL) - t_member_called));
-			switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Cause", "Abort");
-			switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Caller-UUID", uuid);
+			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Member \"%s\" <%s> exit queue %s due to %s\n",
+					switch_str_nil(switch_channel_get_variable(member_channel, "caller_id_name")),
+					switch_str_nil(switch_channel_get_variable(member_channel, "caller_id_number")),
+					queue_name, cc_member_cancel_reason2str(h->member_cancel_reason));
+
+			switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Cause", cc_member_cancel_reason2str(h->member_cancel_reason));
+			switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Caller-UUID", member_uuid);
 			switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Caller-CID-Name", switch_str_nil(switch_channel_get_variable(member_channel, "caller_id_name")));
 			switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Caller-CID-Number", switch_str_nil(switch_channel_get_variable(member_channel, "caller_id_number")));
 			switch_event_fire(&event);
 		}
+
 		/* for xml_cdr needs */
 		switch_channel_set_variable_printf(member_channel, "cc_queue_canceled_epoch", "%ld", (long) switch_epoch_time_now(NULL));
+		switch_channel_set_variable_printf(member_channel, "cc_cause", "%s", cc_member_cancel_reason2str(h->member_cancel_reason));
 
 
 		/* Send Event with queue count */
 		cc_queue_count(queue_name);
 
 	} else {
+		switch_channel_set_variable_printf(member_channel, "cc_cause", "%s", "answered");
 		sql = switch_mprintf("UPDATE members SET state = '%q', bridge_epoch = '%ld' WHERE system = 'single_box' AND uuid = '%q'",
-				cc_member_state2str(CC_MEMBER_STATE_ANSWERED), (long) switch_epoch_time_now(NULL), uuid);
+				cc_member_state2str(CC_MEMBER_STATE_ANSWERED), (long) switch_epoch_time_now(NULL), member_uuid);
 		cc_execute_sql(NULL, sql, NULL);
 		switch_safe_free(sql);
 
@@ -2525,7 +2653,7 @@ SWITCH_STANDARD_API(cc_config_api_function)
 				stream->write_function(stream, "%d\n", atoi(res));
 
 				if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, CALLCENTER_EVENT) == SWITCH_STATUS_SUCCESS) {
-					switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Name", queue_name);
+					switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Queue", queue_name);
 					switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Action", "members-count");
 					switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Count", res);
 					switch_event_fire(&event);