]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
fixup and merge in FS-4027 enhancements for additional device support
authorNathan Neulinger <nneul@neulinger.org>
Fri, 12 Jul 2013 16:39:23 +0000 (11:39 -0500)
committerNathan Neulinger <nneul@neulinger.org>
Fri, 12 Jul 2013 16:39:23 +0000 (11:39 -0500)
src/mod/endpoints/mod_skinny/skinny_protocol.c
src/mod/endpoints/mod_skinny/skinny_protocol.h
src/mod/endpoints/mod_skinny/skinny_server.c

index 3e1748d6e2ac1e3fd85a2b695309dc1f28729f72..677c703b398dce5a7c5fb4c8a8b610361552f92a 100644 (file)
@@ -623,6 +623,26 @@ switch_status_t perform_send_set_speaker_mode(listener_t *listener,
        return skinny_send_reply_quiet(listener, message);
 }
 
+switch_status_t perform_send_srvreq_response(listener_t *listener, 
+               const char *file, const char *func, int line,
+               char *ip, uint32_t port)
+{
+       skinny_message_t *message;
+
+       message = switch_core_alloc(listener->pool, 12+sizeof(message->data.serv_res_mess));
+       message->type = SERVER_RESPONSE_MESSAGE;
+       message->length = 4 + sizeof(message->data.serv_res_mess);
+
+       message->data.serv_res_mess.serverListenPort[0] = port;
+       switch_inet_pton(AF_INET,ip, &message->data.serv_res_mess.serverIpAddr[0]);
+       switch_copy_string(message->data.serv_res_mess.server[0].serverName,ip,sizeof(message->data.serv_res_mess.server[0].serverName));
+
+       skinny_log_l_ffl(listener, file, func, line, SWITCH_LOG_DEBUG,
+               "Sending Server Request Response with IP (%s) and Port (%d)\n", ip, port);
+
+       return skinny_send_reply(listener, message);
+}
+
 switch_status_t perform_send_start_media_transmission(listener_t *listener,
                const char *file, const char *func, int line,
                uint32_t conference_id,
index 5127b1b54b15e4841d7c6b23747fd4c531407cf2..9bdd584b69d72ca65a5b67917ed6c3652f6a0490 100644 (file)
 /* mod_skinny.h should be loaded first */
 #include "mod_skinny.h"
 
+/*****************************************************************************/
+/* SKINNY TYPES */
+/*****************************************************************************/
+typedef enum {
+       SKINNY_CODEC_NONE = 0,
+       SKINNY_CODEC_NONSTANDARD = 1,
+       SKINNY_CODEC_ALAW_64K = 2,
+       SKINNY_CODEC_ALAW_56K = 3,
+       SKINNY_CODEC_ULAW_64K = 4,
+       SKINNY_CODEC_ULAW_56K = 5,
+       SKINNY_CODEC_G722_64K = 6,
+       SKINNY_CODEC_G722_56K = 7,
+       SKINNY_CODEC_G722_48K = 8,
+       SKINNY_CODEC_G723_1 = 9,
+       SKINNY_CODEC_G728 = 10,
+       SKINNY_CODEC_G729 = 11,
+       SKINNY_CODEC_G729A = 12,
+       SKINNY_CODEC_IS11172 = 13,
+       SKINNY_CODEC_IS13818 = 14,
+       SKINNY_CODEC_G729B = 15,
+       SKINNY_CODEC_G729AB = 16,
+       SKINNY_CODEC_GSM_FULL = 18,
+       SKINNY_CODEC_GSM_HALF = 19,
+       SKINNY_CODEC_GSM_EFULL = 20,
+       SKINNY_CODEC_WIDEBAND_256K = 25,
+       SKINNY_CODEC_DATA_64K = 32,
+       SKINNY_CODEC_DATA_56K = 33,
+       SKINNY_CODEC_G722_1_32K = 40,
+       SKINNY_CODEC_G722_1_24K = 41,
+       SKINNY_CODEC_GSM = 80,
+       SKINNY_CODEC_ACTIVEVOICE = 81,
+       SKINNY_CODEC_G726_32K = 82,
+       SKINNY_CODEC_G726_24K = 83,
+       SKINNY_CODEC_G726_16K = 84,
+       SKINNY_CODEC_G729B_BIS = 85,
+       SKINNY_CODEC_G729B_LOW = 86,
+       SKINNY_CODEC_H261 = 100,
+       SKINNY_CODEC_H263 = 101,
+       SKINNY_CODEC_VIDEO = 102,
+       SKINNY_CODEC_H264 = 103,
+       SKINNY_CODEC_T120 = 105,
+       SKINNY_CODEC_H224 = 106,
+       SKINNY_CODEC_RFC2833_DYNPAYLOAD = 257
+} skinny_codecs;
+
+char* skinny_codec2string(skinny_codecs skinnycodec);
+
 /*****************************************************************************/
 /* SKINNY MESSAGE DATA */
 /*****************************************************************************/
@@ -211,6 +258,145 @@ struct PACKED data_message {
 
 #define DEVICE_UPDATECAPABILITIES 0x0030
 
+#define MAX_CUSTOM_PICTURES                                            6
+#define MAX_LAYOUT_WITH_SAME_SERVICE                   5
+#define MAX_SERVICE_TYPE                                               4
+#define SKINNY_MAX_CAPABILITIES                                        18      /*!< max capabilities allowed in Cap response message */
+#define SKINNY_MAX_VIDEO_CAPABILITIES                  10
+#define SKINNY_MAX_DATA_CAPABILITIES                   5
+#define MAX_LEVEL_PREFERENCE                                   4
+
+/*!
+ * \brief Picture Format Structure
+ */
+typedef struct {
+       uint32_t customPictureFormatWidth;                                      /*!< Picture Width */
+       uint32_t customPictureFormatHeight;                                     /*!< Picture Height */
+       uint32_t customPictureFormatpixelAspectRatio;                           /*!< Picture Pixel Aspect Ratio */
+       uint32_t customPictureFormatpixelclockConversionCode;                   /*!< Picture Pixel Conversion Code  */
+       uint32_t customPictureFormatpixelclockDivisor;                          /*!< Picture Pixel Divisor */
+} customPictureFormat_t;
+
+
+/*!
+ * \brief Video Level Preference Structure
+ */
+typedef struct {
+       uint32_t transmitPreference;                                            /*!< Transmit Preference */
+       uint32_t format;                                                        /*!< Format / Codec */
+       uint32_t maxBitRate;                                                    /*!< Maximum BitRate */
+       uint32_t minBitRate;                                                    /*!< Minimum BitRate */
+       uint32_t MPI;                                                           /*!<  */
+       uint32_t serviceNumber;                                                 /*!< Service Number */
+} levelPreference_t;                                                            /*!< Level Preference Structure */
+
+/*! 
+ * \brief Layout Config Structure (Update Capabilities Message Struct)
+ * \since 20080111
+ */
+typedef struct {
+       uint32_t layout;                                                        /*!< Layout \todo what is layout? */
+} layoutConfig_t;                                                               /*!< Layout Config Structure */
+
+
+/*!
+ * \brief Service Resource Structure
+ */
+typedef struct {
+       uint32_t layoutCount;                                                   /*!< Layout Count */
+       layoutConfig_t layout[MAX_LAYOUT_WITH_SAME_SERVICE];                    /*!< Layout */
+       uint32_t serviceNum;                                                    /*!< Service Number */
+       uint32_t maxStreams;                                                    /*!< Maximum number of Streams */
+       uint32_t maxConferences;                                                /*!< Maximum number of Conferences */
+       uint32_t activeConferenceOnRegistration;                                /*!< Active Conference On Registration */
+} serviceResource_t;
+
+
+
+/*!
+ * \brief Audio Capabilities Structure
+ */
+typedef struct {
+       skinny_codecs lel_payloadCapability;                                   /*!< PayLoad Capability */
+       uint32_t lel_maxFramesPerPacket;                                        /*!< Maximum Number of Frames per IP Packet */
+       uint32_t lel_unknown[2];                                                /*!< this are related to G.723 */
+} audioCap_t;  
+
+/*!
+ * \brief Video Capabilities Structure
+ */
+typedef struct {
+       skinny_codecs lel_payloadCapability;                                   /*!< PayLoad Capability */
+       uint32_t lel_transmitOreceive;                                          /*!< Transmit of Receive */
+       uint32_t lel_levelPreferenceCount;                                      /*!< Level of Preference Count */
+
+       levelPreference_t levelPreference[MAX_LEVEL_PREFERENCE];                /*!< Level Preference */
+
+//      uint32_t lel_codec_options[2];                                          /*!< Codec Options */
+
+       union {
+                struct {
+                        uint32_t unknown1;
+                        uint32_t unknown2;
+                } h263;
+                struct {
+                        uint32_t profile;                                       /*!< H264 profile */
+                        uint32_t level;                                         /*!< H264 level */
+                } h264;
+        } codec_options;
+
+        /**
+         * Codec options contains data specific for every codec
+         *
+         * Here is a list of known parameters per codec
+        // H.261
+        uint32_t                lel_temporalSpatialTradeOffCapability;
+        uint32_t                lel_stillImageTransmission;
+
+        // H.263
+        uint32_t                lel_h263_capability_bitfield;
+        uint32_t                lel_annexNandWFutureUse;
+
+        // Video
+        uint32_t                lel_modelNumber;
+        uint32_t                lel_bandwidth;
+        */
+} videoCap_t;                                                                   /*!< Video Capabilities Structure */
+
+/*!
+ * \brief Data Capabilities Structure
+ */
+typedef struct {
+       uint32_t payloadCapability;                                             /*!< Payload Capability */
+       uint32_t transmitOrReceive;                                             /*!< Transmit or Receive */
+       uint32_t protocolDependentData;                                         /*!< Protocol Dependent Data */
+       uint32_t maxBitRate;                                                    /*!< Maximum BitRate */
+} dataCap_t;                                                                    /*!< Data Capabilities Structure */
+
+
+struct PACKED update_capabilities_message {
+       uint32_t lel_audioCapCount;                                     /*!< Audio Capability Count */
+       uint32_t lel_videoCapCount;                                     /*!< Video Capability Count */
+       uint32_t lel_dataCapCount;                                      /*!< Data Capability Count */
+       uint32_t RTPPayloadFormat;                                      /*!< RTP Payload Format */
+       uint32_t customPictureFormatCount;                              /*!< Custom Picture Format Count */
+
+       customPictureFormat_t customPictureFormat[MAX_CUSTOM_PICTURES]; /*!< Custom Picture Format */
+
+       uint32_t activeStreamsOnRegistration;                           /*!< Active Streams on Registration */
+       uint32_t maxBW;                                                 /*!< Max BW ?? */
+
+       uint32_t serviceResourceCount;                                  /*!< Service Resource Count */
+       serviceResource_t serviceResource[MAX_SERVICE_TYPE];            /*!< Service Resource */
+
+       audioCap_t audioCaps[SKINNY_MAX_CAPABILITIES];                  /*!< Audio Capabilities */
+       videoCap_t videoCaps[SKINNY_MAX_VIDEO_CAPABILITIES];            /*!< Video Capabilities */
+       dataCap_t dataCaps[SKINNY_MAX_DATA_CAPABILITIES];               /*!< Data Capabilities */
+
+       uint32_t unknown;                                               /*!< Unknown */
+}; 
+
+
 /* ServiceUrlStatReqMessage */
 #define SERVICE_URL_STAT_REQ_MESSAGE 0x0033
 struct PACKED service_url_stat_req_message {
@@ -447,6 +633,21 @@ struct PACKED register_reject_message {
 };
 
 #define SERVER_RESPONSE_MESSAGE 0x009E
+#define ServerMaxNameSize                       48
+#define StationMaxServers                       5
+/*!
+ * \brief Station Identifier Structure
+ */
+typedef struct {
+       char serverName[ServerMaxNameSize];                                     /*!< Server Name */
+} ServerIdentifier;
+
+struct PACKED server_response_message {
+       ServerIdentifier server[StationMaxServers];                     /*!< Server Identifier */
+       uint32_t serverListenPort[StationMaxServers];                   /*!< Server is Listening on Port */
+       uint32_t serverIpAddr[StationMaxServers];                       /*!< Server IP Port */
+};                                                     /*!< Server Result Message Structure */
+
 
 /* ResetMessage */
 #define RESET_MESSAGE 0x009F
@@ -676,6 +877,7 @@ union skinny_data {
        /* no data for CAPABILITIES_REQ_MESSAGE */
        struct register_reject_message reg_rej;
        struct reset_message reset;
+       struct server_response_message serv_res_mess;
        /* no data for KEEP_ALIVE_ACK_MESSAGE */
        struct open_receive_channel_message open_receive_channel;
        struct close_receive_channel_message close_receive_channel;
@@ -696,6 +898,7 @@ union skinny_data {
        /* see field "extended_data" for USER_TO_DEVICE_DATA_VERSION1_MESSAGE */
        struct dialed_phone_book_ack_message dialed_phone_book_ack;
 
+       struct update_capabilities_message upd_cap;
        struct data_message data;
        struct extended_data_message extended_data;
 
@@ -725,52 +928,7 @@ struct PACKED skinny_message {
 
 typedef struct skinny_message skinny_message_t;
 
-/*****************************************************************************/
-/* SKINNY TYPES */
-/*****************************************************************************/
-typedef enum {
-       SKINNY_CODEC_NONE = 0,
-       SKINNY_CODEC_NONSTANDARD = 1,
-       SKINNY_CODEC_ALAW_64K = 2,
-       SKINNY_CODEC_ALAW_56K = 3,
-       SKINNY_CODEC_ULAW_64K = 4,
-       SKINNY_CODEC_ULAW_56K = 5,
-       SKINNY_CODEC_G722_64K = 6,
-       SKINNY_CODEC_G722_56K = 7,
-       SKINNY_CODEC_G722_48K = 8,
-       SKINNY_CODEC_G723_1 = 9,
-       SKINNY_CODEC_G728 = 10,
-       SKINNY_CODEC_G729 = 11,
-       SKINNY_CODEC_G729A = 12,
-       SKINNY_CODEC_IS11172 = 13,
-       SKINNY_CODEC_IS13818 = 14,
-       SKINNY_CODEC_G729B = 15,
-       SKINNY_CODEC_G729AB = 16,
-       SKINNY_CODEC_GSM_FULL = 18,
-       SKINNY_CODEC_GSM_HALF = 19,
-       SKINNY_CODEC_GSM_EFULL = 20,
-       SKINNY_CODEC_WIDEBAND_256K = 25,
-       SKINNY_CODEC_DATA_64K = 32,
-       SKINNY_CODEC_DATA_56K = 33,
-       SKINNY_CODEC_G722_1_32K = 40,
-       SKINNY_CODEC_G722_1_24K = 41,
-       SKINNY_CODEC_GSM = 80,
-       SKINNY_CODEC_ACTIVEVOICE = 81,
-       SKINNY_CODEC_G726_32K = 82,
-       SKINNY_CODEC_G726_24K = 83,
-       SKINNY_CODEC_G726_16K = 84,
-       SKINNY_CODEC_G729B_BIS = 85,
-       SKINNY_CODEC_G729B_LOW = 86,
-       SKINNY_CODEC_H261 = 100,
-       SKINNY_CODEC_H263 = 101,
-       SKINNY_CODEC_VIDEO = 102,
-       SKINNY_CODEC_H264 = 103,
-       SKINNY_CODEC_T120 = 105,
-       SKINNY_CODEC_H224 = 106,
-       SKINNY_CODEC_RFC2833_DYNPAYLOAD = 257
-} skinny_codecs;
 
-char* skinny_codec2string(skinny_codecs skinnycodec);
 
 /*****************************************************************************/
 /* SKINNY FUNCTIONS */
@@ -862,6 +1020,11 @@ switch_status_t perform_send_set_speaker_mode(listener_t *listener,
                uint32_t mode);
 #define send_set_speaker_mode(listener, ...) perform_send_set_speaker_mode(listener, __FILE__, __SWITCH_FUNC__, __LINE__, __VA_ARGS__)
 
+switch_status_t perform_send_srvreq_response(listener_t *listener,
+               const char *file, const char *func, int line,
+               char *ip, uint32_t port);
+#define send_srvreq_response(listener, ...) perform_send_srvreq_response(listener, __FILE__, __SWITCH_FUNC__, __LINE__, __VA_ARGS__)
+
 switch_status_t perform_send_start_media_transmission(listener_t *listener,
                const char *file, const char *func, int line,
                uint32_t conference_id,
index 2b7031186d8ee38cd4d87dc59dc0324b8b44a525..450584b5540ec2ee74a122d8f94ebf94f10af6c9 100644 (file)
@@ -2184,6 +2184,79 @@ switch_status_t skinny_handle_accessory_status_message(listener_t *listener, ski
        return SWITCH_STATUS_SUCCESS;
 }
 
+switch_status_t skinny_handle_updatecapabilities(listener_t *listener, skinny_message_t *request)
+{
+       char *sql;
+       skinny_profile_t *profile;
+
+       uint32_t i = 0;
+       uint32_t n = 0;
+       char *codec_order[SWITCH_MAX_CODECS];
+       char *codec_string;
+
+       size_t string_len, string_pos, pos;
+
+       switch_assert(listener->profile);
+       switch_assert(listener->device_name);
+
+       profile = listener->profile;
+
+       skinny_check_data_length(request, sizeof(request->data.upd_cap.lel_audioCapCount));
+
+       n = request->data.upd_cap.lel_audioCapCount;
+       if (n > SWITCH_MAX_CODECS) {
+               n = SWITCH_MAX_CODECS;
+       }
+       string_len = -1;
+
+       skinny_check_data_length(request, sizeof(request->data.upd_cap.lel_audioCapCount) + n * sizeof(request->data.upd_cap.audioCaps[0]));
+
+       for (i = 0; i < n; i++) {
+               char *codec = skinny_codec2string(request->data.upd_cap.audioCaps[i].lel_payloadCapability);
+               codec_order[i] = codec;
+               string_len += strlen(codec)+1;
+       }
+       i = 0;
+       pos = 0;
+       codec_string = switch_core_alloc(listener->pool, string_len+1);
+       for (string_pos = 0; string_pos < string_len; string_pos++) {
+               char *codec = codec_order[i];
+               switch_assert(i < n);
+               if(pos == strlen(codec)) {
+                       codec_string[string_pos] = ',';
+                       i++;
+                       pos = 0;
+               } else {
+                       codec_string[string_pos] = codec[pos++];
+               }
+       }
+       codec_string[string_len] = '\0';
+       if ((sql = switch_mprintf(
+                                       "UPDATE skinny_devices SET codec_string='%s' WHERE name='%s'",
+                                       codec_string,
+                                       listener->device_name
+                                ))) {
+               skinny_execute_sql(profile, sql, profile->sql_mutex);
+               switch_safe_free(sql);
+       }
+       switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG,
+                       "Codecs %s supported.\n", codec_string);
+       return SWITCH_STATUS_SUCCESS;
+}
+
+
+switch_status_t skinny_handle_server_req_message(listener_t *listener, skinny_message_t *request)
+{
+       skinny_profile_t *profile;
+
+       profile = listener->profile;
+
+       skinny_log_l(listener, SWITCH_LOG_INFO, "Received Server Request Message (length=%d).\n", request->length);
+
+       send_srvreq_response(listener, profile->ip, profile->port);
+       return SWITCH_STATUS_SUCCESS;
+}
+
 switch_status_t skinny_handle_xml_alarm(listener_t *listener, skinny_message_t *request)
 {
        switch_event_t *event = NULL;
@@ -2209,7 +2282,7 @@ switch_status_t skinny_handle_request(listener_t *listener, skinny_message_t *re
                skinny_log_l(listener, SWITCH_LOG_DEBUG, "Received %s (type=%x,length=%d).\n",
                        skinny_message_type2str(request->type), request->type, request->length);
        }
-       if(zstr(listener->device_name) && request->type != REGISTER_MESSAGE && request->type != ALARM_MESSAGE && request->type != XML_ALARM_MESSAGE) {
+       if(zstr(listener->device_name) && request->type != REGISTER_MESSAGE && request->type != ALARM_MESSAGE && request->type != XML_ALARM_MESSAGE && request->type != KEEP_ALIVE_MESSAGE) {
                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING,
                                "Device should send a register message first. Received %s (type=%x,length=%d).\n", skinny_message_type2str(request->type), request->type, request->length);
                return SWITCH_STATUS_FALSE;
@@ -2281,6 +2354,10 @@ switch_status_t skinny_handle_request(listener_t *listener, skinny_message_t *re
                        return skinny_handle_accessory_status_message(listener, request);
                case XML_ALARM_MESSAGE:
                        return skinny_handle_xml_alarm(listener, request);
+               case DEVICE_UPDATECAPABILITIES:
+                       return skinny_handle_updatecapabilities(listener, request);
+               case SERVER_REQ_MESSAGE:
+                       return skinny_handle_server_req_message(listener, request);         
                default:
                        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING,
                                        "Unhandled %s (type=%x,length=%d).\n", skinny_message_type2str(request->type), request->type, request->length);