1 /*!
2  * \file        sccp_protocol.c
3  * \brief       SCCP Protocol implementation.
4  * This file does the protocol implementation only. It should not be used as a controller.
5  * \author      Marcello Ceschia <marcello.ceschia [at] users.sourceforge.net>
6  * \note                This program is free software and may be modified and distributed under the terms of the GNU Public License.
7  *              See the LICENSE file at the top of the source tree.
8  *
9  */
10 
11 #include "config.h"
12 #include "common.h"
13 #include "sccp_channel.h"
14 #include "sccp_device.h"
15 #include "sccp_enum.h"
16 #include "sccp_line.h"
17 #include "sccp_protocol.h"
18 #include "sccp_linedevice.h"
19 #include "sccp_session.h"
20 #include "sccp_utils.h"
21 #include <asterisk/unaligned.h>
22 SCCP_FILE_VERSION(__FILE__, "");
23 
24 /*!
25  * \brief Build an SCCP Message Packet
26  * \param[in] t SCCP Message Text
27  * \param[out] pkt_len Packet Length
28  * \return SCCP Message
29  */
sccp_build_packet(sccp_mid_t t,size_t pkt_len)30 messagePtr __attribute__((malloc)) sccp_build_packet(sccp_mid_t t, size_t pkt_len)
31 {
32 	int padding = ((pkt_len + 8) % 4);
33 	padding = (padding > 0) ? 4 - padding : 0;
34 
35 	sccp_msg_t * msg = (sccp_msg_t *)sccp_calloc(1, pkt_len + SCCP_PACKET_HEADER + padding);
36 
37 	if(!msg) {
38 		pbx_log(LOG_WARNING, "SCCP: Packet memory allocation error\n");
39 		return NULL;
40 	}
41 	msg->header.length = htolel(pkt_len + 4 + padding);
42 	msg->header.lel_messageId = htolel(t);
43 
44 	// sccp_log(DEBUGCAT_DEVICE)("SCCP: (sccp_build_packet) created packet type:0x%x, msg_size=%lu, hdr_len=%lu\n", t, pkt_len + SCCP_PACKET_HEADER + padding, pkt_len + 4 + padding)
45 	return msg;
46 }
47 
48 /* CallInfo Message */
49 
50 /* =================================================================================================================== Send Messages */
sccp_protocol_sendCallInfoV3(const sccp_callinfo_t * const ci,const uint32_t callid,const skinny_calltype_t calltype,const uint8_t lineInstance,const uint8_t callInstance,const skinny_callsecuritystate_t callsecurityState,constDevicePtr device)51 static void sccp_protocol_sendCallInfoV3 (const sccp_callinfo_t * const ci, const uint32_t callid, const skinny_calltype_t calltype, const uint8_t lineInstance, const uint8_t callInstance, const skinny_callsecuritystate_t callsecurityState, constDevicePtr device)
52 {
53  	pbx_assert(device != NULL);
54 	sccp_msg_t * msg = NULL;
55 
56 	REQ(msg, CallInfoMessage);
57 
58 	int originalCdpnRedirectReason = 0;
59 	int lastRedirectingReason = 0;
60 	sccp_callerid_presentation_t presentation = CALLERID_PRESENTATION_ALLOWED;
61 
62 	iCallInfo.Getter(ci,
63 		SCCP_CALLINFO_CALLEDPARTY_NAME, &msg->data.CallInfoMessage.calledPartyName,
64 		SCCP_CALLINFO_CALLEDPARTY_NUMBER, &msg->data.CallInfoMessage.calledParty,
65 		SCCP_CALLINFO_CALLEDPARTY_VOICEMAIL, &msg->data.CallInfoMessage.cdpnVoiceMailbox,
66 		SCCP_CALLINFO_CALLINGPARTY_NAME, &msg->data.CallInfoMessage.callingPartyName,
67 		SCCP_CALLINFO_CALLINGPARTY_NUMBER, &msg->data.CallInfoMessage.callingParty,
68 		SCCP_CALLINFO_CALLINGPARTY_VOICEMAIL, &msg->data.CallInfoMessage.cgpnVoiceMailbox,
69 		SCCP_CALLINFO_ORIG_CALLEDPARTY_NAME, &msg->data.CallInfoMessage.originalCalledPartyName,
70 		SCCP_CALLINFO_ORIG_CALLEDPARTY_NUMBER, &msg->data.CallInfoMessage.originalCalledParty,
71 		SCCP_CALLINFO_ORIG_CALLEDPARTY_VOICEMAIL, &msg->data.CallInfoMessage.originalCdpnVoiceMailbox,
72 		SCCP_CALLINFO_LAST_REDIRECTINGPARTY_NAME, &msg->data.CallInfoMessage.lastRedirectingPartyName,
73 		SCCP_CALLINFO_LAST_REDIRECTINGPARTY_NUMBER, &msg->data.CallInfoMessage.lastRedirectingParty,
74 		SCCP_CALLINFO_LAST_REDIRECTINGPARTY_VOICEMAIL, &msg->data.CallInfoMessage.lastRedirectingVoiceMailbox,
75 		SCCP_CALLINFO_ORIG_CALLEDPARTY_REDIRECT_REASON, &originalCdpnRedirectReason,
76 		SCCP_CALLINFO_LAST_REDIRECT_REASON, &lastRedirectingReason,
77 		SCCP_CALLINFO_PRESENTATION, &presentation,
78 		SCCP_CALLINFO_KEY_SENTINEL);
79 
80 	// 7920's exception. They don't seem to reverse the interpretation of the presentation flag
81 	if (device->skinny_type == SKINNY_DEVICETYPE_CISCO7920) {
82 		msg->data.CallInfoMessage.partyPIRestrictionBits = presentation ? 0x0 : 0xf;
83 	} else {
84 		msg->data.CallInfoMessage.partyPIRestrictionBits = presentation ? 0xf : 0x0;
85 	}
86 	msg->data.CallInfoMessage.lel_lineInstance = htolel(lineInstance);
87 	msg->data.CallInfoMessage.lel_callReference = htolel(callid);
88 	msg->data.CallInfoMessage.lel_callType = htolel(calltype);
89 	msg->data.CallInfoMessage.lel_callInstance = htolel(callInstance);
90 	msg->data.CallInfoMessage.lel_callSecurityStatus = htolel(callsecurityState);
91 	msg->data.CallInfoMessage.lel_originalCdpnRedirectReason = htolel(originalCdpnRedirectReason);
92 	msg->data.CallInfoMessage.lel_lastRedirectingReason = htolel(lastRedirectingReason);
93 
94 	//sccp_log((DEBUGCAT_CHANNEL | DEBUGCAT_LINE | DEBUGCAT_INDICATE)) (VERBOSE_PREFIX_3 "%s: Send callinfo(V3) for %s channel %d/%d on line instance %d\n", (device) ? device->id : "(null)", skinny_calltype2str(calltype), callid, callInstance, lineInstance);
95 	//if ((GLOB(debug) & (DEBUGCAT_CHANNEL | DEBUGCAT_LINE | DEBUGCAT_INDICATE)) != 0) {
96 	//	iCallInfo.Print2log(ci, "SCCP: (sendCallInfoV3)");
97 	//}
98 	sccp_dev_send(device, msg);
99 }
100 
sccp_protocol_sendCallInfoV7(const sccp_callinfo_t * const ci,const uint32_t callid,const skinny_calltype_t calltype,const uint8_t lineInstance,const uint8_t callInstance,const skinny_callsecuritystate_t callsecurityState,constDevicePtr device)101 static void sccp_protocol_sendCallInfoV7 (const sccp_callinfo_t * const ci, const uint32_t callid, const skinny_calltype_t calltype, const uint8_t lineInstance, const uint8_t callInstance, const skinny_callsecuritystate_t callsecurityState, constDevicePtr device)
102 {
103  	pbx_assert(device != NULL);
104 	sccp_msg_t *msg = NULL;
105 
106 	unsigned int dataSize = 12;
107 	char data[dataSize][StationMaxNameSize];
108 	int data_len[dataSize];
109 	unsigned int i = 0;
110 	int dummy_len = 0;
111 
112 	memset(data, 0, dataSize * StationMaxNameSize);
113 
114 	int originalCdpnRedirectReason = 0;
115 	int lastRedirectingReason = 0;
116 	sccp_callerid_presentation_t presentation = CALLERID_PRESENTATION_ALLOWED;
117 	iCallInfo.Getter(ci,
118 		SCCP_CALLINFO_CALLINGPARTY_NUMBER, &data[0],
119 		SCCP_CALLINFO_CALLEDPARTY_NUMBER, &data[1],
120 		SCCP_CALLINFO_ORIG_CALLEDPARTY_NUMBER, &data[2],
121 		SCCP_CALLINFO_LAST_REDIRECTINGPARTY_NUMBER, &data[3],
122 		SCCP_CALLINFO_CALLINGPARTY_VOICEMAIL, &data[4],
123 		SCCP_CALLINFO_CALLEDPARTY_VOICEMAIL, &data[5],
124 		SCCP_CALLINFO_ORIG_CALLEDPARTY_VOICEMAIL, &data[6],
125 		SCCP_CALLINFO_LAST_REDIRECTINGPARTY_VOICEMAIL, &data[7],
126 		SCCP_CALLINFO_CALLINGPARTY_NAME, &data[8],
127 		SCCP_CALLINFO_CALLEDPARTY_NAME, &data[9],
128 		SCCP_CALLINFO_ORIG_CALLEDPARTY_NAME, &data[10],
129 		SCCP_CALLINFO_LAST_REDIRECTINGPARTY_NAME, &data[11],
130 		SCCP_CALLINFO_ORIG_CALLEDPARTY_REDIRECT_REASON, &originalCdpnRedirectReason,
131 		SCCP_CALLINFO_LAST_REDIRECT_REASON, &lastRedirectingReason,
132 		SCCP_CALLINFO_PRESENTATION, &presentation,
133 		SCCP_CALLINFO_KEY_SENTINEL);
134 
135 
136 	for (i = 0; i < dataSize; i++) {
137 		data_len[i] = strlen(data[i]);
138 		dummy_len += data_len[i];
139 	}
140 
141 	int hdr_len = sizeof(msg->data.CallInfoDynamicMessage) + (dataSize - 3);
142 	msg = sccp_build_packet(CallInfoDynamicMessage, hdr_len + dummy_len);
143 
144 	msg->data.CallInfoDynamicMessage.lel_lineInstance = htolel(lineInstance);
145 	msg->data.CallInfoDynamicMessage.lel_callReference = htolel(callid);
146 	msg->data.CallInfoDynamicMessage.lel_callType = htolel(calltype);
147 	msg->data.CallInfoDynamicMessage.partyPIRestrictionBits = presentation ? 0x0 : 0xf;
148 	//! note callSecurityStatus:
149 	// when indicating ringout we should set SKINNY_CALLSECURITYSTATE_UNKNOWN
150 	// when indicating connected we should set SKINNY_CALLSECURITYSTATE_NOTAUTHENTICATED
151 	msg->data.CallInfoDynamicMessage.lel_callSecurityStatus = htolel(callsecurityState);
152 	msg->data.CallInfoDynamicMessage.lel_callInstance = htolel(callInstance);
153 	msg->data.CallInfoDynamicMessage.lel_originalCdpnRedirectReason = htolel(originalCdpnRedirectReason);
154 	msg->data.CallInfoDynamicMessage.lel_lastRedirectingReason = htolel(lastRedirectingReason);
155 
156 	if (dummy_len) {
157 		int bufferSize = dummy_len + dataSize;
158 		char buffer[bufferSize];
159 		int pos = 0;
160 
161 		memset(&buffer[0], 0, bufferSize);
162 		for (i = 0; i < dataSize; i++) {
163 			if (data_len[i]) {
164 				memcpy(&buffer[pos], data[i], data_len[i]);
165 				pos += data_len[i] + 1;
166 			} else {
167 				pos += 1;
168 			}
169 		}
170 		memcpy(&msg->data.CallInfoDynamicMessage.dummy, &buffer[0], bufferSize);
171 	}
172 
173 	//sccp_log((DEBUGCAT_CHANNEL | DEBUGCAT_LINE | DEBUGCAT_INDICATE)) (VERBOSE_PREFIX_3 "%s: Send callinfo(V7) for %s channel %d/%d on line instance %d\n", (device) ? device->id : "(null)", skinny_calltype2str(calltype), callid, callInstance, lineInstance);
174 	//if ((GLOB(debug) & (DEBUGCAT_CHANNEL | DEBUGCAT_LINE | DEBUGCAT_INDICATE)) != 0) {
175 	//	iCallInfo.Print2log(ci, "SCCP: (sendCallInfoV7)");
176 	//	sccp_dump_msg(msg);
177 	//}
178 	sccp_dev_send(device, msg);
179 }
180 
sccp_protocol_sendCallInfoV16(const sccp_callinfo_t * const ci,const uint32_t callid,const skinny_calltype_t calltype,const uint8_t lineInstance,const uint8_t callInstance,const skinny_callsecuritystate_t callsecurityState,constDevicePtr device)181 static void sccp_protocol_sendCallInfoV16 (const sccp_callinfo_t * const ci, const uint32_t callid, const skinny_calltype_t calltype, const uint8_t lineInstance, const uint8_t callInstance, const skinny_callsecuritystate_t callsecurityState, constDevicePtr device)
182 {
183  	pbx_assert(device != NULL);
184 	sccp_msg_t *msg = NULL;
185 
186 	unsigned int dataSize = 15;
187 	char data[dataSize][StationMaxNameSize];
188 	memset(data, 0, dataSize * StationMaxNameSize);
189 
190 	int originalCdpnRedirectReason = 0;
191 	int lastRedirectingReason = 0;
192 	sccp_callerid_presentation_t presentation = CALLERID_PRESENTATION_ALLOWED;
193 	iCallInfo.Getter(ci,
194 		SCCP_CALLINFO_CALLINGPARTY_NUMBER, &data[0],
195 		SCCP_CALLINFO_ORIG_CALLINGPARTY_NUMBER, &data[1],
196 		SCCP_CALLINFO_CALLEDPARTY_NUMBER, &data[2],
197 		SCCP_CALLINFO_ORIG_CALLEDPARTY_NUMBER, &data[3],
198 		SCCP_CALLINFO_LAST_REDIRECTINGPARTY_NUMBER, &data[4],
199 		SCCP_CALLINFO_CALLINGPARTY_VOICEMAIL, &data[5],
200 		SCCP_CALLINFO_CALLEDPARTY_VOICEMAIL, &data[6],
201 		SCCP_CALLINFO_ORIG_CALLEDPARTY_VOICEMAIL, &data[7],
202 		SCCP_CALLINFO_LAST_REDIRECTINGPARTY_VOICEMAIL, &data[8],
203 		SCCP_CALLINFO_CALLINGPARTY_NAME, &data[9],
204 		SCCP_CALLINFO_CALLEDPARTY_NAME, &data[10],
205 		SCCP_CALLINFO_ORIG_CALLEDPARTY_NAME, &data[11],
206 		SCCP_CALLINFO_LAST_REDIRECTINGPARTY_NAME, &data[12],
207 		SCCP_CALLINFO_HUNT_PILOT_NUMBER, &data[13],
208 		SCCP_CALLINFO_HUNT_PILOT_NAME, &data[14],
209 		SCCP_CALLINFO_ORIG_CALLEDPARTY_REDIRECT_REASON, &originalCdpnRedirectReason,
210 		SCCP_CALLINFO_LAST_REDIRECT_REASON, &lastRedirectingReason,
211 		SCCP_CALLINFO_PRESENTATION, &presentation,
212 		SCCP_CALLINFO_KEY_SENTINEL);
213 
214 	unsigned int field = 0;
215 	int data_len = 0;
216 	int dummy_len = 0;
217 	uint8_t *dummy = (uint8_t *)sccp_calloc(sizeof(uint8_t), dataSize * StationMaxNameSize);
218 	if (!dummy) {
219 		return;
220 	}
221 	for (field = 0; field < dataSize; field++) {
222 		data_len = strlen(data[field]) + 1; 		//add NULL terminator
223 		memcpy(dummy + dummy_len, data[field], data_len);
224 		dummy_len += data_len;
225 	}
226 	int hdr_len = sizeof(msg->data.CallInfoDynamicMessage) - 4;
227 	msg = sccp_build_packet(CallInfoDynamicMessage, hdr_len + dummy_len);
228 	msg->data.CallInfoDynamicMessage.lel_lineInstance		= htolel(lineInstance);
229 	msg->data.CallInfoDynamicMessage.lel_callReference		= htolel(callid);
230 	msg->data.CallInfoDynamicMessage.lel_callType			= htolel(calltype);
231 	msg->data.CallInfoDynamicMessage.partyPIRestrictionBits		= presentation ? 0x0 : 0xf;
232 	msg->data.CallInfoDynamicMessage.lel_callSecurityStatus		= htolel(callsecurityState);
233 	msg->data.CallInfoDynamicMessage.lel_callInstance		= htolel(callInstance);
234 	msg->data.CallInfoDynamicMessage.lel_originalCdpnRedirectReason	= htolel(originalCdpnRedirectReason);
235 	msg->data.CallInfoDynamicMessage.lel_lastRedirectingReason	= htolel(lastRedirectingReason);
236 	memcpy(&msg->data.CallInfoDynamicMessage.dummy, dummy, dummy_len);
237 	sccp_free(dummy);
238 
239 	//sccp_log((DEBUGCAT_CHANNEL | DEBUGCAT_LINE | DEBUGCAT_INDICATE)) (VERBOSE_PREFIX_3 "%s: Send callinfo(V20) for %s channel %d/%d on line instance %d\n", (device) ? device->id : "(null)", skinny_calltype2str(calltype), callid, callInstance, lineInstance);
240 	//if ((GLOB(debug) & (DEBUGCAT_CHANNEL | DEBUGCAT_LINE | DEBUGCAT_INDICATE)) != 0) {
241 	//	iCallInfo.Print2log(ci, "SCCP: (sendCallInfoV16)");
242 	//	sccp_dump_msg(msg);
243 	//}
244 	sccp_dev_send(device, msg);
245 }
246 
247 /* done - CallInfoMessage */
248 
249 
250 /* DialedNumber Message */
251 
252 /*!
253  * \brief Send DialedNumber Message (V3)
254  */
sccp_protocol_sendDialedNumberV3(constDevicePtr device,const uint8_t lineInstance,const uint32_t callid,const char dialedNumber[SCCP_MAX_EXTENSION])255 static void sccp_protocol_sendDialedNumberV3(constDevicePtr device, const uint8_t lineInstance, const uint32_t callid, const char dialedNumber[SCCP_MAX_EXTENSION])
256 {
257 	sccp_msg_t *msg = NULL;
258 
259 	REQ(msg, DialedNumberMessage);
260 
261 	sccp_copy_string(msg->data.DialedNumberMessage.v3.calledParty, dialedNumber, sizeof(msg->data.DialedNumberMessage.v3.calledParty));
262 
263 	msg->data.DialedNumberMessage.v3.lel_lineInstance = htolel(lineInstance);
264 	msg->data.DialedNumberMessage.v3.lel_callReference = htolel(callid);
265 
266 	sccp_dev_send(device, msg);
267 	sccp_log(DEBUGCAT_CHANNEL) (VERBOSE_PREFIX_3 "%s: Send the dialed number:%s, callid:%d, lineInstance:%d\n", device->id, dialedNumber, callid, lineInstance);
268 }
269 
270 /*!
271  * \brief Send DialedNumber Message (V18)
272  *
273  */
sccp_protocol_sendDialedNumberV18(constDevicePtr device,const uint8_t lineInstance,const uint32_t callid,const char dialedNumber[SCCP_MAX_EXTENSION])274 static void sccp_protocol_sendDialedNumberV18(constDevicePtr device, const uint8_t lineInstance, const uint32_t callid, const char dialedNumber[SCCP_MAX_EXTENSION])
275 {
276 	sccp_msg_t *msg = NULL;
277 
278 	REQ(msg, DialedNumberMessage);
279 
280 	sccp_copy_string(msg->data.DialedNumberMessage.v18.calledParty, dialedNumber, sizeof(msg->data.DialedNumberMessage.v18.calledParty));
281 	msg->data.DialedNumberMessage.v18.lel_lineInstance = htolel(lineInstance);
282 	msg->data.DialedNumberMessage.v18.lel_callReference = htolel(callid);
283 
284 	sccp_dev_send(device, msg);
285 	sccp_log(DEBUGCAT_CHANNEL) (VERBOSE_PREFIX_3 "%s: Send the dialed number:%s, callid:%d, lineInstance:%d\n", device->id, dialedNumber, callid, lineInstance);
286 }
287 
288 /* done - DialedNumber Message */
289 
290 /* Display Prompt Message */
291 
292 /*!
293  * \brief Send Display Prompt Message (Static)
294  */
sccp_protocol_sendStaticDisplayprompt(constDevicePtr device,uint8_t lineInstance,uint32_t callid,uint8_t timeout,const char * message)295 static void sccp_protocol_sendStaticDisplayprompt(constDevicePtr device, uint8_t lineInstance, uint32_t callid, uint8_t timeout, const char *message)
296 {
297 	sccp_msg_t *msg = NULL;
298 
299 	REQ(msg, DisplayPromptStatusMessage);
300 	msg->data.DisplayPromptStatusMessage.lel_messageTimeout = htolel(timeout);
301 	msg->data.DisplayPromptStatusMessage.lel_callReference = htolel(callid);
302 	msg->data.DisplayPromptStatusMessage.lel_lineInstance = htolel(lineInstance);
303 	sccp_copy_string(msg->data.DisplayPromptStatusMessage.promptMessage, message, sizeof(msg->data.DisplayPromptStatusMessage.promptMessage));
304 
305 	sccp_dev_send(device, msg);
306 	sccp_log((DEBUGCAT_DEVICE | DEBUGCAT_LINE)) (VERBOSE_PREFIX_3 "%s: Display prompt on line %d, callid %d, timeout %d\n", device->id, lineInstance, callid, timeout);
307 }
308 
309 /*!
310  * \brief Send Display Prompt Message (Dynamic)
311  */
sccp_protocol_sendDynamicDisplayprompt(constDevicePtr device,uint8_t lineInstance,uint32_t callid,uint8_t timeout,const char * message)312 static void sccp_protocol_sendDynamicDisplayprompt(constDevicePtr device, uint8_t lineInstance, uint32_t callid, uint8_t timeout, const char *message)
313 {
314 	sccp_msg_t *msg = NULL;
315 
316 	int msg_len = strlen(message);
317 	int hdr_len = sizeof(msg->data.DisplayDynamicPromptStatusMessage) - 3;
318 	msg = sccp_build_packet(DisplayDynamicPromptStatusMessage, hdr_len + msg_len);
319 	msg->data.DisplayDynamicPromptStatusMessage.lel_messageTimeout = htolel(timeout);
320 	msg->data.DisplayDynamicPromptStatusMessage.lel_callReference = htolel(callid);
321 	msg->data.DisplayDynamicPromptStatusMessage.lel_lineInstance = htolel(lineInstance);
322 	memcpy(&msg->data.DisplayDynamicPromptStatusMessage.dummy, message, msg_len);
323 
324 	sccp_dev_send(device, msg);
325 	sccp_log((DEBUGCAT_DEVICE | DEBUGCAT_LINE)) (VERBOSE_PREFIX_3 "%s: Display prompt on line %d, callid %d, timeout %d\n", device->id, lineInstance, callid, timeout);
326 }
327 
328 /* done - display prompt */
329 
330 /* Display Notify  Message */
331 
332 /*!
333  * \brief Send Display Notify Message (Static)
334  */
sccp_protocol_sendStaticDisplayNotify(constDevicePtr device,uint8_t timeout,const char * message)335 static void sccp_protocol_sendStaticDisplayNotify(constDevicePtr device, uint8_t timeout, const char *message)
336 {
337 	sccp_msg_t *msg = NULL;
338 
339 	REQ(msg, DisplayNotifyMessage);
340 	msg->data.DisplayNotifyMessage.lel_displayTimeout = htolel(timeout);
341 	sccp_copy_string(msg->data.DisplayNotifyMessage.displayMessage, message, sizeof(msg->data.DisplayNotifyMessage.displayMessage));
342 
343 	sccp_dev_send(device, msg);
344 	sccp_log((DEBUGCAT_DEVICE | DEBUGCAT_LINE)) (VERBOSE_PREFIX_3 "%s: Display notify timeout %d\n", device->id, timeout);
345 }
346 
347 /*!
348  * \brief Send Display Notify Message (Dynamic)
349  */
sccp_protocol_sendDynamicDisplayNotify(constDevicePtr device,uint8_t timeout,const char * message)350 static void sccp_protocol_sendDynamicDisplayNotify(constDevicePtr device, uint8_t timeout, const char *message)
351 {
352 	sccp_msg_t *msg = NULL;
353 
354 	int msg_len = strlen(message);
355 
356 	int hdr_len = sizeof(msg->data.DisplayDynamicNotifyMessage) - 3;
357 	msg = sccp_build_packet(DisplayDynamicNotifyMessage, hdr_len + msg_len);
358 	msg->data.DisplayDynamicNotifyMessage.lel_displayTimeout = htolel(timeout);
359 	memcpy(&msg->data.DisplayDynamicNotifyMessage.dummy, message, msg_len);
360 
361 	sccp_dev_send(device, msg);
362 	sccp_log((DEBUGCAT_DEVICE | DEBUGCAT_LINE)) (VERBOSE_PREFIX_3 "%s: Display notify timeout %d\n", device->id, timeout);
363 }
364 
365 /* done - display notify */
366 
367 /* Display Priority Notify Message */
368 
369 /*!
370  * \brief Send Priority Display Notify Message (Static)
371  */
sccp_protocol_sendStaticDisplayPriNotify(constDevicePtr device,uint8_t priority,uint8_t timeout,const char * message)372 static void sccp_protocol_sendStaticDisplayPriNotify(constDevicePtr device, uint8_t priority, uint8_t timeout, const char *message)
373 {
374 	sccp_msg_t *msg = NULL;
375 
376 	REQ(msg, DisplayPriNotifyMessage);
377 	msg->data.DisplayPriNotifyMessage.lel_displayTimeout = htolel(timeout);
378 	msg->data.DisplayPriNotifyMessage.lel_priority = htolel(priority);
379 	sccp_copy_string(msg->data.DisplayPriNotifyMessage.displayMessage, message, sizeof(msg->data.DisplayPriNotifyMessage.displayMessage));
380 
381 	sccp_dev_send(device, msg);
382 	sccp_log((DEBUGCAT_DEVICE | DEBUGCAT_LINE)) (VERBOSE_PREFIX_3 "%s: Display notify timeout %d\n", device->id, timeout);
383 }
384 
385 /*!
386  * \brief Send Priority Display Notify Message (Dynamic)
387  */
sccp_protocol_sendDynamicDisplayPriNotify(constDevicePtr device,uint8_t priority,uint8_t timeout,const char * message)388 static void sccp_protocol_sendDynamicDisplayPriNotify(constDevicePtr device, uint8_t priority, uint8_t timeout, const char *message)
389 {
390 	sccp_msg_t *msg = NULL;
391 
392 	int msg_len = strlen(message);
393 	int hdr_len = sizeof(msg->data.DisplayDynamicPriNotifyMessage) - 3;
394 	msg = sccp_build_packet(DisplayDynamicPriNotifyMessage, hdr_len + msg_len);
395 	msg->data.DisplayDynamicPriNotifyMessage.lel_displayTimeout = htolel(timeout);
396 	msg->data.DisplayDynamicPriNotifyMessage.lel_priority = htolel(priority);
397 	memcpy(&msg->data.DisplayDynamicPriNotifyMessage.dummy, message, msg_len);
398 
399 	sccp_dev_send(device, msg);
400 	sccp_log((DEBUGCAT_DEVICE | DEBUGCAT_LINE)) (VERBOSE_PREFIX_3 "%s: Display notify timeout %d\n", device->id, timeout);
401 }
402 
403 /* done - display notify */
404 
405 /* callForwardStatus Message */
406 
407 /*!
408  * \brief Send Call Forward Status Message
409  * \todo need more information about lel_activeForward and lel_forwardAllActive values.
410  */
sccp_protocol_sendCallForwardStatus(constDevicePtr device,const sccp_linedevice_t * ld)411 static void sccp_protocol_sendCallForwardStatus(constDevicePtr device, const sccp_linedevice_t * ld)
412 {
413 	sccp_msg_t *msg = NULL;
414 
415 	REQ(msg, ForwardStatMessage);
416 	msg->data.ForwardStatMessage.v3.lel_activeForward = (ld->cfwd[SCCP_CFWD_ALL].enabled || ld->cfwd[SCCP_CFWD_BUSY].enabled || ld->cfwd[SCCP_CFWD_NOANSWER].enabled) ? htolel(1) : 0;
417 	msg->data.ForwardStatMessage.v3.lel_lineNumber = htolel(ld->lineInstance);
418 
419 	if(ld->cfwd[SCCP_CFWD_ALL].enabled) {
420 		msg->data.ForwardStatMessage.v3.lel_forwardAllActive = htolel(1);
421 		sccp_copy_string(msg->data.ForwardStatMessage.v3.cfwdallnumber, ld->cfwd[SCCP_CFWD_ALL].number, sizeof(msg->data.ForwardStatMessage.v3.cfwdallnumber));
422 	} else if(ld->cfwd[SCCP_CFWD_BUSY].enabled) {
423 		msg->data.ForwardStatMessage.v3.lel_forwardBusyActive = htolel(1);
424 		sccp_copy_string(msg->data.ForwardStatMessage.v3.cfwdbusynumber, ld->cfwd[SCCP_CFWD_BUSY].number, sizeof(msg->data.ForwardStatMessage.v3.cfwdbusynumber));
425 	} else if(ld->cfwd[SCCP_CFWD_NOANSWER].enabled) {
426 		msg->data.ForwardStatMessage.v3.lel_forwardNoAnswerActive = htolel(1);
427 		sccp_copy_string(msg->data.ForwardStatMessage.v3.cfwdnoanswernumber, ld->cfwd[SCCP_CFWD_NOANSWER].number, sizeof(msg->data.ForwardStatMessage.v3.cfwdnoanswernumber));
428 	} else {
429 		msg->data.ForwardStatMessage.v3.lel_forwardAllActive = htolel(0);
430 		msg->data.ForwardStatMessage.v3.lel_forwardBusyActive = htolel(0);
431 		msg->data.ForwardStatMessage.v3.lel_forwardNoAnswerActive = htolel(0);
432 		sccp_copy_string(msg->data.ForwardStatMessage.v3.cfwdallnumber, "", sizeof(msg->data.ForwardStatMessage.v3.cfwdbusynumber));
433 		sccp_copy_string(msg->data.ForwardStatMessage.v3.cfwdbusynumber, "", sizeof(msg->data.ForwardStatMessage.v3.cfwdbusynumber));
434 		sccp_copy_string(msg->data.ForwardStatMessage.v3.cfwdnoanswernumber, "", sizeof(msg->data.ForwardStatMessage.v3.cfwdnoanswernumber));
435 	}
436 	sccp_dev_send(device, msg);
437 }
438 
439 /*!
440  * \brief Send Call Forward Status Message (V19)
441  * \todo need more information about lel_activeForward and lel_forwardAllActive values.
442  */
sccp_protocol_sendCallForwardStatusV18(constDevicePtr device,const sccp_linedevice_t * ld)443 static void sccp_protocol_sendCallForwardStatusV18(constDevicePtr device, const sccp_linedevice_t * ld)
444 {
445 	sccp_msg_t *msg = NULL;
446 
447 	REQ(msg, ForwardStatMessage);
448 	// activeForward / lel_forwardAllActive =  used 4 before... tcpdump shows 2(enbloc ?) or 8(single keypad ?)
449 	// msg->data.ForwardStatMessage.v18.lel_activeForward = (ld->cfwdAll.enabled || ld->cfwdBusy.enabled) ? htolel(2) : 0;   // should this be 2 instead ?
450 	msg->data.ForwardStatMessage.v18.lel_lineNumber = htolel(ld->lineInstance);
451 	if(ld->cfwd[SCCP_CFWD_ALL].enabled) {
452 		msg->data.ForwardStatMessage.v18.lel_activeForward = 2;
453 		msg->data.ForwardStatMessage.v18.lel_forwardAllActive = htolel(2);	// needs more information about the possible values and their meaning // 2 ?
454 		sccp_copy_string(msg->data.ForwardStatMessage.v18.cfwdallnumber, ld->cfwd[SCCP_CFWD_ALL].number, sizeof(msg->data.ForwardStatMessage.v18.cfwdallnumber));
455 	} else if(ld->cfwd[SCCP_CFWD_BUSY].enabled) {
456 		msg->data.ForwardStatMessage.v18.lel_activeForward = 2;
457 		msg->data.ForwardStatMessage.v18.lel_forwardBusyActive = htolel(2);
458 		sccp_copy_string(msg->data.ForwardStatMessage.v18.cfwdbusynumber, ld->cfwd[SCCP_CFWD_BUSY].number, sizeof(msg->data.ForwardStatMessage.v18.cfwdbusynumber));
459 	} else if(ld->cfwd[SCCP_CFWD_NOANSWER].enabled) {
460 		msg->data.ForwardStatMessage.v18.lel_activeForward = 2;
461 		msg->data.ForwardStatMessage.v18.lel_forwardNoAnswerActive = htolel(2);
462 		sccp_copy_string(msg->data.ForwardStatMessage.v18.cfwdnoanswernumber, ld->cfwd[SCCP_CFWD_NOANSWER].number, sizeof(msg->data.ForwardStatMessage.v18.cfwdnoanswernumber));
463 	} else {
464 		msg->data.ForwardStatMessage.v18.lel_activeForward = 0;
465 		msg->data.ForwardStatMessage.v18.lel_forwardAllActive = htolel(0);
466 		msg->data.ForwardStatMessage.v18.lel_forwardBusyActive = htolel(0);
467 		msg->data.ForwardStatMessage.v18.lel_forwardNoAnswerActive = htolel(0);
468 		sccp_copy_string(msg->data.ForwardStatMessage.v18.cfwdallnumber, "", sizeof(msg->data.ForwardStatMessage.v18.cfwdbusynumber));
469 		sccp_copy_string(msg->data.ForwardStatMessage.v18.cfwdbusynumber, "", sizeof(msg->data.ForwardStatMessage.v18.cfwdbusynumber));
470 		sccp_copy_string(msg->data.ForwardStatMessage.v18.cfwdnoanswernumber, "", sizeof(msg->data.ForwardStatMessage.v18.cfwdnoanswernumber));
471 	}
472 
473 	//msg->data.ForwardStatMessage.v18.lel_unknown = 0x000000FF;
474 	sccp_dev_send(device, msg);
475 }
476 
477 /* done - send callForwardStatus */
478 
479 /* registerAck Message */
480 
481 /*!
482  * \brief Send Register Acknowledgement Message (V3)
483  */
sccp_protocol_sendRegisterAckV3(constDevicePtr device,uint8_t keepAliveInterval,uint8_t secondaryKeepAlive,char * dateformat)484 static void sccp_protocol_sendRegisterAckV3(constDevicePtr device, uint8_t keepAliveInterval, uint8_t secondaryKeepAlive, char *dateformat)
485 {
486 	sccp_msg_t *msg = NULL;
487 
488 	REQ(msg, RegisterAckMessage);
489 
490 	/* just for documentation */
491 	msg->data.RegisterAckMessage.protocolFeatures.protocolVersion = device->protocol->version;
492 	msg->data.RegisterAckMessage.protocolFeatures.phoneFeatures[0] = 0x00;
493 	msg->data.RegisterAckMessage.protocolFeatures.phoneFeatures[1] = 0x00;
494 	msg->data.RegisterAckMessage.protocolFeatures.phoneFeatures[2] = 0x00;
495 
496 	msg->data.RegisterAckMessage.lel_keepAliveInterval = htolel(keepAliveInterval);
497 	msg->data.RegisterAckMessage.lel_secondaryKeepAliveInterval = htolel(secondaryKeepAlive);
498 
499 	if (!sccp_strlen_zero(dateformat)) {
500 		sccp_copy_string(msg->data.RegisterAckMessage.dateTemplate, dateformat, sizeof(msg->data.RegisterAckMessage.dateTemplate));
501 	} else {
502 		sccp_copy_string(msg->data.RegisterAckMessage.dateTemplate, "M/D/Y", sizeof(msg->data.RegisterAckMessage.dateTemplate));
503 	}
504 	sccp_dev_send(device, msg);
505 }
506 
507 /*!
508  * \brief Send Register Acknowledgement Message (V4)
509  */
sccp_protocol_sendRegisterAckV4(constDevicePtr device,uint8_t keepAliveInterval,uint8_t secondaryKeepAlive,char * dateformat)510 static void sccp_protocol_sendRegisterAckV4(constDevicePtr device, uint8_t keepAliveInterval, uint8_t secondaryKeepAlive, char *dateformat)
511 {
512 	sccp_msg_t *msg = NULL;
513 
514 	REQ(msg, RegisterAckMessage);
515 
516 	msg->data.RegisterAckMessage.protocolFeatures.protocolVersion = device->protocol->version;
517 	msg->data.RegisterAckMessage.protocolFeatures.phoneFeatures[0] = 0x20;
518 	msg->data.RegisterAckMessage.protocolFeatures.phoneFeatures[1] = 0xF1;
519 	msg->data.RegisterAckMessage.protocolFeatures.phoneFeatures[2] = 0xFE;
520 
521 	msg->data.RegisterAckMessage.lel_keepAliveInterval = htolel(keepAliveInterval);
522 	msg->data.RegisterAckMessage.lel_secondaryKeepAliveInterval = htolel(secondaryKeepAlive);
523 
524 	if (!sccp_strlen_zero(dateformat)) {
525 		sccp_copy_string(msg->data.RegisterAckMessage.dateTemplate, dateformat, sizeof(msg->data.RegisterAckMessage.dateTemplate));
526 	} else {
527 		sccp_copy_string(msg->data.RegisterAckMessage.dateTemplate, "M/D/Y", sizeof(msg->data.RegisterAckMessage.dateTemplate));
528 	}
529 	sccp_dev_send(device, msg);
530 }
531 
532 /*!
533  * \brief Send Register Acknowledgement Message (V11)
534  */
sccp_protocol_sendRegisterAckV11(constDevicePtr device,uint8_t keepAliveInterval,uint8_t secondaryKeepAlive,char * dateformat)535 static void sccp_protocol_sendRegisterAckV11(constDevicePtr device, uint8_t keepAliveInterval, uint8_t secondaryKeepAlive, char *dateformat)
536 {
537 	sccp_msg_t *msg = NULL;
538 
539 	REQ(msg, RegisterAckMessage);
540 
541 	msg->data.RegisterAckMessage.protocolFeatures.protocolVersion = device->protocol->version;
542 	msg->data.RegisterAckMessage.protocolFeatures.phoneFeatures[0] = 0x20;
543 	msg->data.RegisterAckMessage.protocolFeatures.phoneFeatures[1] = 0xF1;
544 	msg->data.RegisterAckMessage.protocolFeatures.phoneFeatures[2] = 0xFF;
545 
546 	msg->data.RegisterAckMessage.lel_keepAliveInterval = htolel(keepAliveInterval);
547 	msg->data.RegisterAckMessage.lel_secondaryKeepAliveInterval = htolel(secondaryKeepAlive);
548 
549 	if (!sccp_strlen_zero(dateformat)) {
550 		sccp_copy_string(msg->data.RegisterAckMessage.dateTemplate, dateformat, sizeof(msg->data.RegisterAckMessage.dateTemplate));
551 	} else {
552 		sccp_copy_string(msg->data.RegisterAckMessage.dateTemplate, "M/D/Y", sizeof(msg->data.RegisterAckMessage.dateTemplate));
553 	}
554 	sccp_dev_send(device, msg);
555 }
556 /* done - registerACK */
557 
558 /*!
559  * \brief Send Open Receive Channel (V3)
560  */
sccp_protocol_sendOpenReceiveChannelV3(constDevicePtr device,constChannelPtr channel)561 static void sccp_protocol_sendOpenReceiveChannelV3(constDevicePtr device, constChannelPtr channel)
562 {
563 	int packetSize = 20;											/*! \todo calculate packetSize */
564 	sccp_msg_t *msg = sccp_build_packet(OpenReceiveChannel, sizeof(msg->data.OpenReceiveChannel.v3));
565 
566 	msg->data.OpenReceiveChannel.v3.lel_conferenceId = htolel(channel->callid);
567 	msg->data.OpenReceiveChannel.v3.lel_passThruPartyId = htolel(channel->passthrupartyid);
568 	msg->data.OpenReceiveChannel.v3.lel_millisecondPacketSize = htolel(packetSize);
569 	msg->data.OpenReceiveChannel.v3.lel_codecType = htolel(channel->rtp.audio.reception.format);
570 	msg->data.OpenReceiveChannel.v3.lel_vadValue = htolel(channel->line->echocancel);
571 	msg->data.OpenReceiveChannel.v3.lel_callReference = htolel(channel->callid);
572 	//msg->data.OpenReceiveChannel.v3.lel_remotePortNumber = htolel(4000);
573 	if (SCCP_DTMFMODE_SKINNY == channel->dtmfmode) {
574 		msg->data.OpenReceiveChannel.v3.lel_RFC2833Type = htolel(0);
575 	} else {
576 		msg->data.OpenReceiveChannel.v3.lel_RFC2833Type = htolel(101);
577 	}
578 	msg->data.OpenReceiveChannel.v3.lel_dtmfType = htolel(10);;
579 
580 	/* Source Ip Address */
581 	struct sockaddr_storage sas;
582 
583 	memcpy(&sas, &channel->rtp.audio.phone_remote, sizeof(struct sockaddr_storage));
584 	sccp_netsock_ipv4_mapped(&sas, &sas);
585 
586 	struct sockaddr_in *in = (struct sockaddr_in *) &sas;
587 
588 	memcpy(&msg->data.OpenReceiveChannel.v3.bel_remoteIpAddr, &in->sin_addr, 4);
589 	msg->data.OpenReceiveChannel.v3.lel_remotePortNumber = htolel(sccp_netsock_getPort(&sas));
590 
591 	sccp_dev_send(device, msg);
592 }
593 
594 /*!
595  * \brief Send Open Receive Channel (V17)
596  */
sccp_protocol_sendOpenReceiveChannelV17(constDevicePtr device,constChannelPtr channel)597 static void sccp_protocol_sendOpenReceiveChannelV17(constDevicePtr device, constChannelPtr channel)
598 {
599 	int packetSize = 20;											/*! \todo calculate packetSize */
600 	sccp_msg_t *msg = sccp_build_packet(OpenReceiveChannel, sizeof(msg->data.OpenReceiveChannel.v17));
601 
602 	msg->data.OpenReceiveChannel.v17.lel_conferenceId = htolel(channel->callid);
603 	msg->data.OpenReceiveChannel.v17.lel_passThruPartyId = htolel(channel->passthrupartyid);
604 	msg->data.OpenReceiveChannel.v17.lel_millisecondPacketSize = htolel(packetSize);
605 	msg->data.OpenReceiveChannel.v17.lel_codecType = htolel(channel->rtp.audio.reception.format);
606 	msg->data.OpenReceiveChannel.v17.lel_vadValue = htolel(channel->line->echocancel);
607 	msg->data.OpenReceiveChannel.v17.lel_callReference = htolel(channel->callid);
608 	if (SCCP_DTMFMODE_SKINNY == channel->dtmfmode) {
609 		msg->data.OpenReceiveChannel.v17.lel_RFC2833Type = htolel(0);
610 	} else {
611 		msg->data.OpenReceiveChannel.v17.lel_RFC2833Type = htolel(101);
612 	}
613 	msg->data.OpenReceiveChannel.v17.lel_dtmfType = htolel(10);;
614 
615 	/* Source Ip Address */
616 	struct sockaddr_storage sas;
617 
618 	//memcpy(&sas, &device->session->sin, sizeof(struct sockaddr_storage));
619 	memcpy(&sas, &channel->rtp.audio.phone_remote, sizeof(struct sockaddr_storage));
620 	sccp_netsock_ipv4_mapped(&sas, &sas);
621 
622 	if (sas.ss_family == AF_INET6) {
623 		struct sockaddr_in6 *in6 = (struct sockaddr_in6 *) &sas;
624 
625 		memcpy(&msg->data.OpenReceiveChannel.v17.bel_remoteIpAddr, &in6->sin6_addr, 16);
626 		msg->data.OpenReceiveChannel.v17.lel_ipv46 = htolel(1);
627 		msg->data.OpenReceiveChannel.v17.lel_requestedIpAddrType = htolel(SKINNY_IPADDR_IPV6);				//for ipv6 this value have to me > 0, lel_ipv46 doesn't matter
628 	} else {
629 		struct sockaddr_in *in = (struct sockaddr_in *) &sas;
630 
631 		memcpy(&msg->data.OpenReceiveChannel.v17.bel_remoteIpAddr, &in->sin_addr, 4);
632 	}
633 	msg->data.OpenReceiveChannel.v17.lel_remotePortNumber = htolel(sccp_netsock_getPort(&sas));
634 	sccp_dev_send(device, msg);
635 }
636 
637 /*!
638  * \brief Send Open Receive Channel (v22)
639  */
sccp_protocol_sendOpenReceiveChannelv22(constDevicePtr device,constChannelPtr channel)640 static void sccp_protocol_sendOpenReceiveChannelv22(constDevicePtr device, constChannelPtr channel)
641 {
642 	int packetSize = 20;											/*! \todo calculate packetSize */
643 	sccp_msg_t *msg = sccp_build_packet(OpenReceiveChannel, sizeof(msg->data.OpenReceiveChannel.v22));
644 
645 	msg->data.OpenReceiveChannel.v22.lel_conferenceId = htolel(channel->callid);
646 	msg->data.OpenReceiveChannel.v22.lel_passThruPartyId = htolel(channel->passthrupartyid);
647 	msg->data.OpenReceiveChannel.v22.lel_millisecondPacketSize = htolel(packetSize);
648 	msg->data.OpenReceiveChannel.v22.lel_codecType = htolel(channel->rtp.audio.reception.format);
649 	msg->data.OpenReceiveChannel.v22.lel_vadValue = htolel(channel->line->echocancel);
650 	msg->data.OpenReceiveChannel.v22.lel_callReference = htolel(channel->callid);
651 	if (SCCP_DTMFMODE_SKINNY == channel->dtmfmode) {
652 		msg->data.OpenReceiveChannel.v22.lel_RFC2833Type = htolel(0);
653 	} else {
654 		msg->data.OpenReceiveChannel.v22.lel_RFC2833Type = htolel(101);
655 	}
656 	msg->data.OpenReceiveChannel.v22.lel_dtmfType = htolel(10);;
657 
658 	/* Source Ip Address */
659 	struct sockaddr_storage sas;
660 
661 	//memcpy(&sas, &device->session->sin, sizeof(struct sockaddr_storage));
662 	memcpy(&sas, &channel->rtp.audio.phone_remote, sizeof(struct sockaddr_storage));
663 	sccp_netsock_ipv4_mapped(&sas, &sas);
664 
665 	if (sas.ss_family == AF_INET6) {
666 		struct sockaddr_in6 *in6 = (struct sockaddr_in6 *) &sas;
667 
668 		memcpy(&msg->data.OpenReceiveChannel.v22.bel_remoteIpAddr, &in6->sin6_addr, 16);
669 		msg->data.OpenReceiveChannel.v22.lel_ipv46 = htolel(1);						//for ipv6 this value have to me > 0, lel_ipv46 doesn't matter
670 		msg->data.OpenReceiveChannel.v22.lel_requestedIpAddrType = htolel(SKINNY_IPADDR_IPV6);
671 	} else {
672 		struct sockaddr_in *in = (struct sockaddr_in *) &sas;
673 
674 		memcpy(&msg->data.OpenReceiveChannel.v22.bel_remoteIpAddr, &in->sin_addr, 4);
675 	}
676 	msg->data.OpenReceiveChannel.v22.lel_remotePortNumber = htolel(sccp_netsock_getPort(&sas));
677 	sccp_dev_send(device, msg);
678 }
679 
680 /*!
681  * \brief Send Open MultiMediaChannel Message (V3)
682  */
sccp_protocol_sendOpenMultiMediaChannelV3(constDevicePtr device,constChannelPtr channel,skinny_codec_t skinnyFormat,int payloadType,uint8_t lineInstance,int bitRate)683 static void sccp_protocol_sendOpenMultiMediaChannelV3(constDevicePtr device, constChannelPtr channel, skinny_codec_t skinnyFormat, int payloadType, uint8_t lineInstance, int bitRate)
684 {
685 	sccp_msg_t *msg = sccp_build_packet(OpenMultiMediaChannelMessage, sizeof(msg->data.OpenMultiMediaChannelMessage.v3));
686 
687 	msg->data.OpenMultiMediaChannelMessage.v3.lel_conferenceID = htolel(channel->callid);
688 	msg->data.OpenMultiMediaChannelMessage.v3.lel_passThruPartyID = htolel(channel->passthrupartyid);
689 	msg->data.OpenMultiMediaChannelMessage.v3.lel_codecType = htolel(skinnyFormat);
690 	//msg->data.OpenMultiMediaChannelMessage.v3.lel_codecType = htolel(channel->rtp.video.reception.format);
691 	msg->data.OpenMultiMediaChannelMessage.v3.lel_lineInstance = htolel(lineInstance);
692 	msg->data.OpenMultiMediaChannelMessage.v3.lel_callReference = htolel(channel->callid);
693 
694 	msg->data.OpenMultiMediaChannelMessage.v3.payloadType.lel_payload_rfc_number = htolel(0);
695 	msg->data.OpenMultiMediaChannelMessage.v3.payloadType.lel_payloadType = htolel(payloadType);
696 
697 	msg->data.OpenMultiMediaChannelMessage.v3.lel_isConferenceCreator = htolel(0);
698 
699 	skinny_OpenMultiMediaReceiveChannelUnion_t *capability = &(msg->data.OpenMultiMediaChannelMessage.v3.capability);
700 	{
701 		capability->vidParameters.lel_bitRate = htolel(bitRate);
702 		capability->vidParameters.lel_pictureFormatCount = htolel(1);
703 
704 		capability->vidParameters.pictureFormat[0].format = htolel(4);					// should be taken from UpdateCapabilitiesMessage
705 		capability->vidParameters.pictureFormat[0].mpi = htolel(1);					// should be taken from UpdateCapabilitiesMessage
706 		capability->vidParameters.pictureFormat[1].format = htolel(2);
707 		capability->vidParameters.pictureFormat[1].mpi = htolel(1);
708 		capability->vidParameters.pictureFormat[2].format = htolel(1);
709 		capability->vidParameters.pictureFormat[2].mpi = htolel(1);
710 		capability->vidParameters.pictureFormat[3].format = htolel(0);
711 		capability->vidParameters.pictureFormat[3].mpi = htolel(1);
712 		//capability->vidParameters.pictureFormat[4].format = htolel(0);
713 		//capability->vidParameters.pictureFormat[4].mpi = htolel(0);
714 
715 		capability->vidParameters.lel_confServiceNum = htolel(0);
716 
717 		skinny_ChannelVideoParametersUnion_t *channelVideoParams = &(capability->vidParameters.capability);
718 		{
719 			if (skinnyFormat == SKINNY_CODEC_H261) {
720 				channelVideoParams->h261.lel_temporalSpatialTradeOffCapability = htolel(1);	// ??
721 				channelVideoParams->h261.lel_stillImageTransmission = htolel(0);		// ??
722 			} else if (skinnyFormat == SKINNY_CODEC_H263) {						//
723 				channelVideoParams->h263.lel_capabilityBitfield = htolel(0);			// ??
724 				channelVideoParams->h263.lel_annexNandWFutureUse = htolel(0);			// ??
725 			} else if (skinnyFormat == SKINNY_CODEC_H263P) {					// H263P / aka:Vieo / H263-1998
726 				//CIF=1,QCIF=1
727 				channelVideoParams->h263P.lel_modelNumber = htolel(0);				// ??
728 				channelVideoParams->h263P.lel_bandwidth = htolel(0);				// ?? 90000
729 			} else if (skinnyFormat == SKINNY_CODEC_H264) {						// aka: MPEG4-AVC
730 				channelVideoParams->h264.lel_profile = htolel(64);				// should be taken from UpdateCapabilitiesMessage
731 				channelVideoParams->h264.lel_level = htolel(43);				// should be taken from UpdateCapabilitiesMessage
732 				channelVideoParams->h264.lel_customMaxMBPS = htolel(40500);			// should be taken from UpdateCapabilitiesMessage
733 				channelVideoParams->h264.lel_customMaxFS = htolel(1620);			// should be taken from UpdateCapabilitiesMessage
734 				channelVideoParams->h264.lel_customMaxDPB = htolel(8100);			// should be taken from UpdateCapabilitiesMessage
735 				channelVideoParams->h264.lel_customMaxBRandCPB = htolel(10000);			// should be taken from UpdateCapabilitiesMessage
736 			} else {
737 				// error
738 			}
739 		}
740 	}
741 	// Leave empty for now, until we find out more about encryption
742 	//msg->data.OpenMultiMediaChannelMessage.v3.RxEncryptionInfo = {0};
743 	msg->data.OpenMultiMediaChannelMessage.v3.lel_streamPassThroughID = htolel(channel->passthrupartyid);
744 	msg->data.OpenMultiMediaChannelMessage.v3.lel_associatedStreamID = htolel(channel->callid);		// We should use a random number and link it up
745 														// with the MultiMediaTransmission
746 	//sccp_dump_msg(msg);
747 	sccp_dev_send(device, msg);
748 }
749 /*!
750  * \brief Send Open MultiMediaChannel Message (V12)
751  */
sccp_protocol_sendOpenMultiMediaChannelV12(constDevicePtr device,constChannelPtr channel,skinny_codec_t skinnyFormat,int payloadType,uint8_t lineInstance,int bitRate)752 static void sccp_protocol_sendOpenMultiMediaChannelV12(constDevicePtr device, constChannelPtr channel, skinny_codec_t skinnyFormat, int payloadType, uint8_t lineInstance, int bitRate)
753 {
754 	sccp_msg_t *msg = sccp_build_packet(OpenMultiMediaChannelMessage, sizeof(msg->data.OpenMultiMediaChannelMessage.v12));
755 
756 	msg->data.OpenMultiMediaChannelMessage.v12.lel_conferenceID = htolel(channel->callid);
757 	msg->data.OpenMultiMediaChannelMessage.v12.lel_passThruPartyID = htolel(channel->passthrupartyid);
758 	msg->data.OpenMultiMediaChannelMessage.v12.lel_codecType = htolel(skinnyFormat);
759 	//msg->data.OpenMultiMediaChannelMessage.v12.lel_codecType = htolel(channel->rtp.video.reception.format);
760 	msg->data.OpenMultiMediaChannelMessage.v12.lel_lineInstance = htolel(lineInstance);
761 	msg->data.OpenMultiMediaChannelMessage.v12.lel_callReference = htolel(channel->callid);
762 
763 	msg->data.OpenMultiMediaChannelMessage.v12.payloadType.lel_payload_rfc_number = htolel(0);
764 	msg->data.OpenMultiMediaChannelMessage.v12.payloadType.lel_payloadType = htolel(payloadType);
765 
766 	msg->data.OpenMultiMediaChannelMessage.v12.lel_isConferenceCreator = htolel(0);
767 
768 	skinny_OpenMultiMediaReceiveChannelUnion_t *capability = &(msg->data.OpenMultiMediaChannelMessage.v12.capability);
769 	{
770 		capability->vidParameters.lel_bitRate = htolel(bitRate);
771 		capability->vidParameters.lel_pictureFormatCount = htolel(1);
772 
773 		capability->vidParameters.pictureFormat[0].format = htolel(4);					// should be taken from UpdateCapabilitiesMessage
774 		capability->vidParameters.pictureFormat[0].mpi = htolel(1);					// should be taken from UpdateCapabilitiesMessage
775 		capability->vidParameters.pictureFormat[1].format = htolel(2);
776 		capability->vidParameters.pictureFormat[1].mpi = htolel(1);
777 		capability->vidParameters.pictureFormat[2].format = htolel(1);
778 		capability->vidParameters.pictureFormat[2].mpi = htolel(1);
779 		capability->vidParameters.pictureFormat[3].format = htolel(0);
780 		capability->vidParameters.pictureFormat[3].mpi = htolel(1);
781 		//capability->vidParameters.pictureFormat[4].format = htolel(0);
782 		//capability->vidParameters.pictureFormat[4].mpi = htolel(0);
783 
784 		capability->vidParameters.lel_confServiceNum = htolel(0);
785 
786 		skinny_ChannelVideoParametersUnion_t *channelVideoParams = &(capability->vidParameters.capability);
787 		{
788 			if (skinnyFormat == SKINNY_CODEC_H261) {
789 				channelVideoParams->h261.lel_temporalSpatialTradeOffCapability = htolel(1);	// ??
790 				channelVideoParams->h261.lel_stillImageTransmission = htolel(0);		// ??
791 			} else if (skinnyFormat == SKINNY_CODEC_H263) {						//
792 				channelVideoParams->h263.lel_capabilityBitfield = htolel(0);			// ??
793 				channelVideoParams->h263.lel_annexNandWFutureUse = htolel(0);			// ??
794 			} else if (skinnyFormat == SKINNY_CODEC_H263P) {					// H263P / aka:Vieo / H263-1998
795 				//CIF=1,QCIF=1
796 				channelVideoParams->h263P.lel_modelNumber = htolel(0);				// ??
797 				channelVideoParams->h263P.lel_bandwidth = htolel(0);				// ?? 90000
798 			} else if (skinnyFormat == SKINNY_CODEC_H264) {						// aka: MPEG4-AVC
799 				channelVideoParams->h264.lel_profile = htolel(64);				// should be taken from UpdateCapabilitiesMessage
800 				channelVideoParams->h264.lel_level = htolel(43);				// should be taken from UpdateCapabilitiesMessage
801 				channelVideoParams->h264.lel_customMaxMBPS = htolel(40500);			// should be taken from UpdateCapabilitiesMessage
802 				channelVideoParams->h264.lel_customMaxFS = htolel(1620);			// should be taken from UpdateCapabilitiesMessage
803 				channelVideoParams->h264.lel_customMaxDPB = htolel(8100);			// should be taken from UpdateCapabilitiesMessage
804 				channelVideoParams->h264.lel_customMaxBRandCPB = htolel(10000);			// should be taken from UpdateCapabilitiesMessage
805 			} else {
806 				// error
807 			}
808 		}
809 	}
810 	// Leave empty for now, until we find out more about encryption
811 	//msg->data.OpenMultiMediaChannelMessage.v12.RxEncryptionInfo = {0};
812 	msg->data.OpenMultiMediaChannelMessage.v12.lel_streamPassThroughID = htolel(channel->passthrupartyid);
813 	msg->data.OpenMultiMediaChannelMessage.v12.lel_associatedStreamID = htolel(channel->callid);		// We should use a random number and link it up
814 														// with the MultiMediaTransmission
815 
816 	/* Source Ip Address */
817 	struct sockaddr_storage sas;
818 	if (device->directrtp) {
819 		sccp_rtp_getPeer(&channel->rtp.video, &sas);
820 	} else {
821 		sccp_rtp_getUs(&channel->rtp.video, &sas);
822 	}
823 	sccp_netsock_ipv4_mapped(&sas, &sas);
824 
825 	if (sas.ss_family == AF_INET) {
826 		struct sockaddr_in *in = (struct sockaddr_in *) &sas;
827 		memcpy(&msg->data.OpenMultiMediaChannelMessage.v12.bel_sourceIpAddr, &in->sin_addr, 4);
828 	} else {
829 		// error
830 	}
831 	msg->data.OpenMultiMediaChannelMessage.v12.lel_sourcePortNumber=htolel(sccp_netsock_getPort(&sas));
832 
833 	//sccp_dump_msg(msg);
834 	sccp_dev_send(device, msg);
835 }
836 /*!
837  * \brief Send Open MultiMediaChannel Message (V17)
838  */
sccp_protocol_sendOpenMultiMediaChannelV17(constDevicePtr device,constChannelPtr channel,skinny_codec_t skinnyFormat,int payloadType,uint8_t lineInstance,int bitRate)839 static void sccp_protocol_sendOpenMultiMediaChannelV17(constDevicePtr device, constChannelPtr channel, skinny_codec_t skinnyFormat, int payloadType, uint8_t lineInstance, int bitRate)
840 {
841 	sccp_msg_t *msg = sccp_build_packet(OpenMultiMediaChannelMessage, sizeof(msg->data.OpenMultiMediaChannelMessage.v17));
842 
843 	msg->data.OpenMultiMediaChannelMessage.v17.lel_conferenceID = htolel(channel->callid);
844 	msg->data.OpenMultiMediaChannelMessage.v17.lel_passThruPartyID = htolel(channel->passthrupartyid);
845 	msg->data.OpenMultiMediaChannelMessage.v17.lel_codecType = htolel(skinnyFormat);
846 	//msg->data.OpenMultiMediaChannelMessage.v17.lel_codecType = htolel(channel->rtp.video.reception.format);
847 	msg->data.OpenMultiMediaChannelMessage.v17.lel_lineInstance = htolel(lineInstance);
848 	msg->data.OpenMultiMediaChannelMessage.v17.lel_callReference = htolel(channel->callid);
849 
850 	msg->data.OpenMultiMediaChannelMessage.v17.payloadType.lel_payload_rfc_number = htolel(0);
851 	msg->data.OpenMultiMediaChannelMessage.v17.payloadType.lel_payloadType = htolel(payloadType);
852 
853 	msg->data.OpenMultiMediaChannelMessage.v17.lel_isConferenceCreator = htolel(0);
854 
855 
856 	skinny_OpenMultiMediaReceiveChannelUnion_t *capability = &(msg->data.OpenMultiMediaChannelMessage.v17.capability);
857 	{
858 		capability->vidParameters.lel_bitRate = htolel(bitRate);
859 		capability->vidParameters.lel_pictureFormatCount = htolel(1);
860 
861 		capability->vidParameters.pictureFormat[0].format = htolel(4);					// should be taken from UpdateCapabilitiesMessage
862 /*
863 	MPI = Minimum Picture interval. 1=means 29.7 frames, 2=halfs that to 14.9.
864 	If the receiver does not specify the picture size/MPI optional parameter, then it SHOULD be ready to receive QCIF resolution with MPI=1.
865 */
866 		capability->vidParameters.pictureFormat[0].format = htolel(4);					// should be taken from UpdateCapabilitiesMessage
867 		capability->vidParameters.pictureFormat[0].mpi = htolel(1);					// should be taken from UpdateCapabilitiesMessage
868 		capability->vidParameters.pictureFormat[1].format = htolel(2);
869 		capability->vidParameters.pictureFormat[1].mpi = htolel(1);
870 		capability->vidParameters.pictureFormat[2].format = htolel(1);
871 		capability->vidParameters.pictureFormat[2].mpi = htolel(1);
872 		capability->vidParameters.pictureFormat[3].format = htolel(0);
873 		capability->vidParameters.pictureFormat[3].mpi = htolel(1);
874 		//capability->vidParameters.pictureFormat[4].format = htolel(0);
875 		//capability->vidParameters.pictureFormat[4].mpi = htolel(0);
876 
877 		capability->vidParameters.lel_confServiceNum = htolel(0);
878 
879 		skinny_ChannelVideoParametersUnion_t *channelVideoParams = &(capability->vidParameters.capability);
880 		{
881 			if (skinnyFormat == SKINNY_CODEC_H261) {
882 				channelVideoParams->h261.lel_temporalSpatialTradeOffCapability = htolel(1);	// ??
883 				channelVideoParams->h261.lel_stillImageTransmission = htolel(0);		// ??
884 			} else if (skinnyFormat == SKINNY_CODEC_H263) {						// https://tools.ietf.org/html/rfc4629
885 				channelVideoParams->h263.lel_capabilityBitfield = htolel(0);			// ??
886 				channelVideoParams->h263.lel_annexNandWFutureUse = htolel(0);			// ??
887 			} else if (skinnyFormat == SKINNY_CODEC_H263P) {					// H263P / aka:Vieo / H263-1998
888 				//CIF=1,QCIF=1
889 				channelVideoParams->h263P.lel_modelNumber = htolel(0);				// ??
890 				channelVideoParams->h263P.lel_bandwidth = htolel(0);				// ?? 90000
891 			} else if (skinnyFormat == SKINNY_CODEC_H264) {						// aka: MPEG4-AVC
892 				/*
893 				      PROFILE:  profile number, in the range 0 through 10,
894 				      specifying the supported H.263 annexes/subparts based on H.263
895 				      annex X [H263].  The annexes supported in each profile are listed
896 				      in table X.1 of H.263 annex X.  If no profile or H.263 annex is
897 				      specified, then the stream is Baseline H.263 (profile 0 of H.263
898 				      annex X).
899 				*/
900 				channelVideoParams->h264.lel_profile = htolel(64);				// should be taken from UpdateCapabilitiesMessage
901 				/*
902 				      LEVEL:  Level of bitstream operation, in the range 0 through 100,
903 				      specifying the level of computational complexity of the decoding
904 				      process.  The level are described in table X.2 of H.263 annex X.
905 				*/
906 				channelVideoParams->h264.lel_level = htolel(43);				// should be taken from UpdateCapabilitiesMessage
907 				channelVideoParams->h264.lel_customMaxMBPS = htolel(40500);			// should be taken from UpdateCapabilitiesMessage
908 				channelVideoParams->h264.lel_customMaxFS = htolel(1620);			// should be taken from UpdateCapabilitiesMessage
909 				channelVideoParams->h264.lel_customMaxDPB = htolel(8100);			// should be taken from UpdateCapabilitiesMessage
910 				channelVideoParams->h264.lel_customMaxBRandCPB = htolel(10000);			// should be taken from UpdateCapabilitiesMessage
911 			} else {
912 				// error
913 			}
914 		}
915 	}
916 	// Leave empty for now, until we find out more about encryption
917 	//msg->data.OpenMultiMediaChannelMessage.v17.RxEncryptionInfo = {0};
918 	msg->data.OpenMultiMediaChannelMessage.v17.lel_streamPassThroughID = htolel(channel->passthrupartyid);
919 	msg->data.OpenMultiMediaChannelMessage.v17.lel_associatedStreamID = htolel(channel->callid);		// We should use a random number and link it up
920 														// with the MultiMediaTransmission
921 
922 	/* Source Ip Address */
923 	struct sockaddr_storage sas;
924 	if (device->directrtp) {
925 		sccp_rtp_getPeer(&channel->rtp.video, &sas);
926 	} else {
927 		sccp_rtp_getUs(&channel->rtp.video, &sas);
928 	}
929 	sccp_netsock_ipv4_mapped(&sas, &sas);
930 
931 	if (sas.ss_family == AF_INET6) {
932 		struct sockaddr_in6 *in6 = (struct sockaddr_in6 *) &sas;
933 		msg->data.OpenMultiMediaChannelMessage.v17.sourceIpAddr.lel_ipAddrType = htolel(SKINNY_IPADDR_IPV6);
934 
935 		// Also take into account that we could be using IPv46 (ie: both of them)
936 		if (sccp_netsock_is_mapped_IPv4(&sas)) {
937 			msg->data.OpenMultiMediaChannelMessage.v17.lel_requestedIpAddrType = htolel(SKINNY_IPADDR_IPV46);
938 		} else {
939 			msg->data.OpenMultiMediaChannelMessage.v17.lel_requestedIpAddrType = htolel(SKINNY_IPADDR_IPV6);
940 		}
941 		memcpy(&msg->data.OpenMultiMediaChannelMessage.v17.sourceIpAddr.stationIpAddr, &in6->sin6_addr, 16);
942 	} else {
943 		struct sockaddr_in *in = (struct sockaddr_in *) &sas;
944 		msg->data.OpenMultiMediaChannelMessage.v17.sourceIpAddr.lel_ipAddrType = htolel(SKINNY_IPADDR_IPV4);
945 		msg->data.OpenMultiMediaChannelMessage.v17.lel_requestedIpAddrType = htolel(SKINNY_IPADDR_IPV4);
946 		memcpy(&msg->data.OpenMultiMediaChannelMessage.v17.sourceIpAddr.stationIpAddr, &in->sin_addr, 4);
947 	}
948 	msg->data.OpenMultiMediaChannelMessage.v17.lel_sourcePortNumber=htolel(sccp_netsock_getPort(&sas));
949 
950 	//sccp_dump_msg(msg);
951 	sccp_dev_send(device, msg);
952 }
953 
954 /*!
955  * \brief Send Start Media Transmission (V3)
956  */
sccp_protocol_sendStartMediaTransmissionV3(constDevicePtr device,constChannelPtr channel)957 static void sccp_protocol_sendStartMediaTransmissionV3(constDevicePtr device, constChannelPtr channel)
958 {
959 	sccp_msg_t *msg = sccp_build_packet(StartMediaTransmission, sizeof(msg->data.StartMediaTransmission.v3));
960 
961         uint framing = iPbx.get_codec_framing ? iPbx.get_codec_framing(channel) : 20;
962         uint dtmf_payload_code = iPbx.get_dtmf_payload_code ? iPbx.get_dtmf_payload_code(channel) : 101;
963 
964 	msg->data.StartMediaTransmission.v3.lel_conferenceId = htolel(channel->callid);
965 	msg->data.StartMediaTransmission.v3.lel_passThruPartyId = htolel(channel->passthrupartyid);
966 	msg->data.StartMediaTransmission.v3.lel_callReference = htolel(channel->callid);
967 	msg->data.StartMediaTransmission.v3.lel_millisecondPacketSize = htolel(framing);
968 	//msg->data.StartMediaTransmission.v3.lel_payloadType = htolel(channel->rtp.audio.transmission.format);
969 	msg->data.StartMediaTransmission.v3.lel_codecType = htolel(channel->rtp.audio.transmission.format);
970 	msg->data.StartMediaTransmission.v3.lel_precedenceValue = htolel((uint32_t)device->audio_tos);
971 	msg->data.StartMediaTransmission.v3.lel_ssValue = htolel(channel->line->silencesuppression);		// Silence supression
972 	msg->data.StartMediaTransmission.v3.lel_maxFramesPerPacket = htolel(0);
973 	msg->data.StartMediaTransmission.v3.lel_RFC2833Type = htolel(dtmf_payload_code);
974 	msg->data.StartMediaTransmission.v3.lel_dtmfType = htolel(10);;
975 
976 	if (channel->rtp.audio.phone_remote.ss_family == AF_INET) {
977 		struct sockaddr_in *in = (struct sockaddr_in *) &channel->rtp.audio.phone_remote;
978 
979 		memcpy(&msg->data.StartMediaTransmission.v3.bel_remoteIpAddr, &in->sin_addr, 4);
980 	} else {
981 		/* \todo add warning */
982 	}
983 	msg->data.StartMediaTransmission.v3.lel_remotePortNumber = htolel(sccp_netsock_getPort(&channel->rtp.audio.phone_remote));
984 
985 	sccp_dev_send(device, msg);
986 }
987 
988 /*!
989  * \brief Send Start Media Transmission (V17)
990  */
sccp_protocol_sendStartMediaTransmissionV17(constDevicePtr device,constChannelPtr channel)991 static void sccp_protocol_sendStartMediaTransmissionV17(constDevicePtr device, constChannelPtr channel)
992 {
993 	sccp_msg_t *msg = sccp_build_packet(StartMediaTransmission, sizeof(msg->data.StartMediaTransmission.v17));
994 
995         uint framing = iPbx.get_codec_framing ? iPbx.get_codec_framing(channel) : 20;
996         uint dtmf_payload_code = iPbx.get_dtmf_payload_code ? iPbx.get_dtmf_payload_code(channel) : 101;
997 
998 	msg->data.StartMediaTransmission.v17.lel_conferenceId = htolel(channel->callid);
999 	msg->data.StartMediaTransmission.v17.lel_passThruPartyId = htolel(channel->passthrupartyid);
1000 	msg->data.StartMediaTransmission.v17.lel_callReference = htolel(channel->callid);
1001 	msg->data.StartMediaTransmission.v17.lel_millisecondPacketSize = htolel(framing);
1002 	//msg->data.StartMediaTransmission.v17.lel_payloadType = htolel(channel->rtp.audio.transmission.format);
1003 	msg->data.StartMediaTransmission.v17.lel_codecType = htolel(channel->rtp.audio.transmission.format);
1004 	msg->data.StartMediaTransmission.v17.lel_precedenceValue = htolel((uint32_t)device->audio_tos);
1005 	msg->data.StartMediaTransmission.v17.lel_ssValue = htolel(channel->line->silencesuppression);		// Silence supression
1006 	msg->data.StartMediaTransmission.v17.lel_maxFramesPerPacket = htolel(0);
1007 	msg->data.StartMediaTransmission.v17.lel_RFC2833Type = htolel(dtmf_payload_code);
1008 	msg->data.StartMediaTransmission.v17.lel_dtmfType = htolel(10);;
1009 
1010 	if (channel->rtp.audio.phone_remote.ss_family == AF_INET6) {
1011 		struct sockaddr_in6 *in6 = (struct sockaddr_in6 *) &channel->rtp.audio.phone_remote;
1012 
1013 		memcpy(&msg->data.StartMediaTransmission.v17.bel_remoteIpAddr, &in6->sin6_addr, 16);
1014 		msg->data.StartMediaTransmission.v17.lel_ipv46 = htolel(1);
1015 	} else {
1016 		struct sockaddr_in *in = (struct sockaddr_in *) &channel->rtp.audio.phone_remote;
1017 
1018 		memcpy(&msg->data.StartMediaTransmission.v17.bel_remoteIpAddr, &in->sin_addr, 4);
1019 	}
1020 	msg->data.StartMediaTransmission.v17.lel_remotePortNumber = htolel(sccp_netsock_getPort(&channel->rtp.audio.phone_remote));
1021 	sccp_dev_send(device, msg);
1022 }
1023 
1024 /*!
1025  * \brief Send Start Media Transmission (v22)
1026  */
sccp_protocol_sendStartMediaTransmissionv22(constDevicePtr device,constChannelPtr channel)1027 static void sccp_protocol_sendStartMediaTransmissionv22(constDevicePtr device, constChannelPtr channel)
1028 {
1029 	sccp_msg_t *msg = sccp_build_packet(StartMediaTransmission, sizeof(msg->data.StartMediaTransmission.v22));
1030 
1031         uint framing = iPbx.get_codec_framing ? iPbx.get_codec_framing(channel) : 20;
1032         uint dtmf_payload_code = iPbx.get_dtmf_payload_code ? iPbx.get_dtmf_payload_code(channel) : 101;
1033 
1034 	msg->data.StartMediaTransmission.v22.lel_conferenceId = htolel(channel->callid);
1035 	msg->data.StartMediaTransmission.v22.lel_passThruPartyId = htolel(channel->passthrupartyid);
1036 	msg->data.StartMediaTransmission.v22.lel_callReference = htolel(channel->callid);
1037 	msg->data.StartMediaTransmission.v22.lel_millisecondPacketSize = htolel(framing);
1038 	//msg->data.StartMediaTransmission.v22.lel_payloadType = htolel(channel->rtp.audio.transmission.format);
1039 	msg->data.StartMediaTransmission.v22.lel_codecType = htolel(channel->rtp.audio.transmission.format);
1040 	msg->data.StartMediaTransmission.v22.lel_precedenceValue = htolel((uint32_t)device->audio_tos);
1041 	msg->data.StartMediaTransmission.v22.lel_ssValue = htolel(channel->line->silencesuppression);		// Silence supression
1042 	msg->data.StartMediaTransmission.v22.lel_maxFramesPerPacket = htolel(0);
1043 	msg->data.StartMediaTransmission.v22.lel_RFC2833Type = htolel(dtmf_payload_code);
1044 	msg->data.StartMediaTransmission.v22.lel_dtmfType = htolel(10);;
1045 
1046 	if (channel->rtp.audio.phone_remote.ss_family == AF_INET6) {
1047 		struct sockaddr_in6 *in6 = (struct sockaddr_in6 *) &channel->rtp.audio.phone_remote;
1048 
1049 		memcpy(&msg->data.StartMediaTransmission.v22.bel_remoteIpAddr, &in6->sin6_addr, 16);
1050 		msg->data.StartMediaTransmission.v22.lel_ipv46 = htolel(1);
1051 	} else {
1052 		struct sockaddr_in *in = (struct sockaddr_in *) &channel->rtp.audio.phone_remote;
1053 
1054 		memcpy(&msg->data.StartMediaTransmission.v22.bel_remoteIpAddr, &in->sin_addr, 4);
1055 	}
1056 	msg->data.StartMediaTransmission.v22.lel_remotePortNumber = htolel(sccp_netsock_getPort(&channel->rtp.audio.phone_remote));
1057 	sccp_dev_send(device, msg);
1058 }
1059 
1060 /*!
1061  * \brief Send Start MultiMedia Transmission (V3)
1062  */
sccp_protocol_sendStartMultiMediaTransmissionV3(constDevicePtr device,constChannelPtr channel,int payloadType,int bitRate)1063 static void sccp_protocol_sendStartMultiMediaTransmissionV3(constDevicePtr device, constChannelPtr channel, int payloadType, int bitRate)
1064 {
1065 	sccp_msg_t *msg = sccp_build_packet(StartMultiMediaTransmission, sizeof(msg->data.StartMultiMediaTransmission.v3));
1066 	//uint payloadType = sccp_rtp_get_payloadType(&channel->rtp.video, video->transmission.format);
1067 
1068 	msg->data.StartMultiMediaTransmission.v3.lel_conferenceID = htolel(channel->callid);
1069 	msg->data.StartMultiMediaTransmission.v3.lel_passThruPartyId = htolel(channel->passthrupartyid);
1070 	//msg->data.StartMultiMediaTransmission.v3.lel_payloadCapability = htolel(channel->rtp.video.transmission.format);
1071 	msg->data.StartMultiMediaTransmission.v3.lel_codecType = htolel(channel->rtp.video.transmission.format);
1072 	msg->data.StartMultiMediaTransmission.v3.lel_callReference = htolel(channel->callid);
1073 	msg->data.StartMultiMediaTransmission.v3.lel_payload_rfc_number = htolel(0);
1074 	msg->data.StartMultiMediaTransmission.v3.lel_payloadType = htolel(payloadType);
1075 	msg->data.StartMultiMediaTransmission.v3.lel_DSCPValue = htolel(136);
1076 	msg->data.StartMultiMediaTransmission.v3.videoParameter.bitRate = htolel(bitRate);
1077 	//msg->data.StartMultiMediaTransmission.v3.videoParameter.pictureFormatCount            = htolel(0);
1078 	//msg->data.StartMultiMediaTransmission.v3.videoParameter.pictureFormat[0].format       = htolel(4);
1079 	//msg->data.StartMultiMediaTransmission.v3.videoParameter.pictureFormat[0].mpi          = htolel(30);
1080 	msg->data.StartMultiMediaTransmission.v3.videoParameter.profile = htolel(0x40);
1081 	msg->data.StartMultiMediaTransmission.v3.videoParameter.level = htolel(0x32);				/* has to be >= 15 to work with 7985 */
1082 	msg->data.StartMultiMediaTransmission.v3.videoParameter.macroblockspersec = htolel(40500);
1083 	msg->data.StartMultiMediaTransmission.v3.videoParameter.macroblocksperframe = htolel(1620);
1084 	msg->data.StartMultiMediaTransmission.v3.videoParameter.decpicbuf = htolel(8100);
1085 	msg->data.StartMultiMediaTransmission.v3.videoParameter.brandcpb = htolel(10000);
1086 	msg->data.StartMultiMediaTransmission.v3.videoParameter.confServiceNum = htolel(channel->callid);
1087 	msg->data.StartMultiMediaTransmission.v3.lel_remotePortNumber = htolel(sccp_netsock_getPort(&channel->rtp.video.phone_remote));
1088 	if (channel->rtp.video.phone_remote.ss_family == AF_INET) {
1089 		struct sockaddr_in *in = (struct sockaddr_in *) &channel->rtp.video.phone_remote;
1090 
1091 		memcpy(&msg->data.StartMultiMediaTransmission.v3.bel_remoteIpAddr, &in->sin_addr, 4);
1092 	} else {
1093 		/* \todo add warning */
1094 	}
1095 
1096 	//sccp_dump_msg(msg);
1097 	sccp_dev_send(device, msg);
1098 }
1099 
1100 /*!
1101  * \brief Send Start MultiMedia Transmission (V17)
1102  */
sccp_protocol_sendStartMultiMediaTransmissionV17(constDevicePtr device,constChannelPtr channel,int payloadType,int bitRate)1103 static void sccp_protocol_sendStartMultiMediaTransmissionV17(constDevicePtr device, constChannelPtr channel, int payloadType, int bitRate)
1104 {
1105 	sccp_msg_t *msg = sccp_build_packet(StartMultiMediaTransmission, sizeof(msg->data.StartMultiMediaTransmission.v17));
1106 
1107 	msg->data.StartMultiMediaTransmission.v17.lel_conferenceID = htolel(channel->callid);
1108 	msg->data.StartMultiMediaTransmission.v17.lel_passThruPartyId = htolel(channel->passthrupartyid);
1109 	//msg->data.StartMultiMediaTransmission.v17.lel_payloadCapability = htolel(channel->rtp.video.transmission.format);
1110 	msg->data.StartMultiMediaTransmission.v17.lel_codecType = htolel(channel->rtp.video.transmission.format);
1111 	msg->data.StartMultiMediaTransmission.v17.lel_callReference = htolel(channel->callid);
1112 	msg->data.StartMultiMediaTransmission.v17.lel_payload_rfc_number = htolel(0);
1113 	msg->data.StartMultiMediaTransmission.v17.lel_payloadType = htolel(payloadType);
1114 	msg->data.StartMultiMediaTransmission.v17.lel_DSCPValue = htolel(136);
1115 	msg->data.StartMultiMediaTransmission.v17.videoParameter.confServiceNum = htolel(channel->callid);
1116 	msg->data.StartMultiMediaTransmission.v17.videoParameter.bitRate = htolel(bitRate);
1117 	//msg->data.StartMultiMediaTransmission.v17.videoParameter.pictureFormatCount        = htolel(1);
1118 	//msg->data.StartMultiMediaTransmission.v17.videoParameter.pictureFormat[0].format   = htolel(4);
1119 	//msg->data.StartMultiMediaTransmission.v17.videoParameter.pictureFormat[0].mpi      = htolel(1);
1120 	msg->data.StartMultiMediaTransmission.v17.videoParameter.profile = htolel(64);
1121 	msg->data.StartMultiMediaTransmission.v17.videoParameter.level = htolel(50);
1122 	msg->data.StartMultiMediaTransmission.v17.videoParameter.macroblockspersec = htolel(40500);
1123 	msg->data.StartMultiMediaTransmission.v17.videoParameter.macroblocksperframe = htolel(1620);
1124 	msg->data.StartMultiMediaTransmission.v17.videoParameter.decpicbuf = htolel(8100);
1125 	msg->data.StartMultiMediaTransmission.v17.videoParameter.brandcpb = htolel(10000);
1126 	//msg->data.StartMultiMediaTransmission.v17.videoParameter.dummy1 = htolel(1);
1127 	//msg->data.StartMultiMediaTransmission.v17.videoParameter.dummy2 = htolel(2);
1128 	//msg->data.StartMultiMediaTransmission.v17.videoParameter.dummy3 = htolel(3);
1129 	//msg->data.StartMultiMediaTransmission.v17.videoParameter.dummy4 = htolel(4);
1130 	//msg->data.StartMultiMediaTransmission.v17.videoParameter.dummy5 = htolel(5);
1131 	//msg->data.StartMultiMediaTransmission.v17.videoParameter.dummy6 = htolel(6);
1132 	//msg->data.StartMultiMediaTransmission.v17.videoParameter.dummy7 = htolel(7);
1133 	//msg->data.StartMultiMediaTransmission.v17.videoParameter.dummy8 = htolel(8);
1134 
1135 	msg->data.StartMultiMediaTransmission.v17.lel_remotePortNumber = htolel(sccp_netsock_getPort(&channel->rtp.video.phone_remote));
1136 	if (channel->rtp.video.phone_remote.ss_family == AF_INET6) {
1137 		struct sockaddr_in6 *in6 = (struct sockaddr_in6 *) &channel->rtp.video.phone_remote;
1138 
1139 		memcpy(&msg->data.StartMultiMediaTransmission.v17.bel_remoteIpAddr, &in6->sin6_addr, 16);
1140 		msg->data.StartMultiMediaTransmission.v17.lel_ipv46 = htolel(1);
1141 	} else {
1142 		struct sockaddr_in *in = (struct sockaddr_in *) &channel->rtp.video.phone_remote;
1143 
1144 		memcpy(&msg->data.StartMultiMediaTransmission.v17.bel_remoteIpAddr, &in->sin_addr, 4);
1145 	}
1146 	//sccp_dump_msg(msg);
1147 	sccp_dev_send(device, msg);
1148 }
1149 
1150 /* fastPictureUpdate */
sccp_protocol_sendMultiMediaCommand(constDevicePtr device,constChannelPtr channel,skinny_miscCommandType_t command)1151 static void sccp_protocol_sendMultiMediaCommand(constDevicePtr device, constChannelPtr channel, skinny_miscCommandType_t command)
1152 {
1153 	sccp_msg_t *msg = NULL;
1154 
1155 	REQ(msg, MiscellaneousCommandMessage);
1156 
1157 	msg->data.MiscellaneousCommandMessage.lel_conferenceId = htolel(channel->callid);
1158 	msg->data.MiscellaneousCommandMessage.lel_passThruPartyId = htolel(channel->passthrupartyid);
1159 	msg->data.MiscellaneousCommandMessage.lel_callReference = htolel(channel->callid);
1160 	msg->data.MiscellaneousCommandMessage.lel_miscCommandType = htolel(command);
1161 
1162 	sccp_dev_send(device, msg);
1163 }
1164 
1165 /* done - fastPictureUpdate */
1166 
1167 /* sendUserToDeviceData Message */
1168 
1169 /*!
1170  * \brief Send User To Device Message (V1)
1171  */
sccp_protocol_sendUserToDeviceDataVersion1Message(constDevicePtr device,uint32_t appID,uint32_t lineInstance,uint32_t callReference,uint32_t transactionID,const char * xmlData,uint8_t priority)1172 static void sccp_protocol_sendUserToDeviceDataVersion1Message(constDevicePtr device, uint32_t appID, uint32_t lineInstance, uint32_t callReference, uint32_t transactionID, const char *xmlData, uint8_t priority)
1173 {
1174 	int data_len = strlen(xmlData);
1175 	int msg_len = 0;
1176 	int hdr_len = 0;
1177 
1178 	if (device->protocolversion > 17) {
1179 		int segment = 0;
1180 
1181 		sccp_msg_t *msg = NULL;
1182 		hdr_len = sizeof(msg->data.UserToDeviceDataVersion1Message);
1183 		int Sequence = 0x0000;
1184 		int xmlDataStart = 0;
1185 
1186 		while (data_len) {
1187 			if (data_len > StationMaxXMLMessage) {
1188 				msg_len = StationMaxXMLMessage;
1189 			} else {
1190 				msg_len = data_len;
1191 				Sequence = 0x0002;
1192 			}
1193 			data_len -= msg_len;
1194 			msg = sccp_build_packet(UserToDeviceDataVersion1Message, hdr_len + msg_len);
1195 			if (!msg) {
1196 				pbx_log(LOG_ERROR, SS_Memory_Allocation_Error, "SCCP");
1197 				return;
1198 			}
1199 			msg->data.UserToDeviceDataVersion1Message.lel_appID = htolel(appID);
1200 			msg->data.UserToDeviceDataVersion1Message.lel_lineInstance = htolel(lineInstance);
1201 			msg->data.UserToDeviceDataVersion1Message.lel_callReference = htolel(callReference);
1202 			msg->data.UserToDeviceDataVersion1Message.lel_transactionID = htolel(transactionID);
1203 			msg->data.UserToDeviceDataVersion1Message.lel_displayPriority = htolel(priority);
1204 			msg->data.UserToDeviceDataVersion1Message.lel_dataLength = htolel(msg_len);
1205 			msg->data.UserToDeviceDataVersion1Message.lel_sequenceFlag = htolel(Sequence);
1206 			msg->data.UserToDeviceDataVersion1Message.lel_conferenceID = htolel(callReference);
1207 			msg->data.UserToDeviceDataVersion1Message.lel_appInstanceID = htolel(appID);
1208 			msg->data.UserToDeviceDataVersion1Message.lel_routing = htolel(1);
1209 			if (Sequence == 0x0000) {
1210 				Sequence = 0x0001;
1211 			}
1212 
1213 			if (msg_len) {
1214 				memcpy(&msg->data.UserToDeviceDataVersion1Message.data, xmlData + xmlDataStart, msg_len);
1215 				xmlDataStart += msg_len;
1216 			}
1217 
1218 			sccp_dev_send(device, msg);
1219 			sccp_log(DEBUGCAT_HIGH) (VERBOSE_PREFIX_1 "%s: (sccp_protocol_sendUserToDeviceDataVersion1Message) Message sent to device  (hdr_len: %d, msglen: %d/%d, msg-size: %d).\n", DEV_ID_LOG(device), hdr_len, msg_len, (int) strlen(xmlData), hdr_len + msg_len);
1220 			segment++;
1221 		}
1222 	} else if (data_len < StationMaxXMLMessage) {
1223 		sccp_msg_t *msg = NULL;
1224 
1225 		hdr_len = sizeof(msg->data.UserToDeviceDataVersion1Message);
1226 		msg_len = data_len;
1227 
1228 		msg = sccp_build_packet(UserToDeviceDataVersion1Message, hdr_len + msg_len);
1229 		msg->data.UserToDeviceDataVersion1Message.lel_appID = htolel(appID);
1230 		msg->data.UserToDeviceDataVersion1Message.lel_lineInstance = htolel(lineInstance);
1231 		msg->data.UserToDeviceDataVersion1Message.lel_callReference = htolel(callReference);
1232 		msg->data.UserToDeviceDataVersion1Message.lel_transactionID = htolel(transactionID);
1233 		msg->data.UserToDeviceDataVersion1Message.lel_sequenceFlag = htolel(0x0002);
1234 		msg->data.UserToDeviceDataVersion1Message.lel_displayPriority = htolel(priority);
1235 		msg->data.UserToDeviceDataVersion1Message.lel_dataLength = htolel(msg_len);
1236 
1237 		if (msg_len) {
1238 			memcpy(&msg->data.UserToDeviceDataVersion1Message.data, xmlData, msg_len);
1239 		}
1240 		sccp_dev_send(device, msg);
1241 		sccp_log(DEBUGCAT_HIGH) (VERBOSE_PREFIX_1 "%s: (sccp_protocol_sendUserToDeviceDataVersion1Message) Message sent to device  (hdr_len: %d, msglen: %d, msg-size: %d).\n", DEV_ID_LOG(device), hdr_len, msg_len, hdr_len + msg_len);
1242 	} else {
1243 		sccp_log(DEBUGCAT_CORE) (VERBOSE_PREFIX_1 "%s: (sccp_protocol_sendUserToDeviceDataVersion1Message) Message to large to send to device  (msg-size: %d). Skipping !\n", DEV_ID_LOG(device), data_len);
1244 	}
1245 }
1246 
1247 /* done - sendUserToDeviceData */
1248 
1249 /* sendConnectionStatisticsReq Message */
1250 /*!
1251  * \brief Send Start MultiMedia Transmission (V3)
1252  */
sccp_protocol_sendConnectionStatisticsReqV3(constDevicePtr device,constChannelPtr channel,uint8_t clear)1253 static void sccp_protocol_sendConnectionStatisticsReqV3(constDevicePtr device, constChannelPtr channel, uint8_t clear)
1254 {
1255 	sccp_msg_t *msg = sccp_build_packet(ConnectionStatisticsReq, sizeof(msg->data.ConnectionStatisticsReq.v3));
1256 	if (channel->calltype == SKINNY_CALLTYPE_OUTBOUND) {
1257 		iCallInfo.Getter(sccp_channel_getCallInfo(channel),	SCCP_CALLINFO_CALLEDPARTY_NUMBER, &msg->data.ConnectionStatisticsReq.v3.DirectoryNumber, SCCP_CALLINFO_KEY_SENTINEL);
1258 	} else {
1259 		iCallInfo.Getter(sccp_channel_getCallInfo(channel),	SCCP_CALLINFO_CALLINGPARTY_NUMBER, &msg->data.ConnectionStatisticsReq.v3.DirectoryNumber, SCCP_CALLINFO_KEY_SENTINEL);
1260 	}
1261 	msg->data.ConnectionStatisticsReq.v3.lel_callReference = htolel((channel) ? channel->callid : 0);
1262 	msg->data.ConnectionStatisticsReq.v3.lel_StatsProcessing = htolel(clear);
1263 	sccp_dev_send(device, msg);
1264 }
1265 
1266 /*!
1267  * \brief Send Start MultiMedia Transmission (V17)
1268  */
sccp_protocol_sendConnectionStatisticsReqV19(constDevicePtr device,constChannelPtr channel,uint8_t clear)1269 static void sccp_protocol_sendConnectionStatisticsReqV19(constDevicePtr device, constChannelPtr channel, uint8_t clear)
1270 {
1271 	sccp_msg_t *msg = sccp_build_packet(ConnectionStatisticsReq, sizeof(msg->data.ConnectionStatisticsReq.v19));
1272 
1273 	if (channel->calltype == SKINNY_CALLTYPE_OUTBOUND) {
1274 		iCallInfo.Getter(sccp_channel_getCallInfo(channel),	SCCP_CALLINFO_CALLEDPARTY_NUMBER,  &msg->data.ConnectionStatisticsReq.v19.DirectoryNumber, SCCP_CALLINFO_KEY_SENTINEL);
1275 	} else {
1276 		iCallInfo.Getter(sccp_channel_getCallInfo(channel),	SCCP_CALLINFO_CALLINGPARTY_NUMBER, &msg->data.ConnectionStatisticsReq.v19.DirectoryNumber, SCCP_CALLINFO_KEY_SENTINEL);
1277 	}
1278 	msg->data.ConnectionStatisticsReq.v19.lel_callReference = htolel((channel) ? channel->callid : 0);
1279 	msg->data.ConnectionStatisticsReq.v19.lel_StatsProcessing = htolel(clear);
1280 	sccp_dev_send(device, msg);
1281 }
1282 /* done - sendUserToDeviceData */
1283 
1284 
1285 /* sendPortRequest */
1286 /*!
1287  * \brief Send PortRequest (V3)
1288  */
sccp_protocol_sendPortRequest(constDevicePtr device,constChannelPtr channel,skinny_mediaTransportType_t mediaTransportType,skinny_mediaType_t mediaType)1289 static void sccp_protocol_sendPortRequest(constDevicePtr device, constChannelPtr channel, skinny_mediaTransportType_t mediaTransportType, skinny_mediaType_t mediaType)
1290 {
1291 	struct sockaddr_storage sas;
1292 	memcpy(&sas, &channel->rtp.audio.phone_remote, sizeof(struct sockaddr_storage));
1293 	sccp_msg_t *msg = sccp_build_packet(PortRequestMessage, sizeof(msg->data.PortRequestMessage));
1294 
1295 	msg->data.PortRequestMessage.lel_conferenceId = htolel(channel->callid);
1296 	msg->data.PortRequestMessage.lel_callReference = htolel(channel->callid);
1297 	msg->data.PortRequestMessage.lel_passThruPartyId = htolel(channel->passthrupartyid);
1298 	msg->data.PortRequestMessage.lel_mediaTransportType = htolel(mediaTransportType);
1299 	msg->data.PortRequestMessage.lel_ipv46 = htolel(sccp_netsock_is_IPv6(&sas) ? 1 : 0);
1300 	msg->data.PortRequestMessage.lel_mediaType = htolel(mediaType);
1301 
1302 	sccp_dev_send(device, msg);
1303 }
1304 /* done - sendPortRequest */
1305 
1306 /* sendPortClose */
1307 /*!
1308  * \brief Send PortClose
1309  */
sccp_protocol_sendPortClose(constDevicePtr device,constChannelPtr channel,skinny_mediaType_t mediaType)1310 static void sccp_protocol_sendPortClose(constDevicePtr device, constChannelPtr channel, skinny_mediaType_t mediaType)
1311 {
1312 	if (device->protocol && device->protocol->version >= 11) {
1313 		sccp_msg_t *msg = sccp_build_packet(PortCloseMessage, sizeof(msg->data.PortCloseMessage));
1314 		msg->data.PortCloseMessage.lel_conferenceId = htolel(channel->callid);
1315 		msg->data.PortCloseMessage.lel_passThruPartyId = htolel(channel->passthrupartyid);
1316 		msg->data.PortCloseMessage.lel_callReference = htolel(channel->callid);
1317 		msg->data.PortCloseMessage.lel_mediaType = htolel(mediaType);
1318 		sccp_dev_send(device, msg);
1319 	}
1320 }
1321 /* done - sendPortClose */
1322 
1323 /*! \todo need a protocol implementation for ConnectionStatisticsReq using Version 19 and higher */
1324 
1325 /*! \todo need a protocol implementation for ForwardStatMessage using Version 19 and higher */
1326 
1327 /* sendLineStatResponse Message */
1328 /*!
1329  * \brief Send Start Line State Response Message (V3)
1330  */
sccp_protocol_sendLineStatRespV3(constDevicePtr d,uint32_t lineNumber,char * dirNumber,char * fullyQualifiedDisplayName,char * displayName)1331 static void sccp_protocol_sendLineStatRespV3(constDevicePtr d, uint32_t lineNumber, char *dirNumber, char *fullyQualifiedDisplayName, char *displayName)
1332 {
1333 	sccp_msg_t *msg = NULL;
1334 	REQ(msg, LineStatMessage);
1335 	msg->data.LineStatMessage.lel_lineNumber = htolel(lineNumber);
1336 	d->copyStr2Locale(d, msg->data.LineStatMessage.lineDirNumber, dirNumber, sizeof(msg->data.LineStatMessage.lineDirNumber));
1337 	d->copyStr2Locale(d, msg->data.LineStatMessage.lineFullyQualifiedDisplayName, fullyQualifiedDisplayName, sizeof(msg->data.LineStatMessage.lineFullyQualifiedDisplayName));
1338 	d->copyStr2Locale(d, msg->data.LineStatMessage.lineDisplayName, displayName, sizeof(msg->data.LineStatMessage.lineDisplayName));
1339 
1340 	//Bit-field: 1-Original Dialed 2-Redirected Dialed, 4-Calling line ID, 8-Calling name ID
1341 	//msg->data.LineStatMessage.lel_lineDisplayOptions = 0x01 & 0x08;
1342 	msg->data.LineStatMessage.lel_lineDisplayOptions = htolel(15);		// value : 0 or 15
1343 	sccp_dev_send(d, msg);
1344 }
1345 
1346 /*!
1347  * \brief Send Start Line State Response Message (V17)
1348  */
sccp_protocol_sendLineStatRespV17(constDevicePtr d,uint32_t lineNumber,char * dirNumber,char * fullyQualifiedDisplayName,char * displayName)1349 static void sccp_protocol_sendLineStatRespV17(constDevicePtr d, uint32_t lineNumber, char *dirNumber, char *fullyQualifiedDisplayName, char *displayName)
1350 {
1351 	int dirNumLen = dirNumber ? sccp_strlen(dirNumber): 0;
1352 	int fqdnLen = fullyQualifiedDisplayName ? sccp_strlen(fullyQualifiedDisplayName): 0;
1353 	int displayNameLen = displayName ? sccp_strlen(displayName): 0;
1354 	int dummyLen = dirNumLen + fqdnLen + displayNameLen;
1355 
1356  	int pktLen = SCCP_PACKET_HEADER + dummyLen;
1357 	sccp_msg_t *msg = sccp_build_packet(LineStatDynamicMessage, pktLen);
1358 	msg->data.LineStatDynamicMessage.lel_lineNumber = htolel(lineNumber);
1359 
1360 	if (dummyLen) {
1361 		char *dummyPtr = msg->data.LineStatDynamicMessage.dummy;
1362 		d->copyStr2Locale(d, dummyPtr, dirNumber, dirNumLen+1);
1363 		dummyPtr += dirNumLen + 1;
1364 		d->copyStr2Locale(d, dummyPtr, fullyQualifiedDisplayName, fqdnLen+1);
1365 		dummyPtr += fqdnLen + 1;
1366 		d->copyStr2Locale(d, dummyPtr, displayName, displayNameLen+1);
1367 		dummyPtr += displayNameLen + 1;
1368 	}
1369 
1370 	//Bit-field: 1-Original Dialed 2-Redirected Dialed, 4-Calling line ID, 8-Calling name ID
1371 	//int lineDisplayOptions = 0x01 & 0x08;
1372 	//int lineDisplayOptions = htolel(15);
1373 	//msg->data.LineStatDynamicMessage.lel_lineDisplayOptions = htolel(lineDisplayOptions);
1374 	sccp_dev_send(d, msg);
1375 }
1376 
1377 /*
1378 static void sccp_protocol_sendLineStatRespV17(constDevicePtr d, uint32_t lineNumber, char *dirNumber, char *fullyQualifiedDisplayName, char *displayName)
1379 {
1380 	sccp_msg_t *msg = NULL;
1381 	REQ(msg, LineStatDynamicMessage);
1382 	msg->data.LineStatDynamicMessage.lel_lineNumber = htolel(lineNumber);
1383 	d->copyStr2Locale(d, msg->data.LineStatDynamicMessage.lineDirNumber, dirNumber, sizeof(msg->data.LineStatDynamicMessage.lineDirNumber));
1384 	d->copyStr2Locale(d, msg->data.LineStatDynamicMessage.lineFullyQualifiedDisplayName, fullyQualifiedDisplayName, sizeof(msg->data.LineStatDynamicMessage.lineFullyQualifiedDisplayName));
1385 	d->copyStr2Locale(d, msg->data.LineStatDynamicMessage.lineTextLabel, displayName, sizeof(msg->data.LineStatDynamicMessage.lineTextLabel));
1386 
1387 	//Bit-field: 1-Original Dialed 2-Redirected Dialed, 4-Calling line ID, 8-Calling name ID
1388 	//msg->data.LineStatDynamicMessage.lel_lineDisplayOptions = 0x01 & 0x08;
1389 	msg->data.LineStatDynamicMessage.lel_lineDisplayOptions = htolel(15);
1390 	sccp_dev_send(d, msg);
1391 }
1392 */
1393 /* done - sendLineStat */
1394 
1395 /* =================================================================================================================== Parse Received Messages */
1396 
1397 /*!
1398  * \brief OpenReceiveChannelAck
1399  */
sccp_protocol_parseOpenReceiveChannelAckV3(constMessagePtr msg,skinny_mediastatus_t * mediastatus,struct sockaddr_storage * ss,uint32_t * passthrupartyid,uint32_t * callReference)1400 static void sccp_protocol_parseOpenReceiveChannelAckV3(constMessagePtr msg, skinny_mediastatus_t * mediastatus, struct sockaddr_storage *ss, uint32_t * passthrupartyid, uint32_t * callReference)
1401 {
1402 	*mediastatus = letohl(msg->data.OpenReceiveChannelAck.v3.lel_mediastatus);
1403 	*callReference = letohl(msg->data.OpenReceiveChannelAck.v3.lel_callReference);
1404 	*passthrupartyid = letohl(msg->data.OpenReceiveChannelAck.v3.lel_passThruPartyId);
1405 
1406 	ss->ss_family = AF_INET;
1407 	struct sockaddr_in *sin = (struct sockaddr_in *) ss;
1408 
1409 	memcpy(&sin->sin_addr, &msg->data.OpenReceiveChannelAck.v3.bel_ipAddr, sizeof(sin->sin_addr));
1410 	sin->sin_port = htons(htolel(msg->data.OpenReceiveChannelAck.v3.lel_portNumber));
1411 }
1412 
sccp_protocol_parseOpenReceiveChannelAckV17(constMessagePtr msg,skinny_mediastatus_t * mediastatus,struct sockaddr_storage * ss,uint32_t * passthrupartyid,uint32_t * callReference)1413 static void sccp_protocol_parseOpenReceiveChannelAckV17(constMessagePtr msg, skinny_mediastatus_t * mediastatus, struct sockaddr_storage *ss, uint32_t * passthrupartyid, uint32_t * callReference)
1414 {
1415 	*mediastatus = letohl(msg->data.OpenReceiveChannelAck.v17.lel_mediastatus);
1416 	*callReference = letohl(msg->data.OpenReceiveChannelAck.v17.lel_callReference);
1417 	*passthrupartyid = letohl(msg->data.OpenReceiveChannelAck.v17.lel_passThruPartyId);
1418 
1419 	if (letohl(msg->data.OpenReceiveChannelAck.v17.lel_ipv46) == 0) {					// read ipv4 address
1420 		ss->ss_family = AF_INET;
1421 		struct sockaddr_in *sin = (struct sockaddr_in *) ss;
1422 
1423 		memcpy(&sin->sin_addr, &msg->data.OpenReceiveChannelAck.v17.bel_ipAddr, sizeof(sin->sin_addr));
1424 		sin->sin_port = htons(htolel(msg->data.OpenReceiveChannelAck.v17.lel_portNumber));
1425 	} else {												// read ipv6 address
1426 		/* what to do with IPv4-mapped IPv6 addresses */
1427 		ss->ss_family = AF_INET6;
1428 		struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) ss;
1429 
1430 		memcpy(&sin6->sin6_addr, &msg->data.OpenReceiveChannelAck.v17.bel_ipAddr, sizeof(sin6->sin6_addr));
1431 		sin6->sin6_port = htons(htolel(msg->data.OpenReceiveChannelAck.v17.lel_portNumber));
1432 	}
1433 }
1434 
sccp_protocol_parseOpenMultiMediaReceiveChannelAckV3(constMessagePtr msg,skinny_mediastatus_t * mediastatus,struct sockaddr_storage * ss,uint32_t * passthrupartyid,uint32_t * callReference)1435 static void sccp_protocol_parseOpenMultiMediaReceiveChannelAckV3(constMessagePtr msg, skinny_mediastatus_t * mediastatus, struct sockaddr_storage *ss, uint32_t * passthrupartyid, uint32_t * callReference)
1436 {
1437 	*mediastatus = letohl(msg->data.OpenMultiMediaReceiveChannelAckMessage.v3.lel_mediastatus);
1438 	*passthrupartyid = letohl(msg->data.OpenMultiMediaReceiveChannelAckMessage.v3.lel_passThruPartyId);
1439 	*callReference = letohl(msg->data.OpenMultiMediaReceiveChannelAckMessage.v3.lel_callReference);
1440 
1441 	ss->ss_family = AF_INET;
1442 	struct sockaddr_in *sin = (struct sockaddr_in *) ss;
1443 
1444 	memcpy(&sin->sin_addr, &msg->data.OpenMultiMediaReceiveChannelAckMessage.v3.bel_ipAddr, sizeof(sin->sin_addr));
1445 	sin->sin_port = htons(htolel(msg->data.OpenMultiMediaReceiveChannelAckMessage.v3.lel_portNumber));
1446 }
1447 
sccp_protocol_parseOpenMultiMediaReceiveChannelAckV17(constMessagePtr msg,skinny_mediastatus_t * mediastatus,struct sockaddr_storage * ss,uint32_t * passthrupartyid,uint32_t * callReference)1448 static void sccp_protocol_parseOpenMultiMediaReceiveChannelAckV17(constMessagePtr msg, skinny_mediastatus_t * mediastatus, struct sockaddr_storage *ss, uint32_t * passthrupartyid, uint32_t * callReference)
1449 {
1450 	*mediastatus = letohl(msg->data.OpenMultiMediaReceiveChannelAckMessage.v17.lel_mediastatus);
1451 	*passthrupartyid = letohl(msg->data.OpenMultiMediaReceiveChannelAckMessage.v17.lel_passThruPartyId);
1452 	*callReference = letohl(msg->data.OpenMultiMediaReceiveChannelAckMessage.v17.lel_callReference);
1453 
1454 	if (letohl(msg->data.OpenMultiMediaReceiveChannelAckMessage.v17.lel_ipv46) == 0) {			// read ipv4 address
1455 		ss->ss_family = AF_INET;
1456 		struct sockaddr_in *sin = (struct sockaddr_in *) ss;
1457 
1458 		memcpy(&sin->sin_addr, &msg->data.OpenMultiMediaReceiveChannelAckMessage.v17.bel_ipAddr, sizeof(sin->sin_addr));
1459 		sin->sin_port = htons(htolel(msg->data.OpenMultiMediaReceiveChannelAckMessage.v17.lel_portNumber));
1460 	} else {												// read ipv6 address
1461 		/* what to do with IPv4-mapped IPv6 addresses */
1462 		ss->ss_family = AF_INET6;
1463 		struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) ss;
1464 
1465 		memcpy(&sin6->sin6_addr, &msg->data.OpenMultiMediaReceiveChannelAckMessage.v17.bel_ipAddr, sizeof(sin6->sin6_addr));
1466 		sin6->sin6_port = htons(htolel(msg->data.OpenMultiMediaReceiveChannelAckMessage.v17.lel_portNumber));
1467 	}
1468 }
1469 
1470 /*!
1471  * \brief StartMediaTransmissionAck
1472  */
sccp_protocol_parseStartMediaTransmissionAckV3(constMessagePtr msg,uint32_t * partyID,uint32_t * callID,uint32_t * callID1,skinny_mediastatus_t * mediastatus,struct sockaddr_storage * ss)1473 static void sccp_protocol_parseStartMediaTransmissionAckV3(constMessagePtr msg, uint32_t * partyID, uint32_t * callID, uint32_t * callID1, skinny_mediastatus_t * mediastatus, struct sockaddr_storage *ss)
1474 {
1475 	*partyID = letohl(msg->data.StartMediaTransmissionAck.v3.lel_passThruPartyId);
1476 	*callID = letohl(msg->data.StartMediaTransmissionAck.v3.lel_callReference);
1477 	*callID1 = letohl(msg->data.StartMediaTransmissionAck.v3.lel_callReference1);
1478 	*mediastatus = letohl(msg->data.StartMediaTransmissionAck.v3.lel_mediastatus);
1479 
1480 	ss->ss_family = AF_INET;
1481 	struct sockaddr_in *sin = (struct sockaddr_in *) ss;
1482 
1483 	memcpy(&sin->sin_addr, &msg->data.StartMediaTransmissionAck.v3.bel_ipAddr, sizeof(sin->sin_addr));
1484 	sin->sin_port = htons(htolel(msg->data.StartMediaTransmissionAck.v3.lel_portNumber));
1485 }
1486 
sccp_protocol_parseStartMediaTransmissionAckV17(constMessagePtr msg,uint32_t * partyID,uint32_t * callID,uint32_t * callID1,skinny_mediastatus_t * mediastatus,struct sockaddr_storage * ss)1487 static void sccp_protocol_parseStartMediaTransmissionAckV17(constMessagePtr msg, uint32_t * partyID, uint32_t * callID, uint32_t * callID1, skinny_mediastatus_t * mediastatus, struct sockaddr_storage *ss)
1488 {
1489 	*partyID = letohl(msg->data.StartMediaTransmissionAck.v17.lel_passThruPartyId);
1490 	*callID = letohl(msg->data.StartMediaTransmissionAck.v17.lel_callReference);
1491 	*callID1 = letohl(msg->data.StartMediaTransmissionAck.v17.lel_callReference1);
1492 	*mediastatus = letohl(msg->data.StartMediaTransmissionAck.v17.lel_mediastatus);
1493 
1494 	if (letohl(msg->data.StartMediaTransmissionAck.v17.lel_ipv46) == 0) {					// read ipv4 address
1495 		ss->ss_family = AF_INET;
1496 		struct sockaddr_in *sin = (struct sockaddr_in *) ss;
1497 
1498 		memcpy(&sin->sin_addr, &msg->data.StartMediaTransmissionAck.v17.bel_ipAddr, sizeof(sin->sin_addr));
1499 		sin->sin_port = htons(htolel(msg->data.StartMediaTransmissionAck.v17.lel_portNumber));
1500 	} else {												// read ipv6 address
1501 		/* what to do with IPv4-mapped IPv6 addresses */
1502 		ss->ss_family = AF_INET6;
1503 		struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) ss;
1504 
1505 		memcpy(&sin6->sin6_addr, &msg->data.StartMediaTransmissionAck.v17.bel_ipAddr, sizeof(sin6->sin6_addr));
1506 		sin6->sin6_port = htons(htolel(msg->data.StartMediaTransmissionAck.v17.lel_portNumber));
1507 	}
1508 }
1509 
1510 /*!
1511  * \brief StartMultiMediaTransmissionAck
1512  */
sccp_protocol_parseStartMultiMediaTransmissionAckV3(constMessagePtr msg,uint32_t * partyID,uint32_t * callID,uint32_t * callID1,skinny_mediastatus_t * mediastatus,struct sockaddr_storage * ss)1513 static void sccp_protocol_parseStartMultiMediaTransmissionAckV3(constMessagePtr msg, uint32_t * partyID, uint32_t * callID, uint32_t * callID1, skinny_mediastatus_t * mediastatus, struct sockaddr_storage *ss)
1514 {
1515 	*partyID = letohl(msg->data.StartMultiMediaTransmissionAck.v3.lel_passThruPartyId);
1516 	*callID = letohl(msg->data.StartMultiMediaTransmissionAck.v3.lel_callReference);
1517 	*callID1 = letohl(msg->data.StartMultiMediaTransmissionAck.v3.lel_callReference1);
1518 	*mediastatus = letohl(msg->data.StartMultiMediaTransmissionAck.v3.lel_mediastatus);
1519 
1520 	ss->ss_family = AF_INET;
1521 	struct sockaddr_in *sin = (struct sockaddr_in *) ss;
1522 
1523 	memcpy(&sin->sin_addr, &msg->data.StartMultiMediaTransmissionAck.v3.bel_ipAddr, sizeof(sin->sin_addr));
1524 	sin->sin_port = htons(htolel(msg->data.StartMultiMediaTransmissionAck.v3.lel_portNumber));
1525 }
1526 
sccp_protocol_parseStartMultiMediaTransmissionAckV17(constMessagePtr msg,uint32_t * partyID,uint32_t * callID,uint32_t * callID1,skinny_mediastatus_t * mediastatus,struct sockaddr_storage * ss)1527 static void sccp_protocol_parseStartMultiMediaTransmissionAckV17(constMessagePtr msg, uint32_t * partyID, uint32_t * callID, uint32_t * callID1, skinny_mediastatus_t * mediastatus, struct sockaddr_storage *ss)
1528 {
1529 	*partyID = letohl(msg->data.StartMultiMediaTransmissionAck.v17.lel_passThruPartyId);
1530 	*callID = letohl(msg->data.StartMultiMediaTransmissionAck.v17.lel_callReference);
1531 	*callID1 = letohl(msg->data.StartMultiMediaTransmissionAck.v17.lel_callReference1);
1532 	*mediastatus = letohl(msg->data.StartMultiMediaTransmissionAck.v17.lel_mediastatus);
1533 
1534 	if (letohl(msg->data.StartMultiMediaTransmissionAck.v17.lel_ipv46) == 0) {				// read ipv4 address
1535 		ss->ss_family = AF_INET;
1536 		struct sockaddr_in *sin = (struct sockaddr_in *) ss;
1537 
1538 		memcpy(&sin->sin_addr, &msg->data.StartMultiMediaTransmissionAck.v17.bel_ipAddr, sizeof(struct in_addr));
1539 		sin->sin_port = htons(htolel(msg->data.StartMultiMediaTransmissionAck.v17.lel_portNumber));
1540 	} else {												// read ipv6 address
1541 		/* what to do with IPv4-mapped IPv6 addresses */
1542 		ss->ss_family = AF_INET6;
1543 		struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) ss;
1544 
1545 		memcpy(&sin6->sin6_addr, &msg->data.StartMultiMediaTransmissionAck.v17.bel_ipAddr, sizeof(sin6->sin6_addr));
1546 		sin6->sin6_port = htons(htolel(msg->data.StartMultiMediaTransmissionAck.v17.lel_portNumber));
1547 	}
1548 }
1549 
1550 /*!
1551  * \brief EnblocCallMessage
1552  */
sccp_protocol_parseEnblocCallV3(constMessagePtr msg,char * calledParty,uint32_t * lineInstance)1553 static void sccp_protocol_parseEnblocCallV3(constMessagePtr msg, char *calledParty, uint32_t * lineInstance)
1554 {
1555 	sccp_copy_string(calledParty, msg->data.EnblocCallMessage.v3.calledParty, StationMaxDirnumSize);
1556 	*lineInstance = 0;											// v3 - v16 don't provicde lineInstance during enbloc dialing
1557 }
1558 
sccp_protocol_parseEnblocCallV17(constMessagePtr msg,char * calledParty,uint32_t * lineInstance)1559 static void sccp_protocol_parseEnblocCallV17(constMessagePtr msg, char *calledParty, uint32_t * lineInstance)
1560 {
1561 	sccp_copy_string(calledParty, msg->data.EnblocCallMessage.v17.calledParty, StationMaxDirnumSize);
1562 	*lineInstance = letohl(msg->data.EnblocCallMessage.v17.lel_lineInstance);
1563 }
1564 
sccp_protocol_parseEnblocCallV22(constMessagePtr msg,char * calledParty,uint32_t * lineInstance)1565 static void sccp_protocol_parseEnblocCallV22(constMessagePtr msg, char *calledParty, uint32_t * lineInstance)
1566 {
1567 	sccp_copy_string(calledParty, msg->data.EnblocCallMessage.v18u.calledParty, 25);
1568 
1569 	/* message exists in both packed and unpacked version */
1570 	/* 8945 v22 unpacked */
1571 	// 00000000 - 24 00 00 00 16 00 00 00  04 00 00 00 39 38 30 31  - $...........9801
1572 	// 00000010 - 31 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  - 1...............
1573 	// 00000020 - 00 00 00 00 00 00 00 00  01 00 00 00              - ............
1574 
1575 	/* 7970 v22 packed*/
1576 	// 00000000 - 24 00 00 00 16 00 00 00  04 00 00 00 39 38 30 31  - $...........9801
1577 	// 00000010 - 31 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  - 1...............
1578 	// 00000020 - 00 00 00 00 00 01 00 00  00 00 00 00              - ............
1579 
1580 	if (letohl(msg->data.EnblocCallMessage.v18u.lel_lineInstance) > 0) {
1581 		*lineInstance = letohl(msg->data.EnblocCallMessage.v18u.lel_lineInstance);
1582 	} else {
1583 #if defined(HAVE_UNALIGNED_BUSERROR)
1584 		*lineInstance = letohl(get_unaligned_uint32((const void *) &msg->data.EnblocCallMessage.v18p.lel_lineInstance));
1585 #else
1586 		*lineInstance = letohl(msg->data.EnblocCallMessage.v18p.lel_lineInstance);
1587 #endif
1588 	}
1589 }
1590 
1591 /* sendPortResponse */
sccp_protocol_parsePortResponseV3(constMessagePtr msg,uint32_t * conferenceId,uint32_t * callReference,uint32_t * passThruPartyId,struct sockaddr_storage * ss,uint32_t * RTCPPortNumber,skinny_mediaType_t * mediaType)1592 static void sccp_protocol_parsePortResponseV3(constMessagePtr msg, uint32_t *conferenceId, uint32_t *callReference, uint32_t *passThruPartyId, struct sockaddr_storage *ss, uint32_t * RTCPPortNumber, skinny_mediaType_t *mediaType)
1593 {
1594 	*conferenceId = letohl(msg->data.PortResponseMessage.v3.lel_conferenceId);
1595 	*callReference = letohl(msg->data.PortResponseMessage.v3.lel_callReference);
1596 	*passThruPartyId = letohl(msg->data.PortResponseMessage.v3.lel_passThruPartyId);
1597 
1598 	ss->ss_family = AF_INET;
1599 	struct sockaddr_in *sin = (struct sockaddr_in *) ss;
1600 	memcpy(&sin->sin_addr, &msg->data.PortResponseMessage.v3.bel_ipAddr, sizeof(sin->sin_addr));
1601 	sin->sin_port = htons(htolel(msg->data.PortResponseMessage.v3.lel_portNumber));
1602 
1603 	*RTCPPortNumber = letohl(msg->data.PortResponseMessage.v3.lel_RTCPPortNumber);
1604 	*mediaType = SKINNY_MEDIATYPE_SENTINEL;
1605 }
1606 
sccp_protocol_parsePortResponseV19(constMessagePtr msg,uint32_t * conferenceId,uint32_t * callReference,uint32_t * passThruPartyId,struct sockaddr_storage * ss,uint32_t * RTCPPortNumber,skinny_mediaType_t * mediaType)1607 static void sccp_protocol_parsePortResponseV19(constMessagePtr msg, uint32_t *conferenceId, uint32_t *callReference, uint32_t *passThruPartyId, struct sockaddr_storage *ss, uint32_t * RTCPPortNumber, skinny_mediaType_t *mediaType)
1608 {
1609 	*conferenceId = letohl(msg->data.PortResponseMessage.v19.lel_conferenceId);
1610 	*callReference = letohl(msg->data.PortResponseMessage.v19.lel_callReference);
1611 	*passThruPartyId = letohl(msg->data.PortResponseMessage.v19.lel_passThruPartyId);
1612 
1613 	if (letohl(msg->data.PortResponseMessage.v19.lel_ipv46) == 0) {			// read ipv4 address
1614 		ss->ss_family = AF_INET;
1615 		struct sockaddr_in *sin = (struct sockaddr_in *) ss;
1616 
1617 		memcpy(&sin->sin_addr, &msg->data.PortResponseMessage.v19.bel_ipAddr, sizeof(sin->sin_addr));
1618 		sin->sin_port = htons(htolel(msg->data.PortResponseMessage.v19.lel_portNumber));
1619 	} else {												// read ipv6 address
1620 		ss->ss_family = AF_INET6;
1621 		struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) ss;
1622 
1623 		memcpy(&sin6->sin6_addr, &msg->data.PortResponseMessage.v19.bel_ipAddr, sizeof(sin6->sin6_addr));
1624 		sin6->sin6_port = htons(htolel(msg->data.PortResponseMessage.v19.lel_portNumber));
1625 	}
1626 	*RTCPPortNumber = letohl(msg->data.PortResponseMessage.v19.lel_RTCPPortNumber);
1627 	*mediaType = letohl(msg->data.PortResponseMessage.v19.lel_mediaType);
1628 }
1629 /* done - sendPortResponse */
1630 
1631 /* =================================================================================================================== Map Messages to Protocol Version */
1632 
1633 /*!
1634  * \brief SCCP Protocol Version to Message Mapping
1635  */
1636 static const sccp_deviceProtocol_t *sccpProtocolDefinition[] = {
1637 	NULL,
1638 	NULL,
1639 	NULL,
1640 	&(sccp_deviceProtocol_t) {SCCP_PROTOCOL, 3, TimeDateReqMessage, sccp_protocol_sendCallInfoV3, sccp_protocol_sendDialedNumberV3, sccp_protocol_sendRegisterAckV3, sccp_protocol_sendStaticDisplayprompt, sccp_protocol_sendStaticDisplayNotify, sccp_protocol_sendStaticDisplayPriNotify, sccp_protocol_sendCallForwardStatus, sccp_protocol_sendUserToDeviceDataVersion1Message, sccp_protocol_sendMultiMediaCommand, sccp_protocol_sendOpenReceiveChannelV3, sccp_protocol_sendOpenMultiMediaChannelV3,
1641 				  sccp_protocol_sendStartMultiMediaTransmissionV3, sccp_protocol_sendStartMediaTransmissionV3, sccp_protocol_sendConnectionStatisticsReqV3, sccp_protocol_sendPortRequest,sccp_protocol_sendPortClose, sccp_protocol_sendLineStatRespV3,
1642 				  sccp_protocol_parseOpenReceiveChannelAckV3, sccp_protocol_parseOpenMultiMediaReceiveChannelAckV3, sccp_protocol_parseStartMediaTransmissionAckV3, sccp_protocol_parseStartMultiMediaTransmissionAckV3, sccp_protocol_parseEnblocCallV3, sccp_protocol_parsePortResponseV3},	/* default impl */
1643 	NULL,
1644 	&(sccp_deviceProtocol_t) {SCCP_PROTOCOL, 5, TimeDateReqMessage, sccp_protocol_sendCallInfoV3, sccp_protocol_sendDialedNumberV3, sccp_protocol_sendRegisterAckV4, sccp_protocol_sendStaticDisplayprompt, sccp_protocol_sendStaticDisplayNotify, sccp_protocol_sendStaticDisplayPriNotify, sccp_protocol_sendCallForwardStatus, sccp_protocol_sendUserToDeviceDataVersion1Message, sccp_protocol_sendMultiMediaCommand, sccp_protocol_sendOpenReceiveChannelV3, sccp_protocol_sendOpenMultiMediaChannelV3,
1645 				  sccp_protocol_sendStartMultiMediaTransmissionV3, sccp_protocol_sendStartMediaTransmissionV3, sccp_protocol_sendConnectionStatisticsReqV3, sccp_protocol_sendPortRequest,sccp_protocol_sendPortClose, sccp_protocol_sendLineStatRespV3,
1646 				  sccp_protocol_parseOpenReceiveChannelAckV3, sccp_protocol_parseOpenMultiMediaReceiveChannelAckV3, sccp_protocol_parseStartMediaTransmissionAckV3, sccp_protocol_parseStartMultiMediaTransmissionAckV3, sccp_protocol_parseEnblocCallV3, sccp_protocol_parsePortResponseV3},
1647 	NULL,
1648 	NULL,
1649 	&(sccp_deviceProtocol_t) {SCCP_PROTOCOL, 8, TimeDateReqMessage, sccp_protocol_sendCallInfoV7, sccp_protocol_sendDialedNumberV3, sccp_protocol_sendRegisterAckV4, sccp_protocol_sendDynamicDisplayprompt, sccp_protocol_sendDynamicDisplayNotify, sccp_protocol_sendDynamicDisplayPriNotify, sccp_protocol_sendCallForwardStatus, sccp_protocol_sendUserToDeviceDataVersion1Message, sccp_protocol_sendMultiMediaCommand, sccp_protocol_sendOpenReceiveChannelV3, sccp_protocol_sendOpenMultiMediaChannelV3,
1650 				  sccp_protocol_sendStartMultiMediaTransmissionV3, sccp_protocol_sendStartMediaTransmissionV3, sccp_protocol_sendConnectionStatisticsReqV3, sccp_protocol_sendPortRequest,sccp_protocol_sendPortClose, sccp_protocol_sendLineStatRespV3,
1651 				  sccp_protocol_parseOpenReceiveChannelAckV3, sccp_protocol_parseOpenMultiMediaReceiveChannelAckV3, sccp_protocol_parseStartMediaTransmissionAckV3, sccp_protocol_parseStartMultiMediaTransmissionAckV3, sccp_protocol_parseEnblocCallV3, sccp_protocol_parsePortResponseV3},
1652 	&(sccp_deviceProtocol_t) {SCCP_PROTOCOL, 9, TimeDateReqMessage, sccp_protocol_sendCallInfoV7, sccp_protocol_sendDialedNumberV3, sccp_protocol_sendRegisterAckV4, sccp_protocol_sendDynamicDisplayprompt, sccp_protocol_sendDynamicDisplayNotify, sccp_protocol_sendDynamicDisplayPriNotify, sccp_protocol_sendCallForwardStatus, sccp_protocol_sendUserToDeviceDataVersion1Message, sccp_protocol_sendMultiMediaCommand, sccp_protocol_sendOpenReceiveChannelV3, sccp_protocol_sendOpenMultiMediaChannelV3,
1653 				  sccp_protocol_sendStartMultiMediaTransmissionV3, sccp_protocol_sendStartMediaTransmissionV3, sccp_protocol_sendConnectionStatisticsReqV3, sccp_protocol_sendPortRequest,sccp_protocol_sendPortClose, sccp_protocol_sendLineStatRespV3,
1654 				  sccp_protocol_parseOpenReceiveChannelAckV3, sccp_protocol_parseOpenMultiMediaReceiveChannelAckV3, sccp_protocol_parseStartMediaTransmissionAckV3, sccp_protocol_parseStartMultiMediaTransmissionAckV3, sccp_protocol_parseEnblocCallV3, sccp_protocol_parsePortResponseV3},
1655 	&(sccp_deviceProtocol_t) {SCCP_PROTOCOL, 10, TimeDateReqMessage, sccp_protocol_sendCallInfoV7, sccp_protocol_sendDialedNumberV3, sccp_protocol_sendRegisterAckV4, sccp_protocol_sendDynamicDisplayprompt, sccp_protocol_sendDynamicDisplayNotify, sccp_protocol_sendDynamicDisplayPriNotify, sccp_protocol_sendCallForwardStatus, sccp_protocol_sendUserToDeviceDataVersion1Message, sccp_protocol_sendMultiMediaCommand, sccp_protocol_sendOpenReceiveChannelV3, sccp_protocol_sendOpenMultiMediaChannelV3,
1656 				  sccp_protocol_sendStartMultiMediaTransmissionV3, sccp_protocol_sendStartMediaTransmissionV3, sccp_protocol_sendConnectionStatisticsReqV3, sccp_protocol_sendPortRequest,sccp_protocol_sendPortClose, sccp_protocol_sendLineStatRespV3,
1657 				  sccp_protocol_parseOpenReceiveChannelAckV3, sccp_protocol_parseOpenMultiMediaReceiveChannelAckV3, sccp_protocol_parseStartMediaTransmissionAckV3, sccp_protocol_parseStartMultiMediaTransmissionAckV3, sccp_protocol_parseEnblocCallV3, sccp_protocol_parsePortResponseV3},
1658 	&(sccp_deviceProtocol_t) {SCCP_PROTOCOL, 11, TimeDateReqMessage, sccp_protocol_sendCallInfoV7, sccp_protocol_sendDialedNumberV3, sccp_protocol_sendRegisterAckV11, sccp_protocol_sendDynamicDisplayprompt, sccp_protocol_sendDynamicDisplayNotify, sccp_protocol_sendDynamicDisplayPriNotify, sccp_protocol_sendCallForwardStatus, sccp_protocol_sendUserToDeviceDataVersion1Message, sccp_protocol_sendMultiMediaCommand, sccp_protocol_sendOpenReceiveChannelV3, sccp_protocol_sendOpenMultiMediaChannelV3,
1659 				  sccp_protocol_sendStartMultiMediaTransmissionV3, sccp_protocol_sendStartMediaTransmissionV3, sccp_protocol_sendConnectionStatisticsReqV3, sccp_protocol_sendPortRequest,sccp_protocol_sendPortClose, sccp_protocol_sendLineStatRespV3,
1660 				  sccp_protocol_parseOpenReceiveChannelAckV3, sccp_protocol_parseOpenMultiMediaReceiveChannelAckV3, sccp_protocol_parseStartMediaTransmissionAckV3, sccp_protocol_parseStartMultiMediaTransmissionAckV3, sccp_protocol_parseEnblocCallV3, sccp_protocol_parsePortResponseV3},
1661 	NULL,
1662 	NULL,
1663 	NULL,
1664 	&(sccp_deviceProtocol_t) {SCCP_PROTOCOL, 15, TimeDateReqMessage, sccp_protocol_sendCallInfoV7, sccp_protocol_sendDialedNumberV3, sccp_protocol_sendRegisterAckV11, sccp_protocol_sendDynamicDisplayprompt, sccp_protocol_sendDynamicDisplayNotify, sccp_protocol_sendDynamicDisplayPriNotify, sccp_protocol_sendCallForwardStatus, sccp_protocol_sendUserToDeviceDataVersion1Message, sccp_protocol_sendMultiMediaCommand, sccp_protocol_sendOpenReceiveChannelV3, sccp_protocol_sendOpenMultiMediaChannelV12,
1665 				  sccp_protocol_sendStartMultiMediaTransmissionV17, sccp_protocol_sendStartMediaTransmissionV3, sccp_protocol_sendConnectionStatisticsReqV3, sccp_protocol_sendPortRequest,sccp_protocol_sendPortClose, sccp_protocol_sendLineStatRespV3,
1666 				  sccp_protocol_parseOpenReceiveChannelAckV3, sccp_protocol_parseOpenMultiMediaReceiveChannelAckV3, sccp_protocol_parseStartMediaTransmissionAckV3, sccp_protocol_parseStartMultiMediaTransmissionAckV3, sccp_protocol_parseEnblocCallV3, sccp_protocol_parsePortResponseV3},
1667 	&(sccp_deviceProtocol_t) {SCCP_PROTOCOL, 16, TimeDateReqMessage, sccp_protocol_sendCallInfoV16, sccp_protocol_sendDialedNumberV3, sccp_protocol_sendRegisterAckV11, sccp_protocol_sendDynamicDisplayprompt, sccp_protocol_sendDynamicDisplayNotify, sccp_protocol_sendDynamicDisplayPriNotify, sccp_protocol_sendCallForwardStatus, sccp_protocol_sendUserToDeviceDataVersion1Message, sccp_protocol_sendMultiMediaCommand, sccp_protocol_sendOpenReceiveChannelV3, sccp_protocol_sendOpenMultiMediaChannelV12,
1668 				  sccp_protocol_sendStartMultiMediaTransmissionV17, sccp_protocol_sendStartMediaTransmissionV3, sccp_protocol_sendConnectionStatisticsReqV3, sccp_protocol_sendPortRequest,sccp_protocol_sendPortClose, sccp_protocol_sendLineStatRespV3,
1669 				  sccp_protocol_parseOpenReceiveChannelAckV3, sccp_protocol_parseOpenMultiMediaReceiveChannelAckV3, sccp_protocol_parseStartMediaTransmissionAckV3, sccp_protocol_parseStartMultiMediaTransmissionAckV3, sccp_protocol_parseEnblocCallV3, sccp_protocol_parsePortResponseV3},
1670 	&(sccp_deviceProtocol_t) {SCCP_PROTOCOL, 17, TimeDateReqMessage, sccp_protocol_sendCallInfoV16, sccp_protocol_sendDialedNumberV3, sccp_protocol_sendRegisterAckV11, sccp_protocol_sendDynamicDisplayprompt, sccp_protocol_sendDynamicDisplayNotify, sccp_protocol_sendDynamicDisplayPriNotify, sccp_protocol_sendCallForwardStatus, sccp_protocol_sendUserToDeviceDataVersion1Message, sccp_protocol_sendMultiMediaCommand, sccp_protocol_sendOpenReceiveChannelV17, sccp_protocol_sendOpenMultiMediaChannelV17,
1671 				  sccp_protocol_sendStartMultiMediaTransmissionV17, sccp_protocol_sendStartMediaTransmissionV17, sccp_protocol_sendConnectionStatisticsReqV3, sccp_protocol_sendPortRequest,sccp_protocol_sendPortClose, sccp_protocol_sendLineStatRespV17,
1672 				  sccp_protocol_parseOpenReceiveChannelAckV17, sccp_protocol_parseOpenMultiMediaReceiveChannelAckV17, sccp_protocol_parseStartMediaTransmissionAckV17, sccp_protocol_parseStartMultiMediaTransmissionAckV17, sccp_protocol_parseEnblocCallV17, sccp_protocol_parsePortResponseV3},
1673 	&(sccp_deviceProtocol_t) {SCCP_PROTOCOL, 18, TimeDateReqMessage, sccp_protocol_sendCallInfoV16, sccp_protocol_sendDialedNumberV18, sccp_protocol_sendRegisterAckV11, sccp_protocol_sendDynamicDisplayprompt, sccp_protocol_sendDynamicDisplayNotify, sccp_protocol_sendDynamicDisplayPriNotify, sccp_protocol_sendCallForwardStatusV18, sccp_protocol_sendUserToDeviceDataVersion1Message, sccp_protocol_sendMultiMediaCommand, sccp_protocol_sendOpenReceiveChannelV17, sccp_protocol_sendOpenMultiMediaChannelV17,
1674 				  sccp_protocol_sendStartMultiMediaTransmissionV17, sccp_protocol_sendStartMediaTransmissionV17, sccp_protocol_sendConnectionStatisticsReqV3, sccp_protocol_sendPortRequest,sccp_protocol_sendPortClose, sccp_protocol_sendLineStatRespV17,
1675 				  sccp_protocol_parseOpenReceiveChannelAckV17, sccp_protocol_parseOpenMultiMediaReceiveChannelAckV17, sccp_protocol_parseStartMediaTransmissionAckV17, sccp_protocol_parseStartMultiMediaTransmissionAckV17, sccp_protocol_parseEnblocCallV17, sccp_protocol_parsePortResponseV3},
1676 	&(sccp_deviceProtocol_t) {SCCP_PROTOCOL, 19, TimeDateReqMessage, sccp_protocol_sendCallInfoV16, sccp_protocol_sendDialedNumberV18, sccp_protocol_sendRegisterAckV11, sccp_protocol_sendDynamicDisplayprompt, sccp_protocol_sendDynamicDisplayNotify, sccp_protocol_sendDynamicDisplayPriNotify, sccp_protocol_sendCallForwardStatusV18, sccp_protocol_sendUserToDeviceDataVersion1Message, sccp_protocol_sendMultiMediaCommand, sccp_protocol_sendOpenReceiveChannelV17,
1677 				  sccp_protocol_sendOpenMultiMediaChannelV17,
1678 				  sccp_protocol_sendStartMultiMediaTransmissionV17, sccp_protocol_sendStartMediaTransmissionV17, sccp_protocol_sendConnectionStatisticsReqV19, sccp_protocol_sendPortRequest,sccp_protocol_sendPortClose, sccp_protocol_sendLineStatRespV17,
1679 				  sccp_protocol_parseOpenReceiveChannelAckV17, sccp_protocol_parseOpenMultiMediaReceiveChannelAckV17, sccp_protocol_parseStartMediaTransmissionAckV17, sccp_protocol_parseStartMultiMediaTransmissionAckV17, sccp_protocol_parseEnblocCallV17, sccp_protocol_parsePortResponseV19},
1680 	&(sccp_deviceProtocol_t) {SCCP_PROTOCOL, 20, TimeDateReqMessage, sccp_protocol_sendCallInfoV16, sccp_protocol_sendDialedNumberV18, sccp_protocol_sendRegisterAckV11, sccp_protocol_sendDynamicDisplayprompt, sccp_protocol_sendDynamicDisplayNotify, sccp_protocol_sendDynamicDisplayPriNotify, sccp_protocol_sendCallForwardStatusV18, sccp_protocol_sendUserToDeviceDataVersion1Message, sccp_protocol_sendMultiMediaCommand, sccp_protocol_sendOpenReceiveChannelV17,
1681 				  sccp_protocol_sendOpenMultiMediaChannelV17,
1682 				  sccp_protocol_sendStartMultiMediaTransmissionV17, sccp_protocol_sendStartMediaTransmissionV17, sccp_protocol_sendConnectionStatisticsReqV19, sccp_protocol_sendPortRequest,sccp_protocol_sendPortClose, sccp_protocol_sendLineStatRespV17,
1683 				  sccp_protocol_parseOpenReceiveChannelAckV17, sccp_protocol_parseOpenMultiMediaReceiveChannelAckV17, sccp_protocol_parseStartMediaTransmissionAckV17, sccp_protocol_parseStartMultiMediaTransmissionAckV17, sccp_protocol_parseEnblocCallV17, sccp_protocol_parsePortResponseV19},
1684 	&(sccp_deviceProtocol_t) {SCCP_PROTOCOL, 21, TimeDateReqMessage, sccp_protocol_sendCallInfoV16, sccp_protocol_sendDialedNumberV18, sccp_protocol_sendRegisterAckV11, sccp_protocol_sendDynamicDisplayprompt, sccp_protocol_sendDynamicDisplayNotify, sccp_protocol_sendDynamicDisplayPriNotify, sccp_protocol_sendCallForwardStatusV18, sccp_protocol_sendUserToDeviceDataVersion1Message, sccp_protocol_sendMultiMediaCommand, sccp_protocol_sendOpenReceiveChannelV17,
1685 				  sccp_protocol_sendOpenMultiMediaChannelV17,
1686 				  sccp_protocol_sendStartMultiMediaTransmissionV17, sccp_protocol_sendStartMediaTransmissionV17, sccp_protocol_sendConnectionStatisticsReqV19, sccp_protocol_sendPortRequest,sccp_protocol_sendPortClose, sccp_protocol_sendLineStatRespV17,
1687 				  sccp_protocol_parseOpenReceiveChannelAckV17, sccp_protocol_parseOpenMultiMediaReceiveChannelAckV17, sccp_protocol_parseStartMediaTransmissionAckV17, sccp_protocol_parseStartMultiMediaTransmissionAckV17, sccp_protocol_parseEnblocCallV17, sccp_protocol_parsePortResponseV19},
1688 	&(sccp_deviceProtocol_t) {SCCP_PROTOCOL, 22, TimeDateReqMessage, sccp_protocol_sendCallInfoV16,sccp_protocol_sendDialedNumberV18,sccp_protocol_sendRegisterAckV11,sccp_protocol_sendDynamicDisplayprompt,sccp_protocol_sendDynamicDisplayNotify,sccp_protocol_sendDynamicDisplayPriNotify,sccp_protocol_sendCallForwardStatusV18,sccp_protocol_sendUserToDeviceDataVersion1Message,sccp_protocol_sendMultiMediaCommand,sccp_protocol_sendOpenReceiveChannelv22,
1689 				  sccp_protocol_sendOpenMultiMediaChannelV17,
1690 				  sccp_protocol_sendStartMultiMediaTransmissionV17,sccp_protocol_sendStartMediaTransmissionv22,sccp_protocol_sendConnectionStatisticsReqV19, sccp_protocol_sendPortRequest,sccp_protocol_sendPortClose, sccp_protocol_sendLineStatRespV17,
1691 				  sccp_protocol_parseOpenReceiveChannelAckV17,sccp_protocol_parseOpenMultiMediaReceiveChannelAckV17,sccp_protocol_parseStartMediaTransmissionAckV17,sccp_protocol_parseStartMultiMediaTransmissionAckV17,sccp_protocol_parseEnblocCallV22, sccp_protocol_parsePortResponseV19},
1692 };
1693 
1694 /*!
1695  * \brief SPCP Protocol Version to Message Mapping
1696  */
1697 static const sccp_deviceProtocol_t *spcpProtocolDefinition[] = {
1698 	&(sccp_deviceProtocol_t) {SPCP_PROTOCOL, 0, RegisterAvailableLinesMessage, sccp_protocol_sendCallInfoV3, sccp_protocol_sendDialedNumberV3, sccp_protocol_sendRegisterAckV4, sccp_protocol_sendDynamicDisplayprompt, sccp_protocol_sendDynamicDisplayNotify, sccp_protocol_sendDynamicDisplayPriNotify, sccp_protocol_sendCallForwardStatus, sccp_protocol_sendUserToDeviceDataVersion1Message, sccp_protocol_sendMultiMediaCommand, sccp_protocol_sendOpenReceiveChannelV3,
1699 				  sccp_protocol_sendOpenMultiMediaChannelV3,
1700 				  sccp_protocol_sendStartMultiMediaTransmissionV3, sccp_protocol_sendStartMediaTransmissionV3, sccp_protocol_sendConnectionStatisticsReqV3, sccp_protocol_sendPortRequest,sccp_protocol_sendPortClose, sccp_protocol_sendLineStatRespV3,
1701 				  sccp_protocol_parseOpenReceiveChannelAckV3, sccp_protocol_parseOpenMultiMediaReceiveChannelAckV3, sccp_protocol_parseStartMediaTransmissionAckV3, sccp_protocol_parseStartMultiMediaTransmissionAckV3, sccp_protocol_parseEnblocCallV3, sccp_protocol_parsePortResponseV3},
1702 	NULL,
1703 	NULL,
1704 	NULL,
1705 	NULL,
1706 	NULL,
1707 	NULL,
1708 	NULL,
1709 	&(sccp_deviceProtocol_t) {SPCP_PROTOCOL, 8, RegisterAvailableLinesMessage, sccp_protocol_sendCallInfoV3, sccp_protocol_sendDialedNumberV3, sccp_protocol_sendRegisterAckV4, sccp_protocol_sendDynamicDisplayprompt, sccp_protocol_sendDynamicDisplayNotify, sccp_protocol_sendDynamicDisplayPriNotify, sccp_protocol_sendCallForwardStatus, sccp_protocol_sendUserToDeviceDataVersion1Message, sccp_protocol_sendMultiMediaCommand, sccp_protocol_sendOpenReceiveChannelV3,
1710 				  sccp_protocol_sendOpenMultiMediaChannelV3,
1711 				  sccp_protocol_sendStartMultiMediaTransmissionV3, sccp_protocol_sendStartMediaTransmissionV3, sccp_protocol_sendConnectionStatisticsReqV19, sccp_protocol_sendPortRequest,sccp_protocol_sendPortClose, sccp_protocol_sendLineStatRespV3,
1712 				  sccp_protocol_parseOpenReceiveChannelAckV3, sccp_protocol_parseOpenMultiMediaReceiveChannelAckV3, sccp_protocol_parseStartMediaTransmissionAckV3, sccp_protocol_parseStartMultiMediaTransmissionAckV3, sccp_protocol_parseEnblocCallV17, sccp_protocol_parsePortResponseV19},
1713 };
1714 
1715 /*!
1716  * \brief Get Maximum Supported Version Number by Protocol Type
1717  */
sccp_protocol_getMaxSupportedVersionNumber(int type)1718 uint8_t __CONST__ sccp_protocol_getMaxSupportedVersionNumber(int type)
1719 {
1720 	switch (type) {
1721 		case SCCP_PROTOCOL:
1722 			return ARRAY_LEN(sccpProtocolDefinition) - 1;
1723 		case SPCP_PROTOCOL:
1724 			return ARRAY_LEN(spcpProtocolDefinition) - 1;
1725 		default:
1726 			return 0;
1727 	}
1728 }
1729 
sccp_protocol_isProtocolSupported(uint8_t type,uint8_t version)1730 gcc_inline boolean_t sccp_protocol_isProtocolSupported(uint8_t type, uint8_t version)
1731 {
1732 	const sccp_deviceProtocol_t **protocolDef = NULL;
1733 	size_t protocolArraySize = 0 ;
1734 
1735 	switch (type) {
1736 		case SCCP_PROTOCOL:
1737 			protocolArraySize = ARRAY_LEN(sccpProtocolDefinition);
1738 			protocolDef = sccpProtocolDefinition;
1739 			break;
1740 		case SPCP_PROTOCOL:
1741 			protocolArraySize = ARRAY_LEN(spcpProtocolDefinition);
1742 			protocolDef = spcpProtocolDefinition;
1743 			break;
1744 		default:
1745 			pbx_log(LOG_WARNING, "SCCP: Unknown Protocol\n");
1746 	}
1747 
1748 	return (version < protocolArraySize && protocolDef[version] != NULL) ? TRUE : FALSE;
1749 }
1750 
1751 /*!
1752  * \brief Get Maximum Possible Protocol Supported by Device
1753  */
sccp_protocol_getDeviceProtocol(constDevicePtr device,int type)1754 const sccp_deviceProtocol_t *sccp_protocol_getDeviceProtocol(constDevicePtr device, int type)
1755 {
1756 	uint8_t version = device->protocolversion;
1757 	const sccp_deviceProtocol_t ** protocolDef = NULL;
1758 	size_t protocolArraySize = 0;
1759 	uint8_t returnProtocol = 0;
1760 
1761 	sccp_log(DEBUGCAT_DEVICE) (VERBOSE_PREFIX_3 "SCCP: searching for our capability for device protocol version %d\n", version);
1762 
1763 	if (type == SCCP_PROTOCOL) {
1764 		protocolArraySize = ARRAY_LEN(sccpProtocolDefinition);
1765 		protocolDef = sccpProtocolDefinition;
1766 		returnProtocol = 3;										// setting minimally returned protocol
1767 		sccp_log(DEBUGCAT_DEVICE) (VERBOSE_PREFIX_3 "SCCP: searching for our capability for device protocol SCCP\n");
1768 	} else {
1769 		protocolArraySize = ARRAY_LEN(spcpProtocolDefinition);
1770 		protocolDef = spcpProtocolDefinition;
1771 		returnProtocol = 0;
1772 		sccp_log(DEBUGCAT_DEVICE) (VERBOSE_PREFIX_3 "SCCP: searching for our capability for device protocol SPCP\n");
1773 	}
1774 
1775 	for(uint8_t i = (protocolArraySize - 1); i > 0; i--) {
1776 		if (protocolDef[i] != NULL && version >= protocolDef[i]->version) {
1777 			sccp_log(DEBUGCAT_DEVICE) (VERBOSE_PREFIX_3 "%s: found protocol version '%d' at %d\n", protocolDef[i]->type == SCCP_PROTOCOL ? "SCCP" : "SPCP", protocolDef[i]->version, i);
1778 			returnProtocol = i;
1779 			break;
1780 		}
1781 	}
1782 
1783 	return protocolDef[returnProtocol];
1784 }
1785 
skinny_keymode2longstr(skinny_keymode_t keymode)1786 const char * const __CONST__ skinny_keymode2longstr(skinny_keymode_t keymode)
1787 {
1788 	switch (keymode) {
1789 		case KEYMODE_ONHOOK:
1790 			return "On Hook";
1791 		case KEYMODE_CONNECTED:
1792 			return "Connected";
1793 		case KEYMODE_ONHOLD:
1794 			return "On Hold";
1795 		case KEYMODE_RINGIN:
1796 			return "Incoming Call Ringing";
1797 		case KEYMODE_OFFHOOK:
1798 			return "Off Hook";
1799 		case KEYMODE_CONNTRANS:
1800 			return "Connect with Transferable Call";
1801 		case KEYMODE_DIGITSFOLL:
1802 			return "More Digits Following";
1803 		case KEYMODE_CONNCONF:
1804 			return "Connected to Conference";
1805 		case KEYMODE_RINGOUT:
1806 			return "Outgoing Call Ringing";
1807 		case KEYMODE_OFFHOOKFEAT:
1808 			return "Off Hook with Features";
1809 		case KEYMODE_INUSEHINT:
1810 			return "Hint is in use";
1811 		case KEYMODE_ONHOOKSTEALABLE:
1812 			return "On Hook with Stealable Call Present";
1813 		case KEYMODE_HOLDCONF:
1814 			return "Have a Conference On Hold";
1815 		default:
1816 			return "Unknown KeyMode";
1817 	}
1818 }
1819 
1820 const struct messageinfo sccp_messageinfo[] = {
1821 	/* clang-format off */
1822 	/* DEV -> PBX */
1823 	[KeepAliveMessage] = { KeepAliveMessage, "Keep Alive Message", offsize(sccp_data_t, StationKeepAliveMessage), SKINNY_MSGTYPE_REQUEST, SKINNY_MSGDIRECTION_DEV2PBX },
1824 	[RegisterMessage] = { RegisterMessage, "Register Message", offsize(sccp_data_t, RegisterMessage), SKINNY_MSGTYPE_REQUEST, SKINNY_MSGDIRECTION_DEV2PBX },
1825 	[IpPortMessage] = { IpPortMessage, "Ip-Port Message", offsize(sccp_data_t, IpPortMessage), SKINNY_MSGTYPE_EVENT, SKINNY_MSGDIRECTION_DEV2PBX },
1826 	[KeypadButtonMessage] = { KeypadButtonMessage, "Keypad Button Message", offsize(sccp_data_t, KeypadButtonMessage), SKINNY_MSGTYPE_EVENT, SKINNY_MSGDIRECTION_DEV2PBX },
1827 	/**/[EnblocCallMessage] = { EnblocCallMessage, "Enbloc Call Message", offsize(sccp_data_t, EnblocCallMessage), SKINNY_MSGTYPE_EVENT, SKINNY_MSGDIRECTION_PBX2DEV },
1828 	[StimulusMessage] = { StimulusMessage, "Stimulus Message", offsize(sccp_data_t, StimulusMessage), SKINNY_MSGTYPE_EVENT, SKINNY_MSGDIRECTION_DEV2PBX },
1829 	[OffHookMessage] = { OffHookMessage, "Off-Hook Message", offsize(sccp_data_t, OffHookMessage), SKINNY_MSGTYPE_EVENT, SKINNY_MSGDIRECTION_DEV2PBX },
1830 	[OnHookMessage] = { OnHookMessage, "On-Hook Message", offsize(sccp_data_t, OnHookMessage), SKINNY_MSGTYPE_EVENT, SKINNY_MSGDIRECTION_DEV2PBX },
1831 	[HookFlashMessage] = { HookFlashMessage, "Hook-Flash Message", offsize(sccp_data_t, HookFlashMessage), SKINNY_MSGTYPE_EVENT, SKINNY_MSGDIRECTION_DEV2PBX },
1832 	[ForwardStatReqMessage] = { ForwardStatReqMessage, "Forward State Request", offsize(sccp_data_t, ForwardStatReqMessage), SKINNY_MSGTYPE_REQUEST, SKINNY_MSGDIRECTION_DEV2PBX },
1833 	[SpeedDialStatReqMessage] = { SpeedDialStatReqMessage, "Speed-Dial State Request", offsize(sccp_data_t, SpeedDialStatReqMessage), SKINNY_MSGTYPE_REQUEST, SKINNY_MSGDIRECTION_DEV2PBX },
1834 	[LineStatReqMessage] = { LineStatReqMessage, "Line State Request", offsize(sccp_data_t, LineStatReqMessage), SKINNY_MSGTYPE_REQUEST, SKINNY_MSGDIRECTION_DEV2PBX },
1835 	[ConfigStatReqMessage] = { ConfigStatReqMessage, "Config State Request", offsize(sccp_data_t, ConfigStatReqMessage), SKINNY_MSGTYPE_REQUEST, SKINNY_MSGDIRECTION_DEV2PBX },
1836 	/**/[TimeDateReqMessage] = { TimeDateReqMessage, "Time Date Request", offsize(sccp_data_t, TimeDateReqMessage), SKINNY_MSGTYPE_EVENT, SKINNY_MSGDIRECTION_DEV2PBX },
1837 	[ButtonTemplateReqMessage] = { ButtonTemplateReqMessage, "Button Template Request", offsize(sccp_data_t, ButtonTemplateReqMessage), SKINNY_MSGTYPE_REQUEST, SKINNY_MSGDIRECTION_DEV2PBX },
1838 	[VersionReqMessage] = { VersionReqMessage, "Version Request", offsize(sccp_data_t, VersionReqMessage), SKINNY_MSGTYPE_REQUEST, SKINNY_MSGDIRECTION_DEV2PBX },
1839 	[CapabilitiesResMessage] = { CapabilitiesResMessage, "Capabilities Response Message", offsize(sccp_data_t, CapabilitiesResMessage), SKINNY_MSGTYPE_RESPONSE, SKINNY_MSGDIRECTION_DEV2PBX },
1840 	[MediaPortListMessage] = { MediaPortListMessage, "Media Port List Message", offsize(sccp_data_t, MediaPortListMessage), SKINNY_MSGTYPE_EVENT, SKINNY_MSGDIRECTION_DEV2PBX },
1841 	[ServerReqMessage] = { ServerReqMessage, "Server Request", offsize(sccp_data_t, ServerReqMessage), SKINNY_MSGTYPE_REQUEST, SKINNY_MSGDIRECTION_DEV2PBX },
1842 	[AlarmMessage] = { AlarmMessage, "Alarm Message", offsize(sccp_data_t, AlarmMessage), SKINNY_MSGTYPE_EVENT, SKINNY_MSGDIRECTION_DEV2PBX },
1843 	[MulticastMediaReceptionAck] = { MulticastMediaReceptionAck, "Multicast Media Reception Acknowledge", offsize(sccp_data_t, MulticastMediaReceptionAck), SKINNY_MSGTYPE_RESPONSE, SKINNY_MSGDIRECTION_DEV2PBX },
1844 	[OpenReceiveChannelAck] = { OpenReceiveChannelAck, "Open Receive Channel Acknowledge", offsize(sccp_data_t, OpenReceiveChannelAck), SKINNY_MSGTYPE_RESPONSE, SKINNY_MSGDIRECTION_DEV2PBX },
1845 	/*[ConnectionStatisticsRes] = { ConnectionStatisticsRes, "Connection Statistics Response", offsize(sccp_data_t, ConnectionStatisticsRes), SKINNY_MSGTYPE_RESPONSE, SKINNY_MSGDIRECTION_DEV2PBX },*/
1846 	[ConnectionStatisticsRes] = { ConnectionStatisticsRes, "Connection Statistics Response", offsize(sccp_data_t, ConnectionStatisticsRes), SKINNY_MSGTYPE_EVENT, SKINNY_MSGDIRECTION_DEV2PBX },
1847 	[OffHookMessageWithCallingPartyMessage] = { OffHookMessageWithCallingPartyMessage, "Off-Hook With Cgpn Message", offsize(sccp_data_t, OffHookMessageWithCallingPartyMessage), SKINNY_MSGTYPE_EVENT,
1848 						    SKINNY_MSGDIRECTION_DEV2PBX },
1849 	[SoftKeySetReqMessage] = { SoftKeySetReqMessage, "SoftKey Set Request", offsize(sccp_data_t, SoftKeySetReqMessage), SKINNY_MSGTYPE_REQUEST, SKINNY_MSGDIRECTION_DEV2PBX },
1850 	[SoftKeyEventMessage] = { SoftKeyEventMessage, "SoftKey Event Message", offsize(sccp_data_t, SoftKeyEventMessage), SKINNY_MSGTYPE_EVENT, SKINNY_MSGDIRECTION_DEV2PBX },
1851 	[UnregisterMessage] = { UnregisterMessage, "Unregister Message", offsize(sccp_data_t, UnregisterMessage), SKINNY_MSGTYPE_REQUEST, SKINNY_MSGDIRECTION_DEV2PBX },
1852 	[SoftKeyTemplateReqMessage] = { SoftKeyTemplateReqMessage, "SoftKey Template Request", offsize(sccp_data_t, SoftKeyTemplateReqMessage), SKINNY_MSGTYPE_REQUEST, SKINNY_MSGDIRECTION_DEV2PBX },
1853 	[RegisterTokenRequest] = { RegisterTokenRequest, "Register Token Request", offsize(sccp_data_t, RegisterTokenRequest), SKINNY_MSGTYPE_REQUEST, SKINNY_MSGDIRECTION_DEV2PBX },
1854 	/**/[MediaTransmissionFailure] = { MediaTransmissionFailure, "Media Transmission Failure", offsize(sccp_data_t, MediaTransmissionFailure), SKINNY_MSGTYPE_EVENT, SKINNY_MSGDIRECTION_DEV2PBX },
1855 	[HeadsetStatusMessage] = { HeadsetStatusMessage, "Headset Status Message", offsize(sccp_data_t, HeadsetStatusMessage), SKINNY_MSGTYPE_EVENT, SKINNY_MSGDIRECTION_DEV2PBX },
1856 	[MediaResourceNotification] = { MediaResourceNotification, "Media Resource Notification", offsize(sccp_data_t, MediaResourceNotification), SKINNY_MSGTYPE_EVENT, SKINNY_MSGDIRECTION_DEV2PBX },
1857 	[RegisterAvailableLinesMessage] = { RegisterAvailableLinesMessage, "Register Available Lines Message", offsize(sccp_data_t, RegisterAvailableLinesMessage), SKINNY_MSGTYPE_REQUEST, SKINNY_MSGDIRECTION_DEV2PBX },
1858 	[DeviceToUserDataMessage] = { DeviceToUserDataMessage, "Device To User Data Message", offsize(sccp_data_t, DeviceToUserDataMessage), SKINNY_MSGTYPE_EVENT, SKINNY_MSGDIRECTION_DEV2PBX },
1859 	[DeviceToUserDataResponseMessage] = { DeviceToUserDataResponseMessage, "Device To User Data Response", offsize(sccp_data_t, DeviceToUserDataResponseMessage), SKINNY_MSGTYPE_EVENT, SKINNY_MSGDIRECTION_DEV2PBX },
1860 	[UpdateCapabilitiesMessage] = { UpdateCapabilitiesMessage, "Update Capabilities Message", offsize(sccp_data_t, UpdateCapabilitiesMessage), SKINNY_MSGTYPE_EVENT, SKINNY_MSGDIRECTION_DEV2PBX },
1861 	[OpenMultiMediaReceiveChannelAckMessage] = { OpenMultiMediaReceiveChannelAckMessage, "Open MultiMedia Receive Channel Acknowledge", offsize(sccp_data_t, OpenMultiMediaReceiveChannelAckMessage),
1862 						     SKINNY_MSGTYPE_RESPONSE, SKINNY_MSGDIRECTION_DEV2PBX },
1863 	[ClearConferenceMessage] = { ClearConferenceMessage, "Clear Conference Message", offsize(sccp_data_t, ClearConferenceMessage), SKINNY_MSGTYPE_EVENT, SKINNY_MSGDIRECTION_PBX2DEV },
1864 	[ServiceURLStatReqMessage] = { ServiceURLStatReqMessage, "Service URL State Request", offsize(sccp_data_t, ServiceURLStatReqMessage), SKINNY_MSGTYPE_REQUEST, SKINNY_MSGDIRECTION_DEV2PBX },
1865 	[FeatureStatReqMessage] = { FeatureStatReqMessage, "Feature State Request", offsize(sccp_data_t, FeatureStatReqMessage), SKINNY_MSGTYPE_REQUEST, SKINNY_MSGDIRECTION_DEV2PBX },
1866 	[CreateConferenceResMessage] = { CreateConferenceResMessage, "Create Conference Response", offsize(sccp_data_t, CreateConferenceResMessage), SKINNY_MSGTYPE_RESPONSE, SKINNY_MSGDIRECTION_DEV2PBX },
1867 	[DeleteConferenceResMessage] = { DeleteConferenceResMessage, "Delete Conference Response", offsize(sccp_data_t, DeleteConferenceResMessage), SKINNY_MSGTYPE_RESPONSE, SKINNY_MSGDIRECTION_DEV2PBX },
1868 	[ModifyConferenceResMessage] = { ModifyConferenceResMessage, "Modify Conference Response", offsize(sccp_data_t, ModifyConferenceResMessage), SKINNY_MSGTYPE_RESPONSE, SKINNY_MSGDIRECTION_DEV2PBX },
1869 	[AddParticipantResMessage] = { AddParticipantResMessage, "Add Participant Response", offsize(sccp_data_t, AddParticipantResMessage), SKINNY_MSGTYPE_RESPONSE, SKINNY_MSGDIRECTION_DEV2PBX },
1870 	[AuditConferenceResMessage] = { AuditConferenceResMessage, "Audit Conference Response", offsize(sccp_data_t, AuditConferenceResMessage), SKINNY_MSGTYPE_RESPONSE, SKINNY_MSGDIRECTION_DEV2PBX },
1871 	[AuditParticipantResMessage] = { AuditParticipantResMessage, "Audit Participant Response", offsize(sccp_data_t, AuditParticipantResMessage), SKINNY_MSGTYPE_RESPONSE, SKINNY_MSGDIRECTION_DEV2PBX },
1872 	[DeviceToUserDataVersion1Message] = { DeviceToUserDataVersion1Message, "Device To User Data Version1 Message", offsize(sccp_data_t, DeviceToUserDataVersion1Message), SKINNY_MSGTYPE_EVENT,
1873 					      SKINNY_MSGDIRECTION_DEV2PBX },
1874 	[DeviceToUserDataResponseVersion1Message] = { DeviceToUserDataResponseVersion1Message, "Device To User Data Version1 Response", offsize(sccp_data_t, DeviceToUserDataResponseVersion1Message), SKINNY_MSGTYPE_EVENT,
1875 						      SKINNY_MSGDIRECTION_DEV2PBX },
1876 	[SubscriptionStatReqMessage] = { SubscriptionStatReqMessage, "Subscription Status Request (DialedPhoneBook)", offsize(sccp_data_t, SubscriptionStatReqMessage), SKINNY_MSGTYPE_REQUEST, SKINNY_MSGDIRECTION_DEV2PBX },
1877 	[AccessoryStatusMessage] = { AccessoryStatusMessage, "Accessory Status Message", offsize(sccp_data_t, AccessoryStatusMessage), SKINNY_MSGTYPE_EVENT, SKINNY_MSGDIRECTION_DEV2PBX },
1878 
1879 	/* PBX -> DEV */
1880 	[RegisterAckMessage] = { RegisterAckMessage, "Register Acknowledge", offsize(sccp_data_t, RegisterAckMessage), SKINNY_MSGTYPE_RESPONSE, SKINNY_MSGDIRECTION_PBX2DEV },
1881 	[StartToneMessage] = { StartToneMessage, "Start Tone Message", offsize(sccp_data_t, StartToneMessage), SKINNY_MSGTYPE_EVENT, SKINNY_MSGDIRECTION_PBX2DEV },
1882 	[StopToneMessage] = { StopToneMessage, "Stop Tone Message", offsize(sccp_data_t, StopToneMessage), SKINNY_MSGTYPE_EVENT, SKINNY_MSGDIRECTION_PBX2DEV },
1883 	[SetRingerMessage] = { SetRingerMessage, "Set Ringer Message", offsize(sccp_data_t, SetRingerMessage), SKINNY_MSGTYPE_EVENT, SKINNY_MSGDIRECTION_PBX2DEV },
1884 	[SetLampMessage] = { SetLampMessage, "Set Lamp Message", offsize(sccp_data_t, SetLampMessage), SKINNY_MSGTYPE_EVENT, SKINNY_MSGDIRECTION_PBX2DEV },
1885 	[SetHookFlashDetectMessage] = { SetHookFlashDetectMessage, "Set HookFlash Detect Message", offsize(sccp_data_t, SetHookFlashDetectMessage), SKINNY_MSGTYPE_EVENT, SKINNY_MSGDIRECTION_PBX2DEV },
1886 	[SetSpeakerModeMessage] = { SetSpeakerModeMessage, "Set Speaker Mode Message", offsize(sccp_data_t, SetSpeakerModeMessage), SKINNY_MSGTYPE_EVENT, SKINNY_MSGDIRECTION_PBX2DEV },
1887 	[SetMicroModeMessage] = { SetMicroModeMessage, "Set Micro Mode Message", offsize(sccp_data_t, SetMicroModeMessage), SKINNY_MSGTYPE_EVENT, SKINNY_MSGDIRECTION_PBX2DEV },
1888 	/*spa*/[StartMediaTransmission] = { StartMediaTransmission, "Start Media Transmission", offsize(sccp_data_t, StartMediaTransmission), SKINNY_MSGTYPE_EVENT, SKINNY_MSGDIRECTION_PBX2DEV },
1889 	/**/[StopMediaTransmission] = { StopMediaTransmission, "Stop Media Transmission", offsize(sccp_data_t, StopMediaTransmission), SKINNY_MSGTYPE_EVENT, SKINNY_MSGDIRECTION_PBX2DEV },
1890 	/**/[StartMediaReception] = { StartMediaReception, "Start Media Reception", offsize(sccp_data_t, StartMediaReception), SKINNY_MSGTYPE_EVENT, SKINNY_MSGDIRECTION_PBX2DEV },
1891 	/**/[StopMediaReception] = { StopMediaReception, "Stop Media Reception", offsize(sccp_data_t, StopMediaReception), SKINNY_MSGTYPE_EVENT, SKINNY_MSGDIRECTION_PBX2DEV },
1892 	[CallInfoMessage] = { CallInfoMessage, "Call Information Message", offsize(sccp_data_t, CallInfoMessage), SKINNY_MSGTYPE_EVENT, SKINNY_MSGDIRECTION_PBX2DEV },
1893 	[ForwardStatMessage] = { ForwardStatMessage, "Forward State Message", offsize(sccp_data_t, ForwardStatMessage), SKINNY_MSGTYPE_RESPONSE, SKINNY_MSGDIRECTION_PBX2DEV },
1894 	[SpeedDialStatMessage] = { SpeedDialStatMessage, "SpeedDial State Message", offsize(sccp_data_t, SpeedDialStatMessage), SKINNY_MSGTYPE_RESPONSE, SKINNY_MSGDIRECTION_PBX2DEV },
1895 	[LineStatMessage] = { LineStatMessage, "Line State Message", offsize(sccp_data_t, LineStatMessage), SKINNY_MSGTYPE_RESPONSE, SKINNY_MSGDIRECTION_PBX2DEV },
1896 	[ConfigStatMessage] = { ConfigStatMessage, "Config State Message", offsize(sccp_data_t, ConfigStatMessage), SKINNY_MSGTYPE_RESPONSE, SKINNY_MSGDIRECTION_PBX2DEV },
1897 	[ConfigStatDynamicMessage] = { ConfigStatDynamicMessage, "Config State Dynamic Message", offsize(sccp_data_t, ConfigStatDynamicMessage), SKINNY_MSGTYPE_RESPONSE, SKINNY_MSGDIRECTION_PBX2DEV },
1898 	[DefineTimeDate] = { DefineTimeDate, "Define Time Date", offsize(sccp_data_t, DefineTimeDate), SKINNY_MSGTYPE_EVENT, SKINNY_MSGDIRECTION_PBX2DEV },
1899 	/**/[StartSessionTransmission] = { StartSessionTransmission, "Start Session Transmission", offsize(sccp_data_t, StartSessionTransmission), SKINNY_MSGTYPE_EVENT, SKINNY_MSGDIRECTION_PBX2DEV },
1900 	/**/[StopSessionTransmission] = { StopSessionTransmission, "Stop Session Transmission", offsize(sccp_data_t, StopSessionTransmission), SKINNY_MSGTYPE_EVENT, SKINNY_MSGDIRECTION_PBX2DEV },
1901 	[ButtonTemplateMessage] = { ButtonTemplateMessage, "Button Template Message", offsize(sccp_data_t, ButtonTemplateMessage), SKINNY_MSGTYPE_RESPONSE, SKINNY_MSGDIRECTION_PBX2DEV },
1902 	//[ButtonTemplateMessageSingle] = {ButtonTemplateMessageSingle,			"Button Template Message Single",		offsize(sccp_data_t, ButtonTemplateMessageSingle)},
1903 	[VersionMessage] = { VersionMessage, "Version Message", offsize(sccp_data_t, VersionMessage), SKINNY_MSGTYPE_RESPONSE, SKINNY_MSGDIRECTION_PBX2DEV },
1904 	[DisplayTextMessage] = { DisplayTextMessage, "Display Text Message", offsize(sccp_data_t, DisplayTextMessage), SKINNY_MSGTYPE_EVENT, SKINNY_MSGDIRECTION_PBX2DEV },
1905 	[ClearDisplay] = { ClearDisplay, "Clear Display", offsize(sccp_data_t, ClearDisplay), SKINNY_MSGTYPE_EVENT, SKINNY_MSGDIRECTION_PBX2DEV },
1906 
1907 	[CapabilitiesReqMessage] = { CapabilitiesReqMessage, "Capabilities Request", offsize(sccp_data_t, CapabilitiesReqMessage), SKINNY_MSGTYPE_REQUEST, SKINNY_MSGDIRECTION_PBX2DEV },
1908 
1909 	[EnunciatorCommandMessage] = { EnunciatorCommandMessage, "Enunciator Command Message", offsize(sccp_data_t, EnunciatorCommandMessage), SKINNY_MSGTYPE_EVENT, SKINNY_MSGDIRECTION_PBX2DEV },
1910 	[RegisterRejectMessage] = { RegisterRejectMessage, "Register Reject Message", offsize(sccp_data_t, RegisterRejectMessage), SKINNY_MSGTYPE_RESPONSE, SKINNY_MSGDIRECTION_PBX2DEV },
1911 	[ServerResMessage] = { ServerResMessage, "Server Response", offsize(sccp_data_t, ServerResMessage), SKINNY_MSGTYPE_RESPONSE, SKINNY_MSGDIRECTION_PBX2DEV },
1912 	[Reset] = { Reset, "Reset", offsize(sccp_data_t, Reset), SKINNY_MSGTYPE_EVENT, SKINNY_MSGDIRECTION_PBX2DEV },
1913 	[KeepAliveAckMessage] = { KeepAliveAckMessage, "Keep Alive Acknowledge", offsize(sccp_data_t, KeepAliveAckMessage), SKINNY_MSGTYPE_RESPONSE, SKINNY_MSGDIRECTION_PBX2DEV },
1914 	/**/[StartMulticastMediaReception] = { StartMulticastMediaReception, "Start MulticastMedia Reception", offsize(sccp_data_t, StartMulticastMediaReception), SKINNY_MSGTYPE_EVENT, SKINNY_MSGDIRECTION_PBX2DEV },
1915 	/**/[StartMulticastMediaTransmission] = { StartMulticastMediaTransmission, "Start MulticastMedia Transmission", offsize(sccp_data_t, StartMulticastMediaTransmission), SKINNY_MSGTYPE_EVENT,
1916 						  SKINNY_MSGDIRECTION_PBX2DEV },
1917 	/**/[StopMulticastMediaReception] = { StopMulticastMediaReception, "Stop MulticastMedia Reception", offsize(sccp_data_t, StopMulticastMediaReception), SKINNY_MSGTYPE_EVENT, SKINNY_MSGDIRECTION_PBX2DEV },
1918 	/**/[StopMulticastMediaTransmission] = { StopMulticastMediaTransmission, "Stop MulticastMedia Transmission", offsize(sccp_data_t, StopMulticastMediaTransmission), SKINNY_MSGTYPE_EVENT, SKINNY_MSGDIRECTION_PBX2DEV },
1919 	[OpenReceiveChannel] = { OpenReceiveChannel, "Open Receive Channel", offsize(sccp_data_t, OpenReceiveChannel), SKINNY_MSGTYPE_REQUEST, SKINNY_MSGDIRECTION_PBX2DEV },
1920 	[CloseReceiveChannel] = { CloseReceiveChannel, "Close Receive Channel", offsize(sccp_data_t, CloseReceiveChannel), SKINNY_MSGTYPE_EVENT, SKINNY_MSGDIRECTION_PBX2DEV },
1921 	/*[ConnectionStatisticsReq] = { ConnectionStatisticsReq, "Connection Statistics Request", offsize(sccp_data_t, ConnectionStatisticsReq), SKINNY_MSGTYPE_REQUEST, SKINNY_MSGDIRECTION_PBX2DEV },**/
1922 	[ConnectionStatisticsReq] = { ConnectionStatisticsReq, "Connection Statistics Request", offsize(sccp_data_t, ConnectionStatisticsReq), SKINNY_MSGTYPE_EVENT, SKINNY_MSGDIRECTION_PBX2DEV },
1923 	[SoftKeyTemplateResMessage] = { SoftKeyTemplateResMessage, "SoftKey Template Response", offsize(sccp_data_t, SoftKeyTemplateResMessage), SKINNY_MSGTYPE_RESPONSE, SKINNY_MSGDIRECTION_PBX2DEV },
1924 	[SoftKeySetResMessage] = { SoftKeySetResMessage, "SoftKey Set Response", offsize(sccp_data_t, SoftKeySetResMessage), SKINNY_MSGTYPE_RESPONSE, SKINNY_MSGDIRECTION_PBX2DEV },
1925 	[SelectSoftKeysMessage] = { SelectSoftKeysMessage, "Select SoftKeys Message", offsize(sccp_data_t, SelectSoftKeysMessage), SKINNY_MSGTYPE_EVENT, SKINNY_MSGDIRECTION_PBX2DEV },
1926 	[CallStateMessage] = { CallStateMessage, "Call State Message", offsize(sccp_data_t, CallStateMessage), SKINNY_MSGTYPE_EVENT, SKINNY_MSGDIRECTION_PBX2DEV },
1927 	[DisplayPromptStatusMessage] = { DisplayPromptStatusMessage, "Display Prompt Status Message", offsize(sccp_data_t, DisplayPromptStatusMessage), SKINNY_MSGTYPE_EVENT, SKINNY_MSGDIRECTION_PBX2DEV },
1928 	[ClearPromptStatusMessage] = { ClearPromptStatusMessage, "Clear Prompt Status Message", offsize(sccp_data_t, ClearPromptStatusMessage), SKINNY_MSGTYPE_EVENT, SKINNY_MSGDIRECTION_PBX2DEV },
1929 	[DisplayNotifyMessage] = { DisplayNotifyMessage, "Display Notify Message", offsize(sccp_data_t, DisplayNotifyMessage), SKINNY_MSGTYPE_EVENT, SKINNY_MSGDIRECTION_PBX2DEV },
1930 	[ClearNotifyMessage] = { ClearNotifyMessage, "Clear Notify Message", offsize(sccp_data_t, ClearNotifyMessage), SKINNY_MSGTYPE_EVENT, SKINNY_MSGDIRECTION_PBX2DEV },
1931 	[ActivateCallPlaneMessage] = { ActivateCallPlaneMessage, "Activate Call Plane Message", offsize(sccp_data_t, ActivateCallPlaneMessage), SKINNY_MSGTYPE_EVENT, SKINNY_MSGDIRECTION_PBX2DEV },
1932 	[DeactivateCallPlaneMessage] = { DeactivateCallPlaneMessage, "Deactivate Call Plane Message", offsize(sccp_data_t, DeactivateCallPlaneMessage), SKINNY_MSGTYPE_EVENT, SKINNY_MSGDIRECTION_PBX2DEV },
1933 	[UnregisterAckMessage] = { UnregisterAckMessage, "Unregister Acknowledge", offsize(sccp_data_t, UnregisterAckMessage), SKINNY_MSGTYPE_RESPONSE, SKINNY_MSGDIRECTION_PBX2DEV },
1934 	[BackSpaceResMessage] = { BackSpaceResMessage, "Back Space Response", offsize(sccp_data_t, BackSpaceResMessage), SKINNY_MSGTYPE_RESPONSE, SKINNY_MSGDIRECTION_PBX2DEV },
1935 	[RegisterTokenAck] = { RegisterTokenAck, "Register Token Acknowledge", offsize(sccp_data_t, RegisterTokenAck), SKINNY_MSGTYPE_RESPONSE, SKINNY_MSGDIRECTION_PBX2DEV },
1936 	[RegisterTokenReject] = { RegisterTokenReject, "Register Token Reject", offsize(sccp_data_t, RegisterTokenReject), SKINNY_MSGTYPE_RESPONSE, SKINNY_MSGDIRECTION_PBX2DEV },
1937 	[StartMediaFailureDetection] = { StartMediaFailureDetection, "Start Media Failure Detection", offsize(sccp_data_t, StartMediaFailureDetection), SKINNY_MSGTYPE_REQUEST, SKINNY_MSGDIRECTION_PBX2DEV },
1938 	[DialedNumberMessage] = { DialedNumberMessage, "Dialed Number Message", offsize(sccp_data_t, DialedNumberMessage), SKINNY_MSGTYPE_EVENT, SKINNY_MSGDIRECTION_PBX2DEV },
1939 	[UserToDeviceDataMessage] = { UserToDeviceDataMessage, "User To Device Data Message", offsize(sccp_data_t, UserToDeviceDataMessage), SKINNY_MSGTYPE_EVENT, SKINNY_MSGDIRECTION_PBX2DEV },
1940 	[FeatureStatMessage] = { FeatureStatMessage, "Feature State Message", offsize(sccp_data_t, FeatureStatMessage), SKINNY_MSGTYPE_RESPONSE, SKINNY_MSGDIRECTION_PBX2DEV },
1941 	[DisplayPriNotifyMessage] = { DisplayPriNotifyMessage, "Display Pri Notify Message", offsize(sccp_data_t, DisplayPriNotifyMessage), SKINNY_MSGTYPE_EVENT, SKINNY_MSGDIRECTION_PBX2DEV },
1942 	[ClearPriNotifyMessage] = { ClearPriNotifyMessage, "Clear Pri Notify Message", offsize(sccp_data_t, ClearPriNotifyMessage), SKINNY_MSGTYPE_EVENT, SKINNY_MSGDIRECTION_PBX2DEV },
1943 	[StartAnnouncementMessage] = { StartAnnouncementMessage, "Start Announcement Message", offsize(sccp_data_t, StartAnnouncementMessage), SKINNY_MSGTYPE_EVENT, SKINNY_MSGDIRECTION_PBX2DEV },
1944 	[StopAnnouncementMessage] = { StopAnnouncementMessage, "Stop Announcement Message", offsize(sccp_data_t, StopAnnouncementMessage), SKINNY_MSGTYPE_EVENT, SKINNY_MSGDIRECTION_PBX2DEV },
1945 	[AnnouncementFinishMessage] = { AnnouncementFinishMessage, "Announcement Finish Message", offsize(sccp_data_t, AnnouncementFinishMessage), SKINNY_MSGTYPE_EVENT, SKINNY_MSGDIRECTION_PBX2DEV },
1946 	[NotifyDtmfToneMessage] = { NotifyDtmfToneMessage, "Notify DTMF Tone Message", offsize(sccp_data_t, NotifyDtmfToneMessage), SKINNY_MSGTYPE_EVENT, SKINNY_MSGDIRECTION_PBX2DEV },
1947 	[SendDtmfToneMessage] = { SendDtmfToneMessage, "Send DTMF Tone Message", offsize(sccp_data_t, SendDtmfToneMessage), SKINNY_MSGTYPE_EVENT, SKINNY_MSGDIRECTION_PBX2DEV },
1948 	[SubscribeDtmfPayloadReqMessage] = { SubscribeDtmfPayloadReqMessage, "Subscribe DTMF Payload Request", offsize(sccp_data_t, SubscribeDtmfPayloadReqMessage), SKINNY_MSGTYPE_REQUEST, SKINNY_MSGDIRECTION_PBX2DEV },
1949 	[SubscribeDtmfPayloadResMessage] = { SubscribeDtmfPayloadResMessage, "Subscribe DTMF Payload Response", offsize(sccp_data_t, SubscribeDtmfPayloadResMessage), SKINNY_MSGTYPE_RESPONSE, SKINNY_MSGDIRECTION_DEV2PBX },
1950 	[SubscribeDtmfPayloadErrMessage] = { SubscribeDtmfPayloadErrMessage, "Subscribe DTMF Payload Error Message", offsize(sccp_data_t, SubscribeDtmfPayloadErrMessage), SKINNY_MSGTYPE_EVENT, SKINNY_MSGDIRECTION_PBX2DEV },
1951 	[UnSubscribeDtmfPayloadReqMessage] = { UnSubscribeDtmfPayloadReqMessage, "UnSubscribe DTMF Payload Request", offsize(sccp_data_t, UnSubscribeDtmfPayloadReqMessage), SKINNY_MSGTYPE_REQUEST,
1952 					       SKINNY_MSGDIRECTION_UNKNOWN },
1953 	[UnSubscribeDtmfPayloadResMessage] = { UnSubscribeDtmfPayloadResMessage, "UnSubscribe DTMF Payload Response", offsize(sccp_data_t, UnSubscribeDtmfPayloadResMessage), SKINNY_MSGTYPE_RESPONSE,
1954 					       SKINNY_MSGDIRECTION_UNKNOWN },
1955 	[UnSubscribeDtmfPayloadErrMessage] = { UnSubscribeDtmfPayloadErrMessage, "UnSubscribe DTMF Payload Error Message", offsize(sccp_data_t, UnSubscribeDtmfPayloadErrMessage), SKINNY_MSGTYPE_EVENT,
1956 					       SKINNY_MSGDIRECTION_UNKNOWN },
1957 	[ServiceURLStatMessage] = { ServiceURLStatMessage, "ServiceURL State Message", offsize(sccp_data_t, ServiceURLStatMessage), SKINNY_MSGTYPE_RESPONSE, SKINNY_MSGDIRECTION_PBX2DEV },
1958 	[CallSelectStatMessage] = { CallSelectStatMessage, "Call Select State Message", offsize(sccp_data_t, CallSelectStatMessage), SKINNY_MSGTYPE_RESPONSE, SKINNY_MSGDIRECTION_PBX2DEV },
1959 	[OpenMultiMediaChannelMessage] = { OpenMultiMediaChannelMessage, "Open MultiMedia Channel Message", offsize(sccp_data_t, OpenMultiMediaChannelMessage), SKINNY_MSGTYPE_REQUEST, SKINNY_MSGDIRECTION_PBX2DEV },
1960 	/*spa*/[StartMultiMediaTransmission] = { StartMultiMediaTransmission, "Start MultiMedia Transmission", offsize(sccp_data_t, StartMultiMediaTransmission), SKINNY_MSGTYPE_EVENT, SKINNY_MSGDIRECTION_PBX2DEV },
1961 	/**/[StopMultiMediaTransmission] = { StopMultiMediaTransmission, "Stop MultiMedia Transmission", offsize(sccp_data_t, StopMultiMediaTransmission), SKINNY_MSGTYPE_EVENT, SKINNY_MSGDIRECTION_PBX2DEV },
1962 	[MiscellaneousCommandMessage] = { MiscellaneousCommandMessage, "Miscellaneous Command Message", offsize(sccp_data_t, MiscellaneousCommandMessage), SKINNY_MSGTYPE_EVENT, SKINNY_MSGDIRECTION_PBX2DEV },
1963 	[FlowControlCommandMessage] = { FlowControlCommandMessage, "Flow Control Command Message", offsize(sccp_data_t, FlowControlCommandMessage), SKINNY_MSGTYPE_EVENT, SKINNY_MSGDIRECTION_PBX2DEV },
1964 	[CloseMultiMediaReceiveChannel] = { CloseMultiMediaReceiveChannel, "Close MultiMedia Receive Channel", offsize(sccp_data_t, CloseMultiMediaReceiveChannel), SKINNY_MSGTYPE_EVENT, SKINNY_MSGDIRECTION_PBX2DEV },
1965 	[CreateConferenceReqMessage] = { CreateConferenceReqMessage, "Create Conference Request", offsize(sccp_data_t, CreateConferenceReqMessage), SKINNY_MSGTYPE_REQUEST, SKINNY_MSGDIRECTION_PBX2DEV },
1966 	[DeleteConferenceReqMessage] = { DeleteConferenceReqMessage, "Delete Conference Request", offsize(sccp_data_t, DeleteConferenceReqMessage), SKINNY_MSGTYPE_REQUEST, SKINNY_MSGDIRECTION_PBX2DEV },
1967 	[ModifyConferenceReqMessage] = { ModifyConferenceReqMessage, "Modify Conference Request", offsize(sccp_data_t, ModifyConferenceReqMessage), SKINNY_MSGTYPE_REQUEST, SKINNY_MSGDIRECTION_PBX2DEV },
1968 	[AddParticipantReqMessage] = { AddParticipantReqMessage, "Add Participant Request", offsize(sccp_data_t, AddParticipantReqMessage), SKINNY_MSGTYPE_REQUEST, SKINNY_MSGDIRECTION_PBX2DEV },
1969 	[DropParticipantReqMessage] = { DropParticipantReqMessage, "Drop Participant Request", offsize(sccp_data_t, DropParticipantReqMessage), SKINNY_MSGTYPE_REQUEST, SKINNY_MSGDIRECTION_PBX2DEV },
1970 	[AuditConferenceReqMessage] = { AuditConferenceReqMessage, "Audit Conference Request", offsize(sccp_data_t, AuditConferenceReqMessage), SKINNY_MSGTYPE_REQUEST, SKINNY_MSGDIRECTION_PBX2DEV },
1971 	[AuditParticipantReqMessage] = { AuditParticipantReqMessage, "Audit Participant Request", offsize(sccp_data_t, AuditParticipantReqMessage), SKINNY_MSGTYPE_REQUEST, SKINNY_MSGDIRECTION_PBX2DEV },
1972 	[UserToDeviceDataVersion1Message] = { UserToDeviceDataVersion1Message, "User To Device Data Version1 Message", offsize(sccp_data_t, UserToDeviceDataVersion1Message), SKINNY_MSGTYPE_EVENT,
1973 					      SKINNY_MSGDIRECTION_PBX2DEV },
1974 	[DisplayDynamicNotifyMessage] = { DisplayDynamicNotifyMessage, "Display Dynamic Notify Message", offsize(sccp_data_t, DisplayDynamicNotifyMessage), SKINNY_MSGTYPE_EVENT, SKINNY_MSGDIRECTION_PBX2DEV },
1975 	[DisplayDynamicPriNotifyMessage] = { DisplayDynamicPriNotifyMessage, "Display Dynamic Priority Notify Message", offsize(sccp_data_t, DisplayDynamicPriNotifyMessage), SKINNY_MSGTYPE_EVENT,
1976 					     SKINNY_MSGDIRECTION_UNKNOWN },
1977 	[DisplayDynamicPromptStatusMessage] = { DisplayDynamicPromptStatusMessage, "Display Dynamic Prompt Status Message", offsize(sccp_data_t, DisplayDynamicPromptStatusMessage), SKINNY_MSGTYPE_EVENT,
1978 						SKINNY_MSGDIRECTION_UNKNOWN },
1979 	[FeatureStatDynamicMessage] = { FeatureStatDynamicMessage, "SpeedDial State Dynamic Message", offsize(sccp_data_t, FeatureStatDynamicMessage), SKINNY_MSGTYPE_RESPONSE, SKINNY_MSGDIRECTION_PBX2DEV },
1980 	[LineStatDynamicMessage] = { LineStatDynamicMessage, "Line State Dynamic Message", offsize(sccp_data_t, LineStatDynamicMessage), SKINNY_MSGTYPE_RESPONSE, SKINNY_MSGDIRECTION_PBX2DEV },
1981 	[ServiceURLStatDynamicMessage] = { ServiceURLStatDynamicMessage, "Service URL Stat Dynamic Messages", offsize(sccp_data_t, ServiceURLStatDynamicMessage), SKINNY_MSGTYPE_RESPONSE, SKINNY_MSGDIRECTION_PBX2DEV },
1982 	[SpeedDialStatDynamicMessage] = { SpeedDialStatDynamicMessage, "SpeedDial Stat Dynamic Message", offsize(sccp_data_t, SpeedDialStatDynamicMessage), SKINNY_MSGTYPE_RESPONSE, SKINNY_MSGDIRECTION_PBX2DEV },
1983 	[CallInfoDynamicMessage] = { CallInfoDynamicMessage, "Call Information Dynamic Message", offsize(sccp_data_t, CallInfoDynamicMessage), SKINNY_MSGTYPE_EVENT, SKINNY_MSGDIRECTION_PBX2DEV },
1984 	[SubscriptionStatMessage] = { SubscriptionStatMessage, "Subscription Status Response (Dialed Number)", offsize(sccp_data_t, SubscriptionStatMessage), SKINNY_MSGTYPE_RESPONSE, SKINNY_MSGDIRECTION_PBX2DEV },
1985 	[NotificationMessage] = { NotificationMessage, "Notify Call List (CallListStatusUpdate)", offsize(sccp_data_t, NotificationMessage), SKINNY_MSGTYPE_EVENT, SKINNY_MSGDIRECTION_PBX2DEV },
1986 	/*spa*/[StartMediaTransmissionAck] = { StartMediaTransmissionAck, "Start Media Transmission Acknowledge", offsize(sccp_data_t, StartMediaTransmissionAck), SKINNY_MSGTYPE_EVENT, SKINNY_MSGDIRECTION_PBX2DEV },
1987 	/**/[StartMultiMediaTransmissionAck] = { StartMultiMediaTransmissionAck, "Start Media Transmission Acknowledge", offsize(sccp_data_t, StartMultiMediaTransmissionAck), SKINNY_MSGTYPE_EVENT,
1988 						 SKINNY_MSGDIRECTION_PBX2DEV },
1989 	[CallHistoryDispositionMessage] = { CallHistoryDispositionMessage, "Call History Disposition", offsize(sccp_data_t, CallHistoryDispositionMessage), SKINNY_MSGTYPE_EVENT, SKINNY_MSGDIRECTION_PBX2DEV },
1990 	[LocationInfoMessage] = { LocationInfoMessage, "Location/Wifi Information", offsize(sccp_data_t, LocationInfoMessage), SKINNY_MSGTYPE_EVENT, SKINNY_MSGDIRECTION_PBX2DEV },
1991 	[ExtensionDeviceCaps] = { ExtensionDeviceCaps, "Extension Device Capabilities Message", offsize(sccp_data_t, ExtensionDeviceCaps), SKINNY_MSGTYPE_EVENT, SKINNY_MSGDIRECTION_PBX2DEV },
1992 	[XMLAlarmMessage] = { XMLAlarmMessage, "XML-AlarmMessage", offsize(sccp_data_t, XMLAlarmMessage), SKINNY_MSGTYPE_EVENT, SKINNY_MSGDIRECTION_PBX2DEV },
1993 	[MediaPathCapabilityMessage] = { MediaPathCapabilityMessage, "MediaPath Capability Message", offsize(sccp_data_t, MediaPathCapabilityMessage), SKINNY_MSGTYPE_EVENT, SKINNY_MSGDIRECTION_PBX2DEV },
1994 	[FlowControlNotifyMessage] = { FlowControlNotifyMessage, "FlowControl Notify Message", offsize(sccp_data_t, FlowControlNotifyMessage), SKINNY_MSGTYPE_EVENT, SKINNY_MSGDIRECTION_PBX2DEV },
1995 	[CallCountReqMessage] = { CallCountReqMessage, "CallCount Request Message", offsize(sccp_data_t, CallCountReqMessage), SKINNY_MSGTYPE_REQUEST, SKINNY_MSGDIRECTION_PBX2DEV },
1996 	/*new*/
1997 	[UpdateCapabilitiesV2Message] = { UpdateCapabilitiesV2Message, "Update Capabilities V2", offsize(sccp_data_t, UpdateCapabilitiesV2Message), SKINNY_MSGTYPE_EVENT, SKINNY_MSGDIRECTION_DEV2PBX },
1998 	[UpdateCapabilitiesV3Message] = { UpdateCapabilitiesV3Message, "Update Capabilities V3", offsize(sccp_data_t, UpdateCapabilitiesV3Message), SKINNY_MSGTYPE_EVENT, SKINNY_MSGDIRECTION_DEV2PBX },
1999 	[PortResponseMessage] = { PortResponseMessage, "Port Response Message", offsize(sccp_data_t, PortResponseMessage), SKINNY_MSGTYPE_RESPONSE, SKINNY_MSGDIRECTION_PBX2DEV },
2000 	[QoSResvNotifyMessage] = { QoSResvNotifyMessage, "QoS Resv Notify Message", offsize(sccp_data_t, QoSResvNotifyMessage), SKINNY_MSGTYPE_EVENT, SKINNY_MSGDIRECTION_PBX2DEV },
2001 	[QoSErrorNotifyMessage] = { QoSErrorNotifyMessage, "QoS Error Notify Message", offsize(sccp_data_t, QoSErrorNotifyMessage), SKINNY_MSGTYPE_EVENT, SKINNY_MSGDIRECTION_PBX2DEV },
2002 	[PortRequestMessage] = { PortRequestMessage, "Port Request Message", offsize(sccp_data_t, PortRequestMessage), SKINNY_MSGTYPE_REQUEST, SKINNY_MSGDIRECTION_PBX2DEV },
2003 	[PortCloseMessage] = { PortCloseMessage, "Port Close Message", offsize(sccp_data_t, PortCloseMessage), SKINNY_MSGTYPE_EVENT, SKINNY_MSGDIRECTION_PBX2DEV },
2004 	[QoSListenMessage] = { QoSListenMessage, "QoS Listen Message", offsize(sccp_data_t, QoSListenMessage), SKINNY_MSGTYPE_EVENT, SKINNY_MSGDIRECTION_PBX2DEV },
2005 	[QoSPathMessage] = { QoSPathMessage, "QoS Path Message", offsize(sccp_data_t, QoSPathMessage), SKINNY_MSGTYPE_EVENT, SKINNY_MSGDIRECTION_PBX2DEV },
2006 	[QoSTeardownMessage] = { QoSTeardownMessage, "QoS Teardown Message", offsize(sccp_data_t, QoSTeardownMessage), SKINNY_MSGTYPE_EVENT, SKINNY_MSGDIRECTION_PBX2DEV },
2007 	[UpdateDSCPMessage] = { UpdateDSCPMessage, "Update DSCP Message", offsize(sccp_data_t, UpdateDSCPMessage), SKINNY_MSGTYPE_EVENT, SKINNY_MSGDIRECTION_PBX2DEV },
2008 	[QoSModifyMessage] = { QoSModifyMessage, "QoS Modify Message", offsize(sccp_data_t, QoSModifyMessage), SKINNY_MSGTYPE_EVENT, SKINNY_MSGDIRECTION_PBX2DEV },
2009 	[MwiResponseMessage] = { MwiResponseMessage, "Mwi Response Message", offsize(sccp_data_t, MwiResponseMessage), SKINNY_MSGTYPE_RESPONSE, SKINNY_MSGDIRECTION_PBX2DEV },
2010 	[CallCountRespMessage] = { CallCountRespMessage, "CallCount Response Message", offsize(sccp_data_t, CallCountRespMessage), SKINNY_MSGTYPE_RESPONSE, SKINNY_MSGDIRECTION_PBX2DEV },
2011 	[RecordingStatusMessage] = { RecordingStatusMessage, "Recording Status Message", offsize(sccp_data_t, RecordingStatusMessage), SKINNY_MSGTYPE_EVENT, SKINNY_MSGDIRECTION_PBX2DEV },
2012 	/* clang-format on */
2013 };
2014 
2015 const struct messageinfo spcp_messageinfo[] = {
2016 	/* clang-format off */
2017 	[SPCPRegisterTokenRequest - SPCP_MESSAGE_OFFSET] = { SPCPRegisterTokenRequest, "SPCP Register Token Request", offsize(sccp_data_t, SPCPRegisterTokenRequest), SKINNY_MSGTYPE_REQUEST, SKINNY_MSGDIRECTION_DEV2PBX },
2018 	[SPCPRegisterTokenAck - SPCP_MESSAGE_OFFSET] = { SPCPRegisterTokenAck, "SPCP RegisterMessageACK", offsize(sccp_data_t, SPCPRegisterTokenAck), SKINNY_MSGTYPE_RESPONSE, SKINNY_MSGDIRECTION_PBX2DEV },
2019 	[SPCPRegisterTokenReject - SPCP_MESSAGE_OFFSET] = { SPCPRegisterTokenReject, "SPCP RegisterMessageReject", offsize(sccp_data_t, SPCPRegisterTokenReject), SKINNY_MSGTYPE_RESPONSE, SKINNY_MSGDIRECTION_PBX2DEV },
2020 	//[UnknownVGMessage - SPCP_MESSAGE_OFFSET		] = {UnknownVGMessage,		"Unknown Message (VG224)",			offsize(sccp_data_t, UnknownVGMessage)},
2021 	/* clang-format on */
2022 };
2023 
lookupMsgInfoStruct(uint32_t messageId)2024 gcc_inline struct messageinfo * lookupMsgInfoStruct(uint32_t messageId)
2025 {
2026 	if(messageId <= SCCP_MESSAGE_HIGH_BOUNDARY) {
2027 		return (struct messageinfo *)&sccp_messageinfo[messageId];
2028 	}
2029 	if(messageId >= SPCP_MESSAGE_LOW_BOUNDARY && messageId <= SPCP_MESSAGE_HIGH_BOUNDARY) {
2030 		return (struct messageinfo *)&spcp_messageinfo[messageId - SPCP_MESSAGE_OFFSET];
2031 	}
2032 	pbx_log(LOG_ERROR, "SCCP: (session::lookupMsgInfo) messageId out of bounds: %d < %u > %d. Or messageId unknown. discarding message.\n", SCCP_MESSAGE_LOW_BOUNDARY, messageId, SPCP_MESSAGE_HIGH_BOUNDARY);
2033 	return NULL;
2034 }
2035 
msginfo2str(sccp_mid_t msgId)2036 gcc_inline const char * msginfo2str(sccp_mid_t msgId)
2037 {														/* sccp_protocol.h */
2038 	struct messageinfo * info = lookupMsgInfoStruct(msgId);
2039 	return info->text;
2040 }
2041 
2042 // kate: indent-width 8; replace-tabs off; indent-mode cstyle; auto-insert-doxygen on; line-numbers on; tab-indents on; keep-extra-spaces off; auto-brackets off;
2043