1 /*!
2  * \file        ast110.c
3  * \brief       SCCP PBX Asterisk Wrapper Class
4  * \author      Marcello Ceshia
5  * \author      Diederik de Groot <ddegroot [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 #include "config.h"
11 #include "common.h"
12 #include "chan_sccp.h"
13 #include "sccp_pbx.h"
14 #include "sccp_channel.h"
15 #include "sccp_device.h"
16 #include "sccp_line.h"
17 #include "sccp_linedevice.h"
18 #include "sccp_cli.h"
19 #include "sccp_utils.h"
20 #include "sccp_indicate.h"
21 #include "sccp_hint.h"
22 #include "sccp_appfunctions.h"
23 #include "sccp_management.h"
24 #include "sccp_netsock.h"
25 #include "sccp_rtp.h"
26 #include "sccp_session.h"		// required for sccp_session_getOurIP
27 #include "sccp_labels.h"
28 #include "pbx_impl/ast110/ast110.h"
29 
30 SCCP_FILE_VERSION(__FILE__, "");
31 
32 __BEGIN_C_EXTERN__
33 #ifdef HAVE_PBX_ACL_H
34 #  include <asterisk/acl.h>
35 #endif
36 #include <asterisk/module.h>
37 #include <asterisk/callerid.h>
38 #include <asterisk/causes.h>
39 #include <asterisk/musiconhold.h>
40 #ifdef HAVE_PBX_FEATURES_H
41 #  include <asterisk/features.h>
42 #endif
43 #include <asterisk/indications.h>
44 #include <asterisk/cel.h>
45 #include <asterisk/netsock2.h>
46 #define new avoid_cxx_new_keyword
47 #include <asterisk/rtp_engine.h>
48 #undef new
49 #include <asterisk/timing.h>
50 __END_C_EXTERN__
51 
52 static struct ast_sched_context *sched = 0;
53 static struct io_context *io = 0;
54 
55 #ifdef CS_SCCP_CONFERENCE
56 static struct ast_format slinFormat = { AST_FORMAT_SLINEAR, {{0}, 0} };
57 #endif
58 static PBX_CHANNEL_TYPE *sccp_astwrap_request(const char *type, struct ast_format_cap *format, const PBX_CHANNEL_TYPE * requestor, void *data, int *cause);
59 static int sccp_astwrap_call(PBX_CHANNEL_TYPE * ast, char *dest, int timeout);
60 static int sccp_astwrap_answer(PBX_CHANNEL_TYPE * chan);
61 static PBX_FRAME_TYPE *sccp_astwrap_rtp_read(PBX_CHANNEL_TYPE * ast);
62 static int sccp_astwrap_rtp_write(PBX_CHANNEL_TYPE * ast, PBX_FRAME_TYPE * frame);
63 static int sccp_astwrap_indicate(PBX_CHANNEL_TYPE * ast, int ind, const void *data, size_t datalen);
64 static int sccp_astwrap_fixup(PBX_CHANNEL_TYPE * oldchan, PBX_CHANNEL_TYPE * newchan);
65 static int sccp_pbx_sendtext(PBX_CHANNEL_TYPE * ast, const char *text);
66 static int sccp_wrapper_recvdigit_begin(PBX_CHANNEL_TYPE * ast, char digit);
67 static int sccp_wrapper_recvdigit_end(PBX_CHANNEL_TYPE * ast, char digit, unsigned int duration);
68 static int sccp_pbx_sendHTML(PBX_CHANNEL_TYPE * ast, int subclass, const char *data, int datalen);
69 int sccp_astwrap_hangup(PBX_CHANNEL_TYPE * ast_channel);
70 int sccp_astwrap_queue_control(const PBX_CHANNEL_TYPE * pbx_channel, enum ast_control_frame_type control);
71 int sccp_astwrap_queue_control_data(const PBX_CHANNEL_TYPE * pbx_channel, enum ast_control_frame_type control, const void *data, size_t datalen);
72 static int sccp_astwrap_devicestate(void *data);
73 PBX_CHANNEL_TYPE *sccp_astwrap_findPickupChannelByExtenLocked(PBX_CHANNEL_TYPE * chan, const char *exten, const char *context);
74 PBX_CHANNEL_TYPE *sccp_astwrap_findPickupChannelByGroupLocked(PBX_CHANNEL_TYPE * chan);
75 
sccp_astwrap_getSkinnyFormatSingle(struct ast_format_cap * ast_format_capability)76 static skinny_codec_t sccp_astwrap_getSkinnyFormatSingle(struct ast_format_cap *ast_format_capability)
77 {
78 	struct ast_format tmp_fmt;
79 	skinny_codec_t codec = SKINNY_CODEC_NONE;
80 
81 	ast_format_cap_iter_start(ast_format_capability);
82 	while (!ast_format_cap_iter_next(ast_format_capability, &tmp_fmt)) {
83 		if ((codec = pbx_codec2skinny_codec(tmp_fmt.id)) != SKINNY_CODEC_NONE) {
84 			break;
85 		}
86 	}
87 	ast_format_cap_iter_end(ast_format_capability);
88 
89 	if (codec == SKINNY_CODEC_NONE) {
90 		ast_log(LOG_WARNING, "SCCP: (getSkinnyFormatSingle) No matching codec found");
91 	}
92 
93 	return codec;
94 }
95 
sccp_astwrap_getSkinnyFormatMultiple(struct ast_format_cap * ast_format_capability,skinny_codec_t codec[],int length)96 static uint8_t sccp_astwrap_getSkinnyFormatMultiple(struct ast_format_cap *ast_format_capability, skinny_codec_t codec[], int length)
97 {
98 	struct ast_format tmp_fmt;
99 	uint8_t position = 0;
100 	skinny_codec_t found = SKINNY_CODEC_NONE;
101 
102 	ast_format_cap_iter_start(ast_format_capability);
103 	while (!ast_format_cap_iter_next(ast_format_capability, &tmp_fmt) && position < length) {
104 		if ((found = pbx_codec2skinny_codec(tmp_fmt.id)) != SKINNY_CODEC_NONE) {
105 			codec[position++] = found;
106 		}
107 	}
108 	ast_format_cap_iter_end(ast_format_capability);
109 
110 	return position;
111 }
112 
113 #if defined(__cplusplus) || defined(c_plusplus)
114 
115 /*!
116  * \brief SCCP Tech Structure
117  */
118 static struct ast_channel_tech sccp_tech = {
119 	/* *INDENT-OFF* */
120 	type:			SCCP_TECHTYPE_STR,
121 	description:		"Skinny Client Control Protocol (SCCP)",
122 //      capabilities:		AST_FORMAT_ALAW | AST_FORMAT_ULAW | AST_FORMAT_SLINEAR16 | AST_FORMAT_GSM | AST_FORMAT_G723_1 | AST_FORMAT_G729A | AST_FORMAT_H264 | AST_FORMAT_H263_PLUS,
123 	properties:		AST_CHAN_TP_WANTSJITTER | AST_CHAN_TP_CREATESJITTER,
124 	requester:		sccp_astwrap_request,
125 	devicestate:		sccp_astwrap_devicestate,
126 	send_digit_begin:	sccp_wrapper_recvdigit_begin,
127 	send_digit_end:		sccp_wrapper_recvdigit_end,
128 	call:			sccp_astwrap_call,
129 	hangup:			sccp_astwrap_hangup,
130 	answer:			sccp_astwrap_answer,
131 	read:			sccp_astwrap_rtp_read,
132 	write:			sccp_astwrap_rtp_write,
133 	send_text:		sccp_pbx_sendtext,
134 	send_image:		NULL,
135 	send_html:		sccp_pbx_sendHTML,
136 	exception:		NULL,
137 //	bridge:			sccp_astwrap_rtpBridge,
138 	bridge:			ast_rtp_instance_bridge,
139 	early_bridge:		ast_rtp_instance_early_bridge,
140 	indicate:		sccp_astwrap_indicate,
141 	fixup:			sccp_astwrap_fixup,
142 	setoption:		NULL,
143 	queryoption:		NULL,
144 	transfer:		NULL,
145 	write_video:		sccp_astwrap_rtp_write,
146 	write_text:		NULL,
147 	bridged_channel:	NULL,
148 	func_channel_read:	sccp_astgenwrap_channel_read,
149 	func_channel_write:	sccp_astgenwrap_channel_write,
150 	get_base_channel:	NULL,
151 	set_base_channel:	NULL
152 	/* *INDENT-ON* */
153 };
154 
155 #else
156 
157 /*!
158  * \brief SCCP Tech Structure
159  */
160 struct ast_channel_tech sccp_tech = {
161 	/* *INDENT-OFF* */
162 	.type 			= SCCP_TECHTYPE_STR,
163 	.description 		= "Skinny Client Control Protocol (SCCP)",
164 	// we could use the skinny_codec = ast_codec mapping here to generate the list of capabilities
165 //      .capabilities           = AST_FORMAT_SLINEAR16 | AST_FORMAT_SLINEAR | AST_FORMAT_ALAW | AST_FORMAT_ULAW | AST_FORMAT_GSM | AST_FORMAT_G723_1 | AST_FORMAT_G729A,
166 	.properties 		= AST_CHAN_TP_WANTSJITTER | AST_CHAN_TP_CREATESJITTER,
167 	.requester 		= sccp_astwrap_request,
168 	.devicestate 		= sccp_astwrap_devicestate,
169 	.call 			= sccp_astwrap_call,
170 	.hangup 		= sccp_astwrap_hangup,
171 	.answer 		= sccp_astwrap_answer,
172 	.read 			= sccp_astwrap_rtp_read,
173 	.write 			= sccp_astwrap_rtp_write,
174 	.write_video 		= sccp_astwrap_rtp_write,
175 	.indicate 		= sccp_astwrap_indicate,
176 	.fixup 			= sccp_astwrap_fixup,
177 	//.transfer 		= sccp_pbx_transfer,
178 	//.bridge 		= sccp_astwrap_rtpBridge,
179 	.bridge 		= ast_rtp_instance_bridge,
180 	.early_bridge           = ast_rtp_instance_early_bridge,
181 	//.bridged_channel      =
182 
183 	.send_text 		= sccp_pbx_sendtext,
184 	.send_html 		= sccp_pbx_sendHTML,
185 	//.send_html            =
186 	//.send_image           =
187 
188 	.func_channel_read 	= sccp_astgenwrap_channel_read,
189 	.func_channel_write 	= sccp_astgenwrap_channel_write,
190 
191 	.send_digit_begin 	= sccp_wrapper_recvdigit_begin,
192 	.send_digit_end 	= sccp_wrapper_recvdigit_end,
193 
194 	//.write_text           =
195 	//.write_video          =
196 	//.cc_callback          =                                              // ccss, new >1.6.0
197 	//.exception            =                                              // new >1.6.0
198 //      .setoption              = sccp_astwrap_setOption,
199 	//.queryoption          =                                              // new >1.6.0
200 	//.get_pvt_uniqueid     = sccp_pbx_get_callid,                         // new >1.6.0
201 	//.get_base_channel     =
202 	//.set_base_channel     =
203 	/* *INDENT-ON* */
204 };
205 
206 #endif
207 
sccp_astwrap_devicestate(void * data)208 static int sccp_astwrap_devicestate(void *data)
209 {
210 	int res = AST_DEVICE_UNKNOWN;
211 	char *lineName = (char *) data;
212 	char *deviceId = NULL;
213 	sccp_channelstate_t state;
214 
215 	if ((deviceId = strchr(lineName, '@'))) {
216 		*deviceId = '\0';
217 		deviceId++;
218 	}
219 
220 	state = sccp_hint_getLinestate(lineName, deviceId);
221 	sccp_log((DEBUGCAT_HINT)) (VERBOSE_PREFIX_4 "SCCP: (devicestate) sccp_hint returned state:%s for '%s'\n", sccp_channelstate2str(state), lineName);
222 	switch (state) {
223 		case SCCP_CHANNELSTATE_DOWN:
224 		case SCCP_CHANNELSTATE_ONHOOK:
225 			res = AST_DEVICE_NOT_INUSE;
226 			break;
227 		case SCCP_CHANNELSTATE_RINGING:
228 			res = AST_DEVICE_RINGING;
229 			break;
230 		case SCCP_CHANNELSTATE_HOLD:
231 			res = AST_DEVICE_ONHOLD;
232 			break;
233 		case SCCP_CHANNELSTATE_INVALIDNUMBER:
234 			res = AST_DEVICE_INVALID;
235 			break;
236 		case SCCP_CHANNELSTATE_BUSY:
237 			res = AST_DEVICE_BUSY;
238 			break;
239 		case SCCP_CHANNELSTATE_DND:
240 			res = AST_DEVICE_BUSY;
241 			break;
242 		case SCCP_CHANNELSTATE_CONGESTION:
243 #ifndef CS_EXPERIMENTAL
244 		case SCCP_CHANNELSTATE_ZOMBIE:
245 		case SCCP_CHANNELSTATE_SPEEDDIAL:
246 		case SCCP_CHANNELSTATE_INVALIDCONFERENCE:
247 #endif
248 			res = AST_DEVICE_UNAVAILABLE;
249 			break;
250 
251 		case SCCP_CHANNELSTATE_RINGOUT:
252 		case SCCP_CHANNELSTATE_RINGOUT_ALERTING:
253 #ifdef CS_EXPERIMENTAL
254 			res = AST_DEVICE_RINGINUSE;
255 			break;
256 #endif
257 		case SCCP_CHANNELSTATE_DIALING:
258 		case SCCP_CHANNELSTATE_DIGITSFOLL:
259 		case SCCP_CHANNELSTATE_PROGRESS:
260 		case SCCP_CHANNELSTATE_CALLWAITING:
261 #ifndef CS_EXPERIMENTAL
262 			res = AST_DEVICE_RINGINUSE;
263 			break;
264 #endif
265 		case SCCP_CHANNELSTATE_CONNECTEDCONFERENCE:
266 		case SCCP_CHANNELSTATE_OFFHOOK:
267 		case SCCP_CHANNELSTATE_GETDIGITS:
268 		case SCCP_CHANNELSTATE_CONNECTED:
269 		case SCCP_CHANNELSTATE_PROCEED:
270 		case SCCP_CHANNELSTATE_BLINDTRANSFER:
271 		case SCCP_CHANNELSTATE_CALLTRANSFER:
272 		case SCCP_CHANNELSTATE_CALLCONFERENCE:
273 		case SCCP_CHANNELSTATE_CALLPARK:
274 		case SCCP_CHANNELSTATE_CALLREMOTEMULTILINE:
275 			res = AST_DEVICE_INUSE;
276 			break;
277 		case SCCP_CHANNELSTATE_SENTINEL:
278 #ifdef CS_EXPERIMENTAL
279 		case SCCP_CHANNELSTATE_SPEEDDIAL:
280 		case SCCP_CHANNELSTATE_INVALIDCONFERENCE:
281 		case SCCP_CHANNELSTATE_ZOMBIE:
282 			res = AST_DEVICE_UNKNOWN;
283 #endif
284 			break;
285 	}
286 
287 	sccp_log((DEBUGCAT_HINT)) (VERBOSE_PREFIX_4 "SCCP: (devicestate) PBX requests state for '%s' - state %s\n", lineName, ast_devstate2str(res));
288 	return res;
289 }
290 
291 /*!
292  * \brief Convert an array of skinny_codecs (enum) to ast_codec_prefs
293  *
294  * \param skinny_codecs Array of Skinny Codecs
295  * \param astCodecPref Array of PBX Codec Preferences
296  *
297  * \return bit array fmt/Format of ast_format_type (int)
298  */
skinny_codecs2pbx_codec_pref(const skinny_codec_t * const codecs,struct ast_codec_pref * astCodecPref)299 int skinny_codecs2pbx_codec_pref(const skinny_codec_t * const codecs, struct ast_codec_pref *astCodecPref)
300 {
301 	struct ast_format *dst = NULL;
302 	uint32_t codec = skinny_codecs2pbx_codecs(codecs);							// convert to bitfield
303 
304 	dst = ast_format_from_old_bitfield(dst, codec);								// convert bitfield to ast_format
305 	return ast_codec_pref_append(astCodecPref, dst);							// return ast_codec_pref
306 }
307 
308 static boolean_t sccp_astwrap_setReadFormat(const sccp_channel_t * channel, skinny_codec_t codec);
309 
310 #define RTP_NEW_SOURCE(_c,_log) 								\
311         if(c->rtp.audio.instance) { 										\
312                 ast_rtp_new_source(c->rtp.audio.instance); 							\
313                 sccp_log((DEBUGCAT_PBX | DEBUGCAT_INDICATE))(VERBOSE_PREFIX_3 "SCCP: " #_log "\n"); 	\
314         }
315 
316 #define RTP_CHANGE_SOURCE(_c,_log) 								\
317         if(c->rtp.audio.instance) {										\
318                 ast_rtp_change_source(c->rtp.audio.instance);						\
319                 sccp_log((DEBUGCAT_PBX | DEBUGCAT_INDICATE))(VERBOSE_PREFIX_3 "SCCP: " #_log "\n"); 	\
320         }
321 
322 // static void get_skinnyFormats(struct ast_format_cap *format, skinny_codec_t codecs[], size_t size)
323 // {
324 //      unsigned int x;
325 //      unsigned len = 0;
326 //
327 //      size_t f_len;
328 //      struct ast_format tmp_fmt;
329 //      const struct ast_format_list *f_list = ast_format_list_get(&f_len);
330 //
331 //      if (!size) {
332 //              f_list = ast_format_list_destroy(f_list);
333 //              return;
334 //      }
335 //
336 //      for (x = 0; x < ARRAY_LEN(pbx2skinny_codec_maps) && len <= size; x++) {
337 //              ast_format_copy(&tmp_fmt, &f_list[x].format);
338 //              if (ast_format_cap_iscompatible(format, &tmp_fmt)) {
339 //                      if (pbx2skinny_codec_maps[x].pbx_codec == ((uint) tmp_fmt.id)) {
340 //                              codecs[len++] = pbx2skinny_codec_maps[x].skinny_codec;
341 //                      }
342 //              }
343 //      }
344 //      f_list = ast_format_list_destroy(f_list);
345 // }
346 
347 /*************************************************************************************************************** CODEC **/
348 
349 /*! \brief Get the name of a format
350  * \note replacement for ast_getformatname
351  * \param format id of format
352  * \return A static string containing the name of the format or "unknown" if unknown.
353  */
pbx_getformatname(const struct ast_format * format)354 const char *pbx_getformatname(const struct ast_format *format)
355 {
356 	return ast_getformatname(format);
357 }
358 
359 /*!
360  * \brief Get the names of a set of formats
361  * \note replacement for ast_getformatname_multiple
362  * \param buf a buffer for the output string
363  * \param size size of buf (bytes)
364  * \param format the format (combined IDs of codecs)
365  * Prints a list of readable codec names corresponding to "format".
366  * ex: for format=AST_FORMAT_GSM|AST_FORMAT_SPEEX|AST_FORMAT_ILBC it will return "0x602 (GSM|SPEEX|ILBC)"
367  * \return The return value is buf.
368  */
pbx_getformatname_multiple(char * buf,size_t size,struct ast_format_cap * format)369 char *pbx_getformatname_multiple(char *buf, size_t size, struct ast_format_cap *format)
370 {
371 	return ast_getformatname_multiple(buf, size, format);
372 }
373 
374 /*!
375  * \brief Read from an Asterisk Channel
376  * \param ast Asterisk Channel as ast_channel
377  *
378  * \called_from_asterisk
379  *
380  * \note not following the refcount rules... channel is already retained
381  */
sccp_astwrap_rtp_read(PBX_CHANNEL_TYPE * ast)382 static PBX_FRAME_TYPE *sccp_astwrap_rtp_read(PBX_CHANNEL_TYPE * ast)
383 {
384 	//AUTO_RELEASE(sccp_channel_t, c , NULL);									// not following the refcount rules... channel is already retained
385 	sccp_channel_t *c = NULL;
386 	PBX_FRAME_TYPE *frame = NULL;
387 
388 	if (!(c = CS_AST_CHANNEL_PVT(ast))) {									// not following the refcount rules... channel is already retained
389 		return &ast_null_frame;
390 	}
391 
392 	if (!c->rtp.audio.instance) {
393 		return &ast_null_frame;
394 	}
395 
396 	switch (ast->fdno) {
397 
398 		case 0:
399 			frame = ast_rtp_instance_read(c->rtp.audio.instance, 0);					/* RTP Audio */
400 			break;
401 		case 1:
402 			frame = ast_rtp_instance_read(c->rtp.audio.instance, 1);					/* RTCP Control Channel */
403 			break;
404 #ifdef CS_SCCP_VIDEO
405 		case 2:
406 			frame = ast_rtp_instance_read(c->rtp.video.instance, 0);					/* RTP Video */
407 			break;
408 		case 3:
409 			frame = ast_rtp_instance_read(c->rtp.video.instance, 1);					/* RTCP Control Channel for video */
410 			break;
411 #endif
412 		default:
413 			break;
414 	}
415 
416 	if (!frame) {
417 		pbx_log(LOG_WARNING, "%s: error reading frame == NULL\n", c->currentDeviceId);
418 		return &ast_null_frame;
419 	}
420 	//sccp_log((DEBUGCAT_CORE))(VERBOSE_PREFIX_3 "%s: read format: ast->fdno: %d, frametype: %d, %s(%d)\n", DEV_ID_LOG(c->device), ast->fdno, frame->frametype, pbx_getformatname(frame->subclass), frame->subclass);
421 	if (frame->frametype == AST_FRAME_VOICE) {
422 #ifdef CS_SCCP_CONFERENCE
423 		if (c->conference && (!ast_format_is_slinear(&ast->readformat))) {
424 			ast_set_read_format(ast, &slinFormat);
425 		} else
426 #endif
427 		{
428 			if (ast_format_cmp(&frame->subclass.format, &ast->rawreadformat) == AST_FORMAT_CMP_NOT_EQUAL) {
429 				ast_format_cap_remove_bytype(ast->nativeformats, AST_FORMAT_TYPE_AUDIO);
430 				ast_format_cap_add(ast->nativeformats, &frame->subclass.format);
431 				ast_set_read_format(ast, &ast->readformat);
432 				ast_set_write_format(ast, &ast->writeformat);
433 				//ast_rtp_instance_set_read_format(channel->rtp.audio.instance, &ast->readformat);
434 				//ast_rtp_instance_set_write_format(channel->rtp.audio.instance, &ast->writeformat);
435 			}
436 		}
437 	}
438 
439 	return frame;
440 }
441 
442 /*!
443  * \brief Find Asterisk/PBX channel by linkid
444  *
445  * \param ast   pbx channel
446  * \param data  linkId as void *
447  *
448  * \return int
449  */
pbx_find_channel_by_linkid(PBX_CHANNEL_TYPE * ast,const void * data)450 static int pbx_find_channel_by_linkid(PBX_CHANNEL_TYPE * ast, const void *data)
451 {
452 	const char *linkId = (char *) data;
453 
454 	if (!data) {
455 		return 0;
456 	}
457 	return !ast->pbx && ast->linkedid && (!strcasecmp(ast->linkedid, linkId)) && !ast->masq;
458 }
459 
asterisk_indication2str(int ind)460 static const char *asterisk_indication2str(int ind)
461 {
462 	switch (ind) {
463 		case AST_CONTROL_HANGUP: return "AST_CONTROL_HANGUP: Other end has hungup";
464 		case AST_CONTROL_RING: return "AST_CONTROL_RING: Local ring";
465 		case AST_CONTROL_RINGING: return "AST_CONTROL_RINGING: Remote end is ringing";
466 		case AST_CONTROL_ANSWER: return "AST_CONTROL_ANSWER: Remote end has answered";
467 		case AST_CONTROL_BUSY: return "AST_CONTROL_BUSY: Remote end is busy";
468 		case AST_CONTROL_TAKEOFFHOOK: return "AST_CONTROL_TAKEOFFHOOK: Make it go off hook";
469 		case AST_CONTROL_OFFHOOK: return "AST_CONTROL_OFFHOOK: Line is off hook";
470 		case AST_CONTROL_CONGESTION: return "AST_CONTROL_CONGESTION: Congestion (circuits busy)";
471 		case AST_CONTROL_FLASH: return "AST_CONTROL_FLASH: Flash hook";
472 		case AST_CONTROL_WINK: return "AST_CONTROL_WINK: Wink";
473 		case AST_CONTROL_OPTION: return "AST_CONTROL_OPTION: Set a low-level option";
474 		case AST_CONTROL_RADIO_KEY: return "AST_CONTROL_RADIO_KEY: Key Radio";
475 		case AST_CONTROL_RADIO_UNKEY: return "AST_CONTROL_RADIO_UNKEY: Un-Key Radio";
476 		case AST_CONTROL_PROGRESS: return "AST_CONTROL_PROGRESS: Indicate PROGRESS";
477 		case AST_CONTROL_PROCEEDING: return "AST_CONTROL_PROCEEDING: Indicate CALL PROCEEDING";
478 		case AST_CONTROL_HOLD: return "AST_CONTROL_HOLD: Indicate call is placed on hold";
479 		case AST_CONTROL_UNHOLD: return "AST_CONTROL_UNHOLD: Indicate call left hold";
480 		case AST_CONTROL_VIDUPDATE: return "AST_CONTROL_VIDUPDATE: Indicate video frame update";
481 		case _XXX_AST_CONTROL_T38: return "_XXX_AST_CONTROL_T38: T38 state change request/notification. Deprecated This is no longer supported. Use AST_CONTROL_T38_PARAMETERS instead.";
482 		case AST_CONTROL_SRCUPDATE: return "AST_CONTROL_SRCUPDATE: Indicate source of media has changed";
483 		case AST_CONTROL_TRANSFER: return "AST_CONTROL_TRANSFER: Indicate status of a transfer request";
484 		case AST_CONTROL_CONNECTED_LINE: return "AST_CONTROL_CONNECTED_LINE: Indicate connected line has changed";
485 		case AST_CONTROL_REDIRECTING: return "AST_CONTROL_REDIRECTING: Indicate redirecting id has changed";
486 		case AST_CONTROL_T38_PARAMETERS: return "AST_CONTROL_T38_PARAMETERS: T38 state change request/notification with parameters";
487 		case AST_CONTROL_CC: return "AST_CONTROL_CC: Indication that Call completion service is possible";
488 		case AST_CONTROL_SRCCHANGE: return "AST_CONTROL_SRCCHANGE: Media source has changed and requires a new RTP SSRC";
489 		case AST_CONTROL_READ_ACTION: return "AST_CONTROL_READ_ACTION: Tell ast_read to take a specific action";
490 		case AST_CONTROL_AOC: return "AST_CONTROL_AOC: Advice of Charge with encoded generic AOC payload";
491 		case AST_CONTROL_END_OF_Q: return "AST_CONTROL_END_OF_Q: Indicate that this position was the end of the channel queue for a softhangup.";
492 		case AST_CONTROL_INCOMPLETE: return "AST_CONTROL_INCOMPLETE: Indication that the extension dialed is incomplete";
493 		case AST_CONTROL_MCID: return "AST_CONTROL_MCID: Indicate that the caller is being malicious.";
494 		case AST_CONTROL_UPDATE_RTP_PEER: return "AST_CONTROL_UPDATE_RTP_PEER: Interrupt the bridge and have it update the peer";
495 		case -1: return "AST_CONTROL_PROD: Kick remote channel";
496 	}
497 	return "Unknown/Unhandled/IAX Indication";
498 }
499 
sccp_astwrap_indicate(PBX_CHANNEL_TYPE * ast,int ind,const void * data,size_t datalen)500 static int sccp_astwrap_indicate(PBX_CHANNEL_TYPE * ast, int ind, const void *data, size_t datalen)
501 {
502 	int res = 0;
503 
504 	AUTO_RELEASE(sccp_channel_t, c , get_sccp_channel_from_pbx_channel(ast));
505 	if (!c) {
506 		sccp_log((DEBUGCAT_PBX | DEBUGCAT_CHANNEL | DEBUGCAT_INDICATE)) (VERBOSE_PREFIX_3 "SCCP: (pbx_indicate) no sccp channel yet\n");
507 		return -1;
508 	}
509 	sccp_log((DEBUGCAT_PBX | DEBUGCAT_CHANNEL | DEBUGCAT_INDICATE)) (VERBOSE_PREFIX_3 "%s: (pbx_indicate) start indicate '%s'\n", c->designator, asterisk_indication2str(ind));
510 
511 	AUTO_RELEASE(sccp_device_t, d , sccp_channel_getDevice(c));
512 	if (!d || c->state == SCCP_CHANNELSTATE_DOWN) {
513 		//sccp_log((DEBUGCAT_PBX | DEBUGCAT_CHANNEL | DEBUGCAT_INDICATE)) (VERBOSE_PREFIX_3 "SCCP: (pbx_indicate) no sccp device yet\n");
514 		switch (ind) {
515 			case AST_CONTROL_CONNECTED_LINE:
516 				sccp_astwrap_connectedline(c, data, datalen);
517 				res = 0;
518 				break;
519 			case AST_CONTROL_REDIRECTING:
520 				sccp_astwrap_redirectedUpdate(c, data, datalen);
521 				res = 0;
522 				break;
523 			default:
524 				res = -1;
525 				break;
526 		}
527 		return res;
528 	}
529 
530 
531 	/* when the rtp media stream is open we will let asterisk emulate the tones */
532 	res = (((c->rtp.audio.reception.state != SCCP_RTP_STATUS_INACTIVE) || (d && d->earlyrtp)) ? -1 : 0);
533 	sccp_log((DEBUGCAT_PBX | DEBUGCAT_CHANNEL | DEBUGCAT_INDICATE)) (VERBOSE_PREFIX_3 "%s: (pbx_indicate) start indicate '%s' (%d) condition on channel %s (readStat:%d, reception.state:%d, rtp:%s, default res:%s (%d))\n", DEV_ID_LOG(d), asterisk_indication2str(ind), ind, pbx_channel_name(ast), c->rtp.audio.reception.state, c->rtp.audio.reception.state, (c->rtp.audio.instance) ? "yes" : "no", res ? "inband signaling" : "outofband signaling", res);
534 
535 	switch (ind) {
536 		case AST_CONTROL_RINGING:
537 			if (SKINNY_CALLTYPE_OUTBOUND == c->calltype && pbx_channel_state(c->owner) !=  AST_STATE_UP) {
538 				// Allow signalling of RINGOUT only on outbound calls.
539 				// Otherwise, there are some issues with late arrival of ringing
540 				// indications on ISDN calls (chan_lcr, chan_dahdi) (-DD).
541 				sccp_indicate(d, c, SCCP_CHANNELSTATE_RINGOUT);
542 				iPbx.set_callstate(c, AST_STATE_RING);
543 				struct ast_channel_iterator *iterator = ast_channel_iterator_all_new();
544 
545 				((struct ao2_iterator *) iterator)->flags |= AO2_ITERATOR_DONTLOCK;
546 
547 				/*! \todo handle multiple remotePeers i.e. DIAL(SCCP/400&SIP/300), find smallest common codecs, what order to use ? */
548 				PBX_CHANNEL_TYPE *remotePeer;
549 
550 				for (; (remotePeer = ast_channel_iterator_next(iterator)); remotePeer = pbx_channel_unref(remotePeer)) {
551 					if (pbx_find_channel_by_linkid(remotePeer, (void *) ast->linkedid)) {
552 						char buf[512];
553 
554 						AUTO_RELEASE(sccp_channel_t, remoteSccpChannel , get_sccp_channel_from_pbx_channel(remotePeer));
555 						if (remoteSccpChannel) {
556 							sccp_codec_multiple2str(buf, sizeof(buf) - 1, remoteSccpChannel->preferences.audio, ARRAY_LEN(remoteSccpChannel->preferences.audio));
557 							sccp_log(DEBUGCAT_CODEC) (VERBOSE_PREFIX_4 "remote preferences: %s\n", buf);
558 							uint8_t x, y, z;
559 
560 							z = 0;
561 							for (x = 0; x < SKINNY_MAX_CAPABILITIES && remoteSccpChannel->preferences.audio[x] != 0; x++) {
562 								for (y = 0; y < SKINNY_MAX_CAPABILITIES && remoteSccpChannel->capabilities.audio[y] != 0; y++) {
563 									if (remoteSccpChannel->preferences.audio[x] == remoteSccpChannel->capabilities.audio[y]) {
564 										c->remoteCapabilities.audio[z++] = remoteSccpChannel->preferences.audio[x];
565 										break;
566 									}
567 								}
568 							}
569 						} else {
570 							sccp_log(DEBUGCAT_CODEC) (VERBOSE_PREFIX_4 "remote nativeformats: %s\n", pbx_getformatname_multiple(buf, sizeof(buf) - 1, remotePeer->nativeformats));
571 							sccp_astwrap_getSkinnyFormatMultiple(remotePeer->nativeformats, c->remoteCapabilities.audio, ARRAY_LEN(c->remoteCapabilities.audio));
572 						}
573 
574 						sccp_codec_multiple2str(buf, sizeof(buf) - 1, c->remoteCapabilities.audio, ARRAY_LEN(c->remoteCapabilities.audio));
575 						sccp_log(DEBUGCAT_CODEC) (VERBOSE_PREFIX_4 "remote caps: %s\n", buf);
576 						remotePeer = pbx_channel_unref(remotePeer);
577 						break;
578 					}
579 
580 				}
581 				ast_channel_iterator_destroy(iterator);
582 			}
583 			break;
584 		case AST_CONTROL_BUSY:
585 			sccp_indicate(d, c, SCCP_CHANNELSTATE_BUSY);
586 			iPbx.set_callstate(c, AST_STATE_BUSY);
587 			break;
588 		case AST_CONTROL_CONGESTION:
589 			sccp_indicate(d, c, SCCP_CHANNELSTATE_CONGESTION);
590 			break;
591 		case AST_CONTROL_PROGRESS:
592 			sccp_indicate(d, c, SCCP_CHANNELSTATE_PROGRESS);
593 			res = 0;
594 			break;
595 		case AST_CONTROL_PROCEEDING:
596 			sccp_indicate(d, c, SCCP_CHANNELSTATE_PROCEED);
597 			res = 0;
598 			break;
599 		case AST_CONTROL_SRCCHANGE:
600 			if (c->rtp.audio.instance) {
601 				ast_rtp_instance_change_source(c->rtp.audio.instance);
602 			}
603 			res = 0;
604 			break;
605 
606 		case AST_CONTROL_SRCUPDATE:
607 			/* Source media has changed. */
608 			sccp_log((DEBUGCAT_PBX | DEBUGCAT_INDICATE)) (VERBOSE_PREFIX_3 "SCCP: Source UPDATE request\n");
609 
610 			if (c->rtp.audio.instance) {
611 				ast_rtp_instance_change_source(c->rtp.audio.instance);
612 			}
613 
614 		/** this is a dirty workaround to fix audio issue while pickup a parked call
615 		 * reason: asterisk do not indicate connected if we dial to a parked extension
616 		 * -MC
617 		 */
618 			if (c->state != SCCP_CHANNELSTATE_CONNECTED) {
619 				sccp_log((DEBUGCAT_PBX | DEBUGCAT_INDICATE)) (VERBOSE_PREFIX_3 "SCCP: force CONNECT\n");
620 				sccp_indicate(d, c, SCCP_CHANNELSTATE_CONNECTED);
621 			}
622 			res = 0;
623 			break;
624 
625 			/* when the bridged channel hold/unhold the call we are notified here */
626 		case AST_CONTROL_HOLD:
627 			if (c->rtp.audio.instance) {
628 				ast_rtp_instance_update_source(c->rtp.audio.instance);
629 			}
630 #ifdef CS_SCCP_VIDEO
631 			if (c->rtp.video.instance && d && sccp_device_isVideoSupported(d) && sccp_channel_getVideoMode(c) != SCCP_VIDEO_MODE_OFF) {
632 				ast_rtp_instance_update_source(c->rtp.video.instance);
633 				d->protocol->sendMultiMediaCommand(d, c, SKINNY_MISCCOMMANDTYPE_VIDEOFREEZEPICTURE);
634 			}
635 #endif
636 			sccp_astwrap_moh_start(ast, (const char *) data, c->musicclass);
637 			res = 0;
638 			break;
639 		case AST_CONTROL_UNHOLD:
640  			if (c->rtp.audio.instance) {
641  				ast_rtp_instance_update_source(c->rtp.audio.instance);
642  			}
643 #ifdef CS_SCCP_VIDEO
644 			if (c->rtp.video.instance && d && sccp_device_isVideoSupported(d) && sccp_channel_getVideoMode(c) != SCCP_VIDEO_MODE_OFF) {
645 				ast_rtp_instance_update_source(c->rtp.video.instance);
646 				d->protocol->sendMultiMediaCommand(d, c, SKINNY_MISCCOMMANDTYPE_VIDEOFASTUPDATEPICTURE);
647 			};
648 #endif
649 			sccp_astwrap_moh_stop(ast);
650 			res = 0;
651 			break;
652 
653 		case AST_CONTROL_CONNECTED_LINE:
654 			/* remarking out this code, as it is causing issues with callforward + FREEPBX,  the calling party will not hear the remote end ringing
655 			 this patch was added to suppress 'double callwaiting tone', but channel PROD(-1) below is taking care of that already
656 			*/
657 			//if (c->calltype == SKINNY_CALLTYPE_OUTBOUND && c->rtp.audio.reception.state == SCCP_RTP_STATUS_INACTIVE && c->state > SCCP_CHANNELSTATE_DIALING) {
658 			//	sccp_channel_openReceiveChannel(c);
659 			//}
660 			sccp_astwrap_connectedline(c, data, datalen);
661 			res = 0;
662 			break;
663 
664 		case AST_CONTROL_TRANSFER:
665 			ast_log(LOG_NOTICE, "%s: Ast Control Transfer: %d", c->designator, *(int *)data);
666 			//sccp_astwrap_connectedline(c, data, datalen);
667 			res = 0;
668 			break;
669 
670 		case AST_CONTROL_REDIRECTING:
671 			sccp_astwrap_redirectedUpdate(c, data, datalen);
672 			sccp_indicate(d, c, c->state);
673 			res = 0;
674 			break;
675 
676 		case AST_CONTROL_VIDUPDATE:									/* Request a video frame update */
677 #ifdef CS_SCCP_VIDEO
678 			if (c->rtp.video.instance && d && sccp_device_isVideoSupported(d) && sccp_channel_getVideoMode(c) != SCCP_VIDEO_MODE_OFF) {
679 				d->protocol->sendMultiMediaCommand(d, c, SKINNY_MISCCOMMANDTYPE_VIDEOFASTUPDATEPICTURE);
680 				res = 0;
681 			} else
682 #endif
683 			{
684 				res = -1;
685 			}
686 			break;
687 #ifdef CS_AST_CONTROL_INCOMPLETE
688 		case AST_CONTROL_INCOMPLETE:									/*!< Indication that the extension dialed is incomplete */
689 			/* \todo implement dial continuation by:
690 			 *  - display message incomplete number
691 			 *  - adding time to channel->scheduler.digittimeout
692 			 *  - rescheduling sccp_pbx_sched_dial
693 			 */
694 			res = 0;
695 			break;
696 #endif
697 		case -1:											// Asterisk prod the channel
698 			if (	c->line &&
699 				c->state > SCCP_GROUPED_CHANNELSTATE_DIALING &&
700 				c->calltype == SKINNY_CALLTYPE_OUTBOUND &&
701 				c->rtp.audio.reception.state == SCCP_RTP_STATUS_INACTIVE &&
702 				!ast->hangupcause
703 			) {
704 				sccp_channel_openReceiveChannel(c);
705 				uint8_t instance = sccp_device_find_index_for_line(d, c->line->name);
706 				sccp_dev_stoptone(d, instance, c->callid);
707 			}
708 			res = -1;
709 			break;
710 		default:
711 			sccp_log((DEBUGCAT_PBX | DEBUGCAT_INDICATE)) (VERBOSE_PREFIX_3 "%s: (pbx_indicate) Don't know how to indicate condition '%s' (%d)\n", DEV_ID_LOG(d), asterisk_indication2str(ind), ind);
712 			break;
713 	}
714 	sccp_log((DEBUGCAT_PBX | DEBUGCAT_INDICATE)) (VERBOSE_PREFIX_2 "%s: (pbx_indicate) finish: send indication '%s' (%d)\n", DEV_ID_LOG(d), res ? "inband signaling" : "outofband signaling", res);
715 	return res;
716 }
717 
718 /*!
719  * \brief Write to an Asterisk Channel
720  * \param ast Channel as ast_channel
721  * \param frame Frame as ast_frame
722  *
723  * \called_from_asterisk
724  *
725  * \note not following the refcount rules... channel is already retained
726  */
sccp_astwrap_rtp_write(PBX_CHANNEL_TYPE * ast,PBX_FRAME_TYPE * frame)727 static int sccp_astwrap_rtp_write(PBX_CHANNEL_TYPE * ast, PBX_FRAME_TYPE * frame)
728 {
729 	//AUTO_RELEASE(sccp_channel_t, c , NULL);									// not following the refcount rules... channel is already retained
730 	sccp_channel_t *c = NULL;
731 	int res = 0;
732 
733 	if (!(c = CS_AST_CHANNEL_PVT(ast))) {									// not following the refcount rules... channel is already retained
734 		return -1;
735 	}
736 
737 	switch (frame->frametype) {
738 		case AST_FRAME_VOICE:
739 			// checking for samples to transmit
740 			if(pbx_channel_state(c->owner) != AST_STATE_UP && c->wantsEarlyRTP() && !c->progressSent()) {
741 				sccp_log(DEBUGCAT_RTP)(VERBOSE_PREFIX_3 "%s: (rtp_write) device requested earlyRtp and we received an incoming packet calling makeProgress\n", c->designator);
742 				c->makeProgress(c);
743 			}
744 			if (!frame->samples) {
745 				if(!strcasecmp(frame->src, "ast_prod")) {
746 					sccp_log((DEBUGCAT_PBX | DEBUGCAT_CHANNEL))(VERBOSE_PREFIX_3 "%s: Asterisk prodded channel %s.\n", c->currentDeviceId, pbx_channel_name(ast));
747 				} else {
748 					pbx_log(LOG_NOTICE, "%s: Asked to transmit frame type %d ('%s') with no samples.\n", c->currentDeviceId, (int)frame->frametype, frame->src);
749 				}
750 				break;
751 			}
752 			if (c->rtp.audio.instance) {
753 				res = ast_rtp_instance_write(c->rtp.audio.instance, frame);
754 			}
755 			break;
756 		case AST_FRAME_IMAGE:
757 		case AST_FRAME_VIDEO:
758 #ifdef CS_SCCP_VIDEO
759 			if (c->rtp.video.reception.state == SCCP_RTP_STATUS_INACTIVE && c->rtp.video.instance && c->state != SCCP_CHANNELSTATE_HOLD
760 			    //      && (c->device->capability & frame->subclass)
761 			    ) {
762 				// int codec = pbx_codec2skinny_codec((frame->subclass.codec & AST_FORMAT_VIDEO_MASK));
763 				int codec = pbx_codec2skinny_codec((frame->frametype == AST_FRAME_VIDEO));
764 
765 				sccp_log((DEBUGCAT_RTP)) (VERBOSE_PREFIX_3 "%s: got video frame %d\n", c->currentDeviceId, codec);
766 				if (0 != codec) {
767 					c->rtp.video.reception.format = codec;
768 					sccp_channel_openMultiMediaReceiveChannel(c);
769 				}
770 			}
771 
772 			if (c->rtp.video.instance && (c->rtp.video.reception.state & SCCP_RTP_STATUS_ACTIVE) != 0) {
773 				res = ast_rtp_instance_write(c->rtp.video.instance, frame);
774 			}
775 #endif
776 			break;
777 		case AST_FRAME_TEXT:
778 		case AST_FRAME_MODEM:
779 		default:
780 			pbx_log(LOG_WARNING, "%s: Can't send %d type frames with SCCP write on channel %s\n", c->currentDeviceId, frame->frametype, ast->name);
781 			break;
782 	}
783 	return res;
784 }
785 
sccp_astwrap_setCalleridPresentation(PBX_CHANNEL_TYPE * pbx_channel,sccp_callerid_presentation_t presentation)786 static void sccp_astwrap_setCalleridPresentation(PBX_CHANNEL_TYPE *pbx_channel, sccp_callerid_presentation_t presentation)
787 {
788 	if (pbx_channel && CALLERID_PRESENTATION_FORBIDDEN == presentation) {
789 		pbx_channel->caller.id.name.presentation |= AST_PRES_PROHIB_USER_NUMBER_NOT_SCREENED;
790 		pbx_channel->caller.id.number.presentation |= AST_PRES_PROHIB_USER_NUMBER_NOT_SCREENED;
791 	}
792 }
793 
sccp_astwrap_setNativeAudioFormats(const sccp_channel_t * channel,skinny_codec_t codecs[])794 static int sccp_astwrap_setNativeAudioFormats(const sccp_channel_t * channel, skinny_codec_t codecs[])
795 {
796 	struct ast_format fmt;
797 	int i;
798 	if (!channel || !channel->owner || !channel->owner->nativeformats) {
799 		pbx_log(LOG_ERROR, "SCCP: (sccp_wrapper_asterisk110_setNativeAudioFormats) no channel provided!\n");
800 		return 0;
801 	}
802 
803 	int length = 1;
804 	ast_debug(10, "%s: set native Formats length: %d\n", (char *) channel->currentDeviceId, length);
805 
806 	ast_format_cap_remove_bytype(channel->owner->nativeformats, AST_FORMAT_TYPE_AUDIO);
807 	for (i = 0; i < length; i++) {
808 		ast_format_set(&fmt, skinny_codec2pbx_codec(codecs[i]), 0);
809 		ast_format_cap_add(channel->owner->nativeformats, &fmt);
810 	}
811 	return 1;
812 }
813 
sccp_astwrap_setNativeVideoFormats(const sccp_channel_t * channel,skinny_codec_t codecs[])814 static int sccp_astwrap_setNativeVideoFormats(const sccp_channel_t * channel, skinny_codec_t codecs[])
815 {
816 	return 1;
817 }
818 
sccp_astwrap_removeTimingFD(PBX_CHANNEL_TYPE * ast)819 static void sccp_astwrap_removeTimingFD(PBX_CHANNEL_TYPE *ast)
820 {
821 	if (ast) {
822 		struct ast_timer *timer=ast->timer;
823 		if (timer) {
824 			//ast_log(LOG_NOTICE, "%s: (clean_timer_fds) timername: %s, fd:%d\n", ast->name, ast_timer_get_name(timer), ast_timer_fd(timer));
825 			ast_timer_disable_continuous(timer);
826 			ast_timer_close(timer);
827 			ast_channel_set_fd(ast, AST_TIMING_FD, -1);
828 		}
829 	}
830 }
831 
sccp_astwrap_setOwner(sccp_channel_t * channel,PBX_CHANNEL_TYPE * pbx_channel)832 static void sccp_astwrap_setOwner(sccp_channel_t * channel, PBX_CHANNEL_TYPE * pbx_channel)
833 {
834 	PBX_CHANNEL_TYPE *prev_owner = channel->owner;
835 
836 	if (pbx_channel) {
837 		channel->owner = pbx_channel_ref(pbx_channel);
838 		ast_module_ref(ast_module_info->self);
839 	} else {
840 		channel->owner = NULL;
841 	}
842 	if (prev_owner) {
843 		pbx_channel_unref(prev_owner);
844 		ast_module_unref(ast_module_info->self);
845 	}
846 }
847 
__sccp_astwrap_updateConnectedLine(PBX_CHANNEL_TYPE * pbx_channel,const char * number,const char * name,uint8_t reason)848 static void __sccp_astwrap_updateConnectedLine(PBX_CHANNEL_TYPE *pbx_channel, const char *number, const char *name, uint8_t reason)
849 {
850 	if (!pbx_channel) {
851 		return;
852 	}
853 	struct ast_party_connected_line connected;
854 	struct ast_set_party_connected_line update_connected = {{0}};
855 
856 	ast_party_connected_line_init(&connected);
857 	if (number) {
858 		update_connected.id.number = 1;
859 		connected.id.number.valid = 1;
860 		connected.id.number.str = pbx_strdupa(number);
861 		connected.id.number.presentation = AST_PRES_ALLOWED_NETWORK_NUMBER;
862 	}
863 	if (name) {
864 		update_connected.id.name = 1;
865 		connected.id.name.valid = 1;
866 		connected.id.name.str = pbx_strdupa(name);
867 		connected.id.name.presentation = AST_PRES_ALLOWED_NETWORK_NUMBER;
868 	}
869 	if (update_connected.id.number || update_connected.id.name) {
870 		//ast_set_party_id_all(&update_connected.priv);
871 		// connected.id.tag = NULL;
872 		connected.source = reason;
873 		ast_channel_queue_connected_line_update(pbx_channel, &connected, &update_connected);
874 		sccp_log((DEBUGCAT_PBX)) (VERBOSE_PREFIX_3 "SCCP: do connected line for line '%s', name: %s ,num: %s\n", pbx_channel_name(pbx_channel), name ? name : "(NULL)", number ? number : "(NULL)");
875 	}
876 }
877 
sccp_astwrap_allocPBXChannel(sccp_channel_t * channel,const void * ids,const PBX_CHANNEL_TYPE * pbxSrcChannel,PBX_CHANNEL_TYPE ** _pbxDstChannel)878 static boolean_t sccp_astwrap_allocPBXChannel(sccp_channel_t * channel, const void *ids, const PBX_CHANNEL_TYPE * pbxSrcChannel, PBX_CHANNEL_TYPE ** _pbxDstChannel)
879 {
880 	const char *linkedId = ids ? pbx_strdupa(ids) : NULL;
881 	PBX_CHANNEL_TYPE *pbxDstChannel = NULL;
882 	if (!channel || !channel->line) {
883 		return FALSE;
884 	}
885 	AUTO_RELEASE(sccp_line_t, line , sccp_line_retain(channel->line));
886 	if (!line) {
887 		return FALSE;
888 	}
889 
890 	pbxDstChannel = ast_channel_alloc(0, AST_STATE_DOWN, channel->line->cid_num, channel->line->cid_name, channel->line->accountcode, channel->dialedNumber, channel->line->context, linkedId, channel->line->amaflags, "SCCP/%s-%08X", channel->line->name, channel->callid);
891 
892 	if (pbxDstChannel == NULL) {
893 		return FALSE;
894 	}
895 
896 	pbxDstChannel->tech = &sccp_tech;
897 	pbxDstChannel->tech_pvt = sccp_channel_retain(channel);
898 
899 	/* Copy Codec from SrcChannel */
900 	struct ast_format tmpfmt;
901 
902 	if (!pbxSrcChannel || ast_format_cap_is_empty(pbx_channel_nativeformats(pbxSrcChannel))) {
903 		ast_format_set(&tmpfmt, AST_FORMAT_ULAW, 0);
904 	} else {
905 		ast_best_codec(pbx_channel_nativeformats(pbxSrcChannel), &tmpfmt);
906 	}
907 	ast_format_cap_add(pbxDstChannel->nativeformats, &tmpfmt);
908 	ast_set_read_format(pbxDstChannel, &tmpfmt);
909 	ast_set_write_format(pbxDstChannel, &tmpfmt);
910 	/* EndCodec */
911 
912 	memset(pbxDstChannel->exten, 0, sizeof(pbxDstChannel->exten));
913 	pbxDstChannel->priority = 1;
914 	pbxDstChannel->adsicpe = AST_ADSI_UNAVAILABLE;
915 
916 	sccp_copy_string(pbxDstChannel->context, line->context, sizeof(pbxDstChannel->context));
917 
918 	if (!sccp_strlen_zero(line->language)) {
919 		ast_string_field_set(pbxDstChannel, language, line->language);
920 	}
921 	if (!sccp_strlen_zero(line->accountcode)) {
922 		ast_string_field_set(pbxDstChannel, accountcode, line->accountcode);
923 	}
924 	if (!sccp_strlen_zero(line->musicclass)) {
925 		ast_string_field_set(pbxDstChannel, musicclass, line->musicclass);
926 	}
927 	if (line->amaflags) {
928 		pbxDstChannel->amaflags = line->amaflags;
929 	}
930 	if (line->callgroup) {
931 		pbxDstChannel->callgroup = line->callgroup;
932 	}
933 #if CS_SCCP_PICKUP
934 	if (line->pickupgroup) {
935 		pbxDstChannel->pickupgroup = line->pickupgroup;
936 	}
937 #endif
938 	if (!sccp_strlen_zero(line->parkinglot)) {
939 		ast_string_field_set(pbxDstChannel, parkinglot, line->parkinglot);
940 	}
941 
942 	/** the the tonezone using language information */
943 	if (!sccp_strlen_zero(line->language) && ast_get_indication_zone(line->language)) {
944 		pbxDstChannel->zone = ast_get_indication_zone(line->language);					/* this will core asterisk on hangup */
945 	}
946 	sccp_astwrap_setOwner(channel, pbxDstChannel);
947 
948 	(*_pbxDstChannel) = pbxDstChannel;
949 
950 	return TRUE;
951 }
952 
sccp_astwrap_masqueradeHelper(PBX_CHANNEL_TYPE * pbxChannel,PBX_CHANNEL_TYPE * pbxTmpChannel)953 static boolean_t sccp_astwrap_masqueradeHelper(PBX_CHANNEL_TYPE * pbxChannel, PBX_CHANNEL_TYPE * pbxTmpChannel)
954 {
955 	pbx_moh_stop(pbxChannel);
956 	// Masquerade setup and execution must be done without any channel locks held
957 	if (pbx_channel_masquerade(pbxTmpChannel, pbxChannel)) {
958 		return FALSE;
959 	}
960 	//pbxTmpChannel->_state = AST_STATE_UP;
961 	pbx_do_masquerade(pbxTmpChannel);
962 
963 	// when returning from bridge, the channel will continue at the next priority
964 	// ast_explicit_goto(pbxTmpChannel, pbx_channel_context(pbxTmpChannel), pbx_channel_exten(pbxTmpChannel), pbx_channel_priority(pbxTmpChannel) + 1);
965 	return TRUE;
966 }
967 
sccp_astwrap_allocTempPBXChannel(PBX_CHANNEL_TYPE * pbxSrcChannel,PBX_CHANNEL_TYPE ** _pbxDstChannel)968 static boolean_t sccp_astwrap_allocTempPBXChannel(PBX_CHANNEL_TYPE * pbxSrcChannel, PBX_CHANNEL_TYPE ** _pbxDstChannel)
969 {
970 	struct ast_format tmpfmt;
971 	PBX_CHANNEL_TYPE *pbxDstChannel = NULL;
972 
973 	if (!pbxSrcChannel) {
974 		pbx_log(LOG_ERROR, "SCCP: (alloc_conferenceTempPBXChannel) no pbx channel provided\n");
975 		return FALSE;
976 	}
977 	pbxDstChannel = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, pbxSrcChannel->accountcode, pbxSrcChannel->exten, pbxSrcChannel->context, pbxSrcChannel->linkedid, pbxSrcChannel->amaflags, "TMP/%s", pbxSrcChannel->name);
978 	if (pbxDstChannel == NULL) {
979 		pbx_log(LOG_ERROR, "SCCP: (alloc_conferenceTempPBXChannel) create pbx channel failed\n");
980 		return FALSE;
981 	}
982 
983 	ast_channel_lock(pbxSrcChannel);
984 
985 	if (ast_format_cap_is_empty(pbxSrcChannel->nativeformats)) {
986 		ast_format_set(&tmpfmt, AST_FORMAT_ULAW, 0);
987 	} else {
988 		ast_best_codec(pbxSrcChannel->nativeformats, &tmpfmt);
989 	}
990 	ast_format_cap_add(pbxDstChannel->nativeformats, &tmpfmt);
991 	ast_set_read_format(pbxDstChannel, &tmpfmt);
992 	ast_set_write_format(pbxDstChannel, &tmpfmt);
993 
994 	sccp_copy_string(pbxDstChannel->context, pbxSrcChannel->context, sizeof(pbxDstChannel->context));
995 	sccp_copy_string(pbxDstChannel->exten, pbxSrcChannel->exten, sizeof(pbxDstChannel->exten));
996 	pbxDstChannel->priority = pbxSrcChannel->priority;
997 	ast_channel_unlock(pbxSrcChannel);
998 
999 	(*_pbxDstChannel) = pbxDstChannel;
1000 	return TRUE;
1001 }
1002 
sccp_astwrap_requestAnnouncementChannel(pbx_format_enum_type format,const PBX_CHANNEL_TYPE * requestor,void * data)1003 static PBX_CHANNEL_TYPE *sccp_astwrap_requestAnnouncementChannel(pbx_format_enum_type format, const PBX_CHANNEL_TYPE * requestor, void *data)
1004 {
1005 	PBX_CHANNEL_TYPE *chan;
1006 	int cause;
1007 	struct ast_format_cap *cap;
1008 	struct ast_format tmpfmt;
1009 
1010 	if (!(cap = ast_format_cap_alloc_nolock())) {
1011 		return 0;
1012 	}
1013 	ast_format_cap_add(cap, ast_format_set(&tmpfmt, format, 0));
1014 	if (!(chan = ast_request("Bridge", cap, NULL, "", &cause))) {
1015 		pbx_log(LOG_ERROR, "SCCP: Requested channel could not be created, cause: %d\n", cause);
1016 		cap = ast_format_cap_destroy(cap);
1017 		return NULL;
1018 	}
1019 	cap = ast_format_cap_destroy(cap);
1020 	return chan;
1021 }
1022 
sccp_astwrap_hangup(PBX_CHANNEL_TYPE * ast_channel)1023 int sccp_astwrap_hangup(PBX_CHANNEL_TYPE * ast_channel)
1024 {
1025 	AUTO_RELEASE(sccp_channel_t, c , get_sccp_channel_from_pbx_channel(ast_channel));
1026 	int res = -1;
1027 
1028 	if (c) {
1029 		sccp_mutex_lock(&c->lock);
1030 		if (pbx_channel_hangupcause(ast_channel) == AST_CAUSE_ANSWERED_ELSEWHERE) {
1031 			sccp_log((DEBUGCAT_CORE)) (VERBOSE_PREFIX_3 "SCCP: This call was answered elsewhere\n");
1032 			c->answered_elsewhere = TRUE;
1033 		}
1034 		/* postponing pbx_channel_unref to sccp_channel destructor */
1035 		AUTO_RELEASE(sccp_channel_t, channel , sccp_pbx_hangup(c));					/* explicit release from unretained channel returned by sccp_pbx_hangup */
1036 		(void) channel;											// suppress unused variable warning
1037 		sccp_mutex_unlock(&c->lock);
1038 		ast_channel->tech_pvt = NULL;
1039 	} else {												// after this moment c might have gone already
1040 		ast_channel->tech_pvt = NULL;
1041 		pbx_channel_unref(ast_channel);									// strange unknown channel, why did we get called to hang it up ?
1042 	}
1043 	return res;
1044 }
1045 
1046 /*!
1047  * \brief Park the bridge channel of hostChannel
1048  * This function prepares the host and the bridged channel to be ready for parking.
1049  * It clones the pbx channel of both sides forward them to the park_thread
1050  *
1051  * \param hostChannel initial channel that request the parking
1052  * \todo we have a codec issue after unpark a call
1053  * \todo copy connected line info
1054  *
1055  */
sccp_astwrap_park(const sccp_channel_t * hostChannel)1056 static sccp_parkresult_t sccp_astwrap_park(const sccp_channel_t * hostChannel)
1057 {
1058 	int extout;
1059 	char extstr[20];
1060 	sccp_parkresult_t res = PARK_RESULT_FAIL;
1061 	PBX_CHANNEL_TYPE *bridgedChannel = NULL;
1062 
1063 	memset(extstr, 0, sizeof(extstr));
1064 
1065 	if ((bridgedChannel = ast_bridged_channel(hostChannel->owner))) {
1066 		AUTO_RELEASE(sccp_device_t, device , sccp_channel_getDevice(hostChannel));
1067 		if (device) {
1068 			ast_channel_lock(hostChannel->owner);							/* we have to lock our channel, otherwise asterisk crashes internally */
1069 			if (!ast_masq_park_call(bridgedChannel, hostChannel->owner, 0, &extout)) {
1070 				snprintf(extstr, sizeof(extstr), "%c%c %d" , 128, SKINNY_LBL_CALL_PARK_AT, extout);
1071 
1072 				sccp_dev_displayprinotify(device, extstr, 1, 10);
1073 				sccp_log((DEBUGCAT_CHANNEL | DEBUGCAT_CORE)) (VERBOSE_PREFIX_3 "%s: Parked channel %s on %d\n", DEV_ID_LOG(device), bridgedChannel->name, extout);
1074 
1075 				res = PARK_RESULT_SUCCESS;
1076 			}
1077 			ast_channel_unlock(hostChannel->owner);
1078 		}
1079 	}
1080 	return res;
1081 }
1082 
sccp_astwrap_getFeatureExtension(const sccp_channel_t * channel,const char * featureName,char extension[SCCP_MAX_EXTENSION])1083 static boolean_t sccp_astwrap_getFeatureExtension(const sccp_channel_t * channel, const char *featureName, char extension[SCCP_MAX_EXTENSION])
1084 {
1085 	struct ast_call_feature *feat;
1086 
1087 	ast_rdlock_call_features();
1088 	feat = ast_find_call_feature(featureName);
1089 	if (feat) {
1090 		sccp_copy_string(extension, feat->exten, SCCP_MAX_EXTENSION);
1091 	}
1092 	ast_unlock_call_features();
1093 
1094 	return feat ? TRUE : FALSE;
1095 }
1096 
sccp_astwrap_getPickupExtension(const sccp_channel_t * channel,char extension[SCCP_MAX_EXTENSION])1097 static boolean_t sccp_astwrap_getPickupExtension(const sccp_channel_t * channel, char extension[SCCP_MAX_EXTENSION])
1098 {
1099 	boolean_t res = FALSE;
1100 
1101 	if (!sccp_strlen_zero(ast_pickup_ext())) {
1102 		sccp_copy_string(extension, ast_pickup_ext(), SCCP_MAX_EXTENSION);
1103 		res = TRUE;
1104 	}
1105 	return res;
1106 }
1107 
sccp_astwrap_get_payloadType(const struct sccp_rtp * rtp,skinny_codec_t codec)1108 static uint8_t sccp_astwrap_get_payloadType(const struct sccp_rtp *rtp, skinny_codec_t codec)
1109 {
1110 	struct ast_format astCodec;
1111 	int payload;
1112 
1113 	ast_format_set(&astCodec, skinny_codec2pbx_codec(codec), 0);
1114 	payload = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(rtp->instance), 1, &astCodec, 0);
1115 
1116 	return payload;
1117 }
1118 
sccp_astwrap_get_sampleRate(skinny_codec_t codec)1119 static int sccp_astwrap_get_sampleRate(skinny_codec_t codec)
1120 {
1121 	struct ast_format astCodec;
1122 
1123 	ast_format_set(&astCodec, skinny_codec2pbx_codec(codec), 0);
1124 	return ast_rtp_lookup_sample_rate2(1, &astCodec, 0);
1125 }
1126 
sccp_astwrap_extensionStatus(const sccp_channel_t * channel)1127 static sccp_extension_status_t sccp_astwrap_extensionStatus(const sccp_channel_t * channel)
1128 {
1129 	PBX_CHANNEL_TYPE *pbx_channel = channel->owner;
1130 
1131 	if (!pbx_channel || sccp_strlen_zero(pbx_channel->context)) {
1132 		pbx_log(LOG_ERROR, "%s: (extension_status) Either no pbx_channel or no valid context provided to lookup number\n", channel->designator);
1133 		return SCCP_EXTENSION_NOTEXISTS;
1134 	}
1135 	int ignore_pat = ast_ignore_pattern(pbx_channel->context, channel->dialedNumber);
1136 	int ext_exist = ast_exists_extension(pbx_channel, pbx_channel->context, channel->dialedNumber, 1, channel->line->cid_num);
1137 	int ext_canmatch = ast_canmatch_extension(pbx_channel, pbx_channel->context, channel->dialedNumber, 1, channel->line->cid_num);
1138 	int ext_matchmore = ast_matchmore_extension(pbx_channel, pbx_channel->context, channel->dialedNumber, 1, channel->line->cid_num);
1139 
1140 	/* if we dialed the pickup extention, mark this as exact match */
1141 	const char *pickupexten = ast_pickup_ext();
1142 
1143 	if (!sccp_strlen_zero(pickupexten) && sccp_strcaseequals(pickupexten, channel->dialedNumber)) {
1144 		sccp_log(DEBUGCAT_CORE) (VERBOSE_PREFIX_3 "SCCP: pbx extension matcher found pickup extension %s matches dialed number %s\n", channel->dialedNumber, pickupexten);
1145 		ext_exist = 1;
1146 		ext_canmatch = 1;
1147 		ext_matchmore = 0;
1148 	}
1149 
1150 	sccp_log((DEBUGCAT_CORE)) (VERBOSE_PREFIX_3 "+- pbx extension matcher (%-15s): ---+\n" VERBOSE_PREFIX_3 "|ignore     |exists     |can match  |match more|\n" VERBOSE_PREFIX_3 "|%3s        |%3s        |%3s        |%3s       |\n" VERBOSE_PREFIX_3 "+----------------------------------------------+\n", channel->dialedNumber, ignore_pat ? "yes" : "no", ext_exist ? "yes" : "no", ext_canmatch ? "yes" : "no", ext_matchmore ? "yes" : "no");
1151 	if (ignore_pat) {
1152 		return SCCP_EXTENSION_NOTEXISTS;
1153 	}
1154 	if (ext_exist) {
1155 		if (ext_canmatch && !ext_matchmore) {
1156 			return SCCP_EXTENSION_EXACTMATCH;
1157 		}
1158 		return SCCP_EXTENSION_MATCHMORE;
1159 	}
1160 
1161 	return SCCP_EXTENSION_NOTEXISTS;
1162 }
1163 
sccp_astwrap_request(const char * type,struct ast_format_cap * format,const PBX_CHANNEL_TYPE * requestor,void * data,int * cause)1164 static PBX_CHANNEL_TYPE *sccp_astwrap_request(const char *type, struct ast_format_cap *format, const PBX_CHANNEL_TYPE * requestor, void *data, int *cause)
1165 {
1166 	PBX_CHANNEL_TYPE *result_ast_channel = NULL;
1167 	sccp_channel_request_status_t requestStatus;
1168 
1169 	skinny_codec_t audioCapabilities[SKINNY_MAX_CAPABILITIES];
1170 	skinny_codec_t videoCapabilities[SKINNY_MAX_CAPABILITIES];
1171 
1172 	memset(&audioCapabilities, 0, sizeof(audioCapabilities));
1173 	memset(&videoCapabilities, 0, sizeof(videoCapabilities));
1174 
1175 	//! \todo parse request
1176 	char *lineName;
1177 	skinny_codec_t codec = SKINNY_CODEC_G711_ULAW_64K;
1178 	sccp_autoanswer_t autoanswer_type = SCCP_AUTOANSWER_NONE;
1179 	uint8_t autoanswer_cause = AST_CAUSE_NOTDEFINED;
1180 	skinny_ringtype_t ringermode = GLOB(ringtype);
1181 
1182 	*cause = AST_CAUSE_NOTDEFINED;
1183 	if (!type) {
1184 		pbx_log(LOG_NOTICE, "Attempt to call with unspecified type of channel\n");
1185 		*cause = AST_CAUSE_REQUESTED_CHAN_UNAVAIL;
1186 		return NULL;
1187 	}
1188 
1189 	if (!data) {
1190 		pbx_log(LOG_NOTICE, "Attempt to call SCCP/ failed\n");
1191 		*cause = AST_CAUSE_REQUESTED_CHAN_UNAVAIL;
1192 		return NULL;
1193 	}
1194 	/* we leave the data unchanged */
1195 	lineName = pbx_strdupa((const char *) data);
1196 	/* parsing options string */
1197 	char *options = NULL;
1198 	if ((options = strchr(lineName, '/'))) {
1199 		*options = '\0';
1200 		options++;
1201 	}
1202 
1203 	sccp_log(DEBUGCAT_CHANNEL) (VERBOSE_PREFIX_3 "SCCP: Asterisk asked us to create a channel with type=%s, format=" UI64FMT " lineName=%s, options=%s\n", type, (ULONG) ast_format_cap_to_old_bitfield(format), lineName, (options) ? options : "");
1204 	if (requestor) {							/* get ringer mode from ALERT_INFO */
1205 		sccp_parse_alertinfo((PBX_CHANNEL_TYPE *)requestor, &ringermode);
1206 	}
1207 	sccp_parse_dial_options(options, &autoanswer_type, &autoanswer_cause, &ringermode);
1208 	if (autoanswer_cause) {
1209 		*cause = autoanswer_cause;
1210 	}
1211 	sccp_parse_auto_answer((PBX_CHANNEL_TYPE *)requestor, &autoanswer_type);
1212 
1213 	/** getting remote capabilities */
1214 	char cap_buf[512];
1215 
1216 	/* audio capabilities */
1217 	if (requestor) {
1218 		AUTO_RELEASE(sccp_channel_t, remoteSccpChannel , get_sccp_channel_from_pbx_channel(requestor));
1219 		if (remoteSccpChannel) {
1220 			uint8_t x, y, z;
1221 
1222 			z = 0;
1223 			/* shrink audioCapabilities to remote preferred/capable format */
1224 			for (x = 0; x < SKINNY_MAX_CAPABILITIES && remoteSccpChannel->preferences.audio[x] != 0; x++) {
1225 				for (y = 0; y < SKINNY_MAX_CAPABILITIES && remoteSccpChannel->capabilities.audio[y] != 0; y++) {
1226 					if (remoteSccpChannel->preferences.audio[x] == remoteSccpChannel->capabilities.audio[y]) {
1227 						audioCapabilities[z++] = remoteSccpChannel->preferences.audio[x];
1228 						break;
1229 					}
1230 				}
1231 			}
1232 		} else {
1233 			sccp_astwrap_getSkinnyFormatMultiple(requestor->nativeformats, audioCapabilities, ARRAY_LEN(audioCapabilities));	// replace AUDIO_MASK with AST_FORMAT_TYPE_AUDIO check
1234 		}
1235 
1236 		/* video capabilities */
1237 		sccp_astwrap_getSkinnyFormatMultiple(requestor->nativeformats, videoCapabilities, ARRAY_LEN(videoCapabilities));	//replace AUDIO_MASK with AST_FORMAT_TYPE_AUDIO check
1238 	}
1239 
1240 	sccp_codec_multiple2str(cap_buf, sizeof(cap_buf) - 1, audioCapabilities, ARRAY_LEN(audioCapabilities));
1241 	sccp_log(DEBUGCAT_CODEC) (VERBOSE_PREFIX_4 "remote audio caps: %s\n", cap_buf);
1242 
1243 	sccp_codec_multiple2str(cap_buf, sizeof(cap_buf) - 1, videoCapabilities, ARRAY_LEN(videoCapabilities));
1244 	sccp_log(DEBUGCAT_CODEC) (VERBOSE_PREFIX_4 "remote video caps: %s\n", cap_buf);
1245 
1246 	/** done */
1247 
1248 	/** get requested format */
1249 	// codec = pbx_codec2skinny_codec(ast_format_cap_to_old_bitfield(format));
1250 	codec = sccp_astwrap_getSkinnyFormatSingle(format);
1251 
1252 	/* get requested format */
1253 	{
1254 		struct ast_format tmpfmt;
1255 
1256 		ast_format_cap_iter_start(format);
1257 		while (!(ast_format_cap_iter_next(format, &tmpfmt))) {
1258 			if (AST_FORMAT_GET_TYPE(tmpfmt.id) == AST_FORMAT_TYPE_AUDIO) {
1259 				codec = pbx_codec2skinny_codec(tmpfmt.id);
1260 				break;
1261 			}
1262 		}
1263 		ast_format_cap_iter_end(format);
1264 	}
1265 
1266 	AUTO_RELEASE(sccp_channel_t, channel , NULL);
1267 	requestStatus = sccp_requestChannel(lineName, autoanswer_type, autoanswer_cause, ringermode, &channel);
1268 	switch (requestStatus) {
1269 		case SCCP_REQUEST_STATUS_SUCCESS:								// everything is fine
1270 			break;
1271 		case SCCP_REQUEST_STATUS_LINEUNKNOWN:
1272 			sccp_log(DEBUGCAT_CORE) (VERBOSE_PREFIX_4 "SCCP: sccp_requestChannel returned Line %s Unknown -> Not Successfull\n", lineName);
1273 			*cause = AST_CAUSE_DESTINATION_OUT_OF_ORDER;
1274 			goto EXITFUNC;
1275 		case SCCP_REQUEST_STATUS_LINEUNAVAIL:
1276 			sccp_log(DEBUGCAT_CORE) (VERBOSE_PREFIX_4 "SCCP: sccp_requestChannel returned Line %s not currently registered -> Try again later\n", lineName);
1277 			*cause = AST_CAUSE_REQUESTED_CHAN_UNAVAIL;
1278 			goto EXITFUNC;
1279 		case SCCP_REQUEST_STATUS_ERROR:
1280 			pbx_log(LOG_ERROR, "SCCP: sccp_requestChannel returned Status Error for lineName: %s\n", lineName);
1281 			*cause = AST_CAUSE_UNALLOCATED;
1282 			goto EXITFUNC;
1283 		default:
1284 			pbx_log(LOG_ERROR, "SCCP: sccp_requestChannel returned Status Error for lineName: %s\n", lineName);
1285 			*cause = AST_CAUSE_UNALLOCATED;
1286 			goto EXITFUNC;
1287 	}
1288 
1289 	memcpy(&channel->remoteCapabilities.audio, audioCapabilities, sizeof(channel->remoteCapabilities.audio));
1290 #ifdef CS_SCCP_VIDEO
1291 	memset(&channel->remoteCapabilities.video, 0, sizeof(channel->remoteCapabilities.video));
1292 	if (videoCapabilities[0] != SKINNY_CODEC_NONE) {
1293 		memcpy(channel->remoteCapabilities.video, videoCapabilities, ARRAY_LEN(videoCapabilities));
1294 	}
1295 #endif
1296 
1297 	if (!sccp_pbx_channel_allocate(channel, requestor ? requestor->linkedid : NULL, requestor)) {
1298 		*cause = AST_CAUSE_REQUESTED_CHAN_UNAVAIL;
1299 		goto EXITFUNC;
1300 	}
1301 
1302 	/* set initial connected line information, to be exchange with remove party during first CONNECTED_LINE update */
1303 	ast_set_callerid(channel->owner, channel->line->cid_num, channel->line->cid_name, channel->line->cid_num);
1304 	struct ast_party_connected_line connected;
1305 	ast_party_connected_line_set_init(&connected, &channel->owner->connected);
1306 	connected.id.number.valid = 1;
1307 	connected.id.number.str = (char *)channel->line->cid_num;
1308 	connected.id.number.presentation = AST_PRES_ALLOWED_NETWORK_NUMBER;
1309 	connected.id.name.valid = 1;
1310 	connected.id.name.str = (char *)channel->line->cid_name;
1311 	connected.id.name.presentation = AST_PRES_ALLOWED_NETWORK_NUMBER;
1312 	connected.source = AST_CONNECTED_LINE_UPDATE_SOURCE_UNKNOWN;
1313 	ast_channel_set_connected_line(channel->owner, &connected, NULL);
1314 	/* end */
1315 
1316 	if (requestor) {
1317 		/* set calling party */
1318 		sccp_callinfo_t *ci = sccp_channel_getCallInfo(channel);
1319 		iCallInfo.Setter(ci,
1320 				SCCP_CALLINFO_CALLINGPARTY_NAME, requestor->caller.id.name.str,
1321 				SCCP_CALLINFO_CALLINGPARTY_NUMBER, requestor->caller.id.number.str,
1322 				SCCP_CALLINFO_ORIG_CALLEDPARTY_NAME, requestor->redirecting.from.name.str,
1323 				SCCP_CALLINFO_ORIG_CALLEDPARTY_NUMBER, requestor->redirecting.from.number.str,
1324 				SCCP_CALLINFO_KEY_SENTINEL);
1325 
1326 		if (requestor->linkedid) {
1327 			ast_string_field_set(channel->owner, linkedid, requestor->linkedid);
1328 		}
1329 	}
1330 
1331 EXITFUNC:
1332 
1333 	if (channel) {
1334 		result_ast_channel = channel->owner;
1335 	}
1336 	return result_ast_channel;
1337 }
1338 
sccp_astwrap_call(PBX_CHANNEL_TYPE * ast,char * dest,int timeout)1339 static int sccp_astwrap_call(PBX_CHANNEL_TYPE * ast, char *dest, int timeout)
1340 {
1341 	int res = 0;
1342 
1343 	sccp_log((DEBUGCAT_CORE)) (VERBOSE_PREFIX_3 "SCCP: Asterisk request to call %s (dest:%s, timeout: %d)\n", pbx_channel_name(ast), dest, timeout);
1344 
1345 	if (!sccp_strlen_zero(pbx_channel_call_forward(ast))) {
1346 		iPbx.queue_control(ast, -1);									/* Prod Channel if in the middle of a call_forward instead of proceed */
1347 		sccp_log((DEBUGCAT_CORE)) (VERBOSE_PREFIX_3 "SCCP: Forwarding Call to '%s'\n", pbx_channel_call_forward(ast));
1348 		return 0;
1349 	}
1350 
1351 	AUTO_RELEASE(sccp_channel_t, c , get_sccp_channel_from_pbx_channel(ast));
1352 	if (!c) {
1353 		pbx_log(LOG_WARNING, "SCCP: Asterisk request to call %s on channel: %s, but we don't have this channel!\n", dest, pbx_channel_name(ast));
1354 		return -1;
1355 	}
1356 
1357 	res = sccp_pbx_call(c, dest, timeout);
1358 	return res;
1359 
1360 }
1361 
1362 /*
1363  * Remote side has answered the call switch to up state
1364  * Is being called with pbxchan locked by app_dial
1365  */
sccp_astwrap_answer(PBX_CHANNEL_TYPE * pbxchan)1366 static int sccp_astwrap_answer(PBX_CHANNEL_TYPE * pbxchan)
1367 {
1368 	int res = -1;
1369 	int timedout = 0;
1370 	if(pbx_channel_state(pbxchan) == AST_STATE_UP) {
1371 		pbx_log(LOG_NOTICE, "%s: Channel has already been answered remotely, skipping\n", pbx_channel_name(pbxchan));
1372 		return 0;
1373 	}
1374 
1375 	pbx_channel_ref(pbxchan);
1376 	AUTO_RELEASE(sccp_channel_t, c , get_sccp_channel_from_pbx_channel(pbxchan));
1377 	if(c && c->state < SCCP_GROUPED_CHANNELSTATE_CONNECTION) {
1378 		sccp_log(DEBUGCAT_CORE)(VERBOSE_PREFIX_3 "%s: Remote has answered the call.\n", c->designator);
1379 		AUTO_RELEASE(sccp_device_t, d, sccp_channel_getDevice(c));
1380 		if(d && d->session) {
1381 			sccp_log(DEBUGCAT_PBX)(VERBOSE_PREFIX_3 "%s: Waiting for pendingRequests\n", c->designator);
1382 			// this needs to be done with the pbx_channel unlocked to prevent lock investion
1383 			// note we still have a pbx_channel_ref, so the channel cannot be removed under our feet
1384 			pbx_channel_unlock(pbxchan);
1385 			timedout = sccp_session_waitForPendingRequests(d->session);
1386 			pbx_channel_lock(pbxchan);
1387 		}
1388 		if (!timedout) {
1389 			// pbx_indicate(pbxchan, AST_CONTROL_PROGRESS);
1390 			res = sccp_pbx_remote_answer(c);
1391 		}
1392 	}
1393 	pbx_channel_unref(pbxchan);
1394 	return res;
1395 }
1396 
1397 /**
1398  *
1399  * \todo update remote capabilities after fixup
1400  */
sccp_astwrap_fixup(PBX_CHANNEL_TYPE * oldchan,PBX_CHANNEL_TYPE * newchan)1401 static int sccp_astwrap_fixup(PBX_CHANNEL_TYPE * oldchan, PBX_CHANNEL_TYPE * newchan)
1402 {
1403 	sccp_log((DEBUGCAT_CORE)) (VERBOSE_PREFIX_3 "SCCP: we got a fixup request for %s and %s\n", pbx_channel_name(oldchan), pbx_channel_name(newchan));
1404 	int res = 0;
1405 
1406 	AUTO_RELEASE(sccp_channel_t, c , get_sccp_channel_from_pbx_channel(newchan));
1407 	if (c) {
1408 		if (c->owner != oldchan) {
1409 			ast_log(LOG_WARNING, "old channel wasn't %p but was %p\n", oldchan, c->owner);
1410 			res = -1;
1411 		} else {
1412 			/* during a masquerade, fixup gets called twice, The Zombie channel name will have been changed to include '<ZOMBI>' */
1413 			/* using test_flag for ZOMBIE cannot be used, as it is only set after the fixup call */
1414 			if (!strstr(pbx_channel_name(newchan), "<ZOMBIE>")) {
1415 				sccp_log((DEBUGCAT_CORE)) (VERBOSE_PREFIX_3 "%s: set c->hangupRequest = requestQueueHangup\n", c->designator);
1416 				if (pbx_channel_hangupcause(newchan) == AST_CAUSE_ANSWERED_ELSEWHERE) {
1417 					sccp_log((DEBUGCAT_CORE)) (VERBOSE_PREFIX_3 "%s: Fixup Adding Redirecting Party from:%s\n", c->designator, pbx_channel_name(oldchan));
1418 					iCallInfo.Setter(sccp_channel_getCallInfo(c),
1419 						SCCP_CALLINFO_HUNT_PILOT_NAME, oldchan->caller.id.name.str,
1420 						SCCP_CALLINFO_HUNT_PILOT_NUMBER, oldchan->caller.id.number.str,
1421 						SCCP_CALLINFO_LAST_REDIRECTINGPARTY_NAME, oldchan->caller.id.name.str,
1422 						SCCP_CALLINFO_LAST_REDIRECTINGPARTY_NUMBER, oldchan->caller.id.number.str,
1423 						SCCP_CALLINFO_LAST_REDIRECT_REASON, 5,
1424 						SCCP_CALLINFO_KEY_SENTINEL);
1425 				}
1426 
1427 				// set channel requestHangup to use ast_queue_hangup (as it is now part of a __ast_pbx_run, after masquerade completes)
1428 				c->hangupRequest = sccp_astgenwrap_requestQueueHangup;
1429 				if (!sccp_strlen_zero(c->line->language)) {
1430 					ast_string_field_set(newchan, language, c->line->language);
1431 				}
1432 			} else {
1433 				sccp_log((DEBUGCAT_CORE)) (VERBOSE_PREFIX_3 "%s: set c->hangupRequest = requestHangup\n", c->designator);
1434 				// set channel requestHangup to use ast_hangup (as it will not be part of __ast_pbx_run anymore, upon returning from masquerade)
1435 				c->hangupRequest = sccp_astgenwrap_requestHangup;
1436 			}
1437 			sccp_astwrap_setOwner(c, newchan);
1438 			//! \todo force update of rtp peer for directrtp
1439 			// sccp_wrapper_asterisk110_update_rtp_peer(newchan, NULL, NULL, 0, 0, 0);
1440 
1441 			//! \todo update remote capabilities after fixup
1442 
1443 		}
1444 	} else {
1445 		pbx_log(LOG_WARNING, "sccp_pbx_fixup(old: %s(%p), new: %s(%p)). no SCCP channel to fix\n", pbx_channel_name(oldchan), (void *) oldchan, pbx_channel_name(newchan), (void *) newchan);
1446 		res = -1;
1447 	}
1448 	return res;
1449 }
1450 
1451 #if 0
1452 static enum ast_bridge_result sccp_astwrap_rtpBridge(PBX_CHANNEL_TYPE * c0, PBX_CHANNEL_TYPE * c1, int flags, PBX_FRAME_TYPE ** fo, PBX_CHANNEL_TYPE ** rc, int timeoutms)
1453 {
1454 	enum ast_bridge_result res;
1455 	int new_flags = flags;
1456 
1457 	/* \note temporarily marked out until we figure out how to get directrtp back on track - DdG */
1458 	AUTO_RELEASE(sccp_channel_t, sc0 , get_sccp_channel_from_pbx_channel(c0));
1459 	AUTO_RELEASE(sccp_channel_t, sc1 , get_sccp_channel_from_pbx_channel(c1));
1460 
1461 	if ((sc0 && sc1)) {
1462 		// Switch off DTMF between SCCP phones
1463 		new_flags &= !AST_BRIDGE_DTMF_CHANNEL_0;
1464 		new_flags &= !AST_BRIDGE_DTMF_CHANNEL_1;
1465 		if (GLOB(directrtp)) {
1466 			ast_channel_defer_dtmf(c0);
1467 			ast_channel_defer_dtmf(c1);
1468 		} else {
1469 			AUTO_RELEASE(sccp_device_t, d0 , sccp_channel_getDevice(sc0));
1470 			AUTO_RELEASE(sccp_device_t, d1 , sccp_channel_getDevice(sc1));
1471 			if ((d0 && d1) && ((d0->directrtp && d1->directrtp)) {
1472 				ast_channel_defer_dtmf(c0);
1473 				ast_channel_defer_dtmf(c1);
1474 			}
1475 		}
1476 		sc0->peerIsSCCP = TRUE;
1477 		sc1->peerIsSCCP = TRUE;
1478 		// SCCP Key handle direction to asterisk is still to be implemented here
1479 		// sccp_pbx_senddigit
1480 	} else {
1481 		// Switch on DTMF between differing channels
1482 		ast_channel_undefer_dtmf(c0);
1483 		ast_channel_undefer_dtmf(c1);
1484 	}
1485 
1486 	//res = ast_rtp_bridge(c0, c1, new_flags, fo, rc, timeoutms);
1487 	res = ast_rtp_instance_bridge(c0, c1, new_flags, fo, rc, timeoutms);
1488 	switch (res) {
1489 		case AST_BRIDGE_COMPLETE:
1490 			sccp_log((DEBUGCAT_PBX)) (VERBOSE_PREFIX_1 "SCCP: Bridge chan %s and chan %s: Complete\n", c0->name, c1->name);
1491 			break;
1492 		case AST_BRIDGE_FAILED:
1493 			sccp_log((DEBUGCAT_PBX)) (VERBOSE_PREFIX_1 "SCCP: Bridge chan %s and chan %s: Failed\n", c0->name, c1->name);
1494 			break;
1495 		case AST_BRIDGE_FAILED_NOWARN:
1496 			sccp_log((DEBUGCAT_PBX)) (VERBOSE_PREFIX_1 "SCCP: Bridge chan %s and chan %s: Failed NoWarn\n", c0->name, c1->name);
1497 			break;
1498 		case AST_BRIDGE_RETRY:
1499 			sccp_log((DEBUGCAT_PBX)) (VERBOSE_PREFIX_1 "SCCP: Bridge chan %s and chan %s: Failed Retry\n", c0->name, c1->name);
1500 			break;
1501 	}
1502 	/*! \todo Implement callback function queue upon completion */
1503 	return res;
1504 }
1505 #endif
1506 
sccp_astwrap_get_rtp_info(PBX_CHANNEL_TYPE * ast,PBX_RTP_TYPE ** rtp)1507 static enum ast_rtp_glue_result sccp_astwrap_get_rtp_info(PBX_CHANNEL_TYPE * ast, PBX_RTP_TYPE ** rtp)
1508 {
1509 	//AUTO_RELEASE(sccp_channel_t, c , NULL);									// not following the refcount rules... channel is already retained
1510 	sccp_channel_t *c = NULL;
1511 	sccp_rtp_info_t rtpInfo = SCCP_RTP_INFO_NORTP;
1512 	struct sccp_rtp *audioRTP = NULL;
1513 	enum ast_rtp_glue_result res = AST_RTP_GLUE_RESULT_REMOTE;
1514 
1515 	if (!(c = CS_AST_CHANNEL_PVT(ast))) {
1516 		sccp_log((DEBUGCAT_RTP)) (VERBOSE_PREFIX_1 "SCCP: (get_rtp_info) NO PVT\n");
1517 		return AST_RTP_GLUE_RESULT_FORBID;
1518 	}
1519 
1520 	if (pbx_channel_state(ast) != AST_STATE_UP) {
1521 		sccp_log((DEBUGCAT_CHANNEL | DEBUGCAT_RTP)) (VERBOSE_PREFIX_1 "%s: (get_rtp_info) Asterisk requested EarlyRTP peer for channel %s\n", c->currentDeviceId, pbx_channel_name(ast));
1522 	} else {
1523 		sccp_log((DEBUGCAT_CHANNEL | DEBUGCAT_RTP)) (VERBOSE_PREFIX_1 "%s: (get_rtp_info) Asterisk requested RTP peer for channel %s\n", c->currentDeviceId, pbx_channel_name(ast));
1524 	}
1525 
1526 	rtpInfo = sccp_rtp_getAudioPeerInfo(c, &audioRTP);
1527 	if (rtpInfo == SCCP_RTP_INFO_NORTP) {
1528 		return AST_RTP_GLUE_RESULT_FORBID;
1529 	}
1530 
1531 	*rtp = audioRTP->instance;
1532 	if (!*rtp) {
1533 		return AST_RTP_GLUE_RESULT_FORBID;
1534 	}
1535 	// struct ast_sockaddr ast_sockaddr_tmp;
1536 	// ast_rtp_instance_get_remote_address(*rtp, &ast_sockaddr_tmp);
1537 	// sccp_log((DEBUGCAT_RTP | DEBUGCAT_HIGH)) (VERBOSE_PREFIX_3 "%s: (get_rtp_info) remote address:'%s:%d'\n", c->currentDeviceId, ast_sockaddr_stringify_host(&ast_sockaddr_tmp), ast_sockaddr_port(&ast_sockaddr_tmp));
1538 
1539 	ao2_ref(*rtp, +1);
1540 	if (ast_test_flag(GLOB(global_jbconf), AST_JB_FORCED)) {
1541 		sccp_log((DEBUGCAT_RTP)) (VERBOSE_PREFIX_1 "%s: (get_rtp_info) JitterBuffer is Forced. AST_RTP_GET_FAILED\n", c->currentDeviceId);
1542 		return AST_RTP_GLUE_RESULT_LOCAL;
1543 	}
1544 
1545 	if (!(rtpInfo & SCCP_RTP_INFO_ALLOW_DIRECTRTP)) {
1546 		sccp_log((DEBUGCAT_RTP)) (VERBOSE_PREFIX_1 "%s: (get_rtp_info) Direct RTP disabled ->  Using AST_RTP_TRY_PARTIAL for channel %s\n", c->currentDeviceId, pbx_channel_name(ast));
1547 		return AST_RTP_GLUE_RESULT_LOCAL;
1548 	}
1549 
1550 	sccp_log((DEBUGCAT_RTP | DEBUGCAT_HIGH)) (VERBOSE_PREFIX_1 "%s: (get_rtp_info) Channel %s Returning res: %s\n", c->currentDeviceId, pbx_channel_name(ast), ((res == 2) ? "indirect-rtp" : ((res == 1) ? "direct-rtp" : "forbid")));
1551 	return res;
1552 }
1553 
sccp_astwrap_get_vrtp_info(PBX_CHANNEL_TYPE * ast,PBX_RTP_TYPE ** rtp)1554 static enum ast_rtp_glue_result sccp_astwrap_get_vrtp_info(PBX_CHANNEL_TYPE * ast, PBX_RTP_TYPE ** rtp)
1555 {
1556 	//AUTO_RELEASE(sccp_channel_t, c , NULL);									// not following the refcount rules... channel is already retained
1557 	sccp_channel_t *c = NULL;
1558 	sccp_rtp_info_t rtpInfo = SCCP_RTP_INFO_NORTP;
1559 	struct sccp_rtp *videoRTP = NULL;
1560 	enum ast_rtp_glue_result res = AST_RTP_GLUE_RESULT_REMOTE;
1561 
1562 	if (!(c = CS_AST_CHANNEL_PVT(ast))) {
1563 		sccp_log((DEBUGCAT_RTP)) (VERBOSE_PREFIX_1 "SCCP: (get_vrtp_info) NO PVT\n");
1564 		return AST_RTP_GLUE_RESULT_FORBID;
1565 	}
1566 
1567 	if (pbx_channel_state(ast) != AST_STATE_UP) {
1568 		sccp_log((DEBUGCAT_CHANNEL | DEBUGCAT_RTP)) (VERBOSE_PREFIX_1 "%s: (get_vrtp_info) Asterisk requested EarlyRTP peer for channel %s\n", c->currentDeviceId, pbx_channel_name(ast));
1569 	} else {
1570 		sccp_log((DEBUGCAT_CHANNEL | DEBUGCAT_RTP)) (VERBOSE_PREFIX_1 "%s: (get_vrtp_info) Asterisk requested RTP peer for channel %s\n", c->currentDeviceId, pbx_channel_name(ast));
1571 	}
1572 
1573 #ifdef CS_SCCP_VIDEO
1574 	rtpInfo = sccp_rtp_getVideoPeerInfo(c, &videoRTP);
1575 #endif
1576 	if (rtpInfo == SCCP_RTP_INFO_NORTP) {
1577 		return AST_RTP_GLUE_RESULT_FORBID;
1578 	}
1579 
1580 	*rtp = videoRTP->instance;
1581 	if (!*rtp) {
1582 		return AST_RTP_GLUE_RESULT_FORBID;
1583 	}
1584 	// struct ast_sockaddr ast_sockaddr_tmp;
1585 	// ast_rtp_instance_get_remote_address(*rtp, &ast_sockaddr_tmp);
1586 	// sccp_log((DEBUGCAT_RTP | DEBUGCAT_HIGH)) (VERBOSE_PREFIX_3 "%s: (get_vrtp_info) remote address:'%s:%d'\n", c->currentDeviceId, ast_sockaddr_stringify_host(&ast_sockaddr_tmp), ast_sockaddr_port(&ast_sockaddr_tmp));
1587 #ifdef HAVE_PBX_RTP_ENGINE_H
1588 	ao2_ref(*rtp, +1);
1589 #endif
1590 	if (ast_test_flag(GLOB(global_jbconf), AST_JB_FORCED)) {
1591 		sccp_log((DEBUGCAT_RTP)) (VERBOSE_PREFIX_1 "%s: (get_vrtp_info) JitterBuffer is Forced. AST_RTP_GET_FAILED\n", c->currentDeviceId);
1592 		return AST_RTP_GLUE_RESULT_FORBID;
1593 	}
1594 
1595 	if (!(rtpInfo & SCCP_RTP_INFO_ALLOW_DIRECTRTP)) {
1596 		sccp_log((DEBUGCAT_RTP)) (VERBOSE_PREFIX_1 "%s: (get_vrtp_info) Direct RTP disabled ->  Using AST_RTP_TRY_PARTIAL for channel %s\n", c->currentDeviceId, pbx_channel_name(ast));
1597 		return AST_RTP_GLUE_RESULT_LOCAL;
1598 	}
1599 
1600 	sccp_log((DEBUGCAT_RTP | DEBUGCAT_HIGH)) (VERBOSE_PREFIX_1 "%s: (get_vrtp_info) Channel %s Returning res: %s\n", c->currentDeviceId, pbx_channel_name(ast), ((res == 2) ? "indirect-rtp" : ((res == 1) ? "direct-rtp" : "forbid")));
1601 	return res;
1602 }
1603 
sccp_astwrap_update_rtp_peer(PBX_CHANNEL_TYPE * ast,PBX_RTP_TYPE * rtp,PBX_RTP_TYPE * vrtp,PBX_RTP_TYPE * trtp,const struct ast_format_cap * codecs,int nat_active)1604 static int sccp_astwrap_update_rtp_peer(PBX_CHANNEL_TYPE * ast, PBX_RTP_TYPE * rtp, PBX_RTP_TYPE * vrtp, PBX_RTP_TYPE * trtp, const struct ast_format_cap *codecs, int nat_active)
1605 {
1606 	//AUTO_RELEASE(sccp_channel_t, c , NULL);									// not following the refcount rules... channel is already retained
1607 	sccp_channel_t *c = NULL;
1608 	int result = 0;
1609 
1610 	do {
1611 		char codec_buf[512];
1612 
1613 		if (!(c = CS_AST_CHANNEL_PVT(ast))) {
1614 			sccp_log((DEBUGCAT_RTP)) (VERBOSE_PREFIX_1 "SCCP: (update_rtp_peer) NO PVT\n");
1615 			result = -1;
1616 			break;
1617 		}
1618 
1619 		if (!codecs) {
1620 			sccp_log((DEBUGCAT_RTP)) (VERBOSE_PREFIX_1 "%s: (asterisk112_update_rtp_peer) NO Codecs\n", c->currentDeviceId);
1621 			result = -1;
1622 			break;
1623 		}
1624 		ast_getformatname_multiple(codec_buf, sizeof(codec_buf) - 1, (struct ast_format_cap *) codecs);
1625 		sccp_log((DEBUGCAT_RTP)) (VERBOSE_PREFIX_2 "%s: (update_rtp_peer) stage: %s, remote codecs capabilty: %s (%lu), nat_active: %d\n", c->currentDeviceId, S_COR(AST_STATE_UP == pbx_channel_state(ast), "RTP", "EarlyRTP"), codec_buf, (long unsigned int) codecs, nat_active);
1626 		if (!c->line) {
1627 			sccp_log((DEBUGCAT_RTP)) (VERBOSE_PREFIX_1 "%s: (update_rtp_peer) NO LINE\n", c->currentDeviceId);
1628 			result = -1;
1629 			break;
1630 		}
1631 		if (c->state == SCCP_CHANNELSTATE_HOLD) {
1632 			sccp_log((DEBUGCAT_RTP)) (VERBOSE_PREFIX_1 "%s: (update_rtp_peer) On Hold -> No Update\n", c->currentDeviceId);
1633 			result = 0;
1634 			break;
1635 		}
1636 		AUTO_RELEASE(sccp_device_t, d , sccp_channel_getDevice(c));
1637 		if (!d) {
1638 			sccp_log((DEBUGCAT_RTP)) (VERBOSE_PREFIX_1 "%s: (update_rtp_peer) NO DEVICE\n", c->currentDeviceId);
1639 			result = -1;
1640 			break;
1641 		}
1642 		if (!rtp && !vrtp && !trtp) {
1643 			sccp_log((DEBUGCAT_RTP)) (VERBOSE_PREFIX_1 "%s: (update_rtp_peer) RTP not ready\n", c->currentDeviceId);
1644 			result = 0;
1645 			break;
1646 		}
1647 
1648 		PBX_RTP_TYPE *instance = { 0, };
1649 		struct sockaddr_storage sas = { 0, };
1650 		//struct sockaddr_in sin = { 0, };
1651 		struct ast_sockaddr sin_tmp;
1652 		boolean_t directmedia = FALSE;
1653 
1654 		if (rtp) {											// generalize input
1655 			instance = rtp;
1656 		} else if (vrtp) {
1657 			instance = vrtp;
1658 		} else {
1659 			instance = trtp;
1660 		}
1661 
1662 		if (d->directrtp && d->nat < SCCP_NAT_ON && !nat_active && !c->conference) {			// asume directrtp
1663 			ast_rtp_instance_get_remote_address(instance, &sin_tmp);
1664 			memcpy(&sas, &sin_tmp, sizeof(struct sockaddr_storage));
1665 			//ast_sockaddr_to_sin(&sin_tmp, &sin);
1666 			if (d->nat == SCCP_NAT_OFF) {								// forced nat off to circumvent autodetection + direcrtp, requires checking both phone_ip and external session ip address against devices permit/deny
1667 				struct ast_sockaddr sin_local;
1668 				struct sockaddr_storage localsas = { 0, };
1669 				ast_rtp_instance_get_local_address(instance, &sin_local);
1670 				memcpy(&localsas, &sin_local, sizeof(struct sockaddr_storage));
1671 				if (sccp_apply_ha(d->ha, &sas) == AST_SENSE_ALLOW && sccp_apply_ha(d->ha, &localsas) == AST_SENSE_ALLOW) {
1672 					directmedia = TRUE;
1673 				}
1674 			} else if (sccp_apply_ha(d->ha, &sas) == AST_SENSE_ALLOW) {					// check remote sin against local device acl (to match netmask)
1675 				directmedia = TRUE;
1676 			}
1677 		}
1678 		if (!directmedia) {										// fallback to indirectrtp
1679 			ast_rtp_instance_get_local_address(instance, &sin_tmp);
1680 			// ast_sockaddr_to_sin(&sin_tmp, &sin);
1681 			// sin.sin_addr.s_addr = sin.sin_addr.s_addr ? sin.sin_addr.s_addr : d->session->ourip.s_addr;
1682 			memcpy(&sas, &sin_tmp, sizeof(struct sockaddr_storage));
1683 			sccp_session_getOurIP(d->session, &sas, sccp_netsock_is_IPv4(&sas) ? AF_INET : AF_INET6);
1684 		}
1685 
1686 		sccp_log((DEBUGCAT_RTP))(VERBOSE_PREFIX_1 "%s: (asterisk110_update_rtp_peer) new remote rtp ip = '%s'\n (d->directrtp: %s && !d->nat: %s && !remote->nat_active: %s && d->acl_allow: %s) => directmedia=%s\n",
1687 					 c->currentDeviceId, sccp_netsock_stringify(&sas), S_COR(d->directrtp, "yes", "no"), sccp_nat2str(d->nat), S_COR(!nat_active, "yes", "no"), S_COR(directmedia, "yes", "no"),
1688 					 S_COR(directmedia, "yes", "no"));
1689 
1690 		if (rtp) {											// send peer info to phone
1691 			sccp_rtp_set_peer(c, &c->rtp.audio, &sas);
1692 			c->rtp.audio.directMedia = directmedia;
1693 		} else if (vrtp) {
1694 			sccp_rtp_set_peer(c, &c->rtp.video, &sas);
1695 			c->rtp.video.directMedia = directmedia;
1696 		} else {
1697 			//sccp_rtp_set_peer(c, &c->rtp.text, &sas);
1698 			//c->rtp.text.directMedia = directmedia;
1699 		}
1700 	} while (0);
1701 
1702 	/* Need a return here to break the bridge */
1703 	sccp_log(DEBUGCAT_RTP) (VERBOSE_PREFIX_3 "%s: (update_rtp_peer) Result: %d\n", c ? c->currentDeviceId : NULL, result);
1704 	return result;
1705 }
1706 
sccp_astwrap_getCodec(PBX_CHANNEL_TYPE * ast,struct ast_format_cap * result)1707 static void sccp_astwrap_getCodec(PBX_CHANNEL_TYPE * ast, struct ast_format_cap *result)
1708 {
1709 	uint8_t i;
1710 	struct ast_format fmt;
1711 	AUTO_RELEASE(sccp_channel_t, channel , get_sccp_channel_from_pbx_channel(ast));
1712 
1713 	if (!channel) {
1714 		sccp_log((DEBUGCAT_RTP | DEBUGCAT_CODEC)) (VERBOSE_PREFIX_1 "SCCP: (getCodec) NO PVT\n");
1715 		return;
1716 	}
1717 
1718 	ast_debug(10, "asterisk requests format for channel %s, readFormat: %s(%d)\n", ast->name, codec2str(channel->rtp.audio.transmission.format), channel->rtp.audio.transmission.format);
1719 	for (i = 0; i < ARRAY_LEN(channel->preferences.audio); i++) {
1720 		ast_format_set(&fmt, skinny_codec2pbx_codec(channel->preferences.audio[i]), 0);
1721 		ast_format_cap_add(result, &fmt);
1722 	}
1723 
1724 	return;
1725 }
1726 
1727 /*
1728  * \brief get callerid_name from pbx
1729  * \param sccp_channle Asterisk Channel
1730  * \param cid name result
1731  * \return parse result
1732  */
sccp_astwrap_callerid_name(PBX_CHANNEL_TYPE * pbx_chan,char ** cid_name)1733 static int sccp_astwrap_callerid_name(PBX_CHANNEL_TYPE *pbx_chan, char **cid_name)
1734 {
1735 	if (pbx_chan && pbx_chan->caller.id.name.valid && pbx_chan->caller.id.name.str && strlen(pbx_chan->caller.id.name.str) > 0) {
1736 		*cid_name = pbx_strdup(pbx_chan->caller.id.name.str);
1737 		return 1;
1738 	}
1739 	return 0;
1740 }
1741 
1742 /*
1743  * \brief get callerid_name from pbx
1744  * \param ast_chan Asterisk Channel
1745  * \return char * with the caller number
1746  */
sccp_astwrap_callerid_number(PBX_CHANNEL_TYPE * pbx_chan,char ** cid_number)1747 static int sccp_astwrap_callerid_number(PBX_CHANNEL_TYPE *pbx_chan, char **cid_number)
1748 {
1749 	if (pbx_chan && pbx_chan->caller.id.number.valid && pbx_chan->caller.id.number.str && strlen(pbx_chan->caller.id.number.str) > 0) {
1750 		*cid_number = pbx_strdup(pbx_chan->caller.id.number.str);
1751 		return 1;
1752 	}
1753 	return 0;
1754 }
1755 
1756 /*
1757  * \brief get callerid_ton from pbx
1758  * \param ast_chan Asterisk Channel
1759  * \return char * with the caller number
1760  */
sccp_astwrap_callerid_ton(PBX_CHANNEL_TYPE * pbx_chan,int * cid_ton)1761 static int sccp_astwrap_callerid_ton(PBX_CHANNEL_TYPE *pbx_chan, int *cid_ton)
1762 {
1763 	if (pbx_chan && pbx_chan->caller.id.number.valid) {
1764 		*cid_ton = pbx_chan->caller.ani.number.plan;
1765 		return *cid_ton;
1766 	}
1767 	return 0;
1768 }
1769 
1770 /*
1771  * \brief get callerid_ani from pbx
1772  * \param ast_chan Asterisk Channel
1773  * \return char * with the caller number
1774  */
sccp_astwrap_callerid_ani(PBX_CHANNEL_TYPE * pbx_chan,char ** cid_ani)1775 static int sccp_astwrap_callerid_ani(PBX_CHANNEL_TYPE *pbx_chan, char **cid_ani)
1776 {
1777 	if (pbx_chan && pbx_chan->caller.ani.number.valid && pbx_chan->caller.ani.number.str && strlen(pbx_chan->caller.ani.number.str) > 0) {
1778 		*cid_ani = pbx_strdup(pbx_chan->caller.ani.number.str);
1779 		return 1;
1780 	}
1781 	return 0;
1782 }
1783 
1784 /*
1785  * \brief get callerid_dnid from pbx
1786  * \param ast_chan Asterisk Channel
1787  * \return char * with the caller number
1788  */
sccp_astwrap_callerid_subaddr(PBX_CHANNEL_TYPE * pbx_chan,char ** cid_subaddr)1789 static int sccp_astwrap_callerid_subaddr(PBX_CHANNEL_TYPE *pbx_chan, char **cid_subaddr)
1790 {
1791 	if (pbx_chan && pbx_chan->caller.id.subaddress.valid && pbx_chan->caller.id.subaddress.str && strlen(pbx_chan->caller.id.subaddress.str) > 0) {
1792 		*cid_subaddr = pbx_strdup(pbx_chan->caller.id.subaddress.str);
1793 		return 1;
1794 	}
1795 	return 0;
1796 }
1797 
1798 /*
1799  * \brief get callerid_dnid from pbx (Destination ID)
1800  * \param ast_chan Asterisk Channel
1801  * \return char * with the caller number
1802  */
sccp_astwrap_callerid_dnid(PBX_CHANNEL_TYPE * pbx_chan,char ** cid_dnid)1803 static int sccp_astwrap_callerid_dnid(PBX_CHANNEL_TYPE *pbx_chan, char **cid_dnid)
1804 {
1805 	if (pbx_chan && pbx_chan->dialed.number.str && strlen(pbx_chan->dialed.number.str) > 0) {
1806 		*cid_dnid = pbx_strdup(pbx_chan->dialed.number.str);
1807 		return 1;
1808 	}
1809 	return 0;
1810 }
1811 
1812 /*
1813  * \brief get callerid_rdnis from pbx
1814  * \param ast_chan Asterisk Channel
1815  * \return char * with the caller number
1816  */
sccp_astwrap_callerid_rdnis(PBX_CHANNEL_TYPE * pbx_chan,char ** cid_rdnis)1817 static int sccp_astwrap_callerid_rdnis(PBX_CHANNEL_TYPE *pbx_chan, char **cid_rdnis)
1818 {
1819 	if (pbx_chan && pbx_chan->redirecting.from.number.valid && pbx_chan->redirecting.from.number.str && strlen(pbx_chan->redirecting.from.number.str) > 0) {
1820 		*cid_rdnis = pbx_strdup(pbx_chan->redirecting.from.number.str);
1821 		return 1;
1822 	}
1823 	return 0;
1824 }
1825 
1826 /*
1827  * \brief get callerid_presence from pbx
1828  * \param ast_chan Asterisk Channel
1829  * \return char * with the caller number
1830  */
sccp_astwrap_callerid_presentation(PBX_CHANNEL_TYPE * pbx_chan)1831 static sccp_callerid_presentation_t sccp_astwrap_callerid_presentation(PBX_CHANNEL_TYPE *pbx_chan)
1832 {
1833 	if (pbx_chan && (ast_party_id_presentation(&pbx_chan->caller.id) & AST_PRES_RESTRICTION) == AST_PRES_ALLOWED) {
1834 		return CALLERID_PRESENTATION_ALLOWED;
1835 	}
1836 	return CALLERID_PRESENTATION_FORBIDDEN;
1837 }
1838 
sccp_astwrap_createRtpInstance(constDevicePtr d,constChannelPtr c,sccp_rtp_t * rtp)1839 static boolean_t sccp_astwrap_createRtpInstance(constDevicePtr d, constChannelPtr c, sccp_rtp_t *rtp)
1840 {
1841 	uint32_t tos = 0, cos = 0;
1842 
1843 	if (!c || !d) {
1844 		return FALSE;
1845 	}
1846 	struct sockaddr_storage ourip = { 0 };
1847 	sccp_session_getOurIP(d->session, &ourip, 0);
1848 	struct ast_sockaddr sock = { {
1849 	    0,
1850 	} };
1851 	storage2ast_sockaddr(&ourip, &sock);
1852 
1853 	if ((rtp->instance = ast_rtp_instance_new("asterisk", sched, &sock, NULL))) {
1854 		struct ast_sockaddr instance_addr = { {0,} };
1855 		ast_rtp_instance_get_local_address(rtp->instance, &instance_addr);
1856 		sccp_log(DEBUGCAT_RTP) (VERBOSE_PREFIX_3 "%s: rtp server instance created at %s\n", c->designator, ast_sockaddr_stringify(&instance_addr));
1857 	} else {
1858 		return FALSE;
1859 	}
1860 
1861 	/* rest below should be moved out of here (refactoring required) */
1862 	PBX_RTP_TYPE *instance = rtp->instance;
1863 	//char *rtp_map_filter = NULL;
1864 	//skinny_payload_type_t codec_type;
1865 	int fd_offset = 0;
1866 	switch(rtp->type) {
1867 		case SCCP_RTP_AUDIO:
1868 			tos = d->audio_tos;
1869 			cos = d->audio_cos;
1870 			//rtp_map_filter = "audio";
1871 			//codec_type = SKINNY_CODEC_TYPE_AUDIO;
1872 			break;
1873 
1874 #if CS_SCCP_VIDEO
1875 		case SCCP_RTP_VIDEO:
1876 			tos = d->video_tos;
1877 			cos = d->video_cos;
1878 			//rtp_map_filter = "video";
1879 			//codec_type = SKINNY_CODEC_TYPE_VIDEO;
1880 			fd_offset = 2;
1881 			break;
1882 #endif
1883 		default:
1884 			pbx_log(LOG_ERROR, "%s: (wrapper_create_rtp) unknown/unhandled rtp type, returning instance for now\n", c->designator);
1885 			return TRUE;
1886 	}
1887 
1888 	if (c->owner) {
1889 		ast_channel_set_fd(c->owner, fd_offset, ast_rtp_instance_fd(instance, 0));		// RTP
1890 		ast_channel_set_fd(c->owner, fd_offset + 1, ast_rtp_instance_fd(instance, 1));		// RTCP
1891 	}
1892 	ast_rtp_instance_set_prop(instance, AST_RTP_PROPERTY_RTCP, 1);
1893 	if (rtp->type == SCCP_RTP_AUDIO) {
1894 		ast_rtp_instance_set_prop(instance, AST_RTP_PROPERTY_DTMF, 1);
1895 		if (c->dtmfmode == SCCP_DTMFMODE_SKINNY) {
1896 			ast_rtp_instance_set_prop(instance, AST_RTP_PROPERTY_DTMF_COMPENSATE, 1);
1897 			ast_rtp_instance_dtmf_mode_set(instance, AST_RTP_DTMF_MODE_INBAND);
1898 		}
1899 	}
1900 	ast_rtp_instance_set_qos(instance, tos, cos, "SCCP RTP");
1901 
1902 	// Add CISCO DTMF SKINNY payload type
1903 	if (rtp->type == SCCP_RTP_AUDIO && SCCP_DTMFMODE_SKINNY == d->dtmfmode) {
1904 		ast_rtp_codecs_payloads_set_m_type(ast_rtp_instance_get_codecs(c->rtp.audio.instance), c->rtp.audio.instance, 96);
1905 		ast_rtp_codecs_payloads_set_rtpmap_type(ast_rtp_instance_get_codecs(c->rtp.audio.instance), c->rtp.audio.instance, 96, "audio", "telephone-event", 0);
1906 		ast_rtp_codecs_payloads_set_m_type(ast_rtp_instance_get_codecs(c->rtp.audio.instance), c->rtp.audio.instance, 101);
1907 		ast_rtp_codecs_payloads_set_rtpmap_type(ast_rtp_instance_get_codecs(c->rtp.audio.instance), c->rtp.audio.instance, 101, "audio", "telephone-event", 0);
1908 		ast_rtp_codecs_payloads_set_m_type(ast_rtp_instance_get_codecs(c->rtp.audio.instance), c->rtp.audio.instance, 105);
1909 		ast_rtp_codecs_payloads_set_rtpmap_type(ast_rtp_instance_get_codecs(c->rtp.audio.instance), c->rtp.audio.instance, 105, "audio", "cisco-telephone-event", 0);
1910 	}
1911 	if (c->owner) {
1912 		// this prevent a warning about unknown codec, when rtp traffic starts */
1913 		ast_queue_frame(c->owner, &ast_null_frame);
1914 	}
1915 
1916 	return TRUE;
1917 }
1918 
sccp_wrapper_get_dtmf_payload_code(constChannelPtr c)1919 static uint sccp_wrapper_get_dtmf_payload_code(constChannelPtr c)
1920 {
1921 	int rtp_code = 0;
1922 	if (SCCP_DTMFMODE_SKINNY != c->dtmfmode) {
1923 		rtp_code = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(c->rtp.audio.instance), 0, NULL, AST_RTP_DTMF);
1924 	}
1925 	sccp_log(DEBUGCAT_RTP)(VERBOSE_PREFIX_3 "%s: Using dtmf rtp_code : %d\n", c->designator, rtp_code);
1926 	return rtp_code != -1 ? rtp_code : 0;
1927 }
1928 
sccp_astwrap_destroyRTP(PBX_RTP_TYPE * rtp)1929 static boolean_t sccp_astwrap_destroyRTP(PBX_RTP_TYPE * rtp)
1930 {
1931 	int res;
1932 
1933 	res = ast_rtp_instance_destroy(rtp);
1934 	return (!res) ? TRUE : FALSE;
1935 }
1936 
sccp_astwrap_checkHangup(const sccp_channel_t * channel)1937 static boolean_t sccp_astwrap_checkHangup(const sccp_channel_t * channel)
1938 {
1939 	int res;
1940 
1941 	res = ast_check_hangup(channel->owner);
1942 	return (!res) ? TRUE : FALSE;
1943 }
1944 
sccp_astwrap_rtpGetPeer(PBX_RTP_TYPE * rtp,struct sockaddr_storage * address)1945 static boolean_t sccp_astwrap_rtpGetPeer(PBX_RTP_TYPE * rtp, struct sockaddr_storage *address)
1946 {
1947 	struct ast_sockaddr addr;
1948 
1949 	ast_rtp_instance_get_remote_address(rtp, &addr);
1950 	memcpy(address, &addr.ss, sizeof(struct sockaddr_storage));
1951 	return TRUE;
1952 }
1953 
sccp_astwrap_rtpGetUs(PBX_RTP_TYPE * rtp,struct sockaddr_storage * address)1954 static boolean_t sccp_astwrap_rtpGetUs(PBX_RTP_TYPE * rtp, struct sockaddr_storage *address)
1955 {
1956 	struct ast_sockaddr addr;
1957 
1958 	ast_rtp_instance_get_local_address(rtp, &addr);
1959 	memcpy(address, &addr.ss, sizeof(struct sockaddr_storage));
1960 	return TRUE;
1961 }
1962 
sccp_astwrap_getChannelByName(const char * name,PBX_CHANNEL_TYPE ** pbx_channel)1963 static boolean_t sccp_astwrap_getChannelByName(const char *name, PBX_CHANNEL_TYPE ** pbx_channel)
1964 {
1965 	PBX_CHANNEL_TYPE *ast = ast_channel_get_by_name(name);
1966 
1967 	if (!ast) {
1968 		return FALSE;
1969 	}
1970 	pbx_channel_lock(ast);
1971 	*pbx_channel = pbx_channel_ref(ast);
1972 	pbx_channel_unlock(ast);
1973 	return TRUE;
1974 }
1975 
1976 //static int sccp_astwrap_rtp_set_peer(const struct sccp_rtp *rtp, const struct sockaddr_storage *new_peer, int nat_active)
sccp_astwrap_setPhoneRTPAddress(const struct sccp_rtp * rtp,const struct sockaddr_storage * new_peer,int nat_active)1977 static int sccp_astwrap_setPhoneRTPAddress(const struct sccp_rtp *rtp, const struct sockaddr_storage *new_peer, int nat_active)
1978 {
1979 	struct ast_sockaddr ast_sockaddr_dest;
1980 	int res;
1981 
1982 	memcpy(&ast_sockaddr_dest.ss, new_peer, sizeof(struct sockaddr_storage));
1983 	ast_sockaddr_dest.len = (ast_sockaddr_dest.ss.ss_family == AF_INET6) ? sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in);
1984 	res = ast_rtp_instance_set_remote_address(rtp->instance, &ast_sockaddr_dest);
1985 
1986 	sccp_log((DEBUGCAT_RTP | DEBUGCAT_HIGH)) (VERBOSE_PREFIX_3 "SCCP: (setPhoneRTPAddress) Update PBX to send RTP/UDP media to '%s:%d' (new remote) (NAT: %s)\n", ast_sockaddr_stringify_host(&ast_sockaddr_dest), ast_sockaddr_port(&ast_sockaddr_dest), S_COR(nat_active, "yes", "no"));
1987 	if (nat_active) {
1988 		ast_rtp_instance_set_prop(rtp->instance, AST_RTP_PROPERTY_NAT, 1);
1989 	} else {
1990 		ast_rtp_instance_set_prop(rtp->instance, AST_RTP_PROPERTY_NAT, 0);
1991 	}
1992 	return res;
1993 }
1994 
sccp_astwrap_setWriteFormat(const sccp_channel_t * channel,skinny_codec_t codec)1995 static boolean_t sccp_astwrap_setWriteFormat(const sccp_channel_t * channel, skinny_codec_t codec)
1996 {
1997 	//! \todo possibly needs to be synced to ast108
1998 	if (!channel) {
1999 		return FALSE;
2000 	}
2001 	struct ast_format fmt;
2002 
2003 	ast_format_set(&fmt, skinny_codec2pbx_codec(codec), 0);
2004 	ast_format_copy(&channel->owner->writeformat, &fmt);
2005 	ast_format_copy(&channel->owner->rawwriteformat, &fmt);
2006 	if (0 != channel->rtp.audio.instance) {
2007 		ast_rtp_instance_set_write_format(channel->rtp.audio.instance, &fmt);
2008 	}
2009 	return TRUE;
2010 }
2011 
sccp_astwrap_setReadFormat(const sccp_channel_t * channel,skinny_codec_t codec)2012 static boolean_t sccp_astwrap_setReadFormat(const sccp_channel_t * channel, skinny_codec_t codec)
2013 {
2014 	//! \todo possibly needs to be synced to ast108
2015 	if (!channel) {
2016 		return FALSE;
2017 	}
2018 	struct ast_format fmt;
2019 
2020 	ast_format_set(&fmt, skinny_codec2pbx_codec(codec), 0);
2021 	ast_format_copy(&channel->owner->readformat, &fmt);
2022 	ast_format_copy(&channel->owner->rawreadformat, &fmt);
2023 	if (0 != channel->rtp.audio.instance) {
2024 		ast_rtp_instance_set_read_format(channel->rtp.audio.instance, &fmt);
2025 	}
2026 	return TRUE;
2027 }
2028 
sccp_astwrap_setCalleridName(PBX_CHANNEL_TYPE * pbxChannel,const char * name)2029 static void sccp_astwrap_setCalleridName(PBX_CHANNEL_TYPE *pbxChannel, const char *name)
2030 {
2031 	if (pbxChannel && name) {
2032 		pbxChannel->caller.id.name.valid = 1;
2033 		ast_party_name_free(&pbxChannel->caller.id.name);
2034 		pbxChannel->caller.id.name.str = pbx_strdup(name);
2035 	}
2036 }
2037 
sccp_astwrap_setCalleridNumber(PBX_CHANNEL_TYPE * pbxChannel,const char * number)2038 static void sccp_astwrap_setCalleridNumber(PBX_CHANNEL_TYPE *pbxChannel, const char *number)
2039 {
2040 	if (pbxChannel && number) {
2041 		pbxChannel->caller.id.number.valid = 1;
2042 		ast_party_number_free(&pbxChannel->caller.id.number);
2043 		pbxChannel->caller.id.number.str = pbx_strdup(number);
2044 	}
2045 }
2046 
sccp_astwrap_setCalleridAni(PBX_CHANNEL_TYPE * pbxChannel,const char * number)2047 static void sccp_astwrap_setCalleridAni(PBX_CHANNEL_TYPE *pbxChannel, const char *number)
2048 {
2049 	if (pbxChannel && number) {
2050 		pbxChannel->caller.ani.number.valid = 1;
2051 		ast_party_number_free(&pbxChannel->caller.ani.number);
2052 		pbxChannel->caller.ani.number.str = pbx_strdup(number);
2053 	}
2054 }
2055 
sccp_astwrap_setRedirectingParty(PBX_CHANNEL_TYPE * pbxChannel,const char * number,const char * name)2056 static void sccp_astwrap_setRedirectingParty(PBX_CHANNEL_TYPE *pbxChannel, const char *number, const char *name)
2057 {
2058 	if (pbxChannel && number) {
2059 		ast_party_number_free(&pbxChannel->redirecting.from.number);
2060 		pbxChannel->redirecting.from.number.str = pbx_strdup(number);
2061 		pbxChannel->redirecting.from.number.valid = 1;
2062 	}
2063 
2064 	if (pbxChannel && name) {
2065 		ast_party_name_free(&pbxChannel->redirecting.from.name);
2066 		pbxChannel->redirecting.from.name.str = pbx_strdup(name);
2067 		pbxChannel->redirecting.from.name.valid = 1;
2068 	}
2069 }
2070 
sccp_astwrap_setRedirectedParty(PBX_CHANNEL_TYPE * pbxChannel,const char * number,const char * name)2071 static void sccp_astwrap_setRedirectedParty(PBX_CHANNEL_TYPE *pbxChannel, const char *number, const char *name)
2072 {
2073 	if (pbxChannel && number) {
2074 		pbxChannel->redirecting.to.number.valid = 1;
2075 		ast_party_number_free(&pbxChannel->redirecting.to.number);
2076 		pbxChannel->redirecting.to.number.str = pbx_strdup(number);
2077 	}
2078 
2079 	if (pbxChannel && name) {
2080 		pbxChannel->redirecting.to.name.valid = 1;
2081 		ast_party_name_free(&pbxChannel->redirecting.to.name);
2082 		pbxChannel->redirecting.to.name.str = pbx_strdup(name);
2083 	}
2084 }
2085 
sccp_astwrap_updateConnectedLine(const sccp_channel_t * channel,const char * number,const char * name,uint8_t reason)2086 static void sccp_astwrap_updateConnectedLine(const sccp_channel_t * channel, const char *number, const char *name, uint8_t reason)
2087 {
2088 	if (!channel || !channel->owner) {
2089 		return;
2090 	}
2091 	__sccp_astwrap_updateConnectedLine(channel->owner, number, name, reason);
2092 }
2093 
sccp_astwrap_sched_add(int when,sccp_sched_cb callback,const void * data)2094 static int sccp_astwrap_sched_add(int when, sccp_sched_cb callback, const void *data)
2095 {
2096 	if (sched) {
2097 		return ast_sched_add(sched, when, callback, data);
2098 	}
2099 	return -1;
2100 }
2101 
sccp_astwrap_sched_del(int id)2102 static int sccp_astwrap_sched_del(int id)
2103 {
2104 	if (sched) {
2105 		return AST_SCHED_DEL(sched, id);
2106 	}
2107 	return -1;
2108 }
2109 
sccp_astwrap_sched_add_ref(int * id,int when,sccp_sched_cb callback,sccp_channel_t * channel)2110 static int sccp_astwrap_sched_add_ref(int *id, int when, sccp_sched_cb callback, sccp_channel_t * channel)
2111 {
2112 	if (sched && channel) {
2113 		sccp_channel_t *c = sccp_channel_retain(channel);
2114 
2115 		if (c) {
2116 			if ((*id  = ast_sched_add(sched, when, callback, c)) < 0) {
2117 				sccp_log(DEBUGCAT_CORE)(VERBOSE_PREFIX_3 "%s: sched add id:%d, when:%d, failed\n", c->designator, *id, when);
2118 				sccp_channel_release(&channel);			/* explicit release during failure */
2119 			}
2120 			return *id;
2121 		}
2122 	}
2123 	return -2;
2124 }
2125 
sccp_astwrap_sched_del_ref(int * id,sccp_channel_t * channel)2126 static int sccp_astwrap_sched_del_ref(int *id, sccp_channel_t * channel)
2127 {
2128 	if (sched) {
2129 		AST_SCHED_DEL_UNREF(sched, *id, sccp_channel_release(&channel));
2130 		return *id;
2131 	}
2132 	return -2;
2133 }
2134 
sccp_astwrap_sched_replace_ref(int * id,int when,ast_sched_cb callback,sccp_channel_t * channel)2135 static int sccp_astwrap_sched_replace_ref(int *id, int when, ast_sched_cb callback, sccp_channel_t * channel)
2136 {
2137 	if (sched) {
2138 		// sccp_log(DEBUGCAT_CORE)(VERBOSE_PREFIX_3 "%s: (sched_replace_ref) replacing id: %d\n", channel->designator, *id);
2139 		AST_SCHED_REPLACE_UNREF(*id, sched, when, callback, channel, sccp_channel_release((sccp_channel_t **)&_data), sccp_channel_release(&channel), sccp_channel_retain(channel));	/* explicit retain/release */
2140 		// sccp_log(DEBUGCAT_CORE)(VERBOSE_PREFIX_3 "%s: (sched_replace_ref) returning id: %d\n", channel->designator, *id);
2141 		return *id;
2142 	}
2143 	return -2;
2144 }
2145 
sccp_astwrap_sched_when(int id)2146 static long sccp_astwrap_sched_when(int id)
2147 {
2148 	if (sched) {
2149 		return ast_sched_when(sched, id);
2150 	}
2151 	return FALSE;
2152 }
2153 
sccp_astwrap_sched_wait(int id)2154 static int sccp_astwrap_sched_wait(int id)
2155 {
2156 	if (sched) {
2157 		return ast_sched_wait(sched);
2158 	}
2159 	return FALSE;
2160 }
2161 
sccp_astwrap_setCallState(const sccp_channel_t * channel,enum ast_channel_state state)2162 static int sccp_astwrap_setCallState(const sccp_channel_t * channel, enum ast_channel_state state)
2163 {
2164         if (channel && channel->owner) {
2165 		pbx_setstate(channel->owner, state);
2166         }
2167 	//! \todo implement correct return value (take into account negative deadlock prevention)
2168 	return 0;
2169 }
2170 
sccp_astwrap_getRemoteChannel(const sccp_channel_t * channel,PBX_CHANNEL_TYPE ** pbx_channel)2171 static boolean_t sccp_astwrap_getRemoteChannel(const sccp_channel_t * channel, PBX_CHANNEL_TYPE ** pbx_channel)
2172 {
2173 
2174 	PBX_CHANNEL_TYPE *remotePeer;
2175 	struct ast_channel_iterator *iterator = ast_channel_iterator_all_new();
2176 
2177 	((struct ao2_iterator *) iterator)->flags |= AO2_ITERATOR_DONTLOCK;
2178 
2179 	for (; (remotePeer = ast_channel_iterator_next(iterator)); remotePeer = pbx_channel_unref(remotePeer)) {
2180 		if (pbx_find_channel_by_linkid(remotePeer, (void *) channel->owner->linkedid)) {
2181 			break;
2182 		}
2183 	}
2184 	ast_channel_iterator_destroy(iterator);
2185 
2186 	if (remotePeer) {
2187 		*pbx_channel = remotePeer;
2188 		remotePeer = pbx_channel_unref(remotePeer);
2189 		return TRUE;
2190 	}
2191 	return FALSE;
2192 }
2193 
2194 /*!
2195  * \brief Send Text to Asterisk Channel
2196  * \param ast Asterisk Channel as ast_channel
2197  * \param text Text to be send as char
2198  * \return Succes as int
2199  *
2200  * \called_from_asterisk
2201  */
sccp_pbx_sendtext(PBX_CHANNEL_TYPE * ast,const char * text)2202 static int sccp_pbx_sendtext(PBX_CHANNEL_TYPE * ast, const char *text)
2203 {
2204 	uint8_t instance;
2205 
2206 	if (!ast) {
2207 		sccp_log((DEBUGCAT_CORE)) (VERBOSE_PREFIX_3 "SCCP: No PBX CHANNEL to send text to\n");
2208 		return -1;
2209 	}
2210 
2211 	AUTO_RELEASE(sccp_channel_t, c , get_sccp_channel_from_pbx_channel(ast));
2212 	if (!c) {
2213 		sccp_log((DEBUGCAT_CORE)) (VERBOSE_PREFIX_3 "SCCP: No SCCP CHANNEL to send text to (%s)\n", pbx_channel_name(ast));
2214 		return -1;
2215 	}
2216 
2217 	AUTO_RELEASE(sccp_device_t, d , sccp_channel_getDevice(c));
2218 	if (!d) {
2219 		sccp_log((DEBUGCAT_CORE)) (VERBOSE_PREFIX_3 "SCCP: No SCCP DEVICE to send text to (%s)\n", pbx_channel_name(ast));
2220 		return -1;
2221 	}
2222 
2223 	sccp_log((DEBUGCAT_CORE)) (VERBOSE_PREFIX_3 "%s: Sending text %s on %s\n", d->id, text, pbx_channel_name(ast));
2224 
2225 	instance = sccp_device_find_index_for_line(d, c->line->name);
2226 	sccp_dev_displayprompt(d, instance, c->callid, (char *) text, 10);
2227 	return 0;
2228 }
2229 
2230 /*!
2231  * \brief Receive First Digit from Asterisk Channel
2232  * \param ast Asterisk Channel as ast_channel
2233  * \param digit First Digit as char
2234  * \return Always Return -1 as int
2235  *
2236  * \called_from_asterisk
2237  */
sccp_wrapper_recvdigit_begin(PBX_CHANNEL_TYPE * ast,char digit)2238 static int sccp_wrapper_recvdigit_begin(PBX_CHANNEL_TYPE * ast, char digit)
2239 {
2240 	return -1;
2241 }
2242 
2243 /*!
2244  * \brief Receive Last Digit from Asterisk Channel
2245  * \param ast Asterisk Channel as ast_channel
2246  * \param digit Last Digit as char
2247  * \param duration Duration as int
2248  * \return boolean
2249  *
2250  * \called_from_asterisk
2251  */
sccp_wrapper_recvdigit_end(PBX_CHANNEL_TYPE * ast,char digit,unsigned int duration)2252 static int sccp_wrapper_recvdigit_end(PBX_CHANNEL_TYPE * ast, char digit, unsigned int duration)
2253 {
2254 	AUTO_RELEASE(sccp_channel_t, c , get_sccp_channel_from_pbx_channel(ast));
2255 	if (c) {
2256 		if (c->dtmfmode == SCCP_DTMFMODE_RFC2833) {
2257 			sccp_log((DEBUGCAT_CORE)) (VERBOSE_PREFIX_3 "%s: Channel(%s) DTMF Mode is RFC2833. Skipping...\n", c->designator, pbx_channel_name(ast));
2258 			return -1;
2259 		}
2260 
2261 		AUTO_RELEASE(sccp_device_t, d , sccp_channel_getDevice(c));
2262 		if (!d) {
2263 			sccp_log((DEBUGCAT_CORE)) (VERBOSE_PREFIX_3 "SCCP: No SCCP DEVICE to send digit to (%s)\n", pbx_channel_name(ast));
2264 			return -1;
2265 		}
2266 
2267 		sccp_log((DEBUGCAT_CORE)) (VERBOSE_PREFIX_3 "%s: Asterisk asked to send dtmf '%d' to channel %s. Trying to send it %s\n", d->id, digit, pbx_channel_name(ast), sccp_dtmfmode2str(d->dtmfmode));
2268 		if (c->state != SCCP_CHANNELSTATE_CONNECTED) {
2269 			sccp_log((DEBUGCAT_CORE)) (VERBOSE_PREFIX_3 "%s: Can't send the dtmf '%d' %c to a not connected channel %s\n", d->id, digit, digit, pbx_channel_name(ast));
2270 			return -1;
2271 		}
2272 		sccp_dev_keypadbutton(d, digit, sccp_device_find_index_for_line(d, c->line->name), c->callid);
2273 	} else {
2274 		sccp_log((DEBUGCAT_CORE)) (VERBOSE_PREFIX_3 "SCCP: No SCCP CHANNEL to send digit to (%s)\n", pbx_channel_name(ast));
2275 		return -1;
2276 	}
2277 
2278 	return -1;
2279 }
2280 
sccp_astwrap_findChannelWithCallback(int (* const found_cb)(PBX_CHANNEL_TYPE * c,void * data),void * data,boolean_t lock)2281 static PBX_CHANNEL_TYPE *sccp_astwrap_findChannelWithCallback(int (*const found_cb) (PBX_CHANNEL_TYPE * c, void *data), void *data, boolean_t lock)
2282 {
2283 	PBX_CHANNEL_TYPE *remotePeer;
2284 
2285 	struct ast_channel_iterator *iterator = ast_channel_iterator_all_new();
2286 
2287 	if (!lock) {
2288 		((struct ao2_iterator *) iterator)->flags |= AO2_ITERATOR_DONTLOCK;
2289 	}
2290 
2291 	for (; (remotePeer = ast_channel_iterator_next(iterator)); remotePeer = pbx_channel_unref(remotePeer)) {
2292 
2293 		if (found_cb(remotePeer, data)) {
2294 			ast_channel_lock(remotePeer);
2295 			break;
2296 		}
2297 
2298 	}
2299 	ast_channel_iterator_destroy(iterator);
2300 	return remotePeer;
2301 }
2302 
2303 /*! \brief Set an option on a asterisk channel */
2304 #if 0
2305 static int sccp_astwrap_setOption(PBX_CHANNEL_TYPE * ast, int option, void *data, int datalen)
2306 {
2307 	int res = -1;
2308 	AUTO_RELEASE(sccp_channel_t, c , get_sccp_channel_from_pbx_channel(ast));
2309 
2310 	if (c) {
2311 		sccp_log((DEBUGCAT_CORE)) (VERBOSE_PREFIX_2 "%s: channel: %s(%s) setOption: %d\n", c->currentDeviceId, sccp_channel_toString(c), ast->name, option);
2312 		//! if AST_OPTION_FORMAT_READ / AST_OPTION_FORMAT_WRITE are available we might be indication that we can do transcoding (channel.c:set_format). Correct ? */
2313 		switch (option) {
2314 			case AST_OPTION_FORMAT_READ:
2315 				if (c->rtp.audio.instance) {
2316 					res = ast_rtp_instance_set_read_format(c->rtp.audio.instance, (struct ast_format *) data);
2317 				}
2318 				//sccp_astwrap_setReadFormat(c, (struct ast_format *) data);
2319 				break;
2320 			case AST_OPTION_FORMAT_WRITE:
2321 				if (c->rtp.audio.instance) {
2322 					//res = ast_rtp_instance_set_write_format(c->rtp.audio.instance, (struct ast_format *) data);
2323 				}
2324 				//sccp_astwrap_setWriteFormat(c, (struct ast_format *) data);
2325 				break;
2326 
2327 			case AST_OPTION_MAKE_COMPATIBLE:
2328 				if (c->rtp.audio.instance) {
2329 					//res = ast_rtp_instance_make_compatible(ast, c->rtp.audio.instance, (PBX_CHANNEL_TYPE *) data);
2330 				}
2331 				break;
2332 			case AST_OPTION_DIGIT_DETECT:
2333 			case AST_OPTION_SECURE_SIGNALING:
2334 			case AST_OPTION_SECURE_MEDIA:
2335 				res = -1;
2336 				break;
2337 			default:
2338 				break;
2339 		}
2340 	}
2341 	return res;
2342 }
2343 #endif
2344 
sccp_astwrap_set_pbxchannel_linkedid(PBX_CHANNEL_TYPE * pbx_channel,const char * new_linkedid)2345 static void sccp_astwrap_set_pbxchannel_linkedid(PBX_CHANNEL_TYPE * pbx_channel, const char *new_linkedid)
2346 {
2347 	if (pbx_channel) {
2348 		if (!strcmp(pbx_channel->linkedid, new_linkedid)) {
2349 			return;
2350 		}
2351 #if HAVE_PBX_CEL_H
2352 		ast_cel_check_retire_linkedid(pbx_channel);
2353 #endif
2354 		ast_string_field_set(pbx_channel, linkedid, new_linkedid);
2355 #if CS_AST_CEL_LINKEDID_REF
2356 		ast_cel_linkedid_ref(new_linkedid);
2357 #endif
2358 	}
2359 };
2360 
2361 #define DECLARE_PBX_CHANNEL_STRGET(_field) 									\
2362 static const char *sccp_astwrap_get_channel_##_field(const sccp_channel_t * channel)	 		\
2363 {														\
2364 	static const char *empty_channel_##_field = "--no-channel-" #_field "--";				\
2365 	if (channel && channel->owner) {											\
2366 		return channel->owner->_field;									\
2367 	}													\
2368 	return empty_channel_##_field;										\
2369 };
2370 
2371 #define DECLARE_PBX_CHANNEL_STRSET(_field)									\
2372 static void sccp_astwrap_set_channel_##_field(const sccp_channel_t * channel, const char * (_field))	\
2373 { 														\
2374         if (channel && channel->owner) {											\
2375         	sccp_copy_string(channel->owner->_field, _field, sizeof(channel->owner->_field));		\
2376         }													\
2377 };
2378 
2379 DECLARE_PBX_CHANNEL_STRGET(name)
DECLARE_PBX_CHANNEL_STRGET(uniqueid)2380     DECLARE_PBX_CHANNEL_STRGET(uniqueid)
2381     DECLARE_PBX_CHANNEL_STRGET(appl)
2382     DECLARE_PBX_CHANNEL_STRGET(linkedid)
2383     DECLARE_PBX_CHANNEL_STRGET(exten)
2384     DECLARE_PBX_CHANNEL_STRSET(exten)
2385     DECLARE_PBX_CHANNEL_STRGET(context)
2386     DECLARE_PBX_CHANNEL_STRSET(context)
2387     DECLARE_PBX_CHANNEL_STRGET(macroexten)
2388     DECLARE_PBX_CHANNEL_STRSET(macroexten)
2389     DECLARE_PBX_CHANNEL_STRGET(macrocontext)
2390     DECLARE_PBX_CHANNEL_STRSET(macrocontext)
2391     DECLARE_PBX_CHANNEL_STRGET(call_forward)
2392 
2393 static void sccp_astwrap_set_channel_linkedid(const sccp_channel_t * channel, const char *new_linkedid)
2394 {
2395 	if (channel && channel->owner) {
2396 		sccp_astwrap_set_pbxchannel_linkedid(channel->owner, new_linkedid);
2397 	}
2398 };
2399 
sccp_astwrap_set_channel_name(const sccp_channel_t * channel,const char * new_name)2400 static void sccp_astwrap_set_channel_name(const sccp_channel_t * channel, const char *new_name)
2401 {
2402 	if (channel && channel->owner) {
2403 		pbx_string_field_build(channel->owner, name, "%s", new_name);
2404 	}
2405 };
2406 
sccp_astwrap_set_channel_call_forward(const sccp_channel_t * channel,const char * new_call_forward)2407 static void sccp_astwrap_set_channel_call_forward(const sccp_channel_t * channel, const char *new_call_forward)
2408 {
2409 	if (channel && channel->owner) {
2410 		pbx_string_field_set(channel->owner, call_forward, new_call_forward);
2411 	}
2412 }
2413 
sccp_astwrap_get_channel_state(const sccp_channel_t * channel)2414 static enum ast_channel_state sccp_astwrap_get_channel_state(const sccp_channel_t * channel)
2415 {
2416 	if (channel && channel->owner) {
2417 		return channel->owner->_state;
2418 	}
2419 	return 0;
2420 }
2421 
sccp_astwrap_get_channel_pbx(const sccp_channel_t * channel)2422 static const struct ast_pbx *sccp_astwrap_get_channel_pbx(const sccp_channel_t * channel)
2423 {
2424 	if (channel && channel->owner) {
2425 		return channel->owner->pbx;
2426 	}
2427 	return NULL;
2428 }
2429 
sccp_pbx_sendHTML(PBX_CHANNEL_TYPE * ast,int subclass,const char * data,int datalen)2430 static int sccp_pbx_sendHTML(PBX_CHANNEL_TYPE * ast, int subclass, const char *data, int datalen)
2431 {
2432 	int res = -1;
2433 	if (!datalen || sccp_strlen_zero(data) || !(!strncmp(data, "http://", 7) || !strncmp(data, "file://", 7) || !strncmp(data, "ftp://", 6))) {
2434 		pbx_log(LOG_NOTICE, "SCCP: Received a non valid URL\n");
2435 		return res;
2436 	}
2437 	struct ast_frame fr;
2438 
2439 	AUTO_RELEASE(sccp_channel_t, c , get_sccp_channel_from_pbx_channel(ast));
2440 	if (c) {
2441 		AUTO_RELEASE(sccp_device_t, d , c->getDevice(c));
2442 		if (d) {
2443 			memset(&fr, 0, sizeof(fr));
2444 			fr.frametype = AST_FRAME_HTML;
2445 			fr.data.ptr = (char *) data;
2446 			fr.src = "SCCP Send URL";
2447 			fr.datalen = datalen;
2448 
2449 			sccp_push_result_t pushResult = d->pushURL(d, data, 1, SKINNY_TONE_ZIP);
2450 
2451 			if (SCCP_PUSH_RESULT_SUCCESS == pushResult) {
2452 				fr.subclass.integer = AST_HTML_LDCOMPLETE;
2453 			} else {
2454 				fr.subclass.integer = AST_HTML_NOSUPPORT;
2455 			}
2456 			ast_queue_frame(ast, ast_frisolate(&fr));
2457 			res = 0;
2458 		}
2459 	}
2460 	return res;
2461 }
2462 
2463 /*!
2464  * \brief Queue a control frame
2465  * \param pbx_channel PBX Channel
2466  * \param control as Asterisk Control Frame Type
2467  */
sccp_astwrap_queue_control(const PBX_CHANNEL_TYPE * pbx_channel,enum ast_control_frame_type control)2468 int sccp_astwrap_queue_control(const PBX_CHANNEL_TYPE * pbx_channel, enum ast_control_frame_type control)
2469 {
2470 	struct ast_frame f = { AST_FRAME_CONTROL,.subclass.integer = control };
2471 	return ast_queue_frame((PBX_CHANNEL_TYPE *) pbx_channel, &f);
2472 }
2473 
2474 /*!
2475  * \brief Queue a control frame with payload
2476  * \param pbx_channel PBX Channel
2477  * \param control as Asterisk Control Frame Type
2478  * \param data Payload
2479  * \param datalen Payload Length
2480  */
sccp_astwrap_queue_control_data(const PBX_CHANNEL_TYPE * pbx_channel,enum ast_control_frame_type control,const void * data,size_t datalen)2481 int sccp_astwrap_queue_control_data(const PBX_CHANNEL_TYPE * pbx_channel, enum ast_control_frame_type control, const void *data, size_t datalen)
2482 {
2483 	struct ast_frame f = { AST_FRAME_CONTROL,.subclass.integer = control,.data.ptr = (void *) data,.datalen = datalen };
2484 	return ast_queue_frame((PBX_CHANNEL_TYPE *) pbx_channel, &f);
2485 }
2486 
2487 /*!
2488  * \brief Get Hint Extension State and return the matching Busy Lamp Field State
2489  */
sccp_astwrap_getExtensionState(const char * extension,const char * context)2490 static skinny_busylampfield_state_t sccp_astwrap_getExtensionState(const char *extension, const char *context)
2491 {
2492 	skinny_busylampfield_state_t result = SKINNY_BLF_STATUS_UNKNOWN;
2493 
2494 	if (sccp_strlen_zero(extension) || sccp_strlen_zero(context)) {
2495 		pbx_log(LOG_ERROR, "SCCP: iPbx.getExtensionState: Either extension:'%s' or context:;%s' provided is empty\n", extension, context);
2496 		return result;
2497 	}
2498 
2499 	int state = ast_extension_state(NULL, context, extension);
2500 
2501 	switch (state) {
2502 		case AST_EXTENSION_REMOVED:
2503 		case AST_EXTENSION_DEACTIVATED:
2504 		case AST_EXTENSION_UNAVAILABLE:
2505 			result = SKINNY_BLF_STATUS_UNKNOWN;
2506 			break;
2507 		case AST_EXTENSION_NOT_INUSE:
2508 			result = SKINNY_BLF_STATUS_IDLE;
2509 			break;
2510 		case AST_EXTENSION_INUSE:
2511 		case AST_EXTENSION_ONHOLD:
2512 		case AST_EXTENSION_ONHOLD + AST_EXTENSION_INUSE:
2513 		case AST_EXTENSION_BUSY:
2514 			result = SKINNY_BLF_STATUS_INUSE;
2515 			break;
2516 		case AST_EXTENSION_RINGING + AST_EXTENSION_INUSE:
2517 		case AST_EXTENSION_RINGING:
2518 			result = SKINNY_BLF_STATUS_ALERTING;
2519 			break;
2520 	}
2521 	sccp_log(DEBUGCAT_HINT) (VERBOSE_PREFIX_4 "SCCP: (getExtensionState) extension: %s@%s, extension_state: '%s (%d)' -> blf state '%d'\n", extension, context, ast_extension_state2str(state), state, result);
2522 	return result;
2523 }
2524 
sccp_astwrap_channelIsBridged(sccp_channel_t * channel)2525 static boolean_t sccp_astwrap_channelIsBridged(sccp_channel_t * channel)
2526 {
2527 	boolean_t res = FALSE;
2528 
2529 	if (!channel || !channel->owner) {
2530 		return res;
2531 	}
2532 	ast_channel_lock(channel->owner);
2533 	if (ast_bridged_channel(channel->owner)) {
2534 		res = TRUE;
2535 	}
2536 	ast_channel_unlock(channel->owner);
2537 	return res;
2538 }
2539 
sccp_astwrap_getBridgeChannel(PBX_CHANNEL_TYPE * pbx_channel)2540 static PBX_CHANNEL_TYPE *sccp_astwrap_getBridgeChannel(PBX_CHANNEL_TYPE * pbx_channel)
2541 {
2542 	PBX_CHANNEL_TYPE *bridgePeer = NULL;
2543 	if (pbx_channel && (bridgePeer = ast_bridged_channel(pbx_channel))) {
2544 		return pbx_channel_ref(bridgePeer);
2545 	};
2546 	return NULL;
2547 }
2548 
sccp_astwrap_getUnderlyingChannel(PBX_CHANNEL_TYPE * pbx_channel)2549 static PBX_CHANNEL_TYPE *sccp_astwrap_getUnderlyingChannel(PBX_CHANNEL_TYPE * pbx_channel)
2550 {
2551 	PBX_CHANNEL_TYPE *bridgePeer = NULL;
2552 	if (pbx_channel && (bridgePeer = pbx_channel->tech->bridged_channel(pbx_channel, NULL))) {
2553 		return pbx_channel_ref(bridgePeer);
2554 	}
2555 	return NULL;
2556 }
2557 
sccp_astwrap_attended_transfer(sccp_channel_t * destination_channel,sccp_channel_t * source_channel)2558 static boolean_t sccp_astwrap_attended_transfer(sccp_channel_t * destination_channel, sccp_channel_t * source_channel)
2559 {
2560 	// possibly move transfer related callinfo updates here
2561 	if (!destination_channel || !source_channel || !destination_channel->owner || !source_channel->owner) {
2562 		return FALSE;
2563 	}
2564 	PBX_CHANNEL_TYPE *pbx_destination_local_channel = destination_channel->owner;
2565 	PBX_CHANNEL_TYPE *pbx_source_remote_channel = sccp_astwrap_getBridgeChannel(source_channel->owner);
2566 
2567 	if (!pbx_destination_local_channel || !pbx_source_remote_channel) {
2568 		return FALSE;
2569 	}
2570 	return pbx_channel_masquerade(pbx_destination_local_channel, pbx_source_remote_channel);
2571 }
2572 
2573 /*!
2574  * \brief using RTP Glue Engine
2575  */
2576 #if defined(__cplusplus) || defined(c_plusplus)
2577 static struct ast_rtp_glue sccp_rtp = {
2578 	/* *INDENT-OFF* */
2579 	type:	SCCP_TECHTYPE_STR,
2580 	mod:	NULL,
2581 	get_rtp_info:sccp_astwrap_get_rtp_info,
2582 	get_vrtp_info:sccp_astwrap_get_vrtp_info,
2583 	get_trtp_info:NULL,
2584 	update_peer:sccp_astwrap_update_rtp_peer,
2585 	get_codec:sccp_astwrap_getCodec,
2586 	/* *INDENT-ON* */
2587 };
2588 #else
2589 static struct ast_rtp_glue sccp_rtp = {
2590 	/* *INDENT-OFF* */
2591 	.type = SCCP_TECHTYPE_STR,
2592 	.get_rtp_info = sccp_astwrap_get_rtp_info,
2593 	.get_vrtp_info = sccp_astwrap_get_vrtp_info,
2594 	.update_peer = sccp_astwrap_update_rtp_peer,
2595 	.get_codec = sccp_astwrap_getCodec,
2596 	/* *INDENT-ON* */
2597 };
2598 #endif
2599 
2600 #ifdef HAVE_PBX_MESSAGE_H
2601 #include <asterisk/message.h>
sccp_astwrap_message_send(const struct ast_msg * msg,const char * to,const char * from)2602 static int sccp_astwrap_message_send(const struct ast_msg *msg, const char *to, const char *from)
2603 {
2604 	char *lineName;
2605 	const char *messageText = ast_msg_get_body(msg);
2606 	int res = -1;
2607 
2608 	lineName = pbx_strdupa(to);
2609 	if (strchr(lineName, '@')) {
2610 		strsep(&lineName, "@");
2611 	} else {
2612 		strsep(&lineName, ":");
2613 	}
2614 	if (sccp_strlen_zero(lineName)) {
2615 		pbx_log(LOG_WARNING, "MESSAGE(to) is invalid for SCCP - '%s'\n", to);
2616 		return -1;
2617 	}
2618 
2619 	AUTO_RELEASE(sccp_line_t, line , sccp_line_find_byname(lineName, FALSE));
2620 	if (!line) {
2621 		pbx_log(LOG_WARNING, "line '%s' not found\n", lineName);
2622 		return -1;
2623 	}
2624 
2625 	/** \todo move this to line implementation */
2626 	sccp_linedevice_t * ld = NULL;
2627 	sccp_push_result_t pushResult;
2628 
2629 	SCCP_LIST_LOCK(&line->devices);
2630 	SCCP_LIST_TRAVERSE(&line->devices, ld, list) {
2631 		pushResult = ld->device->pushTextMessage(ld->device, messageText, from, 1, SKINNY_TONE_ZIP);
2632 		if (SCCP_PUSH_RESULT_SUCCESS == pushResult) {
2633 			res = 0;
2634 		}
2635 	}
2636 	SCCP_LIST_UNLOCK(&line->devices);
2637 
2638 	return res;
2639 }
2640 
2641 #if defined(__cplusplus) || defined(c_plusplus)
2642 static const struct ast_msg_tech sccp_msg_tech = {
2643 	/* *INDENT-OFF* */
2644 	name:	"sccp",
2645 	msg_send:sccp_astwrap_message_send,
2646 	/* *INDENT-ON* */
2647 };
2648 #else
2649 static const struct ast_msg_tech sccp_msg_tech = {
2650 	/* *INDENT-OFF* */
2651 	.name = "sccp",
2652 	.msg_send = sccp_astwrap_message_send,
2653 	/* *INDENT-ON* */
2654 };
2655 #endif
2656 
2657 #endif
2658 
pbx_manager_register(const char * action,int authority,int (* func)(struct mansession * s,const struct message * m),const char * synopsis,const char * description)2659 int pbx_manager_register(const char * action, int authority, int (*func)(struct mansession * s, const struct message * m), const char * synopsis, const char * description)
2660 {
2661 	return pbx_manager_register(action, authority, func, synopsis, description);
2662 }
2663 
sccp_wrapper_register_manager(const char * action,int authority,int (* func)(struct mansession * s,const struct message * m),const char * synopsis,const char * description)2664 static int sccp_wrapper_register_manager(const char * action, int authority, int (*func)(struct mansession * s, const struct message * m), const char * synopsis, const char * description)
2665 {
2666 	return pbx_manager_register(action, authority, func, synopsis, description);
2667 }
2668 
sccp_wrapper_register_application(const char * app_name,int (* execute)(struct ast_channel *,const char *))2669 static int sccp_wrapper_register_application(const char *app_name, int (*execute)(struct ast_channel *, const char *))
2670 {
2671 	return ast_register_application2(app_name, execute, NULL, NULL, ast_module_info->self);
2672 }
2673 
sccp_wrapper_unregister_application(const char * app_name)2674 static int sccp_wrapper_unregister_application(const char *app_name)
2675 {
2676 	return ast_unregister_application(app_name);
2677 }
2678 
sccp_wrapper_register_function(struct pbx_custom_function * custom_function)2679 static int sccp_wrapper_register_function(struct pbx_custom_function *custom_function)
2680 {
2681 	return __ast_custom_function_register(custom_function, ast_module_info->self);
2682 }
2683 
sccp_wrapper_unregister_function(struct pbx_custom_function * custom_function)2684 static int sccp_wrapper_unregister_function(struct pbx_custom_function *custom_function)
2685 {
2686 	return ast_custom_function_unregister(custom_function);
2687 }
2688 
sccp_astwrap_setLanguage(PBX_CHANNEL_TYPE * pbxChannel,const char * newLanguage)2689 static boolean_t sccp_astwrap_setLanguage(PBX_CHANNEL_TYPE * pbxChannel, const char *newLanguage)
2690 {
2691 
2692 	ast_string_field_set(pbxChannel, language, newLanguage);
2693 	return TRUE;
2694 }
2695 
2696 #if defined(__cplusplus) || defined(c_plusplus)
2697 const PbxInterface iPbx = {
2698 	/* *INDENT-OFF* */
2699 	alloc_pbxChannel: sccp_astwrap_allocPBXChannel,
2700 	set_callstate: sccp_astwrap_setCallState,
2701 	checkhangup: sccp_astwrap_checkHangup,
2702 	hangup: NULL,
2703 	extension_status: sccp_astwrap_extensionStatus,
2704 
2705 	setPBXChannelLinkedId: sccp_astwrap_set_pbxchannel_linkedid,
2706 	/** get channel by name */
2707 	getChannelByName: sccp_astwrap_getChannelByName,
2708 	getRemoteChannel: sccp_astwrap_getRemoteChannel,
2709 	getChannelByCallback: NULL,
2710 
2711 	getChannelLinkedId: sccp_astwrap_get_channel_linkedid,
2712 	setChannelLinkedId: sccp_astwrap_set_channel_linkedid,
2713 	getChannelName: sccp_astwrap_get_channel_name,
2714 	getChannelUniqueID: sccp_astwrap_get_channel_uniqueid,
2715 	getChannelExten: sccp_astwrap_get_channel_exten,
2716 	setChannelExten: sccp_astwrap_set_channel_exten,
2717 	getChannelContext: sccp_astwrap_get_channel_context,
2718 	setChannelContext: sccp_astwrap_set_channel_context,
2719 	getChannelMacroExten: sccp_astwrap_get_channel_macroexten,
2720 	setChannelMacroExten: sccp_astwrap_set_channel_macroexten,
2721 	getChannelMacroContext: sccp_astwrap_get_channel_macrocontext,
2722 	setChannelMacroContext: sccp_astwrap_set_channel_macrocontext,
2723 	getChannelCallForward: sccp_astwrap_get_channel_call_forward,
2724 	setChannelCallForward: sccp_astwrap_set_channel_call_forward,
2725 
2726 	getChannelAppl: sccp_astwrap_get_channel_appl,
2727 	getChannelState: sccp_astwrap_get_channel_state,
2728 	getChannelPbx: sccp_astwrap_get_channel_pbx,
2729 
2730 	set_nativeAudioFormats: sccp_astwrap_setNativeAudioFormats,
2731 	set_nativeVideoFormats: sccp_astwrap_setNativeVideoFormats,
2732 
2733 	getPeerCodecCapabilities: NULL,
2734 	send_digit: sccp_wrapper_sendDigit,
2735 	send_digits: sccp_wrapper_sendDigits,
2736 
2737 	sched_add: sccp_astwrap_sched_add,
2738 	sched_del: sccp_astwrap_sched_del,
2739 	sched_add_ref: sccp_astwrap_sched_add_ref,
2740 	sched_del_ref: sccp_astwrap_sched_del_ref,
2741 	sched_replace_ref: sccp_astwrap_sched_replace_ref,
2742 	sched_when: sccp_astwrap_sched_when,
2743 	sched_wait: sccp_astwrap_sched_wait,
2744 
2745 	/* rtp */
2746 	rtp_getPeer: sccp_astwrap_rtpGetPeer,
2747 	rtp_getUs: sccp_astwrap_rtpGetUs,
2748 	rtp_setPhoneAddress: sccp_astwrap_setPhoneRTPAddress,
2749 	rtp_setWriteFormat: sccp_astwrap_setWriteFormat,
2750 	rtp_setReadFormat: sccp_astwrap_setReadFormat,
2751 	rtp_destroy: sccp_astwrap_destroyRTP,
2752 	rtp_stop: ast_rtp_instance_stop,
2753 	rtp_codec: NULL,
2754 	rtp_create_instance: sccp_astwrap_createRtpInstance,
2755 	rtp_get_payloadType: sccp_astwrap_get_payloadType,
2756 	rtp_get_sampleRate: sccp_astwrap_get_sampleRate,
2757 	rtp_bridgePeers: NULL,
2758 
2759 	/* callerid */
2760 	get_callerid_name: sccp_astwrap_callerid_name,
2761 	get_callerid_number: sccp_astwrap_callerid_number,
2762 	get_callerid_ton: sccp_astwrap_callerid_ton,
2763 	get_callerid_ani: sccp_astwrap_callerid_ani,
2764 	get_callerid_subaddr: sccp_astwrap_callerid_subaddr,
2765 	get_callerid_dnid: sccp_astwrap_callerid_dnid,
2766 	get_callerid_rdnis: sccp_astwrap_callerid_rdnis,
2767 	get_callerid_presentation: sccp_astwrap_callerid_presentation,
2768 
2769 	set_callerid_name: sccp_astwrap_setCalleridName,
2770 	set_callerid_number: sccp_astwrap_setCalleridNumber,
2771 	set_callerid_ani: sccp_astwrap_setCalleridAni,
2772 	set_callerid_dnid: NULL,
2773 	set_callerid_redirectingParty: sccp_astwrap_setRedirectingParty,
2774 	set_callerid_redirectedParty: sccp_astwrap_setRedirectedParty,
2775 	set_callerid_presentation: sccp_astwrap_setCalleridPresentation,
2776 	set_connected_line: sccp_astwrap_updateConnectedLine,
2777 	sendRedirectedUpdate: sccp_astwrap_sendRedirectedUpdate,
2778 
2779 	/* feature section */
2780 	feature_park: sccp_astwrap_park,
2781 	feature_stopMusicOnHold: NULL,
2782 	feature_addToDatabase: sccp_astwrap_addToDatabase,
2783 	feature_getFromDatabase: sccp_astwrap_getFromDatabase,
2784 	feature_removeFromDatabase: sccp_astwrap_removeFromDatabase,
2785 	feature_removeTreeFromDatabase: sccp_astwrap_removeTreeFromDatabase,
2786 	feature_monitor: sccp_astgenwrap_featureMonitor,
2787 	getFeatureExtension: sccp_astwrap_getFeatureExtension,
2788 	getPickupExtension: sccp_astwrap_getPickupExtension,
2789 
2790 	eventSubscribe: NULL,
2791 	findChannelByCallback: sccp_astwrap_findChannelWithCallback,
2792 
2793 	moh_start: sccp_astwrap_moh_start,
2794 	moh_stop: sccp_astwrap_moh_stop,
2795 	queue_control: sccp_astwrap_queue_control,
2796 	queue_control_data: sccp_astwrap_queue_control_data,
2797 
2798 	allocTempPBXChannel: sccp_astwrap_allocTempPBXChannel,
2799 	masqueradeHelper: sccp_astwrap_masqueradeHelper,
2800 	requestAnnouncementChannel: sccp_astwrap_requestAnnouncementChannel,
2801 	set_language: sccp_astwrap_setLanguage,
2802 
2803 	getExtensionState: sccp_astwrap_getExtensionState,
2804 	findPickupChannelByExtenLocked: sccp_astwrap_findPickupChannelByExtenLocked,
2805 	findPickupChannelByGroupLocked: sccp_astwrap_findPickupChannelByGroupLocked,
2806 
2807 	set_owner: sccp_astwrap_setOwner,
2808 	removeTimingFD: sccp_astwrap_removeTimingFD,
2809 	dumpchan: NULL,
2810 	channel_is_bridged: sccp_astwrap_channelIsBridged,
2811 	get_bridged_channel: sccp_astwrap_getBridgeChannel,
2812 	get_underlying_channel: sccp_astwrap_getUnderlyingChannel,
2813 	attended_transfer: sccp_astwrap_attended_transfer,
2814 
2815 	set_callgroup: sccp_astgenwrap_set_callgroup,
2816 	set_pickupgroup: sccp_astgenwrap_set_pickupgroup,
2817 	set_named_callgroups: NULL,
2818 	set_named_pickupgroups: NULL,
2819 
2820 	register_manager: sccp_wrapper_register_manager,
2821 	register_application: sccp_wrapper_register_application,
2822 	unregister_application: sccp_wrapper_unregister_application,
2823 	register_function: sccp_wrapper_register_function,
2824 	unregister_function: sccp_wrapper_unregister_function,
2825 
2826 	get_dtmf_payload_code: sccp_wrapper_get_dtmf_payload_code,
2827 	/* *INDENT-ON* */
2828 };
2829 
2830 #else
2831 
2832 /*!
2833  * \brief SCCP - PBX Callback Functions
2834  * (Decoupling Tight Dependencies on Asterisk Functions)
2835  */
2836 const PbxInterface iPbx = {
2837 	/* *INDENT-OFF* */
2838 
2839 	/* channel */
2840 	.alloc_pbxChannel = sccp_astwrap_allocPBXChannel,
2841 	.extension_status = sccp_astwrap_extensionStatus,
2842 	.setPBXChannelLinkedId = sccp_astwrap_set_pbxchannel_linkedid,
2843 	.getChannelByName = sccp_astwrap_getChannelByName,
2844 
2845 	.getChannelLinkedId = sccp_astwrap_get_channel_linkedid,
2846 	.setChannelLinkedId = sccp_astwrap_set_channel_linkedid,
2847 	.getChannelName = sccp_astwrap_get_channel_name,
2848 	.setChannelName = sccp_astwrap_set_channel_name,
2849 	.getChannelUniqueID = sccp_astwrap_get_channel_uniqueid,
2850 	.getChannelExten = sccp_astwrap_get_channel_exten,
2851 	.setChannelExten = sccp_astwrap_set_channel_exten,
2852 	.getChannelContext = sccp_astwrap_get_channel_context,
2853 	.setChannelContext = sccp_astwrap_set_channel_context,
2854 	.getChannelMacroExten = sccp_astwrap_get_channel_macroexten,
2855 	.setChannelMacroExten = sccp_astwrap_set_channel_macroexten,
2856 	.getChannelMacroContext = sccp_astwrap_get_channel_macrocontext,
2857 	.setChannelMacroContext = sccp_astwrap_set_channel_macrocontext,
2858 	.getChannelCallForward = sccp_astwrap_get_channel_call_forward,
2859 	.setChannelCallForward = sccp_astwrap_set_channel_call_forward,
2860 
2861 	.getChannelAppl = sccp_astwrap_get_channel_appl,
2862 	.getChannelState = sccp_astwrap_get_channel_state,
2863 	.getChannelPbx = sccp_astwrap_get_channel_pbx,
2864 	.getRemoteChannel = sccp_astwrap_getRemoteChannel,
2865 	.checkhangup = sccp_astwrap_checkHangup,
2866 	/* digits */
2867 	.send_digits = sccp_wrapper_sendDigits,
2868 	.send_digit = sccp_wrapper_sendDigit,
2869 
2870 	/* schedulers */
2871 	.sched_add = sccp_astwrap_sched_add,
2872 	.sched_del = sccp_astwrap_sched_del,
2873 	.sched_add_ref = sccp_astwrap_sched_add_ref,
2874 	.sched_del_ref = sccp_astwrap_sched_del_ref,
2875 	.sched_replace_ref = sccp_astwrap_sched_replace_ref,
2876 	.sched_when = sccp_astwrap_sched_when,
2877 	.sched_wait = sccp_astwrap_sched_wait,
2878 	/* callstate / indicate */
2879 	.set_callstate = sccp_astwrap_setCallState,
2880 
2881 	/* codecs */
2882 	.set_nativeAudioFormats = sccp_astwrap_setNativeAudioFormats,
2883 	.set_nativeVideoFormats = sccp_astwrap_setNativeVideoFormats,
2884 
2885 	/* rtp */
2886 	.rtp_getPeer = sccp_astwrap_rtpGetPeer,
2887 	.rtp_getUs = sccp_astwrap_rtpGetUs,
2888 	.rtp_stop = ast_rtp_instance_stop,
2889 	.rtp_create_instance = sccp_astwrap_createRtpInstance,
2890 	.rtp_get_payloadType = sccp_astwrap_get_payloadType,
2891 	.rtp_get_sampleRate = sccp_astwrap_get_sampleRate,
2892 	.rtp_destroy = sccp_astwrap_destroyRTP,
2893 	.rtp_setWriteFormat = sccp_astwrap_setWriteFormat,
2894 	.rtp_setReadFormat = sccp_astwrap_setReadFormat,
2895 	.rtp_setPhoneAddress = sccp_astwrap_setPhoneRTPAddress,
2896 
2897 	/* callerid */
2898 	.get_callerid_name = sccp_astwrap_callerid_name,
2899 	.get_callerid_number = sccp_astwrap_callerid_number,
2900 	.get_callerid_ton = sccp_astwrap_callerid_ton,
2901 	.get_callerid_ani = sccp_astwrap_callerid_ani,
2902 	.get_callerid_subaddr = sccp_astwrap_callerid_subaddr,
2903 	.get_callerid_dnid = sccp_astwrap_callerid_dnid,
2904 	.get_callerid_rdnis = sccp_astwrap_callerid_rdnis,
2905 	.get_callerid_presentation = sccp_astwrap_callerid_presentation,
2906 	.set_callerid_name = sccp_astwrap_setCalleridName,
2907 	.set_callerid_number = sccp_astwrap_setCalleridNumber,
2908 	.set_callerid_ani = sccp_astwrap_setCalleridAni,
2909 	.set_callerid_dnid = NULL,                                        //! \todo implement callback
2910 	.set_callerid_redirectingParty = sccp_astwrap_setRedirectingParty,
2911 	.set_callerid_redirectedParty = sccp_astwrap_setRedirectedParty,
2912 	.set_callerid_presentation = sccp_astwrap_setCalleridPresentation,
2913 	.set_connected_line = sccp_astwrap_updateConnectedLine,
2914 	.sendRedirectedUpdate = sccp_astwrap_sendRedirectedUpdate,
2915 	/* database */
2916 	.feature_addToDatabase = sccp_astwrap_addToDatabase,
2917 	.feature_getFromDatabase = sccp_astwrap_getFromDatabase,
2918 	.feature_removeFromDatabase = sccp_astwrap_removeFromDatabase,
2919 	.feature_removeTreeFromDatabase = sccp_astwrap_removeTreeFromDatabase,
2920 	.feature_monitor = sccp_astgenwrap_featureMonitor,
2921 
2922 	.feature_park = sccp_astwrap_park,
2923 	.getFeatureExtension = sccp_astwrap_getFeatureExtension,
2924 	.getPickupExtension = sccp_astwrap_getPickupExtension,
2925 	.findChannelByCallback = sccp_astwrap_findChannelWithCallback,
2926 
2927 	.moh_start = sccp_astwrap_moh_start,
2928 	.moh_stop = sccp_astwrap_moh_stop,
2929 	.queue_control = sccp_astwrap_queue_control,
2930 	.queue_control_data = sccp_astwrap_queue_control_data,
2931 
2932 	.allocTempPBXChannel = sccp_astwrap_allocTempPBXChannel,
2933 	.masqueradeHelper = sccp_astwrap_masqueradeHelper,
2934 	.requestAnnouncementChannel = sccp_astwrap_requestAnnouncementChannel,
2935 	.set_language = sccp_astwrap_setLanguage,
2936 
2937 	.getExtensionState = sccp_astwrap_getExtensionState,
2938 	.findPickupChannelByExtenLocked = sccp_astwrap_findPickupChannelByExtenLocked,
2939 	.findPickupChannelByGroupLocked = sccp_astwrap_findPickupChannelByGroupLocked,
2940 
2941 	.set_owner = sccp_astwrap_setOwner,
2942 	.removeTimingFD = sccp_astwrap_removeTimingFD,
2943 	.dumpchan = NULL,
2944 	.channel_is_bridged = sccp_astwrap_channelIsBridged,
2945 	.get_bridged_channel = sccp_astwrap_getBridgeChannel,
2946 	.get_underlying_channel = sccp_astwrap_getUnderlyingChannel,
2947 	.attended_transfer = sccp_astwrap_attended_transfer,
2948 
2949 	.set_callgroup = sccp_astgenwrap_set_callgroup,
2950 	.set_pickupgroup = sccp_astgenwrap_set_pickupgroup,
2951 	.set_named_callgroups = NULL,
2952 	.set_named_pickupgroups = NULL,
2953 
2954 	.register_manager = sccp_wrapper_register_manager,
2955 	.register_application = sccp_wrapper_register_application,
2956 	.unregister_application = sccp_wrapper_unregister_application,
2957 	.register_function = sccp_wrapper_register_function,
2958 	.unregister_function = sccp_wrapper_unregister_function,
2959 
2960 	.get_dtmf_payload_code = sccp_wrapper_get_dtmf_payload_code,
2961 	/* *INDENT-ON* */
2962 };
2963 #endif
2964 
unload_module(void)2965 static int unload_module(void)
2966 {
2967 	sccp_preUnload();
2968 	sccp_log((DEBUGCAT_CORE)) (VERBOSE_PREFIX_2 "SCCP: Unregister SCCP RTP protocol\n");
2969 	ast_rtp_glue_unregister(&sccp_rtp);
2970 	sccp_log((DEBUGCAT_CORE)) (VERBOSE_PREFIX_2 "SCCP: Unregister SCCP Channel Tech\n");
2971 
2972 	sccp_tech.capabilities = ast_format_cap_destroy(sccp_tech.capabilities);
2973 	ast_channel_unregister(&sccp_tech);
2974 	sccp_unregister_dialplan_functions();
2975 	sccp_unregister_cli();
2976 #ifdef CS_SCCP_MANAGER
2977 	sccp_unregister_management();
2978 #endif
2979 #ifdef HAVE_PBX_MESSAGE_H
2980 	ast_msg_tech_unregister(&sccp_msg_tech);
2981 #endif
2982 
2983 	if (io) {
2984 		io_context_destroy(io);
2985 		io = NULL;
2986 	}
2987 	while (SCCP_REF_DESTROYED != sccp_refcount_isRunning()) {
2988 		usleep(SCCP_TIME_TO_KEEP_REFCOUNTEDOBJECT);							// give enough time for all schedules to end and refcounted object to be cleanup completely
2989 	}
2990 
2991 	if (sched) {
2992 		pbx_log(LOG_NOTICE, "Cleaning up scheduled items:\n");
2993 		int scheduled_items = 0;
2994 
2995 		ast_sched_dump(sched);
2996 		while ((scheduled_items = ast_sched_runq(sched))) {
2997 			pbx_log(LOG_NOTICE, "Cleaning up %d scheduled items... please wait\n", scheduled_items);
2998 			usleep(ast_sched_wait(sched));
2999 		}
3000 		ast_sched_context_destroy(sched);
3001 		sched = NULL;
3002 	}
3003 
3004 	pbx_log(LOG_NOTICE, "Running Cleanup\n");
3005 	sccp_free(sccp_globals);
3006 	pbx_log(LOG_NOTICE, "Module chan_sccp unloaded\n");
3007 	return 0;
3008 }
3009 
3010 #if defined(__cplusplus) || defined(c_plusplus)
load_module(void)3011 static ast_module_load_result load_module(void)
3012 #else
3013 static int load_module(void)
3014 #endif
3015 {
3016 	int res = AST_MODULE_LOAD_DECLINE;
3017 	do {
3018 		if (ast_module_check("chan_skinny.so")) {
3019 			pbx_log(LOG_ERROR, "Chan_skinny is loaded. Please check modules.conf and remove chan_skinny before loading chan_sccp.\n");
3020 			break;
3021 		}
3022 		if (!(sched = ast_sched_context_create())) {
3023 			pbx_log(LOG_WARNING, "Unable to create schedule context. SCCP channel type disabled\n");
3024 			break;
3025 		}
3026 		if (ast_sched_start_thread(sched)) {
3027 			pbx_log(LOG_ERROR, "Unable to start scheduler\n");
3028 			ast_sched_context_destroy(sched);
3029 			sched = NULL;
3030 			break;
3031 		}
3032 #if defined(CS_DEVSTATE_FEATURE) || defined(CS_USE_ASTERISK_DISTRIBUTED_DEVSTATE)
3033 		ast_enable_distributed_devstate();
3034 #endif
3035 		if (!sccp_prePBXLoad()) {
3036 			pbx_log(LOG_ERROR, "SCCP: prePBXLoad Failed\n");
3037 			break;
3038 		}
3039 		if (!(io = io_context_create())) {
3040 			pbx_log(LOG_ERROR, "Unable to create I/O context. SCCP channel type disabled\n");
3041 			break;
3042 		}
3043 		if (!load_config()) {
3044 			pbx_log(LOG_ERROR, "SCCP: config file could not be parsed\n");
3045 			res = AST_MODULE_LOAD_DECLINE;
3046 			break;
3047 		}
3048 
3049 		sccp_tech.capabilities = ast_format_cap_alloc();
3050 		ast_format_cap_add_all_by_type(sccp_tech.capabilities, AST_FORMAT_TYPE_AUDIO);
3051 		ast_format_cap_add_all_by_type(sccp_tech.capabilities, AST_FORMAT_TYPE_VIDEO);
3052 
3053 		if (ast_channel_register(&sccp_tech)) {
3054 			pbx_log(LOG_ERROR, "Unable to register channel class SCCP\n");
3055 			break;
3056 		}
3057 #ifdef HAVE_PBX_MESSAGE_H
3058 		if (ast_msg_tech_register(&sccp_msg_tech)) {
3059 			pbx_log(LOG_ERROR, "Unable to register message interface\n");
3060 			break;
3061 		}
3062 #endif
3063 		if (ast_rtp_glue_register(&sccp_rtp)) {
3064 			pbx_log(LOG_ERROR, "Unable to register RTP Glue\n");
3065 			break;
3066 		}
3067 		if (sccp_register_management()) {
3068 			pbx_log(LOG_ERROR, "Unable to register management functions");
3069 			break;
3070 		}
3071 		if (sccp_register_cli()) {
3072 			pbx_log(LOG_ERROR, "Unable to register CLI functions");
3073 			break;
3074 		}
3075 		if (sccp_register_dialplan_functions()) {
3076 			pbx_log(LOG_ERROR, "Unable to register dialplan functions");
3077 			break;
3078 		}
3079 		if (!sccp_postPBX_load()) {
3080 			pbx_log(LOG_ERROR, "SCCP: postPBXLoad Failed\n");
3081 			break;
3082 		}
3083 		res = AST_MODULE_LOAD_SUCCESS;
3084 	} while (0);
3085 
3086 	if (res != AST_MODULE_LOAD_SUCCESS) {
3087 		pbx_log(LOG_ERROR, "SCCP: Module Load Failed, unloading...\n");
3088 		unload_module();
3089 	}
3090 	return res;
3091 }
3092 
module_reload(void)3093 static int module_reload(void)
3094 {
3095 	return sccp_reload();
3096 }
3097 
3098 #if defined(__cplusplus) || defined(c_plusplus)
3099 
3100 static struct ast_module_info __mod_info = {
3101 	NULL,
3102 	load_module,
3103 	module_reload,
3104 	unload_module,
3105 	NULL,
3106 	NULL,
3107 	AST_MODULE,
3108 	SCCP_VERSIONSTR,
3109 	ASTERISK_GPL_KEY,
3110 	AST_MODFLAG_LOAD_ORDER,
3111 	AST_BUILDOPT_SUM,
3112 	AST_MODPRI_CHANNEL_DRIVER,
3113 	NULL,
3114 };
3115 
__reg_module(void)3116 static void __attribute__ ((constructor)) __reg_module(void)
3117 {
3118 	ast_module_register(&__mod_info);
3119 }
3120 
__unreg_module(void)3121 static void __attribute__ ((destructor)) __unreg_module(void)
3122 {
3123 	ast_module_unregister(&__mod_info);
3124 }
3125 
3126 static const __attribute__ ((unused))
3127 struct ast_module_info *ast_module_info = &__mod_info;
3128 #else
3129 
3130 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, SCCP_VERSIONSTR,.load = load_module,.unload = unload_module,.reload = module_reload,.load_pri = AST_MODPRI_DEFAULT,
3131 		// .description = "Skinny Client Control Protocol (SCCP)",
3132 		.nonoptreq = "chan_local");
3133 #endif
3134 
3135 #if UNUSEDCODE // 2015-11-01
sccp_search_remotepeer_locked(int (* const found_cb)(PBX_CHANNEL_TYPE * c,void * data),void * data)3136 PBX_CHANNEL_TYPE *sccp_search_remotepeer_locked(int (*const found_cb) (PBX_CHANNEL_TYPE * c, void *data), void *data)
3137 {
3138 	PBX_CHANNEL_TYPE *remotePeer;
3139 
3140 	struct ast_channel_iterator *iterator = ast_channel_iterator_all_new();
3141 
3142 	((struct ao2_iterator *) iterator)->flags |= AO2_ITERATOR_DONTLOCK;
3143 
3144 	for (; (remotePeer = ast_channel_iterator_next(iterator)); remotePeer = pbx_channel_unref(remotePeer)) {
3145 
3146 		if (found_cb(remotePeer, data)) {
3147 			ast_channel_lock(remotePeer);
3148 			break;
3149 		}
3150 
3151 	}
3152 	ast_channel_iterator_destroy(iterator);
3153 	return remotePeer;
3154 }
3155 #endif
3156 
sccp_astwrap_findPickupChannelByExtenLocked(PBX_CHANNEL_TYPE * chan,const char * exten,const char * context)3157 PBX_CHANNEL_TYPE *sccp_astwrap_findPickupChannelByExtenLocked(PBX_CHANNEL_TYPE * chan, const char *exten, const char *context)
3158 {
3159 	struct ast_channel *target = NULL;									/*!< Potential pickup target */
3160 	struct ast_channel_iterator *iter;
3161 
3162 	if (!(iter = ast_channel_iterator_by_exten_new(exten, context))) {
3163 		return NULL;
3164 	}
3165 
3166 	while ((target = ast_channel_iterator_next(iter))) {
3167 		ast_channel_lock(target);
3168 		if ((chan != target) && ast_can_pickup(target)) {
3169 			ast_log(LOG_NOTICE, "%s pickup by %s\n", target->name, chan->name);
3170 			break;
3171 		}
3172 		ast_channel_unlock(target);
3173 		target = pbx_channel_unref(target);
3174 	}
3175 
3176 	ast_channel_iterator_destroy(iter);
3177 	return target;
3178 }
3179 
find_channel_by_group(void * obj,void * arg,void * data,int flags)3180 static int find_channel_by_group(void *obj, void *arg, void *data, int flags)
3181 {
3182 	struct ast_channel *target = obj;
3183 	struct ast_channel *chan = data;
3184 
3185 	ast_channel_lock(target);
3186 	if (chan != target && (chan->pickupgroup & target->callgroup)
3187 		&& ast_can_pickup(target)) {
3188 		return CMP_MATCH | CMP_STOP;
3189 	}
3190 	ast_channel_unlock(target);
3191 
3192 	return 0;
3193 }
3194 
sccp_astwrap_findPickupChannelByGroupLocked(PBX_CHANNEL_TYPE * chan)3195 PBX_CHANNEL_TYPE *sccp_astwrap_findPickupChannelByGroupLocked(PBX_CHANNEL_TYPE * chan)
3196 {
3197 	struct ast_channel *target = NULL;									/*!< Potential pickup target */
3198 	target = ast_channel_callback(find_channel_by_group, NULL, chan, 0);
3199 	return target;
3200 }
3201 
3202 // 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;
3203