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