1 /*!
2 * \file sccp_pbx.c
3 * \brief SCCP PBX Asterisk Wrapper Class
4 * \author Diederik de Groot <ddegroot [at] users.sourceforge.net>
5 * \note Reworked, but based on chan_sccp code.
6 * The original chan_sccp driver that was made by Zozo which itself was derived from the chan_skinny driver.
7 * Modified by Jan Czmok and Julien Goodwin
8 * \note This program is free software and may be modified and distributed under the terms of the GNU Public License.
9 * See the LICENSE file at the top of the source tree.
10 *
11 */
12 #include "config.h"
13 #include "common.h"
14 #include "sccp_pbx.h"
15 #include "sccp_channel.h"
16 #include "sccp_device.h"
17 #include "sccp_conference.h"
18 #include "sccp_feature.h"
19 #include "sccp_line.h"
20 #include "sccp_utils.h"
21 #include "sccp_indicate.h"
22 #include "sccp_linedevice.h"
23 #include "sccp_rtp.h"
24 #include "sccp_netsock.h"
25 #include "sccp_session.h"
26 #include "sccp_atomic.h"
27 #include "sccp_labels.h"
28 #include "sccp_threadpool.h"
29
30 SCCP_FILE_VERSION(__FILE__, "");
31
32 #include <asterisk/callerid.h>
33 #include <asterisk/module.h> // ast_update_use_count
34 #include <asterisk/causes.h> // AST_CAUSE_NORMAL_CLEARING
35
36 /*!
37 * \brief SCCP Request Channel
38 * \param lineName Line Name as Char
39 * \param autoanswer_type SCCP Auto Answer Type
40 * \param autoanswer_cause SCCP Auto Answer Cause
41 * \param ringermode Ringer Mode
42 * \param channel SCCP Channel
43 * \return SCCP Channel Request Status
44 *
45 * \called_from_asterisk
46 */
sccp_requestChannel(const char * lineName,sccp_autoanswer_t autoanswer_type,uint8_t autoanswer_cause,skinny_ringtype_t ringermode,sccp_channel_t * const * channel)47 sccp_channel_request_status_t sccp_requestChannel(const char * lineName, sccp_autoanswer_t autoanswer_type, uint8_t autoanswer_cause, skinny_ringtype_t ringermode, sccp_channel_t * const * channel)
48 {
49 if (!lineName) {
50 return SCCP_REQUEST_STATUS_ERROR;
51 }
52
53 char mainId[SCCP_MAX_EXTENSION];
54 sccp_subscription_id_t subscriptionId;
55 if(!sccp_parseComposedId(lineName, 80, &subscriptionId, mainId)) {
56 sccp_log((DEBUGCAT_CORE))(VERBOSE_PREFIX_3 "Could not parse lineName:%s !\n", lineName);
57 return SCCP_REQUEST_STATUS_LINEUNKNOWN;
58 };
59
60 AUTO_RELEASE(sccp_line_t, l, sccp_line_find_byname(mainId, FALSE));
61 if (!l) {
62 sccp_log((DEBUGCAT_CORE)) (VERBOSE_PREFIX_3 "SCCP/%s does not exist!\n", mainId);
63 return SCCP_REQUEST_STATUS_LINEUNKNOWN;
64 }
65 sccp_log_and((DEBUGCAT_CORE + DEBUGCAT_HIGH)) (VERBOSE_PREFIX_1 "[SCCP] in file %s, line %d (%s)\n", __FILE__, __LINE__, __PRETTY_FUNCTION__);
66 if (SCCP_RWLIST_GETSIZE(&l->devices) == 0) {
67 sccp_log((DEBUGCAT_DEVICE + DEBUGCAT_LINE)) (VERBOSE_PREFIX_3 "SCCP/%s isn't currently registered anywhere.\n", l->name);
68 return SCCP_REQUEST_STATUS_LINEUNAVAIL;
69 }
70 sccp_log_and((DEBUGCAT_CORE + DEBUGCAT_HIGH)) (VERBOSE_PREFIX_1 "[SCCP] in file %s, line %d (%s)\n", __FILE__, __LINE__, __PRETTY_FUNCTION__);
71 /* call forward check */
72
73 // Allocate a new SCCP channel.
74 /* on multiline phone we set the line when answering or switching lines */
75 AUTO_RELEASE(sccp_channel_t, my_sccp_channel, sccp_channel_allocate(l, NULL));
76 if (!my_sccp_channel) {
77 return SCCP_REQUEST_STATUS_ERROR;
78 }
79
80 /* set subscriberId for individual device addressing */
81 if (!sccp_strlen_zero(subscriptionId.number)) {
82 sccp_copy_string(my_sccp_channel->subscriptionId.number, subscriptionId.number, sizeof(my_sccp_channel->subscriptionId.number));
83 if (!sccp_strlen_zero(subscriptionId.name)) {
84 sccp_copy_string(my_sccp_channel->subscriptionId.name, subscriptionId.name, sizeof(my_sccp_channel->subscriptionId.name));
85 } else {
86 //pbx_log(LOG_NOTICE, "%s: calling subscriber id=%s\n", l->id, my_sccp_channel->subscriptionId.number);
87 }
88 } else {
89 sccp_copy_string(my_sccp_channel->subscriptionId.number, l->defaultSubscriptionId.number, sizeof(my_sccp_channel->subscriptionId.number));
90 sccp_copy_string(my_sccp_channel->subscriptionId.name, l->defaultSubscriptionId.name, sizeof(my_sccp_channel->subscriptionId.name));
91 //pbx_log(LOG_NOTICE, "%s: calling all subscribers\n", l->id);
92 }
93
94 //memset(&channel->preferences.audio, 0, sizeof(channel->preferences.audio));
95 //memset(&channel->preferences.video, 0, sizeof(channel->preferences.video));
96
97 my_sccp_channel->autoanswer_type = autoanswer_type;
98 my_sccp_channel->autoanswer_cause = autoanswer_cause;
99 my_sccp_channel->ringermode = ringermode;
100 my_sccp_channel->hangupRequest = sccp_astgenwrap_requestQueueHangup;
101 (*(sccp_channel_t **)channel) = sccp_channel_retain(my_sccp_channel);
102 return SCCP_REQUEST_STATUS_SUCCESS;
103 }
104
105 /*!
106 * \brief SCCP Structure to pass data to the pbx answer thread
107 */
108 struct sccp_answer_conveyor_struct {
109 sccp_linedevice_t * ld;
110 uint32_t callid;
111 };
112 /*!
113 * \brief Call Auto Answer Thead
114 * \param data Data
115 *
116 * The Auto Answer thread is started by ref sccp_pbx_call if necessary
117 */
sccp_pbx_call_autoanswer_thread(void * data)118 static void *sccp_pbx_call_autoanswer_thread(void *data)
119 {
120 struct sccp_answer_conveyor_struct *conveyor = (struct sccp_answer_conveyor_struct *)data;
121
122 sccp_log((DEBUGCAT_PBX))(VERBOSE_PREFIX_3 "SCCP: autoanswer thread started\n");
123
124 sleep(GLOB(autoanswer_ring_time));
125 pthread_testcancel();
126
127 if (!conveyor) {
128 pbx_log(LOG_ERROR, "SCCP: (autoanswer_thread) No conveyor\n");
129 return NULL;
130 }
131 if(!conveyor->ld) {
132 pbx_log(LOG_ERROR, "SCCP: (autoanswer_thread) No linedevice\n");
133 goto FINAL;
134 }
135
136 {
137 AUTO_RELEASE(sccp_device_t, device, sccp_device_retain(conveyor->ld->device));
138
139 if (!device) {
140 pbx_log(LOG_ERROR, "SCCP: (autoanswer_thread) no device\n");
141 goto FINAL;
142 }
143
144 AUTO_RELEASE(sccp_channel_t, c , sccp_channel_find_byid(conveyor->callid));
145
146 if (!c || c->state != SCCP_CHANNELSTATE_RINGING) {
147 pbx_log(LOG_WARNING, "%s: (autoanswer_thread) %s\n", device->id, c ? "not ringing" : "no channel");
148 goto FINAL;
149 }
150 if (c->pbx_callid) {
151 pbx_callid_threadassoc_add(c->pbx_callid);
152 }
153
154 sccp_channel_answer(device, c);
155 c->setTone(c, GLOB(autoanswer_tone), SKINNY_TONEDIRECTION_USER);
156 if (c->autoanswer_type == SCCP_AUTOANSWER_1W) {
157 sccp_dev_set_microphone(device, SKINNY_STATIONMIC_OFF);
158 }
159 if (c->pbx_callid) {
160 pbx_callid_threadassoc_remove();
161 }
162 }
163 FINAL:
164 if(conveyor->ld) {
165 sccp_linedevice_release(&conveyor->ld); // retained in calling thread, explicit release required here
166 }
167 sccp_free(conveyor);
168 return NULL;
169 }
170
171 /*!
172 * \brief Incoming Calls by Asterisk SCCP_Request
173 * \param c SCCP Channel
174 * \param dest Destination as char
175 * \param timeout Timeout after which incoming call is cancelled as int
176 * \return Success as int
177 *
178 * \todo reimplement DNDMODES, ringermode=urgent, autoanswer
179 *
180 * \callgraph
181 * \callergraph
182 *
183 * \called_from_asterisk
184 *
185 * \note called with c retained
186 */
187 // improved sharedline handling
188 // - calculate c->subscribers correctly (using when handling sccp_softkey_onhook, to define behaviour)
189 // - handle dnd and callforward after calculating c->subscribers
190 // - use asterisk local channel to resolve forward bei non-shared line, which does evade
191 // * sccp_channel_callforward
192 // * sccp_channel_end_forwarding_channel
193 // * c->parentChannel
194 // * masquerading in sccp_pbx_answer
195 // in that case
sccp_pbx_call(channelPtr c,const char * dest,int timeout)196 int sccp_pbx_call(channelPtr c, const char * dest, int timeout)
197 {
198 if (!c) {
199 return -1;
200 }
201 int res = 0;
202
203 AUTO_RELEASE(sccp_line_t, l , sccp_line_retain(c->line));
204 if (!l) {
205 pbx_log(LOG_WARNING, "SCCP: The channel %08X has no line. giving up.\n", (c->callid));
206 return -1;
207 }
208
209 sccp_log((DEBUGCAT_CORE)) (VERBOSE_PREFIX_3 "%s: Asterisk request to call %s\n", l->name, iPbx.getChannelName(c));
210
211 /* Reinstated this call instead of the following lines */
212 char cid_name[StationMaxNameSize] = {0};
213 char cid_num[StationMaxDirnumSize] = {0};
214 char suffixedNumber[StationMaxDirnumSize] = {0};
215 sccp_callerid_presentation_t presentation = CALLERID_PRESENTATION_ALLOWED;
216
217 sccp_callinfo_t *ci = sccp_channel_getCallInfo(c);
218 iCallInfo.Getter(ci,
219 SCCP_CALLINFO_CALLINGPARTY_NAME, &cid_name,
220 SCCP_CALLINFO_CALLINGPARTY_NUMBER, &cid_num,
221 SCCP_CALLINFO_PRESENTATION, &presentation,
222 SCCP_CALLINFO_KEY_SENTINEL);
223 sccp_copy_string(suffixedNumber, cid_num, sizeof(suffixedNumber));
224 //! \todo implement dnid, ani, ani2 and rdnis
225 sccp_log((DEBUGCAT_PBX)) (VERBOSE_PREFIX_3 "SCCP: (sccp_pbx_call) asterisk callerid='%s <%s>'\n", cid_name, cid_num);
226
227 /* Set the channel callingParty Name and Number, called Party Name and Number, original CalledParty Name and Number, Presentation */
228 if (GLOB(recorddigittimeoutchar)) {
229 /* The hack to add the # at the end of the incoming number
230 is only applied for numbers beginning with a 0,
231 which is appropriate for Germany and other countries using similar numbering plan.
232 The option should be generalized, moved to the dialplan, or otherwise be replaced. */
233 /* Also, we require an option whether to add the timeout suffix to certain
234 enbloc dialed numbers (such as via 7970 enbloc dialing) if they match a certain pattern.
235 This would help users dial from call history lists on other phones, which do not have enbloc dialing,
236 when using shared lines. */
237 int length = sccp_strlen(cid_num);
238 if (length && (length + 2 < StationMaxDirnumSize) && ('\0' == cid_num[0])) {
239 suffixedNumber[length + 0] = GLOB(digittimeoutchar);
240 suffixedNumber[length + 1] = '\0';
241 }
242 /* Set the channel calledParty Name and Number 7910 compatibility */
243 }
244 //! \todo implement dnid, ani, ani2 and rdnis
245 sccp_callerid_presentation_t pbx_presentation = iPbx.get_callerid_presentation ? iPbx.get_callerid_presentation(c->owner) : SCCP_CALLERID_PRESENTATION_SENTINEL;
246 if ( (!sccp_strequals(suffixedNumber, cid_num)) ||
247 (pbx_presentation != SCCP_CALLERID_PRESENTATION_SENTINEL && pbx_presentation != presentation)
248 ) {
249 iCallInfo.Setter(ci,
250 SCCP_CALLINFO_CALLINGPARTY_NUMBER, (!sccp_strlen_zero(suffixedNumber) ? suffixedNumber : NULL),
251 SCCP_CALLINFO_PRESENTATION, (pbx_presentation != SCCP_CALLERID_PRESENTATION_SENTINEL) ? pbx_presentation : presentation,
252 SCCP_CALLINFO_KEY_SENTINEL);
253 }
254 sccp_channel_display_callInfo(c);
255
256 if (!c->ringermode) {
257 c->ringermode = GLOB(ringtype);
258 }
259 boolean_t isRinging = FALSE;
260 boolean_t isBusy = FALSE;
261 boolean_t bypassCallForward = !sccp_strlen_zero(pbx_builtin_getvar_helper(c->owner, "BYPASS_CFWD"));
262 sccp_linedevice_t * ForwardingLineDevice = NULL;
263
264 sccp_linedevice_t * ld = NULL;
265 sccp_channelstate_t previousstate = c->previousChannelState;
266
267 SCCP_LIST_LOCK(&l->devices);
268 int num_devices = SCCP_LIST_GETSIZE(&l->devices);
269 c->subscribers = num_devices;
270
271 pbx_str_t * cfwds_all = pbx_str_alloca(DEFAULT_PBX_STR_BUFFERSIZE);
272 pbx_str_t * cfwds_busy = pbx_str_alloca(DEFAULT_PBX_STR_BUFFERSIZE);
273 pbx_str_t * cfwds_noanswer = pbx_str_alloca(DEFAULT_PBX_STR_BUFFERSIZE);
274 int cfwd_all = 0;
275 int cfwd_busy = 0;
276 int cfwd_noanswer = 0;
277 SCCP_LIST_TRAVERSE(&l->devices, ld, list) {
278 AUTO_RELEASE(sccp_channel_t, active_channel, sccp_device_getActiveChannel(ld->device));
279
280 // skip incoming call on a shared line from the originator. (sharedline calling same sharedline)
281 if (active_channel && active_channel != c && sccp_strequals(iPbx.getChannelLinkedId(active_channel), iPbx.getChannelLinkedId(c))) {
282 sccp_log((DEBUGCAT_PBX))(VERBOSE_PREFIX_3 "SCCP: (sccp_pbx_call) skip ringing on %s\n", ld->device->id);
283 c->subscribers--;
284 continue;
285 }
286
287 /* do we have cfwd enabled? */
288 if(ld->cfwd[SCCP_CFWD_ALL].enabled) {
289 ast_str_append(&cfwds_all, DEFAULT_PBX_STR_BUFFERSIZE, "%s%s", cfwd_all++ ? "," : "", ld->cfwd[SCCP_CFWD_ALL].number);
290 }
291 if(ld->cfwd[SCCP_CFWD_BUSY].enabled) {
292 ast_str_append(&cfwds_busy, DEFAULT_PBX_STR_BUFFERSIZE, "%s%s", cfwd_busy++ ? "," : "", ld->cfwd[SCCP_CFWD_BUSY].number);
293 }
294 if(!bypassCallForward
295 && (ld->cfwd[SCCP_CFWD_ALL].enabled || (ld->cfwd[SCCP_CFWD_BUSY].enabled && (sccp_device_getDeviceState(ld->device) != SCCP_DEVICESTATE_ONHOOK || sccp_device_getActiveAccessory(ld->device))))) {
296 if (num_devices == 1) {
297 /* when single line -> use asterisk functionality directly, without creating new channel + masquerade */
298 sccp_log((DEBUGCAT_CORE))(VERBOSE_PREFIX_3 "%s: Call Forward active on line %s\n", ld->device->id, ld->line->name);
299 ForwardingLineDevice = ld;
300 } else {
301 /* shared line -> create a temp channel to call forward destination and tie them together */
302 pbx_log(LOG_NOTICE, "%s: handle cfwd to %s for line %s\n", ld->device->id, ld->cfwd[SCCP_CFWD_ALL].enabled ? ld->cfwd[SCCP_CFWD_ALL].number : ld->cfwd[SCCP_CFWD_BUSY].number, l->name);
303 if(sccp_channel_forward(c, ld, ld->cfwd[SCCP_CFWD_ALL].enabled ? ld->cfwd[SCCP_CFWD_ALL].number : ld->cfwd[SCCP_CFWD_BUSY].number) == 0) {
304 sccp_device_sendcallstate(ld->device, ld->lineInstance, c->callid, SKINNY_CALLSTATE_INTERCOMONEWAY, SKINNY_CALLPRIORITY_NORMAL, SKINNY_CALLINFO_VISIBILITY_DEFAULT);
305 sccp_channel_send_callinfo(ld->device, c);
306 isRinging = TRUE;
307 }
308 };
309 c->subscribers--;
310 continue;
311 }
312
313 if(ld->cfwd[SCCP_CFWD_NOANSWER].enabled && c) {
314 sccp_channel_schedule_cfwd_noanswer(c, GLOB(cfwdnoanswer_timeout));
315 ast_str_append(&cfwds_noanswer, DEFAULT_PBX_STR_BUFFERSIZE, "%s%s", cfwd_noanswer++ ? "," : "", ld->cfwd[SCCP_CFWD_NOANSWER].number);
316 }
317
318 if(!ld->device->session) {
319 sccp_log((DEBUGCAT_CORE))(VERBOSE_PREFIX_3 "%s: line device has no session\n", DEV_ID_LOG(ld->device));
320 c->subscribers--;
321 continue;
322 }
323 /* check if c->subscriptionId.number is matching deviceSubscriptionID */
324 /* This means that we call only those devices on a shared line
325 which match the specified subscription id in the dial parameters. */
326 if(!sccp_util_matchSubscriptionId(c, ld->subscriptionId.number)) {
327 sccp_log((DEBUGCAT_PBX))(VERBOSE_PREFIX_3 "%s: device does not match subscriptionId.number c->subscriptionId.number: '%s', deviceSubscriptionID: '%s'\n", DEV_ID_LOG(ld->device),
328 c->subscriptionId.number, ld->subscriptionId.number);
329 c->subscribers--;
330 continue;
331 }
332 /* reset channel state (because we are offering the same call to multiple (shared) lines)*/
333 c->previousChannelState = previousstate;
334
335 int calls = sccp_getCallCount(ld);
336 sccp_log((DEBUGCAT_PBX))(VERBOSE_PREFIX_3 "%s: #calls:%d, Incoming calls limit:%d\n", l->name, calls, l->incominglimit);
337 if(l->incominglimit && calls > l->incominglimit) {
338 sccp_log((DEBUGCAT_CORE))(VERBOSE_PREFIX_3 "%s: #calls:%d > Incoming calls limit:%d -> returning BUSY\n", l->name, calls, l->incominglimit);
339 isBusy = TRUE;
340 c->subscribers--;
341 continue;
342 }
343
344 if (active_channel) {
345 sccp_indicate(ld->device, c, SCCP_CHANNELSTATE_CALLWAITING);
346 /* display the new call on prompt */
347 AUTO_RELEASE(sccp_linedevice_t, activeChannelLinedevice, active_channel->getLineDevice(active_channel));
348 if (activeChannelLinedevice) {
349 char caller[100] = {0};
350 if(!sccp_strlen_zero(cid_name)) {
351 if(!sccp_strlen_zero(cid_num)) {
352 snprintf(caller,sizeof(caller), "%s %s <%s>", SKINNY_DISP_CALL_WAITING, cid_name, cid_num);
353 } else {
354 snprintf(caller,sizeof(caller), "%s %s", SKINNY_DISP_CALL_WAITING, cid_name);
355 }
356 } else {
357 if (!sccp_strlen_zero(cid_num)) {
358 snprintf(caller,sizeof(caller), "%s %s", SKINNY_DISP_CALL_WAITING, cid_num);
359 } else {
360 snprintf(caller,sizeof(caller), "%s %s", SKINNY_DISP_CALL_WAITING, SKINNY_DISP_UNKNOWN_NUMBER);
361 }
362 }
363 // snprintf(prompt, sizeof(prompt), "%s: %s: %s", active_channel->line->name, SKINNY_DISP_FROM, cid_num);
364 // sccp_dev_displayprompt(ld->device, activeChannelLinedevice->lineInstance, active_channel->callid, caller, SCCP_DISPLAYSTATUS_TIMEOUT);
365 sccp_dev_set_message(ld->device, caller, SCCP_DISPLAYSTATUS_TIMEOUT, FALSE, FALSE);
366 }
367 ForwardingLineDevice = NULL; /* reset cfwd if shared */
368 isRinging = TRUE;
369 } else {
370 /** check if ringermode is not urgent and device enabled dnd in reject mode */
371 if(SKINNY_RINGTYPE_URGENT != c->ringermode && ld->device->dndFeature.enabled && ld->device->dndFeature.status == SCCP_DNDMODE_REJECT) {
372 sccp_log((DEBUGCAT_CORE))(VERBOSE_PREFIX_3 "%s: DND active on line %s, returning Busy\n", ld->device->id, ld->line->name);
373 isBusy = TRUE;
374 c->subscribers--;
375 continue;
376 }
377 ForwardingLineDevice = NULL; /* reset cfwd if shared */
378 sccp_log(DEBUGCAT_PBX)(VERBOSE_PREFIX_3 "%s: Ringing %sLine: %s on device:%s using channel:%s, ringermode:%s\n", ld->device->id, SCCP_LIST_GETSIZE(&l->devices) > 1 ? "Shared" : "", ld->line->name,
379 ld->device->id, c->designator, skinny_ringtype2str(c->ringermode));
380 sccp_indicate(ld->device, c, SCCP_CHANNELSTATE_RINGING);
381 isRinging = TRUE;
382 if (c->autoanswer_type) {
383 struct sccp_answer_conveyor_struct *conveyor = (struct sccp_answer_conveyor_struct *)sccp_calloc(1, sizeof(struct sccp_answer_conveyor_struct));
384 if (conveyor) {
385 sccp_log((DEBUGCAT_CORE))(VERBOSE_PREFIX_3 "%s: Running the autoanswer thread on %s\n", DEV_ID_LOG(ld->device), iPbx.getChannelName(c));
386 conveyor->callid = c->callid;
387 conveyor->ld = sccp_linedevice_retain(ld);
388
389 sccp_threadpool_add_work(GLOB(general_threadpool), sccp_pbx_call_autoanswer_thread, (void *) conveyor);
390 } else {
391 pbx_log(LOG_ERROR, SS_Memory_Allocation_Error, c->designator);
392 }
393 }
394 }
395 }
396 SCCP_LIST_UNLOCK(&l->devices);
397
398 // sccp_log(DEBUGCAT_PBX)(VERBOSE_PREFIX_3 "%s: isRinging:%d, hadDNDParticipant:%d, ForwardingLineDevice:%p\n", c->designator, isRinging, isBusy, ForwardingLineDevice);
399 if(cfwd_all) {
400 pbx_builtin_setvar_helper(c->owner, "_CFWD_ALL", pbx_str_buffer(cfwds_all));
401 }
402 if(cfwd_busy) {
403 pbx_builtin_setvar_helper(c->owner, "_CFWD_BUSY", pbx_str_buffer(cfwds_busy));
404 }
405 if(cfwd_noanswer) {
406 pbx_builtin_setvar_helper(c->owner, "_CFWD_NOANSWER", pbx_str_buffer(cfwds_noanswer));
407 }
408 if (isRinging) {
409 sccp_channel_setChannelstate(c, SCCP_CHANNELSTATE_RINGING);
410 iPbx.set_callstate(c, AST_STATE_RINGING);
411 iPbx.queue_control(c->owner, AST_CONTROL_RINGING);
412 } else if (ForwardingLineDevice) {
413 /* when single line -> use asterisk functionality directly, without creating new channel + masquerade */
414 pbx_log(LOG_NOTICE, "%s: handle cfwd to %s for line %s\n", ForwardingLineDevice->device->id,
415 ForwardingLineDevice->cfwd[SCCP_CFWD_ALL].enabled ? ForwardingLineDevice->cfwd[SCCP_CFWD_ALL].number : ForwardingLineDevice->cfwd[SCCP_CFWD_BUSY].number, l->name);
416 #if CS_AST_CONTROL_REDIRECTING
417 iPbx.queue_control(c->owner, AST_CONTROL_REDIRECTING);
418 #endif
419 pbx_channel_call_forward_set(c->owner, ForwardingLineDevice->cfwd[SCCP_CFWD_ALL].enabled ? ForwardingLineDevice->cfwd[SCCP_CFWD_ALL].number : ForwardingLineDevice->cfwd[SCCP_CFWD_BUSY].number);
420 sccp_device_sendcallstate(ForwardingLineDevice->device, ForwardingLineDevice->lineInstance, c->callid, SKINNY_CALLSTATE_INTERCOMONEWAY, SKINNY_CALLPRIORITY_NORMAL, SKINNY_CALLINFO_VISIBILITY_DEFAULT);
421 sccp_channel_send_callinfo(ForwardingLineDevice->device, c);
422 } else if(isBusy) {
423 iPbx.queue_control(c->owner, AST_CONTROL_BUSY);
424 // iPbx.set_callstate(c, AST_STATE_BUSY);
425 // pbx_channel_set_hangupcause(c->owner, AST_CAUSE_USER_BUSY);
426 pbx_channel_set_hangupcause(c->owner, AST_CAUSE_BUSY);
427 res = 0;
428 } else {
429 iPbx.queue_control(c->owner, AST_CONTROL_CONGESTION);
430 res = -1;
431 }
432
433 /* set linevariables */
434 PBX_VARIABLE_TYPE *v = l->variables;
435 while (c->owner && !pbx_check_hangup(c->owner) && l && v) {
436 pbx_builtin_setvar_helper(c->owner, v->name, v->value);
437 v = v->next;
438 }
439
440 sccp_log((DEBUGCAT_CORE)) (VERBOSE_PREFIX_3 "%s: (sccp_pbx_call) Returning: %d\n", c->designator, res);
441 return res;
442 }
443
444 /*!
445 * callback function to handle callforward when recipient does not answer within GLOB(cfwdnoanswer_timeout)
446 *
447 * this callback is scheduled in sccp_pbx_call / sccp_channel_schedule_cfwd_noanswer
448 */
sccp_pbx_cfwdnoanswer_cb(const void * data)449 int sccp_pbx_cfwdnoanswer_cb(const void * data)
450 {
451 AUTO_RELEASE(sccp_channel_t, c, (channelPtr)data); // explicitly taken in sccp_channel_schedule_cfwd_noanswer, releasing on exit
452 if(!c || !c->owner) {
453 pbx_log(LOG_WARNING, "SCCP: No channel provided.\n");
454 return -1;
455 }
456
457 if((ATOMIC_FETCH(&c->scheduler.deny, &c->scheduler.lock) == 0)) {
458 c->scheduler.cfwd_noanswer_id = -3; /* prevent further cfwd_noanswer_id scheduling */
459 }
460
461 AUTO_RELEASE(sccp_line_t, l, sccp_line_retain(c->line));
462 if(!l) {
463 pbx_log(LOG_WARNING, "%s: The channel has no line. giving up.\n", c->designator);
464 return -2;
465 }
466
467 if (sccp_channel_isAnswering(c)) {
468 sccp_log(DEBUGCAT_CHANNEL)(VERBOSE_PREFIX_2 "%s: The channel is already being answered. canceling forward\n", c->designator);
469 return -3;
470 }
471
472 pbx_channel_lock(c->owner);
473 PBX_CHANNEL_TYPE * forwarder = pbx_channel_ref(c->owner);
474 pbx_channel_unlock(c->owner);
475
476 if(!forwarder || c->isHangingUp || pbx_check_hangup_locked(forwarder)) {
477 pbx_log(LOG_WARNING, "%s: The channel was already hungup. giving up.\n", c->designator);
478 pbx_channel_unref(forwarder);
479 return -4;
480 }
481
482 boolean_t bypassCallForward = !sccp_strlen_zero(pbx_builtin_getvar_helper(forwarder, "BYPASS_CFWD"));
483
484 sccp_linedevice_t * ld = NULL;
485 SCCP_LIST_LOCK(&l->devices);
486 int num_devices = SCCP_LIST_GETSIZE(&l->devices);
487 SCCP_LIST_TRAVERSE(&l->devices, ld, list) {
488 /* do we have cfwd enabled? */
489 if(ld->cfwd[SCCP_CFWD_NOANSWER].enabled && !sccp_strlen_zero(ld->cfwd[SCCP_CFWD_NOANSWER].number) && !bypassCallForward) {
490 if(num_devices == 1) {
491 /* when single line -> use asterisk functionality directly, without creating new channel + masquerade */
492 sccp_log(DEBUGCAT_PBX)("%s: Redirecting call to callforward noanswer:%s\n", c->designator, ld->cfwd[SCCP_CFWD_NOANSWER].number);
493 #if CS_AST_CONTROL_REDIRECTING
494 iPbx.queue_control(forwarder, AST_CONTROL_REDIRECTING);
495 #endif
496 pbx_channel_call_forward_set(forwarder, ld->cfwd[SCCP_CFWD_NOANSWER].number);
497 sccp_device_sendcallstate(ld->device, ld->lineInstance, c->callid, SKINNY_CALLSTATE_INTERCOMONEWAY, SKINNY_CALLPRIORITY_NORMAL, SKINNY_CALLINFO_VISIBILITY_DEFAULT);
498 sccp_channel_send_callinfo(ld->device, c);
499 iPbx.set_owner(c, NULL);
500 break; //! \todo currently using only the first match.
501 } else {
502 /* shared line -> create a temp channel to call forward destination and tie them together */
503 pbx_log(LOG_NOTICE, "%s: handle cfwd to %s for line %s\n", ld->device->id, ld->cfwd[SCCP_CFWD_NOANSWER].number, l->name);
504 sccp_channel_forward(c, ld, ld->cfwd[SCCP_CFWD_NOANSWER].number);
505 }
506 }
507 }
508 SCCP_LIST_UNLOCK(&l->devices);
509 pbx_channel_unref(forwarder);
510 return 0;
511 }
512
513 /*!
514 * \brief Handle Hangup Request by Asterisk
515 * \param channel SCCP Channel
516 * \return Success as int
517 *
518 * \callgraph
519 * \callergraph
520 *
521 * \called_from_asterisk via sccp_wrapper_asterisk.._hangup
522 *
523 * \note sccp_channel should be retained in calling function
524 */
525
sccp_pbx_hangup(constChannelPtr channel)526 channelPtr sccp_pbx_hangup(constChannelPtr channel)
527 {
528
529 /* here the ast channel is locked */
530 // sccp_log((DEBUGCAT_CORE)) (;VERBOSE_PREFIX_3 "SCCP: Asterisk request to hangup channel %s\n", iPbx.getChannelName(c));
531 (void) ATOMIC_DECR(&GLOB(usecnt), 1, &GLOB(usecnt_lock));
532
533 pbx_update_use_count();
534
535 AUTO_RELEASE(sccp_channel_t, c , sccp_channel_retain(channel));
536 if (!c) {
537 sccp_log_and((DEBUGCAT_PBX + DEBUGCAT_CHANNEL)) (VERBOSE_PREFIX_3 "SCCP: Asked to hangup channel. SCCP channel already deleted\n");
538 return NULL;
539 }
540 c->isHangingUp = TRUE;
541 sccp_log_and((DEBUGCAT_PBX + DEBUGCAT_CHANNEL))(VERBOSE_PREFIX_3 "%s: Asked to hangup channel.\n", c->designator);
542
543 AUTO_RELEASE(sccp_device_t, d , sccp_channel_getDevice(c));
544 if(d && d->session) {
545 sccp_session_waitForPendingRequests(d->session);
546 /* if (
547 GLOB(remotehangup_tone) &&
548 SKINNY_DEVICE_RS_OK == sccp_device_getRegistrationState(d) &&
549 SCCP_DEVICESTATE_OFFHOOK == sccp_device_getDeviceState(d) &&
550 SCCP_CHANNELSTATE_IsConnected(c->state) &&
551 c == d->active_channel
552 ) {
553 c->setTone(c, GLOB(remotehangup_tone), SKINNY_TONEDIRECTION_USER);
554 }*/
555 }
556
557 AUTO_RELEASE(sccp_line_t, l , sccp_line_retain(c->line));
558
559 #ifdef CS_SCCP_CONFERENCE
560 if (c && c->conference) {
561 sccp_conference_release(&c->conference); /* explicit release required here */
562 }
563 if (d && d->conference) {
564 sccp_conference_release(&d->conference); /* explicit release required here */
565 }
566 #endif // CS_SCCP_CONFERENCE
567 if (c->rtp.audio.instance || c->rtp.video.instance) {
568 sccp_channel_closeAllMediaTransmitAndReceive(c);
569 }
570
571 // removing scheduled dialing
572 sccp_channel_stop_schedule_digittimout(c);
573 sccp_channel_stop_schedule_cfwd_noanswer(c);
574
575 sccp_log((DEBUGCAT_PBX + DEBUGCAT_CHANNEL))(VERBOSE_PREFIX_3 "%s: Current pbxchannelstate %s(%d)\n", c->designator, sccp_channelstate2str(c->state), c->state);
576
577 /* end callforwards */
578 sccp_channel_end_forwarding_channel(c);
579
580 /* cancel transfer if in progress */
581 if(d) {
582 sccp_channel_transfer_cancel(d, c);
583 }
584
585 if (l) {
586 /* remove call from transferee, transferer */
587 sccp_linedevice_t * ld = NULL;
588 SCCP_LIST_LOCK(&l->devices);
589 SCCP_LIST_TRAVERSE(&l->devices, ld, list) {
590 AUTO_RELEASE(sccp_device_t, tmpDevice, sccp_device_retain(ld->device));
591 if(!d && tmpDevice && SKINNY_DEVICE_RS_OK == sccp_device_getRegistrationState(tmpDevice)) {
592 d = sccp_device_retain(tmpDevice);
593 }
594 if (tmpDevice) {
595 sccp_channel_transfer_release(tmpDevice, c); /* explicit release required here */
596 }
597 }
598 SCCP_LIST_UNLOCK(&l->devices);
599 sccp_line_removeChannel(l, c);
600 }
601
602 if (d) {
603 if (d->monitorFeature.status & SCCP_FEATURE_MONITOR_STATE_ACTIVE) {
604 d->monitorFeature.status &= ~SCCP_FEATURE_MONITOR_STATE_ACTIVE;
605 sccp_log((DEBUGCAT_PBX)) (VERBOSE_PREFIX_3 "%s: Reset monitor state after hangup\n", DEV_ID_LOG(d));
606 sccp_feat_changed(d, NULL, SCCP_FEATURE_MONITOR);
607 }
608
609 if (SCCP_CHANNELSTATE_DOWN != c->state && SCCP_CHANNELSTATE_ONHOOK != c->state) {
610 sccp_indicate(d, c, SCCP_CHANNELSTATE_ONHOOK);
611 }
612
613 /* requesting statistics */
614 sccp_channel_StatisticsRequest(c);
615 sccp_channel_clean(c);
616 return c; /* returning unretained so that sccp_wrapper_asterisk113_hangup can clear out the last reference */
617 }
618 return NULL;
619 }
620
621 /*!
622 * \brief Asterisk Channel as been answered by remote
623 * \note we have no bridged channel at this point
624 *
625 * \param channel SCCCP channel
626 * \return Success as int
627 *
628 * \callgraph
629 * \callergraph
630 *
631 * \called_from_asterisk
632 *
633 * \todo masquarade does not succeed when forwarding to a dialplan extension which starts with PLAYBACK (Is this still the case, i think this might have been resolved ?? - DdG -)
634 */
sccp_pbx_remote_answer(constChannelPtr channel)635 int sccp_pbx_remote_answer(constChannelPtr channel)
636 {
637 int res = -1;
638
639 /* \todo perhaps we should lock channel here. */
640 AUTO_RELEASE(sccp_channel_t, c , sccp_channel_retain(channel));
641 if(!c || !c->owner) {
642 return res;
643 }
644 sccp_log((DEBUGCAT_PBX))(VERBOSE_PREFIX_2 "%s: (%s) Remote end has answered the call.\n", c->designator, __func__);
645
646 sccp_channel_stop_schedule_cfwd_noanswer(c);
647
648 // sccp_log((DEBUGCAT_PBX)) (VERBOSE_PREFIX_3 "%s: sccp_pbx_answer checking parent channel\n", c->currentDeviceId);
649 if (c->parentChannel) { // containing a retained channel, final release at the end
650 /* we are a forwarded call, bridge me with my parent (the forwarded channel will take the place of the forwarder.) */
651 sccp_log((DEBUGCAT_PBX))(VERBOSE_PREFIX_3 "%s: (%s) handling forwarded call\n", c->designator, __func__);
652
653 pbx_channel_lock(c->parentChannel->owner);
654 PBX_CHANNEL_TYPE * forwarder = pbx_channel_ref(c->parentChannel->owner);
655 pbx_channel_unlock(c->parentChannel->owner);
656
657 pbx_channel_lock(c->owner);
658 PBX_CHANNEL_TYPE * tmp_channel = pbx_channel_ref(c->owner);
659 pbx_channel_unlock(c->owner);
660
661 const char * destinationChannelName = pbx_builtin_getvar_helper(tmp_channel, CS_BRIDGEPEERNAME);
662
663 PBX_CHANNEL_TYPE * destination = NULL;
664 if(sccp_strlen_zero(destinationChannelName) || !iPbx.getChannelByName(destinationChannelName, &destination)) {
665 pbx_log(LOG_NOTICE, "%s: (%s) Could not retrieve channel for destination: %s", c->designator, __func__, destinationChannelName);
666 return -2;
667 }
668 /*
669 if (iPbx.getChannelAppl(c)) {
670 sccp_log_and((DEBUGCAT_PBX + DEBUGCAT_HIGH)) (VERBOSE_PREFIX_3 "%s: (sccp_pbx_answer) %s bridging to dialplan application %s\n", c->currentDeviceId, iPbx.getChannelName(c), iPbx.getChannelAppl(c));
671 }
672 */
673 sccp_log(DEBUGCAT_PBX)(VERBOSE_PREFIX_3 "\n"
674 "\tendpoint1 | bridge | endpoint2 | comment\n"
675 "\t=================== | ================== | ================== | =================\n"
676 "\t%-20.20s| primary_call |%20.20s| creates tmp_channel in sccp_pbx_call to call forwarding destination\n"
677 "\t%-20.20s| temp_bridge |%20.20s| masquerade on answer of endpoint 2\n"
678 "\t------------------- | ------------------ | ------------------ | <-- masquerade temp_bridge:endpoint2 -> primary_call:endpoint2\n"
679 "\t%-20.20s| primary call |%20.20s| after masquerading, hangup temp_bridge:temp_channel\n",
680 "incoming", pbx_channel_name(forwarder), pbx_channel_name(tmp_channel), destinationChannelName, "incoming", destinationChannelName);
681 do {
682 // retrieve channel by name which will replace in the forwarded channel
683 sccp_channel_release(&c->parentChannel);
684 if(destination) {
685 sccp_log((DEBUGCAT_PBX))(VERBOSE_PREFIX_3 "%s: (%s) handling forwarded call. Replace %s with %s.\n", c->designator, __func__, pbx_channel_name(forwarder), pbx_channel_name(destination));
686 #if ASTERISK_VERSION_GROUP < 116
687 /* set the channel and the bridge to state UP to fix problem with fast pickup / autoanswer */
688 pbx_setstate(tmp_channel, AST_STATE_UP);
689 pbx_setstate(destination, AST_STATE_UP);
690 #endif
691 if(!iPbx.masqueradeHelper(destination, forwarder)) {
692 pbx_log(LOG_ERROR, "%s: (%s) Failed to masquerade bridge into forwarded channel\n", c->designator, __func__);
693 if(destination) {
694 pbx_channel_unref(destination);
695 }
696 res = -3;
697 break;
698 }
699 #if ASTERISK_VERSION_GROUP > 106
700 // Note: destination has taken the place of forwarder
701 pbx_indicate(forwarder, AST_CONTROL_CONNECTED_LINE);
702 #endif
703 sccp_log((DEBUGCAT_PBX))(VERBOSE_PREFIX_4 "%s: (%s) Masqueraded into %s\n", c->designator, __func__, pbx_channel_name(forwarder));
704 res = 0;
705 } else {
706 pbx_log(LOG_ERROR, "%s: (%s) Could not retrieve forwarding channel by name:%s: -> Hangup\n", c->designator, __func__, destinationChannelName);
707 if(pbx_channel_state(tmp_channel) == AST_STATE_RING && pbx_channel_state(forwarder) == AST_STATE_DOWN && iPbx.getChannelPbx(c)) {
708 sccp_log((DEBUGCAT_PBX)) (VERBOSE_PREFIX_4 "SCCP: Receiver Hungup: (hasPBX: %s)\n", iPbx.getChannelPbx(c) ? "yes" : "no");
709 pbx_channel_set_hangupcause(forwarder, AST_CAUSE_CALL_REJECTED);
710 } else {
711 pbx_log(LOG_ERROR, "%s: (%s) We did not find bridge channel for call forwarding call. Hangup\n", c->currentDeviceId, __func__);
712 pbx_channel_set_hangupcause(forwarder, AST_CAUSE_REQUESTED_CHAN_UNAVAIL);
713 sccp_channel_endcall(c);
714 }
715 pbx_channel_set_hangupcause(forwarder, AST_CAUSE_REQUESTED_CHAN_UNAVAIL);
716 pbx_channel_unref(forwarder);
717 if(destination) {
718 pbx_channel_unref(destination);
719 }
720 res = -4;
721 }
722 } while(0);
723 if(tmp_channel) {
724 pbx_channel_unref(tmp_channel);
725 }
726 } else {
727 sccp_log((DEBUGCAT_CORE))(VERBOSE_PREFIX_3 "%s: (%s) Outgoing call %s being answered by remote party\n", c->currentDeviceId, __func__, iPbx.getChannelName(c));
728 AUTO_RELEASE(sccp_device_t, d , sccp_channel_getDevice(c));
729 if (d) {
730 const char * application = ast_channel_appl (c->owner);
731 if (application && sccp_strequals (application, "ParkedCall")) {
732 sccp_log ((DEBUGCAT_CORE)) (VERBOSE_PREFIX_3 "%s: !! retrieving parked call !!\n", c->designator);
733 sccp_channel_setChannelstate (c, SCCP_CHANNELSTATE_CALLPARK);
734 pbx_builtin_setvar_helper (c->owner, "_PARK_RETRIEVER", c->designator);
735 }
736 #if CS_SCCP_CONFERENCE
737 sccp_indicate(d, c, d->conference ? SCCP_CHANNELSTATE_CONNECTEDCONFERENCE : SCCP_CHANNELSTATE_CONNECTED);
738 #else
739 sccp_indicate(d, c, SCCP_CHANNELSTATE_CONNECTED);
740 #endif
741 /** check for monitor request */
742 if((d->monitorFeature.status & SCCP_FEATURE_MONITOR_STATE_REQUESTED) && !(d->monitorFeature.status & SCCP_FEATURE_MONITOR_STATE_ACTIVE)) {
743 pbx_log(LOG_NOTICE, "%s: (%s) request monitor/record\n", d->id, __func__);
744 sccp_feat_monitor(d, NULL, 0, c);
745 }
746
747 sccp_log(DEBUGCAT_PBX)(VERBOSE_PREFIX_3 "%s: (%s) Switching to STATE_UP\n", c->designator, __func__);
748 iPbx.set_callstate(c, AST_STATE_UP);
749 res = 0;
750 }
751
752 if((sccp_rtp_getState(&c->rtp.video, SCCP_RTP_RECEPTION) & SCCP_RTP_STATUS_ACTIVE)) {
753 iPbx.queue_control(c->owner, AST_CONTROL_VIDUPDATE);
754 }
755 }
756 return res;
757 }
758
759 /*!
760 * \brief Allocate an Asterisk Channel
761 * \param channel SCCP Channel
762 * \param ids Void Character Pointer (either Empty / LinkedId / Channel ID, depending on the asterisk version)
763 * \param parentChannel SCCP Channel for which the channel was created
764 * \return 1 on Success as uint8_t
765 *
766 * \callgraph
767 * \callergraph
768 *
769 * \lock
770 * - usecnt_lock
771 */
sccp_pbx_channel_allocate(constChannelPtr channel,const void * ids,const PBX_CHANNEL_TYPE * parentChannel)772 boolean_t sccp_pbx_channel_allocate(constChannelPtr channel, const void * ids, const PBX_CHANNEL_TYPE * parentChannel)
773 {
774 PBX_CHANNEL_TYPE * tmp = NULL;
775 AUTO_RELEASE(sccp_channel_t, c , sccp_channel_retain(channel));
776 AUTO_RELEASE(sccp_device_t, d , NULL);
777
778 if (!c) {
779 return FALSE;
780 }
781 pbx_assert(c->owner == NULL); // prevent calling this function when the channel already has a pbx channel
782
783 #ifndef CS_AST_CHANNEL_HAS_CID
784 char cidtmp[256];
785
786 memset(&cidtmp, 0, sizeof(cidtmp));
787 #endif // CS_AST_CHANNEL_HAS_CID
788
789 AUTO_RELEASE(sccp_line_t, l , sccp_line_retain(c->line));
790 if (!l) {
791 sccp_log((DEBUGCAT_CORE)) (VERBOSE_PREFIX_3 "SCCP: (sccp_pbx_channel_allocate) Unable to find line for channel %s\n", c->designator);
792 pbx_log(LOG_ERROR, "SCCP: Unable to allocate asterisk channel... returning 0\n");
793 return FALSE;
794 }
795
796 sccp_log((DEBUGCAT_PBX + DEBUGCAT_CHANNEL)) (VERBOSE_PREFIX_3 "SCCP: (pbx_channel_allocate) try to allocate %s channel on line: %s\n", skinny_calltype2str(c->calltype), l->name);
797 /* Don't hold a sccp pvt lock while we allocate a channel */
798 char s1[512];
799
800 char s2[512];
801
802 char cid_name[StationMaxNameSize] = {0};
803 char cid_num[StationMaxDirnumSize] = {0};
804 {
805 sccp_linedevice_t * ld = NULL;
806 // if ((d = sccp_channel_getDevice(c))) {
807 d = sccp_channel_getDevice(c) /*ref_replace*/;
808 if(d) {
809 SCCP_LIST_LOCK(&l->devices);
810 SCCP_LIST_TRAVERSE(&l->devices, ld, list) {
811 if(ld->device == d) {
812 break;
813 }
814 }
815 SCCP_LIST_UNLOCK(&l->devices);
816 } else if(SCCP_LIST_GETSIZE(&l->devices) > 0) {
817 SCCP_LIST_LOCK(&l->devices);
818 ld = SCCP_LIST_FIRST(&l->devices);
819 SCCP_LIST_UNLOCK(&l->devices);
820 if(ld && ld->device) {
821 d = sccp_device_retain(ld->device) /*ref_replace*/; // ugly hack just picking the first one !
822 }
823 }
824
825 if(!ld) {
826 pbx_log(LOG_NOTICE, "%s: Could not find an appropriate ld to assign this channel to. Line:%s exists, but was not assigned to any device (yet). We should give up here.\n", c->designator, l->name);
827 goto error_exit;
828 }
829
830 sccp_callinfo_t *ci = sccp_channel_getCallInfo(c);
831 if(ld->subscriptionId.replaceCid) {
832 snprintf(cid_num, StationMaxDirnumSize, "%s", sccp_strlen_zero(ld->subscriptionId.number) ? l->cid_num : ld->subscriptionId.number);
833 snprintf(cid_name, StationMaxNameSize, "%s", sccp_strlen_zero(ld->subscriptionId.name) ? l->cid_name : ld->subscriptionId.name);
834 } else {
835 snprintf(cid_num, StationMaxDirnumSize, "%s%s", l->cid_num, sccp_strlen_zero(ld->subscriptionId.number) ? "" : ld->subscriptionId.number);
836 snprintf(cid_name, StationMaxNameSize, "%s%s", l->cid_name, sccp_strlen_zero(ld->subscriptionId.name) ? "" : ld->subscriptionId.name);
837 }
838 switch (c->calltype) {
839 case SKINNY_CALLTYPE_INBOUND:
840 iCallInfo.Setter(ci, SCCP_CALLINFO_CALLEDPARTY_NAME, &cid_name, SCCP_CALLINFO_CALLEDPARTY_NUMBER, &cid_num, SCCP_CALLINFO_KEY_SENTINEL);
841 break;
842 case SKINNY_CALLTYPE_FORWARD:
843 iCallInfo.Setter(ci,
844 SCCP_CALLINFO_CALLINGPARTY_NAME, &cid_name,
845 SCCP_CALLINFO_CALLINGPARTY_NUMBER, &cid_num,
846 SCCP_CALLINFO_LAST_REDIRECTINGPARTY_NAME, &cid_name,
847 SCCP_CALLINFO_LAST_REDIRECTINGPARTY_NUMBER, &cid_num,
848 SCCP_CALLINFO_LAST_REDIRECT_REASON, 4,
849 SCCP_CALLINFO_KEY_SENTINEL);
850 break;
851 case SKINNY_CALLTYPE_OUTBOUND:
852 iCallInfo.Setter(ci,
853 SCCP_CALLINFO_CALLINGPARTY_NAME, &cid_name,
854 SCCP_CALLINFO_CALLINGPARTY_NUMBER, &cid_num,
855 //SCCP_CALLINFO_ORIG_CALLINGPARTY_NAME, &cid_name,
856 //SCCP_CALLINFO_ORIG_CALLINGPARTY_NUMBER, &cid_num,
857 SCCP_CALLINFO_LAST_REDIRECTINGPARTY_NAME, &cid_name,
858 SCCP_CALLINFO_LAST_REDIRECTINGPARTY_NUMBER, &cid_num,
859 SCCP_CALLINFO_LAST_REDIRECT_REASON, 0,
860 SCCP_CALLINFO_KEY_SENTINEL);
861 break;
862 case SKINNY_CALLTYPE_SENTINEL:
863 break;
864 }
865
866 // make sure preferences only contains the codecs that this channel is capable of
867 if (SCCP_LIST_GETSIZE(&l->devices) == 1 && d) { // singleline
868 //sccp_line_copyCodecSetsFromLineToChannel(l, d, c);
869 sccp_codec_reduceSet(c->preferences.audio, d->capabilities.audio);
870 sccp_codec_reduceSet(c->preferences.video, d->capabilities.video);
871 } else {
872 //sccp_line_copyCodecSetsFromLineToChannel(l, NULL, c); // sharedline
873 sccp_codec_reduceSet(c->preferences.audio, c->capabilities.audio);
874 sccp_codec_reduceSet(c->preferences.video, c->capabilities.video);
875 }
876
877 if (c->preferences.audio[0] == SKINNY_CODEC_NONE || c->capabilities.audio[0] == SKINNY_CODEC_NONE) {
878 pbx_log(LOG_ERROR, "%s: Expect trouble ahead.\n"
879 "The audio preferences:%s of this channel have been reduced to nothing.\n"
880 "Because they are not compatible with this %s capabilities:%s.\n"
881 "Please fix your config. Ending Call !.\n",
882 c->designator,
883 sccp_codec_multiple2str(s1, sizeof(s1) - 1, c->preferences.audio, SKINNY_MAX_CAPABILITIES),
884 l->preferences_set_on_line_level ? "line's" : "device's",
885 sccp_codec_multiple2str(s2, sizeof(s2) - 1, c->capabilities.audio, SKINNY_MAX_CAPABILITIES));
886 goto error_exit;
887 }
888 }
889 sccp_log((DEBUGCAT_PBX + DEBUGCAT_CHANNEL)) (VERBOSE_PREFIX_3 "SCCP: cid_num: %s\n", cid_num);
890 sccp_log((DEBUGCAT_PBX + DEBUGCAT_CHANNEL)) (VERBOSE_PREFIX_3 "SCCP: cid_name: %s\n", cid_name);
891 sccp_log((DEBUGCAT_PBX + DEBUGCAT_CHANNEL)) (VERBOSE_PREFIX_3 "SCCP: accountcode: %s\n", l->accountcode);
892 sccp_log((DEBUGCAT_PBX + DEBUGCAT_CHANNEL)) (VERBOSE_PREFIX_3 "SCCP: exten: %s\n", c->dialedNumber);
893 sccp_log((DEBUGCAT_PBX + DEBUGCAT_CHANNEL)) (VERBOSE_PREFIX_3 "SCCP: context: %s\n", l->context);
894 sccp_log((DEBUGCAT_PBX + DEBUGCAT_CHANNEL)) (VERBOSE_PREFIX_3 "SCCP: amaflags: %d\n", (int)l->amaflags);
895 sccp_log((DEBUGCAT_PBX + DEBUGCAT_CHANNEL)) (VERBOSE_PREFIX_3 "SCCP: chan/call: %s\n", c->designator);
896 sccp_log((DEBUGCAT_PBX + DEBUGCAT_CHANNEL)) (VERBOSE_PREFIX_3 "SCCP: combined audio caps: %s\n", sccp_codec_multiple2str(s1, sizeof(s1) - 1, c->capabilities.audio, SKINNY_MAX_CAPABILITIES));
897 sccp_log((DEBUGCAT_PBX + DEBUGCAT_CHANNEL)) (VERBOSE_PREFIX_3 "SCCP: reduced audio prefs: %s\n", sccp_codec_multiple2str(s1, sizeof(s1) - 1, c->preferences.audio, SKINNY_MAX_CAPABILITIES));
898 sccp_log((DEBUGCAT_PBX + DEBUGCAT_CHANNEL)) (VERBOSE_PREFIX_3 "SCCP: combined video caps: %s\n", sccp_codec_multiple2str(s1, sizeof(s1) - 1, c->capabilities.video, SKINNY_MAX_CAPABILITIES));
899 sccp_log((DEBUGCAT_PBX + DEBUGCAT_CHANNEL)) (VERBOSE_PREFIX_3 "SCCP: reduced video prefs: %s\n", sccp_codec_multiple2str(s1, sizeof(s1) - 1, c->preferences.video, SKINNY_MAX_CAPABILITIES));
900 /*
901 // this should not be done here at this moment, leaving it to alloc_pbxChannel to sort out.
902 if (c->calltype == SKINNY_CALLTYPE_INBOUND) {
903 if (c->remoteCapabilities.audio[0] != SKINNY_CODEC_NONE) {
904 sccp_log((DEBUGCAT_PBX + DEBUGCAT_CHANNEL)) (VERBOSE_PREFIX_3 "SCCP: remote audio prefs: \"%s\"\n", sccp_codec_multiple2str(s1, sizeof(s1) - 1, c->remoteCapabilities.audio, SKINNY_MAX_CAPABILITIES));
905 skinny_codec_t ordered_audio_prefs[SKINNY_MAX_CAPABILITIES] = {SKINNY_CODEC_NONE};
906 memcpy(&ordered_audio_prefs, c->remoteCapabilities.audio, sizeof(ordered_audio_prefs));
907 sccp_codec_reduceSet(ordered_audio_prefs, c->preferences.audio);
908 memcpy(&c->preferences.audio, ordered_audio_prefs, sizeof(c->preferences.audio));
909 sccp_log((DEBUGCAT_PBX + DEBUGCAT_CHANNEL)) (VERBOSE_PREFIX_3 "SCCP: set audio prefs: \"%s\"\n", sccp_codec_multiple2str(s2, sizeof(s2) - 1, c->preferences.audio, SKINNY_MAX_CAPABILITIES));
910 }
911
912 if (c->remoteCapabilities.video[0] != SKINNY_CODEC_NONE && (d ? sccp_device_isVideoSupported(d) : TRUE)) {
913 sccp_log((DEBUGCAT_PBX + DEBUGCAT_CHANNEL)) (VERBOSE_PREFIX_3 "SCCP: remote video prefs: \"%s\"\n", sccp_codec_multiple2str(s1, sizeof(s1) - 1, c->remoteCapabilities.video, SKINNY_MAX_CAPABILITIES));
914 skinny_codec_t ordered_video_prefs[SKINNY_MAX_CAPABILITIES] = {SKINNY_CODEC_NONE};
915 memcpy(&ordered_video_prefs, c->remoteCapabilities.video, sizeof(ordered_video_prefs));
916 sccp_codec_reduceSet(ordered_video_prefs, c->preferences.video);
917 memcpy(&c->preferences.video, ordered_video_prefs, sizeof(c->preferences.video));
918 sccp_log((DEBUGCAT_PBX + DEBUGCAT_CHANNEL)) (VERBOSE_PREFIX_3 "SCCP: set video prefs: \"%s\"\n", sccp_codec_multiple2str(s2, sizeof(s2) - 1, c->preferences.video, SKINNY_MAX_CAPABILITIES));
919 }
920 }
921 */
922 if (!c->pbx_callid && c->calltype != SKINNY_CALLTYPE_INBOUND) {
923 c->pbx_callid = pbx_create_callid();
924 }
925 /* This should definitely fix CDR */
926 iPbx.alloc_pbxChannel(c, ids, parentChannel, &tmp);
927
928 if (!tmp || !c->owner) {
929 pbx_log(LOG_ERROR, "%s: Unable to allocate asterisk channel on line %s\n", c->designator, l->name);
930 goto error_exit;
931 }
932 iPbx.setChannelName(c, c->designator);
933
934 // \todo: Bridge?
935 // \todo: Transfer?
936
937 (void) ATOMIC_INCR(&GLOB(usecnt), 1, &GLOB(usecnt_lock));
938
939 pbx_update_use_count();
940
941 if (iPbx.set_callerid_number) {
942 iPbx.set_callerid_number(c->owner, cid_num);
943 }
944 if (iPbx.set_callerid_ani) {
945 iPbx.set_callerid_ani(c->owner, cid_num);
946 }
947 if (iPbx.set_callerid_name) {
948 iPbx.set_callerid_name(c->owner, cid_name);
949 }
950
951 /* call ast_channel_call_forward_set with the forward destination if this device is forwarded */
952 if (SCCP_LIST_GETSIZE(&l->devices) == 1) {
953 sccp_linedevice_t * ld = NULL;
954
955 SCCP_LIST_LOCK(&l->devices);
956 SCCP_LIST_TRAVERSE(&l->devices, ld, list) {
957 if(ld->line == l) {
958 if(ld->cfwd[SCCP_CFWD_ALL].enabled) {
959 sccp_log((DEBUGCAT_PBX))(VERBOSE_PREFIX_3 "%s: ast call forward channel_set: %s\n", c->designator, ld->cfwd[SCCP_CFWD_ALL].number);
960 iPbx.setChannelCallForward(c, ld->cfwd[SCCP_CFWD_ALL].number);
961 } else if(ld->cfwd[SCCP_CFWD_BUSY].enabled && (sccp_device_getDeviceState(ld->device) != SCCP_DEVICESTATE_ONHOOK || sccp_device_getActiveAccessory(ld->device))) {
962 sccp_log((DEBUGCAT_PBX))(VERBOSE_PREFIX_3 "%s: ast call forward channel_set: %s\n", c->designator, ld->cfwd[SCCP_CFWD_BUSY].number);
963 iPbx.setChannelCallForward(c, ld->cfwd[SCCP_CFWD_BUSY].number);
964 }
965 break;
966 }
967 }
968 SCCP_LIST_UNLOCK(&l->devices);
969 }
970
971 #if CS_SCCP_VIDEO
972 const char *VideoStr = pbx_builtin_getvar_helper(c->owner, "SCCP_VIDEO_MODE");
973 if (VideoStr && !sccp_strlen_zero(VideoStr)) {
974 sccp_channel_setVideoMode(c, VideoStr);
975 }
976 #endif
977 /* asterisk needs the native formats bevore dialout, otherwise the next channel gets the whole AUDIO_MASK as requested format
978 * chan_sip dont like this do sdp processing */
979 //iPbx.set_nativeAudioFormats(c, c->preferences.audio, ARRAY_LEN(c->preferences.audio));
980
981 /* start audio rtp server early, to facilitate choosing codecs via sdp */
982 if (d) {
983 if (c->calltype == SKINNY_CALLTYPE_OUTBOUND) {
984 if (!c->rtp.audio.instance && !sccp_rtp_createServer(d, c, SCCP_RTP_AUDIO)) {
985 pbx_log(LOG_WARNING, "%s: Error opening RTP instance for channel %s\n", d->id, c->designator);
986 goto error_exit;
987 }
988 /*
989 #if CS_SCCP_VIDEO
990 if (sccp_channel_getVideoMode(c) != SCCP_VIDEO_MODE_OFF && sccp_device_isVideoSupported(d) && c->preferences.video[0] != SKINNY_CODEC_NONE && !c->rtp.video.instance &&
991 !sccp_rtp_createServer(d, c, SCCP_RTP_VIDEO)) { pbx_log(LOG_WARNING, "%s: Error opening VRTP instance for channel %s\n", d->id, c->designator); sccp_channel_setVideoMode(c, "off");
992 }
993 #endif
994 */
995 }
996 // export sccp informations in asterisk dialplan
997 pbx_builtin_setvar_helper(tmp, "SCCP_DEVICE_MAC", d->id);
998 struct sockaddr_storage sas = { 0 };
999 sccp_session_getSas(d->session, &sas);
1000 pbx_builtin_setvar_helper(tmp, "SCCP_DEVICE_IP", d->session ? sccp_netsock_stringify_addr(&sas) : "");
1001 pbx_builtin_setvar_helper(tmp, "SCCP_DEVICE_TYPE", skinny_devicetype2str(d->skinny_type));
1002 }
1003 sccp_log((DEBUGCAT_PBX + DEBUGCAT_CHANNEL)) (VERBOSE_PREFIX_3 "%s: Allocated asterisk channel %s\n", (l) ? l->id : "(null)", c->designator);
1004
1005 return TRUE;
1006
1007 error_exit:
1008 if(c) {
1009 pbx_log(LOG_WARNING, "%s: (pbx_channel_allocate) Unable to allocate a new channel for line %s\n -> Hanging up call.", DEV_ID_LOG(d), l->name);
1010 if(c->owner) {
1011 if(d) {
1012 sccp_indicate(d, c, SCCP_CHANNELSTATE_CONGESTION);
1013 }
1014 sccp_channel_endcall(c);
1015 } else {
1016 if(d) {
1017 sccp_indicate(d, channel, SCCP_CHANNELSTATE_ONHOOK);
1018 }
1019 if(c->line) {
1020 sccp_line_removeChannel(c->line, c);
1021 }
1022 sccp_channel_clean(c);
1023 sccp_channel_release(&c);
1024 }
1025 }
1026 return FALSE;
1027 }
1028
1029 /*!
1030 * \brief Schedule Asterisk Dial
1031 * \param data Data as constant
1032 * \return Success as int
1033 *
1034 * \called_from_asterisk
1035 */
sccp_pbx_sched_dial(const void * data)1036 int sccp_pbx_sched_dial(const void * data)
1037 {
1038 AUTO_RELEASE(sccp_channel_t, channel, sccp_channel_retain(data));
1039
1040 if(channel) {
1041 if ((ATOMIC_FETCH(&channel->scheduler.deny, &channel->scheduler.lock) == 0) && channel->scheduler.hangup_id == -1) {
1042 channel->scheduler.digittimeout_id = -3; /* prevent further digittimeout scheduling */
1043 if (channel->owner && !iPbx.getChannelPbx(channel) && !sccp_strlen_zero(channel->dialedNumber)) {
1044 sccp_log((DEBUGCAT_CORE)) (VERBOSE_PREFIX_1 "SCCP: Timeout for call '%s'. Going to dial '%s'\n", channel->designator, channel->dialedNumber);
1045 sccp_pbx_softswitch(channel);
1046 } else {
1047 sccp_log((DEBUGCAT_CORE)) (VERBOSE_PREFIX_1 "SCCP: Timeout for call '%s'. Nothing to dial -> INVALIDNUMBER\n", channel->designator);
1048 channel->dialedNumber[0] = '\0';
1049 sccp_indicate(NULL, channel, SCCP_CHANNELSTATE_INVALIDNUMBER);
1050 }
1051 }
1052 sccp_channel_release((sccp_channel_t **)&data); // release channel retained in scheduled event
1053 }
1054 return 0; // return 0 to release schedule !
1055 }
1056
1057 /*!
1058 * \brief Asterisk Helper
1059 * \param c SCCP Channel as sccp_channel_t
1060 * \return Success as int
1061 */
sccp_pbx_helper(constChannelPtr c)1062 sccp_extension_status_t sccp_pbx_helper(constChannelPtr c)
1063 {
1064 sccp_extension_status_t extensionStatus = 0;
1065 int dialedLen = sccp_strlen(c->dialedNumber);
1066
1067 if (dialedLen > 1) {
1068 if (GLOB(recorddigittimeoutchar) && GLOB(digittimeoutchar) == c->dialedNumber[dialedLen - 1]) {
1069 /* we finished dialing with digit timeout char */
1070 sccp_log((DEBUGCAT_CORE)) (VERBOSE_PREFIX_2 "%s: We finished dialing with digit timeout char %s\n", c->designator, c->dialedNumber);
1071 return SCCP_EXTENSION_EXACTMATCH;
1072 }
1073 }
1074
1075 if ((c->softswitch_action != SCCP_SOFTSWITCH_GETCBARGEROOM) && (c->softswitch_action != SCCP_SOFTSWITCH_GETMEETMEROOM)
1076 #ifdef CS_SCCP_CONFERENCE
1077 && (c->softswitch_action != SCCP_SOFTSWITCH_GETCONFERENCEROOM)
1078 #endif
1079 ) {
1080
1081 //! \todo check overlap feature status -MC
1082 extensionStatus = iPbx.extension_status(c);
1083 AUTO_RELEASE(sccp_device_t, d , sccp_channel_getDevice(c));
1084
1085 if (d) {
1086 if (((d->overlapFeature.enabled && !extensionStatus) || (!d->overlapFeature.enabled && !extensionStatus))) {
1087 sccp_log((DEBUGCAT_CORE)) (VERBOSE_PREFIX_3 "%s: %s Matches More\n", c->designator, c->dialedNumber);
1088 return SCCP_EXTENSION_MATCHMORE;
1089 }
1090 sccp_log((DEBUGCAT_CORE)) (VERBOSE_PREFIX_3 "%s: %s Matches %s\n", c->designator, c->dialedNumber, extensionStatus == SCCP_EXTENSION_EXACTMATCH ? "Exactly" : "More");
1091 }
1092 return extensionStatus;
1093 }
1094 sccp_log((DEBUGCAT_CORE)) (VERBOSE_PREFIX_2 "%s: %s Does Exists\n", c->designator, c->dialedNumber);
1095 return SCCP_EXTENSION_NOTEXISTS;
1096 }
1097
1098 /*!
1099 * \brief Handle Soft Switch
1100 * \param channel SCCP Channel as sccp_channel_t
1101 * \todo clarify Soft Switch Function
1102 */
sccp_pbx_softswitch(constChannelPtr channel)1103 void * sccp_pbx_softswitch(constChannelPtr channel)
1104 {
1105 PBX_CHANNEL_TYPE * pbx_channel = NULL;
1106 PBX_VARIABLE_TYPE * v = NULL;
1107
1108 {
1109 AUTO_RELEASE(sccp_channel_t, c , sccp_channel_retain(channel));
1110
1111 if (!c) {
1112 pbx_log(LOG_ERROR, "SCCP: (sccp_pbx_softswitch) No <channel> available. Returning from dial thread.\n");
1113 goto EXIT_FUNC;
1114 }
1115 sccp_channel_stop_schedule_digittimout(c);
1116
1117 /* Reset Enbloc Dial Emulation */
1118 c->enbloc.deactivate = 0;
1119 c->enbloc.totaldigittime = 0;
1120 c->enbloc.totaldigittimesquared = 0;
1121 c->enbloc.digittimeout = GLOB(digittimeout);
1122
1123 /* prevent softswitch from being executed twice (Pavel Troller / 15-Oct-2010) */
1124 if (iPbx.getChannelPbx(c)) {
1125 sccp_log((DEBUGCAT_CORE)) (VERBOSE_PREFIX_3 "SCCP: (sccp_pbx_softswitch) PBX structure already exists. Dialing instead of starting.\n");
1126 /* If there are any digits, send them instead of starting the PBX */
1127 if (!sccp_strlen_zero(c->dialedNumber)) {
1128 if (iPbx.send_digits) {
1129 iPbx.send_digits(channel, c->dialedNumber);
1130 }
1131 sccp_channel_set_calledparty(c, NULL, c->dialedNumber);
1132 }
1133 goto EXIT_FUNC;
1134 }
1135
1136 if (!c->owner) {
1137 pbx_log(LOG_ERROR, "SCCP: (sccp_pbx_softswitch) No PBX <channel> available. Returning from dial thread.\n");
1138 goto EXIT_FUNC;
1139 }
1140 pbx_channel = pbx_channel_ref(c->owner);
1141
1142 /* we should just process outbound calls, let's check calltype */
1143 if (c->calltype != SKINNY_CALLTYPE_OUTBOUND && c->softswitch_action == SCCP_SOFTSWITCH_DIAL) {
1144 pbx_log(LOG_ERROR, "SCCP: (sccp_pbx_softswitch) This function is for outbound calls only. Exiting\n");
1145 goto EXIT_FUNC;
1146 }
1147
1148 /* assume d is the channel's device */
1149 /* does it exists ? */
1150 AUTO_RELEASE(sccp_device_t, d , sccp_channel_getDevice(c));
1151
1152 if (!d) {
1153 pbx_log(LOG_ERROR, "SCCP: (sccp_pbx_softswitch) No <device> available. Returning from dial thread. Exiting\n");
1154 goto EXIT_FUNC;
1155 }
1156
1157 if (pbx_check_hangup(pbx_channel)) {
1158 pbx_log(LOG_ERROR, "SCCP: (sccp_pbx_softswitch) Channel already hungup, no need to go any further. Exiting\n");
1159 sccp_indicate(d, c, SCCP_CHANNELSTATE_ONHOOK);
1160 goto EXIT_FUNC;
1161 }
1162
1163 /* we don't need to check for a device type but just if the device has an id, otherwise back home -FS */
1164 if (sccp_strlen_zero(d->id)) {
1165 pbx_log(LOG_ERROR, "SCCP: (sccp_pbx_softswitch) No <device> identifier available. Returning from dial thread. Exiting\n");
1166 goto EXIT_FUNC;
1167 }
1168
1169 AUTO_RELEASE(sccp_line_t, l , sccp_line_retain(c->line));
1170
1171 if (!l) {
1172 pbx_log(LOG_ERROR, "SCCP: (sccp_pbx_softswitch) No <line> available. Returning from dial thread. Exiting\n");
1173 c->hangupRequest(c);
1174 goto EXIT_FUNC;
1175 }
1176 uint8_t instance = sccp_device_find_index_for_line(d, l->name);
1177
1178 sccp_log((DEBUGCAT_CORE)) (VERBOSE_PREFIX_3 "%s: (sccp_pbx_softswitch) New call on line %s\n", DEV_ID_LOG(d), l->name);
1179
1180 /* assign callerid name and number */
1181 //sccp_channel_set_callingparty(c, l->cid_name, l->cid_num);
1182
1183 // we use shortenedNumber but why ???
1184 // If the timeout digit has been used to terminate the number
1185 // and this digit shall be included in the phone call history etc (recorddigittimeoutchar is true)
1186 // we still need to dial the number without the timeout char in the pbx
1187 // so that we don't dial strange extensions with a trailing characters.
1188 char shortenedNumber[256] = { '\0' };
1189 sccp_copy_string(shortenedNumber, c->dialedNumber, sizeof(shortenedNumber));
1190 unsigned int len = sccp_strlen(shortenedNumber);
1191
1192 pbx_assert(sccp_strlen(c->dialedNumber) == len);
1193
1194 if (len > 0 && GLOB(digittimeoutchar) == shortenedNumber[len - 1]) {
1195 shortenedNumber[len - 1] = '\0';
1196
1197 // If we don't record the timeoutchar in the logs, we remove it from the sccp channel structure
1198 // Later, the channel dialed number is used for directories, etc.,
1199 // and the shortened number is used for dialing the actual call via asterisk pbx.
1200 if (!GLOB(recorddigittimeoutchar)) {
1201 c->dialedNumber[len - 1] = '\0';
1202 }
1203 }
1204
1205 /* This will choose what to do */
1206 switch (c->softswitch_action) {
1207 case SCCP_SOFTSWITCH_GETFORWARDEXTEN:
1208 {
1209 sccp_cfwd_t type = (sccp_cfwd_t)c->ss_data;
1210 sccp_log((DEBUGCAT_PBX))(VERBOSE_PREFIX_3 "%s: (sccp_pbx_softswitch) Get Forward %s Extension\n", d->id, sccp_cfwd2str(type));
1211 if(!sccp_strlen_zero(shortenedNumber)) {
1212 c->setTone(c, SKINNY_TONE_ZIP, SKINNY_TONEDIRECTION_USER);
1213 sccp_line_cfwd(l, d, type, shortenedNumber);
1214 }
1215 sccp_channel_endcall(c);
1216 goto EXIT_FUNC; // leave simple switch without dial
1217 }
1218 case SCCP_SOFTSWITCH_ENDCALLFORWARD:
1219 {
1220 sccp_cfwd_t type = (sccp_cfwd_t)c->ss_data;
1221 sccp_log((DEBUGCAT_PBX))(VERBOSE_PREFIX_3 "%s: (sccp_pbx_softswitch) Clear Forward %s\n", d->id, sccp_cfwd2str(type));
1222 sccp_line_cfwd(l, d, type, NULL);
1223 switch(type) {
1224 case SCCP_CFWD_ALL:
1225 sccp_device_setLamp(d, SKINNY_STIMULUS_FORWARDALL, instance, SKINNY_LAMP_OFF);
1226 break;
1227 case SCCP_CFWD_BUSY:
1228 sccp_device_setLamp(d, SKINNY_STIMULUS_FORWARDBUSY, instance, SKINNY_LAMP_OFF);
1229 break;
1230 case SCCP_CFWD_NOANSWER:
1231 sccp_device_setLamp(d, SKINNY_STIMULUS_FORWARDNOANSWER, instance, SKINNY_LAMP_OFF);
1232 break;
1233 case SCCP_CFWD_NONE:
1234 case SCCP_CFWD_SENTINEL:
1235 default:
1236 pbx_log(LOG_ERROR, "%s: (sccp_pbx_softswitch) EndCallForward unknown CFWD_TYPE\n", d->id);
1237 }
1238 sccp_channel_endcall(c);
1239 goto EXIT_FUNC; // leave simple switch without dial
1240 }
1241 #ifdef CS_SCCP_PICKUP
1242 case SCCP_SOFTSWITCH_GETPICKUPEXTEN:
1243 sccp_log((DEBUGCAT_PBX)) (VERBOSE_PREFIX_3 "%s: (sccp_pbx_softswitch) Get Pickup Extension\n", d->id);
1244 sccp_dev_clearprompt(d, instance, c->callid);
1245
1246 if (!sccp_strlen_zero(shortenedNumber)) {
1247 sccp_log((DEBUGCAT_CORE)) (VERBOSE_PREFIX_3 "SCCP: (sccp_pbx_softswitch) Asterisk request to pickup exten '%s'\n", shortenedNumber);
1248 sccp_dev_displayprompt(d, instance, c->callid, SKINNY_DISP_PICKUP, GLOB(digittimeout));
1249 if (sccp_feat_directed_pickup(d, c, instance, shortenedNumber) == 0) {
1250 goto EXIT_FUNC;
1251 }
1252 }
1253 sccp_dev_displayprinotify(d, SKINNY_DISP_NO_CALL_AVAILABLE_FOR_PICKUP, SCCP_MESSAGE_PRIORITY_TIMEOUT, 5);
1254 if (c->state == SCCP_CHANNELSTATE_ONHOOK || c->state == SCCP_CHANNELSTATE_DOWN) {
1255 c->setTone(c, SKINNY_TONE_BEEPBONK, SKINNY_TONEDIRECTION_USER);
1256 }
1257 sccp_channel_schedule_hangup(c, 500);
1258 goto EXIT_FUNC; // leave simpleswitch without dial
1259 #endif // CS_SCCP_PICKUP
1260 #ifdef CS_SCCP_CONFERENCE
1261 case SCCP_SOFTSWITCH_GETCONFERENCEROOM:
1262 sccp_log((DEBUGCAT_PBX)) (VERBOSE_PREFIX_3 "%s: (sccp_pbx_softswitch) Conference request\n", d->id);
1263 if (c->owner && !pbx_check_hangup(c->owner)) {
1264 sccp_channel_setChannelstate(c, SCCP_CHANNELSTATE_PROCEED);
1265 iPbx.set_callstate(channel, AST_STATE_UP);
1266 if (!d->conference) {
1267 if (!(d->conference = sccp_conference_create(d, c))) {
1268 goto EXIT_FUNC;
1269 }
1270 } else {
1271 pbx_log(LOG_NOTICE, "%s: There is already a conference running on this device.\n", DEV_ID_LOG(d));
1272 sccp_channel_endcall(c);
1273 goto EXIT_FUNC;
1274 }
1275 sccp_log((DEBUGCAT_CORE)) (VERBOSE_PREFIX_3 "%s: (sccp_pbx_softswitch) Start Conference\n", d->id);
1276 sccp_feat_conference_start(d, instance, c);
1277 }
1278 goto EXIT_FUNC;
1279 #endif // CS_SCCP_CONFERENCE
1280 case SCCP_SOFTSWITCH_GETMEETMEROOM:
1281 sccp_log((DEBUGCAT_PBX)) (VERBOSE_PREFIX_3 "%s: (sccp_pbx_softswitch) Meetme request\n", d->id);
1282 if (!sccp_strlen_zero(shortenedNumber) && !sccp_strlen_zero(c->line->meetmenum)) {
1283 sccp_log((DEBUGCAT_CORE)) (VERBOSE_PREFIX_3 "%s: (sccp_pbx_softswitch) Meetme request for room '%s' on extension '%s'\n", d->id, shortenedNumber, c->line->meetmenum);
1284 if (c->owner && !pbx_check_hangup(c->owner)) {
1285 pbx_builtin_setvar_helper(c->owner, "SCCP_MEETME_ROOM", shortenedNumber);
1286 }
1287 sccp_copy_string(shortenedNumber, c->line->meetmenum, sizeof(shortenedNumber));
1288
1289 //sccp_copy_string(c->dialedNumber, SKINNY_DISP_CONFERENCE, sizeof(c->dialedNumber));
1290 sccp_log((DEBUGCAT_CORE)) (VERBOSE_PREFIX_3 "%s: (sccp_pbx_softswitch) Start Meetme Thread\n", d->id);
1291 sccp_feat_meetme_start(c); /* Copied from Federico Santulli */
1292 sccp_log((DEBUGCAT_CORE)) (VERBOSE_PREFIX_3 "%s: (sccp_pbx_softswitch) Meetme Thread Started\n", d->id);
1293 goto EXIT_FUNC;
1294 } else {
1295 // without a number we can also close the call. Isn't it true ?
1296 sccp_channel_endcall(c);
1297 goto EXIT_FUNC;
1298 }
1299 break;
1300 case SCCP_SOFTSWITCH_GETBARGEEXTEN:
1301 sccp_log((DEBUGCAT_PBX)) (VERBOSE_PREFIX_3 "%s: (sccp_pbx_softswitch) Get Barge Extension\n", d->id);
1302 sccp_dev_clearprompt(d, instance, c->callid);
1303 if (!sccp_strlen_zero(shortenedNumber)) {
1304 sccp_log((DEBUGCAT_CORE)) (VERBOSE_PREFIX_3 "SCCP: (sccp_pbx_softswitch) Asterisk request to barge exten '%s'\n", shortenedNumber);
1305 sccp_dev_displayprompt(d, instance, c->callid, SKINNY_DISP_BARGE, GLOB(digittimeout));
1306 if (sccp_feat_singleline_barge(c, shortenedNumber)) {
1307 //sccp_indicate(d, c, SCCP_CHANNELSTATE_INVALIDNUMBER);
1308 goto EXIT_FUNC;
1309 }
1310 }
1311 sccp_dev_displayprinotify(d, SKINNY_DISP_FAILED_TO_SETUP_BARGE, SCCP_MESSAGE_PRIORITY_TIMEOUT, 5);
1312 if (c->state == SCCP_CHANNELSTATE_ONHOOK || c->state == SCCP_CHANNELSTATE_DOWN) {
1313 c->setTone(c, SKINNY_TONE_BEEPBONK, SKINNY_TONEDIRECTION_USER);
1314 }
1315 sccp_channel_endcall(c);
1316 goto EXIT_FUNC; // leave simpleswitch without dial
1317 case SCCP_SOFTSWITCH_GETCBARGEROOM:
1318 sccp_log((DEBUGCAT_PBX)) (VERBOSE_PREFIX_3 "%s: (sccp_pbx_softswitch) Get Conference Barge Extension\n", d->id);
1319 // like we're dialing but we're not :)
1320 sccp_indicate(d, c, SCCP_CHANNELSTATE_DIALING);
1321 sccp_device_sendcallstate(d, instance, c->callid, SKINNY_CALLSTATE_PROCEED, SKINNY_CALLPRIORITY_LOW, SKINNY_CALLINFO_VISIBILITY_DEFAULT);
1322 sccp_channel_send_callinfo(d, c);
1323 sccp_dev_clearprompt(d, instance, c->callid);
1324 sccp_dev_displayprompt(d, instance, c->callid, SKINNY_DISP_CALL_PROCEED, GLOB(digittimeout));
1325 if (!sccp_strlen_zero(shortenedNumber)) {
1326 sccp_log((DEBUGCAT_CORE)) (VERBOSE_PREFIX_3 "%s: (sccp_pbx_softswitch) Device request to barge conference '%s'\n", d->id, shortenedNumber);
1327 if (sccp_feat_cbarge(c, shortenedNumber)) {
1328 sccp_indicate(d, c, SCCP_CHANNELSTATE_INVALIDNUMBER);
1329 }
1330 } else {
1331 // without a number we can also close the call. Isn't it true ?
1332 sccp_channel_endcall(c);
1333 }
1334 goto EXIT_FUNC; // leave simpleswitch without dial
1335 case SCCP_SOFTSWITCH_SENTINEL:
1336 sccp_log((DEBUGCAT_PBX)) (VERBOSE_PREFIX_3 "%s: (sccp_pbx_softswitch) Unknown Softswitch Request\n", d->id);
1337 goto EXIT_FUNC;
1338 case SCCP_SOFTSWITCH_DIAL:
1339 sccp_log((DEBUGCAT_PBX)) (VERBOSE_PREFIX_3 "%s: (sccp_pbx_softswitch) Dial Extension %s\n", d->id, shortenedNumber);
1340 sccp_indicate(d, c, SCCP_CHANNELSTATE_DIALING);
1341 /* fall through */
1342 }
1343
1344 /* set private variable */
1345 if (pbx_channel && !pbx_check_hangup(pbx_channel)) {
1346 sccp_log((DEBUGCAT_PBX)) (VERBOSE_PREFIX_3 "SCCP: (sccp_pbx_softswitch) set variable SKINNY_PRIVATE to: %s\n", c->privacy ? "1" : "0");
1347 if (c->privacy) {
1348 sccp_channel_set_calleridPresentation(c, CALLERID_PRESENTATION_FORBIDDEN);
1349 }
1350
1351 uint32_t result = d->privacyFeature.status & SCCP_PRIVACYFEATURE_CALLPRESENT;
1352
1353 result |= c->privacy;
1354 if (d->privacyFeature.enabled && result) {
1355 sccp_log((DEBUGCAT_PBX)) (VERBOSE_PREFIX_3 "SCCP: (sccp_pbx_softswitch) set variable SKINNY_PRIVATE to: %s\n", "1");
1356 pbx_builtin_setvar_helper(pbx_channel, "SKINNY_PRIVATE", "1");
1357 } else {
1358 sccp_log((DEBUGCAT_PBX)) (VERBOSE_PREFIX_3 "SCCP: (sccp_pbx_softswitch) set variable SKINNY_PRIVATE to: %s\n", "0");
1359 pbx_builtin_setvar_helper(pbx_channel, "SKINNY_PRIVATE", "0");
1360 }
1361 }
1362
1363 /* set devicevariables */
1364 v = d->variables;
1365 while (pbx_channel && !pbx_check_hangup(pbx_channel) && d && v) {
1366 pbx_builtin_setvar_helper(pbx_channel, v->name, v->value);
1367 v = v->next;
1368 }
1369
1370 /* set linevariables */
1371 v = l->variables;
1372 while (pbx_channel && !pbx_check_hangup(pbx_channel) && l && v) {
1373 pbx_builtin_setvar_helper(pbx_channel, v->name, v->value);
1374 v = v->next;
1375 }
1376
1377 iPbx.setChannelExten(c, shortenedNumber);
1378
1379 /*! \todo DdG: Extra wait time is incurred when checking pbx_exists_extension, when a wrong number is dialed. storing extension_exists status for sccp_log use */
1380 int extension_exists = SCCP_EXTENSION_NOTEXISTS;
1381
1382 if (!sccp_strlen_zero(shortenedNumber) && ((extension_exists = iPbx.extension_status(c) != SCCP_EXTENSION_NOTEXISTS))
1383 ) {
1384 if (pbx_channel && !pbx_check_hangup(pbx_channel)) {
1385 /* found an extension, let's dial it */
1386 sccp_log((DEBUGCAT_PBX + DEBUGCAT_CHANNEL)) (VERBOSE_PREFIX_1 "%s: (sccp_pbx_softswitch) channel %s is dialing number %s\n", DEV_ID_LOG(d), c->designator, shortenedNumber);
1387
1388 /* Answer dialplan command works only when in RINGING OR RING ast_state */
1389 iPbx.set_callstate(c, AST_STATE_RING);
1390
1391 enum ast_pbx_result pbxStartResult = pbx_pbx_start(pbx_channel);
1392
1393 /* \todo replace AST_PBX enum using pbx_impl wrapper enum */
1394 switch (pbxStartResult) {
1395 case AST_PBX_FAILED:
1396 pbx_log(LOG_ERROR, "%s: (sccp_pbx_softswitch) channel %s failed to start new thread to dial %s\n", DEV_ID_LOG(d), c->designator, shortenedNumber);
1397 /* \todo change indicate to something more suitable */
1398 sccp_indicate(d, c, SCCP_CHANNELSTATE_CONGESTION); /* will auto hangup after SCCP_HANGUP_TIMEOUT */
1399 break;
1400 case AST_PBX_CALL_LIMIT:
1401 pbx_log(LOG_WARNING, "%s: (sccp_pbx_softswitch) call limit reached for channel %s-%08x failed to start new thread to dial %s\n", DEV_ID_LOG(d), l->name, c->callid, shortenedNumber);
1402 sccp_indicate(d, c, SCCP_CHANNELSTATE_CONGESTION); /* will auto hangup after SCCP_HANGUP_TIMEOUT */
1403 break;
1404 case AST_PBX_SUCCESS:
1405 sccp_log((DEBUGCAT_PBX)) (VERBOSE_PREFIX_1 "%s: (sccp_pbx_softswitch) pbx started\n", DEV_ID_LOG(d));
1406 #ifdef CS_MANAGER_EVENTS
1407 if (GLOB(callevents)) {
1408 manager_event(EVENT_FLAG_SYSTEM, "ChannelUpdate", "Channel: %s\r\nUniqueid: %s\r\nChanneltype: %s\r\nSCCPdevice: %s\r\nSCCPline: %s\r\nSCCPcallid: %08X\r\nSCCPCallDesignator: %s\r\n",
1409 (pbx_channel) ? pbx_channel_name(pbx_channel) : "(null)",
1410 (pbx_channel) ? pbx_channel_uniqueid(pbx_channel) : "(null)",
1411 "SCCP",
1412 (d) ? d->id : "(null)",
1413 (l) ? l->name : "(null)",
1414 (c && c->callid) ? c->callid : 0,
1415 (c) ? c->designator : "(null)");
1416 }
1417 #endif // CS_MANAGER_EVENTS
1418 break;
1419 }
1420 AUTO_RELEASE(sccp_linedevice_t, ld, c->getLineDevice(c));
1421 if(ld) {
1422 sccp_device_setLastNumberDialed(d, shortenedNumber, ld);
1423 }
1424 if(iPbx.set_dialed_number) {
1425 iPbx.set_dialed_number(c, shortenedNumber);
1426 }
1427 } else {
1428 sccp_log((DEBUGCAT_PBX)) (VERBOSE_PREFIX_1 "%s: (sccp_pbx_softswitch) pbx_check_hangup(chan): %d on line %s\n", DEV_ID_LOG(d), (pbx_channel && pbx_check_hangup(pbx_channel)), l->name);
1429 }
1430 } else {
1431 sccp_log((DEBUGCAT_PBX)) (VERBOSE_PREFIX_1 "%s: (sccp_pbx_softswitch) channel:%s shortenedNumber:%s, extension exists:%s\n", DEV_ID_LOG(d), c->designator, shortenedNumber, (extension_exists != SCCP_EXTENSION_NOTEXISTS) ? "TRUE" : "FALSE");
1432 pbx_log(LOG_NOTICE, "%s: Call from '%s' to extension '%s', rejected because the extension could not be found in context '%s'\n", DEV_ID_LOG(d), l->name, shortenedNumber, pbx_channel ? pbx_channel_context(pbx_channel) : "pbx_channel==NULL");
1433 /* timeout and no extension match */
1434 if (pbx_channel && !pbx_check_hangup(pbx_channel)) {
1435 pbx_log(LOG_NOTICE, "%s: Scheduling Hangup of Call: %s\n", DEV_ID_LOG(d), c->designator);
1436 sccp_indicate(d, c, SCCP_CHANNELSTATE_INVALIDNUMBER); /* will auto hangup after SCCP_HANGUP_TIMEOUT */
1437 }
1438 }
1439
1440 sccp_log((DEBUGCAT_PBX + DEBUGCAT_DEVICE)) (VERBOSE_PREFIX_1 "%s: (sccp_pbx_softswitch) finished\n", DEV_ID_LOG(d));
1441 }
1442 EXIT_FUNC:
1443 sccp_log((DEBUGCAT_PBX + DEBUGCAT_DEVICE)) (VERBOSE_PREFIX_1 "SCCP: (sccp_pbx_softswitch) exit\n");
1444 if (pbx_channel) {
1445 pbx_channel_unref(pbx_channel);
1446 }
1447 return NULL;
1448 }
1449
1450 #if 0
1451 /*!
1452 * \brief Handle Dialplan Transfer
1453 *
1454 * This will allow asterisk to transfer an SCCP Channel via the dialplan transfer function
1455 *
1456 * \param ast Asterisk Channel
1457 * \param dest Destination as char *
1458 * \return result as int
1459 *
1460 * \test Dialplan Transfer Needs to be tested
1461 * \todo pbx_transfer needs to be implemented correctly
1462 *
1463 * \called_from_asterisk
1464 */
1465 int sccp_pbx_transfer(PBX_CHANNEL_TYPE * ast, const char *dest)
1466 {
1467 int res = 0;
1468
1469 if (dest == NULL) { /* functions below do not take a NULL */
1470 dest = "";
1471 return -1;
1472 }
1473
1474 AUTO_RELEASE(sccp_channel_t, c , get_sccp_channel_from_pbx_channel(ast));
1475
1476 if (!c) {
1477 return -1;
1478 }
1479
1480 /*
1481 sccp_device_t *d = NULL;
1482 sccp_channel_t *newcall = NULL;
1483 */
1484
1485 sccp_log((DEBUGCAT_CORE)) (VERBOSE_PREFIX_1 "Transferring '%s' to '%s'\n", iPbx.getChannelName(c), dest);
1486 if (pbx_channel_state(ast) == AST_STATE_RING) {
1487 //! \todo Blindtransfer needs to be implemented correctly
1488
1489 /*
1490 res = sccp_blindxfer(p, dest);
1491 */
1492 res = -1;
1493 } else {
1494 //! \todo Transfer needs to be implemented correctly
1495
1496 /*
1497 res=sccp_channel_transfer(p,dest);
1498 */
1499 res = -1;
1500 }
1501 return res;
1502 }
1503 #endif
1504
1505 // 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;
1506