]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
Skinny: initial transfer support
authorMathieu Parent <math.parent@gmail.com>
Fri, 16 Apr 2010 09:58:15 +0000 (11:58 +0200)
committerMathieu Parent <math.parent@gmail.com>
Fri, 16 Apr 2010 09:59:58 +0000 (11:59 +0200)
and some re-indentation

src/mod/endpoints/mod_skinny/mod_skinny.c
src/mod/endpoints/mod_skinny/mod_skinny.h
src/mod/endpoints/mod_skinny/skinny_protocol.c
src/mod/endpoints/mod_skinny/skinny_protocol.h

index 2a6e65d695c52918c2d969f8fa77b68ea535cf2b..63cc514429f3e30277db7ad771d89bc5cc2e92a0 100644 (file)
@@ -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;
 }
index 3443d2f7dd137b99251d4152bfcb97a5f3ca620c..341499967d8e5af27f12b071b703964e6a1d5b96 100644 (file)
@@ -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;
+
+       /* 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;
+       /* 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;
index 7fd799854549d88e54d99ac895a6d5880e923fea..c6daed417f982f87c06aa16343ecee9c064d36b6 100644 (file)
@@ -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);
index c038be5cc97df5612da2472aac7e0f3dabd8b96f..994462684fd032438cf0f3e160dbf8371b75fb55 100644 (file)
@@ -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 {