1 /*!
2  * \file        ast113.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 "sccp_enum.h"
29 #include "pbx_impl/ast114/ast114.h"
30 #include "pbx_impl/ast_announce/ast_announce.h"
31 
32 SCCP_FILE_VERSION(__FILE__, "");
33 
34 __BEGIN_C_EXTERN__
35 #ifdef HAVE_PBX_ACL_H
36 #  include <asterisk/acl.h>
37 #endif
38 #include <asterisk/module.h>
39 #include <asterisk/callerid.h>
40 #include <asterisk/causes.h>
41 #include <asterisk/musiconhold.h>
42 #ifdef HAVE_PBX_FEATURES_H
43 #  include <asterisk/features_config.h>
44 #  include <asterisk/features.h>
45 #  include <asterisk/parking.h>
46 #  include <asterisk/pickup.h>
47 #endif
48 #ifdef HAVE_PBX_APP_H
49 #  include <asterisk/app.h>
50 #endif
51 #include <asterisk/translate.h>
52 #include <asterisk/indications.h>
53 #include <asterisk/cel.h>
54 #include <asterisk/netsock2.h>
55 #include <asterisk/pickup.h>
56 #include <asterisk/stasis.h>
57 #include <asterisk/stasis_channels.h>
58 #include <asterisk/stasis_endpoints.h>
59 #include <asterisk/bridge_after.h>
60 #include <asterisk/bridge_channel.h>
61 #include <asterisk/format_cap.h>		// for AST_FORMAT_CAP_NAMES_LEN
62 #include <asterisk/say.h>                                        // PARKING
63 
64 #define new avoid_cxx_new_keyword
65 #include <asterisk/rtp_engine.h>
66 #undef new
67 #include <asterisk/timing.h>
68 __END_C_EXTERN__
69 #define pbx_module_info ast_module_info
70 
71 struct ast_sched_context *sched = 0;
72 struct io_context *io = 0;
73 
74 static PBX_CHANNEL_TYPE *sccp_astwrap_request(const char *type, struct ast_format_cap *cap, const struct ast_assigned_ids *assignedids, const PBX_CHANNEL_TYPE * requestor, const char *dest, int *cause);
75 static int sccp_astwrap_call(PBX_CHANNEL_TYPE * ast, const char *dest, int timeout);
76 static int sccp_astwrap_answer(PBX_CHANNEL_TYPE * chan);
77 static PBX_FRAME_TYPE *sccp_astwrap_rtp_read(PBX_CHANNEL_TYPE * ast);
78 static int sccp_astwrap_rtp_write(PBX_CHANNEL_TYPE * ast, PBX_FRAME_TYPE * frame);
79 static int sccp_astwrap_indicate(PBX_CHANNEL_TYPE * ast, int ind, const void *data, size_t datalen);
80 static int sccp_astwrap_fixup(PBX_CHANNEL_TYPE * oldchan, PBX_CHANNEL_TYPE * newchan);
81 static void sccp_astwrap_setDialedNumber(constChannelPtr channel, const char *number);
82 
83 //#ifdef CS_AST_RTP_INSTANCE_BRIDGE
84 //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);
85 //#endif
86 static int sccp_pbx_sendtext(PBX_CHANNEL_TYPE * ast, const char *text);
87 static int sccp_wrapper_recvdigit_begin(PBX_CHANNEL_TYPE * ast, char digit);
88 static int sccp_wrapper_recvdigit_end(PBX_CHANNEL_TYPE * ast, char digit, unsigned int duration);
89 static int sccp_pbx_sendHTML(PBX_CHANNEL_TYPE * ast, int subclass, const char *data, int datalen);
90 int sccp_astwrap_hangup(PBX_CHANNEL_TYPE * ast_channel);
91 int sccp_astwrap_queue_control(const PBX_CHANNEL_TYPE * pbx_channel, enum ast_control_frame_type control);
92 int sccp_astwrap_queue_control_data(const PBX_CHANNEL_TYPE * pbx_channel, enum ast_control_frame_type control, const void *data, size_t datalen);
93 static int sccp_astwrap_devicestate(const char *data);
94 //static boolean_t sccp_astwrap_setWriteFormat(constChannelPtr channel, skinny_codec_t codec);
95 //static boolean_t sccp_astwrap_setReadFormat(constChannelPtr channel, skinny_codec_t codec);
96 PBX_CHANNEL_TYPE *sccp_astwrap_findPickupChannelByExtenLocked(PBX_CHANNEL_TYPE * chan, const char *exten, const char *context);
97 PBX_CHANNEL_TYPE *sccp_astwrap_findPickupChannelByGroupLocked(PBX_CHANNEL_TYPE * chan);
98 
sccp_astwrap_getSkinnyFormatSingle(struct ast_format_cap * ast_format_capability)99 static inline skinny_codec_t sccp_astwrap_getSkinnyFormatSingle(struct ast_format_cap *ast_format_capability)
100 {
101 	uint formatPosition;
102 	skinny_codec_t codec = SKINNY_CODEC_NONE;
103 	struct ast_format *format;
104 
105 	for (formatPosition = 0; formatPosition < ast_format_cap_count(ast_format_capability); ++formatPosition) {
106 		format = ast_format_cap_get_format(ast_format_capability, formatPosition);
107 		uint64_t ast_codec = ast_format_compatibility_format2bitfield(format);
108 		ao2_ref(format, -1);
109 
110 		if ((codec = pbx_codec2skinny_codec(ast_codec)) != SKINNY_CODEC_NONE) {
111 			break;
112 		}
113 	}
114 
115 	if (codec == SKINNY_CODEC_NONE) {
116 		ast_log(LOG_WARNING, "SCCP: (getSkinnyFormatSingle) No matching codec found");
117 	}
118 	return codec;
119 }
120 
sccp_astwrap_getSkinnyFormatMultiple(struct ast_format_cap * ast_format_capability,skinny_codec_t codecs[],int length)121 static uint8_t sccp_astwrap_getSkinnyFormatMultiple(struct ast_format_cap *ast_format_capability, skinny_codec_t codecs[], int length)
122 {
123 	// struct ast_format tmp_fmt;
124 	uint formatPosition;
125 	skinny_codec_t found = SKINNY_CODEC_NONE;
126 	uint8_t position = 0;
127 	struct ast_format *format;
128 
129 	memset(codecs, 0, length * sizeof(skinny_codec_t));
130 
131 	//pbx_str_t *codec_buf = pbx_str_alloca(64);
132 	//sccp_log(DEBUGCAT_RTP)(VERBOSE_PREFIX_3 "SCCP: (getSkinnyFormatMultiple) caps %s\n", ast_format_cap_get_names(ast_format_capability,&codec_buf));
133 	for (formatPosition = 0; formatPosition < ast_format_cap_count(ast_format_capability); ++formatPosition) {
134 		format = ast_format_cap_get_format(ast_format_capability, formatPosition);
135 		uint64_t ast_codec = ast_format_compatibility_format2bitfield(format);
136 		ao2_ref(format, -1);
137 
138 		if ((found = pbx_codec2skinny_codec(ast_codec)) != SKINNY_CODEC_NONE) {
139 			codecs[position++] = found;
140 		}
141 	}
142 
143 	if (codecs[0] == SKINNY_CODEC_NONE) {
144 		ast_log(LOG_WARNING, "SCCP: (getSkinnyFormatSingle) No matching codecs found");
145 	}
146 
147 	return position;
148 }
149 
sccp_astwrap_skinny2ast_format(skinny_codec_t skinnycodec)150 static struct ast_format *sccp_astwrap_skinny2ast_format(skinny_codec_t skinnycodec)
151 {
152 	switch (skinnycodec) {
153 		case SKINNY_CODEC_G711_ALAW_64K:
154 		case SKINNY_CODEC_G711_ALAW_56K:
155 			return ast_format_alaw;
156 		case SKINNY_CODEC_G711_ULAW_64K:
157 		case SKINNY_CODEC_G711_ULAW_56K:
158 			return ast_format_ulaw;
159 		case SKINNY_CODEC_G722_64K:
160 		case SKINNY_CODEC_G722_56K:
161 		case SKINNY_CODEC_G722_48K:
162 			return ast_format_g722;
163 		case SKINNY_CODEC_G723_1:
164 			return ast_format_g723;
165 		case SKINNY_CODEC_G729:
166 			return ast_format_g729;
167 		case SKINNY_CODEC_G729_A:
168 			return ast_format_g729;
169 		case SKINNY_CODEC_G729_B_LOW:
170 			return ast_format_ilbc;
171 //		case SKINNY_CODEC_G729_B:
172 //		case SKINNY_CODEC_G729_ANNEX_B:
173 //		case SKINNY_CODEC_G729_AB:
174 //			return ast_format_g729b;
175 		case SKINNY_CODEC_G726_32K:
176 			return ast_format_g726;
177 		case SKINNY_CODEC_WIDEBAND_256K:
178 			return ast_format_slin16;
179 		case SKINNY_CODEC_GSM:
180 			return ast_format_gsm;
181 #ifdef AST_FORMAT_OPUS
182 		case SKINNY_CODEC_OPUS:
183 			return ast_format_opus;
184 #endif
185 #ifdef AST_FORMAT_SIREN7
186 		case SKINNY_CODEC_G722_1_24K:
187 			return ast_format_siren7;
188 #endif
189 #ifdef AST_FORMAT_SIREN7
190 		case SKINNY_CODEC_G722_1_32K:
191 			return ast_format_siren14;
192 #endif
193 		case SKINNY_CODEC_H261:
194 			return ast_format_h261;
195 		case SKINNY_CODEC_H263:
196 			return ast_format_h263;
197 		case SKINNY_CODEC_H263P:
198 			return ast_format_h263p;
199 		case SKINNY_CODEC_H264:
200 			return ast_format_h264;
201 		case SKINNY_CODEC_T120:
202 			return ast_format_t140;
203 		default:
204 			return ast_format_none;
205 	}
206 }
207 
pbx_format_cap_append_skinny(struct ast_format_cap * caps,skinny_codec_t codecs[SKINNY_MAX_CAPABILITIES])208 static void pbx_format_cap_append_skinny(struct ast_format_cap *caps, skinny_codec_t codecs[SKINNY_MAX_CAPABILITIES]) {
209 	int i;
210 	for (i=0; i<SKINNY_MAX_CAPABILITIES; i++) {
211 		if (codecs[i] == SKINNY_CODEC_NONE) {
212 			break;
213 		}
214 		struct ast_format *format = sccp_astwrap_skinny2ast_format(codecs[i]);
215 		if (format != ast_format_none && ast_format_cap_iscompatible_format(caps, format) == AST_FORMAT_CMP_NOT_EQUAL) {
216 			unsigned int framing = ast_format_get_default_ms(format);
217 			ast_format_cap_append(caps, format, framing);
218 			//sccp_log(DEBUGCAT_CODEC)(VERBOSE_PREFIX_3 "Added codec:%s\n", codec2str(codecs[i]));
219 		}
220 	}
221 }
222 
223 #if defined(__cplusplus) || defined(c_plusplus)
224 /*!
225  * \brief NULL Tech Structure
226  */
227 static const struct ast_channel_tech null_tech = {
228 type:	"NULL",
229 description:"Null channel (should not see this)",
230 };
231 
232 /*!
233  * \brief SCCP Tech Structure
234  */
235 static struct ast_channel_tech sccp_tech = {
236 	/* *INDENT-OFF* */
237 	type:			SCCP_TECHTYPE_STR,
238 	description:		"Skinny Client Control Protocol (SCCP)",
239 //      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,
240 	properties:		AST_CHAN_TP_WANTSJITTER | AST_CHAN_TP_CREATESJITTER,
241 	requester:		sccp_astwrap_request,
242 	devicestate:		sccp_astwrap_devicestate,
243 	send_digit_begin:	sccp_wrapper_recvdigit_begin,
244 	send_digit_end:		sccp_wrapper_recvdigit_end,
245 	call:			sccp_astwrap_call,
246 	hangup:			sccp_astwrap_hangup,
247 	answer:			sccp_astwrap_answer,
248 	read:			sccp_astwrap_rtp_read,
249 	write:			sccp_astwrap_rtp_write,
250 	send_text:		sccp_pbx_sendtext,
251 	send_image:		NULL,
252 	send_html:		sccp_pbx_sendHTML,
253 	exception:		NULL,
254 //	bridge:			sccp_astwrap_rtpBridge,
255         bridge:			ast_rtp_instance_bridge,
256 	early_bridge:		ast_rtp_instance_early_bridge,
257 	indicate:		sccp_astwrap_indicate,
258 	fixup:			sccp_astwrap_fixup,
259 	setoption:		NULL,
260 	queryoption:		NULL,
261 	transfer:		NULL,
262 	write_video:		sccp_astwrap_rtp_write,
263 	write_text:		NULL,
264 	bridged_channel:	NULL,
265 	func_channel_read:	sccp_astgenwrap_channel_read,
266 	func_channel_write:	sccp_astgenwrap_channel_write,
267 	get_base_channel:	NULL,
268 	set_base_channel:	NULL,
269 	/* *INDENT-ON* */
270 };
271 
272 #else
273 /*!
274  * \brief NULL Tech Structure
275  */
276 static const struct ast_channel_tech null_tech = {
277 	.type = "NULL",
278 	.description = "Null channel (should not see this)",
279 };
280 
281 /*!
282  * \brief SCCP Tech Structure
283  */
284 struct ast_channel_tech sccp_tech = {
285 	/* *INDENT-OFF* */
286 	.type 			= SCCP_TECHTYPE_STR,
287 	.description 		= "Skinny Client Control Protocol (SCCP)",
288 	// we could use the skinny_codec = ast_codec mapping here to generate the list of capabilities
289 //      .capabilities           = AST_FORMAT_SLINEAR16 | AST_FORMAT_SLINEAR | AST_FORMAT_ALAW | AST_FORMAT_ULAW | AST_FORMAT_GSM | AST_FORMAT_G723_1 | AST_FORMAT_G729A,
290 	.properties 		= AST_CHAN_TP_WANTSJITTER | AST_CHAN_TP_CREATESJITTER,
291 	.requester 		= sccp_astwrap_request,
292 	.devicestate 		= sccp_astwrap_devicestate,
293 	.call 			= sccp_astwrap_call,
294 	.hangup 		= sccp_astwrap_hangup,
295 	.answer 		= sccp_astwrap_answer,
296 	.read 			= sccp_astwrap_rtp_read,
297 	.write 			= sccp_astwrap_rtp_write,
298 	.write_video 		= sccp_astwrap_rtp_write,
299 	.indicate 		= sccp_astwrap_indicate,
300 	.fixup 			= sccp_astwrap_fixup,
301 	//.transfer 		= sccp_pbx_transfer,
302 #ifdef CS_AST_RTP_INSTANCE_BRIDGE
303 	.bridge 		= ast_rtp_instance_bridge,
304 //	.bridge 		= sccp_astwrap_rtpBridge,
305 #endif
306 	// asterisk-13 rtp_engine.h implementation of ast_rtp_instance_early_bridge is actually not fully c++ compatible to their own definition, so a cast is required
307 	.early_bridge		= (enum ast_bridge_result (*)(struct ast_channel *, struct ast_channel *))&ast_rtp_instance_early_bridge,
308 	//.bridged_channel      =
309 
310 	.send_text 		= sccp_pbx_sendtext,
311 	.send_html 		= sccp_pbx_sendHTML,
312 	//.send_image           =
313 
314 	.func_channel_read 	= sccp_astgenwrap_channel_read,
315 	.func_channel_write	= sccp_astgenwrap_channel_write,
316 
317 	.send_digit_begin 	= sccp_wrapper_recvdigit_begin,
318 	.send_digit_end 	= sccp_wrapper_recvdigit_end,
319 
320 	//.write_text           =
321 	//.write_video          =
322 	//.cc_callback          =                                              // ccss, new >1.6.0
323 	//.exception            =                                              // new >1.6.0
324 	//.setoption              = sccp_astwrap_setOption,
325 	//.queryoption          =                                              // new >1.6.0
326 	//.get_pvt_uniqueid     = sccp_pbx_get_callid,                         // new >1.6.0
327 	//.get_base_channel     =
328 	//.set_base_channel     =
329 	/* *INDENT-ON* */
330 };
331 
332 #endif
333 
sccp_astwrap_devicestate(const char * data)334 static int sccp_astwrap_devicestate(const char *data)
335 {
336 	enum ast_device_state res = AST_DEVICE_UNKNOWN;
337 	char *lineName = (char *) data;
338 	char *deviceId = NULL;
339 	sccp_channelstate_t state;
340 
341 	if ((deviceId = strchr(lineName, '@'))) {
342 		*deviceId = '\0';
343 		deviceId++;
344 	}
345 
346 	state = sccp_hint_getLinestate(lineName, deviceId);
347 	sccp_log((DEBUGCAT_HINT)) (VERBOSE_PREFIX_4 "SCCP: (devicestate) sccp_hint returned state:%s for '%s'\n", sccp_channelstate2str(state), lineName);
348 	switch (state) {
349 		case SCCP_CHANNELSTATE_DOWN:
350 		case SCCP_CHANNELSTATE_ONHOOK:
351 			res = AST_DEVICE_NOT_INUSE;
352 			break;
353 		case SCCP_CHANNELSTATE_RINGING:
354 			res = AST_DEVICE_RINGING;
355 			break;
356 		case SCCP_CHANNELSTATE_HOLD:
357 			res = AST_DEVICE_ONHOLD;
358 			break;
359 		case SCCP_CHANNELSTATE_INVALIDNUMBER:
360 		case SCCP_CHANNELSTATE_INVALIDCONFERENCE:
361 			res = AST_DEVICE_INVALID;
362 			break;
363 		case SCCP_CHANNELSTATE_BUSY:
364 		case SCCP_CHANNELSTATE_DND:
365 			res = AST_DEVICE_BUSY;
366 			break;
367 		case SCCP_CHANNELSTATE_CONGESTION:
368 			res = AST_DEVICE_UNAVAILABLE;
369 			break;
370 		case SCCP_CHANNELSTATE_RINGOUT:
371 		case SCCP_CHANNELSTATE_RINGOUT_ALERTING:
372 			res = AST_DEVICE_RINGINUSE;
373 			break;
374 		case SCCP_CHANNELSTATE_DIALING:
375 		case SCCP_CHANNELSTATE_DIGITSFOLL:
376 		case SCCP_CHANNELSTATE_PROGRESS:
377 		case SCCP_CHANNELSTATE_CALLWAITING:
378 		case SCCP_CHANNELSTATE_CONNECTEDCONFERENCE:
379 		case SCCP_CHANNELSTATE_OFFHOOK:
380 		case SCCP_CHANNELSTATE_GETDIGITS:
381 		case SCCP_CHANNELSTATE_CONNECTED:
382 		case SCCP_CHANNELSTATE_PROCEED:
383 		case SCCP_CHANNELSTATE_BLINDTRANSFER:
384 		case SCCP_CHANNELSTATE_CALLTRANSFER:
385 		case SCCP_CHANNELSTATE_CALLCONFERENCE:
386 		case SCCP_CHANNELSTATE_CALLPARK:
387 		case SCCP_CHANNELSTATE_CALLREMOTEMULTILINE:
388 		case SCCP_CHANNELSTATE_SPEEDDIAL:
389 			res = AST_DEVICE_INUSE;
390 			break;
391 		case SCCP_CHANNELSTATE_SENTINEL:
392 		case SCCP_CHANNELSTATE_ZOMBIE:
393 			res = AST_DEVICE_UNKNOWN;
394 			break;
395 	}
396 
397 	sccp_log((DEBUGCAT_HINT)) (VERBOSE_PREFIX_4 "SCCP: (devicestate) PBX requests state for '%s' - state %s\n", lineName, ast_devstate2str(res));
398 	return (int)res;
399 }
400 
401 static boolean_t sccp_astwrap_setReadFormat(constChannelPtr channel, skinny_codec_t codec);
402 
403 #define RTP_NEW_SOURCE(_c,_log) 								\
404 	if(c->rtp.audio.instance) { 										\
405 		ast_rtp_new_source(c->rtp.audio.instance); 							\
406 		sccp_log((DEBUGCAT_PBX | DEBUGCAT_INDICATE))(VERBOSE_PREFIX_3 "SCCP: " #_log "\n"); 	\
407 	}
408 
409 #define RTP_CHANGE_SOURCE(_c,_log) 								\
410 	if(c->rtp.audio.instance) {										\
411 		ast_rtp_change_source(c->rtp.audio.instance);						\
412 		sccp_log((DEBUGCAT_PBX | DEBUGCAT_INDICATE))(VERBOSE_PREFIX_3 "SCCP: " #_log "\n"); 	\
413 	}
414 
415 // static void get_skinnyFormats(struct ast_format_cap *format, skinny_codec_t codecs[], size_t size)
416 // {
417 //      unsigned int x;
418 //      unsigned len = 0;
419 //
420 //      size_t f_len;
421 //      struct ast_format tmp_fmt;
422 //      const struct ast_format_list *f_list = ast_format_list_get(&f_len);
423 //
424 //      if (!size) {
425 //              f_list = ast_format_list_destroy(f_list);
426 //              return;
427 //      }
428 //
429 //      for (x = 0; x < ARRAY_LEN(pbx2skinny_codec_maps) && len <= size; x++) {
430 //              ast_format_copy(&tmp_fmt, &f_list[x].format);
431 //              if (ast_format_cap_iscompatible(format, &tmp_fmt)) {
432 //                      if (pbx2skinny_codec_maps[x].pbx_codec == ((uint) tmp_fmt.id)) {
433 //                              codecs[len++] = pbx2skinny_codec_maps[x].skinny_codec;
434 //                      }
435 //              }
436 //      }
437 //      f_list = ast_format_list_destroy(f_list);
438 // }
439 
440 /*************************************************************************************************************** CODEC **/
441 
442 /*! \brief Get the name of a format
443  * \note replacement for ast_getformatname
444  * \param format id of format
445  * \return A static string containing the name of the format or "unknown" if unknown.
446  */
pbx_getformatname(const struct ast_format * format)447 const char *pbx_getformatname(const struct ast_format *format)
448 {
449 	return ast_format_get_codec_name(format);
450 }
451 
452 /*!
453  * \brief Get the names of a set of formats
454  * \note replacement for ast_getformatname_multiple
455  * \param buf a buffer for the output string
456  * \param size size of buf (bytes)
457  * \param format the format (combined IDs of codecs)
458  * Prints a list of readable codec names corresponding to "format".
459  * ex: for format=AST_FORMAT_GSM|AST_FORMAT_SPEEX|AST_FORMAT_ILBC it will return "0x602 (GSM|SPEEX|ILBC)"
460  * \return The return value is buf.
461  */
pbx_getformatname_multiple(char * buf,size_t size,struct ast_format_cap * format)462 const char *pbx_getformatname_multiple(char *buf, size_t size, struct ast_format_cap *format)
463 {
464 	pbx_str_t *codec_buf = pbx_str_alloca(64);
465 	ast_format_cap_get_names(format, &codec_buf);
466 	snprintf(buf, size, "%s", ast_format_cap_get_names(format, &codec_buf));
467 	return buf;
468 }
469 
470 
471 
472 /*!
473  * \brief Find Asterisk/PBX channel by linkid
474  *
475  * \param ast   pbx channel
476  * \param data  linkId as void *
477  *
478  * \return int
479  */
pbx_find_channel_by_linkid(PBX_CHANNEL_TYPE * ast,PBX_CHANNEL_TYPE * remotePeer,const void * data)480 static int pbx_find_channel_by_linkid(PBX_CHANNEL_TYPE * ast, PBX_CHANNEL_TYPE * remotePeer, const void *data)
481 {
482 	const char *linkedId = (char *) data;
483 	const char *remoteLinkedId = ast_channel_linkedid(remotePeer);
484 
485 	if (!linkedId) {
486 		return 0;
487 	}
488 
489 	return remotePeer != ast && remoteLinkedId && (!strcasecmp(linkedId, remoteLinkedId)) && !pbx_channel_masq(remotePeer);
490 }
491 
492 /*! Generic helper function to find the best common codec to use */
__find_joint_capabilities(sccp_channel_t * c,PBX_CHANNEL_TYPE * peer,enum ast_media_type media_type,skinny_codec_t remoteCapabilities[])493 static void __find_joint_capabilities(sccp_channel_t *c, PBX_CHANNEL_TYPE* peer, enum ast_media_type media_type, skinny_codec_t remoteCapabilities[])
494 {
495 	char buf[512];
496 	pbx_str_t *codec_buf = pbx_str_alloca(64);
497 	PBX_CHANNEL_TYPE *owner = c->owner;
498 	RAII(struct ast_format_cap *, caps, ao2_t_bump(c->caps, "sccp_channel_caps"), ao2_cleanup);
499 	RAII(struct ast_format_cap *, payload_caps, ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT), ao2_cleanup);
500 	RAII(struct ast_format_cap *, remote_caps, ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT), ao2_cleanup);
501 	RAII(struct ast_format_cap *, joint, ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT), ao2_cleanup);
502 	struct ast_format *best_fmt_cap = NULL;
503 	struct ast_format *best_fmt_native = NULL;
504 	if (caps && payload_caps && remote_caps && joint && !ast_format_cap_empty(caps)) {
505 		ast_format_cap_append_from_cap(payload_caps, caps, media_type);
506 		ast_channel_lock(peer);
507 		struct ast_format_cap * cap_native_peer = ast_channel_nativeformats(peer);
508 		if (!ast_format_cap_empty(cap_native_peer) && ast_format_cap_has_type(cap_native_peer, media_type)) {
509 			ast_format_cap_append_from_cap(remote_caps, cap_native_peer, media_type);
510 		}
511 		ast_channel_unlock(peer);
512 		if (!ast_format_cap_empty(payload_caps) && !ast_format_cap_empty(remote_caps)) {
513 			sccp_log(DEBUGCAT_CODEC)(VERBOSE_PREFIX_3 "%s: (find_joint_capabilities) native caps:%s (%d)\n", c->designator, ast_format_cap_get_names(caps, &codec_buf), (int)ast_format_cap_count(caps));
514 			sccp_log(DEBUGCAT_CODEC)(VERBOSE_PREFIX_3 "%s: (find_joint_capabilities) %s  payload:%s (%d)\n", c->designator, ast_codec_media_type2str(media_type), ast_format_cap_get_names(payload_caps, &codec_buf),
515 			                         (int)ast_format_cap_count(payload_caps));
516 			sccp_log(DEBUGCAT_CODEC)(VERBOSE_PREFIX_3 "%s: (find_joint_capabilities) %s   remote:%s (%d)\n", c->designator, ast_codec_media_type2str(media_type), ast_format_cap_get_names(remote_caps, &codec_buf),
517 			                         (int)ast_format_cap_count(remote_caps));
518 
519 			// fill c->remoteCapabilities
520 			sccp_astwrap_getSkinnyFormatMultiple(remote_caps, remoteCapabilities, SKINNY_MAX_CAPABILITIES);
521 
522 			sccp_codec_multiple2str(buf, sizeof(buf) - 1, remoteCapabilities, SKINNY_MAX_CAPABILITIES);
523 			sccp_log(DEBUGCAT_CODEC) (VERBOSE_PREFIX_4 "skinny set remote %s caps: %s\n", ast_codec_media_type2str(media_type), buf);
524 
525 			ast_format_cap_get_compatible(payload_caps, remote_caps, joint);
526 
527 			if (!ast_format_cap_empty(joint)) {
528 				best_fmt_native = ast_format_cap_get_best_by_type(joint, media_type);
529 				sccp_log(DEBUGCAT_CODEC) (VERBOSE_PREFIX_4 "%s: (find_joint_capabilities) NOT transcoding, best_native:%s\n", c->designator, ast_format_get_codec_name(best_fmt_native));
530 				if (best_fmt_native) {
531 					ast_format_cap_remove_by_type(caps, media_type);
532 					ast_format_cap_append(caps, best_fmt_native, media_type);
533 				}
534 				ast_format_cap_append_from_cap(caps, joint, media_type);
535 			} else {
536 				ast_translator_best_choice(remote_caps, caps, &best_fmt_cap, &best_fmt_native);
537 				if (best_fmt_native) {
538 					ao2_ref(best_fmt_native, +1);
539 					ast_format_cap_remove_by_type(caps, media_type);
540 					ast_format_cap_append(caps, best_fmt_cap, media_type);
541 				} else {
542 					best_fmt_native = ast_format_cap_get_best_by_type(caps, media_type);
543 				}
544 				ast_format_cap_append_from_cap(caps, payload_caps, media_type);
545 				sccp_log(DEBUGCAT_CODEC) (VERBOSE_PREFIX_3 "%s: pbx_retrieve_remote_capabilities: transcoding, best_cap:%s, best_native:%s\n",
546 					c->designator, ast_format_get_codec_name(best_fmt_cap), best_fmt_native ? ast_format_get_codec_name(best_fmt_native) : "");
547 			}
548 
549 			ast_format_cap_append_from_cap(caps, ast_channel_nativeformats(c->owner), AST_MEDIA_TYPE_UNKNOWN);
550 			if (best_fmt_native) {
551 				if (best_fmt_native != ast_format_none) {
552 					if (!ast_format_cap_empty(caps)) {
553 						ast_channel_lock(owner);
554 						ast_channel_nativeformats_set(c->owner, caps);
555 						ast_channel_unlock(owner);
556 						sccp_log(DEBUGCAT_CODEC) (VERBOSE_PREFIX_4 "%s: (find_joint_capabilities) using: caps:%s, codec:%s\n", c->designator, ast_format_cap_get_names(caps, &codec_buf), ast_format_get_codec_name(best_fmt_native));
557 					}
558 					if (AST_MEDIA_TYPE_AUDIO == media_type) {
559 						ast_channel_set_writeformat(c->owner, best_fmt_native);
560 						ast_channel_set_readformat(c->owner, best_fmt_native);
561 						if (c->rtp.audio.instance) {
562 							ast_channel_set_rawwriteformat(c->owner, best_fmt_native);
563 							ast_channel_set_rawreadformat(c->owner, best_fmt_native);
564 						}
565 						if (c->rtp.audio.instance) {
566 							ast_rtp_instance_set_write_format(c->rtp.audio.instance, best_fmt_native);
567 							ast_rtp_instance_set_read_format(c->rtp.audio.instance, best_fmt_native);
568 						}
569 					} else if (AST_MEDIA_TYPE_VIDEO == media_type && c->rtp.video.instance) {
570 						ast_rtp_instance_set_write_format(c->rtp.video.instance, best_fmt_native);
571 						ast_rtp_instance_set_read_format(c->rtp.video.instance, best_fmt_native);
572 					}
573 				}
574 				ao2_ref(best_fmt_native, -1);
575 			}
576 		}
577 		return;
578 	}
579 }
580 
pbx_retrieve_remote_capabilities(sccp_channel_t * c)581 static void pbx_retrieve_remote_capabilities(sccp_channel_t *c)
582 {
583 	pbx_assert(c != NULL);
584 	PBX_CHANNEL_TYPE *ast = c->owner;
585 	PBX_CHANNEL_TYPE *remotePeer;
586 
587 	struct ast_channel_iterator *iterator = ast_channel_iterator_all_new();
588 	((struct ao2_iterator *) iterator)->flags |= AO2_ITERATOR_DONTLOCK;
589 
590 	//! \todo handle multiple remotePeers i.e. DIAL(SCCP/400&SIP/300), find smallest common codecs, what order to use ?
591 	for (; (remotePeer = ast_channel_iterator_next(iterator)); pbx_channel_unref(remotePeer)) {
592 		if (pbx_find_channel_by_linkid(ast, remotePeer, (void *) ast_channel_linkedid(ast))) {
593 			__find_joint_capabilities(c, remotePeer, AST_MEDIA_TYPE_AUDIO, c->remoteCapabilities.audio);
594 #if CS_SCCP_VIDEO
595 			__find_joint_capabilities(c, remotePeer, AST_MEDIA_TYPE_VIDEO, c->remoteCapabilities.video);
596 #endif
597 			break;
598 		}
599 	}
600 	ast_channel_iterator_destroy(iterator);
601 }
602 
603 
asterisk_indication2str(int ind)604 static const char *asterisk_indication2str(int ind)
605 {
606 	switch (ind) {
607 		case AST_CONTROL_HANGUP: return "AST_CONTROL_HANGUP: Other end has hungup";
608 		case AST_CONTROL_RING: return "AST_CONTROL_RING: Local ring";
609 		case AST_CONTROL_RINGING: return "AST_CONTROL_RINGING: Remote end is ringing";
610 		case AST_CONTROL_ANSWER: return "AST_CONTROL_ANSWER: Remote end has answered";
611 		case AST_CONTROL_BUSY: return "AST_CONTROL_BUSY: Remote end is busy";
612 		case AST_CONTROL_TAKEOFFHOOK: return "AST_CONTROL_TAKEOFFHOOK: Make it go off hook";
613 		case AST_CONTROL_OFFHOOK: return "AST_CONTROL_OFFHOOK: Line is off hook";
614 		case AST_CONTROL_CONGESTION: return "AST_CONTROL_CONGESTION: Congestion (circuits busy)";
615 		case AST_CONTROL_FLASH: return "AST_CONTROL_FLASH: Flash hook";
616 		case AST_CONTROL_WINK: return "AST_CONTROL_WINK: Wink";
617 		case AST_CONTROL_OPTION: return "AST_CONTROL_OPTION: Set a low-level option";
618 		case AST_CONTROL_RADIO_KEY: return "AST_CONTROL_RADIO_KEY: Key Radio";
619 		case AST_CONTROL_RADIO_UNKEY: return "AST_CONTROL_RADIO_UNKEY: Un-Key Radio";
620 		case AST_CONTROL_PROGRESS: return "AST_CONTROL_PROGRESS: Indicate PROGRESS";
621 		case AST_CONTROL_PROCEEDING: return "AST_CONTROL_PROCEEDING: Indicate CALL PROCEEDING";
622 		case AST_CONTROL_HOLD: return "AST_CONTROL_HOLD: Indicate call is placed on hold";
623 		case AST_CONTROL_UNHOLD: return "AST_CONTROL_UNHOLD: Indicate call left hold";
624 		case AST_CONTROL_VIDUPDATE: return "AST_CONTROL_VIDUPDATE: Indicate video frame update";
625 		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.";
626 		case AST_CONTROL_SRCUPDATE: return "AST_CONTROL_SRCUPDATE: Indicate source of media has changed";
627 		case AST_CONTROL_TRANSFER: return "AST_CONTROL_TRANSFER: Indicate status of a transfer request";
628 		case AST_CONTROL_CONNECTED_LINE: return "AST_CONTROL_CONNECTED_LINE: Indicate connected line has changed";
629 		case AST_CONTROL_REDIRECTING: return "AST_CONTROL_REDIRECTING: Indicate redirecting id has changed";
630 		case AST_CONTROL_T38_PARAMETERS: return "AST_CONTROL_T38_PARAMETERS: T38 state change request/notification with parameters";
631 		case AST_CONTROL_CC: return "AST_CONTROL_CC: Indication that Call completion service is possible";
632 		case AST_CONTROL_SRCCHANGE: return "AST_CONTROL_SRCCHANGE: Media source has changed and requires a new RTP SSRC";
633 		case AST_CONTROL_READ_ACTION: return "AST_CONTROL_READ_ACTION: Tell ast_read to take a specific action";
634 		case AST_CONTROL_AOC: return "AST_CONTROL_AOC: Advice of Charge with encoded generic AOC payload";
635 		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.";
636 		case AST_CONTROL_INCOMPLETE: return "AST_CONTROL_INCOMPLETE: Indication that the extension dialed is incomplete";
637 		case AST_CONTROL_MCID: return "AST_CONTROL_MCID: Indicate that the caller is being malicious.";
638 		case AST_CONTROL_UPDATE_RTP_PEER: return "AST_CONTROL_UPDATE_RTP_PEER: Interrupt the bridge and have it update the peer";
639 		case AST_CONTROL_PVT_CAUSE_CODE: return "AST_CONTROL_PVT_CAUSE_CODE: Contains an update to the protocol-specific cause-code stored for branching dials";
640 		case AST_CONTROL_MASQUERADE_NOTIFY: return "AST_CONTROL_MASQUERADE_NOTIFY: A masquerade is about to begin/end."; // Never sent as a frame but directly with ast_indicate_data()
641 		case -1: return "AST_CONTROL_PROD: Kick remote channel";
642 	}
643 	return "Unknown/Unhandled/IAX Indication";
644 }
645 
sccp_astwrap_indicate(PBX_CHANNEL_TYPE * ast,int ind,const void * data,size_t datalen)646 static int sccp_astwrap_indicate(PBX_CHANNEL_TYPE * ast, int ind, const void *data, size_t datalen)
647 {
648 	int res = 0;	/* indication supported */
649 
650 	AUTO_RELEASE(sccp_channel_t, c , get_sccp_channel_from_pbx_channel(ast));
651 	if (!c) {
652 		sccp_log((DEBUGCAT_PBX | DEBUGCAT_CHANNEL | DEBUGCAT_INDICATE)) (VERBOSE_PREFIX_3 "SCCP: (pbx_indicate) no sccp channel yet\n");
653 		return -1;
654 	}
655 	sccp_log((DEBUGCAT_PBX | DEBUGCAT_CHANNEL | DEBUGCAT_INDICATE)) (VERBOSE_PREFIX_3 "%s: (pbx_indicate) start indicate '%s'\n", c->designator, asterisk_indication2str(ind));
656 
657 	AUTO_RELEASE(sccp_device_t, d , sccp_channel_getDevice(c));
658 	if (!d || c->state == SCCP_CHANNELSTATE_DOWN) {
659 		//sccp_log((DEBUGCAT_PBX | DEBUGCAT_CHANNEL | DEBUGCAT_INDICATE)) (VERBOSE_PREFIX_3 "SCCP: (pbx_indicate) no sccp device yet\n");
660 		switch (ind) {
661 			case AST_CONTROL_CONNECTED_LINE:
662 				sccp_astwrap_connectedline(c, data, datalen);
663 				break;
664 			case AST_CONTROL_REDIRECTING:
665 				sccp_astwrap_redirectedUpdate(c, data, datalen);
666 				break;
667 			default:
668 				res = -1;	/* this indication is not supported */
669 				break;
670 		}
671 		return res;
672 	}
673 
674 	sccp_log((DEBUGCAT_PBX | DEBUGCAT_CHANNEL
675 		  | DEBUGCAT_INDICATE))(VERBOSE_PREFIX_1 "%s: (pbx_indicate) start indicate '%s' (%d) condition on channel %s (rtp_instance:%s, reception.state:%d/%s, transmission.state:%d/%s)\n", DEV_ID_LOG(d),
676 					asterisk_indication2str(ind), ind, pbx_channel_name(ast), c->rtp.audio.instance ? "yes" : "no", sccp_rtp_getState(&c->rtp.audio, SCCP_RTP_RECEPTION),
677 					codec2str(c->rtp.audio.reception.format), sccp_rtp_getState(&c->rtp.audio, SCCP_RTP_TRANSMISSION), codec2str(c->rtp.audio.transmission.format));
678 
679 	boolean_t inband_if_receivechannel = FALSE;
680 	switch (ind) {
681 		case AST_CONTROL_RINGING:
682 			if (SKINNY_CALLTYPE_OUTBOUND == c->calltype) {
683 				if (pbx_channel_state (c->owner) != AST_STATE_UP) {
684 					if (c->remoteCapabilities.audio[0] == SKINNY_CODEC_NONE) {
685 						pbx_retrieve_remote_capabilities (c);
686 					}
687 					// Allow signalling of RINGOUT only on outbound calls.
688 					// Otherwise, there are some issues with late arrival of ringing
689 					// indications on ISDN calls (chan_lcr, chan_dahdi) (-DD).
690 					iPbx.set_callstate (c, AST_STATE_RING);
691 				} else {
692 					iPbx.set_callstate (c, AST_STATE_RINGING);
693 				}
694 				sccp_indicate(d, c, SCCP_CHANNELSTATE_RINGOUT);
695 			}
696 			inband_if_receivechannel = TRUE;
697 			break;
698 
699 		case AST_CONTROL_BUSY:
700 			sccp_indicate(d, c, SCCP_CHANNELSTATE_BUSY);
701 			iPbx.set_callstate(c, AST_STATE_BUSY);
702 			inband_if_receivechannel = TRUE;
703 			break;
704 
705 		case AST_CONTROL_CONGESTION:
706 			sccp_indicate(d, c, SCCP_CHANNELSTATE_CONGESTION);
707 			inband_if_receivechannel = TRUE;
708 			break;
709 
710 		case AST_CONTROL_PROGRESS:
711 			if (c->remoteCapabilities.audio[0] == SKINNY_CODEC_NONE) {
712 				pbx_retrieve_remote_capabilities(c);
713 			}
714 			sccp_indicate(d, c, SCCP_CHANNELSTATE_PROGRESS);
715 			/*
716 			if (c->state != SCCP_CHANNELSTATE_CONNECTED && c->previousChannelState != SCCP_CHANNELSTATE_CONNECTED) {
717 				sccp_indicate(d, c, SCCP_CHANNELSTATE_PROGRESS);
718 			} else {
719 				// ORIGINATE() to SIP indicates PROGRESS after CONNECTED, causing issues with transfer
720 				sccp_indicate(d, c, SCCP_CHANNELSTATE_CONNECTED);
721 			}*/
722 			inband_if_receivechannel = TRUE;
723 			break;
724 
725 		case AST_CONTROL_PROCEEDING:
726 			sccp_indicate(d, c, SCCP_CHANNELSTATE_PROCEED);
727 			//inband_if_receivechannel = TRUE;
728 			break;
729 
730 		case AST_CONTROL_SRCCHANGE:									/* ask our channel's remote source address to update */
731 			if (c->rtp.audio.instance) {
732 				ast_rtp_instance_change_source(c->rtp.audio.instance);
733 			}
734 			break;
735 
736 		case AST_CONTROL_SRCUPDATE:									/* semd control bit to force other side to update, their source address */
737 			/* Source media has changed. */
738 			sccp_log((DEBUGCAT_PBX | DEBUGCAT_INDICATE)) (VERBOSE_PREFIX_3 "SCCP: Source UPDATE request\n");
739 
740 			if (c->rtp.audio.instance) {
741 				ast_rtp_instance_update_source(c->rtp.audio.instance);
742 			}
743 			break;
744 
745 		case AST_CONTROL_HOLD:										/* when the bridged channel hold/unhold the call we are notified here */
746 			if (c->rtp.audio.instance) {
747 				ast_rtp_instance_update_source(c->rtp.audio.instance);
748 			}
749 #ifdef CS_SCCP_VIDEO
750 			if (c->rtp.video.instance && d && sccp_device_isVideoSupported(d) && sccp_channel_getVideoMode(c) != SCCP_VIDEO_MODE_OFF) {
751 				d->protocol->sendMultiMediaCommand(d, c, SKINNY_MISCCOMMANDTYPE_VIDEOFREEZEPICTURE);
752 				if(sccp_rtp_getState(&c->rtp.video, SCCP_RTP_TRANSMISSION)) {
753 					sccp_channel_stopMultiMediaTransmission(c, TRUE);
754 				}
755 				ast_rtp_instance_update_source(c->rtp.video.instance);
756 			}
757 #endif
758 			sccp_astwrap_moh_start(ast, (const char *) data, c->musicclass);
759 			sccp_dev_set_message(d, SKINNY_DISP_CALL_ON_HOLD, SCCP_MESSAGE_PRIORITY_TIMEOUT, FALSE, FALSE);
760 			break;
761 
762 		case AST_CONTROL_UNHOLD:
763 			if (c->rtp.audio.instance) {
764 				ast_rtp_instance_update_source(c->rtp.audio.instance);
765 			}
766 #ifdef CS_SCCP_VIDEO
767 			if(c->rtp.video.instance && d && sccp_device_isVideoSupported(d) && sccp_channel_getVideoMode(c) != SCCP_VIDEO_MODE_OFF) {
768 				ast_rtp_instance_update_source(c->rtp.video.instance);
769 				if(!sccp_rtp_getState(&c->rtp.video, SCCP_RTP_RECEPTION)) {
770 					sccp_channel_openMultiMediaReceiveChannel(c);
771 				} else if((sccp_rtp_getState(&c->rtp.video, SCCP_RTP_RECEPTION) & SCCP_RTP_STATUS_ACTIVE) && !sccp_rtp_getState(&c->rtp.video, SCCP_RTP_TRANSMISSION)) {
772 					sccp_channel_startMultiMediaTransmission(c);
773 				}
774 				ast_rtp_instance_update_source(c->rtp.video.instance);
775 			}
776 #endif
777 			sccp_astwrap_moh_stop(ast);
778 			sccp_dev_clear_message(d, FALSE);
779 			break;
780 
781 		case AST_CONTROL_CONNECTED_LINE:
782 			/* remarking out this code, as it is causing issues with callforward + FREEPBX,  the calling party will not hear the remote end ringing
783 			 this patch was added to suppress 'double callwaiting tone', but channel PROD(-1) below is taking care of that already
784 			*/
785 			//if (c->calltype == SKINNY_CALLTYPE_OUTBOUND && c->rtp.audio.reception.state == SCCP_RTP_STATUS_INACTIVE && c->state > SCCP_CHANNELSTATE_DIALING) {
786 			//	sccp_channel_openReceiveChannel(c);
787 			//}
788 			sccp_astwrap_connectedline(c, data, datalen);
789 			inband_if_receivechannel = TRUE;
790 			break;
791 
792 		case AST_CONTROL_TRANSFER:
793 			ast_log(LOG_NOTICE, "%s: Ast Control Transfer: %d", c->designator, *(int *)data);
794 			//sccp_astwrap_connectedline(c, data, datalen);
795 			res = -1;
796 			break;
797 
798 		case AST_CONTROL_REDIRECTING:
799 			sccp_astwrap_redirectedUpdate(c, data, datalen);
800 			sccp_indicate(d, c, c->state);
801 			break;
802 
803 		case AST_CONTROL_VIDUPDATE:									/* Request a video frame update */
804 #ifdef CS_SCCP_VIDEO
805 			if (c->rtp.video.instance && d && sccp_device_isVideoSupported(d) && sccp_channel_getVideoMode(c) != SCCP_VIDEO_MODE_OFF) {
806 				d->protocol->sendMultiMediaCommand(d, c, SKINNY_MISCCOMMANDTYPE_VIDEOFASTUPDATEPICTURE);
807 			} else
808 #endif
809 			{
810 				res = -1;	/* this indication is not supported */
811 			}
812 			break;
813 
814 #ifdef CS_AST_CONTROL_INCOMPLETE
815 		case AST_CONTROL_INCOMPLETE:									/*!< Indication that the extension dialed is incomplete */
816 			/* \todo implement dial continuation by:
817 			 *  - display message incomplete number
818 			 *  - adding time to channel->scheduler.digittimeout
819 			 *  - rescheduling sccp_pbx_sched_dial
820 			 */
821 			inband_if_receivechannel = TRUE;
822 			res = -1;
823 			break;
824 #endif
825 
826 		case AST_CONTROL_PVT_CAUSE_CODE:
827 			{
828 				/*! \todo This would also be a good moment to update the c->requestHangup to requestQueueHangup */
829 				// int hangupcause = ast_channel_hangupcause(ast);
830 				// sccp_log((DEBUGCAT_PBX | DEBUGCAT_INDICATE)) (VERBOSE_PREFIX_3 "%s: hangup cause set: %d\n", c->designator, hangupcause);
831 				// res = -1;
832 				inband_if_receivechannel = TRUE;
833 			}
834 			break;
835 
836 		case AST_CONTROL_MASQUERADE_NOTIFY:
837 			res = -1;										// Return -1 so that asterisk core will correctly set up hangupcauses.
838 			break;
839 
840 		case -1:											// Asterisk prod the channel /* STOP_TONE */
841 			if (	c->line &&
842 				c->state > SCCP_GROUPED_CHANNELSTATE_DIALING &&
843 				c->calltype == SKINNY_CALLTYPE_OUTBOUND &&
844 				!ast_channel_hangupcause(ast)
845 			) {
846 				if(!sccp_rtp_getState(&c->rtp.audio, SCCP_RTP_RECEPTION)) {
847 					sccp_channel_openReceiveChannel(c);
848 				}
849 			}
850 			inband_if_receivechannel = TRUE;
851 			break;
852 
853 		default:
854 			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);
855 			res = -1;	/* this indication is not supported */
856 			break;
857 	}
858 	if(inband_if_receivechannel && sccp_rtp_getState(&c->rtp.audio, SCCP_RTP_RECEPTION)) {
859 		res = -1;
860 	}
861 	sccp_log((DEBUGCAT_PBX | DEBUGCAT_INDICATE)) (VERBOSE_PREFIX_2 "%s: (pbx_indicate) finish: send indication (res:%d)\n", DEV_ID_LOG(d), res);
862 	return res;
863 }
864 
865 /*!
866  * \brief Read from an Asterisk Channel
867  * \param ast Asterisk Channel as ast_channel
868  *
869  * \called_from_asterisk
870  *
871  * \note not following the refcount rules... channel is already retained
872  */
sccp_astwrap_rtp_read(PBX_CHANNEL_TYPE * ast)873 static PBX_FRAME_TYPE *sccp_astwrap_rtp_read(PBX_CHANNEL_TYPE * ast)
874 {
875 	//AUTO_RELEASE(sccp_channel_t, c , NULL);									// not following the refcount rules... channel is already retained
876 	sccp_channel_t *c = NULL;
877 	PBX_FRAME_TYPE *frame = &ast_null_frame;
878 
879 	if (!(c = CS_AST_CHANNEL_PVT(ast))) {									// not following the refcount rules... channel is already retained
880 		pbx_log(LOG_ERROR, "SCCP: (rtp_read) no channel pvt\n");
881 		goto EXIT_FUNC;
882 	}
883 
884 	if (!c->rtp.audio.instance) {
885 		pbx_log(LOG_NOTICE, "SCCP: (rtp_read) no rtp stream yet. skip\n");
886 		goto EXIT_FUNC;
887 	}
888 
889 	switch (ast_channel_fdno(ast)) {
890 
891 		case 0:
892 			frame = ast_rtp_instance_read(c->rtp.audio.instance, 0);					/* RTP Audio */
893 			break;
894 		case 1:
895 			frame = ast_rtp_instance_read(c->rtp.audio.instance, 1);					/* RTCP Control Channel */
896 			break;
897 		case 2:
898 #ifdef CS_SCCP_VIDEO
899 			frame = ast_rtp_instance_read(c->rtp.video.instance, 0);					/* RTP Video */
900 #else
901 			pbx_log(LOG_NOTICE, "SCCP: (rtp_read) Cannot handle video rtp stream.\n");
902 #endif
903 			break;
904 		case 3:
905 #ifdef CS_SCCP_VIDEO
906 			frame = ast_rtp_instance_read(c->rtp.video.instance, 1);					/* RTCP Control Channel for video */
907 #else
908 			pbx_log(LOG_NOTICE, "SCCP: (rtp_read) Cannot handle video rtcp stream.\n");
909 #endif
910 			break;
911 		default:
912 			// pbx_log(LOG_NOTICE, "%s: (rtp_read) Unknown Frame Type (%d). Skipping\n", c->designator, ast_channel_fdno(ast));
913 			goto EXIT_FUNC;
914 	}
915 	//sccp_log((DEBUGCAT_CORE))(VERBOSE_PREFIX_3 "%s: read format: ast->fdno: %d, frametype: %d, %s(%d)\n", DEV_ID_LOG(c->device), ast_channel_fdno(ast), frame->frametype, pbx_getformatname(frame->subclass), frame->subclass);
916 	if(frame && frame != &ast_null_frame && frame->frametype == AST_FRAME_VOICE) {
917 #ifdef CS_SCCP_CONFERENCE
918 		if (c->conference && (!ast_format_cache_is_slinear(ast_channel_readformat(ast)))) {
919 			ast_set_read_format(ast, ast_format_slin96);
920 		} else
921 #endif
922 		{
923 			if (ast_format_cap_iscompatible_format(ast_channel_nativeformats(ast), frame->subclass.format) == AST_FORMAT_CMP_NOT_EQUAL) {
924 				struct ast_format_cap *caps;
925 				sccp_log(DEBUGCAT_CODEC)(VERBOSE_PREFIX_3 "%s: (rtp_read) Format changed to %s\n", c->designator, ast_format_get_name(frame->subclass.format));
926 				caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
927 				if (caps) {
928 					ast_format_cap_append(caps, frame->subclass.format, 0);
929 					ast_channel_nativeformats_set(ast, caps);
930 					ao2_cleanup(caps);
931 				}
932 				ast_set_read_format(ast, ast_channel_readformat(ast));
933 				ast_set_write_format(ast, ast_channel_writeformat(ast));
934 			}
935 		}
936 	}
937 
938 	/* Only allow audio through if they sent progress, or if the channel is actually answered */
939 	/* removed causing one way audio trouble, needs more research */
940 	if(c->calltype != SKINNY_CALLTYPE_INBOUND && pbx_channel_state(ast) != AST_STATE_UP && c->wantsEarlyRTP() && c->progressSent() && (frame == &ast_null_frame || !sccp_channel_finishHolePunch(c))) {
941 		// if hole punch is not active and the channel is not active either, we transmit null packets in the meantime
942 		// Only allow audio through if they sent progress
943 		ast_frfree(frame);
944 		frame = &ast_null_frame;
945 	}
946 EXIT_FUNC:
947 	return frame;
948 }
949 
950 /*!
951  * \brief Write to an Asterisk Channel
952  * \param ast Channel as ast_channel
953  * \param frame Frame as ast_frame
954  *
955  * \called_from_asterisk
956  *
957  * \note not following the refcount rules... channel is already retained
958  */
sccp_astwrap_rtp_write(PBX_CHANNEL_TYPE * ast,PBX_FRAME_TYPE * frame)959 static int sccp_astwrap_rtp_write(PBX_CHANNEL_TYPE * ast, PBX_FRAME_TYPE * frame)
960 {
961 	//AUTO_RELEASE(sccp_channel_t, c , NULL);								// not following the refcount rules... channel is already retained
962 	sccp_channel_t *c = NULL;
963 
964 	int res = 0;
965 
966 	if (!(c = CS_AST_CHANNEL_PVT(ast))) {									// not following the refcount rules... channel is already retained
967 		return -1;
968 	}
969 
970 	switch (frame->frametype) {
971 		case AST_FRAME_VOICE:
972 			// checking for samples to transmit
973 			if (ast_format_cap_iscompatible_format(ast_channel_nativeformats(ast), frame->subclass.format) == AST_FORMAT_CMP_NOT_EQUAL) {
974 				pbx_str_t *codec_buf = pbx_str_alloca(64);
975 				sccp_log(DEBUGCAT_CODEC)(VERBOSE_PREFIX_3 "%s: (rtp_write) Asked to transmit frame type %s, while native formats is %s (read/write = %s/%s)\n",
976 					c->designator,
977 					ast_format_get_name(frame->subclass.format),
978 					ast_format_cap_get_names(ast_channel_nativeformats(ast), &codec_buf),
979 					ast_channel_readformat(ast) ? ast_format_get_name(ast_channel_readformat(ast)) : "",
980 					ast_channel_writeformat(ast) ? ast_format_get_name(ast_channel_writeformat(ast)) : ""
981 				);
982 				//return -1;
983 			}
984 			if(pbx_channel_state(ast) != AST_STATE_UP && c->state > SCCP_GROUPED_CHANNELSTATE_DIALING && c->wantsEarlyRTP() && !c->progressSent()) {
985 				sccp_log(DEBUGCAT_RTP)(VERBOSE_PREFIX_3 "%s: (rtp_write) device requested earlyRtp and we received an incoming audio packet calling makeProgress\n", c->designator);
986 				c->makeProgress(c);
987 			}
988 			if (!frame->samples) {
989 				if(!strcasecmp(frame->src, "ast_prod")) {
990 					sccp_log((DEBUGCAT_PBX | DEBUGCAT_CHANNEL)) (VERBOSE_PREFIX_3 "%s: Asterisk prodded channel %s.\n", c->currentDeviceId, pbx_channel_name(ast));
991 				} else {
992 					pbx_log(LOG_NOTICE, "%s: Asked to transmit frame type %d ('%s') with no samples.\n", c->currentDeviceId, (int)frame->frametype, frame->src);
993 				}
994 				break;
995 			}
996 			if(c->rtp.audio.instance && (sccp_rtp_getState(&c->rtp.audio, SCCP_RTP_RECEPTION) & SCCP_RTP_STATUS_ACTIVE) != 0) {
997 				res = ast_rtp_instance_write(c->rtp.audio.instance, frame);
998 			}
999 			break;
1000 		case AST_FRAME_IMAGE:
1001 		case AST_FRAME_VIDEO:
1002 #ifdef CS_SCCP_VIDEO
1003 			if(sccp_channel_getVideoMode(c) != SCCP_VIDEO_MODE_OFF && c->state != SCCP_CHANNELSTATE_HOLD) {
1004 				if(ast_format_cmp(ast_format_h264, frame->subclass.format) != AST_FORMAT_CMP_EQUAL) {
1005 					sccp_channel_closeMultiMediaReceiveChannel(c, TRUE);
1006 					sccp_channel_stopMultiMediaTransmission(c, TRUE);
1007 					sccp_channel_setVideoMode(c, "off");
1008 					return -1;
1009 				}
1010 				sccp_rtp_status_t receptionstate = sccp_rtp_getState(&c->rtp.video, SCCP_RTP_RECEPTION);
1011 				if(pbx_channel_state(ast) != AST_STATE_UP && c->state > SCCP_GROUPED_CHANNELSTATE_DIALING) {
1012 					if(c->wantsEarlyRTP() && !c->progressSent()) {
1013 						sccp_log(DEBUGCAT_RTP)(VERBOSE_PREFIX_3 "%s: (rtp_write) device requested earlyRtp and we received an incoming video packet calling makeProgress\n", c->designator);
1014 						c->makeProgress(c);
1015 					}
1016 				} else if(!receptionstate) {
1017 					sccp_log((DEBUGCAT_RTP))(VERBOSE_PREFIX_3 "%s: got first video frame %s\n", c->currentDeviceId, "H264");
1018 					sccp_channel_openMultiMediaReceiveChannel(c);
1019 				}
1020 				if(receptionstate & SCCP_RTP_STATUS_ACTIVE) {
1021 					res = ast_rtp_instance_write(c->rtp.video.instance, frame);
1022 				}
1023 			}
1024 #endif
1025 			break;
1026 		case AST_FRAME_TEXT:
1027 		case AST_FRAME_MODEM:
1028 		default:
1029 			pbx_log(LOG_WARNING, "%s: Can't send %d type frames with SCCP write on channel %s\n", c->currentDeviceId, frame->frametype, pbx_channel_name(ast));
1030 			break;
1031 	}
1032 
1033 	return res;
1034 }
1035 
sccp_astwrap_setDialedNumber(const sccp_channel_t * channel,const char * number)1036 static void sccp_astwrap_setDialedNumber(const sccp_channel_t *channel, const char *number)
1037 {
1038 	PBX_CHANNEL_TYPE *pbx_channel = channel->owner;
1039 	if (pbx_channel && number) {
1040 		struct ast_party_dialed dialed;
1041 		ast_party_dialed_init(&dialed);
1042 		dialed.number.str = pbx_strdupa(number);
1043 		ast_trim_blanks(dialed.number.str);
1044 		ast_party_dialed_set(ast_channel_dialed(pbx_channel), &dialed);
1045 	}
1046 }
1047 
sccp_astwrap_setCalleridPresentation(PBX_CHANNEL_TYPE * pbx_channel,sccp_callerid_presentation_t presentation)1048 static void sccp_astwrap_setCalleridPresentation(PBX_CHANNEL_TYPE *pbx_channel, sccp_callerid_presentation_t presentation)
1049 {
1050 	if (pbx_channel && CALLERID_PRESENTATION_FORBIDDEN == presentation) {
1051 		ast_channel_caller(pbx_channel)->id.name.presentation |= AST_PRES_PROHIB_USER_NUMBER_NOT_SCREENED;
1052 		ast_channel_caller(pbx_channel)->id.number.presentation |= AST_PRES_PROHIB_USER_NUMBER_NOT_SCREENED;
1053 	}
1054 }
1055 
sccp_astwrap_setNativeAudioFormats(constChannelPtr channel,skinny_codec_t codecs[])1056 static int sccp_astwrap_setNativeAudioFormats(constChannelPtr channel, skinny_codec_t codecs[])
1057 {
1058 	if (!channel || !channel->owner || !ast_channel_nativeformats(channel->owner)) {
1059 		pbx_log(LOG_ERROR, "SCCP: (setNativeAudioFormats) no channel provided!\n");
1060 		return 0;
1061 	}
1062 	PBX_CHANNEL_TYPE *ast = channel->owner;
1063 
1064 	struct ast_format_cap *caps = ao2_t_bump((struct ast_format_cap *)channel->caps, "sccp_channel_caps");
1065 	if (!caps) {
1066         	return 0;
1067 	}
1068 	ast_format_cap_append_from_cap(caps, ast_channel_nativeformats(ast), AST_MEDIA_TYPE_UNKNOWN);
1069 	ast_format_cap_remove_by_type(caps, AST_MEDIA_TYPE_AUDIO);
1070 	pbx_format_cap_append_skinny(caps, codecs);
1071 
1072 	ast_channel_lock(ast);
1073 	ast_channel_nativeformats_set(ast, caps);
1074 	ast_channel_unlock(ast);
1075 	ao2_t_ref(caps, -1, "sccp_channel_caps");
1076 
1077 	pbx_str_t *codec_buf = pbx_str_alloca(AST_FORMAT_CAP_NAMES_LEN);
1078 	sccp_log((DEBUGCAT_RTP | DEBUGCAT_CODEC)) (VERBOSE_PREFIX_3 "%s: (setNativeAudioFormats) %s\n", channel->designator, ast_format_cap_get_names(ast_channel_nativeformats(ast), &codec_buf));
1079 	return 1;
1080 }
1081 
sccp_astwrap_setNativeVideoFormats(constChannelPtr channel,skinny_codec_t codecs[])1082 static int sccp_astwrap_setNativeVideoFormats(constChannelPtr channel, skinny_codec_t codecs[])
1083 {
1084 	if (!channel || !channel->owner || !ast_channel_nativeformats(channel->owner)) {
1085 		pbx_log(LOG_ERROR, "SCCP: (setNativeVideoFormats) no channel provided!\n");
1086 		return 0;
1087 	}
1088 	PBX_CHANNEL_TYPE *ast = channel->owner;
1089 
1090 	struct ast_format_cap *caps = ao2_t_bump((struct ast_format_cap *)channel->caps, "sccp_channel_caps");
1091 	if (!caps) {
1092         	return 0;
1093 	}
1094 	ast_format_cap_append_from_cap(caps, ast_channel_nativeformats(ast), AST_MEDIA_TYPE_UNKNOWN);
1095 	ast_format_cap_remove_by_type(caps, AST_MEDIA_TYPE_VIDEO);
1096 	pbx_format_cap_append_skinny(caps, codecs);
1097 
1098 	ast_channel_lock(ast);
1099 	ast_channel_nativeformats_set(ast, caps);
1100 	ast_channel_unlock(ast);
1101 	ao2_t_ref(caps, -1, "sccp_channel_caps");
1102 
1103 	pbx_str_t *codec_buf = pbx_str_alloca(AST_FORMAT_CAP_NAMES_LEN);
1104 	sccp_log((DEBUGCAT_RTP | DEBUGCAT_CODEC)) (VERBOSE_PREFIX_3 "%s: (setNativeVideoFormats) %s\n", channel->designator, ast_format_cap_get_names(ast_channel_nativeformats(ast), &codec_buf));
1105 	return 1;
1106 }
1107 
sccp_astwrap_setWriteFormat(constChannelPtr channel,skinny_codec_t codec)1108 static boolean_t sccp_astwrap_setWriteFormat(constChannelPtr channel, skinny_codec_t codec)
1109 {
1110 	if (!channel) {
1111 		return FALSE;
1112 	}
1113 	sccp_log((DEBUGCAT_RTP | DEBUGCAT_CODEC)) (VERBOSE_PREFIX_3 "%s: (setWriteFormat) %s)\n", channel->designator, codec2str(codec));
1114 
1115 	struct ast_format *ast_format = sccp_astwrap_skinny2ast_format(codec);
1116 	if (ast_format == ast_format_none)
1117 		return FALSE;
1118 
1119 	if (channel->rtp.audio.instance) {
1120 		ast_channel_set_rawwriteformat(channel->owner, ast_format);
1121 		ast_rtp_instance_set_write_format(channel->rtp.audio.instance, ast_format);
1122 	}
1123 	ast_channel_set_writeformat(channel->owner, ast_format);
1124 	ao2_ref(ast_format, -1);
1125 	return TRUE;
1126 }
1127 
sccp_astwrap_setReadFormat(constChannelPtr channel,skinny_codec_t codec)1128 static boolean_t sccp_astwrap_setReadFormat(constChannelPtr channel, skinny_codec_t codec)
1129 {
1130 	if (!channel) {
1131 		return FALSE;
1132 	}
1133 	sccp_log((DEBUGCAT_RTP | DEBUGCAT_CODEC)) (VERBOSE_PREFIX_3 "%s: (setReadFormat) %s)\n", channel->designator, codec2str(codec));
1134 
1135 	struct ast_format *ast_format = sccp_astwrap_skinny2ast_format(codec);
1136 	if (ast_format == ast_format_none)
1137 		return FALSE;
1138 
1139 	if (channel->rtp.audio.instance) {
1140 		ast_channel_set_rawreadformat(channel->owner, ast_format);
1141 		ast_rtp_instance_set_read_format(channel->rtp.audio.instance, ast_format);
1142 	}
1143 	ast_channel_set_readformat(channel->owner, ast_format);
1144 	ao2_ref(ast_format, -1);
1145 	return TRUE;
1146 }
1147 
1148 
sccp_astwrap_removeTimingFD(PBX_CHANNEL_TYPE * ast)1149 static void sccp_astwrap_removeTimingFD(PBX_CHANNEL_TYPE *ast)
1150 {
1151 	if (ast) {
1152 		struct ast_timer *timer=ast_channel_timer(ast);
1153 		if (timer) {
1154 			//ast_log(LOG_NOTICE, "%s: (clean_timer_fds) timername: %s, fd:%d\n", ast_channel_name(ast), ast_timer_get_name(timer), ast_timer_fd(timer));
1155 			ast_timer_disable_continuous(timer);
1156 			ast_timer_close(timer);
1157 			ast_channel_set_fd(ast, AST_TIMING_FD, -1);
1158 			ast_channel_timingfd_set(ast, -1);
1159 			ast_channel_timer_set(ast, NULL);
1160 		}
1161 	}
1162 }
1163 
sccp_astwrap_setOwner(sccp_channel_t * channel,PBX_CHANNEL_TYPE * pbx_channel)1164 static void sccp_astwrap_setOwner(sccp_channel_t * channel, PBX_CHANNEL_TYPE * pbx_channel)
1165 {
1166 	PBX_CHANNEL_TYPE *prev_owner = channel->owner;
1167 
1168 	if (pbx_channel) {
1169 		channel->owner = pbx_channel_ref(pbx_channel);
1170 		ast_module_ref(ast_module_info->self);
1171 	} else {
1172 		channel->owner = NULL;
1173 	}
1174 	if (prev_owner) {
1175 		pbx_channel_unref(prev_owner);
1176 		ast_module_unref(ast_module_info->self);
1177 	}
1178 	if (channel->rtp.audio.instance) {
1179 		ast_rtp_instance_set_channel_id(channel->rtp.audio.instance, pbx_channel ? ast_channel_uniqueid(pbx_channel) : "");
1180 	}
1181 	if (channel->rtp.video.instance) {
1182 		ast_rtp_instance_set_channel_id(channel->rtp.video.instance, pbx_channel ? ast_channel_uniqueid(pbx_channel) : "");
1183 	}
1184 }
1185 
__sccp_astwrap_updateConnectedLine(PBX_CHANNEL_TYPE * pbx_channel,const char * number,const char * name,uint8_t reason)1186 static void __sccp_astwrap_updateConnectedLine(PBX_CHANNEL_TYPE *pbx_channel, const char *number, const char *name, uint8_t reason)
1187 {
1188 	if (!pbx_channel) {
1189 		return;
1190 	}
1191 
1192 	struct ast_party_connected_line connected;
1193 	struct ast_set_party_connected_line update_connected = {{0}};
1194 
1195 	ast_party_connected_line_init(&connected);
1196 	if (number) {
1197 		update_connected.id.number = 1;
1198 		connected.id.number.valid = 1;
1199 		connected.id.number.str = pbx_strdupa(number);
1200 		connected.id.number.presentation = AST_PRES_ALLOWED_NETWORK_NUMBER;
1201 	}
1202 	if (name) {
1203 		update_connected.id.name = 1;
1204 		connected.id.name.valid = 1;
1205 		connected.id.name.str = pbx_strdupa(name);
1206 		connected.id.name.presentation = AST_PRES_ALLOWED_NETWORK_NUMBER;
1207 	}
1208 	if (update_connected.id.number || update_connected.id.name) {
1209 		ast_set_party_id_all(&update_connected.priv);
1210 		// connected.id.tag = NULL;
1211 		connected.source = reason;
1212 		ast_channel_queue_connected_line_update(pbx_channel, &connected, &update_connected);
1213 		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)");
1214 	}
1215 }
1216 
sccp_astwrap_allocPBXChannel(sccp_channel_t * channel,const void * ids,const PBX_CHANNEL_TYPE * pbxSrcChannel,PBX_CHANNEL_TYPE ** _pbxDstChannel)1217 static boolean_t sccp_astwrap_allocPBXChannel(sccp_channel_t * channel, const void *ids, const PBX_CHANNEL_TYPE * pbxSrcChannel, PBX_CHANNEL_TYPE ** _pbxDstChannel)
1218 {
1219 	const struct ast_assigned_ids *assignedids = NULL;
1220 	PBX_CHANNEL_TYPE *pbxDstChannel = NULL;
1221 	if (!channel || !channel->line) {
1222 		return FALSE;
1223 	}
1224 	AUTO_RELEASE(sccp_line_t, line , sccp_line_retain(channel->line));
1225 	if (!line) {
1226 		return FALSE;
1227 	}
1228 
1229 	channel->caps = ast_t_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT, "sccp_channel_caps");			/* cleanup in channel destructor */
1230 	if (!channel->caps) {
1231 		ao2_cleanup(channel->caps);
1232 		return FALSE;
1233 	}
1234 	struct ast_format_cap *caps = ao2_t_bump(channel->caps, "sccp_channel_caps");
1235 
1236 	if (ids) {
1237 		assignedids = (const struct ast_assigned_ids *)ids;
1238 	}
1239 
1240 	sccp_log(DEBUGCAT_CHANNEL)(VERBOSE_PREFIX_3 "SCCP: (allocPBXChannel) Create New Channel with name: SCCP/%s-%08X\n", line->name, channel->callid);
1241 	pbxDstChannel = ast_channel_alloc(0, AST_STATE_DOWN, line->cid_num, line->cid_name, line->accountcode, line->name, line->context, assignedids, pbxSrcChannel, line->amaflags, "%s", channel->designator);
1242 	if (pbxDstChannel == NULL) {
1243 		pbx_log(LOG_ERROR, "SCCP: (allocPBXChannel) ast_channel_alloc failed\n");
1244 		ao2_cleanup(caps);
1245 		return FALSE;
1246 	}
1247 
1248 	ast_channel_stage_snapshot(pbxDstChannel);
1249 	if (channel->callid) {
1250 		pbx_channel_callid_set(pbxDstChannel, channel->pbx_callid);
1251 	}
1252 
1253 	ast_channel_tech_set(pbxDstChannel, &sccp_tech);
1254 	ast_channel_tech_pvt_set(pbxDstChannel, sccp_channel_retain(channel));
1255 
1256 	pbx_str_t *codec_buf = pbx_str_alloca(AST_FORMAT_CAP_NAMES_LEN);
1257 	//pbx_log(LOG_NOTICE, "allocPBXChannel: tmp->nativeformats=%s\n", ast_format_cap_get_names(ast_channel_nativeformats(pbxDstChannel), &codec_buf));
1258 
1259 	pbx_format_cap_append_skinny(caps, channel->preferences.audio);
1260 #ifdef CS_SCCP_VIDEO
1261 	pbx_format_cap_append_skinny(caps, channel->preferences.video);
1262 #endif
1263 	struct ast_format_cap *joint = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
1264 	if (!joint) {
1265 		ao2_cleanup(pbxDstChannel);
1266 		ao2_cleanup(caps);
1267 		return FALSE;
1268 	}
1269 	struct ast_format_cap *what = NULL;
1270 	if (pbxSrcChannel && ast_format_cap_count(ast_channel_nativeformats(pbxSrcChannel)) > 0) {
1271 		sccp_log(DEBUGCAT_CODEC)(VERBOSE_PREFIX_3 "allocPBXChannel: new->nativeformats=%s based on audio preferences\n", ast_format_cap_get_names(caps, &codec_buf));
1272 
1273 		ast_format_cap_get_compatible(caps, ast_channel_nativeformats(pbxSrcChannel /*requestor*/), joint);
1274 		sccp_log(DEBUGCAT_CODEC)(VERBOSE_PREFIX_3  "allocPBXChannel: requestor->nativeformats=%s\n", ast_format_cap_get_names( ast_channel_nativeformats(pbxSrcChannel /*requestor*/), &codec_buf));
1275 		sccp_log(DEBUGCAT_CODEC)(VERBOSE_PREFIX_3 "allocPBXChannel: joint formats=%s\n", ast_format_cap_get_names(joint, &codec_buf));
1276 	}
1277 	if (ast_format_cap_count(joint) > 0) {
1278 		what = joint;
1279 	} else if (ast_format_cap_count(caps)) {
1280 		what = caps;
1281 	} else {
1282 		what = (&sccp_tech)->capabilities;
1283 	}
1284 	ast_format_cap_append_from_cap(caps, what, AST_MEDIA_TYPE_UNKNOWN);
1285 
1286 	struct ast_format *fmt = ast_format_cap_get_best_by_type(what, AST_MEDIA_TYPE_AUDIO); /* get the best audio format */
1287 	if (fmt) {
1288 		ast_format_cap_remove_by_type(caps, AST_MEDIA_TYPE_AUDIO); /* remove only the other audio formats */
1289 		ast_format_cap_append(caps, fmt, 0); /* add our best choice back */
1290 	} else {
1291 		/* If we don't have an audio format, try to get something */
1292 		fmt = ast_format_cap_get_format(caps, 0);
1293 		if (!fmt) {
1294 			ast_log(LOG_WARNING, "No compatible formats could be found for %s\n", ast_channel_name(pbxDstChannel));
1295 			ao2_cleanup(caps);
1296 			ast_channel_stage_snapshot_done(pbxDstChannel);
1297 			ast_hangup(pbxDstChannel);
1298 			return FALSE;
1299 		}
1300 	}
1301 	ast_channel_nativeformats_set(pbxDstChannel, caps);
1302 	ao2_cleanup(joint);
1303 	ao2_t_ref(caps, -1, "sccp_channel_caps");	/* see:bump */
1304 
1305 	sccp_log(DEBUGCAT_CODEC)(VERBOSE_PREFIX_3 "allocPBXChannel: using nativeformats=%s fmt=%s\n", ast_format_cap_get_names(ast_channel_nativeformats(pbxDstChannel), &codec_buf), ast_format_get_name(fmt));
1306 
1307 	ast_channel_set_writeformat(pbxDstChannel, fmt);
1308 	ast_channel_set_rawwriteformat(pbxDstChannel, fmt);
1309 	ast_channel_set_readformat(pbxDstChannel, fmt);
1310 	ast_channel_set_rawreadformat(pbxDstChannel, fmt);
1311 	ao2_ref(fmt, -1);
1312 	/* EndCodec */
1313 
1314 	sccp_astwrap_setOwner(channel, pbxDstChannel);
1315 
1316 	ast_channel_context_set(pbxDstChannel, line->context);
1317 	ast_channel_exten_set(pbxDstChannel, line->name);
1318 	ast_channel_priority_set(pbxDstChannel, 1);
1319 	ast_channel_adsicpe_set(pbxDstChannel, AST_ADSI_UNAVAILABLE);
1320 
1321 	if (!sccp_strlen_zero(line->language)) {
1322 		ast_channel_language_set(pbxDstChannel, line->language);
1323 	}
1324 
1325 	if (!sccp_strlen_zero(line->accountcode)) {
1326 		ast_channel_accountcode_set(pbxDstChannel, line->accountcode);
1327 	}
1328 
1329 	if (!sccp_strlen_zero(line->musicclass)) {
1330 		ast_channel_musicclass_set(pbxDstChannel, line->musicclass);
1331 	}
1332 
1333 	if (line->amaflags) {
1334 		ast_channel_amaflags_set(pbxDstChannel, line->amaflags);
1335 	}
1336 	if (line->callgroup) {
1337 		ast_channel_callgroup_set(pbxDstChannel, line->callgroup);
1338 	}
1339 
1340 	ast_channel_callgroup_set(pbxDstChannel, line->callgroup);						// needed for ast_pickup_call
1341 #if CS_SCCP_PICKUP
1342 	if (line->pickupgroup) {
1343 		ast_channel_pickupgroup_set(pbxDstChannel, line->pickupgroup);
1344 	}
1345 #if CS_AST_HAS_NAMEDGROUP
1346 	if (!sccp_strlen_zero(line->namedcallgroup)) {
1347 		ast_channel_named_callgroups_set(pbxDstChannel, ast_get_namedgroups(line->namedcallgroup));
1348 	}
1349 
1350 	if (!sccp_strlen_zero(line->namedpickupgroup)) {
1351 		ast_channel_named_pickupgroups_set(pbxDstChannel, ast_get_namedgroups(line->namedpickupgroup));
1352 	}
1353 #	endif
1354 #endif
1355 	if (!sccp_strlen_zero(line->parkinglot)) {
1356 		ast_channel_parkinglot_set(pbxDstChannel, line->parkinglot);
1357 	}
1358 
1359 	/** the the tonezone using language information */
1360 	if (!sccp_strlen_zero(line->language) && ast_get_indication_zone(line->language)) {
1361 		ast_channel_zone_set(pbxDstChannel, ast_get_indication_zone(line->language));			/* this will core asterisk on hangup */
1362 	}
1363 
1364 	ast_channel_stage_snapshot_done(pbxDstChannel);
1365 	ast_channel_unlock(pbxDstChannel);
1366 
1367 	(*_pbxDstChannel) = pbxDstChannel;
1368 
1369 	return TRUE;
1370 }
1371 
1372 /*!
1373  * \brief Uses ast_channel_move instead of the old masquerade procedure to force a channel into a bridge and hangup the peer channel
1374  */
sccp_astwrap_masqueradeHelper(PBX_CHANNEL_TYPE * pbxChannel,PBX_CHANNEL_TYPE * pbxTmpChannel)1375 static boolean_t sccp_astwrap_masqueradeHelper(PBX_CHANNEL_TYPE * pbxChannel, PBX_CHANNEL_TYPE * pbxTmpChannel)
1376 {
1377 	boolean_t res = FALSE;
1378 	pbx_log(LOG_NOTICE, "SCCP: (masqueradeHelper) answer temp: %s\n", ast_channel_name(pbxTmpChannel));
1379 
1380 	ast_channel_ref(pbxChannel);
1381 	if(ast_answer(pbxChannel) == 0) {
1382 		pbx_log(LOG_NOTICE, "SCCP: (masqueradeHelper) replace pbxTmpChannel: %s with %s (move)\n", ast_channel_name(pbxTmpChannel), ast_channel_name(pbxChannel));
1383 		if(ast_channel_move(pbxTmpChannel, pbxChannel)) {
1384 			pbx_log(LOG_ERROR, "SCCP: (masqueradeHelper) move failed. Hanging up tmp channel: %s\n", ast_channel_name(pbxTmpChannel));
1385 			ast_hangup(pbxTmpChannel);
1386 		} else {
1387 			pbx_log(LOG_NOTICE, "SCCP: (masqueradeHelper) move succeeded. Hanging up orphan: %s\n", ast_channel_name(pbxChannel));
1388 			ast_hangup(pbxChannel);
1389 			pbx_channel_set_hangupcause(pbxTmpChannel, AST_CAUSE_REDIRECTED_TO_NEW_DESTINATION);
1390 			res = TRUE;
1391 		}
1392 		pbx_channel_unref(pbxTmpChannel);
1393 	}
1394 	pbx_channel_unref(pbxChannel);
1395 	return res;
1396 }
1397 
sccp_astwrap_allocTempPBXChannel(PBX_CHANNEL_TYPE * pbxSrcChannel,PBX_CHANNEL_TYPE ** _pbxDstChannel)1398 static boolean_t sccp_astwrap_allocTempPBXChannel(PBX_CHANNEL_TYPE * pbxSrcChannel, PBX_CHANNEL_TYPE ** _pbxDstChannel)
1399 {
1400 	PBX_CHANNEL_TYPE *pbxDstChannel = NULL;
1401 	struct ast_assigned_ids assignedids = {NULL, NULL};
1402 
1403 	if (!pbxSrcChannel) {
1404 		pbx_log(LOG_ERROR, "SCCP: (allocTempPBXChannel) no pbx channel provided\n");
1405 		return FALSE;
1406 	}
1407 	struct ast_format_cap *caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
1408 	if (!caps) {
1409 		return FALSE;
1410 	}
1411 
1412 /*
1413 	assignedids.uniqueid = ast_channel_uniqueid(pbxSrcChannel);
1414 	{
1415 		char *uniqueid2;
1416 		uniqueid2 = ast_alloca(strlen(assignedids.uniqueid) + 3);
1417 		strcpy(uniqueid2, assignedids.uniqueid);
1418 		strcat(uniqueid2, ";2");
1419 		assignedids.uniqueid2 = uniqueid2;
1420 	}
1421 */
1422 
1423 	ast_channel_lock(pbxSrcChannel);
1424 	pbxDstChannel = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, ast_channel_accountcode(pbxSrcChannel), pbx_channel_exten(pbxSrcChannel), pbx_channel_context(pbxSrcChannel), &assignedids, pbxSrcChannel, ast_channel_amaflags(pbxSrcChannel), "%s-TMP", ast_channel_name(pbxSrcChannel));
1425 	if (pbxDstChannel == NULL) {
1426 		pbx_log(LOG_ERROR, "SCCP: (allocTempPBXChannel) ast_channel_alloc failed\n");
1427 		ao2_cleanup(caps);
1428 		return FALSE;
1429 	}
1430 
1431 	ast_channel_stage_snapshot(pbxDstChannel);
1432 	//sccp_astwrap_setOwner(channel, pbxDstChannel);
1433 
1434 	ast_channel_tech_set(pbxDstChannel, &null_tech);							// USE null_tech to prevent fixup issues. Channel is only used to masquerade a channel out of a running bridge.
1435 	//ast_channel_tech_pvt_set(pbxDstChannel, sccp_channel_retain(channel));
1436 
1437 	// if (ast_format_cap_is_empty(pbx_channel_nativeformats(pbxSrcChannel))) {
1438 	if (ast_format_cap_count(ast_channel_nativeformats(pbxSrcChannel)) > 0) {
1439 		ast_format_cap_append_from_cap(caps, ast_channel_nativeformats(pbxSrcChannel), AST_MEDIA_TYPE_UNKNOWN);
1440 	} else {
1441 		struct ast_format *ast_format = ast_format_slin16;
1442 		unsigned int framing = ast_format_get_default_ms(ast_format);
1443 		ast_format_cap_append(caps, ast_format, framing);
1444 	}
1445 	ast_channel_nativeformats_set(pbxDstChannel, caps);
1446 	struct ast_format *tmpfmt = ast_format_cap_get_format(caps, 0);
1447 	ast_channel_set_writeformat(pbxDstChannel, tmpfmt);
1448 	ast_channel_set_rawwriteformat(pbxDstChannel, tmpfmt);
1449 	ast_channel_set_readformat(pbxDstChannel, tmpfmt);
1450 	ast_channel_set_rawreadformat(pbxDstChannel, tmpfmt);
1451 
1452 	//pbx_str_t *codec_buf = pbx_str_alloca(AST_FORMAT_CAP_NAMES_LEN);
1453 	//pbx_log(LOG_NOTICE, "allocPBXChannel: tmp->nativeformats=%s fmt=%s\n", ast_format_cap_get_names(ast_channel_nativeformats(pbxDstChannel), &codec_buf), ast_format_get_name(tmpfmt));
1454 
1455 	ao2_ref(tmpfmt, -1);
1456 	//ao2_ref(caps, -1);
1457 	ao2_cleanup(caps);
1458 	/* EndCodec */
1459 
1460 	ast_channel_context_set(pbxDstChannel, ast_channel_context(pbxSrcChannel));
1461 	ast_channel_exten_set(pbxDstChannel, ast_channel_exten(pbxSrcChannel));
1462 	ast_channel_priority_set(pbxDstChannel, ast_channel_priority(pbxSrcChannel));
1463 	ast_channel_adsicpe_set(pbxDstChannel, AST_ADSI_UNAVAILABLE);
1464 	ast_channel_stage_snapshot_done(pbxDstChannel);
1465 	ast_channel_unlock(pbxSrcChannel);
1466 	ast_channel_unlock(pbxDstChannel);
1467 
1468 	(*_pbxDstChannel) = pbxDstChannel;
1469 	//pbx_channel_ref(pbxDstChannel);
1470 
1471 	return TRUE;
1472 }
1473 
sccp_astwrap_requestAnnouncementChannel(pbx_format_type format_type,const PBX_CHANNEL_TYPE * requestor,void * data)1474 static PBX_CHANNEL_TYPE *sccp_astwrap_requestAnnouncementChannel(pbx_format_type format_type, const PBX_CHANNEL_TYPE * requestor, void *data)
1475 {
1476 	PBX_CHANNEL_TYPE *chan;
1477 	int cause;
1478 	struct ast_format_cap *cap;
1479 	struct ast_format *ast_format;
1480 	unsigned int framing;
1481 
1482 	cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
1483 	if (!cap) {
1484 		return NULL;
1485 	}
1486 	// TODO(dkgroot): convert format_type to ast_format
1487 	ast_format = ast_format_alaw;
1488 	framing = ast_format_get_default_ms(ast_format);
1489 
1490 	ast_format_cap_append(cap, ast_format, framing);
1491 	chan = ast_request("SCCPCBAnn", cap, NULL, NULL, (char *) data, &cause);
1492 	ao2_ref(cap, -1);
1493 
1494 	if (!chan) {
1495 		pbx_log(LOG_ERROR, "SCCP: Requested Unreal channel could not be created, cause: %d\n", cause);
1496 	 	return NULL;
1497 	}
1498 	/* To make sure playback_chan has the same language of that profile */
1499 	if (requestor) {
1500 		ast_channel_lock(chan);
1501 		ast_channel_language_set(chan, ast_channel_language(requestor));
1502 		ast_channel_unlock(chan);
1503 	}
1504 
1505 	ast_debug(1, "Created Unreal channel '%s' related to '%s'\n", ast_channel_name(chan), (char *) data);
1506 	return chan;
1507 }
1508 
1509 
sccp_astwrap_hangup(PBX_CHANNEL_TYPE * ast_channel)1510 int sccp_astwrap_hangup(PBX_CHANNEL_TYPE * ast_channel)
1511 {
1512 	// ast_channel_stage_snapshot(ast_channel);
1513 	AUTO_RELEASE(sccp_channel_t, c , get_sccp_channel_from_pbx_channel(ast_channel));
1514 	int res = -1;
1515 
1516 	if (c) {
1517 		sccp_mutex_lock(&c->lock);
1518 		if (pbx_channel_hangupcause(ast_channel) == AST_CAUSE_ANSWERED_ELSEWHERE) {
1519 			sccp_log((DEBUGCAT_CORE)) (VERBOSE_PREFIX_3 "SCCP: This call was answered elsewhere\n");
1520 			c->answered_elsewhere = TRUE;
1521 		}
1522 		/* postponing pbx_channel_unref to sccp_channel destructor */
1523 		AUTO_RELEASE(sccp_channel_t, channel , sccp_pbx_hangup(c));					/* explicit release from unretained channel returned by sccp_pbx_hangup */
1524 		(void) channel;											// suppress unused variable warning
1525 		sccp_mutex_unlock(&c->lock);
1526 		ast_channel_tech_pvt_set(ast_channel, NULL);
1527 	} else {												// after this moment c might have gone already
1528 		ast_channel_tech_pvt_set(ast_channel, NULL);
1529 		pbx_channel_unref(ast_channel);									// strange unknown channel, why did we get called to hang it up ?
1530 	}
1531 	return res;
1532 }
1533 
parking_event_cb(void * data,struct stasis_subscription * sub,struct stasis_message * message)1534 static void parking_event_cb (void * data, struct stasis_subscription * sub, struct stasis_message * message)
1535 {
1536 	struct ast_parked_call_payload * parked_payload = stasis_message_data (message);
1537 	AUTO_RELEASE (sccp_channel_t, parker, sccp_channel_retain ((sccp_channel_t *)data));
1538 	if (!parker) {
1539 		pbx_log (LOG_ERROR, "No Parker provided\n");
1540 		return;
1541 	}
1542 
1543 	RAII (struct ast_channel *, parker_chan, ast_channel_ref (parker->owner), ao2_cleanup);
1544 	if (!parker_chan) {
1545 		pbx_log (LOG_ERROR, "%s: No Park Owner set\n", parker->designator);
1546 		return;
1547 	}
1548 
1549 	if (stasis_subscription_final_message (sub, message)) {
1550 		// pbx_log(LOG_NOTICE, "%s: (parking_event_cb) Final Message", parker->designator);
1551 		return;
1552 	}
1553 
1554 	switch (parked_payload->event_type) {
1555 		case PARKED_CALL: {
1556 			sccp_log (DEBUGCAT_CHANNEL) (VERBOSE_PREFIX_3 "%s Parked call to parkingspace:%d@%s\n", ast_channel_name (parker_chan), parked_payload->parkingspace, parked_payload->parkinglot);
1557 			char parkingspace[16];
1558 			snprintf (parkingspace, sizeof (parkingspace), "%d", parked_payload->parkingspace);
1559 			AUTO_RELEASE (sccp_device_t, d, sccp_channel_getDevice (parker));
1560 			if (d) {
1561 				char extstr[20] = "";
1562 				snprintf (extstr, sizeof (extstr), "%c%c %s", 128, SKINNY_LBL_CALL_PARK_AT, parkingspace);
1563 				sccp_dev_displayprinotify (d, extstr, SCCP_MESSAGE_PRIORITY_TIMEOUT, 20);
1564 			}
1565 			RAII (struct ast_bridge *, bridge, ast_channel_get_bridge (parker_chan), ao2_cleanup);
1566 			if (bridge) {
1567 				ast_bridge_suspend (bridge, parker_chan);
1568 				ast_channel_lock (parker_chan);
1569 				ast_channel_ref (parker_chan);
1570 				ast_channel_unlock (parker_chan);
1571 				ast_say_digit_str (parker_chan, parkingspace, "", ast_channel_language (parker_chan));
1572 				ast_bridge_unsuspend (bridge, parker_chan);
1573 				ast_channel_unref (parker_chan);
1574 			} else {
1575 				parker->setTone (parker, SKINNY_TONE_CONFIRMATIONTONE, SKINNY_TONEDIRECTION_USER);
1576 			}
1577 			sccp_astgenwrap_requestHangup (parker);
1578 		} break;
1579 		case PARKED_CALL_FAILED: {
1580 			pbx_log (LOG_ERROR, "%s Parked failed\n", ast_channel_name (parker_chan));
1581 			AUTO_RELEASE (sccp_device_t, d, sccp_channel_getDevice (parker));
1582 			if (d) {
1583 				sccp_dev_displayprinotify (d, SKINNY_DISP_TEMP_FAIL, SCCP_MESSAGE_PRIORITY_TIMEOUT, GLOB (digittimeout));
1584 			}
1585 			parker->setTone (parker, SKINNY_TONE_REORDERTONE, SKINNY_TONEDIRECTION_USER);
1586 			sccp_astgenwrap_requestHangup (parker);
1587 		} break;
1588 		default:
1589 			break;
1590 	}
1591 }
1592 
parking_subscriptionCleanup(void * data)1593 static void * parking_subscriptionCleanup (void * data)
1594 {
1595 	AUTO_RELEASE (sccp_channel_t, hostChannel, (sccp_channel_t *)data);
1596 	if (hostChannel && hostChannel->parking_sub) {
1597 		hostChannel->parking_sub = stasis_unsubscribe_and_join (hostChannel->parking_sub);
1598 	}
1599 	return NULL;
1600 }
1601 
1602 /*!
1603  * \brief Parking Thread Arguments Structure
1604  */
1605 
1606 /*!
1607  * \brief Park the bridge channel of hostChannel
1608  * This function prepares the host and the bridged channel to be ready for parking.
1609  * It clones the pbx channel of both sides forward them to the park_thread
1610  *
1611  * \param hostChannel initial channel that request the parking
1612  * \todo we have a codec issue after unpark a call
1613  * \todo copy connected line info
1614  *
1615  */
sccp_astwrap_park(constChannelPtr hostChannel)1616 static sccp_parkresult_t sccp_astwrap_park(constChannelPtr hostChannel)
1617 {
1618 	sccp_parkresult_t res = PARK_RESULT_FAIL;
1619 	RAII (struct ast_channel *, parker_chan, ast_channel_ref (hostChannel->owner), ast_channel_cleanup);
1620 	RAII(struct ast_bridge_channel *, bridge_channel, NULL, ao2_cleanup);
1621 
1622 	if (!ast_parking_provider_registered()) {
1623 		return res;
1624 	}
1625 
1626 	do {
1627 		AUTO_RELEASE (sccp_device_t, device, sccp_channel_getDevice (hostChannel));
1628 		sccp_log (DEBUGCAT_CHANNEL) (VERBOSE_PREFIX_3 "%s: Handling Park\n", hostChannel->designator);
1629 		if (device && (ast_channel_state (parker_chan) == AST_STATE_UP)) {
1630 			ast_channel_lock (parker_chan); /* we have to lock our channel, otherwise asterisk crashes internally */
1631 			bridge_channel = ast_channel_get_bridge_channel (parker_chan);
1632 			ast_channel_unlock (parker_chan);
1633 			if (!bridge_channel) {
1634 				pbx_log (LOG_ERROR, "Park action failed\n");
1635 				break;
1636 			}
1637 			if (!hostChannel->parking_sub) {
1638 				// pbx_log(LOG_NOTICE, "%s: Subscribing to park topic\n", hostChannel->designator);
1639 				channelPtr c = (channelPtr)hostChannel;                                        // casting away const
1640 				c->parking_sub = stasis_subscribe (ast_parking_topic(), parking_event_cb, (void *)c);
1641 #if CS_AST_HAS_STASIS_SUBSCRIPTION_SET_FILTER
1642 				stasis_subscription_accept_message_type (c->parking_sub, ast_parked_call_type());
1643 				stasis_subscription_set_filter (c->parking_sub, STASIS_SUBSCRIPTION_FILTER_SELECTIVE);
1644 #endif
1645 				// pbx_log(LOG_NOTICE, "%s: Added cleaning job\n", hostChannel->designator);
1646 				sccp_channel_addCleanupJob (c, &parking_subscriptionCleanup, (void *)sccp_channel_retain (c));
1647 			}
1648 			if (bridge_channel) {
1649 				RAII (struct ast_channel *, other_chan, NULL, ast_channel_cleanup);
1650 				ast_bridge_channel_lock_bridge (bridge_channel);
1651 				uint8_t peer_count = bridge_channel->bridge->num_channels;
1652 				if (peer_count == 2) {
1653 					struct ast_bridge_channel * other = ast_bridge_channel_peer (bridge_channel);
1654 					other_chan = other->chan;
1655 					ast_channel_ref (other_chan);
1656 				}
1657 				ast_bridge_unlock (bridge_channel->bridge);
1658 				if (!other_chan) {
1659 					pbx_log (LOG_WARNING, "%s: Remote channel is missing, giving up (connected to application?)\n", hostChannel->designator);
1660 					break;
1661 				}
1662 				pbx_builtin_setvar_helper (other_chan, "_PARKED_BY_CHANNEL", ast_channel_name (parker_chan));
1663 				pbx_builtin_setvar_helper (other_chan, "_PARKED_BY_UNIQUEID", ast_channel_uniqueid (parker_chan));
1664 
1665 				sccp_log (DEBUGCAT_CHANNEL) (VERBOSE_PREFIX_3 "%s: Parking %s\n", hostChannel->designator, ast_channel_name (other_chan));
1666 				const char * parkinglot = ast_channel_parkinglot (bridge_channel->chan);
1667 				char app_data[256];
1668 				snprintf (app_data, 256, "%s,%s", parkinglot, "s");
1669 				if (ast_bridge_channel_write_park (bridge_channel, ast_channel_uniqueid (other_chan), ast_channel_uniqueid (bridge_channel->chan), app_data) != 0) {
1670 					pbx_log (LOG_ERROR, "%s: Parking bridge_channel failed\n", hostChannel->designator);
1671 					break;
1672 				}
1673 
1674 				AUTO_RELEASE (sccp_channel_t, remote, get_sccp_channel_from_pbx_channel (other_chan));
1675 				if (remote) {
1676 					sccp_indicate (NULL, remote, SCCP_CHANNELSTATE_CALLPARK);
1677 				}
1678 
1679 				pbx_channel_set_hangupcause (parker_chan, AST_CAUSE_REDIRECTED_TO_NEW_DESTINATION);
1680 				sccp_channel_schedule_hangup (hostChannel, SCCP_HANGUP_TIMEOUT);
1681 
1682 				res = PARK_RESULT_SUCCESS;
1683 			}
1684 		}
1685 	} while (0);
1686 	return res;
1687 }
1688 
sccp_astwrap_getFeatureExtension(constChannelPtr channel,const char * featureName,char extension[SCCP_MAX_EXTENSION])1689 static boolean_t sccp_astwrap_getFeatureExtension(constChannelPtr channel, const char *featureName, char extension[SCCP_MAX_EXTENSION])
1690 {
1691 	int feat_res = ast_get_feature(channel->owner, featureName, extension, SCCP_MAX_EXTENSION);
1692 	return feat_res ? FALSE : TRUE;
1693 }
1694 
sccp_astwrap_getPickupExtension(constChannelPtr channel,char extension[SCCP_MAX_EXTENSION])1695 static boolean_t sccp_astwrap_getPickupExtension(constChannelPtr channel, char extension[SCCP_MAX_EXTENSION])
1696 {
1697 	boolean_t res = FALSE;
1698 	struct ast_features_pickup_config *pickup_cfg = NULL;
1699 
1700 	if (channel->owner) {
1701 		pbx_channel_lock(channel->owner);
1702 		pickup_cfg = ast_get_chan_features_pickup_config(channel->owner);
1703 		if (!pickup_cfg) {
1704 			ast_log(LOG_ERROR, "Unable to retrieve pickup configuration options. Unable to detect call pickup extension\n");
1705 		} else {
1706 			if (!sccp_strlen_zero(pickup_cfg->pickupexten)) {
1707 				sccp_copy_string(extension, pickup_cfg->pickupexten, SCCP_MAX_EXTENSION);
1708 				res = TRUE;
1709 			}
1710 			pbx_channel_unref(pickup_cfg);
1711 		}
1712 		pbx_channel_unlock(channel->owner);
1713 	}
1714 	return res;
1715 }
1716 
sccp_astwrap_get_payloadType(const struct sccp_rtp * rtp,skinny_codec_t codec)1717 static uint8_t sccp_astwrap_get_payloadType(const struct sccp_rtp *rtp, skinny_codec_t codec)
1718 {
1719 	struct ast_format *astCodec = sccp_astwrap_skinny2ast_format(codec);
1720 	if (astCodec != ast_format_none) {
1721 		return ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(rtp->instance), 1, astCodec, 0);
1722 	}
1723 	return 0;
1724 }
1725 
sccp_astwrap_get_sampleRate(skinny_codec_t codec)1726 static int sccp_astwrap_get_sampleRate(skinny_codec_t codec)
1727 {
1728 	struct ast_format *astCodec = sccp_astwrap_skinny2ast_format(codec);
1729 	if (astCodec != ast_format_none) {
1730 		return ast_rtp_lookup_sample_rate2(1, astCodec, 0);
1731 	}
1732 	return 0;
1733 }
1734 
sccp_astwrap_extensionStatus(constChannelPtr channel)1735 static sccp_extension_status_t sccp_astwrap_extensionStatus(constChannelPtr channel)
1736 {
1737 	PBX_CHANNEL_TYPE *pbx_channel = channel->owner;
1738 
1739 	if (!pbx_channel || !pbx_channel_context(pbx_channel)) {
1740 		pbx_log(LOG_ERROR, "%s: (extension_status) Either no pbx_channel or no valid context provided to lookup number\n", channel->designator);
1741 		return SCCP_EXTENSION_NOTEXISTS;
1742 	}
1743 	int ignore_pat = ast_ignore_pattern(pbx_channel_context(pbx_channel), channel->dialedNumber);
1744 	int ext_exist = ast_exists_extension(pbx_channel, pbx_channel_context(pbx_channel), channel->dialedNumber, 1, channel->line->cid_num);
1745 	int ext_canmatch = ast_canmatch_extension(pbx_channel, pbx_channel_context(pbx_channel), channel->dialedNumber, 1, channel->line->cid_num);
1746 	int ext_matchmore = ast_matchmore_extension(pbx_channel, pbx_channel_context(pbx_channel), channel->dialedNumber, 1, channel->line->cid_num);
1747 
1748 	// RAII(struct ast_features_pickup_config *, pickup_cfg, ast_get_chan_features_pickup_config(pbx_channel), ao2_cleanup);
1749 	// const char *pickupexten = (pickup_cfg) ? pickup_cfg->pickupexten : "-";
1750 
1751 	/* if we dialed the pickup extention, mark this as exact match */
1752 	const char *pickupexten = "";
1753 	struct ast_features_pickup_config *pickup_cfg = NULL;
1754 
1755 	if (channel->owner) {
1756 		pbx_channel_lock(channel->owner);
1757 		pickup_cfg = ast_get_chan_features_pickup_config(channel->owner);
1758 		if (!pickup_cfg) {
1759 			ast_log(LOG_ERROR, "Unable to retrieve pickup configuration options. Unable to detect call pickup extension\n");
1760 			pickupexten = "";
1761 		} else {
1762 			pickupexten = pbx_strdupa(pickup_cfg->pickupexten);
1763 			pbx_channel_unref(pickup_cfg);
1764 		}
1765 		pbx_channel_unlock(channel->owner);
1766 	}
1767 	if (!sccp_strlen_zero(pickupexten) && sccp_strcaseequals(pickupexten, channel->dialedNumber)) {
1768 		sccp_log(DEBUGCAT_CORE) (VERBOSE_PREFIX_3 "SCCP: pbx extension matcher found pickup extension %s matches dialed number %s\n", channel->dialedNumber, pickupexten);
1769 		ext_exist = 1;
1770 		ext_canmatch = 1;
1771 		ext_matchmore = 0;
1772 	}
1773 
1774 	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");
1775 
1776 	if (ignore_pat) {
1777 		return SCCP_EXTENSION_NOTEXISTS;
1778 	}
1779 	if (ext_exist) {
1780 		if (ext_canmatch && !ext_matchmore) {
1781 			return SCCP_EXTENSION_EXACTMATCH;
1782 		}
1783 		return SCCP_EXTENSION_MATCHMORE;
1784 	}
1785 
1786 	return SCCP_EXTENSION_NOTEXISTS;
1787 }
1788 
sccp_astwrap_request(const char * type,struct ast_format_cap * cap,const struct ast_assigned_ids * assignedids,const struct ast_channel * requestor,const char * dest,int * cause)1789 static PBX_CHANNEL_TYPE *sccp_astwrap_request(const char *type, struct ast_format_cap *cap, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor, const char *dest, int *cause)
1790 {
1791 	sccp_channel_request_status_t requestStatus;
1792 	PBX_CHANNEL_TYPE *result_ast_channel = NULL;
1793 	pbx_str_t *codec_buf = pbx_str_alloca(64);
1794 	ast_callid callid = 0;
1795 
1796 	skinny_codec_t audioCapabilities[SKINNY_MAX_CAPABILITIES] = {SKINNY_CODEC_NONE};
1797 	skinny_codec_t videoCapabilities[SKINNY_MAX_CAPABILITIES] = {SKINNY_CODEC_NONE};
1798 
1799 	//! \todo parse request
1800 	char *lineName;
1801 	skinny_codec_t audio_codec = SKINNY_CODEC_WIDEBAND_256K;
1802 #if CS_SCCP_VIDEO
1803 	skinny_codec_t video_codec = SKINNY_CODEC_NONE;
1804 #endif
1805 	sccp_autoanswer_t autoanswer_type = SCCP_AUTOANSWER_NONE;
1806 	uint8_t autoanswer_cause = AST_CAUSE_NOTDEFINED;
1807 	skinny_ringtype_t ringermode = GLOB(ringtype);
1808 
1809 	if (!(ast_format_cap_has_type(cap, AST_MEDIA_TYPE_AUDIO))) {
1810 		ast_log(LOG_NOTICE, "Asked to get a channel with an unsupported format '%s'\n", ast_format_cap_get_names(cap, &codec_buf));
1811 	}
1812 
1813 	*cause = AST_CAUSE_NOTDEFINED;
1814 	if (!type) {
1815 		pbx_log(LOG_NOTICE, "Attempt to call with unspecified type of channel\n");
1816 		*cause = AST_CAUSE_REQUESTED_CHAN_UNAVAIL;
1817 		return NULL;
1818 	}
1819 
1820 	if (!dest) {
1821 		pbx_log(LOG_NOTICE, "Attempt to call SCCP/ failed\n");
1822 		*cause = AST_CAUSE_REQUESTED_CHAN_UNAVAIL;
1823 		return NULL;
1824 	}
1825 	/* we leave the data unchanged */
1826 	lineName = pbx_strdupa((const char *) dest);
1827 
1828 	/* parsing options string */
1829 	char *options = NULL;
1830 	if ((options = strchr(lineName, '/'))) {
1831 		*options = '\0';
1832 		options++;
1833 	}
1834 	// 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, (uint64_t) ast_format_compatibility_codec2bitfield(cap), lineName, (options) ? options : "");
1835 	sccp_log(DEBUGCAT_CHANNEL) (VERBOSE_PREFIX_3 "SCCP: Asterisk asked us to create a channel with type=%s, format=%s, lineName=%s, options=%s\n", type, ast_format_cap_get_names(cap, &codec_buf), lineName, (options) ? options : "");
1836 	if (requestor) {							/* get ringer mode from ALERT_INFO */
1837 		sccp_parse_alertinfo((PBX_CHANNEL_TYPE *)requestor, &ringermode);
1838 	}
1839 	sccp_parse_dial_options(options, &autoanswer_type, &autoanswer_cause, &ringermode);
1840 	if (autoanswer_cause) {
1841 		*cause = autoanswer_cause;
1842 	}
1843 	sccp_parse_auto_answer((PBX_CHANNEL_TYPE *)requestor, &autoanswer_type);
1844 
1845 	/** getting remote capabilities */
1846 	if (requestor) {
1847 		struct ast_format_cap *acaps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
1848 		if (acaps) {
1849 			ast_format_cap_append_from_cap(acaps, cap, AST_MEDIA_TYPE_AUDIO);								// Add Resquested
1850 			if (ast_format_cap_count(acaps)) {
1851 				audio_codec = sccp_astwrap_getSkinnyFormatSingle(acaps);									// Is it compatible
1852 				ast_format_cap_append_from_cap(acaps, ast_channel_nativeformats(requestor), AST_MEDIA_TYPE_AUDIO);				// Add rest
1853 				sccp_astwrap_getSkinnyFormatMultiple(acaps, audioCapabilities, ARRAY_LEN(audioCapabilities));
1854 				if (audio_codec == SKINNY_CODEC_NONE && (audio_codec = audioCapabilities[0]) == SKINNY_CODEC_NONE) {
1855 					pbx_log(LOG_NOTICE, "SCCP: remote native audio formats are not compatible with any skinny format. Transcoding required\n");
1856 					audioCapabilities[0] = SKINNY_CODEC_WIDEBAND_256K;
1857 					audio_codec  =SKINNY_CODEC_WIDEBAND_256K;
1858 				}
1859 			}
1860 			ao2_cleanup(acaps);
1861 		}
1862 #if CS_SCCP_VIDEO
1863 		struct ast_format_cap *vcaps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
1864 		if (vcaps) {
1865 			ast_format_cap_append_from_cap(vcaps, cap, AST_MEDIA_TYPE_VIDEO);								// Add Resquested
1866 			if (ast_format_cap_count(vcaps)) {
1867 				video_codec = sccp_astwrap_getSkinnyFormatSingle(vcaps);								// Is it compatible
1868 				ast_format_cap_append_from_cap(vcaps, ast_channel_nativeformats(requestor), AST_MEDIA_TYPE_VIDEO);			// Add rest
1869 				sccp_astwrap_getSkinnyFormatMultiple(vcaps, videoCapabilities, ARRAY_LEN(videoCapabilities));
1870 				if (video_codec == SKINNY_CODEC_NONE && (video_codec = videoCapabilities[0]) == SKINNY_CODEC_NONE) {
1871 					pbx_log(LOG_NOTICE, "SCCP: remote native video formats are not compatible with any skinny format. Deny video\n");
1872 					videoCapabilities[0] = SKINNY_CODEC_NONE;
1873 					video_codec = SKINNY_CODEC_NONE;
1874 				}
1875 			}
1876 			ao2_cleanup(vcaps);
1877 		}
1878 #endif
1879 	}
1880 
1881 	char cap_buf[512];
1882 	sccp_codec_multiple2str(cap_buf, sizeof(cap_buf) - 1, audioCapabilities, ARRAY_LEN(audioCapabilities));
1883 	sccp_log(DEBUGCAT_CODEC) (VERBOSE_PREFIX_4 "remote audio caps: %s\n", cap_buf);
1884 
1885 	sccp_codec_multiple2str(cap_buf, sizeof(cap_buf) - 1, videoCapabilities, ARRAY_LEN(videoCapabilities));
1886 	sccp_log(DEBUGCAT_CODEC) (VERBOSE_PREFIX_4 "remote video caps: %s\n", cap_buf);
1887 
1888 	//sccp_log(DEBUGCAT_CODEC) (VERBOSE_PREFIX_4 "SCCP: requestedCodec in Skinny Format: audio:%s (video:%s)\n", codec2name(audio_codec), codec2name(video_codec));
1889 	/** done getting remote capabilities */
1890 
1891 	callid = ast_read_threadstorage_callid();
1892 
1893 	AUTO_RELEASE(sccp_channel_t, channel , NULL);
1894 	requestStatus = sccp_requestChannel(lineName, autoanswer_type, autoanswer_cause, ringermode, &channel);
1895 	switch (requestStatus) {
1896 		case SCCP_REQUEST_STATUS_SUCCESS:								// everything is fine
1897 			break;
1898 		case SCCP_REQUEST_STATUS_LINEUNKNOWN:
1899 			sccp_log(DEBUGCAT_CORE) (VERBOSE_PREFIX_4 "SCCP: sccp_requestChannel returned Line %s Unknown -> Not Successfull\n", lineName);
1900 			*cause = AST_CAUSE_DESTINATION_OUT_OF_ORDER;
1901 			goto EXITFUNC;
1902 		case SCCP_REQUEST_STATUS_LINEUNAVAIL:
1903 			sccp_log(DEBUGCAT_CORE) (VERBOSE_PREFIX_4 "SCCP: sccp_requestChannel returned Line %s not currently registered -> Try again later\n", lineName);
1904 			*cause = AST_CAUSE_REQUESTED_CHAN_UNAVAIL;
1905 			goto EXITFUNC;
1906 		case SCCP_REQUEST_STATUS_ERROR:
1907 			pbx_log(LOG_ERROR, "SCCP: sccp_requestChannel returned Status Error for lineName: %s\n", lineName);
1908 			*cause = AST_CAUSE_UNALLOCATED;
1909 			goto EXITFUNC;
1910 		default:
1911 			pbx_log(LOG_ERROR, "SCCP: sccp_requestChannel returned Status Error for lineName: %s\n", lineName);
1912 			*cause = AST_CAUSE_UNALLOCATED;
1913 			goto EXITFUNC;
1914 	}
1915 #ifdef CS_SCCP_VIDEO
1916 	memset(&channel->remoteCapabilities.video, 0, sizeof(channel->remoteCapabilities.video));
1917 	if (videoCapabilities[0] != SKINNY_CODEC_NONE) {
1918 		memcpy(channel->remoteCapabilities.video, videoCapabilities, ARRAY_LEN(videoCapabilities));
1919 	} else if (video_codec) {
1920 		channel->remoteCapabilities.video[0] = video_codec;
1921 	}
1922 #endif
1923 	if (callid) {
1924 		channel->pbx_callid = (pbx_callid_t)callid;
1925 	}
1926 
1927 	if (!sccp_pbx_channel_allocate(channel, assignedids, requestor)) {
1928 		//! \todo handle error in more detail, cleanup sccp channel
1929 		*cause = AST_CAUSE_REQUESTED_CHAN_UNAVAIL;
1930 		goto EXITFUNC;
1931 	}
1932 
1933 	/* set initial connected line information, to be exchange with remove party during first CONNECTED_LINE update */
1934 	ast_set_callerid(channel->owner, channel->line->cid_num, channel->line->cid_name, channel->line->cid_num);
1935 	struct ast_party_connected_line connected;
1936 	ast_party_connected_line_set_init(&connected, ast_channel_connected(channel->owner));
1937 	connected.id.number.valid = 1;
1938 	connected.id.number.str = (char *)channel->line->cid_num;
1939 	connected.id.number.presentation = AST_PRES_ALLOWED_NETWORK_NUMBER;
1940 	connected.id.name.valid = 1;
1941 	connected.id.name.str = (char *)channel->line->cid_name;
1942 	connected.id.name.presentation = AST_PRES_ALLOWED_NETWORK_NUMBER;
1943 	connected.source = AST_CONNECTED_LINE_UPDATE_SOURCE_UNKNOWN;
1944 	ast_channel_set_connected_line(channel->owner, &connected, NULL);
1945 	/* end */
1946 
1947 	if (requestor) {
1948 		/* set calling party */
1949 		sccp_callinfo_t *ci = sccp_channel_getCallInfo(channel);
1950 		iCallInfo.Setter(ci,
1951 				SCCP_CALLINFO_CALLINGPARTY_NAME, ast_channel_caller((PBX_CHANNEL_TYPE *) requestor)->id.name.str,
1952 				SCCP_CALLINFO_CALLINGPARTY_NUMBER, ast_channel_caller((PBX_CHANNEL_TYPE *) requestor)->id.number.str,
1953 				SCCP_CALLINFO_ORIG_CALLEDPARTY_NAME, ast_channel_redirecting((PBX_CHANNEL_TYPE *) requestor)->orig.name.str,
1954 				SCCP_CALLINFO_ORIG_CALLEDPARTY_NUMBER, ast_channel_redirecting((PBX_CHANNEL_TYPE *) requestor)->orig.number.str,
1955 				SCCP_CALLINFO_KEY_SENTINEL);
1956 	}
1957 
1958 	/** workaround for asterisk console log flooded
1959 	 channel.c:5080 ast_write: Codec mismatch on channel SCCP/xxx-0000002d setting write format to g722 from unknown native formats (nothing)
1960 	*/
1961 	if (!channel->capabilities.audio[0]) {
1962 		skinny_codec_t codecs[SKINNY_MAX_CAPABILITIES] = { SKINNY_CODEC_WIDEBAND_256K, SKINNY_CODEC_NONE};
1963 		sccp_astwrap_setNativeAudioFormats(channel, codecs);
1964 		sccp_astwrap_setReadFormat(channel, SKINNY_CODEC_WIDEBAND_256K);
1965 		sccp_astwrap_setWriteFormat(channel, SKINNY_CODEC_WIDEBAND_256K);
1966 	}
1967 
1968 	/* get remote codecs from channel driver */
1969 	//ast_rtp_instance_get_codecs(c->rtp.adio.rtp);
1970 	//ast_rtp_instance_get_codecs(c->rtp.video.instance);
1971 	/** done */
1972 
1973 EXITFUNC:
1974 	if (channel  && channel->owner) {
1975 		result_ast_channel = channel->owner;
1976 		if (callid) {
1977 			ast_channel_callid_set(result_ast_channel, callid);
1978 		}
1979 	}
1980 	return result_ast_channel;
1981 }
1982 
sccp_astwrap_call(PBX_CHANNEL_TYPE * ast,const char * dest,int timeout)1983 static int sccp_astwrap_call(PBX_CHANNEL_TYPE * ast, const char *dest, int timeout)
1984 {
1985 	int res = 0;
1986 
1987 	sccp_log((DEBUGCAT_CORE)) (VERBOSE_PREFIX_3 "SCCP: Asterisk request to call %s (dest:%s, timeout: %d)\n", pbx_channel_name(ast), dest, timeout);
1988 
1989 	if (!sccp_strlen_zero(pbx_channel_call_forward(ast))) {
1990 		iPbx.queue_control(ast, (enum ast_control_frame_type) -1);						/* Prod Channel if in the middle of a call_forward instead of proceed */
1991 		sccp_log((DEBUGCAT_CORE)) (VERBOSE_PREFIX_3 "SCCP: Forwarding Call to '%s'\n", pbx_channel_call_forward(ast));
1992 		return 0;
1993 	}
1994 
1995 	AUTO_RELEASE(sccp_channel_t, c , get_sccp_channel_from_pbx_channel(ast));
1996 	if (!c) {
1997 		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));
1998 		return -1;
1999 	}
2000 
2001 	/* Check whether there is MaxCallBR variables */
2002 	const char *MaxCallBRStr = pbx_builtin_getvar_helper(ast, "MaxCallBR");
2003 	if (MaxCallBRStr && !sccp_strlen_zero(MaxCallBRStr)) {
2004 		sccp_astgenwrap_channel_write(ast, "CHANNEL", "MaxCallBR", MaxCallBRStr);
2005 	}
2006 
2007 	res = sccp_pbx_call(c, (char *) dest, timeout);
2008 	return res;
2009 }
2010 
2011 /*
2012  * Remote side has answered the call switch to up state
2013  * Is being called with pbxchan locked by app_dial
2014  */
sccp_astwrap_answer(PBX_CHANNEL_TYPE * pbxchan)2015 static int sccp_astwrap_answer(PBX_CHANNEL_TYPE * pbxchan)
2016 {
2017 	int res = -1;
2018 	int timedout = 0;
2019 	if(pbx_channel_state(pbxchan) == AST_STATE_UP) {
2020 		pbx_log(LOG_NOTICE, "%s: Channel has already been answered remotely, skipping\n", pbx_channel_name(pbxchan));
2021 		return 0;
2022 	}
2023 
2024 	pbx_channel_ref(pbxchan);
2025 	AUTO_RELEASE(sccp_channel_t, c , get_sccp_channel_from_pbx_channel(pbxchan));
2026 	if(c && c->state < SCCP_GROUPED_CHANNELSTATE_CONNECTION) {
2027 		sccp_log(DEBUGCAT_CORE)(VERBOSE_PREFIX_3 "%s: Remote has answered the call.\n", c->designator);
2028 
2029 		AUTO_RELEASE(sccp_device_t, d, sccp_channel_getDevice(c));
2030 		if(d && d->session) {
2031 			sccp_log(DEBUGCAT_PBX)(VERBOSE_PREFIX_3 "%s: Waiting for pendingRequests\n", c->designator);
2032 			// this needs to be done with the pbx_channel unlocked to prevent lock investion
2033 			// note we still have a pbx_channel_ref, so the channel cannot be removed under our feet
2034 			pbx_channel_unlock(pbxchan);
2035 			timedout = sccp_session_waitForPendingRequests(d->session);
2036 			pbx_channel_lock(pbxchan);
2037 		}
2038 		if (!timedout) {
2039 			// pbx_indicate(pbxchan, AST_CONTROL_PROGRESS);
2040 			res = sccp_pbx_remote_answer(c);
2041 		}
2042 	}
2043 	pbx_channel_unref(pbxchan);
2044 	return res;
2045 }
2046 
2047 /**
2048  *
2049  * \todo update remote capabilities after fixup
2050  */
sccp_astwrap_fixup(PBX_CHANNEL_TYPE * oldchan,PBX_CHANNEL_TYPE * newchan)2051 static int sccp_astwrap_fixup(PBX_CHANNEL_TYPE * oldchan, PBX_CHANNEL_TYPE * newchan)
2052 {
2053 	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));
2054 	int res = 0;
2055 
2056 	AUTO_RELEASE(sccp_channel_t, c , get_sccp_channel_from_pbx_channel(newchan));
2057 	if (c) {
2058 		if (c->owner != oldchan) {
2059 			ast_log(LOG_WARNING, "old channel wasn't %p but was %p\n", oldchan, c->owner);
2060 			res = -1;
2061 		} else {
2062 			/* during a masquerade, fixup gets called twice */
2063 			if(ast_channel_masqr(newchan)) { /* this is the channel that is masquaraded out */
2064 				// set to simple channel requestHangup, we are out of pbx_run_pbx, upon returning from masquerade */
2065 				// sccp_log((DEBUGCAT_CORE)) (VERBOSE_PREFIX_3 "%s: set c->hangupRequest = requestHangup\n", c->designator);
2066 				c->hangupRequest = sccp_astgenwrap_requestHangup;
2067 
2068 				if (pbx_channel_hangupcause(newchan) == AST_CAUSE_ANSWERED_ELSEWHERE) {
2069 					sccp_log((DEBUGCAT_CORE)) (VERBOSE_PREFIX_3 "%s: Fixup Adding Redirecting Party from:%s\n", c->designator, pbx_channel_name(oldchan));
2070 					iCallInfo.Setter(sccp_channel_getCallInfo(c),
2071 						SCCP_CALLINFO_HUNT_PILOT_NAME, ast_channel_caller(oldchan)->id.name.str,
2072 						SCCP_CALLINFO_HUNT_PILOT_NUMBER, ast_channel_caller(oldchan)->id.number.str,
2073 						SCCP_CALLINFO_LAST_REDIRECTINGPARTY_NAME, ast_channel_caller(oldchan)->id.name.str,
2074 						SCCP_CALLINFO_LAST_REDIRECTINGPARTY_NUMBER, ast_channel_caller(oldchan)->id.number.str,
2075 						SCCP_CALLINFO_LAST_REDIRECT_REASON, 5,
2076 						SCCP_CALLINFO_KEY_SENTINEL);
2077 				}
2078 			} else {
2079 				// set channel requestHangup to use ast_hangup (as it will not be part of __ast_pbx_run, upon returning from masquerade) */
2080 				// sccp_log((DEBUGCAT_CORE)) (VERBOSE_PREFIX_3 "%s: set c->hangupRequest = requestQueueHangup\n", c->designator);
2081 				c->hangupRequest = sccp_astgenwrap_requestQueueHangup;
2082 
2083 				if (!sccp_strlen_zero(c->line->language)) {
2084 					ast_channel_language_set(newchan, c->line->language);
2085 				}
2086 
2087 				//! \todo update remote capabilities after fixup
2088 				pbx_retrieve_remote_capabilities(c);
2089 
2090 				/* Re-invite RTP back to Asterisk. Needed if channel is masqueraded out of a native
2091 				   RTP bridge (i.e., RTP not going through Asterisk): RTP bridge code might not be
2092 				   able to do this if the masquerade happens before the bridge breaks (e.g., AMI
2093 				   redirect of both channels). Note that a channel can not be masqueraded *into*
2094 				   a native bridge. So there is no danger that this breaks a native bridge that
2095 				   should stay up. */
2096 				// sccp_astwrap_update_rtp_peer(newchan, NULL, NULL, 0, 0, 0);
2097 			}
2098 			sccp_astwrap_setOwner(c, newchan);
2099 		}
2100 	} else {
2101 		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);
2102 		res = -1;
2103 	}
2104 	return res;
2105 }
2106 
2107 #if 0
2108 #ifdef CS_AST_RTP_INSTANCE_BRIDGE
2109 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)
2110 {
2111 	enum ast_bridge_result res;
2112 	int new_flags = flags;
2113 
2114 	/* \note temporarily marked out until we figure out how to get directrtp back on track - DdG */
2115 	AUTO_RELEASE(sccp_channel_t, sc0 , get_sccp_channel_from_pbx_channel(c0));
2116 	AUTO_RELEASE(sccp_channel_t, sc1 , get_sccp_channel_from_pbx_channel(c1));
2117 
2118 	if ((sc0 && sc1)) {
2119 		// Switch off DTMF between SCCP phones
2120 		new_flags &= !AST_BRIDGE_DTMF_CHANNEL_0;
2121 		new_flags &= !AST_BRIDGE_DTMF_CHANNEL_1;
2122 		if (GLOB(directrtp)) {
2123 			ast_channel_defer_dtmf(c0);
2124 			ast_channel_defer_dtmf(c1);
2125 		} else {
2126 			AUTO_RELEASE(sccp_device_t, d0 , sccp_channel_getDevice(sc0));
2127 			AUTO_RELEASE(sccp_device_t, d1 , sccp_channel_getDevice(sc1));
2128 			if ((d0 && d1) && ((d0->directrtp && d1->directrtp)) {
2129 				ast_channel_defer_dtmf(c0);
2130 				ast_channel_defer_dtmf(c1);
2131 			}
2132 		}
2133 		sc0->peerIsSCCP = TRUE;
2134 		sc1->peerIsSCCP = TRUE;
2135 		// SCCP Key handle direction to asterisk is still to be implemented here
2136 		// sccp_pbx_senddigit
2137 	} else {
2138 		// Switch on DTMF between differing channels
2139 		ast_channel_undefer_dtmf(c0);
2140 		ast_channel_undefer_dtmf(c1);
2141 	}
2142 	//res = ast_rtp_bridge(c0, c1, new_flags, fo, rc, timeoutms);
2143 	res = ast_rtp_instance_bridge(c0, c1, new_flags, fo, rc, timeoutms);
2144 	switch (res) {
2145 		case AST_BRIDGE_COMPLETE:
2146 			sccp_log((DEBUGCAT_PBX)) (VERBOSE_PREFIX_1 "SCCP: Bridge chan %s and chan %s: Complete\n", ast_channel_name(c0), ast_channel_name(c1));
2147 			break;
2148 		case AST_BRIDGE_FAILED:
2149 			sccp_log((DEBUGCAT_PBX)) (VERBOSE_PREFIX_1 "SCCP: Bridge chan %s and chan %s: Failed\n", ast_channel_name(c0), ast_channel_name(c1));
2150 			break;
2151 		case AST_BRIDGE_FAILED_NOWARN:
2152 			sccp_log((DEBUGCAT_PBX)) (VERBOSE_PREFIX_1 "SCCP: Bridge chan %s and chan %s: Failed NoWarn\n", ast_channel_name(c0), ast_channel_name(c1));
2153 			break;
2154 		case AST_BRIDGE_RETRY:
2155 			sccp_log((DEBUGCAT_PBX)) (VERBOSE_PREFIX_1 "SCCP: Bridge chan %s and chan %s: Failed Retry\n", ast_channel_name(c0), ast_channel_name(c1));
2156 			break;
2157 	}
2158 	/*! \todo Implement callback function queue upon completion */
2159 	return res;
2160 }
2161 #endif
2162 #endif
2163 
sccp_astwrap_get_rtp_info(PBX_CHANNEL_TYPE * ast,PBX_RTP_TYPE ** rtp)2164 static enum ast_rtp_glue_result sccp_astwrap_get_rtp_info(PBX_CHANNEL_TYPE * ast, PBX_RTP_TYPE ** rtp)
2165 {
2166 	//AUTO_RELEASE(sccp_channel_t, c , get_sccp_channel_from_pbx_channel(ast));				// not following the refcount rules... channel is already retained
2167 	sccp_channel_t *c = NULL;
2168 	sccp_rtp_info_t rtpInfo = SCCP_RTP_INFO_NORTP;
2169 	struct sccp_rtp *audioRTP = NULL;
2170 	enum ast_rtp_glue_result res = AST_RTP_GLUE_RESULT_REMOTE;
2171 
2172 	if (!(c = CS_AST_CHANNEL_PVT(ast))) {
2173 		sccp_log((DEBUGCAT_RTP)) (VERBOSE_PREFIX_1 "SCCP: (get_rtp_info) NO PVT\n");
2174 		return AST_RTP_GLUE_RESULT_FORBID;
2175 	}
2176 
2177 	if (pbx_channel_state(ast) != AST_STATE_UP) {
2178 		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));
2179 		return AST_RTP_GLUE_RESULT_LOCAL;
2180 	} else {
2181 		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));
2182 	}
2183 
2184 	rtpInfo = sccp_rtp_getAudioPeerInfo(c, &audioRTP);
2185 	if (rtpInfo == SCCP_RTP_INFO_NORTP) {
2186 		return AST_RTP_GLUE_RESULT_FORBID;
2187 	}
2188 
2189 	*rtp = audioRTP->instance;
2190 	if (!*rtp) {
2191 		sccp_log(DEBUGCAT_RTP)(VERBOSE_PREFIX_2 "%s: (get_rtp_info) no rtp instance yet => returning AST_RTP_GLUE_RESULT_FORBID\n", c->designator);
2192 		return AST_RTP_GLUE_RESULT_FORBID;
2193 	}
2194 #ifdef HAVE_PBX_RTP_ENGINE_H
2195 	ao2_ref(*rtp, +1);
2196 #endif
2197 	// struct ast_sockaddr ast_sockaddr_tmp;
2198 	// ast_rtp_instance_get_remote_address(*rtp, &ast_sockaddr_tmp);
2199 	// 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));
2200 
2201 	if (ast_test_flag(GLOB(global_jbconf), AST_JB_FORCED)) {
2202 		sccp_log((DEBUGCAT_RTP)) (VERBOSE_PREFIX_1 "%s: (get_rtp_info) JitterBuffer is Forced. AST_RTP_GET_FAILED\n", c->currentDeviceId);
2203 		return AST_RTP_GLUE_RESULT_LOCAL;
2204 	}
2205 
2206 	if (!(rtpInfo & SCCP_RTP_INFO_ALLOW_DIRECTRTP)) {
2207 		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));
2208 		return AST_RTP_GLUE_RESULT_LOCAL;
2209 	}
2210 
2211 	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")));
2212 	return res;
2213 }
2214 
sccp_astwrap_get_vrtp_info(PBX_CHANNEL_TYPE * ast,PBX_RTP_TYPE ** rtp)2215 static enum ast_rtp_glue_result sccp_astwrap_get_vrtp_info(PBX_CHANNEL_TYPE * ast, PBX_RTP_TYPE ** rtp)
2216 {
2217 	//AUTO_RELEASE(sccp_channel_t, c , get_sccp_channel_from_pbx_channel(ast));				// not following the refcount rules... channel is already retained
2218 	sccp_channel_t *c = NULL;
2219 	sccp_rtp_info_t rtpInfo = SCCP_RTP_INFO_NORTP;
2220 	struct sccp_rtp *videoRTP = NULL;
2221 	enum ast_rtp_glue_result res = AST_RTP_GLUE_RESULT_REMOTE;
2222 
2223 	if (!(c = CS_AST_CHANNEL_PVT(ast))) {
2224 		sccp_log((DEBUGCAT_RTP)) (VERBOSE_PREFIX_1 "SCCP: (get_vrtp_info) NO PVT\n");
2225 		return AST_RTP_GLUE_RESULT_FORBID;
2226 	}
2227 
2228 	if (pbx_channel_state(ast) != AST_STATE_UP) {
2229 		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));
2230 	} else {
2231 		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));
2232 	}
2233 
2234 #ifdef CS_SCCP_VIDEO
2235 	rtpInfo = sccp_rtp_getVideoPeerInfo(c, &videoRTP);
2236 #endif
2237 	if (rtpInfo == SCCP_RTP_INFO_NORTP) {
2238 		return AST_RTP_GLUE_RESULT_FORBID;
2239 	}
2240 
2241 	*rtp = videoRTP->instance;
2242 	if (!*rtp) {
2243 		return AST_RTP_GLUE_RESULT_FORBID;
2244 	}
2245 #ifdef HAVE_PBX_RTP_ENGINE_H
2246 	ao2_ref(*rtp, +1);
2247 #endif
2248 	// struct ast_sockaddr ast_sockaddr_tmp;
2249 	// ast_rtp_instance_get_remote_address(*rtp, &ast_sockaddr_tmp);
2250 	// 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));
2251 	if (ast_test_flag(GLOB(global_jbconf), AST_JB_FORCED)) {
2252 		sccp_log((DEBUGCAT_RTP)) (VERBOSE_PREFIX_1 "%s: (get_vrtp_info) JitterBuffer is Forced. AST_RTP_GET_FAILED\n", c->currentDeviceId);
2253 		return AST_RTP_GLUE_RESULT_FORBID;
2254 	}
2255 
2256 	if (!(rtpInfo & SCCP_RTP_INFO_ALLOW_DIRECTRTP)) {
2257 		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));
2258 		return AST_RTP_GLUE_RESULT_LOCAL;
2259 	}
2260 
2261 	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")));
2262 	return res;
2263 }
2264 
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)2265 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)
2266 {
2267 	//AUTO_RELEASE(sccp_channel_t, c , get_sccp_channel_from_pbx_channel(ast));				// not following the refcount rules... channel is already retained
2268 	sccp_channel_t *c = NULL;
2269 	int result = 0;
2270 	do {
2271 		pbx_str_t *codec_buf = pbx_str_alloca(64);
2272 
2273 		if (!(c = CS_AST_CHANNEL_PVT(ast))) {
2274 			sccp_log((DEBUGCAT_RTP)) (VERBOSE_PREFIX_1 "SCCP: (update_rtp_peer) NO PVT\n");
2275 			result = -1;
2276 			break;
2277 		}
2278 
2279 		if (!codecs || ast_format_cap_count(codecs) <= 0) {
2280 			sccp_log((DEBUGCAT_RTP)) (VERBOSE_PREFIX_1 "%s: (update_rtp_peer) NO Codecs\n", c->currentDeviceId);
2281 			result = -1;
2282 			break;
2283 		}
2284 		sccp_log((DEBUGCAT_RTP)) (VERBOSE_PREFIX_2 "%s: (update_rtp_peer) stage: %s, remote codecs capabilty: %s, nat_active: %d\n", c->currentDeviceId,
2285 			S_COR(AST_STATE_UP == pbx_channel_state(ast), "RTP", "EarlyRTP"), ast_format_cap_get_names((struct ast_format_cap *) codecs, &codec_buf), nat_active);
2286 
2287 		if (!c->line) {
2288 			sccp_log((DEBUGCAT_RTP)) (VERBOSE_PREFIX_1 "%s: (update_rtp_peer) NO LINE\n", c->currentDeviceId);
2289 			result = -1;
2290 			break;
2291 		}
2292 		if (c->state == SCCP_CHANNELSTATE_HOLD) {
2293 			sccp_log((DEBUGCAT_RTP)) (VERBOSE_PREFIX_1 "%s: (update_rtp_peer) On Hold -> No Update\n", c->currentDeviceId);
2294 			result = 0;
2295 			break;
2296 		}
2297 		AUTO_RELEASE(sccp_device_t, d , sccp_channel_getDevice(c));
2298 		if (!d) {
2299 			sccp_log((DEBUGCAT_RTP)) (VERBOSE_PREFIX_1 "%s: (update_rtp_peer) NO DEVICE\n", c->currentDeviceId);
2300 			result = -1;
2301 			break;
2302 		}
2303 
2304 		if (!rtp && !vrtp && !trtp) {
2305 			sccp_log((DEBUGCAT_RTP)) (VERBOSE_PREFIX_1 "%s: (update_rtp_peer) RTP not ready\n", c->currentDeviceId);
2306 			result = 0;
2307 			break;
2308 		}
2309 
2310 		PBX_RTP_TYPE *instance = { 0, };
2311 		struct sockaddr_storage sas = { 0, };
2312 		//struct sockaddr_in sin = { 0, };
2313 		struct ast_sockaddr sin_tmp;
2314 		boolean_t directmedia = FALSE;
2315 
2316 		if (rtp) {											// generalize input
2317 			instance = rtp;
2318 		} else if (vrtp) {
2319 			instance = vrtp;
2320 #ifdef CS_SCCP_VIDEO
2321 			/* video requested by remote side, let's see if we support video */
2322  			/* should be moved to sccp_rtp.c */
2323 /*
2324 			if (ast_format_cap_has_type(codecs, AST_MEDIA_TYPE_VIDEO) && sccp_device_isVideoSupported(d) && sccp_channel_getVideoMode(c) == SCCP_VIDEO_MODE_AUTO) {
2325 				if (!c->rtp.video.instance && !sccp_rtp_createVideoServer(c)) {
2326 					sccp_log((DEBUGCAT_RTP)) (VERBOSE_PREFIX_3 "%s: can not start vrtp\n", DEV_ID_LOG(d));
2327 				} else {
2328 					if (!c->rtp.video.transmission.state) {
2329 						sccp_log((DEBUGCAT_RTP)) (VERBOSE_PREFIX_3 "%s: video rtp started\n", DEV_ID_LOG(d));
2330 						sccp_channel_startMultiMediaTransmission(c);
2331 					}
2332 				}
2333 			}
2334 */
2335 #endif
2336 		} else {
2337 			instance = trtp;
2338 		}
2339 
2340 		if (d->directrtp && d->nat < SCCP_NAT_ON && !nat_active && !c->conference) {			// assume directrtp
2341 			ast_rtp_instance_get_remote_address(instance, &sin_tmp);
2342 			memcpy(&sas, &sin_tmp, sizeof(struct sockaddr_storage));
2343 			//ast_sockaddr_to_sin(&sin_tmp, &sin);
2344 			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
2345 				struct ast_sockaddr sin_local;
2346 				struct sockaddr_storage localsas = { 0, };
2347 				ast_rtp_instance_get_local_address(instance, &sin_local);
2348 				memcpy(&localsas, &sin_local, sizeof(struct sockaddr_storage));
2349 				if (sccp_apply_ha(d->ha, &sas) == AST_SENSE_ALLOW && sccp_apply_ha(d->ha, &localsas) == AST_SENSE_ALLOW) {
2350 					directmedia = TRUE;
2351 				}
2352 			} else if (sccp_apply_ha(d->ha, &sas) == AST_SENSE_ALLOW) {					// check remote sin against local device acl (to match netmask)
2353 				directmedia = TRUE;
2354 				// ast_channel_defer_dtmf(ast);
2355 			}
2356 		}
2357 		if (!directmedia) {										// fallback to indirectrtp
2358 			ast_rtp_instance_get_local_address(instance, &sin_tmp);
2359 			memcpy(&sas, &sin_tmp, sizeof(struct sockaddr_storage));
2360 			sccp_session_getOurIP(d->session, &sas, sccp_netsock_is_IPv4(&sas) ? AF_INET : AF_INET6);
2361 		}
2362 
2363 		sccp_log((DEBUGCAT_RTP)) (VERBOSE_PREFIX_1 "%s: (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", c->currentDeviceId, sccp_netsock_stringify(&sas), S_COR(d->directrtp, "yes", "no"),
2364 					  sccp_nat2str(d->nat),
2365 					  S_COR(!nat_active, "yes", "no"), S_COR(directmedia, "yes", "no"), S_COR(directmedia, "yes", "no")
2366 		    );
2367 
2368 		if (rtp) {											// send peer info to phone
2369 			sccp_rtp_set_peer(c, &c->rtp.audio, &sas);
2370 			c->rtp.audio.directMedia = directmedia;
2371 		} else if (vrtp) {
2372 			sccp_rtp_set_peer(c, &c->rtp.video, &sas);
2373 			c->rtp.video.directMedia = directmedia;
2374 		} else {
2375 			//sccp_rtp_set_peer(c, &c->rtp.text, &sas);
2376 			//c->rtp.text.directMedia = directmedia;
2377 		}
2378 	} while (0);
2379 
2380 	/* Need a return here to break the bridge */
2381 	sccp_log(DEBUGCAT_RTP) (VERBOSE_PREFIX_3 "%s: (update_rtp_peer) Result: %d\n", c->currentDeviceId, result);
2382 	return result;
2383 }
2384 
sccp_astwrap_getCodec(PBX_CHANNEL_TYPE * ast,struct ast_format_cap * result)2385 static void sccp_astwrap_getCodec(PBX_CHANNEL_TYPE * ast, struct ast_format_cap *result)
2386 {
2387 	uint8_t i;
2388 	AUTO_RELEASE(sccp_channel_t, channel , get_sccp_channel_from_pbx_channel(ast));
2389 
2390 	if (!channel) {
2391 		sccp_log((DEBUGCAT_RTP | DEBUGCAT_CODEC)) (VERBOSE_PREFIX_1 "SCCP: (getCodec) NO PVT\n");
2392 		return;
2393 	}
2394 
2395 	ast_debug(10, "asterisk requests format for channel %s, readFormat: %s(%d)\n", pbx_channel_name(ast), codec2str(channel->rtp.audio.transmission.format), channel->rtp.audio.transmission.format);
2396 	for (i = 0; i < ARRAY_LEN(channel->preferences.audio); i++) {
2397 		struct ast_format *ast_format = sccp_astwrap_skinny2ast_format(channel->preferences.audio[i]);
2398 		if (ast_format != ast_format_none) {
2399 			unsigned int framing = ast_format_get_default_ms(ast_format);
2400 			ast_format_cap_append(result, ast_format, framing);
2401 		}
2402 	}
2403 	for (i = 0; i < ARRAY_LEN(channel->preferences.video); i++) {
2404 		struct ast_format *ast_format = sccp_astwrap_skinny2ast_format(channel->preferences.video[i]);
2405 		if (ast_format != ast_format_none) {
2406 			unsigned int framing = ast_format_get_default_ms(ast_format);
2407 			ast_format_cap_append(result, ast_format, framing);
2408 		}
2409 	}
2410 
2411 	return;
2412 }
2413 
2414 /*
2415  * \brief get callerid_name from pbx
2416  * \param sccp_channle Asterisk Channel
2417  * \param cid name result
2418  * \return parse result
2419  */
sccp_astwrap_callerid_name(PBX_CHANNEL_TYPE * pbx_chan,char ** cid_name)2420 static int sccp_astwrap_callerid_name(PBX_CHANNEL_TYPE *pbx_chan, char **cid_name)
2421 {
2422 	if (pbx_chan && ast_channel_caller(pbx_chan)->id.name.str && strlen(ast_channel_caller(pbx_chan)->id.name.str) > 0) {
2423 		*cid_name = pbx_strdup(ast_channel_caller(pbx_chan)->id.name.str);
2424 		return 1;
2425 	}
2426 
2427 	return 0;
2428 }
2429 
2430 /*
2431  * \brief get callerid_name from pbx
2432  * \param ast_chan Asterisk Channel
2433  * \return char * with the caller number
2434  */
sccp_astwrap_callerid_number(PBX_CHANNEL_TYPE * pbx_chan,char ** cid_number)2435 static int sccp_astwrap_callerid_number(PBX_CHANNEL_TYPE *pbx_chan, char **cid_number)
2436 {
2437 	if (pbx_chan && ast_channel_caller(pbx_chan)->id.number.str && strlen(ast_channel_caller(pbx_chan)->id.number.str) > 0) {
2438 		*cid_number = pbx_strdup(ast_channel_caller(pbx_chan)->id.number.str);
2439 		return 1;
2440 	}
2441 
2442 	return 0;
2443 }
2444 
2445 /*
2446  * \brief get callerid_ton from pbx
2447  * \param ast_chan Asterisk Channel
2448  * \return char * with the caller number
2449  */
sccp_astwrap_callerid_ton(PBX_CHANNEL_TYPE * pbx_chan,int * cid_ton)2450 static int sccp_astwrap_callerid_ton(PBX_CHANNEL_TYPE *pbx_chan, int *cid_ton)
2451 {
2452 	if (pbx_chan && ast_channel_caller(pbx_chan)->id.number.valid) {
2453 		*cid_ton = ast_channel_caller(pbx_chan)->ani.number.plan;
2454 		return *cid_ton;
2455 	}
2456 	return 0;
2457 }
2458 
2459 /*
2460  * \brief get callerid_ani from pbx
2461  * \param ast_chan Asterisk Channel
2462  * \return char * with the caller number
2463  */
sccp_astwrap_callerid_ani(PBX_CHANNEL_TYPE * pbx_chan,char ** cid_ani)2464 static int sccp_astwrap_callerid_ani(PBX_CHANNEL_TYPE *pbx_chan, char **cid_ani)
2465 {
2466 	if (pbx_chan && ast_channel_caller(pbx_chan)->ani.number.valid && ast_channel_caller(pbx_chan)->ani.number.str && strlen(ast_channel_caller(pbx_chan)->ani.number.str) > 0) {
2467 		*cid_ani = pbx_strdup(ast_channel_caller(pbx_chan)->ani.number.str);
2468 		return 1;
2469 	}
2470 
2471 	return 0;
2472 }
2473 
2474 /*
2475  * \brief get callerid_dnid from pbx
2476  * \param ast_chan Asterisk Channel
2477  * \return char * with the caller number
2478  */
sccp_astwrap_callerid_subaddr(PBX_CHANNEL_TYPE * pbx_chan,char ** cid_subaddr)2479 static int sccp_astwrap_callerid_subaddr(PBX_CHANNEL_TYPE *pbx_chan, char **cid_subaddr)
2480 {
2481 	if (pbx_chan && ast_channel_caller(pbx_chan)->id.subaddress.valid && ast_channel_caller(pbx_chan)->id.subaddress.str && strlen(ast_channel_caller(pbx_chan)->id.subaddress.str) > 0) {
2482 		*cid_subaddr = pbx_strdup(ast_channel_caller(pbx_chan)->id.subaddress.str);
2483 		return 1;
2484 	}
2485 
2486 	return 0;
2487 }
2488 
2489 /*
2490  * \brief get callerid_dnid from pbx (Destination ID)
2491  * \param ast_chan Asterisk Channel
2492  * \return char * with the caller number
2493  */
sccp_astwrap_callerid_dnid(PBX_CHANNEL_TYPE * pbx_chan,char ** cid_dnid)2494 static int sccp_astwrap_callerid_dnid(PBX_CHANNEL_TYPE *pbx_chan, char **cid_dnid)
2495 {
2496 	if (pbx_chan && ast_channel_dialed(pbx_chan)->number.str && strlen(ast_channel_dialed(pbx_chan)->number.str) > 0) {
2497 		*cid_dnid = pbx_strdup(ast_channel_dialed(pbx_chan)->number.str);
2498 		return 1;
2499 	}
2500 
2501 	return 0;
2502 }
2503 
2504 /*
2505  * \brief get callerid_rdnis from pbx
2506  * \param ast_chan Asterisk Channel
2507  * \return char * with the caller number
2508  */
sccp_astwrap_callerid_rdnis(PBX_CHANNEL_TYPE * pbx_chan,char ** cid_rdnis)2509 static int sccp_astwrap_callerid_rdnis(PBX_CHANNEL_TYPE *pbx_chan, char **cid_rdnis)
2510 {
2511 	if (pbx_chan && ast_channel_redirecting(pbx_chan)->from.number.valid && ast_channel_redirecting(pbx_chan)->from.number.str && strlen(ast_channel_redirecting(pbx_chan)->from.number.str) > 0) {
2512 		*cid_rdnis = pbx_strdup(ast_channel_redirecting(pbx_chan)->from.number.str);
2513 		return 1;
2514 	}
2515 
2516 	return 0;
2517 }
2518 
2519 /*
2520  * \brief get callerid_presence from pbx
2521  * \param ast_chan Asterisk Channel
2522  * \return char * with the caller number
2523  */
sccp_astwrap_callerid_presentation(PBX_CHANNEL_TYPE * pbx_chan)2524 static sccp_callerid_presentation_t sccp_astwrap_callerid_presentation(PBX_CHANNEL_TYPE *pbx_chan)
2525 {
2526 	if (pbx_chan && (ast_party_id_presentation(&ast_channel_caller(pbx_chan)->id) & AST_PRES_RESTRICTION) == AST_PRES_ALLOWED) {
2527 		return CALLERID_PRESENTATION_ALLOWED;
2528 	}
2529 	return CALLERID_PRESENTATION_FORBIDDEN;
2530 }
2531 
sccp_astwrap_createRtpInstance(constDevicePtr d,constChannelPtr c,sccp_rtp_t * rtp)2532 static boolean_t sccp_astwrap_createRtpInstance(constDevicePtr d, constChannelPtr c, sccp_rtp_t *rtp)
2533 {
2534 	uint32_t tos = 0, cos = 0;
2535 
2536 	if(!c || !d) {
2537 		return FALSE;
2538 	}
2539 	struct sockaddr_storage ourip = { 0 };
2540 	sccp_session_getOurIP(d->session, &ourip, 0);
2541 	struct ast_sockaddr sock = { {
2542 	    0,
2543 	} };
2544 	storage2ast_sockaddr(&ourip, &sock);
2545 
2546 	if ((rtp->instance = ast_rtp_instance_new("asterisk", sched, &sock, NULL))) {
2547 		struct ast_sockaddr instance_addr = { {0,} };
2548 		ast_rtp_instance_get_local_address(rtp->instance, &instance_addr);
2549 		sccp_log(DEBUGCAT_RTP) (VERBOSE_PREFIX_3 "%s: rtp server instance created at %s\n", c->designator, ast_sockaddr_stringify(&instance_addr));
2550 	} else {
2551 		return FALSE;
2552 	}
2553 
2554 	/* rest below should be moved out of here (refactoring required) */
2555 	PBX_RTP_TYPE *instance = rtp->instance;
2556 	char *rtp_map_filter = NULL;
2557 	//enum ast_media_type format_type = AST_MEDIA_TYPE_AUDIO;
2558 	int fd_offset = 0;
2559 	switch(rtp->type) {
2560 		case SCCP_RTP_AUDIO:
2561 			tos = d->audio_tos;
2562 			cos = d->audio_cos;
2563 			rtp_map_filter = "audio";
2564 			//format_type = AST_MEDIA_TYPE_AUDIO;
2565 			break;
2566 
2567 #if CS_SCCP_VIDEO
2568 		case SCCP_RTP_VIDEO:
2569 			tos = d->video_tos;
2570 			cos = d->video_cos;
2571 			rtp_map_filter = "video";
2572 			//format_type = AST_MEDIA_TYPE_VIDEO;
2573 			fd_offset = 2;
2574 			break;
2575 #endif
2576 		default:
2577 			pbx_log(LOG_ERROR, "%s: (wrapper_create_rtp) unknown/unhandled rtp type, returning instance for now\n", c->designator);
2578 			return TRUE;
2579 	}
2580 
2581 	if (c->owner) {
2582 		ast_rtp_instance_set_channel_id(instance, ast_channel_uniqueid(c->owner));
2583 		ast_channel_set_fd(c->owner, fd_offset, ast_rtp_instance_fd(instance, 0));		// RTP
2584 		ast_channel_set_fd(c->owner, fd_offset + 1, ast_rtp_instance_fd(instance, 1));		// RTCP
2585 	}
2586 	ast_rtp_instance_set_prop(instance, AST_RTP_PROPERTY_RTCP, 1);
2587 	if (rtp->type == SCCP_RTP_AUDIO) {
2588 		ast_rtp_instance_set_prop(instance, AST_RTP_PROPERTY_DTMF, 1);
2589 		if (c->dtmfmode == SCCP_DTMFMODE_SKINNY) {
2590 			ast_rtp_instance_set_prop(instance, AST_RTP_PROPERTY_DTMF_COMPENSATE, 1);
2591 			ast_rtp_instance_dtmf_mode_set(instance, AST_RTP_DTMF_MODE_INBAND);
2592 		} else {
2593 			ast_rtp_instance_dtmf_mode_set(instance, AST_RTP_DTMF_MODE_RFC2833);
2594 		}
2595 	}
2596 	ast_rtp_instance_set_qos(instance, tos, cos, "SCCP RTP");
2597 
2598 	if (rtp->type == SCCP_RTP_AUDIO) {
2599 		sccp_log(DEBUGCAT_CODEC)(VERBOSE_PREFIX_2 "%s: update rtpmap: format:%s, payload:%d, mime:%s, rate:%d\n",
2600 			c->designator, "CISCO-DTMF", 101, "audio", 0);
2601 		ast_rtp_codecs_payloads_set_m_type(ast_rtp_instance_get_codecs(instance), instance, 101);
2602 		if (ast_rtp_codecs_payloads_set_rtpmap_type(ast_rtp_instance_get_codecs(instance), instance, 101, rtp_map_filter, "telephone-event", (enum ast_rtp_options)0)) {
2603 			ast_rtp_codecs_payloads_unset(ast_rtp_instance_get_codecs(instance), instance, 101);
2604  		}
2605 		ast_rtp_codecs_payload_replace_format(ast_rtp_instance_get_codecs(instance), 25, ast_format_slin16);				// replace slin16 RTPPayloadType=25 (wideband-256)
2606 	}
2607 
2608 	ast_rtp_codecs_set_framing(ast_rtp_instance_get_codecs(instance), ast_format_cap_get_framing(ast_channel_nativeformats(c->owner)));
2609 	ast_rtp_instance_activate(instance);
2610 
2611 	if (c->owner) {
2612 		ast_queue_frame(c->owner, &ast_null_frame);
2613 	}
2614 
2615 	return TRUE;
2616 }
2617 
sccp_wrapper_get_codec_framing(constChannelPtr c)2618 static uint sccp_wrapper_get_codec_framing(constChannelPtr c)
2619 {
2620 	return ast_rtp_codecs_get_framing(ast_rtp_instance_get_codecs(c->rtp.audio.instance));
2621 }
2622 
sccp_wrapper_get_dtmf_payload_code(constChannelPtr c)2623 static uint sccp_wrapper_get_dtmf_payload_code(constChannelPtr c)
2624 {
2625 	int rtp_code = 0;
2626 	if (SCCP_DTMFMODE_SKINNY != c->dtmfmode) {
2627 		rtp_code = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(c->rtp.audio.instance), 0, NULL, AST_RTP_DTMF);
2628 		//rtp_code = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(c->rtp.audio.instance), 0, NULL, AST_RTP_CISCO_DTMF);
2629 	}
2630 	sccp_log(DEBUGCAT_RTP)(VERBOSE_PREFIX_3 "%s: Using dtmf rtp_code : %d\n", c->designator, rtp_code);
2631 	return rtp_code != -1 ? rtp_code : 0;
2632 }
2633 
sccp_astwrap_destroyRTP(PBX_RTP_TYPE * rtp)2634 static boolean_t sccp_astwrap_destroyRTP(PBX_RTP_TYPE * rtp)
2635 {
2636 	int res;
2637 
2638 	res = ast_rtp_instance_destroy(rtp);
2639 	return (!res) ? TRUE : FALSE;
2640 }
2641 
sccp_astwrap_checkHangup(constChannelPtr channel)2642 static boolean_t sccp_astwrap_checkHangup(constChannelPtr channel)
2643 {
2644 	int res;
2645 
2646 	res = ast_check_hangup(channel->owner);
2647 	return (!res) ? TRUE : FALSE;
2648 }
2649 
sccp_astwrap_rtpGetPeer(PBX_RTP_TYPE * rtp,struct sockaddr_storage * address)2650 static boolean_t sccp_astwrap_rtpGetPeer(PBX_RTP_TYPE * rtp, struct sockaddr_storage *address)
2651 {
2652 	struct ast_sockaddr addr;
2653 
2654 	ast_rtp_instance_get_remote_address(rtp, &addr);
2655 	memcpy(address, &addr.ss, sizeof(struct sockaddr_storage));
2656 	return TRUE;
2657 }
2658 
sccp_astwrap_rtpGetUs(PBX_RTP_TYPE * rtp,struct sockaddr_storage * address)2659 static boolean_t sccp_astwrap_rtpGetUs(PBX_RTP_TYPE * rtp, struct sockaddr_storage *address)
2660 {
2661 	struct ast_sockaddr addr;
2662 
2663 	ast_rtp_instance_get_local_address(rtp, &addr);
2664 	memcpy(address, &addr.ss, sizeof(struct sockaddr_storage));
2665 	return TRUE;
2666 }
2667 
sccp_astwrap_getChannelByName(const char * name,PBX_CHANNEL_TYPE ** pbx_channel)2668 static boolean_t sccp_astwrap_getChannelByName(const char *name, PBX_CHANNEL_TYPE ** pbx_channel)
2669 {
2670 	PBX_CHANNEL_TYPE *ast = ast_channel_get_by_name(name);
2671 
2672 	if (!ast) {
2673 		return FALSE;
2674 	}
2675 	pbx_channel_lock(ast);
2676 	*pbx_channel = pbx_channel_ref(ast);
2677 	pbx_channel_unlock(ast);
2678 	return TRUE;
2679 }
2680 
2681 //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)2682 static int sccp_astwrap_setPhoneRTPAddress(const struct sccp_rtp *rtp, const struct sockaddr_storage *new_peer, int nat_active)
2683 {
2684 	struct ast_sockaddr ast_sockaddr_dest;
2685 	int res;
2686 
2687 	memcpy(&ast_sockaddr_dest.ss, new_peer, sizeof(struct sockaddr_storage));
2688 	ast_sockaddr_dest.len = (ast_sockaddr_dest.ss.ss_family == AF_INET6) ? sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in);
2689 	res = ast_rtp_instance_set_remote_address(rtp->instance, &ast_sockaddr_dest);
2690 
2691 	sccp_log((DEBUGCAT_RTP | DEBUGCAT_HIGH)) (VERBOSE_PREFIX_3 "SCCP: (setPhoneRTPAddress) Update PBX to send RTP/UDP media to '%s' (new remote) (NAT: %s)\n", ast_sockaddr_stringify(&ast_sockaddr_dest), S_COR(nat_active, "yes", "no"));
2692 	if (nat_active) {
2693 		ast_rtp_instance_set_prop(rtp->instance, AST_RTP_PROPERTY_NAT, 1);
2694 	} else {
2695 		ast_rtp_instance_set_prop(rtp->instance, AST_RTP_PROPERTY_NAT, 0);
2696 	}
2697 	return res;
2698 }
2699 
sccp_astwrap_setCalleridName(PBX_CHANNEL_TYPE * pbx_channel,const char * name)2700 static void sccp_astwrap_setCalleridName(PBX_CHANNEL_TYPE *pbx_channel, const char *name)
2701 {
2702 	if (pbx_channel && name) {
2703 		ast_party_name_free(&ast_channel_caller(pbx_channel)->id.name);
2704 		ast_channel_caller(pbx_channel)->id.name.str = pbx_strdup(name);
2705 		ast_channel_caller(pbx_channel)->id.name.valid = 1;
2706 	}
2707 }
2708 
sccp_astwrap_setCalleridNumber(PBX_CHANNEL_TYPE * pbx_channel,const char * number)2709 static void sccp_astwrap_setCalleridNumber(PBX_CHANNEL_TYPE *pbx_channel, const char *number)
2710 {
2711 	if (pbx_channel && number) {
2712 		ast_party_number_free(&ast_channel_caller(pbx_channel)->id.number);
2713 		ast_channel_caller(pbx_channel)->id.number.str = pbx_strdup(number);
2714 		ast_channel_caller(pbx_channel)->id.number.valid = 1;
2715 	}
2716 }
2717 
sccp_astwrap_setCalleridAni(PBX_CHANNEL_TYPE * pbx_channel,const char * number)2718 static void sccp_astwrap_setCalleridAni(PBX_CHANNEL_TYPE *pbx_channel, const char *number)
2719 {
2720 	if (pbx_channel && number) {
2721 		ast_party_number_free(&ast_channel_caller(pbx_channel)->ani.number);
2722 		ast_channel_caller(pbx_channel)->ani.number.str = pbx_strdup(number);
2723 		ast_channel_caller(pbx_channel)->ani.number.valid = 1;
2724 	}
2725 }
2726 
sccp_astwrap_setRedirectingParty(PBX_CHANNEL_TYPE * pbx_channel,const char * number,const char * name)2727 static void sccp_astwrap_setRedirectingParty(PBX_CHANNEL_TYPE *pbx_channel, const char *number, const char *name)
2728 {
2729 	if (pbx_channel) {
2730 		if (number) {
2731 			ast_party_number_free(&ast_channel_redirecting(pbx_channel)->from.number);
2732 			ast_channel_redirecting(pbx_channel)->from.number.str = pbx_strdup(number);
2733 			ast_channel_redirecting(pbx_channel)->from.number.valid = 1;
2734 		}
2735 
2736 		if (name) {
2737 			ast_party_name_free(&ast_channel_redirecting(pbx_channel)->from.name);
2738 			ast_channel_redirecting(pbx_channel)->from.name.str = pbx_strdup(name);
2739 			ast_channel_redirecting(pbx_channel)->from.name.valid = 1;
2740 		}
2741 	}
2742 }
2743 
sccp_astwrap_setRedirectedParty(PBX_CHANNEL_TYPE * pbx_channel,const char * number,const char * name)2744 static void sccp_astwrap_setRedirectedParty(PBX_CHANNEL_TYPE *pbx_channel, const char *number, const char *name)
2745 {
2746 	if (pbx_channel) {
2747 		if (number) {
2748 			ast_party_number_free(&ast_channel_redirecting(pbx_channel)->to.number);
2749 			ast_channel_redirecting(pbx_channel)->to.number.str = pbx_strdup(number);
2750 			ast_channel_redirecting(pbx_channel)->to.number.valid = 1;
2751 		}
2752 
2753 		if (name) {
2754 			ast_party_name_free(&ast_channel_redirecting(pbx_channel)->to.name);
2755 			ast_channel_redirecting(pbx_channel)->to.name.str = pbx_strdup(name);
2756 			ast_channel_redirecting(pbx_channel)->to.name.valid = 1;
2757 		}
2758 	}
2759 }
2760 
sccp_astwrap_updateConnectedLine(constChannelPtr channel,const char * number,const char * name,uint8_t reason)2761 static void sccp_astwrap_updateConnectedLine(constChannelPtr channel, const char *number, const char *name, uint8_t reason)
2762 {
2763 	if (!channel || !channel->owner) {
2764 		return;
2765 	}
2766 	__sccp_astwrap_updateConnectedLine(channel->owner, number,name, reason);
2767 }
2768 
sccp_astwrap_sched_add(int when,sccp_sched_cb callback,const void * data)2769 static int sccp_astwrap_sched_add(int when, sccp_sched_cb callback, const void *data)
2770 {
2771 	if (sched) {
2772 		return ast_sched_add(sched, when, callback, data);
2773 	}
2774 	return -1;
2775 }
2776 
sccp_astwrap_sched_del(int id)2777 static int sccp_astwrap_sched_del(int id)
2778 {
2779 	if (sched) {
2780 		return AST_SCHED_DEL(sched, id);
2781 	}
2782 	return -1;
2783 }
2784 
sccp_astwrap_sched_add_ref(int * id,int when,sccp_sched_cb callback,sccp_channel_t * channel)2785 static int sccp_astwrap_sched_add_ref(int *id, int when, sccp_sched_cb callback, sccp_channel_t * channel)
2786 {
2787 	if (sched && channel) {
2788 		sccp_channel_t *c = sccp_channel_retain(channel);
2789 
2790 		if (c) {
2791 			if ((*id  = ast_sched_add(sched, when, callback, c)) < 0) {
2792 				sccp_log(DEBUGCAT_CORE)(VERBOSE_PREFIX_3 "%s: sched add id:%d, when:%d, failed\n", c->designator, *id, when);
2793 				sccp_channel_release(&channel);			/* explicit release during failure */
2794 			}
2795 			return *id;
2796 		}
2797 	}
2798 	return -2;
2799 }
2800 
sccp_astwrap_sched_del_ref(int * id,sccp_channel_t * channel)2801 static int sccp_astwrap_sched_del_ref(int *id, sccp_channel_t *channel)
2802 {
2803 	if (sched) {
2804 		AST_SCHED_DEL_UNREF(sched, *id, sccp_channel_release(&channel));
2805 		return *id;
2806 	}
2807 	return -2;
2808 }
2809 
sccp_astwrap_sched_replace_ref(int * id,int when,ast_sched_cb callback,sccp_channel_t * channel)2810 static int sccp_astwrap_sched_replace_ref(int *id, int when, ast_sched_cb callback, sccp_channel_t *channel)
2811 {
2812 	if (sched) {
2813 		//sccp_log(DEBUGCAT_CORE)(VERBOSE_PREFIX_3 "%s: (sched_replace_ref) replacing id: %d\n", channel->designator, *id);
2814 		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 */
2815 		//sccp_log(DEBUGCAT_CORE)(VERBOSE_PREFIX_3 "%s: (sched_replace_ref) returning id: %d\n", channel->designator, *id);
2816 		return *id;
2817 	}
2818 	return -2;
2819 }
2820 
sccp_astwrap_sched_when(int id)2821 static long sccp_astwrap_sched_when(int id)
2822 {
2823 	if (sched) {
2824 		return ast_sched_when(sched, id);
2825 	}
2826 	return FALSE;
2827 }
2828 
sccp_astwrap_sched_wait(int id)2829 static int sccp_astwrap_sched_wait(int id)
2830 {
2831 	if (sched) {
2832 		return ast_sched_wait(sched);
2833 	}
2834 	return FALSE;
2835 }
2836 
sccp_astwrap_setCallState(constChannelPtr channel,enum ast_channel_state state)2837 static int sccp_astwrap_setCallState(constChannelPtr channel, enum ast_channel_state state)
2838 {
2839         if (channel && channel->owner) {
2840 		pbx_setstate(channel->owner, state);
2841 	}
2842 	return 0;
2843 }
2844 
sccp_astwrap_getRemoteChannel(constChannelPtr channel,PBX_CHANNEL_TYPE ** pbx_channel)2845 static boolean_t sccp_astwrap_getRemoteChannel(constChannelPtr channel, PBX_CHANNEL_TYPE ** pbx_channel)
2846 {
2847 
2848 	PBX_CHANNEL_TYPE *remotePeer = NULL;
2849 
2850 	/*
2851 	struct ast_channel_iterator *iterator = ast_channel_iterator_all_new();
2852 	((struct ao2_iterator *)iterator)->flags |= AO2_ITERATOR_DONTLOCK;
2853 	for (; (remotePeer = ast_channel_iterator_next(iterator)); pbx_channel_unref(remotePeer)) {
2854 		if (pbx_find_channel_by_linkid(remotePeer, (void *)ast_channel_linkedid(channel->owner))) {
2855 			break;
2856 		}
2857 	}
2858 	while(!(remotePeer = ast_channel_iterator_next(iterator) ){
2859 		pbx_channel_unref(remotePeer);
2860 	}
2861 	ast_channel_iterator_destroy(iterator);
2862 	if (remotePeer) {
2863 		*pbx_channel = remotePeer;
2864 		remotePeer = pbx_channel_unref(remotePeer);                     //  should we be releasing th referenec here, it has not been taken explicitly.
2865 		return TRUE;
2866 	}
2867 	*/
2868 	*pbx_channel = remotePeer;
2869 	return FALSE;
2870 }
2871 
2872 /*!
2873  * \brief Send Text to Asterisk Channel
2874  * \param ast Asterisk Channel as ast_channel
2875  * \param text Text to be send as char
2876  * \return Succes as int
2877  *
2878  * \called_from_asterisk
2879  */
sccp_pbx_sendtext(PBX_CHANNEL_TYPE * ast,const char * text)2880 static int sccp_pbx_sendtext(PBX_CHANNEL_TYPE * ast, const char *text)
2881 {
2882 	uint8_t instance;
2883 
2884 	if (!ast) {
2885 		sccp_log((DEBUGCAT_CORE)) (VERBOSE_PREFIX_3 "SCCP: No PBX CHANNEL to send text to\n");
2886 		return -1;
2887 	}
2888 
2889 	AUTO_RELEASE(sccp_channel_t, c , get_sccp_channel_from_pbx_channel(ast));
2890 	if (!c) {
2891 		sccp_log((DEBUGCAT_CORE)) (VERBOSE_PREFIX_3 "SCCP: No SCCP CHANNEL to send text to (%s)\n", pbx_channel_name(ast));
2892 		return -1;
2893 	}
2894 
2895 	AUTO_RELEASE(sccp_device_t, d , sccp_channel_getDevice(c));
2896 	if (!d) {
2897 		sccp_log((DEBUGCAT_CORE)) (VERBOSE_PREFIX_3 "SCCP: No SCCP DEVICE to send text to (%s)\n", pbx_channel_name(ast));
2898 		return -1;
2899 	}
2900 
2901 	sccp_log((DEBUGCAT_CORE)) (VERBOSE_PREFIX_3 "%s: Sending text %s on %s\n", d->id, text, pbx_channel_name(ast));
2902 
2903 	instance = sccp_device_find_index_for_line(d, c->line->name);
2904 	sccp_dev_displayprompt(d, instance, c->callid, (char *) text, 10);
2905 	return 0;
2906 }
2907 
2908 /*!
2909  * \brief Receive First Digit from Asterisk Channel
2910  * \param ast Asterisk Channel as ast_channel
2911  * \param digit First Digit as char
2912  * \return Always Return -1 as int
2913  *
2914  * \called_from_asterisk
2915  */
sccp_wrapper_recvdigit_begin(PBX_CHANNEL_TYPE * ast,char digit)2916 static int sccp_wrapper_recvdigit_begin(PBX_CHANNEL_TYPE * ast, char digit)
2917 {
2918 	return -1;
2919 }
2920 
2921 /*!
2922  * \brief Receive Last Digit from Asterisk Channel
2923  * \param ast Asterisk Channel as ast_channel
2924  * \param digit Last Digit as char
2925  * \param duration Duration as int
2926  * \return boolean
2927  *
2928  * \called_from_asterisk
2929  */
sccp_wrapper_recvdigit_end(PBX_CHANNEL_TYPE * ast,char digit,unsigned int duration)2930 static int sccp_wrapper_recvdigit_end(PBX_CHANNEL_TYPE * ast, char digit, unsigned int duration)
2931 {
2932 	AUTO_RELEASE(sccp_channel_t, c , get_sccp_channel_from_pbx_channel(ast));
2933 	if (c) {
2934 		if (c->dtmfmode == SCCP_DTMFMODE_RFC2833) {
2935 			sccp_log((DEBUGCAT_CORE)) (VERBOSE_PREFIX_3 "%s: Channel(%s) DTMF Mode is RFC2833. Skipping...\n", c->designator, pbx_channel_name(ast));
2936 			return -1;
2937 		}
2938 
2939 		AUTO_RELEASE(sccp_device_t, d , sccp_channel_getDevice(c));
2940 		if (!d) {
2941 			sccp_log((DEBUGCAT_CORE)) (VERBOSE_PREFIX_3 "SCCP: No SCCP DEVICE to send digit to (%s)\n", pbx_channel_name(ast));
2942 			return -1;
2943 		}
2944 
2945 		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));
2946 		if (c->state != SCCP_CHANNELSTATE_CONNECTED) {
2947 			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));
2948 			return -1;
2949 		}
2950 		sccp_dev_keypadbutton(d, digit, sccp_device_find_index_for_line(d, c->line->name), c->callid);
2951 	} else {
2952 		sccp_log((DEBUGCAT_CORE)) (VERBOSE_PREFIX_3 "SCCP: No SCCP CHANNEL to send digit to (%s)\n", pbx_channel_name(ast));
2953 		return -1;
2954 	}
2955 
2956 	return -1;
2957 }
2958 
sccp_astwrap_findChannelWithCallback(int (* const found_cb)(PBX_CHANNEL_TYPE * c,void * data),void * data,boolean_t lock)2959 static PBX_CHANNEL_TYPE *sccp_astwrap_findChannelWithCallback(int (*const found_cb) (PBX_CHANNEL_TYPE * c, void *data), void *data, boolean_t lock)
2960 {
2961 	PBX_CHANNEL_TYPE *remotePeer = NULL;
2962 
2963 	/*
2964 	struct ast_channel_iterator *iterator = ast_channel_iterator_all_new();
2965 	if (!lock) {
2966 		((struct ao2_iterator *)iterator)->flags |= AO2_ITERATOR_DONTLOCK;
2967 	}
2968 	for (; (remotePeer = ast_channel_iterator_next(iterator)); remotePeer = pbx_channel_unref(remotePeer)) {
2969 		if (found_cb(remotePeer, data)) {
2970 			// ast_channel_lock(remotePeer);
2971 			pbx_channel_unref(remotePeer);
2972 			break;
2973 		}
2974 	}
2975 	ast_channel_iterator_destroy(iterator);
2976 	*/
2977 
2978 	return remotePeer;
2979 }
2980 
2981 /*! \brief Set an option on a asterisk channel */
2982 #if 0
2983 static int sccp_astwrap_setOption(PBX_CHANNEL_TYPE * ast, int option, void *data, int datalen)
2984 {
2985 	int res = -1;
2986 	AUTO_RELEASE(sccp_channel_t, c , get_sccp_channel_from_pbx_channel(ast));
2987 
2988 	if (c) {
2989 		sccp_log((DEBUGCAT_CORE)) (VERBOSE_PREFIX_2 "%s: channel: %s(%s) setOption: %d\n", c->currentDeviceId, sccp_channel_toString(c), pbx_channel_name(ast), option);
2990 		//! 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 ? */
2991 		switch (option) {
2992 			case AST_OPTION_FORMAT_READ:
2993 				if (c->rtp.audio.instance) {
2994 					res = ast_rtp_instance_set_read_format(c->rtp.audio.instance, (struct ast_format *) data);
2995 				}
2996 				//sccp_astwrap_setReadFormat(c, (struct ast_format *) data);
2997 				break;
2998 			case AST_OPTION_FORMAT_WRITE:
2999 				if (c->rtp.audio.instance) {
3000 					res = ast_rtp_instance_set_write_format(c->rtp.audio.instance, (struct ast_format *) data);
3001 				}
3002 				//sccp_astwrap_setWriteFormat(c, (struct ast_format *) data);
3003 				break;
3004 
3005 			case AST_OPTION_MAKE_COMPATIBLE:
3006 				if (c->rtp.audio.instance) {
3007 					res = ast_rtp_instance_make_compatible(ast, c->rtp.audio.instance, (PBX_CHANNEL_TYPE *) data);
3008 				}
3009 				break;
3010 			case AST_OPTION_DIGIT_DETECT:
3011 			case AST_OPTION_SECURE_SIGNALING:
3012 			case AST_OPTION_SECURE_MEDIA:
3013 				res = -1;
3014 				break;
3015 			default:
3016 				break;
3017 		}
3018 	}
3019 	return res;
3020 }
3021 #endif
3022 
sccp_astwrap_set_pbxchannel_linkedid(PBX_CHANNEL_TYPE * pbx_channel,const char * new_linkedid)3023 static void sccp_astwrap_set_pbxchannel_linkedid(PBX_CHANNEL_TYPE * pbx_channel, const char *new_linkedid)
3024 {
3025 	if (pbx_channel) {
3026 		if (!strcmp(ast_channel_linkedid(pbx_channel), new_linkedid)) {
3027 			return;
3028 		}
3029 		// ast_cel_check_retire_linkedid(pbx_channel);
3030 		// ast_channel_linkedid_set(pbx_channel, new_linkedid);
3031 		// ast_cel_linkedid_ref(new_linkedid);
3032 	}
3033 };
3034 
3035 #define DECLARE_PBX_CHANNEL_STRGET(_field) 									\
3036 static const char *sccp_astwrap_get_channel_##_field(constChannelPtr channel)	 		\
3037 {														\
3038 	static const char *empty_channel_##_field = "--no-channel" #_field "--";				\
3039 	if (channel && channel->owner) {											\
3040 		return ast_channel_##_field(channel->owner);							\
3041 	}													\
3042 	return empty_channel_##_field;										\
3043 };
3044 
3045 #define DECLARE_PBX_CHANNEL_STRSET(_field)									\
3046 static void sccp_astwrap_set_channel_##_field(constChannelPtr channel, const char * (_field))	\
3047 { 														\
3048 	if (channel && channel->owner) {											\
3049 		ast_channel_##_field##_set(channel->owner, _field);						\
3050 	}													\
3051 };
3052 
3053 DECLARE_PBX_CHANNEL_STRGET(name)
DECLARE_PBX_CHANNEL_STRSET(name)3054     DECLARE_PBX_CHANNEL_STRSET(name)
3055     DECLARE_PBX_CHANNEL_STRGET(uniqueid)
3056     DECLARE_PBX_CHANNEL_STRGET(appl)
3057     DECLARE_PBX_CHANNEL_STRGET(exten)
3058     DECLARE_PBX_CHANNEL_STRSET(exten)
3059     DECLARE_PBX_CHANNEL_STRGET(linkedid)
3060     DECLARE_PBX_CHANNEL_STRGET(context)
3061     DECLARE_PBX_CHANNEL_STRSET(context)
3062     DECLARE_PBX_CHANNEL_STRGET(macroexten)
3063     DECLARE_PBX_CHANNEL_STRSET(macroexten)
3064     DECLARE_PBX_CHANNEL_STRGET(macrocontext)
3065     DECLARE_PBX_CHANNEL_STRSET(macrocontext)
3066     DECLARE_PBX_CHANNEL_STRGET(call_forward)
3067     DECLARE_PBX_CHANNEL_STRSET(call_forward)
3068 
3069 static void sccp_astwrap_set_channel_linkedid(constChannelPtr channel, const char *new_linkedid)
3070 {
3071 	if (channel && channel->owner) {
3072 		sccp_astwrap_set_pbxchannel_linkedid(channel->owner, new_linkedid);
3073 	}
3074 };
3075 
sccp_astwrap_get_channel_state(constChannelPtr channel)3076 static enum ast_channel_state sccp_astwrap_get_channel_state(constChannelPtr channel)
3077 {
3078 	if (channel && channel->owner) {
3079 		return ast_channel_state(channel->owner);
3080 	}
3081 	return (enum ast_channel_state) 0;
3082 }
3083 
sccp_astwrap_get_channel_pbx(constChannelPtr channel)3084 static const struct ast_pbx *sccp_astwrap_get_channel_pbx(constChannelPtr channel)
3085 {
3086 	if (channel && channel->owner) {
3087 		return ast_channel_pbx(channel->owner);
3088 	}
3089 	return NULL;
3090 }
3091 
sccp_pbx_sendHTML(PBX_CHANNEL_TYPE * ast,int subclass,const char * data,int datalen)3092 static int sccp_pbx_sendHTML(PBX_CHANNEL_TYPE * ast, int subclass, const char *data, int datalen)
3093 {
3094 	int res = -1;
3095 	if (!datalen || sccp_strlen_zero(data) || !(!strncmp(data, "http://", 7) || !strncmp(data, "file://", 7) || !strncmp(data, "ftp://", 6))) {
3096 		pbx_log(LOG_NOTICE, "SCCP: Received a non valid URL\n");
3097 		return res;
3098 	}
3099 	struct ast_frame fr;
3100 
3101 	AUTO_RELEASE(sccp_channel_t, c , get_sccp_channel_from_pbx_channel(ast));
3102 	if (c) {
3103 		AUTO_RELEASE(sccp_device_t, d , c->getDevice(c));
3104 		if (d) {
3105 			memset(&fr, 0, sizeof(fr));
3106 			fr.frametype = AST_FRAME_HTML;
3107 			fr.data.ptr = (char *) data;
3108 			fr.src = "SCCP Send URL";
3109 			fr.datalen = datalen;
3110 
3111 			sccp_push_result_t pushResult = d->pushURL(d, data, 1, SKINNY_TONE_ZIP);
3112 
3113 			if (SCCP_PUSH_RESULT_SUCCESS == pushResult) {
3114 				fr.subclass.integer = AST_HTML_LDCOMPLETE;
3115 			} else {
3116 				fr.subclass.integer = AST_HTML_NOSUPPORT;
3117 			}
3118 			ast_queue_frame(ast, ast_frisolate(&fr));
3119 			res = 0;
3120 		}
3121 	}
3122 	return res;
3123 }
3124 
3125 /*!
3126  * \brief Queue a control frame
3127  * \param pbx_channel PBX Channel
3128  * \param control as Asterisk Control Frame Type
3129  */
sccp_astwrap_queue_control(const PBX_CHANNEL_TYPE * pbx_channel,enum ast_control_frame_type control)3130 int sccp_astwrap_queue_control(const PBX_CHANNEL_TYPE * pbx_channel, enum ast_control_frame_type control)
3131 {
3132 	struct ast_frame f = { AST_FRAME_CONTROL,.subclass.integer = control };
3133 	return ast_queue_frame((PBX_CHANNEL_TYPE *) pbx_channel, &f);
3134 }
3135 
3136 /*!
3137  * \brief Queue a control frame with payload
3138  * \param pbx_channel PBX Channel
3139  * \param control as Asterisk Control Frame Type
3140  * \param data Payload
3141  * \param datalen Payload Length
3142  */
sccp_astwrap_queue_control_data(const PBX_CHANNEL_TYPE * pbx_channel,enum ast_control_frame_type control,const void * data,size_t datalen)3143 int sccp_astwrap_queue_control_data(const PBX_CHANNEL_TYPE * pbx_channel, enum ast_control_frame_type control, const void *data, size_t datalen)
3144 {
3145 	struct ast_frame f = { AST_FRAME_CONTROL,.subclass.integer = control,.data.ptr = (void *) data,.datalen = datalen };
3146 	return ast_queue_frame((PBX_CHANNEL_TYPE *) pbx_channel, &f);
3147 }
3148 
3149 /*!
3150  * \brief Get Hint Extension State and return the matching Busy Lamp Field State
3151  */
sccp_astwrap_getExtensionState(const char * extension,const char * context)3152 static skinny_busylampfield_state_t sccp_astwrap_getExtensionState(const char *extension, const char *context)
3153 {
3154 	skinny_busylampfield_state_t result = SKINNY_BLF_STATUS_UNKNOWN;
3155 
3156 	if (sccp_strlen_zero(extension) || sccp_strlen_zero(context)) {
3157 		pbx_log(LOG_ERROR, "SCCP: iPbx.getExtensionState: Either extension:'%s' or context:;%s' provided is empty\n", extension, context);
3158 		return result;
3159 	}
3160 
3161 	int state = ast_extension_state(NULL, context, extension);
3162 
3163 	switch (state) {
3164 		case AST_EXTENSION_REMOVED:
3165 		case AST_EXTENSION_DEACTIVATED:
3166 		case AST_EXTENSION_UNAVAILABLE:
3167 			result = SKINNY_BLF_STATUS_UNKNOWN;
3168 			break;
3169 		case AST_EXTENSION_NOT_INUSE:
3170 			result = SKINNY_BLF_STATUS_IDLE;
3171 			break;
3172 		case AST_EXTENSION_INUSE:
3173 		case AST_EXTENSION_ONHOLD:
3174 		case AST_EXTENSION_ONHOLD + AST_EXTENSION_INUSE:
3175 			result = SKINNY_BLF_STATUS_INUSE;
3176 			break;
3177 		case AST_EXTENSION_BUSY:
3178 			result = SKINNY_BLF_STATUS_DND;
3179 			break;
3180 		case AST_EXTENSION_RINGING + AST_EXTENSION_INUSE:
3181 		case AST_EXTENSION_RINGING:
3182 			result = SKINNY_BLF_STATUS_ALERTING;
3183 			break;
3184 	}
3185 	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);
3186 	return result;
3187 }
3188 
sccp_astwrap_endpoint_create(const char * tech,const char * resource)3189 static struct ast_endpoint *sccp_astwrap_endpoint_create(const char *tech, const char *resource)
3190 {
3191 	return ast_endpoint_create(tech, resource);
3192 }
3193 
sccp_astwrap_endpoint_online(struct ast_endpoint * endpoint,const char * address)3194 static void sccp_astwrap_endpoint_online(struct ast_endpoint *endpoint, const char *address)
3195 {
3196 	RAII(struct ast_json *, blob, NULL, ast_json_unref);
3197 	ast_endpoint_set_state(endpoint, AST_ENDPOINT_ONLINE);
3198 	blob = ast_json_pack("{s: s, s: s}", "peer_status", "Registered", "address", address);
3199 	ast_endpoint_blob_publish(endpoint, ast_endpoint_state_type(), blob);
3200 }
3201 
sccp_astwrap_endpoint_offline(struct ast_endpoint * endpoint,const char * cause)3202 static void sccp_astwrap_endpoint_offline(struct ast_endpoint *endpoint, const char *cause)
3203 {
3204 	RAII(struct ast_json *, blob, NULL, ast_json_unref);
3205 	ast_endpoint_set_state(endpoint, AST_ENDPOINT_OFFLINE);
3206 	blob = ast_json_pack("{s: s, s: s}", "peer_status", "Unregistered", "cause", cause);
3207 	ast_endpoint_blob_publish(endpoint, ast_endpoint_state_type(), blob);
3208 }
3209 
sccp_astwrap_endpoint_shutdown(struct ast_endpoint ** endpoint)3210 static void sccp_astwrap_endpoint_shutdown(struct ast_endpoint **endpoint)
3211 {
3212 	ast_endpoint_shutdown(*endpoint);
3213 	*endpoint = NULL;
3214 }
3215 
sccp_astwrap_dumpchan(PBX_CHANNEL_TYPE * const c,char * const buf,size_t size)3216 static int sccp_astwrap_dumpchan(PBX_CHANNEL_TYPE * const c, char * const buf, size_t size)
3217 {
3218 	long elapsed_seconds = 0;
3219 	int hour = 0, min = 0, sec = 0;
3220 	char cgrp[256];
3221 	char pgrp[256];
3222 	pbx_str_t *write_transpath = pbx_str_alloca(256);
3223 	pbx_str_t *read_transpath = pbx_str_alloca(256);
3224 	struct ast_bridge *bridge;
3225 	pbx_str_t *vars = pbx_str_thread_get(&ast_str_thread_global_buf, 16);
3226 	pbx_str_t *codec_buf = pbx_str_alloca(64);
3227 
3228 	memset(buf, 0, size);
3229 	if (!c) {
3230 		return -1;
3231 	}
3232 
3233 	elapsed_seconds = ast_channel_get_duration(c);
3234 	hour = elapsed_seconds / 3600;
3235 	min = (elapsed_seconds % 3600) / 60;
3236 	sec = elapsed_seconds % 60;
3237 
3238 	ast_channel_lock(c);
3239 	bridge = ast_channel_get_bridge(c);
3240 	ast_channel_unlock(c);
3241 
3242 	pbx_builtin_serialize_variables(c, &vars);
3243 
3244 	snprintf(buf, size, "Name=               %s\n"
3245 				"Type=               %s\n"
3246 				"UniqueID=           %s\n"
3247 				"LinkedID=           %s\n"
3248 				"CallerIDNum=        %s\n"
3249 				"CallerIDName=       %s\n"
3250 				"ConnectedLineIDNum= %s\n"
3251 				"ConnectedLineIDName=%s\n"
3252 				"DNIDDigits=         %s\n"
3253 				"RDNIS=              %s\n"
3254 				"Parkinglot=         %s\n"
3255 				"Language=           %s\n"
3256 				"State=              %s (%d)\n"
3257 				"Rings=              %d\n"
3258 				"NativeFormat=       %s\n"
3259 				"WriteFormat=        %s\n"
3260 				"ReadFormat=         %s\n"
3261 				"RawWriteFormat=     %s\n"
3262 				"RawReadFormat=      %s\n"
3263 				"WriteTranscode=     %s %s\n"
3264 				"ReadTranscode=      %s %s\n"
3265 				"1stFileDescriptor=  %d\n"
3266 				"Framesin=           %d %s\n"
3267 				"Framesout=          %d %s\n"
3268 				"TimetoHangup=       %ld\n"
3269 				"ElapsedTime=        %dh%dm%ds\n"
3270 				"BridgeID=           %s\n"
3271 				"Context=            %s\n"
3272 				"Extension=          %s\n"
3273 				"Priority=           %d\n"
3274 				"CallGroup=          %s\n"
3275 				"PickupGroup=        %s\n"
3276 				"Application=        %s\n"
3277 				"Data=               %s\n"
3278 				"Blocking_in=        %s\n"
3279 				"Variables=          %s\n",
3280 		ast_channel_name(c),
3281 		ast_channel_tech(c)->type,
3282 		ast_channel_uniqueid(c),
3283 		ast_channel_linkedid(c),
3284 		S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, "(N/A)"),
3285 		S_COR(ast_channel_caller(c)->id.name.valid, ast_channel_caller(c)->id.name.str, "(N/A)"),
3286 		S_COR(ast_channel_connected(c)->id.number.valid, ast_channel_connected(c)->id.number.str, "(N/A)"),
3287 		S_COR(ast_channel_connected(c)->id.name.valid, ast_channel_connected(c)->id.name.str, "(N/A)"),
3288 		S_OR(ast_channel_dialed(c)->number.str, "(N/A)"),
3289 		S_COR(ast_channel_redirecting(c)->from.number.valid, ast_channel_redirecting(c)->from.number.str, "(N/A)"),
3290 		ast_channel_parkinglot(c),
3291 		ast_channel_language(c),
3292 		ast_state2str(ast_channel_state(c)),
3293 		ast_channel_state(c),
3294 		ast_channel_rings(c),
3295 		ast_format_cap_get_names(ast_channel_nativeformats(c), &codec_buf),	//ast_getformatname_multiple(nf, sizeof(nf), ast_channel_nativeformats(c)),
3296 		ast_format_get_name(ast_channel_writeformat(c)),
3297 		ast_format_get_name(ast_channel_readformat(c)),
3298 		ast_format_get_name(ast_channel_rawwriteformat(c)),
3299 		ast_format_get_name(ast_channel_rawreadformat(c)),
3300 		ast_channel_writetrans(c) ? "Yes" : "No",
3301 		ast_translate_path_to_str(ast_channel_writetrans(c), &write_transpath),
3302 		ast_channel_readtrans(c) ? "Yes" : "No",
3303 		ast_translate_path_to_str(ast_channel_readtrans(c), &read_transpath),
3304 		ast_channel_fd(c, 0),
3305 		ast_channel_fin(c) & ~DEBUGCHAN_FLAG, (ast_channel_fin(c) & DEBUGCHAN_FLAG) ? " (DEBUGGED)" : "",
3306 		ast_channel_fout(c) & ~DEBUGCHAN_FLAG, (ast_channel_fout(c) & DEBUGCHAN_FLAG) ? " (DEBUGGED)" : "",
3307 		(long) ast_channel_whentohangup(c)->tv_sec,
3308 		hour,
3309 		min,
3310 		sec,
3311 		bridge ? bridge->uniqueid : "(Not bridged)",
3312 		ast_channel_context(c),
3313 		ast_channel_exten(c),
3314 		ast_channel_priority(c),
3315 		ast_print_group(cgrp, sizeof(cgrp), ast_channel_callgroup(c)),
3316 		ast_print_group(pgrp, sizeof(pgrp), ast_channel_pickupgroup(c)),
3317 		ast_channel_appl(c) ? ast_channel_appl(c) : "(N/A)",
3318 		ast_channel_data(c) ? S_OR(ast_channel_data(c), "(Empty)") : "(None)",
3319 		(ast_test_flag(ast_channel_flags(c), AST_FLAG_BLOCKING) ? ast_channel_blockproc(c) : "(Not Blocking)"),
3320 		ast_str_buffer(vars)
3321 	);
3322 
3323 	ao2_cleanup(bridge);
3324 	return 0;
3325 }
3326 
sccp_astwrap_channelIsBridged(sccp_channel_t * channel)3327 static boolean_t sccp_astwrap_channelIsBridged(sccp_channel_t * channel)
3328 {
3329 	boolean_t res = FALSE;
3330 
3331 	if (!channel || !channel->owner) {
3332 		return res;
3333 	}
3334 	ast_channel_lock(channel->owner);
3335 	res = ast_channel_is_bridged(channel->owner);
3336 	ast_channel_unlock(channel->owner);
3337 	return res;
3338 }
3339 
sccp_astwrap_getBridgeChannel(PBX_CHANNEL_TYPE * pbx_channel)3340 static PBX_CHANNEL_TYPE *sccp_astwrap_getBridgeChannel(PBX_CHANNEL_TYPE * pbx_channel)
3341 {
3342 	PBX_CHANNEL_TYPE *bridgePeer = NULL;
3343 	if (pbx_channel) {
3344 		bridgePeer = ast_channel_bridge_peer(pbx_channel);		/* return pbx_channel_ref +1 */
3345 	}
3346 	return bridgePeer;
3347 }
3348 
sccp_astwrap_attended_transfer(sccp_channel_t * destination_channel,sccp_channel_t * source_channel)3349 static boolean_t sccp_astwrap_attended_transfer(sccp_channel_t * destination_channel, sccp_channel_t * source_channel)
3350 {
3351 	enum ast_transfer_result res;
3352 	// possibly move transfer related callinfo updates here
3353 	if (!destination_channel || !source_channel || !destination_channel->owner || !source_channel->owner) {
3354 		return FALSE;
3355 	}
3356 	PBX_CHANNEL_TYPE *pbx_destination_local_channel = destination_channel->owner;
3357 	PBX_CHANNEL_TYPE *pbx_source_local_channel = source_channel->owner;
3358 
3359 	res = ast_bridge_transfer_attended(pbx_destination_local_channel, pbx_source_local_channel);
3360 	if (res != AST_BRIDGE_TRANSFER_SUCCESS) {
3361 		pbx_log(LOG_ERROR, "%s: Failed to transfer %s to %s (%u)\n", source_channel->designator, source_channel->designator, destination_channel->designator, res);
3362 		ast_queue_control(pbx_destination_local_channel, AST_CONTROL_HOLD);
3363 		return FALSE;
3364 	}
3365 	return TRUE;
3366 }
3367 
3368 /*!
3369  * \brief using RTP Glue Engine
3370  */
3371 #if defined(__cplusplus) || defined(c_plusplus)
3372 struct ast_rtp_glue sccp_rtp = {
3373 	/* *INDENT-OFF* */
3374 	type:	SCCP_TECHTYPE_STR,
3375 	mod:	NULL,
3376 	get_rtp_info:sccp_astwrap_get_rtp_info,
3377 	//allow_rtp_remote:sccp_astwrap_allow_rtp_remote, 		/* check c->directmedia and return 1 if ok */
3378 	get_vrtp_info:sccp_astwrap_get_vrtp_info,
3379 	//allow_vrtp_remote:sccp_astwrap_allow_vrtp_remote, 	/* check c->directmedia and return 1 if ok */
3380 	get_trtp_info:NULL,
3381 	update_peer:sccp_astwrap_update_rtp_peer,
3382 	get_codec:sccp_astwrap_getCodec,
3383 	/* *INDENT-ON* */
3384 };
3385 #else
3386 struct ast_rtp_glue sccp_rtp = {
3387 	.type = SCCP_TECHTYPE_STR,
3388 	.get_rtp_info = sccp_astwrap_get_rtp_info,
3389 	//.allow_rtp_remote = sccp_astwrap_allow_rtp_remote, 	/* check c->directmedia and return 1 if ok */
3390 	.get_vrtp_info = sccp_astwrap_get_vrtp_info,
3391 	//.allow_vrtp_remote = sccp_astwrap_allow_vrtp_remote, 	/* check c->directmedia and return 1 if ok */
3392 	.update_peer = sccp_astwrap_update_rtp_peer,
3393 	.get_codec = sccp_astwrap_getCodec,
3394 };
3395 #endif
3396 
3397 #ifdef HAVE_PBX_MESSAGE_H
3398 #include <asterisk/message.h>
sccp_astwrap_message_send(const struct ast_msg * msg,const char * to,const char * from)3399 static int sccp_astwrap_message_send(const struct ast_msg *msg, const char *to, const char *from)
3400 {
3401 	char *lineName;
3402 	const char *messageText = ast_msg_get_body(msg);
3403 	int res = -1;
3404 
3405 	lineName = pbx_strdupa(to);
3406 	if (strchr(lineName, '@')) {
3407 		strsep(&lineName, "@");
3408 	} else {
3409 		strsep(&lineName, ":");
3410 	}
3411 	if (sccp_strlen_zero(lineName)) {
3412 		pbx_log(LOG_WARNING, "MESSAGE(to) is invalid for SCCP - '%s'\n", to);
3413 		return -1;
3414 	}
3415 
3416 	AUTO_RELEASE(sccp_line_t, line , sccp_line_find_byname(lineName, FALSE));
3417 	if (!line) {
3418 		pbx_log(LOG_WARNING, "line '%s' not found\n", lineName);
3419 		return -1;
3420 	}
3421 
3422 	/** \todo move this to line implementation */
3423 	sccp_linedevice_t * ld = NULL;
3424 	sccp_push_result_t pushResult;
3425 
3426 	SCCP_LIST_LOCK(&line->devices);
3427 	SCCP_LIST_TRAVERSE(&line->devices, ld, list) {
3428 		pushResult = ld->device->pushTextMessage(ld->device, messageText, from, 1, SKINNY_TONE_ZIP);
3429 		if (SCCP_PUSH_RESULT_SUCCESS == pushResult) {
3430 			res = 0;
3431 		}
3432 	}
3433 	SCCP_LIST_UNLOCK(&line->devices);
3434 
3435 	return res;
3436 }
3437 
3438 #if defined(__cplusplus) || defined(c_plusplus)
3439 static const struct ast_msg_tech sccp_msg_tech = {
3440 	/* *INDENT-OFF* */
3441 	name:	"sccp",
3442 	msg_send:sccp_astwrap_message_send,
3443 	/* *INDENT-ON* */
3444 };
3445 #else
3446 static const struct ast_msg_tech sccp_msg_tech = {
3447 	/* *INDENT-OFF* */
3448 	.name = "sccp",
3449 	.msg_send = sccp_astwrap_message_send,
3450 	/* *INDENT-ON* */
3451 };
3452 #endif
3453 
3454 #endif
3455 
3456 /*!
3457  * \brief pbx_manager_register
3458  *
3459  * \note this functions needs to be defined here, because it depends on the static declaration of pbx_module_info->self
3460  */
pbx_manager_register(const char * action,int authority,int (* func)(struct mansession * s,const struct message * m),const char * synopsis,const char * description)3461 int pbx_manager_register(const char * action, int authority, int (*func)(struct mansession * s, const struct message * m), const char * synopsis, const char * description)
3462 {
3463 #if defined(__cplusplus) || defined(c_plusplus)
3464 	return 0;
3465 #else
3466 	return ast_manager_register2(action, authority, func, pbx_module_info->self, synopsis, description);
3467 #endif
3468 }
3469 
sccp_wrapper_register_manager(const char * action,int authority,int (* func)(struct mansession * s,const struct message * m),const char * synopsis,const char * description)3470 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)
3471 {
3472 #if defined(__cplusplus) || defined(c_plusplus)
3473 	return 0;
3474 #else
3475 	return ast_manager_register2(action, authority, func, ast_module_info->self, synopsis, description);
3476 #endif
3477 }
3478 
sccp_wrapper_register_application(const char * app_name,int (* execute)(struct ast_channel *,const char *))3479 static int sccp_wrapper_register_application(const char *app_name, int (*execute)(struct ast_channel *, const char *))
3480 {
3481 #if defined(__cplusplus) || defined(c_plusplus)
3482 	return 0;
3483 #else
3484 	return ast_register_application2(app_name, execute, NULL, NULL, ast_module_info->self);
3485 #endif
3486 }
3487 
sccp_wrapper_unregister_application(const char * app_name)3488 static int sccp_wrapper_unregister_application(const char *app_name)
3489 {
3490 	return ast_unregister_application(app_name);
3491 }
3492 
sccp_wrapper_register_function(struct pbx_custom_function * custom_function)3493 static int sccp_wrapper_register_function(struct pbx_custom_function *custom_function)
3494 {
3495 #if defined(__cplusplus) || defined(c_plusplus)
3496 	return 0;
3497 #else
3498 	return __ast_custom_function_register(custom_function, ast_module_info->self);
3499 #endif
3500 }
3501 
sccp_wrapper_unregister_function(struct pbx_custom_function * custom_function)3502 static int sccp_wrapper_unregister_function(struct pbx_custom_function *custom_function)
3503 {
3504 	return ast_custom_function_unregister(custom_function);
3505 }
3506 
sccp_astwrap_setLanguage(PBX_CHANNEL_TYPE * pbxChannel,const char * language)3507 static boolean_t sccp_astwrap_setLanguage(PBX_CHANNEL_TYPE * pbxChannel, const char *language)
3508 {
3509 	ast_channel_language_set(pbxChannel, language);
3510 	return TRUE;
3511 }
3512 
3513 #if defined(__cplusplus) || defined(c_plusplus)
3514 //sccp_pbx_cb sccp_pbx = {
3515 const PbxInterface iPbx = {
3516 	/* *INDENT-OFF* */
3517 
3518 	/* channel */
3519 	alloc_pbxChannel: sccp_astwrap_allocPBXChannel,
3520 	extension_status: sccp_astwrap_extensionStatus,
3521 	setPBXChannelLinkedId: sccp_astwrap_set_pbxchannel_linkedid,
3522 
3523 	getChannelByName: sccp_astwrap_getChannelByName,
3524 	getChannelLinkedId: sccp_astwrap_get_channel_linkedid,
3525 	setChannelLinkedId: sccp_astwrap_set_channel_linkedid,
3526 	getChannelName: sccp_astwrap_get_channel_name,
3527 	setChannelName: sccp_astwrap_set_channel_name,
3528 	getChannelUniqueID: sccp_astwrap_get_channel_uniqueid,
3529 	getChannelExten: sccp_astwrap_get_channel_exten,
3530 	setChannelExten: sccp_astwrap_set_channel_exten,
3531 	getChannelContext: sccp_astwrap_get_channel_context,
3532 	setChannelContext: sccp_astwrap_set_channel_context,
3533 	getChannelMacroExten: sccp_astwrap_get_channel_macroexten,
3534 	setChannelMacroExten: sccp_astwrap_set_channel_macroexten,
3535 	getChannelMacroContext: sccp_astwrap_get_channel_macrocontext,
3536 	setChannelMacroContext: sccp_astwrap_set_channel_macrocontext,
3537 	getChannelCallForward: sccp_astwrap_get_channel_call_forward,
3538 	setChannelCallForward: sccp_astwrap_set_channel_call_forward,
3539 
3540 	getChannelAppl: sccp_astwrap_get_channel_appl,
3541 	getChannelState: sccp_astwrap_get_channel_state,
3542 	getChannelPbx: sccp_astwrap_get_channel_pbx,
3543 
3544 	getRemoteChannel: sccp_astwrap_getRemoteChannel,
3545 	checkhangup: sccp_astwrap_checkHangup,
3546 
3547 	/* digits */
3548 	send_digits: sccp_wrapper_sendDigits,
3549 	send_digit: sccp_wrapper_sendDigit,
3550 
3551 	/* schedulers */
3552 	sched_add: sccp_astwrap_sched_add,
3553 	sched_del: sccp_astwrap_sched_del,
3554 	sched_add_ref: sccp_astwrap_sched_add_ref,
3555 	sched_del_ref: sccp_astwrap_sched_del_ref,
3556 	sched_replace_ref: sccp_astwrap_sched_replace_ref,
3557 	sched_when: sccp_astwrap_sched_when,
3558 	sched_wait: sccp_astwrap_sched_wait,
3559 
3560 	/* callstate / indicate */
3561 	set_callstate: sccp_astwrap_setCallState,
3562 
3563 	/* codecs */
3564 	set_nativeAudioFormats: sccp_astwrap_setNativeAudioFormats,
3565 	set_nativeVideoFormats: sccp_astwrap_setNativeVideoFormats,
3566 
3567 	/* rtp */
3568 	rtp_getPeer: sccp_astwrap_rtpGetPeer,
3569 	rtp_getUs: sccp_astwrap_rtpGetUs,
3570 	rtp_stop: ast_rtp_instance_stop,
3571 	rtp_create_instance: sccp_astwrap_createRtpInstance,
3572 	rtp_get_payloadType: sccp_astwrap_get_payloadType,
3573 	rtp_get_sampleRate: sccp_astwrap_get_sampleRate,
3574 	rtp_destroy: sccp_astwrap_destroyRTP,
3575 	rtp_setWriteFormat: sccp_astwrap_setWriteFormat,
3576 	rtp_setReadFormat: sccp_astwrap_setReadFormat,
3577 	rtp_setPhoneAddress: sccp_astwrap_setPhoneRTPAddress,
3578 
3579 	/* callerid */
3580 	get_callerid_name: sccp_astwrap_callerid_name,
3581 	get_callerid_number: sccp_astwrap_callerid_number,
3582 	get_callerid_ton: sccp_astwrap_callerid_ton,
3583 	get_callerid_ani: sccp_astwrap_callerid_ani,
3584 	get_callerid_subaddr: sccp_astwrap_callerid_subaddr,
3585 	get_callerid_dnid: sccp_astwrap_callerid_dnid,
3586 	get_callerid_rdnis: sccp_astwrap_callerid_rdnis,
3587 	get_callerid_presentation: sccp_astwrap_callerid_presentation,
3588 
3589 	set_callerid_name: sccp_astwrap_setCalleridName,
3590 	set_callerid_number: sccp_astwrap_setCalleridNumber,
3591 	set_callerid_ani: sccp_astwrap_setCalleridAni,
3592 	set_callerid_dnid: NULL,                                        //! \todo implement callback
3593 	set_callerid_redirectingParty: sccp_astwrap_setRedirectingParty,
3594 	set_callerid_redirectedParty: sccp_astwrap_setRedirectedParty,
3595 	set_callerid_presentation: sccp_astwrap_setCalleridPresentation,
3596 	set_dialed_number: sccp_astwrap_setDialedNumber,
3597 	set_connected_line: sccp_astwrap_updateConnectedLine,
3598 	sendRedirectedUpdate: sccp_astwrap_sendRedirectedUpdate,
3599 
3600 	/* database */
3601 	feature_addToDatabase: sccp_astwrap_addToDatabase,
3602 	feature_getFromDatabase: sccp_astwrap_getFromDatabase,
3603 	feature_removeFromDatabase: sccp_astwrap_removeFromDatabase,
3604 	feature_removeTreeFromDatabase: sccp_astwrap_removeTreeFromDatabase,
3605 	feature_monitor: sccp_astgenwrap_featureMonitor,
3606 
3607 	feature_park: sccp_astwrap_park,
3608 	getFeatureExtension: sccp_astwrap_getFeatureExtension,
3609 	getPickupExtension: sccp_astwrap_getPickupExtension,
3610 
3611 	findChannelByCallback: sccp_astwrap_findChannelWithCallback,
3612 
3613 	moh_start: sccp_astwrap_moh_start,
3614 	moh_stop: sccp_astwrap_moh_stop,
3615 	queue_control: sccp_astwrap_queue_control,
3616 	queue_control_data: sccp_astwrap_queue_control_data,
3617 
3618 	allocTempPBXChannel: sccp_astwrap_allocTempPBXChannel,
3619 	masqueradeHelper: sccp_astwrap_masqueradeHelper,
3620 	requestAnnouncementChannel: sccp_astwrap_requestAnnouncementChannel,
3621 
3622 	set_language: sccp_astwrap_setLanguage,
3623 
3624 	getExtensionState: sccp_astwrap_getExtensionState,
3625 	findPickupChannelByExtenLocked: sccp_astwrap_findPickupChannelByExtenLocked,
3626 	findPickupChannelByGroupLocked: sccp_astwrap_findPickupChannelByGroupLocked,
3627 
3628 	endpoint_create: sccp_astwrap_endpoint_create,
3629 	endpoint_online: sccp_astwrap_endpoint_online,
3630 	endpoint_offline: sccp_astwrap_endpoint_offline,
3631 	endpoint_shutdown: sccp_astwrap_endpoint_shutdown,
3632 
3633 	set_owner: sccp_astwrap_setOwner,
3634 	removeTimingFD: sccp_astwrap_removeTimingFD,
3635 	dumpchan: sccp_astwrap_dumpchan,
3636 	channel_is_bridged: sccp_astwrap_channelIsBridged,
3637 	get_bridged_channel: sccp_astwrap_getBridgeChannel,
3638 	get_underlying_channel: sccp_astwrap_getBridgeChannel,
3639 	attended_transfer: sccp_astwrap_attended_transfer,
3640 
3641 	set_callgroup: sccp_astgenwrap_set_callgroup,
3642 	set_pickupgroup: sccp_astgenwrap_set_pickupgroup,
3643 	set_named_callgroups: sccp_astgenwrap_set_named_callgroups,
3644 	set_named_pickupgroups: sccp_astgenwrap_set_named_pickupgroups,
3645 
3646 	register_manager: sccp_wrapper_register_manager,
3647 	register_application: sccp_wrapper_register_application,
3648 	unregister_application: sccp_wrapper_unregister_application,
3649 	register_function: sccp_wrapper_register_function,
3650 	unregister_function: sccp_wrapper_unregister_function,
3651 
3652 	get_codec_framing: sccp_wrapper_get_codec_framing,
3653 	get_dtmf_payload_code: sccp_wrapper_get_dtmf_payload_code,
3654 
3655 	retrieve_remote_capabilities: pbx_retrieve_remote_capabilities,
3656 	/* *INDENT-ON* */
3657 };
3658 
3659 #else
3660 
3661 /*!
3662  * \brief SCCP - PBX Callback Functions
3663  * (Decoupling Tight Dependencies on Asterisk Functions)
3664  */
3665 //struct sccp_pbx_cb sccp_pbx = {
3666 const PbxInterface iPbx = {
3667 	/* *INDENT-OFF* */
3668 
3669 	/* channel */
3670 	.alloc_pbxChannel = sccp_astwrap_allocPBXChannel,
3671 	.extension_status = sccp_astwrap_extensionStatus,
3672 	.setPBXChannelLinkedId = sccp_astwrap_set_pbxchannel_linkedid,
3673 
3674 	.getChannelByName = sccp_astwrap_getChannelByName,
3675 	.getChannelLinkedId = sccp_astwrap_get_channel_linkedid,
3676 	.setChannelLinkedId = sccp_astwrap_set_channel_linkedid,
3677 	.getChannelName = sccp_astwrap_get_channel_name,
3678 	.setChannelName = sccp_astwrap_set_channel_name,
3679 	.getChannelUniqueID = sccp_astwrap_get_channel_uniqueid,
3680 	.getChannelExten = sccp_astwrap_get_channel_exten,
3681 	.setChannelExten = sccp_astwrap_set_channel_exten,
3682 	.getChannelContext = sccp_astwrap_get_channel_context,
3683 	.setChannelContext = sccp_astwrap_set_channel_context,
3684 	.getChannelMacroExten = sccp_astwrap_get_channel_macroexten,
3685 	.setChannelMacroExten = sccp_astwrap_set_channel_macroexten,
3686 	.getChannelMacroContext = sccp_astwrap_get_channel_macrocontext,
3687 	.setChannelMacroContext = sccp_astwrap_set_channel_macrocontext,
3688 	.getChannelCallForward = sccp_astwrap_get_channel_call_forward,
3689 	.setChannelCallForward = sccp_astwrap_set_channel_call_forward,
3690 
3691 	.getChannelAppl = sccp_astwrap_get_channel_appl,
3692 	.getChannelState = sccp_astwrap_get_channel_state,
3693 	.getChannelPbx = sccp_astwrap_get_channel_pbx,
3694 
3695 	.getRemoteChannel = sccp_astwrap_getRemoteChannel,
3696 	.checkhangup = sccp_astwrap_checkHangup,
3697 
3698 	/* digits */
3699 	.send_digits = sccp_wrapper_sendDigits,
3700 	.send_digit = sccp_wrapper_sendDigit,
3701 
3702 	/* schedulers */
3703 	.sched_add = sccp_astwrap_sched_add,
3704 	.sched_del = sccp_astwrap_sched_del,
3705 	.sched_add_ref = sccp_astwrap_sched_add_ref,
3706 	.sched_del_ref = sccp_astwrap_sched_del_ref,
3707 	.sched_replace_ref = sccp_astwrap_sched_replace_ref,
3708 	.sched_when = sccp_astwrap_sched_when,
3709 	.sched_wait = sccp_astwrap_sched_wait,
3710 
3711 	/* callstate / indicate */
3712 	.set_callstate = sccp_astwrap_setCallState,
3713 
3714 	/* codecs */
3715 	.set_nativeAudioFormats = sccp_astwrap_setNativeAudioFormats,
3716 	.set_nativeVideoFormats = sccp_astwrap_setNativeVideoFormats,
3717 
3718 	/* rtp */
3719 	.rtp_getPeer = sccp_astwrap_rtpGetPeer,
3720 	.rtp_getUs = sccp_astwrap_rtpGetUs,
3721 	.rtp_stop = ast_rtp_instance_stop,
3722 	.rtp_create_instance = sccp_astwrap_createRtpInstance,
3723 	.rtp_get_payloadType = sccp_astwrap_get_payloadType,
3724 	.rtp_get_sampleRate = sccp_astwrap_get_sampleRate,
3725 	.rtp_destroy = sccp_astwrap_destroyRTP,
3726 	.rtp_setWriteFormat = sccp_astwrap_setWriteFormat,
3727 	.rtp_setReadFormat = sccp_astwrap_setReadFormat,
3728 	.rtp_setPhoneAddress = sccp_astwrap_setPhoneRTPAddress,
3729 
3730 	/* callerid */
3731 	.get_callerid_name = sccp_astwrap_callerid_name,
3732 	.get_callerid_number = sccp_astwrap_callerid_number,
3733 	.get_callerid_ton = sccp_astwrap_callerid_ton,
3734 	.get_callerid_ani = sccp_astwrap_callerid_ani,
3735 	.get_callerid_subaddr = sccp_astwrap_callerid_subaddr,
3736 	.get_callerid_dnid = sccp_astwrap_callerid_dnid,
3737 	.get_callerid_rdnis = sccp_astwrap_callerid_rdnis,
3738 	.get_callerid_presentation = sccp_astwrap_callerid_presentation,
3739 
3740 	.set_callerid_name = sccp_astwrap_setCalleridName,
3741 	.set_callerid_number = sccp_astwrap_setCalleridNumber,
3742 	.set_callerid_ani = sccp_astwrap_setCalleridAni,
3743 	.set_callerid_dnid = NULL,                                        //! \todo implement callback
3744 	.set_callerid_redirectingParty = sccp_astwrap_setRedirectingParty,
3745 	.set_callerid_redirectedParty = sccp_astwrap_setRedirectedParty,
3746 	.set_callerid_presentation = sccp_astwrap_setCalleridPresentation,
3747 	.set_dialed_number = sccp_astwrap_setDialedNumber,
3748 	.set_connected_line = sccp_astwrap_updateConnectedLine,
3749 	.sendRedirectedUpdate = sccp_astwrap_sendRedirectedUpdate,
3750 
3751 	/* database */
3752 	.feature_addToDatabase = sccp_astwrap_addToDatabase,
3753 	.feature_getFromDatabase = sccp_astwrap_getFromDatabase,
3754 	.feature_removeFromDatabase = sccp_astwrap_removeFromDatabase,
3755 	.feature_removeTreeFromDatabase = sccp_astwrap_removeTreeFromDatabase,
3756 	.feature_monitor = sccp_astgenwrap_featureMonitor,
3757 
3758 	.feature_park = sccp_astwrap_park,
3759 	.getFeatureExtension = sccp_astwrap_getFeatureExtension,
3760 	.getPickupExtension = sccp_astwrap_getPickupExtension,
3761 
3762 	.findChannelByCallback = sccp_astwrap_findChannelWithCallback,
3763 
3764 	.moh_start = sccp_astwrap_moh_start,
3765 	.moh_stop = sccp_astwrap_moh_stop,
3766 	.queue_control = sccp_astwrap_queue_control,
3767 	.queue_control_data = sccp_astwrap_queue_control_data,
3768 
3769 	.allocTempPBXChannel = sccp_astwrap_allocTempPBXChannel,
3770 	.masqueradeHelper = sccp_astwrap_masqueradeHelper,
3771 	.requestAnnouncementChannel = sccp_astwrap_requestAnnouncementChannel,
3772 
3773 	.set_language = sccp_astwrap_setLanguage,
3774 
3775 	.getExtensionState = sccp_astwrap_getExtensionState,
3776 	.findPickupChannelByExtenLocked = sccp_astwrap_findPickupChannelByExtenLocked,
3777 	.findPickupChannelByGroupLocked = sccp_astwrap_findPickupChannelByGroupLocked,
3778 
3779 	.endpoint_create = sccp_astwrap_endpoint_create,
3780 	.endpoint_online = sccp_astwrap_endpoint_online,
3781 	.endpoint_offline = sccp_astwrap_endpoint_offline,
3782 	.endpoint_shutdown = sccp_astwrap_endpoint_shutdown,
3783 
3784 	.set_owner = sccp_astwrap_setOwner,
3785 	.removeTimingFD = sccp_astwrap_removeTimingFD,
3786 	.dumpchan = sccp_astwrap_dumpchan,
3787 	.channel_is_bridged = sccp_astwrap_channelIsBridged,
3788 	.get_bridged_channel = sccp_astwrap_getBridgeChannel,
3789 	.get_underlying_channel = sccp_astwrap_getBridgeChannel,
3790 	.attended_transfer = sccp_astwrap_attended_transfer,
3791 
3792 	.set_callgroup = sccp_astgenwrap_set_callgroup,
3793 	.set_pickupgroup = sccp_astgenwrap_set_pickupgroup,
3794 	.set_named_callgroups = sccp_astgenwrap_set_named_callgroups,
3795 	.set_named_pickupgroups = sccp_astgenwrap_set_named_pickupgroups,
3796 
3797 	.register_manager = sccp_wrapper_register_manager,
3798 	.register_application = sccp_wrapper_register_application,
3799 	.unregister_application = sccp_wrapper_unregister_application,
3800 	.register_function = sccp_wrapper_register_function,
3801 	.unregister_function = sccp_wrapper_unregister_function,
3802 
3803 	.get_codec_framing = sccp_wrapper_get_codec_framing,
3804 	.get_dtmf_payload_code = sccp_wrapper_get_dtmf_payload_code,
3805 
3806 	.retrieve_remote_capabilities = pbx_retrieve_remote_capabilities,
3807 	/* *INDENT-ON* */
3808 };
3809 #endif
3810 
register_channel_tech(struct ast_channel_tech * tech)3811 static int register_channel_tech(struct ast_channel_tech *tech)
3812 {
3813 	tech->capabilities = ast_format_cap_alloc((enum ast_format_cap_flags)0);
3814 	if (!tech->capabilities) {
3815 		ao2_cleanup(tech->capabilities);
3816 		return -1;
3817 	}
3818 	ast_format_cap_append_by_type(tech->capabilities, AST_MEDIA_TYPE_AUDIO);
3819 	ast_format_cap_append_by_type(tech->capabilities, AST_MEDIA_TYPE_VIDEO);
3820 	//ast_format_cap_append_by_type(tech->capabilities, AST_MEDIA_TYPE_TEXT);
3821 	//pbx_format_cap_append_skinny(tech->capabilities, GLOB(global_preferences));
3822 
3823 	if (ast_channel_register(tech)) {
3824 		ast_log(LOG_ERROR, "Unable to register channel technology %s(%s).\n", tech->type, tech->description);
3825 		return -1;
3826 	}
3827 	return 0;
3828 }
3829 
unregister_channel_tech(struct ast_channel_tech * tech)3830 static void unregister_channel_tech(struct ast_channel_tech *tech)
3831 {
3832 	ast_channel_unregister(tech);
3833 	if (tech->capabilities) {
3834 		ao2_ref(tech->capabilities, -1);
3835 	}
3836 	tech->capabilities = NULL;
3837 	tech = NULL;
3838 }
3839 
unload_module(void)3840 static int unload_module(void)
3841 {
3842 	pbx_log(LOG_NOTICE, "SCCP: Module Unload\n");
3843 	sccp_preUnload();
3844 	sccp_log((DEBUGCAT_CORE)) (VERBOSE_PREFIX_2 "SCCP: Unregister SCCP RTP protocol\n");
3845 	ast_rtp_glue_unregister(&sccp_rtp);
3846 	sccp_log((DEBUGCAT_CORE)) (VERBOSE_PREFIX_2 "SCCP: Unregister SCCP Channel Tech\n");
3847 
3848 	unregister_channel_tech(&sccp_tech);
3849 	sccp_unregister_dialplan_functions();
3850 	sccp_unregister_cli();
3851 #ifdef CS_SCCP_MANAGER
3852 	sccp_unregister_management();
3853 #endif
3854 #ifdef HAVE_PBX_MESSAGE_H
3855 	ast_msg_tech_unregister(&sccp_msg_tech);
3856 #endif
3857 #ifdef CS_SCCP_CONFERENCE
3858 	unregister_channel_tech(sccpconf_announce_get_tech());
3859 #endif
3860 
3861 	if (io) {
3862 		io_context_destroy(io);
3863 		io = NULL;
3864 	}
3865 
3866 	while (SCCP_REF_DESTROYED != sccp_refcount_isRunning()) {
3867 		usleep(SCCP_TIME_TO_KEEP_REFCOUNTEDOBJECT);							// give enough time for all schedules to end and refcounted object to be cleanup completely
3868 	}
3869 
3870 	if (sched) {
3871 		pbx_log(LOG_NOTICE, "Cleaning up scheduled items:\n");
3872 		int scheduled_items = 0;
3873 
3874 		ast_sched_dump(sched);
3875 		while ((scheduled_items = ast_sched_runq(sched))) {
3876 			pbx_log(LOG_NOTICE, "Cleaning up %d scheduled items... please wait\n", scheduled_items);
3877 			usleep(ast_sched_wait(sched));
3878 		}
3879 		ast_sched_context_destroy(sched);
3880 		sched = NULL;
3881 	}
3882 
3883 	pbx_log(LOG_NOTICE, "Running Cleanup\n");
3884 	sccp_free(sccp_globals);
3885 	pbx_log(LOG_NOTICE, "Module chan_sccp unloaded\n");
3886 	return 0;
3887 }
3888 
load_module(void)3889 static enum ast_module_load_result load_module(void)
3890 {
3891 	if (ast_module_check("chan_skinny.so")) {
3892 		pbx_log(LOG_ERROR, "Chan_skinny is loaded. Please check modules.conf and remove chan_skinny before loading chan_sccp.\n");
3893 		return AST_MODULE_LOAD_SUCCESS;
3894 	}
3895 
3896 	enum ast_module_load_result res = AST_MODULE_LOAD_DECLINE;
3897 	do {
3898 		if (!(sched = ast_sched_context_create())) {
3899 			pbx_log(LOG_WARNING, "Unable to create schedule context. SCCP channel type disabled\n");
3900 			break;
3901 		}
3902 		if (ast_sched_start_thread(sched)) {
3903 			pbx_log(LOG_ERROR, "Unable to start scheduler\n");
3904 			ast_sched_context_destroy(sched);
3905 			sched = NULL;
3906 			break;
3907 		}
3908 #if defined(CS_DEVSTATE_FEATURE) || defined(CS_USE_ASTERISK_DISTRIBUTED_DEVSTATE)
3909 		// ast_enable_distributed_devstate();
3910 #endif
3911 		if (!sccp_prePBXLoad()) {
3912 			pbx_log(LOG_ERROR, "SCCP: prePBXLoad Failed\n");
3913 			break;
3914 		}
3915 		if (!(io = io_context_create())) {
3916 			pbx_log(LOG_ERROR, "Unable to create I/O context. SCCP channel type disabled\n");
3917 			break;
3918 		}
3919 		if (!load_config()) {
3920 			pbx_log(LOG_ERROR, "SCCP: config file could not be parsed\n");
3921 			res = AST_MODULE_LOAD_DECLINE;
3922 			break;
3923 		}
3924 		if (register_channel_tech(&sccp_tech)) {
3925 			pbx_log(LOG_ERROR, "Unable to register channel class SCCP\n");
3926 			break;
3927 		}
3928 #ifdef HAVE_PBX_MESSAGE_H
3929 		if (ast_msg_tech_register(&sccp_msg_tech)) {
3930 			pbx_log(LOG_ERROR, "Unable to register message interface\n");
3931 			break;
3932 		}
3933 #endif
3934 
3935 #ifdef CS_SCCP_CONFERENCE
3936 		if (register_channel_tech(sccpconf_announce_get_tech())) {
3937 			pbx_log(LOG_ERROR, "Unable to register channel class ANNOUNCE (conference)\n");
3938 			break;
3939 		}
3940 #endif
3941 		if (ast_rtp_glue_register(&sccp_rtp)) {
3942 			pbx_log(LOG_ERROR, "Unable to register RTP Glue\n");
3943 			break;
3944 		}
3945 		if (sccp_register_management()) {
3946 			pbx_log(LOG_ERROR, "Unable to register management functions");
3947 			break;
3948 		}
3949 		if (sccp_register_cli()) {
3950 			pbx_log(LOG_ERROR, "Unable to register CLI functions");
3951 			break;
3952 		}
3953 		if (sccp_register_dialplan_functions()) {
3954 			pbx_log(LOG_ERROR, "Unable to register dialplan functions");
3955 			break;
3956 		}
3957 		if (!sccp_postPBX_load()) {
3958 			pbx_log(LOG_ERROR, "SCCP: postPBXLoad Failed\n");
3959 			break;
3960 		}
3961 		res = AST_MODULE_LOAD_SUCCESS;
3962 	} while (0);
3963 
3964 	if (res != AST_MODULE_LOAD_SUCCESS) {
3965 		pbx_log(LOG_ERROR, "SCCP: Module Load Failed, unloading...\n");
3966 		unload_module();
3967 	}
3968 	return res;
3969 }
3970 
module_reload(void)3971 static int module_reload(void)
3972 {
3973 	return sccp_reload();
3974 }
3975 
3976 #if defined(__cplusplus) || defined(c_plusplus)
3977 
3978 static struct ast_module_info __mod_info = {
3979 	NULL,
3980 	load_module,
3981 	module_reload,
3982 	unload_module,
3983 	NULL,
3984 	NULL,
3985 	AST_MODULE,
3986 	SCCP_VERSIONSTR,
3987 	ASTERISK_GPL_KEY,
3988 	AST_MODFLAG_LOAD_ORDER,
3989 	AST_BUILDOPT_SUM,
3990 	AST_MODPRI_CHANNEL_DRIVER,
3991 	NULL,
3992 };
3993 
__reg_module(void)3994 static void __attribute__ ((constructor)) __reg_module(void)
3995 {
3996 	ast_module_register(&__mod_info);
3997 }
3998 
__unreg_module(void)3999 static void __attribute__ ((destructor)) __unreg_module(void)
4000 {
4001 	ast_module_unregister(&__mod_info);
4002 }
4003 
4004 static const __attribute__ ((unused))
4005 struct ast_module_info *ast_module_info = &__mod_info;
4006 #else
4007 
4008 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,.nonoptreq = "chan_local");
4009 #endif
4010 
sccp_astwrap_findPickupChannelByExtenLocked(PBX_CHANNEL_TYPE * chan,const char * exten,const char * context)4011 PBX_CHANNEL_TYPE *sccp_astwrap_findPickupChannelByExtenLocked(PBX_CHANNEL_TYPE * chan, const char *exten, const char *context)
4012 {
4013 	struct ast_channel *target = NULL;									/*!< Potential pickup target */
4014 	struct ast_channel_iterator *iter;
4015 
4016 	if (!(iter = ast_channel_iterator_by_exten_new(exten, context))) {
4017 		return NULL;
4018 	}
4019 
4020 	//ast_log(LOG_NOTICE, "(findPickupChannelByExtenLocked) checking pickup of channel: %s, context: %s, exten: %s, iter: %p\n", pbx_channel_name(chan), exten, context, iter);
4021 	while ((target = ast_channel_iterator_next(iter))) {
4022 		ast_channel_lock(target);
4023 		//ast_log(LOG_NOTICE, "(findPickupChannelByExtenLocked) checking channel: %s, target:%s, can_pickup: %d\n", pbx_channel_name(chan), pbx_channel_name(target), ast_can_pickup(target));
4024 		if ((chan != target) && ast_can_pickup(target)) {
4025 			ast_log(LOG_NOTICE, "%s pickup by %s\n", ast_channel_name(target), ast_channel_name(chan));
4026 			break;
4027 		}
4028 		ast_channel_unlock(target);
4029 		target = pbx_channel_unref(target);
4030 	}
4031 
4032 	ast_channel_iterator_destroy(iter);
4033 	return target;
4034 }
4035 
sccp_astwrap_findPickupChannelByGroupLocked(PBX_CHANNEL_TYPE * chan)4036 PBX_CHANNEL_TYPE *sccp_astwrap_findPickupChannelByGroupLocked(PBX_CHANNEL_TYPE * chan)
4037 {
4038 	struct ast_channel *target = NULL;									/*!< Potential pickup target */
4039 
4040 	target = ast_pickup_find_by_group(chan);
4041 	return target;
4042 }
4043 
4044 // 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;
4045