Add skinny version 17 protocol support.
authorDamien Wedhorn <voip@facts.com.au>
Mon, 10 Oct 2011 00:57:06 +0000 (00:57 +0000)
committerDamien Wedhorn <voip@facts.com.au>
Mon, 10 Oct 2011 00:57:06 +0000 (00:57 +0000)
Added some data to skinny packet structures to make compatible
with v17. Added protocolversion to device, set on registration
based on the version provided by device.

v17 includes some increased ip space for ip6. This patch increases
ip space in the packets but still only uses ip4. Some packet
structures duplicated (ip4 and ip6 types). ip4 type used unless
version is greater or equal to 17.

Tested by snuff and myself on 7961 with recent 8.5 firmware. Also
tested compatible with old 7960 and older 30VIPs.

git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@340071 65c4cc65-6c06-0410-ace0-fbb531ad65f3

channels/chan_skinny.c

index 7c5ca90..070ad7b 100644 (file)
@@ -273,6 +273,9 @@ struct register_message {
        uint32_t ip;
        uint32_t type;
        uint32_t maxStreams;
+       uint32_t space;
+       uint8_t protocolVersion;
+       char space2[3] ;
 };
 
 #define IP_PORT_MESSAGE 0x0002
@@ -350,11 +353,18 @@ struct alarm_message {
 };
 
 #define OPEN_RECEIVE_CHANNEL_ACK_MESSAGE 0x0022
-struct open_receive_channel_ack_message {
+struct open_receive_channel_ack_message_ip4 {
        uint32_t status;
        uint32_t ipAddr;
        uint32_t port;
-       uint32_t passThruId;
+       uint32_t callReference;
+};
+struct open_receive_channel_ack_message_ip6 {
+       uint32_t status;
+       uint32_t space;
+       char ipAddr[16];
+       uint32_t port;
+       uint32_t callReference;
 };
 
 #define SOFT_KEY_SET_REQ_MESSAGE 0x0025
@@ -392,6 +402,7 @@ struct start_tone_message {
 struct stop_tone_message {
        uint32_t instance;
        uint32_t reference;
+       uint32_t space;
 };
 
 #define SET_RINGER_MESSAGE 0x0085
@@ -424,11 +435,11 @@ struct set_microphone_message {
 struct media_qualifier {
        uint32_t precedence;
        uint32_t vad;
-       uint16_t packets;
+       uint32_t packets;
        uint32_t bitRate;
 };
 
-struct start_media_transmission_message {
+struct start_media_transmission_message_ip4 {
        uint32_t conferenceId;
        uint32_t passThruPartyId;
        uint32_t remoteIp;
@@ -436,7 +447,19 @@ struct start_media_transmission_message {
        uint32_t packetSize;
        uint32_t payloadType;
        struct media_qualifier qualifier;
-       uint32_t space[16];
+       uint32_t space[19];
+};
+
+struct start_media_transmission_message_ip6 {
+       uint32_t conferenceId;
+       uint32_t passThruPartyId;
+       uint32_t space;
+       char remoteIp[16];
+       uint32_t remotePort;
+       uint32_t packetSize;
+       uint32_t payloadType;
+       struct media_qualifier qualifier;
+       uint32_t space2[19];
 };
 
 #define STOP_MEDIA_TRANSMISSION_MESSAGE 0x008B
@@ -580,6 +603,9 @@ struct displaytext_message {
 
 #define CLEAR_NOTIFY_MESSAGE  0x0115
 #define CLEAR_DISPLAY_MESSAGE 0x009A
+struct clear_display_message {
+       uint32_t space;
+};
 
 #define CAPABILITIES_REQ_MESSAGE 0x009B
 
@@ -614,7 +640,7 @@ struct open_receive_channel_message {
        uint32_t capability;
        uint32_t echo;
        uint32_t bitrate;
-       uint32_t space[16];
+       uint32_t space[36];
 };
 
 #define CLOSE_RECEIVE_CHANNEL_MESSAGE 0x0106
@@ -1012,6 +1038,7 @@ union skinny_data {
        struct version_res_message version;
        struct button_template_res_message buttontemplate;
        struct displaytext_message displaytext;
+       struct clear_display_message cleardisplay;
        struct display_prompt_status_message displaypromptstatus;
        struct clear_prompt_message clearpromptstatus;
        struct definetimedate_message definetimedate;
@@ -1036,10 +1063,12 @@ union skinny_data {
        struct set_speaker_message setspeaker;
        struct set_microphone_message setmicrophone;
        struct call_info_message callinfo;
-       struct start_media_transmission_message startmedia;
+       struct start_media_transmission_message_ip4 startmedia_ip4;
+       struct start_media_transmission_message_ip6 startmedia_ip6;
        struct stop_media_transmission_message stopmedia;
        struct open_receive_channel_message openreceivechannel;
-       struct open_receive_channel_ack_message openreceivechannelack;
+       struct open_receive_channel_ack_message_ip4 openreceivechannelack_ip4;
+       struct open_receive_channel_ack_message_ip6 openreceivechannelack_ip6;
        struct close_receive_channel_message closereceivechannel;
        struct display_notify_message displaynotify;
        struct dialed_number_message dialednumber;
@@ -1382,6 +1411,7 @@ struct skinny_addon {
        char version_id[16];                                    \
        char vmexten[AST_MAX_EXTENSION];                        \
        int type;                                               \
+       int protocolversion;                            \
        int registered;                                         \
        int hookstate;                                  \
        int lastlineinstance;                                   \
@@ -2057,6 +2087,7 @@ static int skinny_register(struct skinny_req *req, struct skinnysession *s)
                                && ast_apply_ha(d->ha, &addr)) {
                        s->device = d;
                        d->type = letohl(req->data.reg.type);
+                       d->protocolversion = letohl(req->data.reg.protocolVersion);
                        if (ast_strlen_zero(d->version_id)) {
                                ast_copy_string(d->version_id, version_id, sizeof(d->version_id));
                        }
@@ -2582,7 +2613,7 @@ static void transmit_ringer_mode(struct skinny_device *d, int mode)
 static void transmit_clear_display_message(struct skinny_device *d, int instance, int reference)
 {
        struct skinny_req *req;
-       if (!(req = req_alloc(0, CLEAR_DISPLAY_MESSAGE)))
+       if (!(req = req_alloc(sizeof(struct clear_display_message), CLEAR_DISPLAY_MESSAGE)))
                return;
 
        //what do we want hear CLEAR_DISPLAY_MESSAGE or CLEAR_PROMPT_STATUS???
@@ -2706,19 +2737,33 @@ static void transmit_startmediatransmission(struct skinny_device *d, struct skin
 {
        struct skinny_req *req;
 
-       if (!(req = req_alloc(sizeof(struct start_media_transmission_message), START_MEDIA_TRANSMISSION_MESSAGE)))
-               return;
-
-       req->data.startmedia.conferenceId = htolel(sub->callid);
-       req->data.startmedia.passThruPartyId = htolel(sub->callid);
-       req->data.startmedia.remoteIp = dest.sin_addr.s_addr;
-       req->data.startmedia.remotePort = htolel(ntohs(dest.sin_port));
-       req->data.startmedia.packetSize = htolel(fmt.cur_ms);
-       req->data.startmedia.payloadType = htolel(codec_ast2skinny(&fmt.format));
-       req->data.startmedia.qualifier.precedence = htolel(127);
-       req->data.startmedia.qualifier.vad = htolel(0);
-       req->data.startmedia.qualifier.packets = htolel(0);
-       req->data.startmedia.qualifier.bitRate = htolel(0);
+       if (d->protocolversion < 17) {
+               if (!(req = req_alloc(sizeof(struct start_media_transmission_message_ip4), START_MEDIA_TRANSMISSION_MESSAGE)))
+                       return;
+               req->data.startmedia_ip4.conferenceId = htolel(sub->callid);
+               req->data.startmedia_ip4.passThruPartyId = htolel(sub->callid);
+               req->data.startmedia_ip4.remoteIp = dest.sin_addr.s_addr;
+               req->data.startmedia_ip4.remotePort = htolel(ntohs(dest.sin_port));
+               req->data.startmedia_ip4.packetSize = htolel(fmt.cur_ms);
+               req->data.startmedia_ip4.payloadType = htolel(codec_ast2skinny(&fmt.format));
+               req->data.startmedia_ip4.qualifier.precedence = htolel(127);
+               req->data.startmedia_ip4.qualifier.vad = htolel(0);
+               req->data.startmedia_ip4.qualifier.packets = htolel(0);
+               req->data.startmedia_ip4.qualifier.bitRate = htolel(0);
+       } else {
+               if (!(req = req_alloc(sizeof(struct start_media_transmission_message_ip6), START_MEDIA_TRANSMISSION_MESSAGE)))
+                       return;
+               req->data.startmedia_ip6.conferenceId = htolel(sub->callid);
+               req->data.startmedia_ip6.passThruPartyId = htolel(sub->callid);
+               memcpy(req->data.startmedia_ip6.remoteIp, &dest.sin_addr.s_addr, sizeof(dest.sin_addr.s_addr));
+               req->data.startmedia_ip6.remotePort = htolel(ntohs(dest.sin_port));
+               req->data.startmedia_ip6.packetSize = htolel(fmt.cur_ms);
+               req->data.startmedia_ip6.payloadType = htolel(codec_ast2skinny(&fmt.format));
+               req->data.startmedia_ip6.qualifier.precedence = htolel(127);
+               req->data.startmedia_ip6.qualifier.vad = htolel(0);
+               req->data.startmedia_ip6.qualifier.packets = htolel(0);
+               req->data.startmedia_ip6.qualifier.bitRate = htolel(0);
+       }
        transmit_response(d, req);
 }
 
@@ -6181,25 +6226,33 @@ static int handle_open_receive_channel_ack_message(struct skinny_req *req, struc
        uint32_t addr;
        int port;
        int status;
-       int passthruid;
+       int callid;
 
-       status = letohl(req->data.openreceivechannelack.status);
+       status = (d->protocolversion<17)?letohl(req->data.openreceivechannelack_ip4.status):letohl(req->data.openreceivechannelack_ip6.status);
        if (status) {
                ast_log(LOG_ERROR, "Open Receive Channel Failure\n");
                return 0;
        }
-       addr = req->data.openreceivechannelack.ipAddr;
-       port = letohl(req->data.openreceivechannelack.port);
-       passthruid = letohl(req->data.openreceivechannelack.passThruId);
+       if (d->protocolversion<17) {
+               addr = req->data.openreceivechannelack_ip4.ipAddr;
+               port = letohl(req->data.openreceivechannelack_ip4.port);
+               callid = letohl(req->data.openreceivechannelack_ip4.callReference);
+       } else {
+               memcpy(&addr, &req->data.openreceivechannelack_ip6.ipAddr, sizeof(addr));
+               port = letohl(req->data.openreceivechannelack_ip6.port);
+               callid = letohl(req->data.openreceivechannelack_ip6.callReference);
+       }
 
        sin.sin_family = AF_INET;
        sin.sin_addr.s_addr = addr;
        sin.sin_port = htons(port);
 
-       sub = find_subchannel_by_reference(d, passthruid);
+       sub = find_subchannel_by_reference(d, callid);
 
-       if (!sub)
+       if (!sub) {
+               ast_log(LOG_ERROR, "Open Receive Channel Failure - can't find sub for %d\n", callid);
                return 0;
+       }
 
        l = sub->line;
 
@@ -6602,7 +6655,7 @@ static int handle_message(struct skinny_req *req, struct skinnysession *s)
        case REGISTER_MESSAGE:
                if (skinny_register(req, s)) {
                        ast_atomic_fetchadd_int(&unauth_sessions, -1);
-                       ast_verb(3, "Device '%s' successfully registered\n", s->device->name);
+                       ast_verb(3, "Device '%s' successfully registered (protoVers %d)\n", s->device->name, s->device->protocolversion);
                        transmit_registerack(s->device);
                        transmit_capabilitiesreq(s->device);
                } else {