diff --git a/channels/chan_skinny.c b/channels/chan_skinny.c index 7c5ca907bc..070ad7b809 100644 --- a/channels/chan_skinny.c +++ b/channels/chan_skinny.c @@ -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 {