diff --git a/src/mod/endpoints/mod_skinny/mod_skinny.c b/src/mod/endpoints/mod_skinny/mod_skinny.c index c67c20fde4..fc7d8721a0 100644 --- a/src/mod/endpoints/mod_skinny/mod_skinny.c +++ b/src/mod/endpoints/mod_skinny/mod_skinny.c @@ -1911,6 +1911,55 @@ static switch_status_t load_skinny_config(void) return SWITCH_STATUS_SUCCESS; } +static void skinny_user_to_device_event_handler(switch_event_t *event) +{ + char *profile_name = switch_event_get_header_nil(event, "Skinny-Profile-Name"); + skinny_profile_t *profile; + + if ((profile = skinny_find_profile(profile_name))) { + char *device_name = switch_event_get_header_nil(event, "Skinny-Device-Name"); + uint32_t device_instance = atoi(switch_event_get_header_nil(event, "Skinny-Station-Instance")); + listener_t *listener = NULL; + skinny_profile_find_listener_by_device_name_and_instance(profile, device_name, device_instance, &listener); + if(listener) { + uint32_t message_type = atoi(switch_event_get_header_nil(event, "Skinny-UserToDevice-Message-Id")); + uint32_t application_id = atoi(switch_event_get_header_nil(event, "Skinny-UserToDevice-Application-Id")); + uint32_t line_instance = atoi(switch_event_get_header_nil(event, "Skinny-UserToDevice-Line-Instance")); + uint32_t call_id = atoi(switch_event_get_header_nil(event, "Skinny-UserToDevice-Call-Id")); + uint32_t transaction_id = atoi(switch_event_get_header_nil(event, "Skinny-UserToDevice-Transaction-Id")); + uint32_t data_length = atoi(switch_event_get_header_nil(event, "Skinny-UserToDevice-Data-Length")); + uint32_t sequence_flag = atoi(switch_event_get_header_nil(event, "Skinny-UserToDevice-Sequence-Flag")); + uint32_t display_priority = atoi(switch_event_get_header_nil(event, "Skinny-UserToDevice-Display-Priority")); + uint32_t conference_id = atoi(switch_event_get_header_nil(event, "Skinny-UserToDevice-Conference-Id")); + uint32_t app_instance_id = atoi(switch_event_get_header_nil(event, "Skinny-UserToDevice-App-Instance-Id")); + uint32_t routing_id = atoi(switch_event_get_header_nil(event, "Skinny-UserToDevice-Routing-Id")); + char *data = switch_event_get_body(event); + if (message_type == 0) { + message_type = skinny_str2message_type(switch_event_get_header_nil(event, "Skinny-UserToDevice-Message-Id-String")); + } + switch(message_type) { + case USER_TO_DEVICE_DATA_MESSAGE: + case USER_TO_DEVICE_DATA_VERSION1_MESSAGE: + data_length = strlen(data); /* we ignore data_length sent */ + send_extended_data(listener, message_type, + application_id, line_instance, call_id, transaction_id, data_length, + sequence_flag, display_priority, conference_id, app_instance_id, routing_id, + data); + break; + default: + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, + "Incorrect message type %s (%d).\n", skinny_message_type2str(message_type), message_type); + } + } else { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, + "Device %s:%d in profile '%s' not found.\n", device_name, device_instance, profile_name); + } + } else { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, + "Profile '%s' not found.\n", profile_name); + } +} + static void skinny_call_state_event_handler(switch_event_t *event) { char *subclass; @@ -2130,6 +2179,10 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_skinny_load) switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Couldn't bind our trap handler!\n"); /* Not such severe to prevent loading */ } + if ((switch_event_bind_removable(modname, SWITCH_EVENT_CUSTOM, SKINNY_EVENT_USER_TO_DEVICE, skinny_user_to_device_event_handler, NULL, &globals.user_to_device_node) != SWITCH_STATUS_SUCCESS)) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't bind our user_to_device handler!\n"); + /* Not such severe to prevent loading */ + } /* reserve events */ if (switch_event_reserve_subclass(SKINNY_EVENT_REGISTER) != SWITCH_STATUS_SUCCESS) { @@ -2152,6 +2205,14 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_skinny_load) switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't register subclass %s!\n", SKINNY_EVENT_CALL_STATE); return SWITCH_STATUS_TERM; } + if (switch_event_reserve_subclass(SKINNY_EVENT_USER_TO_DEVICE) != SWITCH_STATUS_SUCCESS) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't register subclass %s!\n", SKINNY_EVENT_USER_TO_DEVICE); + return SWITCH_STATUS_TERM; + } + if (switch_event_reserve_subclass(SKINNY_EVENT_DEVICE_TO_USER) != SWITCH_STATUS_SUCCESS) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't register subclass %s!\n", SKINNY_EVENT_DEVICE_TO_USER); + return SWITCH_STATUS_TERM; + } /* connect my internal structure to the blank pointer passed to me */ *module_interface = switch_loadable_module_create_module_interface(globals.pool, modname); @@ -2190,6 +2251,7 @@ SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_skinny_shutdown) skinny_api_unregister(); /* release events */ + switch_event_unbind(&globals.user_to_device_node); switch_event_unbind(&globals.call_state_node); switch_event_unbind(&globals.message_waiting_node); switch_event_unbind(&globals.trap_node); @@ -2198,6 +2260,8 @@ SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_skinny_shutdown) switch_event_free_subclass(SKINNY_EVENT_EXPIRE); switch_event_free_subclass(SKINNY_EVENT_ALARM); switch_event_free_subclass(SKINNY_EVENT_CALL_STATE); + switch_event_free_subclass(SKINNY_EVENT_USER_TO_DEVICE); + switch_event_free_subclass(SKINNY_EVENT_DEVICE_TO_USER); switch_mutex_lock(mutex); diff --git a/src/mod/endpoints/mod_skinny/mod_skinny.h b/src/mod/endpoints/mod_skinny/mod_skinny.h index 7a4df6ff03..b5cc96b7ae 100644 --- a/src/mod/endpoints/mod_skinny/mod_skinny.h +++ b/src/mod/endpoints/mod_skinny/mod_skinny.h @@ -43,12 +43,15 @@ #define SKINNY_EVENT_EXPIRE "skinny::expire" #define SKINNY_EVENT_ALARM "skinny::alarm" #define SKINNY_EVENT_CALL_STATE "skinny::call_state" +#define SKINNY_EVENT_USER_TO_DEVICE "skinny::user_to_device" +#define SKINNY_EVENT_DEVICE_TO_USER "skinny::device_to_user" struct skinny_globals { int running; switch_memory_pool_t *pool; switch_mutex_t *mutex; switch_hash_t *profile_hash; + switch_event_node_t *user_to_device_node; switch_event_node_t *call_state_node; switch_event_node_t *message_waiting_node; switch_event_node_t *trap_node; diff --git a/src/mod/endpoints/mod_skinny/skinny_api.c b/src/mod/endpoints/mod_skinny/skinny_api.c index 90699d1ad2..9f527f544c 100644 --- a/src/mod/endpoints/mod_skinny/skinny_api.c +++ b/src/mod/endpoints/mod_skinny/skinny_api.c @@ -366,6 +366,62 @@ static switch_status_t skinny_api_cmd_profile_device_send_reset_message(const ch return SWITCH_STATUS_SUCCESS; } +static switch_status_t skinny_api_cmd_profile_device_send_data(const char *profile_name, const char *device_name, const char *message_type, char *params, const char *body, switch_stream_handle_t *stream) +{ + skinny_profile_t *profile; + + if ((profile = skinny_find_profile(profile_name))) { + listener_t *listener = NULL; + skinny_profile_find_listener_by_device_name(profile, device_name, &listener); + if(listener) { + switch_event_t *event = NULL; + char *argv[64] = { 0 }; + int argc = 0; + int x = 0; + /* skinny::user_to_device event */ + skinny_device_event(listener, &event, SWITCH_EVENT_CUSTOM, SKINNY_EVENT_USER_TO_DEVICE); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Skinny-UserToDevice-Message-Id-String", "%s", message_type); + argc = switch_separate_string(params, ';', argv, (sizeof(argv) / sizeof(argv[0]))); + for (x = 0; x < argc; x++) { + char *var_name, *var_value = NULL; + var_name = argv[x]; + if (var_name && (var_value = strchr(var_name, '='))) { + *var_value++ = '\0'; + } + if (zstr(var_name)) { + stream->write_function(stream, "-ERR No variable specified\n"); + } else { + char *tmp = switch_mprintf("Skinny-UserToDevice-%s", var_name); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, tmp, "%s", var_value); + switch_safe_free(tmp); + /* + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Skinny-UserToDevice-Application-Id", "%d", request->data.extended_data.application_id); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Skinny-UserToDevice-Line-Instance", "%d", request->data.extended_data.line_instance); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Skinny-UserToDevice-Call-Id", "%d", request->data.extended_data.call_id); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Skinny-UserToDevice-Transaction-Id", "%d", request->data.extended_data.transaction_id); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Skinny-UserToDevice-Data-Length", "%d", request->data.extended_data.data_length); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Skinny-UserToDevice-Sequence-Flag", "%d", request->data.extended_data.sequence_flag); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Skinny-UserToDevice-Display-Priority", "%d", request->data.extended_data.display_priority); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Skinny-UserToDevice-Conference-Id", "%d", request->data.extended_data.conference_id); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Skinny-UserToDevice-App-Instance-Id", "%d", request->data.extended_data.app_instance_id); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Skinny-UserToDevice-Routing-Id", "%d", request->data.extended_data.routing_id); + */ + } + } + switch_event_add_body(event, body); + switch_event_fire(&event); + stream->write_function(stream, "+OK\n"); + } else { + stream->write_function(stream, "Listener not found!\n"); + } + } else { + stream->write_function(stream, "Profile not found!\n"); + } + + return SWITCH_STATUS_SUCCESS; +} + + static switch_status_t skinny_api_cmd_profile_set(const char *profile_name, const char *name, const char *value, switch_stream_handle_t *stream) { skinny_profile_t *profile; @@ -403,6 +459,7 @@ SWITCH_STANDARD_API(skinny_function) "skinny profile device send SetLampMessage \n" "skinny profile device send SetSpeakerModeMessage \n" "skinny profile device send CallStateMessage \n" + "skinny profile device send [ =;... ] \n" "skinny profile set \n" "--------------------------------------------------------------------------------\n"; if (session) { @@ -465,6 +522,16 @@ SWITCH_STANDARD_API(skinny_function) status = skinny_api_cmd_profile_device_send_reset_message(argv[1], argv[3], argv[6], stream); } break; + case USER_TO_DEVICE_DATA_MESSAGE: + case USER_TO_DEVICE_DATA_VERSION1_MESSAGE: + if(argc == 8) { + /* [ =;... ] */ + status = skinny_api_cmd_profile_device_send_data(argv[1], argv[3], argv[5], argv[6], argv[7], stream); + } else if(argc == 7) { + /* */ + status = skinny_api_cmd_profile_device_send_data(argv[1], argv[3], argv[5], "", argv[6], stream); + } + break; default: stream->write_function(stream, "Unhandled message %s\n", argv[5]); } @@ -495,6 +562,8 @@ switch_status_t skinny_api_register(switch_loadable_module_interface_t **module_ switch_console_set_complete("add skinny profile ::skinny::list_profiles device ::skinny::list_devices send SetLampMessage ::skinny::list_stimuli ::skinny::list_stimulus_instances ::skinny::list_stimulus_modes"); switch_console_set_complete("add skinny profile ::skinny::list_profiles device ::skinny::list_devices send SetSpeakerModeMessage ::skinny::list_speaker_modes"); switch_console_set_complete("add skinny profile ::skinny::list_profiles device ::skinny::list_devices send CallStateMessage ::skinny::list_call_states ::skinny::list_line_instances ::skinny::list_call_ids"); + switch_console_set_complete("add skinny profile ::skinny::list_profiles device ::skinny::list_devices send UserToDeviceDataMessage"); + switch_console_set_complete("add skinny profile ::skinny::list_profiles device ::skinny::list_devices send UserToDeviceDataVersion1Message"); switch_console_set_complete("add skinny profile ::skinny::list_profiles set ::skinny::list_settings"); switch_console_add_complete_func("::skinny::list_profiles", skinny_api_list_profiles); diff --git a/src/mod/endpoints/mod_skinny/skinny_protocol.c b/src/mod/endpoints/mod_skinny/skinny_protocol.c index 465e41b21c..5486f0833d 100644 --- a/src/mod/endpoints/mod_skinny/skinny_protocol.c +++ b/src/mod/endpoints/mod_skinny/skinny_protocol.c @@ -902,6 +902,42 @@ switch_status_t send_reset(listener_t *listener, uint32_t reset_type) return skinny_send_reply(listener, message); } +switch_status_t send_extended_data(listener_t *listener, uint32_t message_type, + uint32_t application_id, + uint32_t line_instance, + uint32_t call_id, + uint32_t transaction_id, + uint32_t data_length, + uint32_t sequence_flag, + uint32_t display_priority, + uint32_t conference_id, + uint32_t app_instance_id, + uint32_t routing_id, + const char *data) +{ + skinny_message_t *message; + switch_assert(data_length == strlen(data)); + /* data_length should be a multiple of 4 */ + if ((data_length % 4) != 0) { + data_length = (data_length / 4 + 1) * 4; + } + message = switch_core_alloc(listener->pool, 12+sizeof(message->data.extended_data)+data_length-1); + message->type = message_type; + message->length = 4 + sizeof(message->data.extended_data)+data_length-1; + message->data.extended_data.application_id = application_id; + message->data.extended_data.line_instance = line_instance; + message->data.extended_data.call_id = call_id; + message->data.extended_data.transaction_id = transaction_id; + message->data.extended_data.data_length = data_length; + message->data.extended_data.sequence_flag = sequence_flag; + message->data.extended_data.display_priority = display_priority; + message->data.extended_data.conference_id = conference_id; + message->data.extended_data.app_instance_id = app_instance_id; + message->data.extended_data.routing_id = routing_id; + strncpy(message->data.extended_data.data, data, data_length); + return skinny_send_reply(listener, message); +} + switch_status_t skinny_perform_send_reply(listener_t *listener, const char *file, const char *func, int line, skinny_message_t *reply) { char *ptr; diff --git a/src/mod/endpoints/mod_skinny/skinny_protocol.h b/src/mod/endpoints/mod_skinny/skinny_protocol.h index 567c1b1003..b741fa9c8a 100644 --- a/src/mod/endpoints/mod_skinny/skinny_protocol.h +++ b/src/mod/endpoints/mod_skinny/skinny_protocol.h @@ -176,7 +176,7 @@ struct PACKED register_available_lines_message { /* DeviceToUserDataMessage */ #define DEVICE_TO_USER_DATA_MESSAGE 0x002E -struct PACKED device_to_user_data_message { +struct PACKED data_message { uint32_t application_id; uint32_t line_instance; uint32_t call_id; @@ -187,14 +187,7 @@ struct PACKED device_to_user_data_message { /* DeviceToUserDataResponseMessage */ #define DEVICE_TO_USER_DATA_RESPONSE_MESSAGE 0x002F -struct PACKED device_to_user_data_response_message { - uint32_t application_id; - uint32_t line_instance; - uint32_t call_id; - uint32_t transaction_id; - uint32_t data_length; - char data[1]; -}; +/* See struct PACKED data_message */ /* ServiceUrlStatReqMessage */ #define SERVICE_URL_STAT_REQ_MESSAGE 0x0033 @@ -210,7 +203,7 @@ struct PACKED feature_stat_req_message { /* DeviceToUserDataVersion1Message */ #define DEVICE_TO_USER_DATA_VERSION1_MESSAGE 0x0041 -struct PACKED device_to_user_data_version1_message { +struct PACKED extended_data_message { uint32_t application_id; uint32_t line_instance; uint32_t call_id; @@ -226,19 +219,7 @@ struct PACKED device_to_user_data_version1_message { /* DeviceToUserDataResponseVersion1Message */ #define DEVICE_TO_USER_DATA_RESPONSE_VERSION1_MESSAGE 0x0042 -struct PACKED device_to_user_data_response_version1_message { - uint32_t application_id; - uint32_t line_instance; - uint32_t call_id; - uint32_t transaction_id; - uint32_t data_length; - uint32_t sequence_flag; - uint32_t display_priority; - uint32_t conference_id; - uint32_t app_instance_id; - uint32_t routing_id; - char data[1]; -}; +/* See struct PACKED extended_data_message */ /* RegisterAckMessage */ #define REGISTER_ACK_MESSAGE 0x0081 @@ -535,14 +516,7 @@ struct PACKED dialed_number_message { /* UserToDeviceDataMessage */ #define USER_TO_DEVICE_DATA_MESSAGE 0x011E -struct PACKED user_to_device_data_message { - uint32_t application_id; - uint32_t line_instance; - uint32_t call_id; - uint32_t transaction_id; - uint32_t data_length; - char data[1]; -}; +/* See struct PACKED data_message */ /* FeatureStatMessage */ #define FEATURE_STAT_RES_MESSAGE 0x011F @@ -571,19 +545,7 @@ struct PACKED service_url_stat_res_message { /* UserToDeviceDataVersion1Message */ #define USER_TO_DEVICE_DATA_VERSION1_MESSAGE 0x013F -struct PACKED user_to_device_data_version1_message { - uint32_t application_id; - uint32_t line_instance; - uint32_t call_id; - uint32_t transaction_id; - uint32_t data_length; - uint32_t sequence_flag; - uint32_t display_priority; - uint32_t conference_id; - uint32_t app_instance_id; - uint32_t routing_id; - char data[1]; -}; +/* See struct PACKED extended_data_message */ /*****************************************************************************/ /* SKINNY MESSAGE */ @@ -615,12 +577,12 @@ union skinny_data { /* no data for SOFT_KEY_TEMPLATE_REQ_MESSAGE */ struct headset_status_message headset_status; struct register_available_lines_message reg_lines; - struct device_to_user_data_message d2u_data; - struct device_to_user_data_response_message d2u_data_response; + /* see field "data" for DEVICE_TO_USER_DATA_MESSAGE */ + /* see field "data" for DEVICE_TO_USER_DATA_RESPONSE_MESSAGE */ struct service_url_stat_req_message service_url_req; struct feature_stat_req_message feature_req; - struct device_to_user_data_version1_message d2u_data_v1; - struct device_to_user_data_response_version1_message d2u_data_response_v1; + /* see field "extended_data" for DEVICE_TO_USER_DATA_VERSION1_MESSAGE */ + /* see field "extended_data" for DEVICE_TO_USER_DATA_RESPONSE_VERSION1_MESSAGE */ struct register_ack_message reg_ack; struct start_tone_message start_tone; struct stop_tone_message stop_tone; @@ -652,11 +614,15 @@ union skinny_data { struct unregister_ack_message unregister_ack; struct back_space_req_message back_space_req; struct dialed_number_message dialed_number; - struct user_to_device_data_message u2d_data; + /* see field "data" for USER_TO_DEVICE_DATA_MESSAGE */ struct feature_stat_res_message feature_res; struct display_pri_notify_message display_pri_notify; struct service_url_stat_res_message service_url_res; - struct user_to_device_data_version1_message u2d_data_v1; + /* see field "extended_data" for USER_TO_DEVICE_DATA_VERSION1_MESSAGE */ + + struct data_message data; + struct extended_data_message extended_data; + uint16_t as_uint16; char as_char; void *raw; @@ -873,6 +839,19 @@ switch_status_t send_display_pri_notify(listener_t *listener, switch_status_t send_reset(listener_t *listener, uint32_t reset_type); +switch_status_t send_extended_data(listener_t *listener, uint32_t message_type, + uint32_t application_id, + uint32_t line_instance, + uint32_t call_id, + uint32_t transaction_id, + uint32_t data_length, + uint32_t sequence_flag, + uint32_t display_priority, + uint32_t conference_id, + uint32_t app_instance_id, + uint32_t routing_id, + const char *data); + #endif /* _SKINNY_PROTOCOL_H */ /* For Emacs: diff --git a/src/mod/endpoints/mod_skinny/skinny_server.c b/src/mod/endpoints/mod_skinny/skinny_server.c index 3fa4aab6c4..945611698b 100644 --- a/src/mod/endpoints/mod_skinny/skinny_server.c +++ b/src/mod/endpoints/mod_skinny/skinny_server.c @@ -1864,6 +1864,30 @@ switch_status_t skinny_handle_register_available_lines_message(listener_t *liste return SWITCH_STATUS_SUCCESS; } +switch_status_t skinny_handle_data_message(listener_t *listener, skinny_message_t *request) +{ + switch_event_t *event = NULL; + char *tmp = NULL; + skinny_check_data_length(request, sizeof(request->data.data)); + skinny_check_data_length(request, sizeof(request->data.data) + request->data.data.data_length - 1); + + /* skinny::device_to_user event */ + skinny_device_event(listener, &event, SWITCH_EVENT_CUSTOM, SKINNY_EVENT_DEVICE_TO_USER); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Skinny-DeviceToUser-Message-Id", "%d", request->type); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Skinny-DeviceToUser-Message-Id-String", "%s", skinny_message_type2str(request->type)); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Skinny-DeviceToUser-Application-Id", "%d", request->data.data.application_id); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Skinny-DeviceToUser-Line-Instance", "%d", request->data.data.line_instance); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Skinny-DeviceToUser-Call-Id", "%d", request->data.data.call_id); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Skinny-DeviceToUser-Transaction-Id", "%d", request->data.data.transaction_id); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Skinny-DeviceToUser-Data-Length", "%d", request->data.data.data_length); + tmp = strndup(request->data.data.data, request->data.data.data_length); + switch_event_add_body(event, tmp); + switch_safe_free(tmp); + switch_event_fire(&event); + + return SWITCH_STATUS_SUCCESS; +} + switch_status_t skinny_handle_service_url_stat_request(listener_t *listener, skinny_message_t *request) { skinny_message_t *message; @@ -1904,6 +1928,35 @@ switch_status_t skinny_handle_feature_stat_request(listener_t *listener, skinny_ return SWITCH_STATUS_SUCCESS; } +switch_status_t skinny_handle_extended_data_message(listener_t *listener, skinny_message_t *request) +{ + switch_event_t *event = NULL; + char *tmp = NULL; + skinny_check_data_length(request, sizeof(request->data.extended_data)); + skinny_check_data_length(request, sizeof(request->data.extended_data)+request->data.extended_data.data_length-1); + + /* skinny::device_to_user event */ + skinny_device_event(listener, &event, SWITCH_EVENT_CUSTOM, SKINNY_EVENT_DEVICE_TO_USER); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Skinny-DeviceToUser-Message-Id", "%d", request->type); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Skinny-DeviceToUser-Message-Id-String", "%s", skinny_message_type2str(request->type)); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Skinny-DeviceToUser-Application-Id", "%d", request->data.extended_data.application_id); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Skinny-DeviceToUser-Line-Instance", "%d", request->data.extended_data.line_instance); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Skinny-DeviceToUser-Call-Id", "%d", request->data.extended_data.call_id); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Skinny-DeviceToUser-Transaction-Id", "%d", request->data.extended_data.transaction_id); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Skinny-DeviceToUser-Data-Length", "%d", request->data.extended_data.data_length); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Skinny-DeviceToUser-Sequence-Flag", "%d", request->data.extended_data.sequence_flag); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Skinny-DeviceToUser-Display-Priority", "%d", request->data.extended_data.display_priority); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Skinny-DeviceToUser-Conference-Id", "%d", request->data.extended_data.conference_id); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Skinny-DeviceToUser-App-Instance-Id", "%d", request->data.extended_data.app_instance_id); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Skinny-DeviceToUser-Routing-Id", "%d", request->data.extended_data.routing_id); + tmp = strndup(request->data.extended_data.data, request->data.extended_data.data_length); + switch_event_add_body(event, tmp); + switch_safe_free(tmp); + switch_event_fire(&event); + + return SWITCH_STATUS_SUCCESS; +} + switch_status_t skinny_handle_request(listener_t *listener, skinny_message_t *request) { if (listener->profile->debug >= 10 || request->type != KEEP_ALIVE_MESSAGE) { @@ -1961,10 +2014,18 @@ switch_status_t skinny_handle_request(listener_t *listener, skinny_message_t *re return skinny_headset_status_message(listener, request); case REGISTER_AVAILABLE_LINES_MESSAGE: return skinny_handle_register_available_lines_message(listener, request); + case DEVICE_TO_USER_DATA_MESSAGE: + return skinny_handle_data_message(listener, request); + case DEVICE_TO_USER_DATA_RESPONSE_MESSAGE: + return skinny_handle_data_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); + case DEVICE_TO_USER_DATA_VERSION1_MESSAGE: + return skinny_handle_extended_data_message(listener, request); + case DEVICE_TO_USER_DATA_RESPONSE_VERSION1_MESSAGE: + return skinny_handle_extended_data_message(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);