Revision
16789
Author
sathieu
Date
2010-02-24 06:05:45 -0600 (Wed, 24 Feb 2010)

Log Message

Skinny: Corrections
- Construct call_id based on simple increment per profile
- close RTP only if needed
- now hanging up while there is no other leg works
- better steps: create_session -> process_dest -> answer

Modified Paths

Diff

Modified: freeswitch/trunk/src/mod/endpoints/mod_skinny/mod_skinny.c (16788 => 16789)


--- freeswitch/trunk/src/mod/endpoints/mod_skinny/mod_skinny.c	2010-02-24 12:05:34 UTC (rev 16788)
+++ freeswitch/trunk/src/mod/endpoints/mod_skinny/mod_skinny.c	2010-02-24 12:05:45 UTC (rev 16789)
@@ -381,13 +381,19 @@
 	return status;
 }
 
-void tech_init(private_t *tech_pvt, switch_core_session_t *session)
+void tech_init(private_t *tech_pvt, switch_core_session_t *session, listener_t *listener, uint32_t line)
 {
+	switch_assert(tech_pvt);
+	switch_assert(session);
+	switch_assert(listener);
+	
 	tech_pvt->read_frame.data = tech_pvt->databuf;
 	tech_pvt->read_frame.buflen = sizeof(tech_pvt->databuf);
 	switch_mutex_init(&tech_pvt->mutex, SWITCH_MUTEX_NESTED, switch_core_session_get_pool(session));
 	switch_mutex_init(&tech_pvt->flag_mutex, SWITCH_MUTEX_NESTED, switch_core_session_get_pool(session));
-	tech_pvt->call_id = 12345; /* TODO */
+	tech_pvt->call_id = listener->profile->next_call_id++;
+	tech_pvt->listener = listener;
+	tech_pvt->line = line;
 	switch_core_session_set_private(session, tech_pvt);
 	tech_pvt->session = session;
 }
@@ -508,16 +514,25 @@
 	stop_tone(listener, tech_pvt->line, tech_pvt->call_id);
 	set_lamp(listener, SKINNY_BUTTON_LINE, tech_pvt->line, SKINNY_LAMP_OFF);
 	clear_prompt_status(listener, tech_pvt->line, tech_pvt->call_id);
-	close_receive_channel(listener,
-		tech_pvt->call_id, /* uint32_t conference_id, */
-		tech_pvt->party_id, /* uint32_t pass_thru_party_id, */
-		tech_pvt->call_id /* uint32_t conference_id2, */
-	);
-	stop_media_transmission(listener,
-		tech_pvt->call_id, /* uint32_t conference_id, */
-		tech_pvt->party_id, /* uint32_t pass_thru_party_id, */
-		tech_pvt->call_id /* uint32_t conference_id2, */
-	);
+
+	if( skinny_line_get_state(tech_pvt->listener, tech_pvt->line) == SKINNY_KEY_SET_CONNECTED ) {
+		close_receive_channel(listener,
+			tech_pvt->call_id, /* uint32_t conference_id, */
+			tech_pvt->party_id, /* uint32_t pass_thru_party_id, */
+			tech_pvt->call_id /* uint32_t conference_id2, */
+		);
+		stop_media_transmission(listener,
+			tech_pvt->call_id, /* uint32_t conference_id, */
+			tech_pvt->party_id, /* uint32_t pass_thru_party_id, */
+			tech_pvt->call_id /* uint32_t conference_id2, */
+		);
+		switch_mutex_lock(globals.calls_mutex);
+		globals.calls--;
+		if (globals.calls < 0) {
+			globals.calls = 0;
+		}
+		switch_mutex_unlock(globals.calls_mutex);
+	}
 	send_call_state(listener,
 		SKINNY_ON_HOOK,
 		tech_pvt->line,
@@ -526,15 +541,7 @@
 	/* TODO: DefineTimeDate */
 	set_speaker_mode(listener, SKINNY_SPEAKER_OFF);
 	set_ringer(listener, SKINNY_RING_OFF, SKINNY_RING_FOREVER, 0);
-	
 
-	switch_mutex_lock(globals.calls_mutex);
-	globals.calls--;
-	if (globals.calls < 0) {
-		globals.calls = 0;
-	}
-	switch_mutex_unlock(globals.calls_mutex);
-
 	return SWITCH_STATUS_SUCCESS;
 }
 
@@ -551,12 +558,12 @@
 
 	switch (sig) {
 	case SWITCH_SIG_KILL:
-		switch_clear_flag_locked(tech_pvt, TFLAG_IO);
-		switch_clear_flag_locked(tech_pvt, TFLAG_VOICE);
 		switch_channel_hangup(channel, SWITCH_CAUSE_NORMAL_CLEARING);
 		break;
 	case SWITCH_SIG_BREAK:
-		switch_set_flag_locked(tech_pvt, TFLAG_BREAK);
+		if (switch_rtp_ready(tech_pvt->rtp_session)) {
+			switch_rtp_break(tech_pvt->rtp_session);
+		}
 		break;
 	default:
 		break;
@@ -748,6 +755,8 @@
 	
 	char *profile_name, *dest;
 	skinny_profile_t *profile = NULL;
+	listener_t *listener = NULL;
+	uint32_t line = 0;
 	char name[128];
 	switch_channel_t *channel;
 	switch_caller_profile_t *caller_profile;
@@ -767,8 +776,6 @@
 		goto error;
 	}
 
-	tech_init(tech_pvt, nsession);
-
 	if(!(profile_name = switch_core_session_strdup(nsession, outbound_profile->destination_number))) {
 		switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_CRIT, "Error Creating Session Info\n");
 		goto error;
@@ -794,31 +801,33 @@
 	switch_channel_set_name(channel, name);
 	
 
-	caller_profile = switch_caller_profile_clone(nsession, outbound_profile);
-	switch_channel_set_caller_profile(channel, caller_profile);
-	tech_pvt->caller_profile = caller_profile;
-
-	switch_channel_set_flag(channel, CF_OUTBOUND);
-	switch_set_flag_locked(tech_pvt, TFLAG_OUTBOUND);
-
-	if ((skinny_profile_find_listener(profile, dest, &tech_pvt->listener, &tech_pvt->line) != SWITCH_STATUS_SUCCESS)) {
+	if ((skinny_profile_find_listener(profile, dest, &listener, &line) != SWITCH_STATUS_SUCCESS)) {
 		switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Problem while retrieving listener and line for destination %s in profile %s\n", dest, profile_name);
 		cause = SWITCH_CAUSE_UNALLOCATED_NUMBER;
 		goto error;
 	}
 	
-	if (!tech_pvt->listener) {
+	if (!listener) {
 		switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Invalid destination or phone not registred %s in profile %s\n", dest, profile_name);
 		cause = SWITCH_CAUSE_UNALLOCATED_NUMBER;
 		goto error;
 	}
 
-	if (tech_pvt->line == 0) {
+	if (line == 0) {
 		switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Invalid destination or phone not registred %s in profile %s\n", dest, profile_name);
 		cause = SWITCH_CAUSE_UNALLOCATED_NUMBER;
 		goto error;
 	}
 	
+	tech_init(tech_pvt, nsession, listener, line);
+
+	caller_profile = switch_caller_profile_clone(nsession, outbound_profile);
+	switch_channel_set_caller_profile(channel, caller_profile);
+	tech_pvt->caller_profile = caller_profile;
+
+	switch_channel_set_flag(channel, CF_OUTBOUND);
+	switch_set_flag_locked(tech_pvt, TFLAG_OUTBOUND);
+
 	if(tech_pvt->listener->session[tech_pvt->line]) { /* Line is busy */
 		switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Device line is busy %s in profile %s\n", dest, profile_name);
 		cause = SWITCH_CAUSE_USER_BUSY;
@@ -1424,8 +1433,6 @@
 				skinny_execute_sql_callback(profile, profile->listener_mutex, "DELETE FROM skinny_devices", NULL, NULL);
 				skinny_execute_sql_callback(profile, profile->listener_mutex, "DELETE FROM skinny_buttons", NULL, NULL);
 
-				switch_core_hash_init(&profile->session_hash, module_pool);
-				
 				switch_core_hash_insert(globals.profile_hash, profile->name, profile);
 				profile = NULL;
 			} else {

Modified: freeswitch/trunk/src/mod/endpoints/mod_skinny/mod_skinny.h (16788 => 16789)


--- freeswitch/trunk/src/mod/endpoints/mod_skinny/mod_skinny.h	2010-02-24 12:05:34 UTC (rev 16788)
+++ freeswitch/trunk/src/mod/endpoints/mod_skinny/mod_skinny.h	2010-02-24 12:05:45 UTC (rev 16789)
@@ -92,9 +92,8 @@
 	switch_mutex_t *sock_mutex;
 	struct listener *listeners;
 	uint8_t listener_ready;
-	/* sessions */
-	switch_hash_t *session_hash;
-	switch_mutex_t *sessions_mutex;
+	/* call id */
+	uint32_t next_call_id;
 };
 typedef struct skinny_profile skinny_profile_t;
 
@@ -143,7 +142,6 @@
 	TFLAG_HANGUP = (1 << 5),
 	TFLAG_LINEAR = (1 << 6),
 	TFLAG_CODEC = (1 << 7),
-	TFLAG_BREAK = (1 << 8),
 	
 	TFLAG_READING = (1 << 9),
 	TFLAG_WRITING = (1 << 10)
@@ -209,7 +207,7 @@
 uint32_t skinny_line_get_state(listener_t *listener, uint32_t instance);
 
 switch_status_t skinny_tech_set_codec(private_t *tech_pvt, int force);
-void tech_init(private_t *tech_pvt, switch_core_session_t *session);
+void tech_init(private_t *tech_pvt, switch_core_session_t *session, listener_t *listener, uint32_t line);
 switch_status_t channel_on_init(switch_core_session_t *session);
 switch_status_t channel_on_hangup(switch_core_session_t *session);
 switch_status_t channel_on_destroy(switch_core_session_t *session);

Modified: freeswitch/trunk/src/mod/endpoints/mod_skinny/skinny_protocol.c (16788 => 16789)


--- freeswitch/trunk/src/mod/endpoints/mod_skinny/skinny_protocol.c	2010-02-24 12:05:34 UTC (rev 16788)
+++ freeswitch/trunk/src/mod/endpoints/mod_skinny/skinny_protocol.c	2010-02-24 12:05:45 UTC (rev 16789)
@@ -272,6 +272,7 @@
 	}
 }
 
+/*****************************************************************************/
 switch_status_t skinny_read_packet(listener_t *listener, skinny_message_t **req)
 {
 	skinny_message_t *request;
@@ -355,6 +356,7 @@
 	return SWITCH_STATUS_SUCCESS;
 }
 
+/*****************************************************************************/
 int skinny_device_event_callback(void *pArg, int argc, char **argv, char **columnNames)
 {
 	switch_event_t *event = (switch_event_t *) pArg;
@@ -399,6 +401,7 @@
 	return SWITCH_STATUS_SUCCESS;
 }
 
+/*****************************************************************************/
 switch_status_t skinny_send_call_info(switch_core_session_t *session)
 {
 	private_t *tech_pvt;
@@ -435,11 +438,15 @@
 	return SWITCH_STATUS_SUCCESS;
 }
 
-switch_status_t skinny_pick_up(listener_t *listener, uint32_t line)
+/*****************************************************************************/
+switch_status_t skinny_create_session(listener_t *listener, uint32_t line, uint32_t to_state)
 {
 	switch_core_session_t *session;
 	switch_channel_t *channel;
 	private_t *tech_pvt;
+	char *cid_name = "TODO-soft_key_event"; /* TODO set form the line*/
+	char *cid_num = "00000"; /* TODO set form the line */
+	char name[128];
 
 	if (!(session = switch_core_session_request(skinny_get_endpoint_interface(), SWITCH_CALL_DIRECTION_INBOUND, NULL))) {
 		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Error Creating Session\n");
@@ -453,11 +460,26 @@
 
 	switch_core_session_add_stream(session, NULL);
 
-	tech_pvt->listener = listener;
-	tech_pvt->line = line;
+	tech_init(tech_pvt, session, listener, line);
 
-	tech_init(tech_pvt, session);
+	channel = switch_core_session_get_channel(session);
 
+	snprintf(name, sizeof(name), "SKINNY/%s/%s/%d", listener->profile->name, listener->device_name, tech_pvt->line);
+	switch_channel_set_name(channel, name);
+
+	if (switch_core_session_thread_launch(session) != SWITCH_STATUS_SUCCESS) {
+		switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_CRIT, "Error Creating Session thread\n");
+		goto error;
+	}
+
+	if (!(tech_pvt->caller_profile = switch_caller_profile_new(switch_core_session_get_pool(session),
+															  NULL, listener->profile->dialplan, cid_name, cid_num, listener->remote_ip, NULL, NULL, NULL, "skinny" /* modname */, listener->profile->context, tech_pvt->dest)) != 0) {
+		switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_CRIT, "Error Creating Session caller profile\n");
+		goto error;
+	}
+
+	switch_channel_set_caller_profile(channel, tech_pvt->caller_profile);
+
 	set_ringer(listener, SKINNY_RING_OFF, SKINNY_RING_FOREVER, 0);
 	set_speaker_mode(listener, SKINNY_SPEAKER_ON);
 	set_lamp(listener, SKINNY_BUTTON_LINE, tech_pvt->line, SKINNY_LAMP_ON);
@@ -465,7 +487,7 @@
 		SKINNY_OFF_HOOK,
 		tech_pvt->line,
 		tech_pvt->call_id);
-	skinny_line_set_state(listener, tech_pvt->line, SKINNY_KEY_SET_OFF_HOOK, tech_pvt->call_id);
+	skinny_line_set_state(listener, tech_pvt->line, to_state, tech_pvt->call_id);
 	display_prompt_status(listener,
 		0,
 		"\200\000",
@@ -474,7 +496,6 @@
 	activate_call_plane(listener, tech_pvt->line);
 	start_tone(listener, SKINNY_TONE_DIALTONE, 0, tech_pvt->line, tech_pvt->call_id);
 
-	channel = switch_core_session_get_channel(session);
 	goto done;
 error:
 	if (session) {
@@ -488,6 +509,29 @@
 	return SWITCH_STATUS_SUCCESS;
 }
 
+switch_status_t skinny_process_dest(listener_t *listener, uint32_t line)
+{
+	switch_channel_t *channel = NULL;
+	private_t *tech_pvt = NULL;
+
+	channel = switch_core_session_get_channel(listener->session[line]);
+	assert(channel != NULL);
+
+	tech_pvt = switch_core_session_get_private(listener->session[line]);
+	assert(tech_pvt != NULL);
+
+	tech_pvt->caller_profile->destination_number = switch_core_strdup(tech_pvt->caller_profile->pool, tech_pvt->dest);
+	if(strlen(tech_pvt->dest) >= 4) { /* TODO Number is complete -> check against dialplan */
+		if (switch_channel_get_state(channel) == CS_NEW) {
+			switch_channel_set_state(channel, CS_INIT);
+		}
+
+		send_dialed_number(listener, tech_pvt->dest, tech_pvt->line, tech_pvt->call_id);
+		skinny_answer(listener->session[line]);
+	}
+	return SWITCH_STATUS_SUCCESS;
+}
+
 switch_status_t skinny_answer(switch_core_session_t *session)
 {
 	private_t *tech_pvt;
@@ -525,21 +569,40 @@
 	return SWITCH_STATUS_SUCCESS;
 }
 
-switch_status_t skinny_hangup(listener_t *listener, uint32_t line)
+struct speed_dial_get_dest_helper {
+	uint32_t pos;
+	char dest[40];
+};
+
+int skinny_speed_dial_get_dest_callback(void *pArg, int argc, char **argv, char **columnNames)
 {
-	switch_channel_t *channel = NULL;
-	private_t *tech_pvt = NULL;
+	struct speed_dial_get_dest_helper *helper = pArg;
 
-	channel = switch_core_session_get_channel(listener->session[line]);
-	assert(channel != NULL);
+	helper->pos++;
+	if (helper->pos == atoi(argv[0])) { /* wanted_position */
+		strncpy(helper->dest,  argv[3], 40); /* value */
+	}
+	return 0;
+}
 
-	tech_pvt = switch_core_session_get_private(listener->session[line]);
-	assert(tech_pvt != NULL);
+void skinny_speed_dial_get_dest(skinny_profile_t *profile, const char *device_name, uint32_t instance, char *dest)
+{
+	struct speed_dial_get_dest_helper helper = {0};
+	char *sql;
 
-	switch_clear_flag_locked(tech_pvt, TFLAG_IO);
-	switch_clear_flag_locked(tech_pvt, TFLAG_VOICE);
-	switch_channel_hangup(channel, SWITCH_CAUSE_NORMAL_CLEARING);
-	return SWITCH_STATUS_SUCCESS;
+	switch_assert(device_name);
+
+	if ((sql = switch_mprintf(
+			"SELECT '%d' AS wanted_position, position, label, value, settings "
+				"FROM skinny_buttons WHERE device_name='%s' AND type='speed-dial' "
+				"ORDER BY position",
+			instance,
+			device_name
+			))) {
+		skinny_execute_sql_callback(profile, profile->listener_mutex, sql, skinny_speed_dial_get_dest_callback, &helper);
+		switch_safe_free(sql);
+	}
+	strncpy(dest, helper.dest, 40);
 }
 
 /*****************************************************************************/
@@ -1273,8 +1336,12 @@
 	message->data.soft_key_set.total_soft_key_set_count = 11;
 	
 	/* TODO fill the set */
+
 	skinny_send_reply(listener, message);
 
+	/* Init the states */
+	skinny_line_set_state(listener, 0, SKINNY_KEY_SET_ON_HOOK, 0);
+	
 	return SWITCH_STATUS_SUCCESS;
 }
 
@@ -1420,6 +1487,7 @@
 	switch_status_t status = SWITCH_STATUS_SUCCESS;
 
 	skinny_profile_t *profile;
+	switch_channel_t *channel = NULL;
 	uint32_t line;
 
 	switch_assert(listener->profile);
@@ -1438,7 +1506,7 @@
 	if(!listener->session[line]) { /*the line is not busy */
 		switch(request->data.soft_key_event.event) {
 			case SOFTKEY_NEWCALL:
-				skinny_pick_up(listener, line);
+				skinny_create_session(listener, line, SKINNY_KEY_SET_OFF_HOOK);
 				break;
 			default:
 				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO,
@@ -1447,7 +1515,11 @@
 	} else { /* the line is busy */
 		switch(request->data.soft_key_event.event) {
 			case SOFTKEY_ENDCALL:
-				skinny_hangup(listener, line);
+				channel = switch_core_session_get_channel(listener->session[line]);
+				assert(channel != NULL);
+
+				switch_channel_hangup(channel, SWITCH_CAUSE_NORMAL_CLEARING);
+
 				break;
 			default:
 				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO,
@@ -1477,11 +1549,52 @@
 	if(listener->session[line]) { /*answering a call */
 		skinny_answer(listener->session[line]);
 	} else { /* start a new call */
-		skinny_pick_up(listener, line);
+		skinny_create_session(listener, line, SKINNY_KEY_SET_OFF_HOOK);
 	}
 	return SWITCH_STATUS_SUCCESS;
 }
 
+switch_status_t skinny_handle_stimulus_message(listener_t *listener, skinny_message_t *request)
+{
+	skinny_profile_t *profile;
+	uint32_t line = 1;
+	private_t *tech_pvt = NULL;
+	char dest[40] = "";
+
+	switch_assert(listener->profile);
+	switch_assert(listener->device_name);
+
+	profile = listener->profile;
+
+	skinny_check_data_length(request, sizeof(request->data.stimulus));
+
+	switch(request->data.stimulus.instance_type) {
+		case SKINNY_BUTTON_VOICEMAIL:
+			skinny_create_session(listener, line, SKINNY_KEY_SET_DIGITS_AFTER_DIALING_FIRST_DIGIT);
+	
+			tech_pvt = switch_core_session_get_private(listener->session[line]);
+			assert(tech_pvt != NULL);
+		
+			strcpy(tech_pvt->dest, "vmain");
+			skinny_process_dest(listener, line);
+			break;
+		case SKINNY_BUTTON_SPEED_DIAL:
+			skinny_speed_dial_get_dest(listener->profile, listener->device_name, request->data.stimulus.instance, dest);
+			if(strlen(dest) > 0) {
+				skinny_create_session(listener, line, SKINNY_KEY_SET_DIGITS_AFTER_DIALING_FIRST_DIGIT);
+
+				tech_pvt = switch_core_session_get_private(listener->session[line]);
+				assert(tech_pvt != NULL);
+		
+				strcpy(tech_pvt->dest, dest);
+				skinny_process_dest(listener, line);
+			}
+		default:
+			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Unknown Stimulus Type Received [%d]\n", request->data.stimulus.instance_type);
+	}
+	return SWITCH_STATUS_SUCCESS;
+}
+
 switch_status_t skinny_handle_open_receive_channel_ack_message(listener_t *listener, skinny_message_t *request)
 {
 	switch_status_t status = SWITCH_STATUS_SUCCESS;
@@ -1581,7 +1694,7 @@
 
 	skinny_check_data_length(request, sizeof(request->data.keypad_button));
 
-	if(request->data.keypad_button.line_instance) {
+	if(request->data.keypad_button.line_instance != 0) {
 		line = request->data.keypad_button.line_instance;
 	} else {
 		/* Find first active line */
@@ -1619,10 +1732,6 @@
 
 		if((skinny_line_get_state(listener, tech_pvt->line) == SKINNY_KEY_SET_OFF_HOOK)
 				|| (skinny_line_get_state(listener, tech_pvt->line) == SKINNY_KEY_SET_DIGITS_AFTER_DIALING_FIRST_DIGIT)) {
-			char name[128];
-			switch_channel_t *channel;
-			char *cid_name = "TODO-soft_key_event"; /* TODO */
-			char *cid_num = "00000"; /* TODO */
 			if(strlen(tech_pvt->dest) == 0) {/* first digit */
 				stop_tone(listener, tech_pvt->line, tech_pvt->call_id);
 				skinny_line_set_state(listener, tech_pvt->line, SKINNY_KEY_SET_DIGITS_AFTER_DIALING_FIRST_DIGIT, tech_pvt->call_id);
@@ -1630,38 +1739,7 @@
 			
 			tech_pvt->dest[strlen(tech_pvt->dest)] = digit;
 			
-			if(strlen(tech_pvt->dest) >= 4) { /* TODO Number is complete */
-				if (!(tech_pvt->caller_profile = switch_caller_profile_new(switch_core_session_get_pool(listener->session[line]),
-																		  NULL, listener->profile->dialplan, cid_name, cid_num, listener->remote_ip, NULL, NULL, NULL, "skinny" /* modname */, listener->profile->context, tech_pvt->dest)) != 0) {
-					switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(listener->session[line]), SWITCH_LOG_CRIT, "Error Creating Session caller profile\n");
-					goto error;
-				}
-
-				channel = switch_core_session_get_channel(listener->session[line]);
-				snprintf(name, sizeof(name), "SKINNY/%s/%s/%d", listener->profile->name, listener->device_name, line);
-				switch_channel_set_name(channel, name);
-
-				switch_channel_set_caller_profile(channel, tech_pvt->caller_profile);
-
-				if (switch_channel_get_state(channel) == CS_NEW) {
-					switch_channel_set_state(channel, CS_INIT);
-				}
-
-				if (switch_core_session_thread_launch(listener->session[line]) != SWITCH_STATUS_SUCCESS) {
-					switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(listener->session[line]), SWITCH_LOG_CRIT, "Error Creating Session thread\n");
-					goto error;
-				}
-
-				skinny_line_set_state(listener, tech_pvt->line, SKINNY_KEY_SET_CONNECTED, tech_pvt->call_id);
-				send_dialed_number(listener, tech_pvt->dest, tech_pvt->line, tech_pvt->call_id);
-				skinny_answer(listener->session[line]);
-
-				goto done;
-error:
-			return SWITCH_STATUS_FALSE;
-done:
-			return SWITCH_STATUS_SUCCESS;
-			}
+			skinny_process_dest(listener, tech_pvt->line);
 		} else {
 			if(digit != '\0') {
 				switch_dtmf_t dtmf = { 0, switch_core_default_dtmf_duration(0)};
@@ -1687,7 +1765,7 @@
 
 	skinny_check_data_length(request, sizeof(request->data.on_hook));
 
-	if(request->data.on_hook.line_instance) {
+	if(request->data.on_hook.line_instance != 0) {
 		line = request->data.on_hook.line_instance;
 	} else {
 		/* Find first active line */
@@ -1700,7 +1778,12 @@
 	}
 
 	if(listener->session[line]) {
-		skinny_hangup(listener, line);
+		switch_channel_t *channel = NULL;
+
+		channel = switch_core_session_get_channel(listener->session[line]);
+		assert(channel != NULL);
+
+		switch_channel_hangup(channel, SWITCH_CAUSE_NORMAL_CLEARING);
 	}
 	return status;
 }
@@ -1758,6 +1841,8 @@
 			return skinny_handle_soft_key_event_message(listener, request);
 		case OFF_HOOK_MESSAGE:
 			return skinny_handle_off_hook_message(listener, request);
+		case STIMULUS_MESSAGE:
+			return skinny_handle_stimulus_message(listener, request);
 		case OPEN_RECEIVE_CHANNEL_ACK_MESSAGE:
 			return skinny_handle_open_receive_channel_ack_message(listener, request);
 		case KEYPAD_BUTTON_MESSAGE:

Modified: freeswitch/trunk/src/mod/endpoints/mod_skinny/skinny_protocol.h (16788 => 16789)


--- freeswitch/trunk/src/mod/endpoints/mod_skinny/skinny_protocol.h	2010-02-24 12:05:34 UTC (rev 16788)
+++ freeswitch/trunk/src/mod/endpoints/mod_skinny/skinny_protocol.h	2010-02-24 12:05:45 UTC (rev 16789)
@@ -73,7 +73,7 @@
 struct stimulus_message {
 	uint32_t instance_type; /* See enum skinny_button_definition */
 	uint32_t instance;
-	uint32_t call_reference;
+	/* uint32_t call_reference; */
 };
 
 /* OffHookMessage */
@@ -665,6 +665,10 @@
 
 switch_status_t skinny_send_call_info(switch_core_session_t *session);
 
+switch_status_t skinny_create_session(listener_t *listener, uint32_t line, uint32_t to_state);
+switch_status_t skinny_process_dest(listener_t *listener, uint32_t line);
+switch_status_t skinny_answer(switch_core_session_t *session);
+
 switch_status_t skinny_perform_send_reply(listener_t *listener, const char *file, const char *func, int line, skinny_message_t *reply);
 #define  skinny_send_reply(listener, reply)  skinny_perform_send_reply(listener, __FILE__, __SWITCH_FUNC__, __LINE__, reply)