From 00b262235007cb6407c986b355d3a49881401419 Mon Sep 17 00:00:00 2001 From: Mathieu Parent Date: Fri, 16 Apr 2010 11:58:15 +0200 Subject: [PATCH] Skinny: initial transfer support and some re-indentation --- src/mod/endpoints/mod_skinny/mod_skinny.c | 2 +- src/mod/endpoints/mod_skinny/mod_skinny.h | 60 ++++++++-------- .../endpoints/mod_skinny/skinny_protocol.c | 72 ++++++++++++++++--- .../endpoints/mod_skinny/skinny_protocol.h | 24 +++---- 4 files changed, 106 insertions(+), 52 deletions(-) diff --git a/src/mod/endpoints/mod_skinny/mod_skinny.c b/src/mod/endpoints/mod_skinny/mod_skinny.c index 2a6e65d695..63cc514429 100644 --- a/src/mod/endpoints/mod_skinny/mod_skinny.c +++ b/src/mod/endpoints/mod_skinny/mod_skinny.c @@ -542,9 +542,9 @@ void tech_init(private_t *tech_pvt, skinny_profile_t *profile, switch_core_sessi 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->profile = profile; tech_pvt->call_id = ++profile->next_call_id; tech_pvt->party_id = tech_pvt->call_id; - tech_pvt->profile = profile; switch_core_session_set_private(session, tech_pvt); tech_pvt->session = session; } diff --git a/src/mod/endpoints/mod_skinny/mod_skinny.h b/src/mod/endpoints/mod_skinny/mod_skinny.h index 3443d2f7dd..341499967d 100644 --- a/src/mod/endpoints/mod_skinny/mod_skinny.h +++ b/src/mod/endpoints/mod_skinny/mod_skinny.h @@ -147,36 +147,40 @@ typedef enum { } GFLAGS; struct private_object { - unsigned int flags; - switch_frame_t read_frame; - unsigned char databuf[SWITCH_RECOMMENDED_BUFFER_SIZE]; - switch_core_session_t *session; - switch_caller_profile_t *caller_profile; - switch_mutex_t *mutex; - switch_mutex_t *flag_mutex; - /* identification */ - uint32_t call_id; - uint32_t party_id; + unsigned int flags; + switch_frame_t read_frame; + unsigned char databuf[SWITCH_RECOMMENDED_BUFFER_SIZE]; + switch_core_session_t *session; + switch_caller_profile_t *caller_profile; + switch_mutex_t *mutex; + switch_mutex_t *flag_mutex; - skinny_profile_t *profile; + /* identification */ + skinny_profile_t *profile; + uint32_t call_id; + uint32_t party_id; - /* codec */ - char *iananame; - switch_codec_t read_codec; - switch_codec_t write_codec; - switch_codec_implementation_t read_impl; - switch_codec_implementation_t write_impl; - unsigned long rm_rate; - uint32_t codec_ms; - char *rm_encoding; - char *rm_fmtp; - switch_payload_t agreed_pt; - /* RTP */ - switch_rtp_t *rtp_session; - char *local_sdp_audio_ip; - switch_port_t local_sdp_audio_port; - char *remote_sdp_audio_ip; - switch_port_t remote_sdp_audio_port; + /* related calls */ + uint32_t transfer_to_call_id; + uint32_t transfer_from_call_id; + + /* codec */ + char *iananame; + switch_codec_t read_codec; + switch_codec_t write_codec; + switch_codec_implementation_t read_impl; + switch_codec_implementation_t write_impl; + unsigned long rm_rate; + uint32_t codec_ms; + char *rm_encoding; + char *rm_fmtp; + switch_payload_t agreed_pt; + /* RTP */ + switch_rtp_t *rtp_session; + char *local_sdp_audio_ip; + switch_port_t local_sdp_audio_port; + char *remote_sdp_audio_ip; + switch_port_t remote_sdp_audio_port; }; typedef struct private_object private_t; diff --git a/src/mod/endpoints/mod_skinny/skinny_protocol.c b/src/mod/endpoints/mod_skinny/skinny_protocol.c index 7fd7998545..c6daed417f 100644 --- a/src/mod/endpoints/mod_skinny/skinny_protocol.c +++ b/src/mod/endpoints/mod_skinny/skinny_protocol.c @@ -837,6 +837,47 @@ switch_status_t skinny_session_unhold_line(switch_core_session_t *session, liste return SWITCH_STATUS_SUCCESS; } +switch_status_t skinny_session_transfer(switch_core_session_t *session, listener_t *listener, uint32_t line_instance) +{ + switch_status_t status = SWITCH_STATUS_SUCCESS; + private_t *tech_pvt = NULL; + switch_channel_t *channel = NULL; + const char *uuid = NULL; + switch_core_session_t *session2 = NULL; + private_t *tech_pvt2 = NULL; + + switch_assert(session); + switch_assert(listener); + switch_assert(listener->profile); + + tech_pvt = switch_core_session_get_private(session); + channel = switch_core_session_get_channel(session); + uuid = switch_channel_get_variable(channel, SWITCH_BRIDGE_VARIABLE); + + if (tech_pvt->transfer_from_call_id) { + if((session2 = skinny_profile_find_session(listener->profile, listener, &line_instance, 0))) { + switch_channel_t *channel2 = switch_core_session_get_channel(session2); + const char *uuid2 = switch_channel_get_variable(channel2, SWITCH_BRIDGE_VARIABLE); + switch_ivr_uuid_bridge(uuid, uuid2); + switch_core_session_rwunlock(session2); + /* TODO: How to inform the user that the bridge is not possible? */ + } + } else { + if(uuid) { + /* TODO CallSelectStat */ + status = skinny_create_ingoing_session(listener, &line_instance, &session2); + tech_pvt2 = switch_core_session_get_private(session2); + tech_pvt2->transfer_from_call_id = tech_pvt->call_id; + tech_pvt->transfer_to_call_id = tech_pvt2->call_id; + skinny_session_process_dest(session2, listener, line_instance, NULL, '\0', 0); + switch_core_session_rwunlock(session2); + } else { + /* TODO: How to inform the user that the bridge is not possible? */ + } + } + return status; +} + switch_status_t skinny_session_stop_media(switch_core_session_t *session, listener_t *listener, uint32_t line_instance) { switch_channel_t *channel = NULL; @@ -1990,6 +2031,7 @@ switch_status_t skinny_handle_soft_key_set_request(listener_t *listener, skinny_ message->data.soft_key_set.soft_key_set[SKINNY_KEY_SET_CONNECTED].soft_key_template_index[0] = SOFTKEY_ENDCALL; message->data.soft_key_set.soft_key_set[SKINNY_KEY_SET_CONNECTED].soft_key_template_index[1] = SOFTKEY_HOLD; message->data.soft_key_set.soft_key_set[SKINNY_KEY_SET_CONNECTED].soft_key_template_index[2] = SOFTKEY_NEWCALL; + message->data.soft_key_set.soft_key_set[SKINNY_KEY_SET_CONNECTED].soft_key_template_index[3] = SOFTKEY_TRANSFER; message->data.soft_key_set.soft_key_set[SKINNY_KEY_SET_RING_IN].soft_key_template_index[0] = SOFTKEY_ANSWER; message->data.soft_key_set.soft_key_set[SKINNY_KEY_SET_RING_IN].soft_key_template_index[1] = SOFTKEY_ENDCALL; @@ -1998,6 +2040,9 @@ switch_status_t skinny_handle_soft_key_set_request(listener_t *listener, skinny_ message->data.soft_key_set.soft_key_set[SKINNY_KEY_SET_ON_HOLD].soft_key_template_index[0] = SOFTKEY_NEWCALL; message->data.soft_key_set.soft_key_set[SKINNY_KEY_SET_ON_HOLD].soft_key_template_index[1] = SOFTKEY_RESUME; message->data.soft_key_set.soft_key_set[SKINNY_KEY_SET_ON_HOLD].soft_key_template_index[2] = SOFTKEY_ENDCALL; + + message->data.soft_key_set.soft_key_set[SKINNY_KEY_SET_OFF_HOOK_WITH_FEATURES].soft_key_template_index[1] = SOFTKEY_REDIAL; + message->data.soft_key_set.soft_key_set[SKINNY_KEY_SET_OFF_HOOK_WITH_FEATURES].soft_key_template_index[2] = SOFTKEY_ENDCALL; skinny_send_reply(listener, message); @@ -2146,6 +2191,13 @@ switch_status_t skinny_handle_soft_key_event_message(listener_t *listener, skinn status = skinny_session_hold_line(session, listener, line_instance); } break; + case SOFTKEY_TRANSFER: + session = skinny_profile_find_session(listener->profile, listener, &line_instance, request->data.soft_key_event.call_id); + + if(session) { + status = skinny_session_transfer(session, listener, line_instance); + } + break; case SOFTKEY_BACKSPACE: session = skinny_profile_find_session(listener->profile, listener, &line_instance, request->data.soft_key_event.call_id); @@ -2341,19 +2393,17 @@ switch_status_t skinny_handle_open_receive_channel_ack_message(listener_t *liste 0, /* uint32_t silence_suppression, */ 0, /* uint16_t max_frames_per_packet, */ 0 /* uint32_t g723_bitrate */ - ); - if (switch_channel_get_state(channel) == CS_NEW) { - switch_channel_set_state(channel, CS_INIT); - } - switch_channel_mark_answered(channel); + ); + if (switch_channel_get_state(channel) == CS_NEW) { + switch_channel_set_state(channel, CS_INIT); + } + switch_channel_mark_answered(channel); } end: - if(session) { switch_core_session_rwunlock(session); } - return status; } @@ -2509,14 +2559,14 @@ switch_status_t skinny_handle_request(listener_t *listener, skinny_message_t *re return skinny_handle_unregister(listener, request); case SOFT_KEY_TEMPLATE_REQ_MESSAGE: return skinny_handle_soft_key_template_request(listener, request); - case SERVICE_URL_STAT_REQ_MESSAGE: - return skinny_handle_service_url_stat_request(listener, request); - case FEATURE_STAT_REQ_MESSAGE: - return skinny_handle_feature_stat_request(listener, request); case HEADSET_STATUS_MESSAGE: return skinny_headset_status_message(listener, request); case REGISTER_AVAILABLE_LINES_MESSAGE: return skinny_handle_register_available_lines_message(listener, request); + case SERVICE_URL_STAT_REQ_MESSAGE: + return skinny_handle_service_url_stat_request(listener, request); + case FEATURE_STAT_REQ_MESSAGE: + return skinny_handle_feature_stat_request(listener, request); default: switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Unhandled request %s (type=%x,length=%d).\n", skinny_message_type2str(request->type), request->type, request->length); diff --git a/src/mod/endpoints/mod_skinny/skinny_protocol.h b/src/mod/endpoints/mod_skinny/skinny_protocol.h index c038be5cc9..994462684f 100644 --- a/src/mod/endpoints/mod_skinny/skinny_protocol.h +++ b/src/mod/endpoints/mod_skinny/skinny_protocol.h @@ -162,18 +162,6 @@ struct soft_key_event_message { /* SoftKeyTemplateReqMessage */ #define SOFT_KEY_TEMPLATE_REQ_MESSAGE 0x0028 -/* ServiceUrlStatReqMessage */ -#define SERVICE_URL_STAT_REQ_MESSAGE 0x0033 -struct service_url_stat_req_message { - uint32_t service_url_index; -}; - -/* FeatureStatReqMessage */ -#define FEATURE_STAT_REQ_MESSAGE 0x0034 -struct feature_stat_req_message { - uint32_t feature_index; -}; - /* HeadsetStatusMessage */ #define HEADSET_STATUS_MESSAGE 0x002B struct headset_status_message { @@ -186,6 +174,18 @@ struct register_available_lines_message { uint32_t count; }; +/* ServiceUrlStatReqMessage */ +#define SERVICE_URL_STAT_REQ_MESSAGE 0x0033 +struct service_url_stat_req_message { + uint32_t service_url_index; +}; + +/* FeatureStatReqMessage */ +#define FEATURE_STAT_REQ_MESSAGE 0x0034 +struct feature_stat_req_message { + uint32_t feature_index; +}; + /* RegisterAckMessage */ #define REGISTER_ACK_MESSAGE 0x0081 struct register_ack_message {