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