Bug Summary

File:src/switch_channel.c
Location:line 3553, column 7
Description:Null pointer passed as an argument to a 'nonnull' parameter

Annotated Source Code

1/*
2 * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
3 * Copyright (C) 2005-2014, Anthony Minessale II <anthm@freeswitch.org>
4 *
5 * Version: MPL 1.1
6 *
7 * The contents of this file are subject to the Mozilla Public License Version
8 * 1.1 (the "License"); you may not use this file except in compliance with
9 * the License. You may obtain a copy of the License at
10 * http://www.mozilla.org/MPL/
11 *
12 * Software distributed under the License is distributed on an "AS IS" basis,
13 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
14 * for the specific language governing rights and limitations under the
15 * License.
16 *
17 * The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
18 *
19 * The Initial Developer of the Original Code is
20 * Anthony Minessale II <anthm@freeswitch.org>
21 * Portions created by the Initial Developer are Copyright (C)
22 * the Initial Developer. All Rights Reserved.
23 *
24 * Contributor(s):
25 *
26 * Anthony Minessale II <anthm@freeswitch.org>
27 * Michael Jerris <mike@jerris.com>
28 *
29 *
30 * switch_channel.c -- Media Channel Interface
31 *
32 */
33
34#include <switch.h>
35#include <switch_channel.h>
36#include <pcre.h>
37
38struct switch_cause_table {
39 const char *name;
40 switch_call_cause_t cause;
41};
42
43typedef struct switch_device_state_binding_s {
44 switch_device_state_function_t function;
45 void *user_data;
46 struct switch_device_state_binding_s *next;
47} switch_device_state_binding_t;
48
49static struct {
50 switch_memory_pool_t *pool;
51 switch_hash_t *device_hash;
52 switch_mutex_t *device_mutex;
53 switch_device_state_binding_t *device_bindings;
54} globals;
55
56static struct switch_cause_table CAUSE_CHART[] = {
57 {"NONE", SWITCH_CAUSE_NONE},
58 {"UNALLOCATED_NUMBER", SWITCH_CAUSE_UNALLOCATED_NUMBER},
59 {"NO_ROUTE_TRANSIT_NET", SWITCH_CAUSE_NO_ROUTE_TRANSIT_NET},
60 {"NO_ROUTE_DESTINATION", SWITCH_CAUSE_NO_ROUTE_DESTINATION},
61 {"CHANNEL_UNACCEPTABLE", SWITCH_CAUSE_CHANNEL_UNACCEPTABLE},
62 {"CALL_AWARDED_DELIVERED", SWITCH_CAUSE_CALL_AWARDED_DELIVERED},
63 {"NORMAL_CLEARING", SWITCH_CAUSE_NORMAL_CLEARING},
64 {"USER_BUSY", SWITCH_CAUSE_USER_BUSY},
65 {"NO_USER_RESPONSE", SWITCH_CAUSE_NO_USER_RESPONSE},
66 {"NO_ANSWER", SWITCH_CAUSE_NO_ANSWER},
67 {"SUBSCRIBER_ABSENT", SWITCH_CAUSE_SUBSCRIBER_ABSENT},
68 {"CALL_REJECTED", SWITCH_CAUSE_CALL_REJECTED},
69 {"NUMBER_CHANGED", SWITCH_CAUSE_NUMBER_CHANGED},
70 {"REDIRECTION_TO_NEW_DESTINATION", SWITCH_CAUSE_REDIRECTION_TO_NEW_DESTINATION},
71 {"EXCHANGE_ROUTING_ERROR", SWITCH_CAUSE_EXCHANGE_ROUTING_ERROR},
72 {"DESTINATION_OUT_OF_ORDER", SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER},
73 {"INVALID_NUMBER_FORMAT", SWITCH_CAUSE_INVALID_NUMBER_FORMAT},
74 {"FACILITY_REJECTED", SWITCH_CAUSE_FACILITY_REJECTED},
75 {"RESPONSE_TO_STATUS_ENQUIRY", SWITCH_CAUSE_RESPONSE_TO_STATUS_ENQUIRY},
76 {"NORMAL_UNSPECIFIED", SWITCH_CAUSE_NORMAL_UNSPECIFIED},
77 {"NORMAL_CIRCUIT_CONGESTION", SWITCH_CAUSE_NORMAL_CIRCUIT_CONGESTION},
78 {"NETWORK_OUT_OF_ORDER", SWITCH_CAUSE_NETWORK_OUT_OF_ORDER},
79 {"NORMAL_TEMPORARY_FAILURE", SWITCH_CAUSE_NORMAL_TEMPORARY_FAILURE},
80 {"SWITCH_CONGESTION", SWITCH_CAUSE_SWITCH_CONGESTION},
81 {"ACCESS_INFO_DISCARDED", SWITCH_CAUSE_ACCESS_INFO_DISCARDED},
82 {"REQUESTED_CHAN_UNAVAIL", SWITCH_CAUSE_REQUESTED_CHAN_UNAVAIL},
83 {"PRE_EMPTED", SWITCH_CAUSE_PRE_EMPTED},
84 {"FACILITY_NOT_SUBSCRIBED", SWITCH_CAUSE_FACILITY_NOT_SUBSCRIBED},
85 {"OUTGOING_CALL_BARRED", SWITCH_CAUSE_OUTGOING_CALL_BARRED},
86 {"INCOMING_CALL_BARRED", SWITCH_CAUSE_INCOMING_CALL_BARRED},
87 {"BEARERCAPABILITY_NOTAUTH", SWITCH_CAUSE_BEARERCAPABILITY_NOTAUTH},
88 {"BEARERCAPABILITY_NOTAVAIL", SWITCH_CAUSE_BEARERCAPABILITY_NOTAVAIL},
89 {"SERVICE_UNAVAILABLE", SWITCH_CAUSE_SERVICE_UNAVAILABLE},
90 {"BEARERCAPABILITY_NOTIMPL", SWITCH_CAUSE_BEARERCAPABILITY_NOTIMPL},
91 {"CHAN_NOT_IMPLEMENTED", SWITCH_CAUSE_CHAN_NOT_IMPLEMENTED},
92 {"FACILITY_NOT_IMPLEMENTED", SWITCH_CAUSE_FACILITY_NOT_IMPLEMENTED},
93 {"SERVICE_NOT_IMPLEMENTED", SWITCH_CAUSE_SERVICE_NOT_IMPLEMENTED},
94 {"INVALID_CALL_REFERENCE", SWITCH_CAUSE_INVALID_CALL_REFERENCE},
95 {"INCOMPATIBLE_DESTINATION", SWITCH_CAUSE_INCOMPATIBLE_DESTINATION},
96 {"INVALID_MSG_UNSPECIFIED", SWITCH_CAUSE_INVALID_MSG_UNSPECIFIED},
97 {"MANDATORY_IE_MISSING", SWITCH_CAUSE_MANDATORY_IE_MISSING},
98 {"MESSAGE_TYPE_NONEXIST", SWITCH_CAUSE_MESSAGE_TYPE_NONEXIST},
99 {"WRONG_MESSAGE", SWITCH_CAUSE_WRONG_MESSAGE},
100 {"IE_NONEXIST", SWITCH_CAUSE_IE_NONEXIST},
101 {"INVALID_IE_CONTENTS", SWITCH_CAUSE_INVALID_IE_CONTENTS},
102 {"WRONG_CALL_STATE", SWITCH_CAUSE_WRONG_CALL_STATE},
103 {"RECOVERY_ON_TIMER_EXPIRE", SWITCH_CAUSE_RECOVERY_ON_TIMER_EXPIRE},
104 {"MANDATORY_IE_LENGTH_ERROR", SWITCH_CAUSE_MANDATORY_IE_LENGTH_ERROR},
105 {"PROTOCOL_ERROR", SWITCH_CAUSE_PROTOCOL_ERROR},
106 {"INTERWORKING", SWITCH_CAUSE_INTERWORKING},
107 {"SUCCESS", SWITCH_CAUSE_SUCCESS},
108 {"ORIGINATOR_CANCEL", SWITCH_CAUSE_ORIGINATOR_CANCEL},
109 {"CRASH", SWITCH_CAUSE_CRASH},
110 {"SYSTEM_SHUTDOWN", SWITCH_CAUSE_SYSTEM_SHUTDOWN},
111 {"LOSE_RACE", SWITCH_CAUSE_LOSE_RACE},
112 {"MANAGER_REQUEST", SWITCH_CAUSE_MANAGER_REQUEST},
113 {"BLIND_TRANSFER", SWITCH_CAUSE_BLIND_TRANSFER},
114 {"ATTENDED_TRANSFER", SWITCH_CAUSE_ATTENDED_TRANSFER},
115 {"ALLOTTED_TIMEOUT", SWITCH_CAUSE_ALLOTTED_TIMEOUT},
116 {"USER_CHALLENGE", SWITCH_CAUSE_USER_CHALLENGE},
117 {"MEDIA_TIMEOUT", SWITCH_CAUSE_MEDIA_TIMEOUT},
118 {"PICKED_OFF", SWITCH_CAUSE_PICKED_OFF},
119 {"USER_NOT_REGISTERED", SWITCH_CAUSE_USER_NOT_REGISTERED},
120 {"PROGRESS_TIMEOUT", SWITCH_CAUSE_PROGRESS_TIMEOUT},
121 {"INVALID_GATEWAY", SWITCH_CAUSE_INVALID_GATEWAY},
122 {"GATEWAY_DOWN", SWITCH_CAUSE_GATEWAY_DOWN},
123 {"INVALID_URL", SWITCH_CAUSE_INVALID_URL},
124 {"INVALID_PROFILE", SWITCH_CAUSE_INVALID_PROFILE},
125 {"NO_PICKUP", SWITCH_CAUSE_NO_PICKUP},
126 {"SRTP_READ_ERROR", SWITCH_CAUSE_SRTP_READ_ERROR},
127 {NULL((void*)0), 0}
128};
129
130typedef enum {
131 OCF_HANGUP = (1 << 0)
132} opaque_channel_flag_t;
133
134typedef enum {
135 LP_NEITHER,
136 LP_ORIGINATOR,
137 LP_ORIGINATEE
138} switch_originator_type_t;
139
140struct switch_channel {
141 char *name;
142 switch_call_direction_t direction;
143 switch_call_direction_t logical_direction;
144 switch_queue_t *dtmf_queue;
145 switch_queue_t *dtmf_log_queue;
146 switch_mutex_t*dtmf_mutex;
147 switch_mutex_t *flag_mutex;
148 switch_mutex_t *state_mutex;
149 switch_mutex_t *thread_mutex;
150 switch_mutex_t *profile_mutex;
151 switch_core_session_t *session;
152 switch_channel_state_t state;
153 switch_channel_state_t running_state;
154 switch_channel_callstate_t callstate;
155 uint32_t flags[CF_FLAG_MAX];
156 uint32_t caps[CC_FLAG_MAX];
157 uint8_t state_flags[CF_FLAG_MAX];
158 uint32_t private_flags;
159 switch_caller_profile_t *caller_profile;
160 const switch_state_handler_table_t *state_handlers[SWITCH_MAX_STATE_HANDLERS30];
161 int state_handler_index;
162 switch_event_t *variables;
163 switch_event_t *scope_variables;
164 switch_hash_t *private_hash;
165 switch_hash_t *app_flag_hash;
166 switch_call_cause_t hangup_cause;
167 int vi;
168 int event_count;
169 int profile_index;
170 opaque_channel_flag_t opaque_flags;
171 switch_originator_type_t last_profile_type;
172 switch_caller_extension_t *queued_extension;
173 switch_event_t *app_list;
174 switch_event_t *api_list;
175 switch_event_t *var_list;
176 switch_hold_record_t *hold_record;
177 switch_device_node_t *device_node;
178 char *device_id;
179};
180
181static void process_device_hup(switch_channel_t *channel);
182static void switch_channel_check_device_state(switch_channel_t *channel, switch_channel_callstate_t callstate);
183
184SWITCH_DECLARE(switch_hold_record_t *)__attribute__((visibility("default"))) switch_hold_record_t * switch_channel_get_hold_record(switch_channel_t *channel)
185{
186 return channel->hold_record;
187}
188
189SWITCH_DECLARE(const char *)__attribute__((visibility("default"))) const char * switch_channel_cause2str(switch_call_cause_t cause)
190{
191 uint8_t x;
192 const char *str = "UNKNOWN";
193
194 for (x = 0; x < (sizeof(CAUSE_CHART) / sizeof(struct switch_cause_table)) - 1; x++) {
195 if (CAUSE_CHART[x].cause == cause) {
196 str = CAUSE_CHART[x].name;
197 break;
198 }
199 }
200
201 return str;
202}
203
204SWITCH_DECLARE(switch_call_cause_t)__attribute__((visibility("default"))) switch_call_cause_t switch_channel_str2cause(const char *str)
205{
206 uint8_t x;
207 switch_call_cause_t cause = SWITCH_CAUSE_NONE;
208
209 if (*str > 47 && *str < 58) {
210 cause = atoi(str);
211 } else {
212 for (x = 0; x < (sizeof(CAUSE_CHART) / sizeof(struct switch_cause_table)) - 1 && CAUSE_CHART[x].name; x++) {
213 if (!strcasecmp(CAUSE_CHART[x].name, str)) {
214 cause = CAUSE_CHART[x].cause;
215 break;
216 }
217 }
218 }
219 return cause;
220}
221
222SWITCH_DECLARE(switch_call_cause_t)__attribute__((visibility("default"))) switch_call_cause_t switch_channel_get_cause(switch_channel_t *channel)
223{
224 return channel->hangup_cause;
225}
226
227
228SWITCH_DECLARE(switch_call_cause_t *)__attribute__((visibility("default"))) switch_call_cause_t * switch_channel_get_cause_ptr(switch_channel_t *channel)
229{
230 return &channel->hangup_cause;
231}
232
233
234struct switch_callstate_table {
235 const char *name;
236 switch_channel_callstate_t callstate;
237};
238static struct switch_callstate_table CALLSTATE_CHART[] = {
239 {"DOWN", CCS_DOWN},
240 {"DIALING", CCS_DIALING},
241 {"RINGING", CCS_RINGING},
242 {"EARLY", CCS_EARLY},
243 {"ACTIVE", CCS_ACTIVE},
244 {"HELD", CCS_HELD},
245 {"RING_WAIT", CCS_RING_WAIT},
246 {"HANGUP", CCS_HANGUP},
247 {"UNHELD", CCS_UNHELD},
248 {NULL((void*)0), 0}
249};
250
251struct switch_device_state_table {
252 const char *name;
253 switch_device_state_t device_state;
254};
255static struct switch_device_state_table DEVICE_STATE_CHART[] = {
256 {"DOWN", SDS_DOWN},
257 {"RINGING", SDS_RINGING},
258 {"ACTIVE", SDS_ACTIVE},
259 {"ACTIVE_MULTI", SDS_ACTIVE_MULTI},
260 {"HELD", SDS_HELD},
261 {"UNHELD", SDS_UNHELD},
262 {"HANGUP", SDS_HANGUP},
263 {NULL((void*)0), 0}
264};
265
266
267SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_channel_perform_set_callstate(switch_channel_t *channel, switch_channel_callstate_t callstate,
268 const char *file, const char *func, int line)
269{
270 switch_event_t *event;
271 switch_channel_callstate_t o_callstate = channel->callstate;
272
273 if (o_callstate == callstate || o_callstate == CCS_HANGUP) return;
274
275 channel->callstate = callstate;
276 if (channel->device_node) {
277 channel->device_node->callstate = callstate;
278 }
279 switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, func, line, switch_channel_get_uuid(channel), SWITCH_LOG_DEBUG,
280 "(%s) Callstate Change %s -> %s\n", channel->name,
281 switch_channel_callstate2str(o_callstate), switch_channel_callstate2str(callstate));
282
283 switch_channel_check_device_state(channel, channel->callstate);
284
285 if (switch_event_create(&event, SWITCH_EVENT_CHANNEL_CALLSTATE)switch_event_create_subclass_detailed("src/switch_channel.c",
(const char * )(const char *)__func__, 285, &event, SWITCH_EVENT_CHANNEL_CALLSTATE
, ((void*)0))
== SWITCH_STATUS_SUCCESS) {
286 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Original-Channel-Call-State", switch_channel_callstate2str(o_callstate));
287 switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Channel-Call-State-Number", "%d", callstate);
288 switch_channel_event_set_data(channel, event);
289 switch_event_fire(&event)switch_event_fire_detailed("src/switch_channel.c", (const char
* )(const char *)__func__, 289, &event, ((void*)0))
;
290 }
291}
292
293SWITCH_DECLARE(switch_channel_callstate_t)__attribute__((visibility("default"))) switch_channel_callstate_t switch_channel_get_callstate(switch_channel_t *channel)
294{
295 return channel->callstate;
296}
297
298
299SWITCH_DECLARE(const char *)__attribute__((visibility("default"))) const char * switch_channel_callstate2str(switch_channel_callstate_t callstate)
300{
301 uint8_t x;
302 const char *str = "UNKNOWN";
303
304 for (x = 0; x < (sizeof(CALLSTATE_CHART) / sizeof(struct switch_cause_table)) - 1; x++) {
305 if (CALLSTATE_CHART[x].callstate == callstate) {
306 str = CALLSTATE_CHART[x].name;
307 break;
308 }
309 }
310
311 return str;
312}
313
314SWITCH_DECLARE(const char *)__attribute__((visibility("default"))) const char * switch_channel_device_state2str(switch_device_state_t device_state)
315{
316 uint8_t x;
317 const char *str = "UNKNOWN";
318
319 for (x = 0; x < (sizeof(DEVICE_STATE_CHART) / sizeof(struct switch_cause_table)) - 1; x++) {
320 if (DEVICE_STATE_CHART[x].device_state == device_state) {
321 str = DEVICE_STATE_CHART[x].name;
322 break;
323 }
324 }
325
326 return str;
327}
328
329
330SWITCH_DECLARE(switch_channel_callstate_t)__attribute__((visibility("default"))) switch_channel_callstate_t switch_channel_str2callstate(const char *str)
331{
332 uint8_t x;
333 switch_channel_callstate_t callstate = (switch_channel_callstate_t) SWITCH_CAUSE_NONE;
334
335 if (*str > 47 && *str < 58) {
336 callstate = atoi(str);
337 } else {
338 for (x = 0; x < (sizeof(CALLSTATE_CHART) / sizeof(struct switch_callstate_table)) - 1 && CALLSTATE_CHART[x].name; x++) {
339 if (!strcasecmp(CALLSTATE_CHART[x].name, str)) {
340 callstate = CALLSTATE_CHART[x].callstate;
341 break;
342 }
343 }
344 }
345 return callstate;
346}
347
348
349
350SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_channel_perform_audio_sync(switch_channel_t *channel, const char *file, const char *func, int line)
351{
352 if (switch_channel_media_up(channel)(switch_channel_test_flag(channel, CF_ANSWERED) || switch_channel_test_flag
(channel, CF_EARLY_MEDIA))
) {
353 switch_core_session_message_t msg = { 0 };
354 msg.message_id = SWITCH_MESSAGE_INDICATE_AUDIO_SYNC;
355 msg.from = channel->name;
356 msg._file = file;
357 msg._func = func;
358 msg._line = line;
359 switch_core_session_receive_message(channel->session, &msg)switch_core_session_perform_receive_message(channel->session
, &msg, "src/switch_channel.c", (const char *)__func__, 359
)
;
360 }
361}
362
363
364
365SWITCH_DECLARE(switch_call_cause_t)__attribute__((visibility("default"))) switch_call_cause_t switch_channel_cause_q850(switch_call_cause_t cause)
366{
367 if (cause <= SWITCH_CAUSE_INTERWORKING) {
368 return cause;
369 } else {
370 return SWITCH_CAUSE_NORMAL_CLEARING;
371 }
372}
373
374SWITCH_DECLARE(switch_call_cause_t)__attribute__((visibility("default"))) switch_call_cause_t switch_channel_get_cause_q850(switch_channel_t *channel)
375{
376 return switch_channel_cause_q850(channel->hangup_cause);
377}
378
379SWITCH_DECLARE(switch_channel_timetable_t *)__attribute__((visibility("default"))) switch_channel_timetable_t
*
switch_channel_get_timetable(switch_channel_t *channel)
380{
381 switch_channel_timetable_t *times = NULL((void*)0);
382
383 if (channel->caller_profile) {
384 switch_mutex_lock(channel->profile_mutex);
385 times = channel->caller_profile->times;
386 switch_mutex_unlock(channel->profile_mutex);
387 }
388
389 return times;
390}
391
392SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_channel_set_direction(switch_channel_t *channel, switch_call_direction_t direction)
393{
394 if (!switch_core_session_in_thread(channel->session)) {
395 channel->direction = channel->logical_direction = direction;
396 switch_channel_set_variable(channel, "direction", switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND ? "outbound" : "inbound")switch_channel_set_variable_var_check(channel, "direction", switch_channel_direction
(channel) == SWITCH_CALL_DIRECTION_OUTBOUND ? "outbound" : "inbound"
, SWITCH_TRUE)
;
397 }
398}
399
400SWITCH_DECLARE(switch_call_direction_t)__attribute__((visibility("default"))) switch_call_direction_t switch_channel_direction(switch_channel_t *channel)
401{
402 return channel->direction;
403}
404
405SWITCH_DECLARE(switch_call_direction_t)__attribute__((visibility("default"))) switch_call_direction_t switch_channel_logical_direction(switch_channel_t *channel)
406{
407 return channel->logical_direction;
408}
409
410SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_channel_alloc(switch_channel_t **channel, switch_call_direction_t direction, switch_memory_pool_t *pool)
411{
412 switch_assert(pool != NULL)((pool != ((void*)0)) ? (void) (0) : __assert_fail ("pool != ((void*)0)"
, "src/switch_channel.c", 412, __PRETTY_FUNCTION__))
;
413
414 if (((*channel) = switch_core_alloc(pool, sizeof(switch_channel_t))switch_core_perform_alloc(pool, sizeof(switch_channel_t), "src/switch_channel.c"
, (const char *)__func__, 414)
) == 0) {
415 return SWITCH_STATUS_MEMERR;
416 }
417
418 switch_event_create_plain(&(*channel)->variables, SWITCH_EVENT_CHANNEL_DATA);
419
420 switch_core_hash_init(&(*channel)->private_hash)switch_core_hash_init_case(&(*channel)->private_hash, SWITCH_TRUE
)
;
421 switch_queue_create(&(*channel)->dtmf_queue, SWITCH_DTMF_LOG_LEN1000, pool);
422 switch_queue_create(&(*channel)->dtmf_log_queue, SWITCH_DTMF_LOG_LEN1000, pool);
423
424 switch_mutex_init(&(*channel)->dtmf_mutex, SWITCH_MUTEX_NESTED0x1, pool);
425 switch_mutex_init(&(*channel)->flag_mutex, SWITCH_MUTEX_NESTED0x1, pool);
426 switch_mutex_init(&(*channel)->state_mutex, SWITCH_MUTEX_NESTED0x1, pool);
427 switch_mutex_init(&(*channel)->thread_mutex, SWITCH_MUTEX_NESTED0x1, pool);
428 switch_mutex_init(&(*channel)->profile_mutex, SWITCH_MUTEX_NESTED0x1, pool);
429 (*channel)->hangup_cause = SWITCH_CAUSE_NONE;
430 (*channel)->name = "";
431 (*channel)->direction = (*channel)->logical_direction = direction;
432 switch_channel_set_variable(*channel, "direction", switch_channel_direction(*channel) == SWITCH_CALL_DIRECTION_OUTBOUND ? "outbound" : "inbound")switch_channel_set_variable_var_check(*channel, "direction", switch_channel_direction
(*channel) == SWITCH_CALL_DIRECTION_OUTBOUND ? "outbound" : "inbound"
, SWITCH_TRUE)
;
433
434 return SWITCH_STATUS_SUCCESS;
435}
436
437SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_channel_dtmf_lock(switch_channel_t *channel)
438{
439 return switch_mutex_lock(channel->dtmf_mutex);
440}
441
442SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_channel_try_dtmf_lock(switch_channel_t *channel)
443{
444 return switch_mutex_trylock(channel->dtmf_mutex);
445}
446
447SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_channel_dtmf_unlock(switch_channel_t *channel)
448{
449 return switch_mutex_unlock(channel->dtmf_mutex);
450}
451
452SWITCH_DECLARE(switch_size_t)__attribute__((visibility("default"))) switch_size_t switch_channel_has_dtmf(switch_channel_t *channel)
453{
454 switch_size_t has;
455
456 switch_mutex_lock(channel->dtmf_mutex);
457 has = switch_queue_size(channel->dtmf_queue);
458 switch_mutex_unlock(channel->dtmf_mutex);
459
460 return has;
461}
462
463SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_channel_queue_dtmf(switch_channel_t *channel, const switch_dtmf_t *dtmf)
464{
465 switch_status_t status;
466 void *pop;
467 switch_dtmf_t new_dtmf = { 0 };
468 switch_bool_t sensitive = switch_true(switch_channel_get_variable_dup(channel, SWITCH_SENSITIVE_DTMF_VARIABLE"sensitive_dtmf", SWITCH_FALSE, -1));
469
470 switch_assert(dtmf)((dtmf) ? (void) (0) : __assert_fail ("dtmf", "src/switch_channel.c"
, 470, __PRETTY_FUNCTION__))
;
471
472 switch_mutex_lock(channel->dtmf_mutex);
473 new_dtmf = *dtmf;
474
475 if (sensitive) {
476 switch_set_flag((&new_dtmf), DTMF_FLAG_SENSITIVE)((&new_dtmf))->flags |= (DTMF_FLAG_SENSITIVE);
477 }
478
479 if ((status = switch_core_session_recv_dtmf(channel->session, dtmf) != SWITCH_STATUS_SUCCESS)) {
480 goto done;
481 }
482
483 if (is_dtmf(new_dtmf.digit)((new_dtmf.digit > 47 && new_dtmf.digit < 58) ||
(new_dtmf.digit > 64 && new_dtmf.digit < 69) ||
(new_dtmf.digit > 96 && new_dtmf.digit < 101) ||
new_dtmf.digit == 35 || new_dtmf.digit == 42 || new_dtmf.digit
== 87 || new_dtmf.digit == 119 || new_dtmf.digit == 70 || new_dtmf
.digit == 102)
) {
484 switch_dtmf_t *dt;
485 int x = 0;
486
487 if (!sensitive) {
488 switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel)SWITCH_CHANNEL_ID_SESSION, "src/switch_channel.c", (const char
*)__func__, 488, (const char*)switch_channel_get_session(channel
)
, SWITCH_LOG_DEBUG, "RECV DTMF %c:%d\n", new_dtmf.digit, new_dtmf.duration);
489 }
490
491 if (new_dtmf.digit != 'w' && new_dtmf.digit != 'W') {
492 if (new_dtmf.duration > switch_core_max_dtmf_duration(0)) {
493 switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel)SWITCH_CHANNEL_ID_SESSION, "src/switch_channel.c", (const char
*)__func__, 493, (const char*)switch_channel_get_session(channel
)
, SWITCH_LOG_DEBUG, "%s EXCESSIVE DTMF DIGIT LEN [%d]\n",
494 switch_channel_get_name(channel), new_dtmf.duration);
495 new_dtmf.duration = switch_core_max_dtmf_duration(0);
496 } else if (new_dtmf.duration < switch_core_min_dtmf_duration(0)) {
497 switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel)SWITCH_CHANNEL_ID_SESSION, "src/switch_channel.c", (const char
*)__func__, 497, (const char*)switch_channel_get_session(channel
)
, SWITCH_LOG_DEBUG, "%s SHORT DTMF DIGIT LEN [%d]\n",
498 switch_channel_get_name(channel), new_dtmf.duration);
499 new_dtmf.duration = switch_core_min_dtmf_duration(0);
500 }
501 }
502
503 if (!new_dtmf.duration) {
504 new_dtmf.duration = switch_core_default_dtmf_duration(0);
505 }
506
507
508 switch_zmalloc(dt, sizeof(*dt))(void)((((dt = calloc(1, (sizeof(*dt))))) ? (void) (0) : __assert_fail
("(dt = calloc(1, (sizeof(*dt))))", "src/switch_channel.c", 508
, __PRETTY_FUNCTION__)),dt)
;
509 *dt = new_dtmf;
510
511
512 while (switch_queue_trypush(channel->dtmf_queue, dt) != SWITCH_STATUS_SUCCESS) {
513 if (switch_queue_trypop(channel->dtmf_queue, &pop) == SWITCH_STATUS_SUCCESS) {
514 free(pop);
515 }
516 if (++x > 100) {
517 status = SWITCH_STATUS_FALSE;
518 free(dt);
519 goto done;
520 }
521 }
522 }
523
524 status = SWITCH_STATUS_SUCCESS;
525
526 done:
527
528 switch_mutex_unlock(channel->dtmf_mutex);
529
530 switch_core_media_break(channel->session, SWITCH_MEDIA_TYPE_AUDIO);
531
532 return status;
533}
534
535SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_channel_queue_dtmf_string(switch_channel_t *channel, const char *dtmf_string)
536{
537 char *p;
538 switch_dtmf_t dtmf = { 0, switch_core_default_dtmf_duration(0), 0, SWITCH_DTMF_APP };
539 int sent = 0, dur;
540 char *string;
541 int i, argc;
542 char *argv[256];
543
544 if (zstr(dtmf_string)_zstr(dtmf_string)) {
545 return SWITCH_STATUS_FALSE;
546 }
547
548
549 dtmf.flags = DTMF_FLAG_SKIP_PROCESS;
550
551 if (*dtmf_string == '~') {
552 dtmf_string++;
553 dtmf.flags = 0;
554 }
555
556 string = switch_core_session_strdup(channel->session, dtmf_string)switch_core_perform_session_strdup(channel->session, dtmf_string
, "src/switch_channel.c", (const char *)__func__, 556)
;
557 argc = switch_separate_string(string, '+', argv, (sizeof(argv) / sizeof(argv[0])));
558
559 for (i = 0; i < argc; i++) {
560 dtmf.duration = switch_core_default_dtmf_duration(0);
561 dur = switch_core_default_dtmf_duration(0) / 8;
562 if ((p = strchr(argv[i], '@')(__extension__ (__builtin_constant_p ('@') && !__builtin_constant_p
(argv[i]) && ('@') == '\0' ? (char *) __rawmemchr (argv
[i], '@') : __builtin_strchr (argv[i], '@')))
)) {
563 *p++ = '\0';
564 if ((dur = atoi(p)) > (int)switch_core_min_dtmf_duration(0) / 8) {
565 dtmf.duration = dur * 8;
566 }
567 }
568
569 for (p = argv[i]; p && *p; p++) {
570 if (is_dtmf(*p)((*p > 47 && *p < 58) || (*p > 64 &&
*p < 69) || (*p > 96 && *p < 101) || *p == 35
|| *p == 42 || *p == 87 || *p == 119 || *p == 70 || *p == 102
)
) {
571 dtmf.digit = *p;
572
573 if (dtmf.duration > switch_core_max_dtmf_duration(0)) {
574 switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel)SWITCH_CHANNEL_ID_SESSION, "src/switch_channel.c", (const char
*)__func__, 574, (const char*)switch_channel_get_session(channel
)
, SWITCH_LOG_WARNING, "EXCESSIVE DTMF DIGIT LEN %c %d\n", dtmf.digit, dtmf.duration);
575 dtmf.duration = switch_core_max_dtmf_duration(0);
576 } else if (dtmf.duration < switch_core_min_dtmf_duration(0)) {
577 switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel)SWITCH_CHANNEL_ID_SESSION, "src/switch_channel.c", (const char
*)__func__, 577, (const char*)switch_channel_get_session(channel
)
, SWITCH_LOG_WARNING, "SHORT DTMF DIGIT LEN %c %d\n", dtmf.digit, dtmf.duration);
578 dtmf.duration = switch_core_min_dtmf_duration(0);
579 } else if (!dtmf.duration) {
580 dtmf.duration = switch_core_default_dtmf_duration(0);
581 }
582
583 if (switch_channel_queue_dtmf(channel, &dtmf) == SWITCH_STATUS_SUCCESS) {
584 switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel)SWITCH_CHANNEL_ID_SESSION, "src/switch_channel.c", (const char
*)__func__, 584, (const char*)switch_channel_get_session(channel
)
, SWITCH_LOG_DEBUG, "%s Queue dtmf\ndigit=%c ms=%u samples=%u\n",
585 switch_channel_get_name(channel), dtmf.digit, dur, dtmf.duration);
586 sent++;
587 }
588 }
589 }
590
591 }
592
593 return sent ? SWITCH_STATUS_SUCCESS : SWITCH_STATUS_FALSE;
594}
595
596SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_channel_dequeue_dtmf(switch_channel_t *channel, switch_dtmf_t *dtmf)
597{
598 switch_event_t *event;
599 void *pop;
600 switch_dtmf_t *dt;
601 switch_status_t status = SWITCH_STATUS_FALSE;
602 int sensitive = 0;
603
604 switch_mutex_lock(channel->dtmf_mutex);
605
606 if (switch_queue_trypop(channel->dtmf_queue, &pop) == SWITCH_STATUS_SUCCESS) {
607 dt = (switch_dtmf_t *) pop;
608 *dtmf = *dt;
609 sensitive = switch_test_flag(dtmf, DTMF_FLAG_SENSITIVE)((dtmf)->flags & DTMF_FLAG_SENSITIVE);
610
611 if (!sensitive && switch_queue_trypush(channel->dtmf_log_queue, dt) != SWITCH_STATUS_SUCCESS) {
612 free(dt);
613 }
614
615 dt = NULL((void*)0);
616
617 if (dtmf->duration > switch_core_max_dtmf_duration(0)) {
618 switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel)SWITCH_CHANNEL_ID_SESSION, "src/switch_channel.c", (const char
*)__func__, 618, (const char*)switch_channel_get_session(channel
)
, SWITCH_LOG_WARNING, "%s EXCESSIVE DTMF DIGIT [%c] LEN [%d]\n",
619 switch_channel_get_name(channel), sensitive ? 'S' : dtmf->digit, dtmf->duration);
620 dtmf->duration = switch_core_max_dtmf_duration(0);
621 } else if (dtmf->duration < switch_core_min_dtmf_duration(0)) {
622 switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel)SWITCH_CHANNEL_ID_SESSION, "src/switch_channel.c", (const char
*)__func__, 622, (const char*)switch_channel_get_session(channel
)
, SWITCH_LOG_WARNING, "%s SHORT DTMF DIGIT [%c] LEN [%d]\n",
623 switch_channel_get_name(channel), sensitive ? 'S' : dtmf->digit, dtmf->duration);
624 dtmf->duration = switch_core_min_dtmf_duration(0);
625 } else if (!dtmf->duration) {
626 dtmf->duration = switch_core_default_dtmf_duration(0);
627 }
628
629 status = SWITCH_STATUS_SUCCESS;
630 }
631 switch_mutex_unlock(channel->dtmf_mutex);
632
633 if (!sensitive && status == SWITCH_STATUS_SUCCESS && switch_event_create(&event, SWITCH_EVENT_DTMF)switch_event_create_subclass_detailed("src/switch_channel.c",
(const char * )(const char *)__func__, 633, &event, SWITCH_EVENT_DTMF
, ((void*)0))
== SWITCH_STATUS_SUCCESS) {
634 switch_channel_event_set_data(channel, event);
635 switch_event_add_header(event, SWITCH_STACK_BOTTOM, "DTMF-Digit", "%c", dtmf->digit);
636 switch_event_add_header(event, SWITCH_STACK_BOTTOM, "DTMF-Duration", "%u", dtmf->duration);
637 if (switch_channel_test_flag(channel, CF_DIVERT_EVENTS)) {
638 switch_core_session_queue_event(channel->session, &event);
639 } else {
640 switch_event_fire(&event)switch_event_fire_detailed("src/switch_channel.c", (const char
* )(const char *)__func__, 640, &event, ((void*)0))
;
641 }
642 }
643
644 return status;
645}
646
647SWITCH_DECLARE(switch_size_t)__attribute__((visibility("default"))) switch_size_t switch_channel_dequeue_dtmf_string(switch_channel_t *channel, char *dtmf_str, switch_size_t len)
648{
649 switch_size_t x = 0;
650 switch_dtmf_t dtmf = { 0 };
651
652 memset(dtmf_str, 0, len);
653
654 while (x < len - 1 && switch_channel_dequeue_dtmf(channel, &dtmf) == SWITCH_STATUS_SUCCESS) {
655 dtmf_str[x++] = dtmf.digit;
656 }
657
658 return x;
659
660}
661
662SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_channel_flush_dtmf(switch_channel_t *channel)
663{
664 void *pop;
665
666 switch_mutex_lock(channel->dtmf_mutex);
667 while (switch_queue_trypop(channel->dtmf_queue, &pop) == SWITCH_STATUS_SUCCESS) {
668 switch_dtmf_t *dt = (switch_dtmf_t *) pop;
669 if (channel->state >= CS_HANGUP || switch_queue_trypush(channel->dtmf_log_queue, dt) != SWITCH_STATUS_SUCCESS) {
670 free(dt);
671 }
672 }
673 switch_mutex_unlock(channel->dtmf_mutex);
674}
675
676SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_channel_uninit(switch_channel_t *channel)
677{
678 void *pop;
679 switch_channel_flush_dtmf(channel);
680 while (switch_queue_trypop(channel->dtmf_log_queue, &pop) == SWITCH_STATUS_SUCCESS) {
681 switch_safe_free(pop)if (pop) {free(pop);pop=((void*)0);};
682 }
683
684 if (channel->private_hash) {
685 switch_core_hash_destroy(&channel->private_hash);
686 }
687
688 if (channel->app_flag_hash) {
689 switch_core_hash_destroy(&channel->app_flag_hash);
690 }
691
692 switch_mutex_lock(channel->profile_mutex);
693 switch_event_destroy(&channel->variables);
694 switch_event_destroy(&channel->api_list);
695 switch_event_destroy(&channel->var_list);
696 switch_event_destroy(&channel->app_list);
697 switch_mutex_unlock(channel->profile_mutex);
698}
699
700SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_channel_init(switch_channel_t *channel, switch_core_session_t *session, switch_channel_state_t state,
701 switch_channel_flag_t flag)
702{
703 switch_assert(channel != NULL)((channel != ((void*)0)) ? (void) (0) : __assert_fail ("channel != ((void*)0)"
, "src/switch_channel.c", 703, __PRETTY_FUNCTION__))
;
704 channel->state = state;
705 switch_channel_set_flag(channel, flag)switch_channel_set_flag_value(channel, flag, 1);
706 channel->session = session;
707 channel->running_state = CS_NONE;
708 return SWITCH_STATUS_SUCCESS;
709}
710
711SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_channel_perform_presence(switch_channel_t *channel, const char *rpid, const char *status, const char *id,
712 const char *file, const char *func, int line)
713{
714 switch_event_t *event;
715 switch_event_types_t type = SWITCH_EVENT_PRESENCE_IN;
716 const char *call_info = NULL((void*)0);
717 char *call_info_state = "active";
718
719 if (switch_channel_test_flag(channel, CF_NO_PRESENCE)) {
720 return;
721 }
722
723 if (!status) {
724 type = SWITCH_EVENT_PRESENCE_OUT;
725 status = "idle";
726 }
727
728 if (!id) {
729 id = switch_channel_get_variable(channel, "presence_id")switch_channel_get_variable_dup(channel, "presence_id", SWITCH_TRUE
, -1)
;
730 }
731
732 if (!id) {
733 return;
734 }
735
736 call_info = switch_channel_get_variable(channel, "presence_call_info")switch_channel_get_variable_dup(channel, "presence_call_info"
, SWITCH_TRUE, -1)
;
737
738 if (switch_event_create(&event, type)switch_event_create_subclass_detailed("src/switch_channel.c",
(const char * )(const char *)__func__, 738, &event, type
, ((void*)0))
== SWITCH_STATUS_SUCCESS) {
739 switch_channel_event_set_data(channel, event);
740 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "proto", "any");
741 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "login", __FILE__"src/switch_channel.c");
742 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "from", id);
743 if (type == SWITCH_EVENT_PRESENCE_IN) {
744 if (!rpid) {
745 rpid = "unknown";
746 }
747 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "rpid", rpid);
748 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "status", status);
749 }
750 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "event_type", "presence");
751 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "alt_event_type", "dialog");
752
753
754 if (!strcasecmp(status, "idle") || !switch_channel_up_nosig(channel)(switch_channel_get_state(channel) < CS_HANGUP)) {
755 call_info_state = "idle";
756 } else if (!strcasecmp(status, "hold-private")) {
757 call_info_state = "held-private";
758 } else if (!strcasecmp(status, "hold")) {
759 call_info_state = "held";
760 } else if (!switch_channel_test_flag(channel, CF_ANSWERED)) {
761 if (channel->direction == SWITCH_CALL_DIRECTION_OUTBOUND) {
762 call_info_state = "progressing";
763 } else {
764 if (switch_channel_test_flag(channel, CF_SLA_INTERCEPT)) {
765 call_info_state = "idle";
766 } else {
767 call_info_state = "alerting";
768 }
769 }
770 }
771
772 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "presence-call-info-state", call_info_state);
773
774 if (call_info) {
775 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "presence-call-info", call_info);
776 }
777
778 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "presence-call-direction",
779 channel->direction == SWITCH_CALL_DIRECTION_OUTBOUND ? "outbound" : "inbound");
780
781 switch_event_add_header(event, SWITCH_STACK_BOTTOM, "event_count", "%d", channel->event_count++);
782 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Presence-Calling-File", file);
783 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Presence-Calling-Function", func);
784 switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Presence-Calling-Line", "%d", line);
785
786 if (switch_true(switch_channel_get_variable(channel, "presence_privacy")switch_channel_get_variable_dup(channel, "presence_privacy", SWITCH_TRUE
, -1)
)) {
787 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Presence-Privacy", "true");
788 }
789
790 switch_event_fire(&event)switch_event_fire_detailed("src/switch_channel.c", (const char
* )(const char *)__func__, 790, &event, ((void*)0))
;
791 }
792}
793
794SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_channel_mark_hold(switch_channel_t *channel, switch_bool_t on)
795{
796 switch_event_t *event;
797
798 if (!!on == !!switch_channel_test_flag(channel, CF_LEG_HOLDING)) {
799 goto end;
800 }
801
802 if (on) {
803 switch_channel_set_flag(channel, CF_LEG_HOLDING)switch_channel_set_flag_value(channel, CF_LEG_HOLDING, 1);
804 } else {
805 switch_channel_clear_flag(channel, CF_LEG_HOLDING);
806 }
807
808 if (switch_event_create(&event, on ? SWITCH_EVENT_CHANNEL_HOLD : SWITCH_EVENT_CHANNEL_UNHOLD)switch_event_create_subclass_detailed("src/switch_channel.c",
(const char * )(const char *)__func__, 808, &event, on ?
SWITCH_EVENT_CHANNEL_HOLD : SWITCH_EVENT_CHANNEL_UNHOLD, ((void
*)0))
== SWITCH_STATUS_SUCCESS) {
809 switch_channel_event_set_data(channel, event);
810 switch_event_fire(&event)switch_event_fire_detailed("src/switch_channel.c", (const char
* )(const char *)__func__, 810, &event, ((void*)0))
;
811 }
812
813 end:
814
815 if (on) {
816 if (switch_true(switch_channel_get_variable(channel, "flip_record_on_hold")switch_channel_get_variable_dup(channel, "flip_record_on_hold"
, SWITCH_TRUE, -1)
)) {
817 switch_core_session_t *other_session;
818 if (switch_core_session_get_partner(channel->session, &other_session)switch_core_session_perform_get_partner(channel->session, &
other_session, "src/switch_channel.c", (const char *)__func__
, 818)
== SWITCH_STATUS_SUCCESS) {
819 switch_core_media_bug_transfer_recordings(channel->session, other_session);
820 switch_core_session_rwunlock(other_session);
821 }
822 }
823 }
824
825}
826
827SWITCH_DECLARE(const char *)__attribute__((visibility("default"))) const char * switch_channel_get_hold_music(switch_channel_t *channel)
828{
829 const char *var;
830
831 if (!(var = switch_channel_get_variable(channel, SWITCH_TEMP_HOLD_MUSIC_VARIABLE)switch_channel_get_variable_dup(channel, "temp_hold_music", SWITCH_TRUE
, -1)
)) {
832 var = switch_channel_get_variable(channel, SWITCH_HOLD_MUSIC_VARIABLE)switch_channel_get_variable_dup(channel, "hold_music", SWITCH_TRUE
, -1)
;
833 }
834
835 if (!zstr(var)_zstr(var)) {
836 char *expanded = switch_channel_expand_variables(channel, var)switch_channel_expand_variables_check(channel, var, ((void*)0
), ((void*)0), 0)
;
837
838 if (expanded != var) {
839 var = switch_core_session_strdup(channel->session, expanded)switch_core_perform_session_strdup(channel->session, expanded
, "src/switch_channel.c", (const char *)__func__, 839)
;
840 free(expanded);
841 }
842 }
843
844
845 return var;
846}
847
848SWITCH_DECLARE(const char *)__attribute__((visibility("default"))) const char * switch_channel_get_hold_music_partner(switch_channel_t *channel)
849{
850 switch_core_session_t *session;
851 const char *r = NULL((void*)0);
852
853 if (switch_core_session_get_partner(channel->session, &session)switch_core_session_perform_get_partner(channel->session, &
session, "src/switch_channel.c", (const char *)__func__, 853)
== SWITCH_STATUS_SUCCESS) {
854 r = switch_channel_get_hold_music(switch_core_session_get_channel(session));
855 switch_core_session_rwunlock(session);
856 }
857
858 return r;
859}
860
861SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_channel_set_scope_variables(switch_channel_t *channel, switch_event_t **event)
862{
863 switch_mutex_lock(channel->profile_mutex);
864
865 if (event && *event) { /* push */
866 (*event)->next = channel->scope_variables;
867 channel->scope_variables = *event;
868 *event = NULL((void*)0);
869 } else if (channel->scope_variables) { /* pop */
870 switch_event_t *top_event = channel->scope_variables;
871 channel->scope_variables = channel->scope_variables->next;
872 switch_event_destroy(&top_event);
873 }
874
875 switch_mutex_unlock(channel->profile_mutex);
876
877}
878
879SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_channel_get_scope_variables(switch_channel_t *channel, switch_event_t **event)
880{
881 switch_status_t status = SWITCH_STATUS_FALSE;
882 switch_event_t *new_event;
883
884 switch_mutex_lock(channel->profile_mutex);
885 if (channel->scope_variables) {
886 switch_event_t *ep;
887 switch_event_header_t *hp;
888
889 switch_event_create_plain(&new_event, SWITCH_EVENT_CHANNEL_DATA);
890 status = SWITCH_STATUS_SUCCESS;
891 *event = new_event;
892
893 for (ep = channel->scope_variables; ep; ep = ep->next) {
894 for (hp = ep->headers; hp; hp = hp->next) {
895 if (!switch_event_get_header(new_event, hp->value)switch_event_get_header_idx(new_event, hp->value, -1)) {
896 switch_event_add_header_string(new_event, SWITCH_STACK_BOTTOM, hp->name, hp->value);
897 }
898 }
899 }
900 }
901 switch_mutex_unlock(channel->profile_mutex);
902
903 return status;
904}
905
906SWITCH_DECLARE(const char *)__attribute__((visibility("default"))) const char * switch_channel_get_variable_dup(switch_channel_t *channel, const char *varname, switch_bool_t dup, int idx)
907{
908 const char *v = NULL((void*)0), *r = NULL((void*)0), *vdup = NULL((void*)0);
909 switch_assert(channel != NULL)((channel != ((void*)0)) ? (void) (0) : __assert_fail ("channel != ((void*)0)"
, "src/switch_channel.c", 909, __PRETTY_FUNCTION__))
;
910
911 switch_mutex_lock(channel->profile_mutex);
912
913 if (channel->scope_variables) {
914 switch_event_t *ep;
915
916 for (ep = channel->scope_variables; ep; ep = ep->next) {
917 if ((v = switch_event_get_header_idx(ep, varname, idx))) {
918 break;
919 }
920 }
921 }
922
923 if (!v && (!channel->variables || !(v = switch_event_get_header_idx(channel->variables, varname, idx)))) {
924 switch_caller_profile_t *cp = switch_channel_get_caller_profile(channel);
925
926 if (cp) {
927 if (!strncmp(varname, "aleg_", 5)(__extension__ (__builtin_constant_p (5) && ((__builtin_constant_p
(varname) && strlen (varname) < ((size_t) (5))) ||
(__builtin_constant_p ("aleg_") && strlen ("aleg_") <
((size_t) (5)))) ? __extension__ ({ size_t __s1_len, __s2_len
; (__builtin_constant_p (varname) && __builtin_constant_p
("aleg_") && (__s1_len = __builtin_strlen (varname),
__s2_len = __builtin_strlen ("aleg_"), (!((size_t)(const void
*)((varname) + 1) - (size_t)(const void *)(varname) == 1) ||
__s1_len >= 4) && (!((size_t)(const void *)(("aleg_"
) + 1) - (size_t)(const void *)("aleg_") == 1) || __s2_len >=
4)) ? __builtin_strcmp (varname, "aleg_") : (__builtin_constant_p
(varname) && ((size_t)(const void *)((varname) + 1) -
(size_t)(const void *)(varname) == 1) && (__s1_len =
__builtin_strlen (varname), __s1_len < 4) ? (__builtin_constant_p
("aleg_") && ((size_t)(const void *)(("aleg_") + 1) -
(size_t)(const void *)("aleg_") == 1) ? __builtin_strcmp (varname
, "aleg_") : (__extension__ ({ const unsigned char *__s2 = (const
unsigned char *) (const char *) ("aleg_"); int __result = ((
(const unsigned char *) (const char *) (varname))[0] - __s2[0
]); if (__s1_len > 0 && __result == 0) { __result =
(((const unsigned char *) (const char *) (varname))[1] - __s2
[1]); if (__s1_len > 1 && __result == 0) { __result
= (((const unsigned char *) (const char *) (varname))[2] - __s2
[2]); if (__s1_len > 2 && __result == 0) __result =
(((const unsigned char *) (const char *) (varname))[3] - __s2
[3]); } } __result; }))) : (__builtin_constant_p ("aleg_") &&
((size_t)(const void *)(("aleg_") + 1) - (size_t)(const void
*)("aleg_") == 1) && (__s2_len = __builtin_strlen ("aleg_"
), __s2_len < 4) ? (__builtin_constant_p (varname) &&
((size_t)(const void *)((varname) + 1) - (size_t)(const void
*)(varname) == 1) ? __builtin_strcmp (varname, "aleg_") : (-
(__extension__ ({ const unsigned char *__s2 = (const unsigned
char *) (const char *) (varname); int __result = (((const unsigned
char *) (const char *) ("aleg_"))[0] - __s2[0]); if (__s2_len
> 0 && __result == 0) { __result = (((const unsigned
char *) (const char *) ("aleg_"))[1] - __s2[1]); if (__s2_len
> 1 && __result == 0) { __result = (((const unsigned
char *) (const char *) ("aleg_"))[2] - __s2[2]); if (__s2_len
> 2 && __result == 0) __result = (((const unsigned
char *) (const char *) ("aleg_"))[3] - __s2[3]); } } __result
; })))) : __builtin_strcmp (varname, "aleg_")))); }) : strncmp
(varname, "aleg_", 5)))
) {
928 cp = cp->originator_caller_profile;
929 varname += 5;
930 } else if (!strncmp(varname, "bleg_", 5)(__extension__ (__builtin_constant_p (5) && ((__builtin_constant_p
(varname) && strlen (varname) < ((size_t) (5))) ||
(__builtin_constant_p ("bleg_") && strlen ("bleg_") <
((size_t) (5)))) ? __extension__ ({ size_t __s1_len, __s2_len
; (__builtin_constant_p (varname) && __builtin_constant_p
("bleg_") && (__s1_len = __builtin_strlen (varname),
__s2_len = __builtin_strlen ("bleg_"), (!((size_t)(const void
*)((varname) + 1) - (size_t)(const void *)(varname) == 1) ||
__s1_len >= 4) && (!((size_t)(const void *)(("bleg_"
) + 1) - (size_t)(const void *)("bleg_") == 1) || __s2_len >=
4)) ? __builtin_strcmp (varname, "bleg_") : (__builtin_constant_p
(varname) && ((size_t)(const void *)((varname) + 1) -
(size_t)(const void *)(varname) == 1) && (__s1_len =
__builtin_strlen (varname), __s1_len < 4) ? (__builtin_constant_p
("bleg_") && ((size_t)(const void *)(("bleg_") + 1) -
(size_t)(const void *)("bleg_") == 1) ? __builtin_strcmp (varname
, "bleg_") : (__extension__ ({ const unsigned char *__s2 = (const
unsigned char *) (const char *) ("bleg_"); int __result = ((
(const unsigned char *) (const char *) (varname))[0] - __s2[0
]); if (__s1_len > 0 && __result == 0) { __result =
(((const unsigned char *) (const char *) (varname))[1] - __s2
[1]); if (__s1_len > 1 && __result == 0) { __result
= (((const unsigned char *) (const char *) (varname))[2] - __s2
[2]); if (__s1_len > 2 && __result == 0) __result =
(((const unsigned char *) (const char *) (varname))[3] - __s2
[3]); } } __result; }))) : (__builtin_constant_p ("bleg_") &&
((size_t)(const void *)(("bleg_") + 1) - (size_t)(const void
*)("bleg_") == 1) && (__s2_len = __builtin_strlen ("bleg_"
), __s2_len < 4) ? (__builtin_constant_p (varname) &&
((size_t)(const void *)((varname) + 1) - (size_t)(const void
*)(varname) == 1) ? __builtin_strcmp (varname, "bleg_") : (-
(__extension__ ({ const unsigned char *__s2 = (const unsigned
char *) (const char *) (varname); int __result = (((const unsigned
char *) (const char *) ("bleg_"))[0] - __s2[0]); if (__s2_len
> 0 && __result == 0) { __result = (((const unsigned
char *) (const char *) ("bleg_"))[1] - __s2[1]); if (__s2_len
> 1 && __result == 0) { __result = (((const unsigned
char *) (const char *) ("bleg_"))[2] - __s2[2]); if (__s2_len
> 2 && __result == 0) __result = (((const unsigned
char *) (const char *) ("bleg_"))[3] - __s2[3]); } } __result
; })))) : __builtin_strcmp (varname, "bleg_")))); }) : strncmp
(varname, "bleg_", 5)))
) {
931 cp = cp->originatee_caller_profile;
932 varname += 5;
933 }
934 }
935
936 if (!cp || !(v = switch_caller_get_field_by_name(cp, varname))) {
937 if ((vdup = switch_core_get_variable_pdup(varname, switch_core_session_get_pool(channel->session)))) {
938 v = vdup;
939 }
940 }
941 }
942
943 if (dup && v != vdup) {
944 if (v) {
945 r = switch_core_session_strdup(channel->session, v)switch_core_perform_session_strdup(channel->session, v, "src/switch_channel.c"
, (const char *)__func__, 945)
;
946 }
947 } else {
948 r = v;
949 }
950
951 switch_mutex_unlock(channel->profile_mutex);
952
953 return r;
954}
955
956SWITCH_DECLARE(const char *)__attribute__((visibility("default"))) const char * switch_channel_get_variable_partner(switch_channel_t *channel, const char *varname)
957{
958 const char *uuid;
959 const char *val = NULL((void*)0), *r = NULL((void*)0);
960 switch_assert(channel != NULL)((channel != ((void*)0)) ? (void) (0) : __assert_fail ("channel != ((void*)0)"
, "src/switch_channel.c", 960, __PRETTY_FUNCTION__))
;
961
962 if (!zstr(varname)_zstr(varname)) {
963 if ((uuid = switch_channel_get_partner_uuid(channel))) {
964 switch_core_session_t *session;
965 if ((session = switch_core_session_locate(uuid)switch_core_session_perform_locate(uuid, "src/switch_channel.c"
, (const char *)__func__, 965)
)) {
966 switch_channel_t *tchannel = switch_core_session_get_channel(session);
967 val = switch_channel_get_variable(tchannel, varname)switch_channel_get_variable_dup(tchannel, varname, SWITCH_TRUE
, -1)
;
968 switch_core_session_rwunlock(session);
969 }
970 }
971 }
972
973 if (val)
974 r = switch_core_session_strdup(channel->session, val)switch_core_perform_session_strdup(channel->session, val, "src/switch_channel.c"
, (const char *)__func__, 974)
;
975
976 return r;
977}
978
979
980SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_channel_variable_last(switch_channel_t *channel)
981{
982 switch_assert(channel != NULL)((channel != ((void*)0)) ? (void) (0) : __assert_fail ("channel != ((void*)0)"
, "src/switch_channel.c", 982, __PRETTY_FUNCTION__))
;
983 if (!channel->vi) {
984 return;
985 }
986 channel->vi = 0;
987 switch_mutex_unlock(channel->profile_mutex);
988
989}
990
991SWITCH_DECLARE(switch_event_header_t *)__attribute__((visibility("default"))) switch_event_header_t * switch_channel_variable_first(switch_channel_t *channel)
992{
993 switch_event_header_t *hi = NULL((void*)0);
994
995 switch_assert(channel != NULL)((channel != ((void*)0)) ? (void) (0) : __assert_fail ("channel != ((void*)0)"
, "src/switch_channel.c", 995, __PRETTY_FUNCTION__))
;
996 switch_mutex_lock(channel->profile_mutex);
997 if (channel->variables && (hi = channel->variables->headers)) {
998 channel->vi = 1;
999 } else {
1000 switch_mutex_unlock(channel->profile_mutex);
1001 }
1002
1003 return hi;
1004}
1005
1006SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_channel_set_private(switch_channel_t *channel, const char *key, const void *private_info)
1007{
1008 switch_assert(channel != NULL)((channel != ((void*)0)) ? (void) (0) : __assert_fail ("channel != ((void*)0)"
, "src/switch_channel.c", 1008, __PRETTY_FUNCTION__))
;
1009 switch_core_hash_insert_locked(channel->private_hash, key, private_info, channel->profile_mutex);
1010 return SWITCH_STATUS_SUCCESS;
1011}
1012
1013SWITCH_DECLARE(void *)__attribute__((visibility("default"))) void * switch_channel_get_private(switch_channel_t *channel, const char *key)
1014{
1015 void *val;
1016 switch_assert(channel != NULL)((channel != ((void*)0)) ? (void) (0) : __assert_fail ("channel != ((void*)0)"
, "src/switch_channel.c", 1016, __PRETTY_FUNCTION__))
;
1017 val = switch_core_hash_find_locked(channel->private_hash, key, channel->profile_mutex);
1018 return val;
1019}
1020
1021SWITCH_DECLARE(void *)__attribute__((visibility("default"))) void * switch_channel_get_private_partner(switch_channel_t *channel, const char *key)
1022{
1023 const char *uuid;
1024 void *val = NULL((void*)0);
1025
1026 switch_assert(channel != NULL)((channel != ((void*)0)) ? (void) (0) : __assert_fail ("channel != ((void*)0)"
, "src/switch_channel.c", 1026, __PRETTY_FUNCTION__))
;
1027
1028 if ((uuid = switch_channel_get_partner_uuid(channel))) {
1029 switch_core_session_t *session;
1030 if ((session = switch_core_session_locate(uuid)switch_core_session_perform_locate(uuid, "src/switch_channel.c"
, (const char *)__func__, 1030)
)) {
1031 val = switch_core_hash_find_locked(channel->private_hash, key, channel->profile_mutex);
1032 switch_core_session_rwunlock(session);
1033 }
1034 }
1035
1036 return val;
1037}
1038
1039SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_channel_set_name(switch_channel_t *channel, const char *name)
1040{
1041 const char *old = NULL((void*)0);
1042
1043 switch_assert(channel != NULL)((channel != ((void*)0)) ? (void) (0) : __assert_fail ("channel != ((void*)0)"
, "src/switch_channel.c", 1043, __PRETTY_FUNCTION__))
;
1044 if (!zstr(channel->name)_zstr(channel->name)) {
1045 old = channel->name;
1046 }
1047 channel->name = NULL((void*)0);
1048 if (name) {
1049 char *uuid = switch_core_session_get_uuid(channel->session);
1050 channel->name = switch_core_session_strdup(channel->session, name)switch_core_perform_session_strdup(channel->session, name,
"src/switch_channel.c", (const char *)__func__, 1050)
;
1051 switch_channel_set_variable(channel, SWITCH_CHANNEL_NAME_VARIABLE, name)switch_channel_set_variable_var_check(channel, "channel_name"
, name, SWITCH_TRUE)
;
1052 if (old) {
1053 switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel)SWITCH_CHANNEL_ID_SESSION, "src/switch_channel.c", (const char
*)__func__, 1053, (const char*)switch_channel_get_session(channel
)
, SWITCH_LOG_NOTICE, "Rename Channel %s->%s [%s]\n", old, name, uuid);
1054 } else {
1055 switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel)SWITCH_CHANNEL_ID_SESSION, "src/switch_channel.c", (const char
*)__func__, 1055, (const char*)switch_channel_get_session(channel
)
, SWITCH_LOG_NOTICE, "New Channel %s [%s]\n", name, uuid);
1056 }
1057 }
1058 return SWITCH_STATUS_SUCCESS;
1059}
1060
1061SWITCH_DECLARE(char *)__attribute__((visibility("default"))) char * switch_channel_get_name(switch_channel_t *channel)
1062{
1063 switch_assert(channel != NULL)((channel != ((void*)0)) ? (void) (0) : __assert_fail ("channel != ((void*)0)"
, "src/switch_channel.c", 1063, __PRETTY_FUNCTION__))
;
1064 return (!zstr(channel->name)_zstr(channel->name)) ? channel->name : "N/A";
1065}
1066
1067SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_channel_set_profile_var(switch_channel_t *channel, const char *name, const char *val)
1068{
1069 char *v;
1070 switch_status_t status = SWITCH_STATUS_SUCCESS;
1071
1072 switch_mutex_lock(channel->profile_mutex);
1073
1074
1075 if (!strcasecmp(name, "device_id") && !zstr(val)_zstr(val)) {
1076 const char *device_id;
1077 if (!(device_id = switch_channel_set_device_id(channel, val))) {
1078 /* one time setting */
1079 switch_mutex_unlock(channel->profile_mutex);
1080 return status;
1081 }
1082
1083 val = device_id;
1084 }
1085
1086 if (!zstr(val)_zstr(val)) {
1087 v = switch_core_strdup(channel->caller_profile->pool, val)switch_core_perform_strdup(channel->caller_profile->pool
, val, "src/switch_channel.c", (const char *)__func__, 1087)
;
1088 } else {
1089 v = SWITCH_BLANK_STRING"";
1090 }
1091
1092 if (!strcasecmp(name, "dialplan")) {
1093 channel->caller_profile->dialplan = v;
1094 } else if (!strcasecmp(name, "username")) {
1095 channel->caller_profile->username = v;
1096 } else if (!strcasecmp(name, "caller_id_name")) {
1097 channel->caller_profile->caller_id_name = v;
1098 } else if (!strcasecmp(name, "caller_id_number")) {
1099 channel->caller_profile->caller_id_number = v;
1100 } else if (!strcasecmp(name, "callee_id_name")) {
1101 channel->caller_profile->callee_id_name = v;
1102 } else if (!strcasecmp(name, "callee_id_number")) {
1103 channel->caller_profile->callee_id_number = v;
1104 } else if (val && !strcasecmp(name, "caller_ton")) {
1105 channel->caller_profile->caller_ton = (uint8_t) atoi(v);
1106 } else if (val && !strcasecmp(name, "caller_numplan")) {
1107 channel->caller_profile->caller_numplan = (uint8_t) atoi(v);
1108 } else if (val && !strcasecmp(name, "destination_number_ton")) {
1109 channel->caller_profile->destination_number_ton = (uint8_t) atoi(v);
1110 } else if (val && !strcasecmp(name, "destination_number_numplan")) {
1111 channel->caller_profile->destination_number_numplan = (uint8_t) atoi(v);
1112 } else if (!strcasecmp(name, "ani")) {
1113 channel->caller_profile->ani = v;
1114 } else if (!strcasecmp(name, "aniii")) {
1115 channel->caller_profile->aniii = v;
1116 } else if (!strcasecmp(name, "network_addr")) {
1117 channel->caller_profile->network_addr = v;
1118 } else if (!strcasecmp(name, "rdnis")) {
1119 channel->caller_profile->rdnis = v;
1120 } else if (!strcasecmp(name, "destination_number")) {
1121 channel->caller_profile->destination_number = v;
1122 } else if (!strcasecmp(name, "uuid")) {
1123 channel->caller_profile->uuid = v;
1124 } else if (!strcasecmp(name, "source")) {
1125 channel->caller_profile->source = v;
1126 } else if (!strcasecmp(name, "context")) {
1127 channel->caller_profile->context = v;
1128 } else if (!strcasecmp(name, "chan_name")) {
1129 channel->caller_profile->chan_name = v;
1130 } else {
1131 profile_node_t *pn, *n = switch_core_alloc(channel->caller_profile->pool, sizeof(*n))switch_core_perform_alloc(channel->caller_profile->pool
, sizeof(*n), "src/switch_channel.c", (const char *)__func__,
1131)
;
1132 int var_found;
1133
1134 n->var = switch_core_strdup(channel->caller_profile->pool, name)switch_core_perform_strdup(channel->caller_profile->pool
, name, "src/switch_channel.c", (const char *)__func__, 1134)
;
1135 n->val = v;
1136
1137 if (!channel->caller_profile->soft) {
1138 channel->caller_profile->soft = n;
1139 } else {
1140 var_found = 0;
1141
1142 for(pn = channel->caller_profile->soft; pn ; pn = pn->next) {
1143 if (!strcasecmp(pn->var,n->var)) {
1144 pn->val = n->val;
1145 var_found = 1;
1146 break;
1147 }
1148
1149 if(!pn->next) {
1150 break;
1151 }
1152 }
1153
1154 if (pn && !pn->next && !var_found) {
1155 pn->next = n;
1156 }
1157 }
1158 }
1159 switch_mutex_unlock(channel->profile_mutex);
1160
1161 return status;
1162}
1163
1164
1165SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_channel_process_export(switch_channel_t *channel, switch_channel_t *peer_channel,
1166 switch_event_t *var_event, const char *export_varname)
1167{
1168
1169 const char *export_vars = switch_channel_get_variable(channel, export_varname)switch_channel_get_variable_dup(channel, export_varname, SWITCH_TRUE
, -1)
;
1170 char *cptmp = switch_core_session_strdup(channel->session, export_vars)switch_core_perform_session_strdup(channel->session, export_vars
, "src/switch_channel.c", (const char *)__func__, 1170)
;
1171 int argc;
1172 char *argv[256];
1173
1174 if (zstr(export_vars)_zstr(export_vars)) return;
1175
1176
1177 if (var_event) {
1178 switch_event_del_header(var_event, export_varname)switch_event_del_header_val(var_event, export_varname, ((void
*)0))
;
1179 switch_event_add_header_string(var_event, SWITCH_STACK_BOTTOM, export_varname, export_vars);
1180 }
1181
1182 if (peer_channel) {
1183 switch_channel_set_variable(peer_channel, export_varname, export_vars)switch_channel_set_variable_var_check(peer_channel, export_varname
, export_vars, SWITCH_TRUE)
;
1184 }
1185
1186 if ((argc = switch_separate_string(cptmp, ',', argv, (sizeof(argv) / sizeof(argv[0]))))) {
1187 int x;
1188
1189 for (x = 0; x < argc; x++) {
1190 const char *vval;
1191 if ((vval = switch_channel_get_variable(channel, argv[x])switch_channel_get_variable_dup(channel, argv[x], SWITCH_TRUE
, -1)
)) {
1192 char *vvar = argv[x];
1193 if (!strncasecmp(vvar, "nolocal:", 8)) { /* remove this later ? */
1194 vvar += 8;
1195 } else if (!strncasecmp(vvar, "_nolocal_", 9)) {
1196 vvar += 9;
1197 }
1198 if (var_event) {
1199 switch_event_del_header(var_event, vvar)switch_event_del_header_val(var_event, vvar, ((void*)0));
1200 switch_event_add_header_string(var_event, SWITCH_STACK_BOTTOM, vvar, vval);
1201 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(channel->session)SWITCH_CHANNEL_ID_SESSION, "src/switch_channel.c", (const char
*)__func__, 1201, (const char*)(channel->session)
, SWITCH_LOG_DEBUG,
1202 "%s EXPORTING[%s] [%s]=[%s] to event\n",
1203 switch_channel_get_name(channel),
1204 export_varname,
1205 vvar, vval);
1206 }
1207 if (peer_channel) {
1208 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(channel->session)SWITCH_CHANNEL_ID_SESSION, "src/switch_channel.c", (const char
*)__func__, 1208, (const char*)(channel->session)
, SWITCH_LOG_DEBUG,
1209 "%s EXPORTING[%s] [%s]=[%s] to %s\n",
1210 switch_channel_get_name(channel),
1211 export_varname,
1212 vvar, vval, switch_channel_get_name(peer_channel));
1213 switch_channel_set_variable(peer_channel, vvar, vval)switch_channel_set_variable_var_check(peer_channel, vvar, vval
, SWITCH_TRUE)
;
1214 }
1215 }
1216 }
1217 }
1218
1219
1220}
1221
1222SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_channel_export_variable_var_check(switch_channel_t *channel,
1223 const char *varname, const char *val,
1224 const char *export_varname, switch_bool_t var_check)
1225{
1226 char *var_name = NULL((void*)0);
1227 const char *exports;
1228 char *var, *new_exports, *new_exports_d = NULL((void*)0);
1229 int local = 1;
1230
1231 exports = switch_channel_get_variable(channel, export_varname)switch_channel_get_variable_dup(channel, export_varname, SWITCH_TRUE
, -1)
;
1232
1233 var = switch_core_session_strdup(channel->session, varname)switch_core_perform_session_strdup(channel->session, varname
, "src/switch_channel.c", (const char *)__func__, 1233)
;
1234
1235 if (var) {
1236 if (!strncasecmp(var, "nolocal:", 8)) { /* remove this later ? */
1237 var_name = var + 8;
1238 local = 0;
1239 } else if (!strncasecmp(var, "_nolocal_", 9)) {
1240 var_name = var + 9;
1241 local = 0;
1242 } else {
1243 var_name = var;
1244 }
1245 }
1246
1247 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(channel->session)SWITCH_CHANNEL_ID_SESSION, "src/switch_channel.c", (const char
*)__func__, 1247, (const char*)(channel->session)
, SWITCH_LOG_DEBUG, "EXPORT (%s) %s[%s]=[%s]\n",
1248 export_varname, local ? "" : "(REMOTE ONLY) ",
1249 var_name ? var_name : "", val ? val : "UNDEF");
1250
1251
1252 switch_channel_set_variable_var_check(channel, var, val, var_check);
1253
1254 if (var && val) {
1255 if (exports) {
1256 new_exports_d = switch_mprintf("%s,%s", exports, var);
1257 new_exports = new_exports_d;
1258 } else {
1259 new_exports = var;
1260 }
1261
1262 switch_channel_set_variable(channel, export_varname, new_exports)switch_channel_set_variable_var_check(channel, export_varname
, new_exports, SWITCH_TRUE)
;
1263
1264 switch_safe_free(new_exports_d)if (new_exports_d) {free(new_exports_d);new_exports_d=((void*
)0);}
;
1265 }
1266
1267 return SWITCH_STATUS_SUCCESS;
1268}
1269
1270SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_channel_export_variable_printf(switch_channel_t *channel, const char *varname,
1271 const char *export_varname, const char *fmt, ...)
1272{
1273 switch_status_t status = SWITCH_STATUS_FALSE;
1274 char *data = NULL((void*)0);
1275 va_list ap;
1276 int ret;
1277
1278 switch_assert(channel != NULL)((channel != ((void*)0)) ? (void) (0) : __assert_fail ("channel != ((void*)0)"
, "src/switch_channel.c", 1278, __PRETTY_FUNCTION__))
;
1279
1280 va_start(ap, fmt)__builtin_va_start(ap, fmt);
1281 ret = switch_vasprintf(&data, fmt, ap);
1282 va_end(ap)__builtin_va_end(ap);
1283
1284 if (ret == -1) {
1285 return SWITCH_STATUS_FALSE;
1286 }
1287
1288 status = switch_channel_export_variable(channel, varname, data, export_varname)switch_channel_export_variable_var_check(channel, varname, data
, export_varname, SWITCH_TRUE)
;
1289
1290 free(data);
1291
1292 return status;
1293}
1294
1295
1296SWITCH_DECLARE(uint32_t)__attribute__((visibility("default"))) uint32_t switch_channel_del_variable_prefix(switch_channel_t *channel, const char *prefix)
1297{
1298 switch_event_t *event;
1299 switch_event_header_t *hp;
1300 uint32_t r = 0;
1301
1302 switch_channel_get_variables(channel, &event);
1303
1304 if (event) {
1305 for (hp = event->headers; hp; hp = hp->next) {
1306 if (zstr(prefix)_zstr(prefix) || !strncasecmp(hp->name, prefix, strlen(prefix))) {
1307 switch_channel_set_variable(channel, hp->name, NULL)switch_channel_set_variable_var_check(channel, hp->name, (
(void*)0), SWITCH_TRUE)
;
1308 }
1309 }
1310 }
1311
1312 switch_event_destroy(&event);
1313
1314 return r;
1315}
1316
1317SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_channel_transfer_variable_prefix(switch_channel_t *orig_channel, switch_channel_t *new_channel, const char *prefix)
1318{
1319 switch_event_header_t *hi = NULL((void*)0);
1320 int x = 0;
1321
1322 if ((hi = switch_channel_variable_first(orig_channel))) {
1323 for (; hi; hi = hi->next) {
1324 char *var = hi->name;
1325 char *val = hi->value;
1326
1327 if (zstr(prefix)_zstr(prefix) || !strncasecmp(var, prefix, strlen(prefix))) {
1328 x++;
1329 switch_channel_set_variable(new_channel, var, val)switch_channel_set_variable_var_check(new_channel, var, val, SWITCH_TRUE
)
;
1330 }
1331 }
1332 switch_channel_variable_last(orig_channel);
1333 }
1334
1335 return x ? SWITCH_STATUS_SUCCESS : SWITCH_STATUS_FALSE;
1336}
1337
1338SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_channel_set_presence_data_vals(switch_channel_t *channel, const char *presence_data_cols)
1339{
1340 char *cols[128] = { 0 };
1341 char header_name[128] = "";
1342 int col_count = 0, i = 0;
1343 char *data_copy = NULL((void*)0);
1344
1345 if (zstr(presence_data_cols)_zstr(presence_data_cols)) {
1346 presence_data_cols = switch_channel_get_variable_dup(channel, "presence_data_cols", SWITCH_FALSE, -1);
1347 if (zstr(presence_data_cols)_zstr(presence_data_cols)) {
1348 return;
1349 }
1350 }
1351
1352 data_copy = strdup(presence_data_cols)(__extension__ (__builtin_constant_p (presence_data_cols) &&
((size_t)(const void *)((presence_data_cols) + 1) - (size_t)
(const void *)(presence_data_cols) == 1) ? (((const char *) (
presence_data_cols))[0] == '\0' ? (char *) calloc ((size_t) 1
, (size_t) 1) : ({ size_t __len = strlen (presence_data_cols)
+ 1; char *__retval = (char *) malloc (__len); if (__retval !=
((void*)0)) __retval = (char *) memcpy (__retval, presence_data_cols
, __len); __retval; })) : __strdup (presence_data_cols)))
;
1353
1354 col_count = switch_split(data_copy, ':', cols)switch_separate_string(data_copy, ':', cols, (sizeof(cols) / sizeof
(cols[0])))
;
1355
1356 for (i = 0; i < col_count; i++) {
1357 const char *val = NULL((void*)0);
1358 switch_snprintf(header_name, sizeof(header_name), "PD-%s", cols[i]);
1359 val = switch_channel_get_variable(channel, cols[i])switch_channel_get_variable_dup(channel, cols[i], SWITCH_TRUE
, -1)
;
1360 switch_channel_set_profile_var(channel, header_name, val);
1361 }
1362
1363 switch_safe_free(data_copy)if (data_copy) {free(data_copy);data_copy=((void*)0);};
1364}
1365
1366
1367SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_channel_set_variable_var_check(switch_channel_t *channel,
1368 const char *varname, const char *value, switch_bool_t var_check)
1369{
1370 switch_status_t status = SWITCH_STATUS_FALSE;
1371
1372 switch_assert(channel != NULL)((channel != ((void*)0)) ? (void) (0) : __assert_fail ("channel != ((void*)0)"
, "src/switch_channel.c", 1372, __PRETTY_FUNCTION__))
;
1373
1374 switch_mutex_lock(channel->profile_mutex);
1375 if (channel->variables && !zstr(varname)_zstr(varname)) {
1376 if (zstr(value)_zstr(value)) {
1377 switch_event_del_header(channel->variables, varname)switch_event_del_header_val(channel->variables, varname, (
(void*)0))
;
1378 } else {
1379 int ok = 1;
1380
1381 if (var_check) {
1382 ok = !switch_string_var_check_const(value);
1383 }
1384 if (ok) {
1385 switch_event_add_header_string(channel->variables, SWITCH_STACK_BOTTOM, varname, value);
1386 } else {
1387 switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel)SWITCH_CHANNEL_ID_SESSION, "src/switch_channel.c", (const char
*)__func__, 1387, (const char*)switch_channel_get_session(channel
)
, SWITCH_LOG_CRIT, "Invalid data (${%s} contains a variable)\n", varname);
1388 }
1389 }
1390 status = SWITCH_STATUS_SUCCESS;
1391 }
1392 switch_mutex_unlock(channel->profile_mutex);
1393
1394 return status;
1395}
1396
1397
1398SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_channel_add_variable_var_check(switch_channel_t *channel,
1399 const char *varname, const char *value, switch_bool_t var_check, switch_stack_t stack)
1400{
1401 switch_status_t status = SWITCH_STATUS_FALSE;
1402
1403 switch_assert(channel != NULL)((channel != ((void*)0)) ? (void) (0) : __assert_fail ("channel != ((void*)0)"
, "src/switch_channel.c", 1403, __PRETTY_FUNCTION__))
;
1404
1405 switch_mutex_lock(channel->profile_mutex);
1406 if (channel->variables && !zstr(varname)_zstr(varname)) {
1407 if (zstr(value)_zstr(value)) {
1408 switch_event_del_header(channel->variables, varname)switch_event_del_header_val(channel->variables, varname, (
(void*)0))
;
1409 } else {
1410 int ok = 1;
1411
1412 if (var_check) {
1413 ok = !switch_string_var_check_const(value);
1414 }
1415 if (ok) {
1416 switch_event_add_header_string(channel->variables, stack, varname, value);
1417 } else {
1418 switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel)SWITCH_CHANNEL_ID_SESSION, "src/switch_channel.c", (const char
*)__func__, 1418, (const char*)switch_channel_get_session(channel
)
, SWITCH_LOG_CRIT, "Invalid data (${%s} contains a variable)\n", varname);
1419 }
1420 }
1421 status = SWITCH_STATUS_SUCCESS;
1422 }
1423 switch_mutex_unlock(channel->profile_mutex);
1424
1425 return status;
1426}
1427
1428
1429switch_status_t switch_event_base_add_header(switch_event_t *event, switch_stack_t stack, const char *header_name, char *data);
1430
1431SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_channel_set_variable_printf(switch_channel_t *channel, const char *varname, const char *fmt, ...)
1432{
1433 int ret = 0;
1434 char *data;
1435 va_list ap;
1436 switch_status_t status = SWITCH_STATUS_FALSE;
1437
1438 switch_assert(channel != NULL)((channel != ((void*)0)) ? (void) (0) : __assert_fail ("channel != ((void*)0)"
, "src/switch_channel.c", 1438, __PRETTY_FUNCTION__))
;
1439
1440 switch_mutex_lock(channel->profile_mutex);
1441 if (channel->variables && !zstr(varname)_zstr(varname)) {
1442 switch_event_del_header(channel->variables, varname)switch_event_del_header_val(channel->variables, varname, (
(void*)0))
;
1443
1444 va_start(ap, fmt)__builtin_va_start(ap, fmt);
1445 ret = switch_vasprintf(&data, fmt, ap);
1446 va_end(ap)__builtin_va_end(ap);
1447
1448 if (ret == -1) {
1449 switch_mutex_unlock(channel->profile_mutex);
1450 return SWITCH_STATUS_MEMERR;
1451 }
1452
1453 status = switch_channel_set_variable(channel, varname, data)switch_channel_set_variable_var_check(channel, varname, data,
SWITCH_TRUE)
;
1454 free(data);
1455 }
1456 switch_mutex_unlock(channel->profile_mutex);
1457
1458 return status;
1459}
1460
1461
1462SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_channel_set_variable_name_printf(switch_channel_t *channel, const char *val, const char *fmt, ...)
1463{
1464 int ret = 0;
1465 char *varname;
1466 va_list ap;
1467 switch_status_t status = SWITCH_STATUS_FALSE;
1468
1469 switch_assert(channel != NULL)((channel != ((void*)0)) ? (void) (0) : __assert_fail ("channel != ((void*)0)"
, "src/switch_channel.c", 1469, __PRETTY_FUNCTION__))
;
1470
1471 switch_mutex_lock(channel->profile_mutex);
1472
1473 va_start(ap, fmt)__builtin_va_start(ap, fmt);
1474 ret = switch_vasprintf(&varname, fmt, ap);
1475 va_end(ap)__builtin_va_end(ap);
1476
1477 if (ret == -1) {
1478 switch_mutex_unlock(channel->profile_mutex);
1479 return SWITCH_STATUS_MEMERR;
1480 }
1481
1482 status = switch_channel_set_variable(channel, varname, val)switch_channel_set_variable_var_check(channel, varname, val, SWITCH_TRUE
)
;
1483
1484 free(varname);
1485
1486 switch_mutex_unlock(channel->profile_mutex);
1487
1488 return status;
1489}
1490
1491
1492SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_channel_set_variable_partner_var_check(switch_channel_t *channel,
1493 const char *varname, const char *value, switch_bool_t var_check)
1494{
1495 const char *uuid;
1496 switch_assert(channel != NULL)((channel != ((void*)0)) ? (void) (0) : __assert_fail ("channel != ((void*)0)"
, "src/switch_channel.c", 1496, __PRETTY_FUNCTION__))
;
1497
1498 if (!zstr(varname)_zstr(varname)) {
1499 if ((uuid = switch_channel_get_partner_uuid(channel))) {
1500 switch_core_session_t *session;
1501 if ((session = switch_core_session_locate(uuid)switch_core_session_perform_locate(uuid, "src/switch_channel.c"
, (const char *)__func__, 1501)
)) {
1502 switch_channel_t *tchannel = switch_core_session_get_channel(session);
1503 switch_channel_set_variable_var_check(tchannel, varname, value, var_check);
1504 switch_core_session_rwunlock(session);
1505 }
1506 return SWITCH_STATUS_SUCCESS;
1507 }
1508 }
1509
1510 return SWITCH_STATUS_FALSE;
1511}
1512
1513SWITCH_DECLARE(uint32_t)__attribute__((visibility("default"))) uint32_t switch_channel_test_flag(switch_channel_t *channel, switch_channel_flag_t flag)
1514{
1515 uint32_t r = 0;
1516
1517 switch_assert(channel != NULL)((channel != ((void*)0)) ? (void) (0) : __assert_fail ("channel != ((void*)0)"
, "src/switch_channel.c", 1517, __PRETTY_FUNCTION__))
;
1518
1519 switch_mutex_lock(channel->flag_mutex);
1520 r = channel->flags[flag];
1521 switch_mutex_unlock(channel->flag_mutex);
1522
1523 return r;
1524}
1525
1526SWITCH_DECLARE(switch_bool_t)__attribute__((visibility("default"))) switch_bool_t switch_channel_set_flag_partner(switch_channel_t *channel, switch_channel_flag_t flag)
1527{
1528 const char *uuid;
1529
1530 switch_assert(channel != NULL)((channel != ((void*)0)) ? (void) (0) : __assert_fail ("channel != ((void*)0)"
, "src/switch_channel.c", 1530, __PRETTY_FUNCTION__))
;
1531
1532 if ((uuid = switch_channel_get_partner_uuid(channel))) {
1533 switch_core_session_t *session;
1534 if ((session = switch_core_session_locate(uuid)switch_core_session_perform_locate(uuid, "src/switch_channel.c"
, (const char *)__func__, 1534)
)) {
1535 switch_channel_set_flag(switch_core_session_get_channel(session), flag)switch_channel_set_flag_value(switch_core_session_get_channel
(session), flag, 1)
;
1536 switch_core_session_rwunlock(session);
1537 return SWITCH_TRUE;
1538 }
1539 }
1540
1541 return SWITCH_FALSE;
1542}
1543
1544SWITCH_DECLARE(uint32_t)__attribute__((visibility("default"))) uint32_t switch_channel_test_flag_partner(switch_channel_t *channel, switch_channel_flag_t flag)
1545{
1546 const char *uuid;
1547 int r = 0;
1548
1549 switch_assert(channel != NULL)((channel != ((void*)0)) ? (void) (0) : __assert_fail ("channel != ((void*)0)"
, "src/switch_channel.c", 1549, __PRETTY_FUNCTION__))
;
1550
1551 if ((uuid = switch_channel_get_partner_uuid(channel))) {
1552 switch_core_session_t *session;
1553 if ((session = switch_core_session_locate(uuid)switch_core_session_perform_locate(uuid, "src/switch_channel.c"
, (const char *)__func__, 1553)
)) {
1554 r = switch_channel_test_flag(switch_core_session_get_channel(session), flag);
1555 switch_core_session_rwunlock(session);
1556 }
1557 }
1558
1559 return r;
1560}
1561
1562SWITCH_DECLARE(switch_bool_t)__attribute__((visibility("default"))) switch_bool_t switch_channel_clear_flag_partner(switch_channel_t *channel, switch_channel_flag_t flag)
1563{
1564 const char *uuid;
1565
1566 switch_assert(channel != NULL)((channel != ((void*)0)) ? (void) (0) : __assert_fail ("channel != ((void*)0)"
, "src/switch_channel.c", 1566, __PRETTY_FUNCTION__))
;
1567
1568 if ((uuid = switch_channel_get_partner_uuid(channel))) {
1569 switch_core_session_t *session;
1570 if ((session = switch_core_session_locate(uuid)switch_core_session_perform_locate(uuid, "src/switch_channel.c"
, (const char *)__func__, 1570)
)) {
1571 switch_channel_clear_flag(switch_core_session_get_channel(session), flag);
1572 switch_core_session_rwunlock(session);
1573 return SWITCH_TRUE;
1574 }
1575 }
1576
1577 return SWITCH_FALSE;
1578}
1579
1580SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_channel_wait_for_state(switch_channel_t *channel, switch_channel_t *other_channel, switch_channel_state_t want_state)
1581{
1582
1583 switch_assert(channel)((channel) ? (void) (0) : __assert_fail ("channel", "src/switch_channel.c"
, 1583, __PRETTY_FUNCTION__))
;
1584
1585 for (;;) {
1586 if ((channel->state < CS_HANGUP && channel->state == channel->running_state && channel->running_state == want_state) ||
1587 (other_channel && switch_channel_down_nosig(other_channel)(switch_channel_get_state(other_channel) >= CS_HANGUP)) || switch_channel_down(channel)(switch_channel_check_signal(channel, SWITCH_TRUE) || switch_channel_get_state
(channel) >= CS_HANGUP)
) {
1588 break;
1589 }
1590 switch_cond_next();
1591 }
1592}
1593
1594
1595SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_channel_wait_for_state_timeout(switch_channel_t *channel, switch_channel_state_t want_state, uint32_t timeout)
1596{
1597
1598 uint32_t count = 0;
1599
1600 for (;;) {
1601
1602 if ((channel->state == channel->running_state && channel->running_state == want_state) || channel->state >= CS_HANGUP) {
1603 break;
1604 }
1605
1606 switch_channel_check_signal(channel, SWITCH_TRUE);
1607
1608 switch_cond_next();
1609
1610 if (++count >= timeout) {
1611 break;
1612 }
1613 }
1614}
1615
1616SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_channel_wait_for_flag(switch_channel_t *channel,
1617 switch_channel_flag_t want_flag,
1618 switch_bool_t pres, uint32_t to, switch_channel_t *super_channel)
1619{
1620
1621 if (to) {
1622 to++;
1623 }
1624
1625 for (;;) {
1626 if (pres) {
1627 if (switch_channel_test_flag(channel, want_flag)) {
1628 break;
1629 }
1630 } else {
1631 if (!switch_channel_test_flag(channel, want_flag)) {
1632 break;
1633 }
1634 }
1635
1636 switch_cond_next();
1637
1638 if (super_channel && !switch_channel_ready(super_channel)switch_channel_test_ready(super_channel, SWITCH_TRUE, SWITCH_FALSE
)
) {
1639 return SWITCH_STATUS_FALSE;
1640 }
1641
1642 if (switch_channel_down(channel)(switch_channel_check_signal(channel, SWITCH_TRUE) || switch_channel_get_state
(channel) >= CS_HANGUP)
) {
1643 return SWITCH_STATUS_FALSE;
1644 }
1645
1646 if (to && !--to) {
1647 return SWITCH_STATUS_TIMEOUT;
1648 }
1649 }
1650
1651 return SWITCH_STATUS_SUCCESS;
1652}
1653
1654
1655SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_channel_set_cap_value(switch_channel_t *channel, switch_channel_cap_t cap, uint32_t value)
1656{
1657 switch_assert(channel)((channel) ? (void) (0) : __assert_fail ("channel", "src/switch_channel.c"
, 1657, __PRETTY_FUNCTION__))
;
1658 switch_assert(channel->flag_mutex)((channel->flag_mutex) ? (void) (0) : __assert_fail ("channel->flag_mutex"
, "src/switch_channel.c", 1658, __PRETTY_FUNCTION__))
;
1659
1660 switch_mutex_lock(channel->flag_mutex);
1661 channel->caps[cap] = value;
1662 switch_mutex_unlock(channel->flag_mutex);
1663}
1664
1665SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_channel_clear_cap(switch_channel_t *channel, switch_channel_cap_t cap)
1666{
1667 switch_assert(channel != NULL)((channel != ((void*)0)) ? (void) (0) : __assert_fail ("channel != ((void*)0)"
, "src/switch_channel.c", 1667, __PRETTY_FUNCTION__))
;
1668 switch_assert(channel->flag_mutex)((channel->flag_mutex) ? (void) (0) : __assert_fail ("channel->flag_mutex"
, "src/switch_channel.c", 1668, __PRETTY_FUNCTION__))
;
1669
1670 switch_mutex_lock(channel->flag_mutex);
1671 channel->caps[cap] = 0;
1672 switch_mutex_unlock(channel->flag_mutex);
1673}
1674
1675SWITCH_DECLARE(uint32_t)__attribute__((visibility("default"))) uint32_t switch_channel_test_cap(switch_channel_t *channel, switch_channel_cap_t cap)
1676{
1677 switch_assert(channel != NULL)((channel != ((void*)0)) ? (void) (0) : __assert_fail ("channel != ((void*)0)"
, "src/switch_channel.c", 1677, __PRETTY_FUNCTION__))
;
1678 return channel->caps[cap] ? 1 : 0;
1679}
1680
1681SWITCH_DECLARE(uint32_t)__attribute__((visibility("default"))) uint32_t switch_channel_test_cap_partner(switch_channel_t *channel, switch_channel_cap_t cap)
1682{
1683 const char *uuid;
1684 int r = 0;
1685
1686 switch_assert(channel != NULL)((channel != ((void*)0)) ? (void) (0) : __assert_fail ("channel != ((void*)0)"
, "src/switch_channel.c", 1686, __PRETTY_FUNCTION__))
;
1687
1688 if ((uuid = switch_channel_get_partner_uuid(channel))) {
1689 switch_core_session_t *session;
1690 if ((session = switch_core_session_locate(uuid)switch_core_session_perform_locate(uuid, "src/switch_channel.c"
, (const char *)__func__, 1690)
)) {
1691 r = switch_channel_test_cap(switch_core_session_get_channel(session), cap);
1692 switch_core_session_rwunlock(session);
1693 }
1694 }
1695
1696 return r;
1697}
1698
1699SWITCH_DECLARE(char *)__attribute__((visibility("default"))) char * switch_channel_get_flag_string(switch_channel_t *channel)
1700{
1701 switch_stream_handle_t stream = { 0 };
1702 char *r;
1703 int i = 0;
1704
1705 SWITCH_STANDARD_STREAM(stream)memset(&stream, 0, sizeof(stream)); stream.data = malloc(
1024); ((stream.data) ? (void) (0) : __assert_fail ("stream.data"
, "src/switch_channel.c", 1705, __PRETTY_FUNCTION__)); memset
(stream.data, 0, 1024); stream.end = stream.data; stream.data_size
= 1024; stream.write_function = switch_console_stream_write;
stream.raw_write_function = switch_console_stream_raw_write;
stream.alloc_len = 1024; stream.alloc_chunk = 1024
;
1706
1707 switch_mutex_lock(channel->flag_mutex);
1708 for (i = 0; i < CF_FLAG_MAX; i++) {
1709 if (channel->flags[i]) {
1710 stream.write_function(&stream, "%d=%d;", i, channel->flags[i]);
1711 }
1712 }
1713 switch_mutex_unlock(channel->flag_mutex);
1714
1715 r = (char *) stream.data;
1716
1717 if (end_of(r)*(*r == '\0' ? r : r + strlen(r) - 1) == ';') {
1718 end_of(r)*(*r == '\0' ? r : r + strlen(r) - 1) = '\0';
1719 }
1720
1721 return r;
1722
1723}
1724
1725SWITCH_DECLARE(char *)__attribute__((visibility("default"))) char * switch_channel_get_cap_string(switch_channel_t *channel)
1726{
1727 switch_stream_handle_t stream = { 0 };
1728 char *r;
1729 int i = 0;
1730
1731 SWITCH_STANDARD_STREAM(stream)memset(&stream, 0, sizeof(stream)); stream.data = malloc(
1024); ((stream.data) ? (void) (0) : __assert_fail ("stream.data"
, "src/switch_channel.c", 1731, __PRETTY_FUNCTION__)); memset
(stream.data, 0, 1024); stream.end = stream.data; stream.data_size
= 1024; stream.write_function = switch_console_stream_write;
stream.raw_write_function = switch_console_stream_raw_write;
stream.alloc_len = 1024; stream.alloc_chunk = 1024
;
1732
1733 switch_mutex_lock(channel->flag_mutex);
1734 for (i = 0; i < CC_FLAG_MAX; i++) {
1735 if (channel->caps[i]) {
1736 stream.write_function(&stream, "%d=%d;", i, channel->caps[i]);
1737 }
1738 }
1739 switch_mutex_unlock(channel->flag_mutex);
1740
1741 r = (char *) stream.data;
1742
1743 if (end_of(r)*(*r == '\0' ? r : r + strlen(r) - 1) == ';') {
1744 end_of(r)*(*r == '\0' ? r : r + strlen(r) - 1) = '\0';
1745 }
1746
1747 return r;
1748
1749}
1750
1751SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_channel_set_flag_value(switch_channel_t *channel, switch_channel_flag_t flag, uint32_t value)
1752{
1753 int HELD = 0;
1754
1755 switch_assert(channel)((channel) ? (void) (0) : __assert_fail ("channel", "src/switch_channel.c"
, 1755, __PRETTY_FUNCTION__))
;
1756 switch_assert(channel->flag_mutex)((channel->flag_mutex) ? (void) (0) : __assert_fail ("channel->flag_mutex"
, "src/switch_channel.c", 1756, __PRETTY_FUNCTION__))
;
1757
1758 switch_mutex_lock(channel->flag_mutex);
1759 if (flag == CF_LEG_HOLDING && !channel->flags[flag] && channel->flags[CF_ANSWERED]) {
1760 HELD = 1;
1761 }
1762 channel->flags[flag] = value;
1763 switch_mutex_unlock(channel->flag_mutex);
1764
1765 if (flag == CF_ORIGINATOR && switch_channel_test_flag(channel, CF_ANSWERED) && switch_channel_up_nosig(channel)(switch_channel_get_state(channel) < CS_HANGUP)) {
1766 switch_channel_set_callstate(channel, CCS_RING_WAIT)switch_channel_perform_set_callstate(channel, CCS_RING_WAIT, "src/switch_channel.c"
, (const char *)__func__, 1766)
;
1767 }
1768
1769 if (flag == CF_DIALPLAN) {
1770 if (channel->direction == SWITCH_CALL_DIRECTION_INBOUND) {
1771 channel->logical_direction = SWITCH_CALL_DIRECTION_OUTBOUND;
1772 if (channel->device_node) {
1773 channel->device_node->direction = SWITCH_CALL_DIRECTION_INBOUND;
1774 }
1775 } else {
1776 channel->logical_direction = SWITCH_CALL_DIRECTION_INBOUND;
1777 if (channel->device_node) {
1778 channel->device_node->direction = SWITCH_CALL_DIRECTION_OUTBOUND;
1779 }
1780 }
1781 }
1782
1783 if (HELD) {
1784 switch_hold_record_t *hr;
1785 const char *brto = switch_channel_get_partner_uuid(channel);
1786
1787 switch_channel_set_callstate(channel, CCS_HELD)switch_channel_perform_set_callstate(channel, CCS_HELD, "src/switch_channel.c"
, (const char *)__func__, 1787)
;
1788 switch_mutex_lock(channel->profile_mutex);
1789 channel->caller_profile->times->last_hold = switch_time_now();
1790
1791 hr = switch_core_session_alloc(channel->session, sizeof(*hr))switch_core_perform_session_alloc(channel->session, sizeof
(*hr), "src/switch_channel.c", (const char *)__func__, 1791)
;
1792 hr->on = switch_time_now();
1793 if (brto) {
1794 hr->uuid = switch_core_session_strdup(channel->session, brto)switch_core_perform_session_strdup(channel->session, brto,
"src/switch_channel.c", (const char *)__func__, 1794)
;
1795 }
1796
1797 if (channel->hold_record) {
1798 hr->next = channel->hold_record;
1799 }
1800 channel->hold_record = hr;
1801
1802 switch_mutex_unlock(channel->profile_mutex);
1803 }
1804
1805 if (flag == CF_OUTBOUND) {
1806 switch_channel_set_variable(channel, "is_outbound", "true")switch_channel_set_variable_var_check(channel, "is_outbound",
"true", SWITCH_TRUE)
;
1807 }
1808
1809 if (flag == CF_RECOVERED) {
1810 switch_channel_set_variable(channel, "recovered", "true")switch_channel_set_variable_var_check(channel, "recovered", "true"
, SWITCH_TRUE)
;
1811 }
1812
1813}
1814
1815SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_channel_set_flag_recursive(switch_channel_t *channel, switch_channel_flag_t flag)
1816{
1817 switch_assert(channel)((channel) ? (void) (0) : __assert_fail ("channel", "src/switch_channel.c"
, 1817, __PRETTY_FUNCTION__))
;
1818 switch_assert(channel->flag_mutex)((channel->flag_mutex) ? (void) (0) : __assert_fail ("channel->flag_mutex"
, "src/switch_channel.c", 1818, __PRETTY_FUNCTION__))
;
1819
1820 switch_mutex_lock(channel->flag_mutex);
1821 channel->flags[flag]++;
1822 switch_mutex_unlock(channel->flag_mutex);
1823
1824 if (flag == CF_OUTBOUND) {
1825 switch_channel_set_variable(channel, "is_outbound", "true")switch_channel_set_variable_var_check(channel, "is_outbound",
"true", SWITCH_TRUE)
;
1826 }
1827
1828 if (flag == CF_RECOVERED) {
1829 switch_channel_set_variable(channel, "recovered", "true")switch_channel_set_variable_var_check(channel, "recovered", "true"
, SWITCH_TRUE)
;
1830 }
1831}
1832
1833
1834SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_channel_set_private_flag(switch_channel_t *channel, uint32_t flags)
1835{
1836 switch_assert(channel != NULL)((channel != ((void*)0)) ? (void) (0) : __assert_fail ("channel != ((void*)0)"
, "src/switch_channel.c", 1836, __PRETTY_FUNCTION__))
;
1837 switch_mutex_lock(channel->flag_mutex);
1838 channel->private_flags |= flags;
1839 switch_mutex_unlock(channel->flag_mutex);
1840}
1841
1842SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_channel_clear_private_flag(switch_channel_t *channel, uint32_t flags)
1843{
1844 switch_assert(channel != NULL)((channel != ((void*)0)) ? (void) (0) : __assert_fail ("channel != ((void*)0)"
, "src/switch_channel.c", 1844, __PRETTY_FUNCTION__))
;
1845 switch_mutex_lock(channel->flag_mutex);
1846 channel->private_flags &= ~flags;
1847 switch_mutex_unlock(channel->flag_mutex);
1848}
1849
1850SWITCH_DECLARE(int)__attribute__((visibility("default"))) int switch_channel_test_private_flag(switch_channel_t *channel, uint32_t flags)
1851{
1852 switch_assert(channel != NULL)((channel != ((void*)0)) ? (void) (0) : __assert_fail ("channel != ((void*)0)"
, "src/switch_channel.c", 1852, __PRETTY_FUNCTION__))
;
1853 return (channel->private_flags & flags);
1854}
1855
1856SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_channel_set_app_flag_key(const char *key, switch_channel_t *channel, uint32_t flags)
1857{
1858 uint32_t *flagp = NULL((void*)0);
1859 switch_byte_t new = 0;
1860
1861 switch_assert(channel != NULL)((channel != ((void*)0)) ? (void) (0) : __assert_fail ("channel != ((void*)0)"
, "src/switch_channel.c", 1861, __PRETTY_FUNCTION__))
;
1862 switch_mutex_lock(channel->flag_mutex);
1863
1864 if (!channel->app_flag_hash) {
1865 switch_core_hash_init(&channel->app_flag_hash)switch_core_hash_init_case(&channel->app_flag_hash, SWITCH_TRUE
)
;
1866 new++;
1867 }
1868
1869 if (new || !(flagp = switch_core_hash_find(channel->app_flag_hash, key))) {
1870 flagp = switch_core_session_alloc(channel->session, sizeof(uint32_t))switch_core_perform_session_alloc(channel->session, sizeof
(uint32_t), "src/switch_channel.c", (const char *)__func__, 1870
)
;
1871 switch_core_hash_insert(channel->app_flag_hash, key, flagp)switch_core_hash_insert_destructor(channel->app_flag_hash,
key, flagp, ((void*)0))
;
1872 }
1873
1874 switch_assert(flagp)((flagp) ? (void) (0) : __assert_fail ("flagp", "src/switch_channel.c"
, 1874, __PRETTY_FUNCTION__))
;
1875 *flagp |= flags;
1876
1877 switch_mutex_unlock(channel->flag_mutex);
1878}
1879
1880SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_channel_clear_app_flag_key(const char *key, switch_channel_t *channel, uint32_t flags)
1881{
1882 uint32_t *flagp = NULL((void*)0);
1883
1884 switch_assert(channel != NULL)((channel != ((void*)0)) ? (void) (0) : __assert_fail ("channel != ((void*)0)"
, "src/switch_channel.c", 1884, __PRETTY_FUNCTION__))
;
1885 switch_mutex_lock(channel->flag_mutex);
1886 if (channel->app_flag_hash && (flagp = switch_core_hash_find(channel->app_flag_hash, key))) {
1887 if (!flags) {
1888 *flagp = 0;
1889 } else {
1890 *flagp &= ~flags;
1891 }
1892 }
1893 switch_mutex_unlock(channel->flag_mutex);
1894}
1895
1896SWITCH_DECLARE(int)__attribute__((visibility("default"))) int switch_channel_test_app_flag_key(const char *key, switch_channel_t *channel, uint32_t flags)
1897{
1898 int r = 0;
1899 uint32_t *flagp = NULL((void*)0);
1900 switch_assert(channel != NULL)((channel != ((void*)0)) ? (void) (0) : __assert_fail ("channel != ((void*)0)"
, "src/switch_channel.c", 1900, __PRETTY_FUNCTION__))
;
1901
1902 switch_mutex_lock(channel->flag_mutex);
1903 if (channel->app_flag_hash && (flagp = switch_core_hash_find(channel->app_flag_hash, key))) {
1904 r = (*flagp & flags);
1905 }
1906 switch_mutex_unlock(channel->flag_mutex);
1907
1908
1909 return r;
1910}
1911
1912SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_channel_set_state_flag(switch_channel_t *channel, switch_channel_flag_t flag)
1913{
1914 switch_assert(channel != NULL)((channel != ((void*)0)) ? (void) (0) : __assert_fail ("channel != ((void*)0)"
, "src/switch_channel.c", 1914, __PRETTY_FUNCTION__))
;
1915
1916 switch_mutex_lock(channel->flag_mutex);
1917 channel->state_flags[0] = 1;
1918 channel->state_flags[flag] = 1;
1919 switch_mutex_unlock(channel->flag_mutex);
1920}
1921
1922SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_channel_clear_state_flag(switch_channel_t *channel, switch_channel_flag_t flag)
1923{
1924 switch_assert(channel != NULL)((channel != ((void*)0)) ? (void) (0) : __assert_fail ("channel != ((void*)0)"
, "src/switch_channel.c", 1924, __PRETTY_FUNCTION__))
;
1925
1926 switch_mutex_lock(channel->flag_mutex);
1927 channel->state_flags[flag] = 0;
1928 switch_mutex_unlock(channel->flag_mutex);
1929}
1930
1931SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_channel_clear_flag(switch_channel_t *channel, switch_channel_flag_t flag)
1932{
1933 int ACTIVE = 0;
1934 int CLEAR = 0;
1935
1936 switch_assert(channel != NULL)((channel != ((void*)0)) ? (void) (0) : __assert_fail ("channel != ((void*)0)"
, "src/switch_channel.c", 1936, __PRETTY_FUNCTION__))
;
1937 switch_assert(channel->flag_mutex)((channel->flag_mutex) ? (void) (0) : __assert_fail ("channel->flag_mutex"
, "src/switch_channel.c", 1937, __PRETTY_FUNCTION__))
;
1938
1939 switch_mutex_lock(channel->flag_mutex);
1940 if (flag == CF_LEG_HOLDING && channel->flags[flag] && channel->flags[CF_ANSWERED]) {
1941 ACTIVE = 1;
1942 }
1943
1944 if (flag == CF_VIDEO_PASSIVE && channel->flags[flag]) {
1945 CLEAR = 1;
1946 }
1947
1948 channel->flags[flag] = 0;
1949 switch_mutex_unlock(channel->flag_mutex);
1950
1951 if (flag == CF_DIALPLAN) {
1952 if (channel->direction == SWITCH_CALL_DIRECTION_OUTBOUND) {
1953 channel->logical_direction = SWITCH_CALL_DIRECTION_OUTBOUND;
1954 if (channel->device_node) {
1955 channel->device_node->direction = SWITCH_CALL_DIRECTION_INBOUND;
1956 }
1957 }
1958 }
1959
1960 if (ACTIVE) {
1961 switch_channel_set_callstate(channel, CCS_UNHELD)switch_channel_perform_set_callstate(channel, CCS_UNHELD, "src/switch_channel.c"
, (const char *)__func__, 1961)
;
1962 switch_mutex_lock(channel->profile_mutex);
1963 if (channel->caller_profile->times->last_hold) {
1964 channel->caller_profile->times->hold_accum += (switch_time_now() - channel->caller_profile->times->last_hold);
1965 }
1966
1967 if (channel->hold_record) {
1968 channel->hold_record->off = switch_time_now();
1969 }
1970
1971 if (switch_channel_test_flag(channel, CF_PROXY_MODE) && switch_channel_test_flag(channel, CF_BRIDGED)) {
1972 switch_channel_set_callstate(channel, CCS_ACTIVE)switch_channel_perform_set_callstate(channel, CCS_ACTIVE, "src/switch_channel.c"
, (const char *)__func__, 1972)
;
1973 }
1974
1975 switch_mutex_unlock(channel->profile_mutex);
1976 }
1977
1978 if (flag == CF_ORIGINATOR && switch_channel_test_flag(channel, CF_ANSWERED) && switch_channel_up_nosig(channel)(switch_channel_get_state(channel) < CS_HANGUP)) {
1979 switch_channel_set_callstate(channel, CCS_ACTIVE)switch_channel_perform_set_callstate(channel, CCS_ACTIVE, "src/switch_channel.c"
, (const char *)__func__, 1979)
;
1980 }
1981
1982 if (flag == CF_OUTBOUND) {
1983 switch_channel_set_variable(channel, "is_outbound", NULL)switch_channel_set_variable_var_check(channel, "is_outbound",
((void*)0), SWITCH_TRUE)
;
1984 }
1985
1986 if (flag == CF_RECOVERED) {
1987 switch_channel_set_variable(channel, "recovered", NULL)switch_channel_set_variable_var_check(channel, "recovered", (
(void*)0), SWITCH_TRUE)
;
1988 }
1989
1990 if (flag == CF_VIDEO_PASSIVE && CLEAR) {
1991 switch_core_session_wake_video_thread(channel->session);
1992 }
1993
1994 if (flag == CF_RECOVERING && !channel->hangup_cause) {
1995 switch_core_recovery_track(channel->session);
1996 }
1997
1998}
1999
2000
2001SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_channel_clear_flag_recursive(switch_channel_t *channel, switch_channel_flag_t flag)
2002{
2003 switch_assert(channel != NULL)((channel != ((void*)0)) ? (void) (0) : __assert_fail ("channel != ((void*)0)"
, "src/switch_channel.c", 2003, __PRETTY_FUNCTION__))
;
2004 switch_assert(channel->flag_mutex)((channel->flag_mutex) ? (void) (0) : __assert_fail ("channel->flag_mutex"
, "src/switch_channel.c", 2004, __PRETTY_FUNCTION__))
;
2005
2006 switch_mutex_lock(channel->flag_mutex);
2007 if (channel->flags[flag]) {
2008 channel->flags[flag]--;
2009 }
2010 switch_mutex_unlock(channel->flag_mutex);
2011
2012 if (flag == CF_OUTBOUND) {
2013 switch_channel_set_variable(channel, "is_outbound", NULL)switch_channel_set_variable_var_check(channel, "is_outbound",
((void*)0), SWITCH_TRUE)
;
2014 }
2015}
2016
2017SWITCH_DECLARE(switch_channel_state_t)__attribute__((visibility("default"))) switch_channel_state_t switch_channel_get_state(switch_channel_t *channel)
2018{
2019 switch_channel_state_t state;
2020 switch_assert(channel != NULL)((channel != ((void*)0)) ? (void) (0) : __assert_fail ("channel != ((void*)0)"
, "src/switch_channel.c", 2020, __PRETTY_FUNCTION__))
;
2021
2022 state = channel->state;
2023
2024 return state;
2025}
2026
2027SWITCH_DECLARE(switch_channel_state_t)__attribute__((visibility("default"))) switch_channel_state_t switch_channel_get_running_state(switch_channel_t *channel)
2028{
2029 switch_channel_state_t state;
2030 switch_assert(channel != NULL)((channel != ((void*)0)) ? (void) (0) : __assert_fail ("channel != ((void*)0)"
, "src/switch_channel.c", 2030, __PRETTY_FUNCTION__))
;
2031
2032 state = channel->running_state;
2033
2034 return state;
2035}
2036
2037SWITCH_DECLARE(int)__attribute__((visibility("default"))) int switch_channel_state_change_pending(switch_channel_t *channel)
2038{
2039 if (switch_channel_down_nosig(channel)(switch_channel_get_state(channel) >= CS_HANGUP) || !switch_core_session_in_thread(channel->session)) {
2040 return 0;
2041 }
2042
2043 return channel->running_state != channel->state;
2044}
2045
2046SWITCH_DECLARE(int)__attribute__((visibility("default"))) int switch_channel_check_signal(switch_channel_t *channel, switch_bool_t in_thread_only)
2047{
2048 if (!in_thread_only || switch_core_session_in_thread(channel->session)) {
2049 switch_ivr_parse_all_signal_data(channel->session);
2050 }
2051
2052 return 0;
2053}
2054
2055SWITCH_DECLARE(int)__attribute__((visibility("default"))) int switch_channel_test_ready(switch_channel_t *channel, switch_bool_t check_ready, switch_bool_t check_media)
2056{
2057 int ret = 0;
2058
2059 switch_assert(channel != NULL)((channel != ((void*)0)) ? (void) (0) : __assert_fail ("channel != ((void*)0)"
, "src/switch_channel.c", 2059, __PRETTY_FUNCTION__))
;
2060
2061 switch_channel_check_signal(channel, SWITCH_TRUE);
2062
2063 if (check_media) {
2064 ret = ((switch_channel_test_flag(channel, CF_ANSWERED) ||
2065 switch_channel_test_flag(channel, CF_EARLY_MEDIA)) && !switch_channel_test_flag(channel, CF_PROXY_MODE) &&
2066 switch_core_session_get_read_codec(channel->session) && switch_core_session_get_write_codec(channel->session));
2067
2068
2069 if (!ret)
2070 return ret;
2071 }
2072
2073 if (!check_ready)
2074 return ret;
2075
2076 ret = 0;
2077
2078 if (!channel->hangup_cause && channel->state > CS_ROUTING && channel->state < CS_HANGUP && channel->state != CS_RESET &&
2079 !switch_channel_test_flag(channel, CF_TRANSFER) && !switch_channel_test_flag(channel, CF_NOT_READY) &&
2080 !switch_channel_state_change_pending(channel)) {
2081 ret++;
2082 }
2083
2084
2085
2086 return ret;
2087}
2088
2089static const char *state_names[] = {
2090 "CS_NEW",
2091 "CS_INIT",
2092 "CS_ROUTING",
2093 "CS_SOFT_EXECUTE",
2094 "CS_EXECUTE",
2095 "CS_EXCHANGE_MEDIA",
2096 "CS_PARK",
2097 "CS_CONSUME_MEDIA",
2098 "CS_HIBERNATE",
2099 "CS_RESET",
2100 "CS_HANGUP",
2101 "CS_REPORTING",
2102 "CS_DESTROY",
2103 "CS_NONE",
2104 NULL((void*)0)
2105};
2106
2107SWITCH_DECLARE(const char *)__attribute__((visibility("default"))) const char * switch_channel_state_name(switch_channel_state_t state)
2108{
2109 return state_names[state];
2110}
2111
2112
2113SWITCH_DECLARE(switch_channel_state_t)__attribute__((visibility("default"))) switch_channel_state_t switch_channel_name_state(const char *name)
2114{
2115 uint32_t x = 0;
2116 for (x = 0; state_names[x]; x++) {
2117 if (!strcasecmp(state_names[x], name)) {
2118 return (switch_channel_state_t) x;
2119 }
2120 }
2121
2122 return CS_DESTROY;
2123}
2124
2125static inline void careful_set(switch_channel_t *channel, switch_channel_state_t *state, switch_channel_state_t val) {
2126
2127 if (switch_mutex_trylock(channel->thread_mutex) == SWITCH_STATUS_SUCCESS) {
2128 *state = val;
2129 switch_mutex_unlock(channel->thread_mutex);
2130 } else {
2131 switch_mutex_t *mutex = switch_core_session_get_mutex(channel->session);
2132 int x = 0;
2133
2134 for (x = 0; x < 100; x++) {
2135 if (switch_mutex_trylock(mutex) == SWITCH_STATUS_SUCCESS) {
2136 *state = val;
2137 switch_mutex_unlock(mutex);
2138 break;
2139 } else {
2140 switch_cond_next();
2141 }
2142 }
2143
2144 if (x == 100) {
2145 *state = val;
2146 }
2147
2148 }
2149}
2150
2151SWITCH_DECLARE(switch_channel_state_t)__attribute__((visibility("default"))) switch_channel_state_t switch_channel_perform_set_running_state(switch_channel_t *channel, switch_channel_state_t state,
2152 const char *file, const char *func, int line)
2153{
2154 int x;
2155
2156 switch_mutex_lock(channel->flag_mutex);
2157 if (channel->state_flags[0]) {
2158 for (x = 1; x < CF_FLAG_MAX; x++) {
2159 if (channel->state_flags[x]) {
2160 channel->flags[x] = 1;
2161 channel->state_flags[x] = 0;
2162 }
2163 }
2164 channel->state_flags[0] = 0;
2165 }
2166 switch_mutex_unlock(channel->flag_mutex);
2167
2168 switch_channel_clear_flag(channel, CF_TAGGED);
2169
2170
2171 switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, func, line, switch_channel_get_uuid(channel), SWITCH_LOG_DEBUG, "(%s) Running State Change %s\n",
2172 channel->name, state_names[state]);
2173
2174 switch_mutex_lock(channel->state_mutex);
2175
2176 careful_set(channel, &channel->running_state, state);
2177
2178 if (state <= CS_DESTROY) {
2179 switch_event_t *event;
2180
2181 if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_INBOUND) {
2182 if (state < CS_HANGUP) {
2183 if (state == CS_ROUTING) {
2184 switch_channel_set_callstate(channel, CCS_RINGING)switch_channel_perform_set_callstate(channel, CCS_RINGING, "src/switch_channel.c"
, (const char *)__func__, 2184)
;
2185 } else if (switch_channel_test_flag(channel, CF_ANSWERED)) {
2186 switch_channel_set_callstate(channel, CCS_ACTIVE)switch_channel_perform_set_callstate(channel, CCS_ACTIVE, "src/switch_channel.c"
, (const char *)__func__, 2186)
;
2187 } else if (switch_channel_test_flag(channel, CF_EARLY_MEDIA)) {
2188 switch_channel_set_callstate(channel, CCS_EARLY)switch_channel_perform_set_callstate(channel, CCS_EARLY, "src/switch_channel.c"
, (const char *)__func__, 2188)
;
2189 }
2190 }
2191 }
2192
2193 if (switch_event_create(&event, SWITCH_EVENT_CHANNEL_STATE)switch_event_create_subclass_detailed("src/switch_channel.c",
(const char * )(const char *)__func__, 2193, &event, SWITCH_EVENT_CHANNEL_STATE
, ((void*)0))
== SWITCH_STATUS_SUCCESS) {
2194 switch_channel_event_set_data(channel, event);
2195 switch_event_fire(&event)switch_event_fire_detailed("src/switch_channel.c", (const char
* )(const char *)__func__, 2195, &event, ((void*)0))
;
2196 }
2197 }
2198
2199 switch_mutex_unlock(channel->state_mutex);
2200
2201 return (switch_channel_state_t) SWITCH_STATUS_SUCCESS;
2202}
2203
2204SWITCH_DECLARE(switch_channel_state_t)__attribute__((visibility("default"))) switch_channel_state_t switch_channel_perform_set_state(switch_channel_t *channel,
2205 const char *file, const char *func, int line, switch_channel_state_t state)
2206{
2207 switch_channel_state_t last_state;
2208 int ok = 0;
2209
2210 switch_assert(channel != NULL)((channel != ((void*)0)) ? (void) (0) : __assert_fail ("channel != ((void*)0)"
, "src/switch_channel.c", 2210, __PRETTY_FUNCTION__))
;
2211 switch_assert(state <= CS_DESTROY)((state <= CS_DESTROY) ? (void) (0) : __assert_fail ("state <= CS_DESTROY"
, "src/switch_channel.c", 2211, __PRETTY_FUNCTION__))
;
2212 switch_mutex_lock(channel->state_mutex);
2213
2214 last_state = channel->state;
2215 switch_assert(last_state <= CS_DESTROY)((last_state <= CS_DESTROY) ? (void) (0) : __assert_fail (
"last_state <= CS_DESTROY", "src/switch_channel.c", 2215, __PRETTY_FUNCTION__
))
;
2216
2217 if (last_state == state) {
2218 goto done;
2219 }
2220
2221 if (last_state >= CS_HANGUP && state < last_state) {
2222 goto done;
2223 }
2224
2225 /* STUB for more dev
2226 case CS_INIT:
2227 switch(state) {
2228
2229 case CS_NEW:
2230 case CS_INIT:
2231 case CS_EXCHANGE_MEDIA:
2232 case CS_SOFT_EXECUTE:
2233 case CS_ROUTING:
2234 case CS_EXECUTE:
2235 case CS_HANGUP:
2236 case CS_DESTROY:
2237
2238 default:
2239 break;
2240 }
2241 break;
2242 */
2243
2244 switch (last_state) {
2245 case CS_NEW:
2246 case CS_RESET:
2247 switch (state) {
2248 default:
2249 ok++;
2250 break;
2251 }
2252 break;
2253
2254 case CS_INIT:
2255 switch (state) {
2256 case CS_EXCHANGE_MEDIA:
2257 case CS_SOFT_EXECUTE:
2258 case CS_ROUTING:
2259 case CS_EXECUTE:
2260 case CS_PARK:
2261 case CS_CONSUME_MEDIA:
2262 case CS_HIBERNATE:
2263 case CS_RESET:
2264 ok++;
2265 default:
2266 break;
2267 }
2268 break;
2269
2270 case CS_EXCHANGE_MEDIA:
2271 switch (state) {
2272 case CS_SOFT_EXECUTE:
2273 case CS_ROUTING:
2274 case CS_EXECUTE:
2275 case CS_PARK:
2276 case CS_CONSUME_MEDIA:
2277 case CS_HIBERNATE:
2278 case CS_RESET:
2279 ok++;
2280 default:
2281 break;
2282 }
2283 break;
2284
2285 case CS_SOFT_EXECUTE:
2286 switch (state) {
2287 case CS_EXCHANGE_MEDIA:
2288 case CS_ROUTING:
2289 case CS_EXECUTE:
2290 case CS_PARK:
2291 case CS_CONSUME_MEDIA:
2292 case CS_HIBERNATE:
2293 case CS_RESET:
2294 ok++;
2295 default:
2296 break;
2297 }
2298 break;
2299
2300 case CS_PARK:
2301 switch (state) {
2302 case CS_EXCHANGE_MEDIA:
2303 case CS_ROUTING:
2304 case CS_EXECUTE:
2305 case CS_SOFT_EXECUTE:
2306 case CS_HIBERNATE:
2307 case CS_RESET:
2308 case CS_CONSUME_MEDIA:
2309 ok++;
2310 default:
2311 break;
2312 }
2313 break;
2314
2315 case CS_CONSUME_MEDIA:
2316 switch (state) {
2317 case CS_EXCHANGE_MEDIA:
2318 case CS_ROUTING:
2319 case CS_EXECUTE:
2320 case CS_SOFT_EXECUTE:
2321 case CS_HIBERNATE:
2322 case CS_RESET:
2323 case CS_PARK:
2324 ok++;
2325 default:
2326 break;
2327 }
2328 break;
2329 case CS_HIBERNATE:
2330 switch (state) {
2331 case CS_EXCHANGE_MEDIA:
2332 case CS_INIT:
2333 case CS_ROUTING:
2334 case CS_EXECUTE:
2335 case CS_SOFT_EXECUTE:
2336 case CS_PARK:
2337 case CS_CONSUME_MEDIA:
2338 case CS_RESET:
2339 ok++;
2340 default:
2341 break;
2342 }
2343 break;
2344
2345 case CS_ROUTING:
2346 switch (state) {
2347 case CS_EXCHANGE_MEDIA:
2348 case CS_EXECUTE:
2349 case CS_SOFT_EXECUTE:
2350 case CS_PARK:
2351 case CS_CONSUME_MEDIA:
2352 case CS_HIBERNATE:
2353 case CS_RESET:
2354 ok++;
2355 default:
2356 break;
2357 }
2358 break;
2359
2360 case CS_EXECUTE:
2361 switch (state) {
2362 case CS_EXCHANGE_MEDIA:
2363 case CS_SOFT_EXECUTE:
2364 case CS_ROUTING:
2365 case CS_PARK:
2366 case CS_CONSUME_MEDIA:
2367 case CS_HIBERNATE:
2368 case CS_RESET:
2369 ok++;
2370 default:
2371 break;
2372 }
2373 break;
2374
2375 case CS_HANGUP:
2376 switch (state) {
2377 case CS_REPORTING:
2378 case CS_DESTROY:
2379 ok++;
2380 default:
2381 break;
2382 }
2383 break;
2384
2385 case CS_REPORTING:
2386 switch (state) {
2387 case CS_DESTROY:
2388 ok++;
2389 default:
2390 break;
2391 }
2392 break;
2393
2394 default:
2395 break;
2396
2397 }
2398
2399 if (ok) {
2400 switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, func, line, switch_channel_get_uuid(channel), SWITCH_LOG_DEBUG, "(%s) State Change %s -> %s\n",
2401 channel->name, state_names[last_state], state_names[state]);
2402
2403 careful_set(channel, &channel->state, state);
2404
2405 if (state == CS_HANGUP && !channel->hangup_cause) {
2406 channel->hangup_cause = SWITCH_CAUSE_NORMAL_CLEARING;
2407 }
2408
2409 if (state <= CS_DESTROY) {
2410 switch_core_session_signal_state_change(channel->session);
2411 }
2412 } else {
2413 switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, func, line, switch_channel_get_uuid(channel), SWITCH_LOG_WARNING,
2414 "(%s) Invalid State Change %s -> %s\n", channel->name, state_names[last_state], state_names[state]);
2415 /* we won't tolerate an invalid state change so we can make sure we are as robust as a nice cup of dark coffee! */
2416 /* not cool lets crash this bad boy and figure out wtf is going on */
2417 switch_assert(channel->state >= CS_HANGUP)((channel->state >= CS_HANGUP) ? (void) (0) : __assert_fail
("channel->state >= CS_HANGUP", "src/switch_channel.c"
, 2417, __PRETTY_FUNCTION__))
;
2418 }
2419 done:
2420
2421 switch_mutex_unlock(channel->state_mutex);
2422 return channel->state;
2423}
2424
2425SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_channel_state_thread_lock(switch_channel_t *channel)
2426{
2427 switch_mutex_lock(channel->thread_mutex);
2428}
2429
2430
2431SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_channel_state_thread_trylock(switch_channel_t *channel)
2432{
2433 return switch_mutex_trylock(channel->thread_mutex);
2434}
2435
2436
2437SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_channel_state_thread_unlock(switch_channel_t *channel)
2438{
2439 switch_mutex_unlock(channel->thread_mutex);
2440}
2441
2442SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_channel_event_set_basic_data(switch_channel_t *channel, switch_event_t *event)
2443{
2444 switch_caller_profile_t *caller_profile, *originator_caller_profile = NULL((void*)0), *originatee_caller_profile = NULL((void*)0);
2445 switch_codec_implementation_t impl = { 0 };
2446 char state_num[25];
2447 const char *v;
2448
2449 switch_mutex_lock(channel->profile_mutex);
2450
2451 if ((caller_profile = channel->caller_profile)) {
2452 originator_caller_profile = caller_profile->originator_caller_profile;
2453 originatee_caller_profile = caller_profile->originatee_caller_profile;
2454 }
2455
2456 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Channel-State", switch_channel_state_name(channel->running_state));
2457 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Channel-Call-State", switch_channel_callstate2str(channel->callstate));
2458 switch_snprintf(state_num, sizeof(state_num), "%d", channel->state);
2459 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Channel-State-Number", state_num);
2460 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Channel-Name", switch_channel_get_name(channel));
2461 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Unique-ID", switch_core_session_get_uuid(channel->session));
2462
2463 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Call-Direction",
2464 channel->direction == SWITCH_CALL_DIRECTION_OUTBOUND ? "outbound" : "inbound");
2465 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Presence-Call-Direction",
2466 channel->direction == SWITCH_CALL_DIRECTION_OUTBOUND ? "outbound" : "inbound");
2467
2468 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Channel-HIT-Dialplan",
2469 switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_INBOUND ||
2470 switch_channel_test_flag(channel, CF_DIALPLAN) ? "true" : "false");
2471
2472
2473 if ((v = switch_channel_get_variable(channel, "presence_id")switch_channel_get_variable_dup(channel, "presence_id", SWITCH_TRUE
, -1)
)) {
2474 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Channel-Presence-ID", v);
2475 }
2476
2477 if ((v = switch_channel_get_variable(channel, "presence_data")switch_channel_get_variable_dup(channel, "presence_data", SWITCH_TRUE
, -1)
)) {
2478 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Channel-Presence-Data", v);
2479 }
2480
2481
2482 if ((v = switch_channel_get_variable(channel, "presence_data_cols")switch_channel_get_variable_dup(channel, "presence_data_cols"
, SWITCH_TRUE, -1)
)) {
2483 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Presence-Data-Cols", v);
2484 switch_event_add_presence_data_cols(channel, event, "PD-");
2485 }
2486
2487 if ((v = switch_channel_get_variable(channel, "call_uuid")switch_channel_get_variable_dup(channel, "call_uuid", SWITCH_TRUE
, -1)
)) {
2488 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Channel-Call-UUID", v);
2489 } else {
2490 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Channel-Call-UUID", switch_core_session_get_uuid(channel->session));
2491 }
2492
2493 if (switch_channel_down_nosig(channel)(switch_channel_get_state(channel) >= CS_HANGUP)) {
2494 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Answer-State", "hangup");
2495 } else if (switch_channel_test_flag(channel, CF_ANSWERED)) {
2496 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Answer-State", "answered");
2497 } else if (switch_channel_test_flag(channel, CF_EARLY_MEDIA)) {
2498 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Answer-State", "early");
2499 } else {
2500 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Answer-State", "ringing");
2501 }
2502
2503 if (channel->hangup_cause) {
2504 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Hangup-Cause", switch_channel_cause2str(channel->hangup_cause));
2505 }
2506
2507
2508 switch_core_session_get_read_impl(channel->session, &impl);
2509
2510 if (impl.iananame) {
2511 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Channel-Read-Codec-Name", impl.iananame);
2512 switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Channel-Read-Codec-Rate", "%u", impl.actual_samples_per_second);
2513 switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Channel-Read-Codec-Bit-Rate", "%d", impl.bits_per_second);
2514 }
2515
2516 switch_core_session_get_write_impl(channel->session, &impl);
2517
2518 if (impl.iananame) {
2519 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Channel-Write-Codec-Name", impl.iananame);
2520 switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Channel-Write-Codec-Rate", "%u", impl.actual_samples_per_second);
2521 switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Channel-Write-Codec-Bit-Rate", "%d", impl.bits_per_second);
2522 }
2523
2524 /* Index Caller's Profile */
2525 if (caller_profile) {
2526 switch_caller_profile_event_set_data(caller_profile, "Caller", event);
2527 }
2528
2529 /* Index Originator/ee's Profile */
2530 if (originator_caller_profile && channel->last_profile_type == LP_ORIGINATOR) {
2531 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Other-Type", "originator");
2532 switch_caller_profile_event_set_data(originator_caller_profile, "Other-Leg", event);
2533 } else if (originatee_caller_profile && channel->last_profile_type == LP_ORIGINATEE) { /* Index Originatee's Profile */
2534 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Other-Type", "originatee");
2535 switch_caller_profile_event_set_data(originatee_caller_profile, "Other-Leg", event);
2536 }
2537
2538
2539 switch_mutex_unlock(channel->profile_mutex);
2540}
2541
2542SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_channel_event_set_extended_data(switch_channel_t *channel, switch_event_t *event)
2543{
2544 switch_event_header_t *hi;
2545 int global_verbose_events = -1;
2546
2547 switch_mutex_lock(channel->profile_mutex);
2548
2549 switch_core_session_ctl(SCSC_VERBOSE_EVENTS, &global_verbose_events);
2550
2551 if (global_verbose_events ||
2552 switch_channel_test_flag(channel, CF_VERBOSE_EVENTS) ||
2553 switch_event_get_header(event, "presence-data-cols")switch_event_get_header_idx(event, "presence-data-cols", -1) ||
2554 event->event_id == SWITCH_EVENT_CHANNEL_CREATE ||
2555 event->event_id == SWITCH_EVENT_CHANNEL_ORIGINATE ||
2556 event->event_id == SWITCH_EVENT_CHANNEL_UUID ||
2557 event->event_id == SWITCH_EVENT_CHANNEL_ANSWER ||
2558 event->event_id == SWITCH_EVENT_CHANNEL_PARK ||
2559 event->event_id == SWITCH_EVENT_CHANNEL_UNPARK ||
2560 event->event_id == SWITCH_EVENT_CHANNEL_BRIDGE ||
2561 event->event_id == SWITCH_EVENT_CHANNEL_UNBRIDGE ||
2562 event->event_id == SWITCH_EVENT_CHANNEL_PROGRESS ||
2563 event->event_id == SWITCH_EVENT_CHANNEL_PROGRESS_MEDIA ||
2564 event->event_id == SWITCH_EVENT_CHANNEL_HANGUP ||
2565 event->event_id == SWITCH_EVENT_CHANNEL_HANGUP_COMPLETE ||
2566 event->event_id == SWITCH_EVENT_REQUEST_PARAMS ||
2567 event->event_id == SWITCH_EVENT_CHANNEL_DATA ||
2568 event->event_id == SWITCH_EVENT_CHANNEL_EXECUTE ||
2569 event->event_id == SWITCH_EVENT_CHANNEL_EXECUTE_COMPLETE ||
2570 event->event_id == SWITCH_EVENT_CHANNEL_DESTROY ||
2571 event->event_id == SWITCH_EVENT_SESSION_HEARTBEAT ||
2572 event->event_id == SWITCH_EVENT_API ||
2573 event->event_id == SWITCH_EVENT_RECORD_START ||
2574 event->event_id == SWITCH_EVENT_RECORD_STOP ||
2575 event->event_id == SWITCH_EVENT_PLAYBACK_START ||
2576 event->event_id == SWITCH_EVENT_PLAYBACK_STOP ||
2577 event->event_id == SWITCH_EVENT_CALL_UPDATE ||
2578 event->event_id == SWITCH_EVENT_MEDIA_BUG_START ||
2579 event->event_id == SWITCH_EVENT_MEDIA_BUG_STOP ||
2580 event->event_id == SWITCH_EVENT_CUSTOM) {
2581
2582 /* Index Variables */
2583
2584 if (channel->scope_variables) {
2585 switch_event_t *ep;
2586
2587 for (ep = channel->scope_variables; ep; ep = ep->next) {
2588 for (hi = ep->headers; hi; hi = hi->next) {
2589 char buf[1024];
2590 char *vvar = NULL((void*)0), *vval = NULL((void*)0);
2591
2592 vvar = (char *) hi->name;
2593 vval = (char *) hi->value;
2594
2595 switch_assert(vvar && vval)((vvar && vval) ? (void) (0) : __assert_fail ("vvar && vval"
, "src/switch_channel.c", 2595, __PRETTY_FUNCTION__))
;
2596 switch_snprintf(buf, sizeof(buf), "scope_variable_%s", vvar);
2597
2598 if (!switch_event_get_header(event, buf)switch_event_get_header_idx(event, buf, -1)) {
2599 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, buf, vval);
2600 }
2601 }
2602 }
2603 }
2604
2605 if (channel->variables) {
2606 for (hi = channel->variables->headers; hi; hi = hi->next) {
2607 char buf[1024];
2608 char *vvar = NULL((void*)0), *vval = NULL((void*)0);
2609
2610 vvar = (char *) hi->name;
2611 vval = (char *) hi->value;
2612
2613 switch_assert(vvar && vval)((vvar && vval) ? (void) (0) : __assert_fail ("vvar && vval"
, "src/switch_channel.c", 2613, __PRETTY_FUNCTION__))
;
2614 switch_snprintf(buf, sizeof(buf), "variable_%s", vvar);
2615 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, buf, vval);
2616 }
2617 }
2618 }
2619
2620 switch_mutex_unlock(channel->profile_mutex);
2621}
2622
2623
2624SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_channel_event_set_data(switch_channel_t *channel, switch_event_t *event)
2625{
2626 switch_mutex_lock(channel->profile_mutex);
2627 switch_channel_event_set_basic_data(channel, event);
2628 switch_channel_event_set_extended_data(channel, event);
2629 switch_mutex_unlock(channel->profile_mutex);
2630}
2631
2632SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_channel_step_caller_profile(switch_channel_t *channel)
2633{
2634 switch_caller_profile_t *cp;
2635
2636
2637 switch_mutex_lock(channel->profile_mutex);
2638 cp = switch_caller_profile_clone(channel->session, channel->caller_profile);
2639 switch_mutex_unlock(channel->profile_mutex);
2640
2641 switch_channel_set_caller_profile(channel, cp);
2642}
2643
2644SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_channel_set_caller_profile(switch_channel_t *channel, switch_caller_profile_t *caller_profile)
2645{
2646 char *uuid = NULL((void*)0);
2647 switch_assert(channel != NULL)((channel != ((void*)0)) ? (void) (0) : __assert_fail ("channel != ((void*)0)"
, "src/switch_channel.c", 2647, __PRETTY_FUNCTION__))
;
2648 switch_assert(channel->session != NULL)((channel->session != ((void*)0)) ? (void) (0) : __assert_fail
("channel->session != ((void*)0)", "src/switch_channel.c"
, 2648, __PRETTY_FUNCTION__))
;
2649 switch_mutex_lock(channel->profile_mutex);
2650 switch_assert(caller_profile != NULL)((caller_profile != ((void*)0)) ? (void) (0) : __assert_fail (
"caller_profile != ((void*)0)", "src/switch_channel.c", 2650,
__PRETTY_FUNCTION__))
;
2651
2652 caller_profile->direction = channel->direction;
2653 caller_profile->logical_direction = channel->logical_direction;
2654 uuid = switch_core_session_get_uuid(channel->session);
2655
2656 if (!caller_profile->uuid || strcasecmp(caller_profile->uuid, uuid)) {
2657 caller_profile->uuid = switch_core_session_strdup(channel->session, uuid)switch_core_perform_session_strdup(channel->session, uuid,
"src/switch_channel.c", (const char *)__func__, 2657)
;
2658 }
2659
2660 if (!caller_profile->chan_name || strcasecmp(caller_profile->chan_name, channel->name)) {
2661 caller_profile->chan_name = switch_core_session_strdup(channel->session, channel->name)switch_core_perform_session_strdup(channel->session, channel
->name, "src/switch_channel.c", (const char *)__func__, 2661
)
;
2662 }
2663
2664 if (!caller_profile->context) {
2665 caller_profile->context = switch_core_session_strdup(channel->session, "default")switch_core_perform_session_strdup(channel->session, "default"
, "src/switch_channel.c", (const char *)__func__, 2665)
;
2666 }
2667
2668 if (!caller_profile->times) {
2669 caller_profile->times = (switch_channel_timetable_t *) switch_core_session_alloc(channel->session, sizeof(*caller_profile->times))switch_core_perform_session_alloc(channel->session, sizeof
(*caller_profile->times), "src/switch_channel.c", (const char
*)__func__, 2669)
;
2670 caller_profile->times->profile_created = switch_micro_time_now();
2671 }
2672
2673 if (channel->caller_profile && channel->caller_profile->times) {
2674 channel->caller_profile->times->transferred = caller_profile->times->profile_created;
2675 caller_profile->times->answered = channel->caller_profile->times->answered;
2676 caller_profile->times->progress = channel->caller_profile->times->progress;
2677 caller_profile->times->progress_media = channel->caller_profile->times->progress_media;
2678 caller_profile->times->created = channel->caller_profile->times->created;
2679 caller_profile->times->hungup = channel->caller_profile->times->hungup;
2680 if (channel->caller_profile->caller_extension) {
2681 switch_caller_extension_clone(&caller_profile->caller_extension, channel->caller_profile->caller_extension, caller_profile->pool);
2682 }
2683 } else {
2684 caller_profile->times->created = switch_micro_time_now();
2685 }
2686
2687
2688 caller_profile->next = channel->caller_profile;
2689 channel->caller_profile = caller_profile;
2690 caller_profile->profile_index = switch_core_sprintf(caller_profile->pool, "%d", ++channel->profile_index);
2691
2692 switch_mutex_unlock(channel->profile_mutex);
2693}
2694
2695SWITCH_DECLARE(switch_caller_profile_t *)__attribute__((visibility("default"))) switch_caller_profile_t
*
switch_channel_get_caller_profile(switch_channel_t *channel)
2696{
2697 switch_caller_profile_t *profile;
2698 switch_assert(channel != NULL)((channel != ((void*)0)) ? (void) (0) : __assert_fail ("channel != ((void*)0)"
, "src/switch_channel.c", 2698, __PRETTY_FUNCTION__))
;
2699 switch_mutex_lock(channel->profile_mutex);
2700 if ((profile = channel->caller_profile) && profile->hunt_caller_profile) {
2701 profile = profile->hunt_caller_profile;
2702 }
2703 switch_mutex_unlock(channel->profile_mutex);
2704 return profile;
2705}
2706
2707SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_channel_set_originator_caller_profile(switch_channel_t *channel, switch_caller_profile_t *caller_profile)
2708{
2709 switch_assert(channel != NULL)((channel != ((void*)0)) ? (void) (0) : __assert_fail ("channel != ((void*)0)"
, "src/switch_channel.c", 2709, __PRETTY_FUNCTION__))
;
2710 switch_assert(channel->caller_profile != NULL)((channel->caller_profile != ((void*)0)) ? (void) (0) : __assert_fail
("channel->caller_profile != ((void*)0)", "src/switch_channel.c"
, 2710, __PRETTY_FUNCTION__))
;
2711 switch_mutex_lock(channel->profile_mutex);
2712
2713 if (!caller_profile->times) {
2714 caller_profile->times = (switch_channel_timetable_t *) switch_core_alloc(caller_profile->pool, sizeof(*caller_profile->times))switch_core_perform_alloc(caller_profile->pool, sizeof(*caller_profile
->times), "src/switch_channel.c", (const char *)__func__, 2714
)
;
2715 }
2716
2717 if (channel->caller_profile) {
2718 caller_profile->next = channel->caller_profile->originator_caller_profile;
2719 channel->caller_profile->originator_caller_profile = caller_profile;
2720 channel->last_profile_type = LP_ORIGINATOR;
2721 }
2722 switch_assert(channel->caller_profile->originator_caller_profile->next != channel->caller_profile->originator_caller_profile)((channel->caller_profile->originator_caller_profile->
next != channel->caller_profile->originator_caller_profile
) ? (void) (0) : __assert_fail ("channel->caller_profile->originator_caller_profile->next != channel->caller_profile->originator_caller_profile"
, "src/switch_channel.c", 2722, __PRETTY_FUNCTION__))
;
2723 switch_mutex_unlock(channel->profile_mutex);
2724}
2725
2726SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_channel_set_hunt_caller_profile(switch_channel_t *channel, switch_caller_profile_t *caller_profile)
2727{
2728 switch_assert(channel != NULL)((channel != ((void*)0)) ? (void) (0) : __assert_fail ("channel != ((void*)0)"
, "src/switch_channel.c", 2728, __PRETTY_FUNCTION__))
;
2729 switch_assert(channel->caller_profile != NULL)((channel->caller_profile != ((void*)0)) ? (void) (0) : __assert_fail
("channel->caller_profile != ((void*)0)", "src/switch_channel.c"
, 2729, __PRETTY_FUNCTION__))
;
2730
2731 switch_mutex_lock(channel->profile_mutex);
2732
2733 channel->caller_profile->hunt_caller_profile = NULL((void*)0);
2734 if (channel->caller_profile && caller_profile) {
2735 caller_profile->direction = channel->direction;
2736 caller_profile->logical_direction = channel->logical_direction;
2737 channel->caller_profile->hunt_caller_profile = caller_profile;
2738 }
2739 switch_mutex_unlock(channel->profile_mutex);
2740}
2741
2742SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_channel_set_origination_caller_profile(switch_channel_t *channel, switch_caller_profile_t *caller_profile)
2743{
2744 switch_assert(channel != NULL)((channel != ((void*)0)) ? (void) (0) : __assert_fail ("channel != ((void*)0)"
, "src/switch_channel.c", 2744, __PRETTY_FUNCTION__))
;
2745 switch_assert(channel->caller_profile != NULL)((channel->caller_profile != ((void*)0)) ? (void) (0) : __assert_fail
("channel->caller_profile != ((void*)0)", "src/switch_channel.c"
, 2745, __PRETTY_FUNCTION__))
;
2746
2747 switch_mutex_lock(channel->profile_mutex);
2748
2749 if (channel->caller_profile) {
2750 caller_profile->next = channel->caller_profile->origination_caller_profile;
2751 channel->caller_profile->origination_caller_profile = caller_profile;
2752 }
2753 switch_assert(channel->caller_profile->origination_caller_profile->next != channel->caller_profile->origination_caller_profile)((channel->caller_profile->origination_caller_profile->
next != channel->caller_profile->origination_caller_profile
) ? (void) (0) : __assert_fail ("channel->caller_profile->origination_caller_profile->next != channel->caller_profile->origination_caller_profile"
, "src/switch_channel.c", 2753, __PRETTY_FUNCTION__))
;
2754 switch_mutex_unlock(channel->profile_mutex);
2755}
2756
2757SWITCH_DECLARE(switch_caller_profile_t *)__attribute__((visibility("default"))) switch_caller_profile_t
*
switch_channel_get_origination_caller_profile(switch_channel_t *channel)
2758{
2759 switch_caller_profile_t *profile = NULL((void*)0);
2760 switch_assert(channel != NULL)((channel != ((void*)0)) ? (void) (0) : __assert_fail ("channel != ((void*)0)"
, "src/switch_channel.c", 2760, __PRETTY_FUNCTION__))
;
2761
2762 switch_mutex_lock(channel->profile_mutex);
2763 if (channel->caller_profile) {
2764 profile = channel->caller_profile->origination_caller_profile;
2765 }
2766 switch_mutex_unlock(channel->profile_mutex);
2767
2768 return profile;
2769}
2770
2771
2772SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_channel_set_originatee_caller_profile(switch_channel_t *channel, switch_caller_profile_t *caller_profile)
2773{
2774 switch_assert(channel != NULL)((channel != ((void*)0)) ? (void) (0) : __assert_fail ("channel != ((void*)0)"
, "src/switch_channel.c", 2774, __PRETTY_FUNCTION__))
;
2775 switch_assert(channel->caller_profile != NULL)((channel->caller_profile != ((void*)0)) ? (void) (0) : __assert_fail
("channel->caller_profile != ((void*)0)", "src/switch_channel.c"
, 2775, __PRETTY_FUNCTION__))
;
2776
2777 switch_mutex_lock(channel->profile_mutex);
2778
2779 if (channel->caller_profile) {
2780 caller_profile->next = channel->caller_profile->originatee_caller_profile;
2781 channel->caller_profile->originatee_caller_profile = caller_profile;
2782 channel->last_profile_type = LP_ORIGINATEE;
2783 }
2784 switch_assert(channel->caller_profile->originatee_caller_profile->next != channel->caller_profile->originatee_caller_profile)((channel->caller_profile->originatee_caller_profile->
next != channel->caller_profile->originatee_caller_profile
) ? (void) (0) : __assert_fail ("channel->caller_profile->originatee_caller_profile->next != channel->caller_profile->originatee_caller_profile"
, "src/switch_channel.c", 2784, __PRETTY_FUNCTION__))
;
2785 switch_mutex_unlock(channel->profile_mutex);
2786}
2787
2788SWITCH_DECLARE(switch_caller_profile_t *)__attribute__((visibility("default"))) switch_caller_profile_t
*
switch_channel_get_originator_caller_profile(switch_channel_t *channel)
2789{
2790 switch_caller_profile_t *profile = NULL((void*)0);
2791 switch_assert(channel != NULL)((channel != ((void*)0)) ? (void) (0) : __assert_fail ("channel != ((void*)0)"
, "src/switch_channel.c", 2791, __PRETTY_FUNCTION__))
;
2792
2793 switch_mutex_lock(channel->profile_mutex);
2794
2795 if (channel->caller_profile) {
2796 profile = channel->caller_profile->originator_caller_profile;
2797 }
2798 switch_mutex_unlock(channel->profile_mutex);
2799
2800 return profile;
2801}
2802
2803SWITCH_DECLARE(switch_caller_profile_t *)__attribute__((visibility("default"))) switch_caller_profile_t
*
switch_channel_get_originatee_caller_profile(switch_channel_t *channel)
2804{
2805 switch_caller_profile_t *profile = NULL((void*)0);
2806 switch_assert(channel != NULL)((channel != ((void*)0)) ? (void) (0) : __assert_fail ("channel != ((void*)0)"
, "src/switch_channel.c", 2806, __PRETTY_FUNCTION__))
;
2807
2808 switch_mutex_lock(channel->profile_mutex);
2809 if (channel->caller_profile) {
2810 profile = channel->caller_profile->originatee_caller_profile;
2811 }
2812 switch_mutex_unlock(channel->profile_mutex);
2813
2814 return profile;
2815}
2816
2817SWITCH_DECLARE(char *)__attribute__((visibility("default"))) char * switch_channel_get_uuid(switch_channel_t *channel)
2818{
2819 switch_assert(channel != NULL)((channel != ((void*)0)) ? (void) (0) : __assert_fail ("channel != ((void*)0)"
, "src/switch_channel.c", 2819, __PRETTY_FUNCTION__))
;
2820 switch_assert(channel->session != NULL)((channel->session != ((void*)0)) ? (void) (0) : __assert_fail
("channel->session != ((void*)0)", "src/switch_channel.c"
, 2820, __PRETTY_FUNCTION__))
;
2821 return switch_core_session_get_uuid(channel->session);
2822}
2823
2824SWITCH_DECLARE(int)__attribute__((visibility("default"))) int switch_channel_add_state_handler(switch_channel_t *channel, const switch_state_handler_table_t *state_handler)
2825{
2826 int x, index;
2827
2828 switch_assert(channel != NULL)((channel != ((void*)0)) ? (void) (0) : __assert_fail ("channel != ((void*)0)"
, "src/switch_channel.c", 2828, __PRETTY_FUNCTION__))
;
2829 switch_mutex_lock(channel->state_mutex);
2830 for (x = 0; x < SWITCH_MAX_STATE_HANDLERS30; x++) {
2831 if (channel->state_handlers[x] == state_handler) {
2832 index = x;
2833 goto end;
2834 }
2835 }
2836 index = channel->state_handler_index++;
2837
2838 if (channel->state_handler_index >= SWITCH_MAX_STATE_HANDLERS30) {
2839 index = -1;
2840 goto end;
2841 }
2842
2843 channel->state_handlers[index] = state_handler;
2844
2845 end:
2846 switch_mutex_unlock(channel->state_mutex);
2847 return index;
2848}
2849
2850SWITCH_DECLARE(const switch_state_handler_table_t *)__attribute__((visibility("default"))) const switch_state_handler_table_t
*
switch_channel_get_state_handler(switch_channel_t *channel, int index)
2851{
2852 const switch_state_handler_table_t *h = NULL((void*)0);
2853
2854 switch_assert(channel != NULL)((channel != ((void*)0)) ? (void) (0) : __assert_fail ("channel != ((void*)0)"
, "src/switch_channel.c", 2854, __PRETTY_FUNCTION__))
;
2855
2856 if (index >= SWITCH_MAX_STATE_HANDLERS30 || index > channel->state_handler_index) {
2857 return NULL((void*)0);
2858 }
2859
2860 switch_mutex_lock(channel->state_mutex);
2861 h = channel->state_handlers[index];
2862 switch_mutex_unlock(channel->state_mutex);
2863
2864 return h;
2865}
2866
2867SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_channel_clear_state_handler(switch_channel_t *channel, const switch_state_handler_table_t *state_handler)
2868{
2869 int index, i = channel->state_handler_index;
2870 const switch_state_handler_table_t *new_handlers[SWITCH_MAX_STATE_HANDLERS30] = { 0 };
2871
2872 switch_assert(channel != NULL)((channel != ((void*)0)) ? (void) (0) : __assert_fail ("channel != ((void*)0)"
, "src/switch_channel.c", 2872, __PRETTY_FUNCTION__))
;
2873
2874 switch_mutex_lock(channel->state_mutex);
2875 channel->state_handler_index = 0;
2876
2877 if (state_handler) {
2878 for (index = 0; index < i; index++) {
2879 if (channel->state_handlers[index] != state_handler) {
2880 new_handlers[channel->state_handler_index++] = channel->state_handlers[index];
2881 }
2882 }
2883 } else {
2884 for (index = 0; index < i; index++) {
2885 if (channel->state_handlers[index] && switch_test_flag(channel->state_handlers[index], SSH_FLAG_STICKY)((channel->state_handlers[index])->flags & SSH_FLAG_STICKY
)
) {
2886 new_handlers[channel->state_handler_index++] = channel->state_handlers[index];
2887 }
2888 }
2889 }
2890
2891 for (index = 0; index < SWITCH_MAX_STATE_HANDLERS30; index++) {
2892 channel->state_handlers[index] = NULL((void*)0);
2893 }
2894
2895 if (channel->state_handler_index > 0) {
2896 for (index = 0; index < channel->state_handler_index; index++) {
2897 channel->state_handlers[index] = new_handlers[index];
2898 }
2899 }
2900
2901 switch_mutex_unlock(channel->state_mutex);
2902}
2903
2904SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_channel_restart(switch_channel_t *channel)
2905{
2906 switch_channel_set_state(channel, CS_RESET)switch_channel_perform_set_state(channel, "src/switch_channel.c"
, (const char *)__func__, 2906, CS_RESET)
;
2907 switch_channel_wait_for_state_timeout(channel, CS_RESET, 5000);
2908 switch_channel_set_state(channel, CS_EXECUTE)switch_channel_perform_set_state(channel, "src/switch_channel.c"
, (const char *)__func__, 2908, CS_EXECUTE)
;
2909}
2910
2911/* XXX This is a somewhat simple operation. Were essentially taking the extension that one channel
2912 was executing and generating a new extension for another channel that starts out where the
2913 original one left off with an optional forward offset. Since all we are really doing is
2914 copying a few basic pool-allocated structures from one channel to another there really is
2915 not much to worry about here in terms of threading since we use read-write locks.
2916 While the features are nice, they only really are needed in one specific crazy attended
2917 transfer scenario where one channel was in the middle of calling a particular extension
2918 when it was rudely cut off by a transfer key press. XXX */
2919
2920SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_channel_caller_extension_masquerade(switch_channel_t *orig_channel, switch_channel_t *new_channel, uint32_t offset)
2921{
2922 switch_caller_profile_t *caller_profile;
2923 switch_caller_extension_t *extension = NULL((void*)0), *orig_extension = NULL((void*)0);
2924 switch_caller_application_t *ap;
2925 switch_status_t status = SWITCH_STATUS_FALSE;
2926 switch_event_header_t *hi = NULL((void*)0);
2927 const char *no_copy = switch_channel_get_variable(orig_channel, "attended_transfer_no_copy")switch_channel_get_variable_dup(orig_channel, "attended_transfer_no_copy"
, SWITCH_TRUE, -1)
;
2928 char *dup;
2929 int i, argc = 0;
2930 char *argv[128];
2931
2932 if (no_copy) {
2933 dup = switch_core_session_strdup(new_channel->session, no_copy)switch_core_perform_session_strdup(new_channel->session, no_copy
, "src/switch_channel.c", (const char *)__func__, 2933)
;
2934 argc = switch_separate_string(dup, ',', argv, (sizeof(argv) / sizeof(argv[0])));
2935 }
2936
2937
2938 switch_mutex_lock(orig_channel->profile_mutex);
2939 switch_mutex_lock(new_channel->profile_mutex);
2940
2941
2942 caller_profile = switch_caller_profile_clone(new_channel->session, new_channel->caller_profile);
2943 switch_assert(caller_profile)((caller_profile) ? (void) (0) : __assert_fail ("caller_profile"
, "src/switch_channel.c", 2943, __PRETTY_FUNCTION__))
;
2944 extension = switch_caller_extension_new(new_channel->session, caller_profile->destination_number, caller_profile->destination_number);
2945 orig_extension = switch_channel_get_caller_extension(orig_channel);
2946
2947
2948 if (extension && orig_extension) {
2949 for (ap = orig_extension->current_application; ap && offset > 0; offset--) {
2950 ap = ap->next;
2951 }
2952
2953 for (; ap; ap = ap->next) {
2954 switch_caller_extension_add_application(new_channel->session, extension, ap->application_name, ap->application_data);
2955 }
2956
2957 caller_profile->destination_number = switch_core_strdup(caller_profile->pool, orig_channel->caller_profile->destination_number)switch_core_perform_strdup(caller_profile->pool, orig_channel
->caller_profile->destination_number, "src/switch_channel.c"
, (const char *)__func__, 2957)
;
2958 switch_channel_set_caller_profile(new_channel, caller_profile);
2959 switch_channel_set_caller_extension(new_channel, extension);
2960
2961 for (hi = orig_channel->variables->headers; hi; hi = hi->next) {
2962 int ok = 1;
2963 for (i = 0; i < argc; i++) {
2964 if (!strcasecmp(argv[i], hi->name)) {
2965 ok = 0;
2966 break;
2967 }
2968 }
2969
2970 if (!ok)
2971 continue;
2972
2973 switch_channel_set_variable(new_channel, hi->name, hi->value)switch_channel_set_variable_var_check(new_channel, hi->name
, hi->value, SWITCH_TRUE)
;
2974 }
2975
2976 status = SWITCH_STATUS_SUCCESS;
2977 }
2978
2979
2980 switch_mutex_unlock(new_channel->profile_mutex);
2981 switch_mutex_unlock(orig_channel->profile_mutex);
2982
2983
2984 return status;
2985}
2986
2987SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_channel_invert_cid(switch_channel_t *channel)
2988{
2989 const char *tname, *tnum;
2990 switch_caller_profile_t *cp;
2991
2992 cp = switch_channel_get_caller_profile(channel);
2993
2994 tname = cp->caller_id_name;
2995 tnum = cp->caller_id_number;
2996
2997#ifdef DEEP_DEBUG_CID
2998 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_channel.c", (const char *)
__func__, 2998, ((void*)0)
, SWITCH_LOG_CRIT, "SWAP [%s][%s] [%s][%s]\n", cp->caller_id_name, cp->caller_id_number, cp->callee_id_name, cp->callee_id_number);
2999#endif
3000
3001 cp->caller_id_name = cp->callee_id_name;
3002 cp->caller_id_number = cp->callee_id_number;
3003
3004 cp->callee_id_name = tname;
3005 cp->callee_id_number = tnum;
3006
3007 if (zstr(cp->caller_id_name)_zstr(cp->caller_id_name)) {
3008 cp->caller_id_name = "Unknown";
3009 }
3010
3011 if (zstr(cp->caller_id_number)_zstr(cp->caller_id_number)) {
3012 cp->caller_id_number = "Unknown";
3013 }
3014}
3015
3016
3017SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_channel_flip_cid(switch_channel_t *channel)
3018{
3019 switch_event_t *event;
3020 const char *tmp = NULL((void*)0);
3021
3022 switch_mutex_lock(channel->profile_mutex);
3023 if (channel->caller_profile->callee_id_name) {
3024 tmp = channel->caller_profile->caller_id_name;
3025 switch_channel_set_variable(channel, "pre_transfer_caller_id_name", channel->caller_profile->caller_id_name)switch_channel_set_variable_var_check(channel, "pre_transfer_caller_id_name"
, channel->caller_profile->caller_id_name, SWITCH_TRUE)
;
3026 channel->caller_profile->caller_id_name = switch_core_strdup(channel->caller_profile->pool, channel->caller_profile->callee_id_name)switch_core_perform_strdup(channel->caller_profile->pool
, channel->caller_profile->callee_id_name, "src/switch_channel.c"
, (const char *)__func__, 3026)
;
3027 }
3028
3029 if (switch_channel_test_flag(channel, CF_BRIDGED)) {
3030 channel->caller_profile->callee_id_name = SWITCH_BLANK_STRING"";
3031 } else if (tmp) {
3032 channel->caller_profile->callee_id_name = tmp;
3033 }
3034
3035 if (channel->caller_profile->callee_id_number) {
3036 tmp = channel->caller_profile->caller_id_number;
3037 switch_channel_set_variable(channel, "pre_transfer_caller_id_number", channel->caller_profile->caller_id_number)switch_channel_set_variable_var_check(channel, "pre_transfer_caller_id_number"
, channel->caller_profile->caller_id_number, SWITCH_TRUE
)
;
3038 channel->caller_profile->caller_id_number = switch_core_strdup(channel->caller_profile->pool, channel->caller_profile->callee_id_number)switch_core_perform_strdup(channel->caller_profile->pool
, channel->caller_profile->callee_id_number, "src/switch_channel.c"
, (const char *)__func__, 3038)
;
3039 }
3040
3041 if (switch_channel_test_flag(channel, CF_BRIDGED)) {
3042 channel->caller_profile->callee_id_number = SWITCH_BLANK_STRING"";
3043 } else if (tmp) {
3044 channel->caller_profile->callee_id_number = tmp;
3045 }
3046
3047 switch_mutex_unlock(channel->profile_mutex);
3048
3049
3050 if (switch_event_create(&event, SWITCH_EVENT_CALL_UPDATE)switch_event_create_subclass_detailed("src/switch_channel.c",
(const char * )(const char *)__func__, 3050, &event, SWITCH_EVENT_CALL_UPDATE
, ((void*)0))
== SWITCH_STATUS_SUCCESS) {
3051 const char *uuid = switch_channel_get_partner_uuid(channel);
3052 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Direction", "RECV");
3053
3054 if (uuid) {
3055 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Bridged-To", uuid);
3056 }
3057 switch_channel_event_set_data(channel, event);
3058 switch_event_fire(&event)switch_event_fire_detailed("src/switch_channel.c", (const char
* )(const char *)__func__, 3058, &event, ((void*)0))
;
3059 }
3060
3061
3062 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(channel->session)SWITCH_CHANNEL_ID_SESSION, "src/switch_channel.c", (const char
*)__func__, 3062, (const char*)(channel->session)
, SWITCH_LOG_INFO, "%s Flipping CID from \"%s\" <%s> to \"%s\" <%s>\n",
3063 switch_channel_get_name(channel),
3064 switch_str_nil(switch_channel_get_variable(channel, "pre_transfer_caller_id_name"))(switch_channel_get_variable_dup(channel, "pre_transfer_caller_id_name"
, SWITCH_TRUE, -1) ? switch_channel_get_variable_dup(channel,
"pre_transfer_caller_id_name", SWITCH_TRUE, -1) : "")
,
3065 switch_str_nil(switch_channel_get_variable(channel, "pre_transfer_caller_id_number"))(switch_channel_get_variable_dup(channel, "pre_transfer_caller_id_number"
, SWITCH_TRUE, -1) ? switch_channel_get_variable_dup(channel,
"pre_transfer_caller_id_number", SWITCH_TRUE, -1) : "")
,
3066 channel->caller_profile->caller_id_name,
3067 channel->caller_profile->caller_id_number
3068 );
3069
3070}
3071
3072SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_channel_sort_cid(switch_channel_t *channel)
3073{
3074
3075 if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_INBOUND && switch_channel_test_flag(channel, CF_BLEG)) {
3076 switch_channel_flip_cid(channel);
3077 switch_channel_clear_flag(channel, CF_BLEG);
3078 } else if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND && !switch_channel_test_flag(channel, CF_DIALPLAN)) {
3079 switch_channel_set_flag(channel, CF_DIALPLAN)switch_channel_set_flag_value(channel, CF_DIALPLAN, 1);
3080 switch_channel_flip_cid(channel);
3081 }
3082}
3083
3084SWITCH_DECLARE(switch_caller_extension_t *)__attribute__((visibility("default"))) switch_caller_extension_t
*
switch_channel_get_queued_extension(switch_channel_t *channel)
3085{
3086 switch_caller_extension_t *caller_extension;
3087
3088 switch_mutex_lock(channel->profile_mutex);
3089 caller_extension = channel->queued_extension;
3090 channel->queued_extension = NULL((void*)0);
3091 switch_mutex_unlock(channel->profile_mutex);
3092
3093 return caller_extension;
3094}
3095
3096SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_channel_transfer_to_extension(switch_channel_t *channel, switch_caller_extension_t *caller_extension)
3097{
3098 switch_mutex_lock(channel->profile_mutex);
3099 channel->queued_extension = caller_extension;
3100 switch_mutex_unlock(channel->profile_mutex);
3101
3102 switch_channel_set_flag(channel, CF_TRANSFER)switch_channel_set_flag_value(channel, CF_TRANSFER, 1);
3103 switch_channel_set_state(channel, CS_ROUTING)switch_channel_perform_set_state(channel, "src/switch_channel.c"
, (const char *)__func__, 3103, CS_ROUTING)
;
3104}
3105
3106SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_channel_set_caller_extension(switch_channel_t *channel, switch_caller_extension_t *caller_extension)
3107{
3108 switch_assert(channel != NULL)((channel != ((void*)0)) ? (void) (0) : __assert_fail ("channel != ((void*)0)"
, "src/switch_channel.c", 3108, __PRETTY_FUNCTION__))
;
3109
3110 switch_channel_sort_cid(channel);
3111
3112 switch_mutex_lock(channel->profile_mutex);
3113 caller_extension->next = channel->caller_profile->caller_extension;
3114 channel->caller_profile->caller_extension = caller_extension;
3115 switch_mutex_unlock(channel->profile_mutex);
3116}
3117
3118
3119SWITCH_DECLARE(switch_caller_extension_t *)__attribute__((visibility("default"))) switch_caller_extension_t
*
switch_channel_get_caller_extension(switch_channel_t *channel)
3120{
3121 switch_caller_extension_t *extension = NULL((void*)0);
3122
3123 switch_assert(channel != NULL)((channel != ((void*)0)) ? (void) (0) : __assert_fail ("channel != ((void*)0)"
, "src/switch_channel.c", 3123, __PRETTY_FUNCTION__))
;
3124 switch_mutex_lock(channel->profile_mutex);
3125 if (channel->caller_profile) {
3126 extension = channel->caller_profile->caller_extension;
3127 }
3128 switch_mutex_unlock(channel->profile_mutex);
3129 return extension;
3130}
3131
3132
3133SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_channel_set_bridge_time(switch_channel_t *channel)
3134{
3135 switch_mutex_lock(channel->profile_mutex);
3136 if (channel->caller_profile && channel->caller_profile->times) {
3137 channel->caller_profile->times->bridged = switch_micro_time_now();
3138 }
3139 switch_mutex_unlock(channel->profile_mutex);
3140}
3141
3142
3143SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_channel_set_hangup_time(switch_channel_t *channel)
3144{
3145 if (channel->caller_profile && channel->caller_profile->times && !channel->caller_profile->times->hungup) {
3146 switch_mutex_lock(channel->profile_mutex);
3147 channel->caller_profile->times->hungup = switch_micro_time_now();
3148 switch_mutex_unlock(channel->profile_mutex);
3149 }
3150}
3151
3152
3153SWITCH_DECLARE(switch_channel_state_t)__attribute__((visibility("default"))) switch_channel_state_t switch_channel_perform_hangup(switch_channel_t *channel,
3154 const char *file, const char *func, int line, switch_call_cause_t hangup_cause)
3155{
3156 int ok = 0;
3157
3158 switch_assert(channel != NULL)((channel != ((void*)0)) ? (void) (0) : __assert_fail ("channel != ((void*)0)"
, "src/switch_channel.c", 3158, __PRETTY_FUNCTION__))
;
3159
3160 /* one per customer */
3161 switch_mutex_lock(channel->state_mutex);
3162 if (!(channel->opaque_flags & OCF_HANGUP)) {
3163 channel->opaque_flags |= OCF_HANGUP;
3164 ok = 1;
3165 }
3166 switch_mutex_unlock(channel->state_mutex);
3167
3168 if (switch_channel_test_flag(channel, CF_LEG_HOLDING)) {
3169 switch_channel_mark_hold(channel, SWITCH_FALSE);
3170 switch_channel_set_flag(channel, CF_HANGUP_HELD)switch_channel_set_flag_value(channel, CF_HANGUP_HELD, 1);
3171 }
3172
3173 if (!ok) {
3174 return channel->state;
3175 }
3176
3177 switch_channel_clear_flag(channel, CF_BLOCK_STATE);
3178
3179 if (channel->state < CS_HANGUP) {
3180 switch_channel_state_t last_state;
3181 switch_event_t *event;
3182 const char *var;
3183
3184 switch_mutex_lock(channel->profile_mutex);
3185 if (channel->hold_record && !channel->hold_record->off) {
3186 channel->hold_record->off = switch_time_now();
3187 }
3188 switch_mutex_unlock(channel->profile_mutex);
3189
3190 switch_mutex_lock(channel->state_mutex);
3191 last_state = channel->state;
3192 channel->state = CS_HANGUP;
3193 switch_mutex_unlock(channel->state_mutex);
3194
3195 channel->hangup_cause = hangup_cause;
3196 switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, func, line, switch_channel_get_uuid(channel), SWITCH_LOG_NOTICE, "Hangup %s [%s] [%s]\n",
3197 channel->name, state_names[last_state], switch_channel_cause2str(channel->hangup_cause));
3198
3199
3200 switch_channel_set_variable_partner(channel, "last_bridge_hangup_cause", switch_channel_cause2str(hangup_cause))switch_channel_set_variable_partner_var_check(channel, "last_bridge_hangup_cause"
, switch_channel_cause2str(hangup_cause), SWITCH_TRUE)
;
3201
3202 if ((var = switch_channel_get_variable(channel, SWITCH_PROTO_SPECIFIC_HANGUP_CAUSE_VARIABLE)switch_channel_get_variable_dup(channel, "proto_specific_hangup_cause"
, SWITCH_TRUE, -1)
)) {
3203 switch_channel_set_variable_partner(channel, "last_bridge_" SWITCH_PROTO_SPECIFIC_HANGUP_CAUSE_VARIABLE, var)switch_channel_set_variable_partner_var_check(channel, "last_bridge_"
"proto_specific_hangup_cause", var, SWITCH_TRUE)
;
3204 }
3205
3206 if (switch_channel_test_flag(channel, CF_BRIDGE_ORIGINATOR)) {
3207 switch_channel_set_variable(channel, "last_bridge_role", "originator")switch_channel_set_variable_var_check(channel, "last_bridge_role"
, "originator", SWITCH_TRUE)
;
3208 } else if (switch_channel_test_flag(channel, CF_BRIDGED)) {
3209 switch_channel_set_variable(channel, "last_bridge_role", "originatee")switch_channel_set_variable_var_check(channel, "last_bridge_role"
, "originatee", SWITCH_TRUE)
;
3210 }
3211
3212
3213 if (!switch_core_session_running(channel->session) && !switch_core_session_started(channel->session)) {
3214 switch_core_session_thread_launch(channel->session);
3215 }
3216
3217 if (switch_event_create(&event, SWITCH_EVENT_CHANNEL_HANGUP)switch_event_create_subclass_detailed("src/switch_channel.c",
(const char * )(const char *)__func__, 3217, &event, SWITCH_EVENT_CHANNEL_HANGUP
, ((void*)0))
== SWITCH_STATUS_SUCCESS) {
3218 switch_channel_event_set_data(channel, event);
3219 switch_event_fire(&event)switch_event_fire_detailed("src/switch_channel.c", (const char
* )(const char *)__func__, 3219, &event, ((void*)0))
;
3220 }
3221
3222 switch_core_session_kill_channel(channel->session, SWITCH_SIG_KILL)switch_core_session_perform_kill_channel(channel->session,
"src/switch_channel.c", (const char *)__func__, 3222, SWITCH_SIG_KILL
)
;
3223 switch_core_session_signal_state_change(channel->session);
3224 switch_core_session_hangup_state(channel->session, SWITCH_FALSE);
3225 }
3226
3227 return channel->state;
3228}
3229
3230static switch_status_t send_ind(switch_channel_t *channel, switch_core_session_message_types_t msg_id, const char *file, const char *func, int line)
3231{
3232 switch_core_session_message_t msg = { 0 };
3233
3234 msg.message_id = msg_id;
3235 msg.from = channel->name;
3236 return switch_core_session_perform_receive_message(channel->session, &msg, file, func, line);
3237}
3238
3239
3240SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_channel_perform_mark_ring_ready_value(switch_channel_t *channel,
3241 switch_ring_ready_t rv,
3242 const char *file, const char *func, int line)
3243{
3244 switch_event_t *event;
3245
3246 if (!switch_channel_test_flag(channel, CF_RING_READY) && !switch_channel_test_flag(channel, CF_ANSWERED)) {
3247 switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, func, line, switch_channel_get_uuid(channel), SWITCH_LOG_NOTICE, "Ring-Ready %s!\n", channel->name);
3248 switch_channel_set_flag_value(channel, CF_RING_READY, rv);
3249
3250
3251 if (channel->caller_profile && channel->caller_profile->times) {
3252 switch_mutex_lock(channel->profile_mutex);
3253 channel->caller_profile->times->progress = switch_micro_time_now();
3254 if (channel->caller_profile->originator_caller_profile) {
3255 switch_core_session_t *other_session;
3256 if ((other_session = switch_core_session_locate(channel->caller_profile->originator_caller_profile->uuid)switch_core_session_perform_locate(channel->caller_profile
->originator_caller_profile->uuid, "src/switch_channel.c"
, (const char *)__func__, 3256)
)) {
3257 switch_channel_t *other_channel;
3258 other_channel = switch_core_session_get_channel(other_session);
3259 if (other_channel->caller_profile) {
3260 other_channel->caller_profile->times->progress = channel->caller_profile->times->progress;
3261 }
3262 switch_core_session_rwunlock(other_session);
3263 }
3264 channel->caller_profile->originator_caller_profile->times->progress = channel->caller_profile->times->progress;
3265 }
3266 switch_mutex_unlock(channel->profile_mutex);
3267 }
3268
3269 if (switch_event_create(&event, SWITCH_EVENT_CHANNEL_PROGRESS)switch_event_create_subclass_detailed("src/switch_channel.c",
(const char * )(const char *)__func__, 3269, &event, SWITCH_EVENT_CHANNEL_PROGRESS
, ((void*)0))
== SWITCH_STATUS_SUCCESS) {
3270 switch_channel_event_set_data(channel, event);
3271 switch_event_fire(&event)switch_event_fire_detailed("src/switch_channel.c", (const char
* )(const char *)__func__, 3271, &event, ((void*)0))
;
3272 }
3273
3274 switch_channel_execute_on(channel, SWITCH_CHANNEL_EXECUTE_ON_RING_VARIABLE"execute_on_ring");
3275 switch_channel_api_on(channel, SWITCH_CHANNEL_API_ON_RING_VARIABLE"api_on_ring");
3276
3277 switch_channel_set_callstate(channel, CCS_RINGING)switch_channel_perform_set_callstate(channel, CCS_RINGING, "src/switch_channel.c"
, (const char *)__func__, 3277)
;
3278
3279 send_ind(channel, SWITCH_MESSAGE_RING_EVENT, file, func, line);
3280
3281 return SWITCH_STATUS_SUCCESS;
3282 }
3283
3284 return SWITCH_STATUS_FALSE;
3285}
3286
3287SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_channel_check_zrtp(switch_channel_t *channel)
3288{
3289
3290 if (!switch_channel_test_flag(channel, CF_ZRTP_PASSTHRU)
3291 && switch_channel_test_flag(channel, CF_ZRTP_PASSTHRU_REQ)
3292 && switch_channel_test_flag(channel, CF_ZRTP_HASH)) {
3293 switch_core_session_t *other_session;
3294 switch_channel_t *other_channel;
3295 int doit = 1;
3296
3297 if (switch_core_session_get_partner(channel->session, &other_session)switch_core_session_perform_get_partner(channel->session, &
other_session, "src/switch_channel.c", (const char *)__func__
, 3297)
== SWITCH_STATUS_SUCCESS) {
3298 other_channel = switch_core_session_get_channel(other_session);
3299
3300 if (switch_channel_test_flag(other_channel, CF_ZRTP_HASH) && !switch_channel_test_flag(other_channel, CF_ZRTP_PASSTHRU)) {
3301
3302 switch_channel_set_flag(channel, CF_ZRTP_PASSTHRU)switch_channel_set_flag_value(channel, CF_ZRTP_PASSTHRU, 1);
3303 switch_channel_set_flag(other_channel, CF_ZRTP_PASSTHRU)switch_channel_set_flag_value(other_channel, CF_ZRTP_PASSTHRU
, 1)
;
3304
3305 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(channel->session)SWITCH_CHANNEL_ID_SESSION, "src/switch_channel.c", (const char
*)__func__, 3305, (const char*)(channel->session)
, SWITCH_LOG_INFO,
3306 "%s Activating ZRTP passthru mode.\n", switch_channel_get_name(channel));
3307
3308 switch_channel_set_variable(channel, "zrtp_passthru_active", "true")switch_channel_set_variable_var_check(channel, "zrtp_passthru_active"
, "true", SWITCH_TRUE)
;
3309 switch_channel_set_variable(other_channel, "zrtp_passthru_active", "true")switch_channel_set_variable_var_check(other_channel, "zrtp_passthru_active"
, "true", SWITCH_TRUE)
;
3310 switch_channel_set_variable(channel, "zrtp_secure_media", "false")switch_channel_set_variable_var_check(channel, "zrtp_secure_media"
, "false", SWITCH_TRUE)
;
3311 switch_channel_set_variable(other_channel, "zrtp_secure_media", "false")switch_channel_set_variable_var_check(other_channel, "zrtp_secure_media"
, "false", SWITCH_TRUE)
;
3312 doit = 0;
3313 }
3314
3315 switch_core_session_rwunlock(other_session);
3316 }
3317
3318 if (doit) {
3319 switch_channel_set_variable(channel, "zrtp_passthru_active", "false")switch_channel_set_variable_var_check(channel, "zrtp_passthru_active"
, "false", SWITCH_TRUE)
;
3320 switch_channel_set_variable(channel, "zrtp_secure_media", "true")switch_channel_set_variable_var_check(channel, "zrtp_secure_media"
, "true", SWITCH_TRUE)
;
3321 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(channel->session)SWITCH_CHANNEL_ID_SESSION, "src/switch_channel.c", (const char
*)__func__, 3321, (const char*)(channel->session)
, SWITCH_LOG_INFO,
3322 "%s ZRTP not negotiated on both sides; disabling ZRTP passthru mode.\n", switch_channel_get_name(channel));
3323
3324 switch_channel_clear_flag(channel, CF_ZRTP_PASSTHRU);
3325 switch_channel_clear_flag(channel, CF_ZRTP_HASH);
3326
3327 if (switch_core_session_get_partner(channel->session, &other_session)switch_core_session_perform_get_partner(channel->session, &
other_session, "src/switch_channel.c", (const char *)__func__
, 3327)
== SWITCH_STATUS_SUCCESS) {
3328 other_channel = switch_core_session_get_channel(other_session);
3329
3330 switch_channel_set_variable(other_channel, "zrtp_passthru_active", "false")switch_channel_set_variable_var_check(other_channel, "zrtp_passthru_active"
, "false", SWITCH_TRUE)
;
3331 switch_channel_set_variable(other_channel, "zrtp_secure_media", "true")switch_channel_set_variable_var_check(other_channel, "zrtp_secure_media"
, "true", SWITCH_TRUE)
;
3332 switch_channel_clear_flag(other_channel, CF_ZRTP_PASSTHRU);
3333 switch_channel_clear_flag(other_channel, CF_ZRTP_HASH);
3334
3335 switch_core_session_rwunlock(other_session);
3336 }
3337
3338 }
3339 }
3340}
3341
3342SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_channel_perform_mark_pre_answered(switch_channel_t *channel, const char *file, const char *func, int line)
3343{
3344 switch_event_t *event;
3345
3346 if (!switch_channel_test_flag(channel, CF_EARLY_MEDIA) && !switch_channel_test_flag(channel, CF_ANSWERED)) {
3347 const char *uuid;
3348 switch_core_session_t *other_session;
3349
3350 switch_channel_check_zrtp(channel);
3351 switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, func, line, switch_channel_get_uuid(channel), SWITCH_LOG_NOTICE, "Pre-Answer %s!\n", channel->name);
3352 switch_channel_set_flag(channel, CF_EARLY_MEDIA)switch_channel_set_flag_value(channel, CF_EARLY_MEDIA, 1);
3353
3354 switch_channel_set_variable(channel, SWITCH_ENDPOINT_DISPOSITION_VARIABLE, "EARLY MEDIA")switch_channel_set_variable_var_check(channel, "endpoint_disposition"
, "EARLY MEDIA", SWITCH_TRUE)
;
3355
3356 if (channel->caller_profile && channel->caller_profile->times) {
3357 switch_mutex_lock(channel->profile_mutex);
3358 channel->caller_profile->times->progress_media = switch_micro_time_now();
3359 if (channel->caller_profile->originator_caller_profile) {
3360 switch_core_session_t *osession;
3361 if ((osession = switch_core_session_locate(channel->caller_profile->originator_caller_profile->uuid)switch_core_session_perform_locate(channel->caller_profile
->originator_caller_profile->uuid, "src/switch_channel.c"
, (const char *)__func__, 3361)
)) {
3362 switch_channel_t *other_channel;
3363 other_channel = switch_core_session_get_channel(osession);
3364 if (other_channel->caller_profile) {
3365 other_channel->caller_profile->times->progress_media = channel->caller_profile->times->progress_media;
3366 }
3367 switch_core_session_rwunlock(osession);
3368 }
3369 channel->caller_profile->originator_caller_profile->times->progress_media = channel->caller_profile->times->progress_media;
3370 }
3371 switch_mutex_unlock(channel->profile_mutex);
3372 }
3373
3374 if (switch_event_create(&event, SWITCH_EVENT_CHANNEL_PROGRESS_MEDIA)switch_event_create_subclass_detailed("src/switch_channel.c",
(const char * )(const char *)__func__, 3374, &event, SWITCH_EVENT_CHANNEL_PROGRESS_MEDIA
, ((void*)0))
== SWITCH_STATUS_SUCCESS) {
3375 switch_channel_event_set_data(channel, event);
3376 switch_event_fire(&event)switch_event_fire_detailed("src/switch_channel.c", (const char
* )(const char *)__func__, 3376, &event, ((void*)0))
;
3377 }
3378
3379 switch_channel_execute_on(channel, SWITCH_CHANNEL_EXECUTE_ON_PRE_ANSWER_VARIABLE"execute_on_pre_answer");
3380 switch_channel_execute_on(channel, SWITCH_CHANNEL_EXECUTE_ON_MEDIA_VARIABLE"execute_on_media");
3381
3382 switch_channel_api_on(channel, SWITCH_CHANNEL_API_ON_PRE_ANSWER_VARIABLE"api_on_pre_answer");
3383 switch_channel_api_on(channel, SWITCH_CHANNEL_API_ON_MEDIA_VARIABLE"api_on_media");
3384
3385 if (switch_true(switch_channel_get_variable(channel, SWITCH_PASSTHRU_PTIME_MISMATCH_VARIABLE)switch_channel_get_variable_dup(channel, "passthru_ptime_mismatch"
, SWITCH_TRUE, -1)
)) {
3386 switch_channel_set_flag(channel, CF_PASSTHRU_PTIME_MISMATCH)switch_channel_set_flag_value(channel, CF_PASSTHRU_PTIME_MISMATCH
, 1)
;
3387 }
3388
3389
3390 /* if we're the child of another channel and the other channel is in a blocking read they will never realize we have answered so send
3391 a SWITCH_SIG_BREAK to interrupt any blocking reads on that channel
3392 */
3393 if ((uuid = switch_channel_get_variable(channel, SWITCH_ORIGINATOR_VARIABLE)switch_channel_get_variable_dup(channel, "originator", SWITCH_TRUE
, -1)
)
3394 && (other_session = switch_core_session_locate(uuid)switch_core_session_perform_locate(uuid, "src/switch_channel.c"
, (const char *)__func__, 3394)
)) {
3395 switch_core_session_kill_channel(other_session, SWITCH_SIG_BREAK)switch_core_session_perform_kill_channel(other_session, "src/switch_channel.c"
, (const char *)__func__, 3395, SWITCH_SIG_BREAK)
;
3396 switch_core_session_rwunlock(other_session);
3397 }
3398
3399 switch_channel_set_callstate(channel, CCS_EARLY)switch_channel_perform_set_callstate(channel, CCS_EARLY, "src/switch_channel.c"
, (const char *)__func__, 3399)
;
3400
3401 send_ind(channel, SWITCH_MESSAGE_PROGRESS_EVENT, file, func, line);
3402
3403 return SWITCH_STATUS_SUCCESS;
3404 }
3405
3406 return SWITCH_STATUS_FALSE;
3407}
3408
3409SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_channel_perform_pre_answer(switch_channel_t *channel, const char *file, const char *func, int line)
3410{
3411 switch_core_session_message_t msg = { 0 };
3412 switch_status_t status = SWITCH_STATUS_SUCCESS;
3413
3414 switch_assert(channel != NULL)((channel != ((void*)0)) ? (void) (0) : __assert_fail ("channel != ((void*)0)"
, "src/switch_channel.c", 3414, __PRETTY_FUNCTION__))
;
3415
3416 if (channel->hangup_cause || channel->state >= CS_HANGUP) {
3417 return SWITCH_STATUS_FALSE;
3418 }
3419
3420 if (switch_channel_test_flag(channel, CF_ANSWERED)) {
3421 return SWITCH_STATUS_SUCCESS;
3422 }
3423
3424 if (switch_channel_test_flag(channel, CF_EARLY_MEDIA)) {
3425 return SWITCH_STATUS_SUCCESS;
3426 }
3427
3428 if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_INBOUND) {
3429 msg.message_id = SWITCH_MESSAGE_INDICATE_PROGRESS;
3430 msg.from = channel->name;
3431 status = switch_core_session_perform_receive_message(channel->session, &msg, file, func, line);
3432 }
3433
3434 if (status == SWITCH_STATUS_SUCCESS) {
3435 switch_channel_perform_mark_pre_answered(channel, file, func, line);
3436 switch_channel_audio_sync(channel)switch_channel_perform_audio_sync(channel, "src/switch_channel.c"
, (const char *)__func__, 3436)
;
3437 } else {
3438 switch_channel_hangup(channel, SWITCH_CAUSE_INCOMPATIBLE_DESTINATION)switch_channel_perform_hangup(channel, "src/switch_channel.c"
, (const char *)__func__, 3438, SWITCH_CAUSE_INCOMPATIBLE_DESTINATION
)
;
3439 }
3440
3441 return status;
3442}
3443
3444SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_channel_perform_ring_ready_value(switch_channel_t *channel, switch_ring_ready_t rv,
3445 const char *file, const char *func, int line)
3446{
3447 switch_core_session_message_t msg = { 0 };
3448 switch_status_t status = SWITCH_STATUS_SUCCESS;
3449
3450 switch_assert(channel != NULL)((channel != ((void*)0)) ? (void) (0) : __assert_fail ("channel != ((void*)0)"
, "src/switch_channel.c", 3450, __PRETTY_FUNCTION__))
;
3451
3452 if (channel->hangup_cause || channel->state >= CS_HANGUP) {
3453 return SWITCH_STATUS_FALSE;
3454 }
3455
3456 if (switch_channel_test_flag(channel, CF_ANSWERED)) {
3457 return SWITCH_STATUS_SUCCESS;
3458 }
3459
3460 if (switch_channel_test_flag(channel, CF_EARLY_MEDIA)) {
3461 return SWITCH_STATUS_SUCCESS;
3462 }
3463
3464 if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_INBOUND) {
3465 msg.message_id = SWITCH_MESSAGE_INDICATE_RINGING;
3466 msg.from = channel->name;
3467 msg.numeric_arg = rv;
3468 status = switch_core_session_perform_receive_message(channel->session, &msg, file, func, line);
3469 }
3470
3471 if (status == SWITCH_STATUS_SUCCESS) {
3472 switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, func, line, switch_channel_get_uuid(channel), SWITCH_LOG_NOTICE, "Ring Ready %s!\n", channel->name);
3473 switch_channel_perform_mark_ring_ready_value(channel, rv, file, func, line);
3474 } else {
3475 switch_channel_hangup(channel, SWITCH_CAUSE_INCOMPATIBLE_DESTINATION)switch_channel_perform_hangup(channel, "src/switch_channel.c"
, (const char *)__func__, 3475, SWITCH_CAUSE_INCOMPATIBLE_DESTINATION
)
;
3476 }
3477
3478 return status;
3479}
3480
3481static void do_api_on(switch_channel_t *channel, const char *variable)
3482{
3483 char *app;
3484 char *arg = NULL((void*)0);
3485 switch_stream_handle_t stream = { 0 };
3486
3487 app = switch_core_session_strdup(channel->session, variable)switch_core_perform_session_strdup(channel->session, variable
, "src/switch_channel.c", (const char *)__func__, 3487)
;
3488
3489 if ((arg = strchr(app, ' ')(__extension__ (__builtin_constant_p (' ') && !__builtin_constant_p
(app) && (' ') == '\0' ? (char *) __rawmemchr (app, ' '
) : __builtin_strchr (app, ' ')))
)) {
3490 *arg++ = '\0';
3491 }
3492
3493 SWITCH_STANDARD_STREAM(stream)memset(&stream, 0, sizeof(stream)); stream.data = malloc(
1024); ((stream.data) ? (void) (0) : __assert_fail ("stream.data"
, "src/switch_channel.c", 3493, __PRETTY_FUNCTION__)); memset
(stream.data, 0, 1024); stream.end = stream.data; stream.data_size
= 1024; stream.write_function = switch_console_stream_write;
stream.raw_write_function = switch_console_stream_raw_write;
stream.alloc_len = 1024; stream.alloc_chunk = 1024
;
3494 switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel)SWITCH_CHANNEL_ID_SESSION, "src/switch_channel.c", (const char
*)__func__, 3494, (const char*)switch_channel_get_session(channel
)
, SWITCH_LOG_DEBUG, "%s process %s: %s(%s)\n%s\n",
3495 channel->name, variable, app, switch_str_nil(arg)(arg ? arg : ""), (char *) stream.data);
3496 switch_api_execute(app, arg, NULL((void*)0), &stream);
3497 free(stream.data);
3498}
3499
3500
3501SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_channel_api_on(switch_channel_t *channel, const char *variable_prefix)
3502{
3503 switch_event_header_t *hp;
3504 switch_event_t *event;
3505 int x = 0;
3506
3507
3508 switch_channel_get_variables(channel, &event);
3509
3510 for (hp = event->headers; hp; hp = hp->next) {
3511 char *var = hp->name;
3512 char *val = hp->value;
3513
3514 if (!strncasecmp(var, variable_prefix, strlen(variable_prefix))) {
3515 if (hp->idx) {
3516 int i;
3517 for (i = 0; i < hp->idx; i++) {
3518 x++;
3519 do_api_on(channel, hp->array[i]);
3520 }
3521 } else {
3522 x++;
3523 do_api_on(channel, val);
3524 }
3525 }
3526 }
3527
3528 switch_event_destroy(&event);
3529
3530 return x ? SWITCH_STATUS_SUCCESS : SWITCH_STATUS_FALSE;
3531}
3532
3533static void do_execute_on(switch_channel_t *channel, const char *variable)
3534{
3535 char *arg = NULL((void*)0);
3536 char *p;
3537 int bg = 0;
3538 char *app;
3539
3540 app = switch_core_session_strdup(channel->session, variable)switch_core_perform_session_strdup(channel->session, variable
, "src/switch_channel.c", (const char *)__func__, 3540)
;
26
Value assigned to 'app'
3541
3542 for(p = app; p && *p; p++) {
27
Assuming pointer value is null
3543 if (*p == ' ' || (*p == ':' && (*(p+1) != ':'))) {
3544 *p++ = '\0';
3545 arg = p;
3546 break;
3547 } else if (*p == ':' && (*(p+1) == ':')) {
3548 bg++;
3549 break;
3550 }
3551 }
3552
3553 if (!strncasecmp(app, "perl", 4)) {
28
Null pointer passed as an argument to a 'nonnull' parameter
3554 bg++;
3555 }
3556
3557 if (bg) {
3558 switch_core_session_execute_application_async(channel->session, app, arg);
3559 } else {
3560 switch_core_session_execute_application(channel->session, app, arg)switch_core_session_execute_application_get_flags(channel->
session, app, arg, ((void*)0))
;
3561 }
3562}
3563
3564SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_channel_execute_on(switch_channel_t *channel, const char *variable_prefix)
3565{
3566 switch_event_header_t *hp;
3567 switch_event_t *event, *cevent;
3568 int x = 0;
3569
3570 switch_core_get_variables(&event);
3571 switch_channel_get_variables(channel, &cevent);
3572 switch_event_merge(event, cevent);
3573
3574 for (hp = event->headers; hp; hp = hp->next) {
16
Loop condition is true. Entering loop body
18
Loop condition is true. Entering loop body
20
Loop condition is true. Entering loop body
22
Loop condition is true. Entering loop body
3575 char *var = hp->name;
3576 char *val = hp->value;
3577
3578 if (!strncasecmp(var, variable_prefix, strlen(variable_prefix))) {
17
Taking false branch
19
Taking false branch
21
Taking false branch
23
Taking true branch
3579 if (hp->idx) {
24
Taking false branch
3580 int i;
3581 for (i = 0; i < hp->idx; i++) {
3582 x++;
3583 do_execute_on(channel, hp->array[i]);
3584 }
3585 } else {
3586 x++;
3587 do_execute_on(channel, val);
25
Calling 'do_execute_on'
3588 }
3589 }
3590 }
3591
3592 switch_event_destroy(&event);
3593 switch_event_destroy(&cevent);
3594
3595 return x ? SWITCH_STATUS_SUCCESS : SWITCH_STATUS_FALSE;
3596}
3597
3598SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_channel_perform_mark_answered(switch_channel_t *channel, const char *file, const char *func, int line)
3599{
3600 switch_event_t *event;
3601 const char *uuid;
3602 switch_core_session_t *other_session;
3603 const char *var;
3604
3605 switch_assert(channel != NULL)((channel != ((void*)0)) ? (void) (0) : __assert_fail ("channel != ((void*)0)"
, "src/switch_channel.c", 3605, __PRETTY_FUNCTION__))
;
3606
3607 if (channel->hangup_cause || channel->state >= CS_HANGUP) {
7
Taking false branch
3608 return SWITCH_STATUS_FALSE;
3609 }
3610
3611 if (switch_channel_test_flag(channel, CF_ANSWERED)) {
8
Taking false branch
3612 return SWITCH_STATUS_SUCCESS;
3613 }
3614
3615 if (channel->caller_profile && channel->caller_profile->times) {
3616 switch_mutex_lock(channel->profile_mutex);
3617 channel->caller_profile->times->answered = switch_micro_time_now();
3618 switch_mutex_unlock(channel->profile_mutex);
3619 }
3620
3621 switch_channel_check_zrtp(channel);
3622 switch_channel_set_flag(channel, CF_ANSWERED)switch_channel_set_flag_value(channel, CF_ANSWERED, 1);
3623
3624
3625 if (switch_event_create(&event, SWITCH_EVENT_CHANNEL_ANSWER)switch_event_create_subclass_detailed("src/switch_channel.c",
(const char * )(const char *)__func__, 3625, &event, SWITCH_EVENT_CHANNEL_ANSWER
, ((void*)0))
== SWITCH_STATUS_SUCCESS) {
9
Taking false branch
3626 switch_channel_event_set_data(channel, event);
3627 switch_event_fire(&event)switch_event_fire_detailed("src/switch_channel.c", (const char
* )(const char *)__func__, 3627, &event, ((void*)0))
;
3628 }
3629
3630 /* if we're the child of another channel and the other channel is in a blocking read they will never realize we have answered so send
3631 a SWITCH_SIG_BREAK to interrupt any blocking reads on that channel
3632 */
3633 if ((uuid = switch_channel_get_variable(channel, SWITCH_ORIGINATOR_VARIABLE)switch_channel_get_variable_dup(channel, "originator", SWITCH_TRUE
, -1)
)
3634 && (other_session = switch_core_session_locate(uuid)switch_core_session_perform_locate(uuid, "src/switch_channel.c"
, (const char *)__func__, 3634)
)) {
3635 switch_core_session_kill_channel(other_session, SWITCH_SIG_BREAK)switch_core_session_perform_kill_channel(other_session, "src/switch_channel.c"
, (const char *)__func__, 3635, SWITCH_SIG_BREAK)
;
3636 switch_core_session_rwunlock(other_session);
3637 }
3638
3639 if (switch_true(switch_channel_get_variable(channel, SWITCH_PASSTHRU_PTIME_MISMATCH_VARIABLE)switch_channel_get_variable_dup(channel, "passthru_ptime_mismatch"
, SWITCH_TRUE, -1)
)) {
10
Taking false branch
3640 switch_channel_set_flag(channel, CF_PASSTHRU_PTIME_MISMATCH)switch_channel_set_flag_value(channel, CF_PASSTHRU_PTIME_MISMATCH
, 1)
;
3641 }
3642
3643 if ((var = switch_channel_get_variable(channel, SWITCH_ENABLE_HEARTBEAT_EVENTS_VARIABLE)switch_channel_get_variable_dup(channel, "enable_heartbeat_events"
, SWITCH_TRUE, -1)
)) {
11
Assuming 'var' is null
12
Taking false branch
3644 uint32_t seconds = 60;
3645 int tmp;
3646
3647 if (switch_is_number(var)) {
3648 tmp = atoi(var);
3649 if (tmp > 0) {
3650 seconds = tmp;
3651 }
3652 } else if (!switch_true(var)) {
3653 seconds = 0;
3654 }
3655
3656 if (seconds) {
3657 switch_core_session_enable_heartbeat(channel->session, seconds);
3658 }
3659 }
3660
3661 switch_channel_set_variable(channel, SWITCH_ENDPOINT_DISPOSITION_VARIABLE, "ANSWER")switch_channel_set_variable_var_check(channel, "endpoint_disposition"
, "ANSWER", SWITCH_TRUE)
;
3662 switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, func, line, switch_channel_get_uuid(channel), SWITCH_LOG_NOTICE, "Channel [%s] has been answered\n",
3663 channel->name);
3664
3665
3666 if (switch_channel_get_variable(channel, "absolute_codec_string")switch_channel_get_variable_dup(channel, "absolute_codec_string"
, SWITCH_TRUE, -1)
) {
13
Taking false branch
3667 /* inherit_codec == true will implicitly clear the absolute_codec_string
3668 variable if used since it was the reason it was set in the first place and is no longer needed */
3669 if (switch_true(switch_channel_get_variable(channel, "inherit_codec")switch_channel_get_variable_dup(channel, "inherit_codec", SWITCH_TRUE
, -1)
)) {
3670 switch_channel_set_variable(channel, "absolute_codec_string", NULL)switch_channel_set_variable_var_check(channel, "absolute_codec_string"
, ((void*)0), SWITCH_TRUE)
;
3671 }
3672 }
3673
3674 switch_channel_execute_on(channel, SWITCH_CHANNEL_EXECUTE_ON_ANSWER_VARIABLE"execute_on_answer");
3675
3676 if (!switch_channel_test_flag(channel, CF_EARLY_MEDIA)) {
14
Taking true branch
3677 switch_channel_execute_on(channel, SWITCH_CHANNEL_EXECUTE_ON_MEDIA_VARIABLE"execute_on_media");
15
Calling 'switch_channel_execute_on'
3678 switch_channel_api_on(channel, SWITCH_CHANNEL_API_ON_MEDIA_VARIABLE"api_on_media");
3679 }
3680
3681 switch_channel_api_on(channel, SWITCH_CHANNEL_API_ON_ANSWER_VARIABLE"api_on_answer");
3682
3683 switch_channel_presence(channel, "unknown", "answered", NULL)switch_channel_perform_presence(channel, "unknown", "answered"
, ((void*)0), "src/switch_channel.c", (const char *)__func__,
3683)
;
3684
3685 //switch_channel_audio_sync(channel);
3686
3687 switch_core_recovery_track(channel->session);
3688
3689 switch_channel_set_callstate(channel, CCS_ACTIVE)switch_channel_perform_set_callstate(channel, CCS_ACTIVE, "src/switch_channel.c"
, (const char *)__func__, 3689)
;
3690
3691 send_ind(channel, SWITCH_MESSAGE_ANSWER_EVENT, file, func, line);
3692
3693
3694 return SWITCH_STATUS_SUCCESS;
3695}
3696
3697SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_channel_perform_answer(switch_channel_t *channel, const char *file, const char *func, int line)
3698{
3699 switch_core_session_message_t msg = { 0 };
3700 switch_status_t status = SWITCH_STATUS_SUCCESS;
3701
3702 switch_assert(channel != NULL)((channel != ((void*)0)) ? (void) (0) : __assert_fail ("channel != ((void*)0)"
, "src/switch_channel.c", 3702, __PRETTY_FUNCTION__))
;
3703
3704 if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) {
1
Taking false branch
3705 return SWITCH_STATUS_SUCCESS;
3706 }
3707
3708 if (channel->hangup_cause || channel->state >= CS_HANGUP) {
2
Taking false branch
3709 return SWITCH_STATUS_FALSE;
3710 }
3711
3712 if (switch_channel_test_flag(channel, CF_ANSWERED)) {
3
Taking false branch
3713 return SWITCH_STATUS_SUCCESS;
3714 }
3715
3716 msg.message_id = SWITCH_MESSAGE_INDICATE_ANSWER;
3717 msg.from = channel->name;
3718 status = switch_core_session_perform_receive_message(channel->session, &msg, file, func, line);
3719
3720
3721 if (status == SWITCH_STATUS_SUCCESS) {
4
Assuming 'status' is equal to SWITCH_STATUS_SUCCESS
5
Taking true branch
3722 switch_channel_perform_mark_answered(channel, file, func, line);
6
Calling 'switch_channel_perform_mark_answered'
3723 if (!switch_channel_test_flag(channel, CF_EARLY_MEDIA)) {
3724 switch_channel_audio_sync(channel)switch_channel_perform_audio_sync(channel, "src/switch_channel.c"
, (const char *)__func__, 3724)
;
3725 }
3726 } else {
3727 switch_channel_hangup(channel, SWITCH_CAUSE_INCOMPATIBLE_DESTINATION)switch_channel_perform_hangup(channel, "src/switch_channel.c"
, (const char *)__func__, 3727, SWITCH_CAUSE_INCOMPATIBLE_DESTINATION
)
;
3728 }
3729
3730
3731 if (switch_core_session_in_thread(channel->session)) {
3732 const char *delay;
3733
3734 if ((delay = switch_channel_get_variable(channel, "answer_delay")switch_channel_get_variable_dup(channel, "answer_delay", SWITCH_TRUE
, -1)
)) {
3735 uint32_t msec = atoi(delay);
3736
3737 if (msec) {
3738 switch_ivr_sleep(channel->session, msec, SWITCH_TRUE, NULL((void*)0));
3739 }
3740 }
3741 }
3742
3743 return status;
3744}
3745
3746#define resize(l){ char *dp; olen += (len + l + block); cpos = c - data; if ((
dp = realloc(data, olen))) { data = dp; c = data + cpos; memset
(c, 0, olen - cpos); }}
{\
3747 char *dp;\
3748 olen += (len + l + block);\
3749 cpos = c - data;\
3750 if ((dp = realloc(data, olen))) {\
3751 data = dp;\
3752 c = data + cpos;\
3753 memset(c, 0, olen - cpos);\
3754 }} \
3755
3756SWITCH_DECLARE(char *)__attribute__((visibility("default"))) char * switch_channel_expand_variables_check(switch_channel_t *channel, const char *in, switch_event_t *var_list, switch_event_t *api_list, uint32_t recur)
3757{
3758 char *p, *c = NULL((void*)0);
3759 char *data, *indup, *endof_indup;
3760 size_t sp = 0, len = 0, olen = 0, vtype = 0, br = 0, cpos, block = 128;
3761 char *cloned_sub_val = NULL((void*)0), *sub_val = NULL((void*)0), *expanded_sub_val = NULL((void*)0);
3762 char *func_val = NULL((void*)0), *sb = NULL((void*)0);
3763 int nv = 0;
3764
3765 if (recur > 100) {
3766 return (char *) in;
3767 }
3768
3769 if (zstr(in)_zstr(in)) {
3770 return (char *) in;
3771 }
3772
3773 nv = switch_string_var_check_const(in) || switch_string_has_escaped_data(in);
3774
3775 if (!nv) {
3776 return (char *) in;
3777 }
3778
3779
3780 nv = 0;
3781 olen = strlen(in) + 1;
3782 indup = strdup(in)(__extension__ (__builtin_constant_p (in) && ((size_t
)(const void *)((in) + 1) - (size_t)(const void *)(in) == 1) ?
(((const char *) (in))[0] == '\0' ? (char *) calloc ((size_t
) 1, (size_t) 1) : ({ size_t __len = strlen (in) + 1; char *__retval
= (char *) malloc (__len); if (__retval != ((void*)0)) __retval
= (char *) memcpy (__retval, in, __len); __retval; })) : __strdup
(in)))
;
3783 endof_indup = end_of_p(indup)(*indup == '\0' ? indup : indup + strlen(indup) - 1) + 1;
3784
3785 if ((data = malloc(olen))) {
3786 memset(data, 0, olen);
3787 c = data;
3788 for (p = indup; p && p < endof_indup && *p; p++) {
3789 int global = 0;
3790 vtype = 0;
3791
3792 if (*p == '\\') {
3793 if (*(p + 1) == '$') {
3794 nv = 1;
3795 p++;
3796 if (*(p + 1) == '$') {
3797 p++;
3798 }
3799 } else if (*(p + 1) == '\'') {
3800 p++;
3801 continue;
3802 } else if (*(p + 1) == '\\') {
3803 *c++ = *p++;
3804 len++;
3805 continue;
3806 }
3807 }
3808
3809 if (*p == '$' && !nv) {
3810
3811 if (*(p + 1) == '$') {
3812 p++;
3813 global++;
3814 }
3815
3816 if (*(p + 1)) {
3817 if (*(p + 1) == '{') {
3818 vtype = global ? 3 : 1;
3819 } else {
3820 nv = 1;
3821 }
3822 } else {
3823 nv = 1;
3824 }
3825 }
3826
3827 if (nv) {
3828 *c++ = *p;
3829 len++;
3830 nv = 0;
3831 continue;
3832 }
3833
3834 if (vtype) {
3835 char *s = p, *e, *vname, *vval = NULL((void*)0);
3836 size_t nlen;
3837
3838 s++;
3839
3840 if ((vtype == 1 || vtype == 3) && *s == '{') {
3841 br = 1;
3842 s++;
3843 }
3844
3845 e = s;
3846 vname = s;
3847 while (*e) {
3848 if (br == 1 && *e == '}') {
3849 br = 0;
3850 *e++ = '\0';
3851 break;
3852 }
3853
3854 if (br > 0) {
3855 if (e != s && *e == '{') {
3856 br++;
3857 } else if (br > 1 && *e == '}') {
3858 br--;
3859 }
3860 }
3861
3862 e++;
3863 }
3864 p = e > endof_indup ? endof_indup : e;
3865
3866 vval = NULL((void*)0);
3867 for(sb = vname; sb && *sb; sb++) {
3868 if (*sb == ' ') {
3869 vval = sb;
3870 break;
3871 } else if (*sb == '(') {
3872 vval = sb;
3873 br = 1;
3874 break;
3875 }
3876 }
3877
3878 if (vval) {
3879 e = vval - 1;
3880 *vval++ = '\0';
3881 while (*e == ' ') {
3882 *e-- = '\0';
3883 }
3884 e = vval;
3885
3886 while (e && *e) {
3887 if (*e == '(') {
3888 br++;
3889 } else if (br > 1 && *e == ')') {
3890 br--;
3891 } else if (br == 1 && *e == ')') {
3892 *e = '\0';
3893 break;
3894 }
3895 e++;
3896 }
3897
3898 vtype = 2;
3899 }
3900
3901 if (vtype == 1 || vtype == 3) {
3902 char *expanded = NULL((void*)0);
3903 int offset = 0;
3904 int ooffset = 0;
3905 char *ptr;
3906 int idx = -1;
3907
3908 if ((expanded = switch_channel_expand_variables_check(channel, (char *) vname, var_list, api_list, recur+1)) == vname) {
3909 expanded = NULL((void*)0);
3910 } else {
3911 vname = expanded;
3912 }
3913
3914 if ((ptr = strchr(vname, ':')(__extension__ (__builtin_constant_p (':') && !__builtin_constant_p
(vname) && (':') == '\0' ? (char *) __rawmemchr (vname
, ':') : __builtin_strchr (vname, ':')))
)) {
3915 *ptr++ = '\0';
3916 offset = atoi(ptr);
3917 if ((ptr = strchr(ptr, ':')(__extension__ (__builtin_constant_p (':') && !__builtin_constant_p
(ptr) && (':') == '\0' ? (char *) __rawmemchr (ptr, ':'
) : __builtin_strchr (ptr, ':')))
)) {
3918 ptr++;
3919 ooffset = atoi(ptr);
3920 }
3921 }
3922
3923 if ((ptr = strchr(vname, '[')(__extension__ (__builtin_constant_p ('[') && !__builtin_constant_p
(vname) && ('[') == '\0' ? (char *) __rawmemchr (vname
, '[') : __builtin_strchr (vname, '[')))
) && strchr(ptr, ']')(__extension__ (__builtin_constant_p (']') && !__builtin_constant_p
(ptr) && (']') == '\0' ? (char *) __rawmemchr (ptr, ']'
) : __builtin_strchr (ptr, ']')))
) {
3924 *ptr++ = '\0';
3925 idx = atoi(ptr);
3926 }
3927
3928 if ((sub_val = (char *) switch_channel_get_variable_dup(channel, vname, SWITCH_TRUE, idx))) {
3929 if (var_list && !switch_event_check_permission_list(var_list, vname)) {
3930 sub_val = "<Variable Expansion Permission Denied>";
3931 }
3932
3933 if ((expanded_sub_val = switch_channel_expand_variables_check(channel, sub_val, var_list, api_list, recur+1)) == sub_val) {
3934 expanded_sub_val = NULL((void*)0);
3935 } else {
3936 sub_val = expanded_sub_val;
3937 }
3938
3939 if (offset || ooffset) {
3940 cloned_sub_val = strdup(sub_val)(__extension__ (__builtin_constant_p (sub_val) && ((size_t
)(const void *)((sub_val) + 1) - (size_t)(const void *)(sub_val
) == 1) ? (((const char *) (sub_val))[0] == '\0' ? (char *) calloc
((size_t) 1, (size_t) 1) : ({ size_t __len = strlen (sub_val
) + 1; char *__retval = (char *) malloc (__len); if (__retval
!= ((void*)0)) __retval = (char *) memcpy (__retval, sub_val
, __len); __retval; })) : __strdup (sub_val)))
;
3941 switch_assert(cloned_sub_val)((cloned_sub_val) ? (void) (0) : __assert_fail ("cloned_sub_val"
, "src/switch_channel.c", 3941, __PRETTY_FUNCTION__))
;
3942 sub_val = cloned_sub_val;
3943 }
3944
3945 if (offset >= 0) {
3946 if ((size_t) offset > strlen(sub_val)) {
3947 *sub_val = '\0';
3948 } else {
3949 sub_val += offset;
3950 }
3951 } else if ((size_t) abs(offset) <= strlen(sub_val)) {
3952 sub_val = cloned_sub_val + (strlen(cloned_sub_val) + offset);
3953 }
3954
3955 if (ooffset > 0 && (size_t) ooffset < strlen(sub_val)) {
3956 if ((ptr = (char *) sub_val + ooffset)) {
3957 *ptr = '\0';
3958 }
3959 }
3960 }
3961
3962 switch_safe_free(expanded)if (expanded) {free(expanded);expanded=((void*)0);};
3963 } else {
3964 switch_stream_handle_t stream = { 0 };
3965 char *expanded = NULL((void*)0);
3966
3967 SWITCH_STANDARD_STREAM(stream)memset(&stream, 0, sizeof(stream)); stream.data = malloc(
1024); ((stream.data) ? (void) (0) : __assert_fail ("stream.data"
, "src/switch_channel.c", 3967, __PRETTY_FUNCTION__)); memset
(stream.data, 0, 1024); stream.end = stream.data; stream.data_size
= 1024; stream.write_function = switch_console_stream_write;
stream.raw_write_function = switch_console_stream_raw_write;
stream.alloc_len = 1024; stream.alloc_chunk = 1024
;
3968
3969 if (stream.data) {
3970 char *expanded_vname = NULL((void*)0);
3971
3972 if ((expanded_vname = switch_channel_expand_variables_check(channel, (char *) vname, var_list, api_list, recur+1)) == vname) {
3973 expanded_vname = NULL((void*)0);
3974 } else {
3975 vname = expanded_vname;
3976 }
3977
3978 if ((expanded = switch_channel_expand_variables_check(channel, vval, var_list, api_list, recur+1)) == vval) {
3979 expanded = NULL((void*)0);
3980 } else {
3981 vval = expanded;
3982 }
3983
3984 if (!switch_core_test_flag(SCF_API_EXPANSION) || (api_list && !switch_event_check_permission_list(api_list, vname))) {
3985 func_val = NULL((void*)0);
3986 sub_val = "<API Execute Permission Denied>";
3987 } else {
3988 if (switch_api_execute(vname, vval, channel->session, &stream) == SWITCH_STATUS_SUCCESS) {
3989 func_val = stream.data;
3990 sub_val = func_val;
3991 } else {
3992 free(stream.data);
3993 }
3994 }
3995
3996 switch_safe_free(expanded)if (expanded) {free(expanded);expanded=((void*)0);};
3997 switch_safe_free(expanded_vname)if (expanded_vname) {free(expanded_vname);expanded_vname=((void
*)0);}
;
3998
3999 } else {
4000 switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel)SWITCH_CHANNEL_ID_SESSION, "src/switch_channel.c", (const char
*)__func__, 4000, (const char*)switch_channel_get_session(channel
)
, SWITCH_LOG_CRIT, "Memory Error!\n");
4001 free(data);
4002 free(indup);
4003 return (char *) in;
4004 }
4005 }
4006 if ((nlen = sub_val ? strlen(sub_val) : 0)) {
4007 if (len + nlen >= olen) {
4008 resize(nlen){ char *dp; olen += (len + nlen + block); cpos = c - data; if
((dp = realloc(data, olen))) { data = dp; c = data + cpos; memset
(c, 0, olen - cpos); }}
;
4009 }
4010
4011 len += nlen;
4012 strcat(c, sub_val);
4013 c += nlen;
4014 }
4015
4016 switch_safe_free(func_val)if (func_val) {free(func_val);func_val=((void*)0);};
4017 switch_safe_free(cloned_sub_val)if (cloned_sub_val) {free(cloned_sub_val);cloned_sub_val=((void
*)0);}
;
4018 switch_safe_free(expanded_sub_val)if (expanded_sub_val) {free(expanded_sub_val);expanded_sub_val
=((void*)0);}
;
4019 sub_val = NULL((void*)0);
4020 vname = NULL((void*)0);
4021 br = 0;
4022 }
4023 if (len + 1 >= olen) {
4024 resize(1){ char *dp; olen += (len + 1 + block); cpos = c - data; if ((
dp = realloc(data, olen))) { data = dp; c = data + cpos; memset
(c, 0, olen - cpos); }}
;
4025 }
4026
4027 if (sp) {
4028 *c++ = ' ';
4029 sp = 0;
4030 len++;
4031 }
4032
4033 if (*p == '$') {
4034 p--;
4035 } else {
4036 *c++ = *p;
4037 len++;
4038 }
4039 }
4040 }
4041 free(indup);
4042
4043 return data;
4044}
4045
4046SWITCH_DECLARE(char *)__attribute__((visibility("default"))) char * switch_channel_build_param_string(switch_channel_t *channel, switch_caller_profile_t *caller_profile, const char *prefix)
4047{
4048 switch_stream_handle_t stream = { 0 };
4049 switch_size_t encode_len = 1024, new_len = 0;
4050 char *encode_buf = NULL((void*)0);
4051 const char *prof[13] = { 0 }, *prof_names[13] = {
4052 0};
4053 char *e = NULL((void*)0);
4054 switch_event_header_t *hi;
4055 uint32_t x = 0;
4056
4057 SWITCH_STANDARD_STREAM(stream)memset(&stream, 0, sizeof(stream)); stream.data = malloc(
1024); ((stream.data) ? (void) (0) : __assert_fail ("stream.data"
, "src/switch_channel.c", 4057, __PRETTY_FUNCTION__)); memset
(stream.data, 0, 1024); stream.end = stream.data; stream.data_size
= 1024; stream.write_function = switch_console_stream_write;
stream.raw_write_function = switch_console_stream_raw_write;
stream.alloc_len = 1024; stream.alloc_chunk = 1024
;
4058
4059 if (prefix) {
4060 stream.write_function(&stream, "%s&", prefix);
4061 }
4062
4063 encode_buf = malloc(encode_len);
4064 switch_assert(encode_buf)((encode_buf) ? (void) (0) : __assert_fail ("encode_buf", "src/switch_channel.c"
, 4064, __PRETTY_FUNCTION__))
;
4065
4066 if (!caller_profile) {
4067 caller_profile = switch_channel_get_caller_profile(channel);
4068 }
4069
4070 switch_assert(caller_profile != NULL)((caller_profile != ((void*)0)) ? (void) (0) : __assert_fail (
"caller_profile != ((void*)0)", "src/switch_channel.c", 4070,
__PRETTY_FUNCTION__))
;
4071
4072 prof[0] = caller_profile->context;
4073 prof[1] = caller_profile->destination_number;
4074 prof[2] = caller_profile->caller_id_name;
4075 prof[3] = caller_profile->caller_id_number;
4076 prof[4] = caller_profile->network_addr;
4077 prof[5] = caller_profile->ani;
4078 prof[6] = caller_profile->aniii;
4079 prof[7] = caller_profile->rdnis;
4080 prof[8] = caller_profile->source;
4081 prof[9] = caller_profile->chan_name;
4082 prof[10] = caller_profile->uuid;
4083 prof[11] = caller_profile->transfer_source;
4084
4085 prof_names[0] = "context";
4086 prof_names[1] = "destination_number";
4087 prof_names[2] = "caller_id_name";
4088 prof_names[3] = "caller_id_number";
4089 prof_names[4] = "network_addr";
4090 prof_names[5] = "ani";
4091 prof_names[6] = "aniii";
4092 prof_names[7] = "rdnis";
4093 prof_names[8] = "source";
4094 prof_names[9] = "chan_name";
4095 prof_names[10] = "uuid";
4096 prof_names[11] = "transfer_source";
4097
4098 for (x = 0; prof[x]; x++) {
4099 if (zstr(prof[x])_zstr(prof[x])) {
4100 continue;
4101 }
4102 new_len = (strlen(prof[x]) * 3) + 1;
4103 if (encode_len < new_len) {
4104 char *tmp;
4105
4106 encode_len = new_len;
4107
4108 if (!(tmp = realloc(encode_buf, encode_len))) {
4109 abort();
4110 }
4111
4112 encode_buf = tmp;
4113 }
4114 switch_url_encode(prof[x], encode_buf, encode_len);
4115 stream.write_function(&stream, "%s=%s&", prof_names[x], encode_buf);
4116 }
4117
4118 if (channel->caller_profile->soft) {
4119 profile_node_t *pn;
4120
4121 for(pn = channel->caller_profile->soft; pn; pn = pn->next) {
4122 char *var = pn->var;
4123 char *val = pn->val;
4124
4125 new_len = (strlen((char *) var) * 3) + 1;
4126 if (encode_len < new_len) {
4127 char *tmp;
4128
4129 encode_len = new_len;
4130
4131 tmp = realloc(encode_buf, encode_len);
4132 switch_assert(tmp)((tmp) ? (void) (0) : __assert_fail ("tmp", "src/switch_channel.c"
, 4132, __PRETTY_FUNCTION__))
;
4133 encode_buf = tmp;
4134 }
4135
4136 switch_url_encode((char *) val, encode_buf, encode_len);
4137 stream.write_function(&stream, "%s=%s&", (char *) var, encode_buf);
4138
4139 }
4140 }
4141
4142 if ((hi = switch_channel_variable_first(channel))) {
4143 for (; hi; hi = hi->next) {
4144 char *var = hi->name;
4145 char *val = hi->value;
4146
4147 new_len = (strlen((char *) var) * 3) + 1;
4148 if (encode_len < new_len) {
4149 char *tmp;
4150
4151 encode_len = new_len;
4152
4153 tmp = realloc(encode_buf, encode_len);
4154 switch_assert(tmp)((tmp) ? (void) (0) : __assert_fail ("tmp", "src/switch_channel.c"
, 4154, __PRETTY_FUNCTION__))
;
4155 encode_buf = tmp;
4156 }
4157
4158 switch_url_encode((char *) val, encode_buf, encode_len);
4159 stream.write_function(&stream, "%s=%s&", (char *) var, encode_buf);
4160
4161 }
4162 switch_channel_variable_last(channel);
4163 }
4164
4165 e = (char *) stream.data + (strlen((char *) stream.data) - 1);
4166
4167 if (e && *e == '&') {
4168 *e = '\0';
4169 }
4170
4171 switch_safe_free(encode_buf)if (encode_buf) {free(encode_buf);encode_buf=((void*)0);};
4172
4173 return stream.data;
4174}
4175
4176SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_channel_pass_callee_id(switch_channel_t *channel, switch_channel_t *other_channel)
4177{
4178 int x = 0;
4179
4180 switch_assert(channel)((channel) ? (void) (0) : __assert_fail ("channel", "src/switch_channel.c"
, 4180, __PRETTY_FUNCTION__))
;
4181 switch_assert(other_channel)((other_channel) ? (void) (0) : __assert_fail ("other_channel"
, "src/switch_channel.c", 4181, __PRETTY_FUNCTION__))
;
4182
4183 switch_mutex_lock(channel->profile_mutex);
4184 switch_mutex_lock(other_channel->profile_mutex);
4185
4186 if (!zstr(channel->caller_profile->callee_id_name)_zstr(channel->caller_profile->callee_id_name)) {
4187 other_channel->caller_profile->callee_id_name = switch_core_strdup(other_channel->caller_profile->pool, channel->caller_profile->callee_id_name)switch_core_perform_strdup(other_channel->caller_profile->
pool, channel->caller_profile->callee_id_name, "src/switch_channel.c"
, (const char *)__func__, 4187)
;
4188 x++;
4189 }
4190
4191 if (!zstr(channel->caller_profile->callee_id_number)_zstr(channel->caller_profile->callee_id_number)) {
4192 other_channel->caller_profile->callee_id_number = switch_core_strdup(other_channel->caller_profile->pool, channel->caller_profile->callee_id_number)switch_core_perform_strdup(other_channel->caller_profile->
pool, channel->caller_profile->callee_id_number, "src/switch_channel.c"
, (const char *)__func__, 4192)
;
4193 x++;
4194 }
4195
4196 switch_mutex_unlock(other_channel->profile_mutex);
4197 switch_mutex_unlock(channel->profile_mutex);
4198
4199 return x ? SWITCH_STATUS_SUCCESS : SWITCH_STATUS_FALSE;
4200}
4201
4202SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_channel_get_variables(switch_channel_t *channel, switch_event_t **event)
4203{
4204 switch_status_t status;
4205 switch_mutex_lock(channel->profile_mutex);
4206 if (channel->variables) {
4207 status = switch_event_dup(event, channel->variables);
4208 } else {
4209 status = switch_event_create(event, SWITCH_EVENT_CHANNEL_DATA)switch_event_create_subclass_detailed("src/switch_channel.c",
(const char * )(const char *)__func__, 4209, event, SWITCH_EVENT_CHANNEL_DATA
, ((void*)0))
;
4210 }
4211 switch_mutex_unlock(channel->profile_mutex);
4212 return status;
4213}
4214
4215SWITCH_DECLARE(switch_core_session_t *)__attribute__((visibility("default"))) switch_core_session_t * switch_channel_get_session(switch_channel_t *channel)
4216{
4217 switch_assert(channel)((channel) ? (void) (0) : __assert_fail ("channel", "src/switch_channel.c"
, 4217, __PRETTY_FUNCTION__))
;
4218 return channel->session;
4219}
4220
4221SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_channel_set_timestamps(switch_channel_t *channel)
4222{
4223 switch_status_t status = SWITCH_STATUS_SUCCESS;
4224 const char *cid_buf = NULL((void*)0);
4225 switch_caller_profile_t *caller_profile;
4226 switch_app_log_t *app_log, *ap;
4227 char *last_app = NULL((void*)0), *last_arg = NULL((void*)0);
4228 char start[80] = "", resurrect[80] = "", answer[80] = "", hold[80],
4229 bridge[80] = "", progress[80] = "", progress_media[80] = "", end[80] = "", tmp[80] = "",
4230 profile_start[80] = "";
4231 int32_t duration = 0, legbillsec = 0, billsec = 0, mduration = 0, billmsec = 0, legbillmsec = 0, progressmsec = 0, progress_mediamsec = 0;
4232 int32_t answersec = 0, answermsec = 0, waitsec = 0, waitmsec = 0;
4233 switch_time_t answerusec = 0;
4234 switch_time_t uduration = 0, legbillusec = 0, billusec = 0, progresssec = 0, progressusec = 0, progress_mediasec = 0, progress_mediausec = 0, waitusec = 0;
4235 time_t tt_created = 0, tt_answered = 0, tt_resurrected = 0, tt_bridged, tt_last_hold, tt_hold_accum,
4236 tt_progress = 0, tt_progress_media = 0, tt_hungup = 0, mtt_created = 0, mtt_answered = 0, mtt_bridged = 0,
4237 mtt_hungup = 0, tt_prof_created, mtt_progress = 0, mtt_progress_media = 0;
4238 void *pop;
4239 char dtstr[SWITCH_DTMF_LOG_LEN1000 + 1] = "";
4240 int x = 0;
4241
4242 switch_mutex_lock(channel->profile_mutex);
4243
4244 if (switch_channel_test_flag(channel, CF_TIMESTAMP_SET)) {
4245 switch_mutex_unlock(channel->profile_mutex);
4246 return SWITCH_STATUS_FALSE;
4247 }
4248
4249 if (!(caller_profile = channel->caller_profile) || !channel->variables) {
4250 switch_mutex_unlock(channel->profile_mutex);
4251 return SWITCH_STATUS_FALSE;
4252 }
4253
4254 switch_channel_set_flag(channel, CF_TIMESTAMP_SET)switch_channel_set_flag_value(channel, CF_TIMESTAMP_SET, 1);
4255
4256 if ((app_log = switch_core_session_get_app_log(channel->session))) {
4257 for (ap = app_log; ap && ap->next; ap = ap->next);
4258 last_app = ap->app;
4259 last_arg = ap->arg;
4260 }
4261
4262 if (!zstr(caller_profile->caller_id_name)_zstr(caller_profile->caller_id_name)) {
4263 cid_buf = switch_core_session_sprintf(channel->session, "\"%s\" <%s>", caller_profile->caller_id_name,
4264 switch_str_nil(caller_profile->caller_id_number)(caller_profile->caller_id_number ? caller_profile->caller_id_number
: "")
);
4265 } else {
4266 cid_buf = caller_profile->caller_id_number;
4267 }
4268
4269 while (x < SWITCH_DTMF_LOG_LEN1000 && switch_queue_trypop(channel->dtmf_log_queue, &pop) == SWITCH_STATUS_SUCCESS) {
4270 switch_dtmf_t *dt = (switch_dtmf_t *) pop;
4271
4272 if (dt) {
4273 dtstr[x++] = dt->digit;
4274 free(dt);
4275 dt = NULL((void*)0);
4276 }
4277 }
4278
4279 if (x) {
4280 const char *var = switch_channel_get_variable(channel, "digits_dialed_filter")switch_channel_get_variable_dup(channel, "digits_dialed_filter"
, SWITCH_TRUE, -1)
;
4281 char *digit_string = dtstr;
4282 char *X = NULL((void*)0);
4283 switch_regex_t *re = NULL((void*)0);
4284 char *substituted = NULL((void*)0);
4285
4286 if (!zstr(var)_zstr(var)) {
4287 int proceed = 0;
4288 int ovector[30];
4289
4290 if ((proceed = switch_regex_perform(dtstr, var, &re, ovector, sizeof(ovector) / sizeof(ovector[0])))) {
4291 int len = (strlen(dtstr) + strlen(var) + 10) * proceed;
4292 int i = 0;
4293 const char *replace = NULL((void*)0);
4294
4295 X = malloc(len);
4296
4297 for (i = 0; i < proceed; i++) {
4298 if (pcre_get_substring(dtstr, ovector, proceed, i, &replace) > 0) {
4299 switch_size_t plen = strlen(replace);
4300 memset(X, 'X', plen);
4301 *(X+plen) = '\0';
4302
4303 switch_safe_free(substituted)if (substituted) {free(substituted);substituted=((void*)0);};
4304 substituted = switch_string_replace(substituted ? substituted : dtstr, replace, X);
4305
4306 pcre_free_substring(replace);
4307 }
4308 }
4309
4310 if (!zstr(substituted)_zstr(substituted)) {
4311 digit_string = substituted;
4312 }
4313 }
4314 }
4315
4316 switch_channel_set_variable(channel, "digits_dialed", digit_string)switch_channel_set_variable_var_check(channel, "digits_dialed"
, digit_string, SWITCH_TRUE)
;
4317 switch_regex_safe_free(re)if (re) { switch_regex_free(re); re = ((void*)0); };
4318 switch_safe_free(substituted)if (substituted) {free(substituted);substituted=((void*)0);};
4319 switch_safe_free(X)if (X) {free(X);X=((void*)0);};
4320 } else {
4321 switch_channel_set_variable(channel, "digits_dialed", "none")switch_channel_set_variable_var_check(channel, "digits_dialed"
, "none", SWITCH_TRUE)
;
4322 }
4323
4324 if (caller_profile->times) {
4325 switch_time_exp_t tm;
4326 switch_size_t retsize;
4327 const char *fmt = "%Y-%m-%d %T";
4328
4329 switch_time_exp_lt(&tm, caller_profile->times->created);
4330 switch_strftime_nocheck(start, &retsize, sizeof(start), fmt, &tm);
4331 switch_channel_set_variable(channel, "start_stamp", start)switch_channel_set_variable_var_check(channel, "start_stamp",
start, SWITCH_TRUE)
;
4332
4333 switch_time_exp_lt(&tm, caller_profile->times->profile_created);
4334 switch_strftime_nocheck(profile_start, &retsize, sizeof(profile_start), fmt, &tm);
4335 switch_channel_set_variable(channel, "profile_start_stamp", profile_start)switch_channel_set_variable_var_check(channel, "profile_start_stamp"
, profile_start, SWITCH_TRUE)
;
4336
4337 if (caller_profile->times->answered) {
4338 switch_time_exp_lt(&tm, caller_profile->times->answered);
4339 switch_strftime_nocheck(answer, &retsize, sizeof(answer), fmt, &tm);
4340 switch_channel_set_variable(channel, "answer_stamp", answer)switch_channel_set_variable_var_check(channel, "answer_stamp"
, answer, SWITCH_TRUE)
;
4341 }
4342
4343 if (caller_profile->times->bridged) {
4344 switch_time_exp_lt(&tm, caller_profile->times->bridged);
4345 switch_strftime_nocheck(bridge, &retsize, sizeof(bridge), fmt, &tm);
4346 switch_channel_set_variable(channel, "bridge_stamp", bridge)switch_channel_set_variable_var_check(channel, "bridge_stamp"
, bridge, SWITCH_TRUE)
;
4347 }
4348
4349 if (caller_profile->times->last_hold) {
4350 switch_time_exp_lt(&tm, caller_profile->times->last_hold);
4351 switch_strftime_nocheck(hold, &retsize, sizeof(hold), fmt, &tm);
4352 switch_channel_set_variable(channel, "hold_stamp", hold)switch_channel_set_variable_var_check(channel, "hold_stamp", hold
, SWITCH_TRUE)
;
4353 }
4354
4355 if (caller_profile->times->resurrected) {
4356 switch_time_exp_lt(&tm, caller_profile->times->resurrected);
4357 switch_strftime_nocheck(resurrect, &retsize, sizeof(resurrect), fmt, &tm);
4358 switch_channel_set_variable(channel, "resurrect_stamp", resurrect)switch_channel_set_variable_var_check(channel, "resurrect_stamp"
, resurrect, SWITCH_TRUE)
;
4359 }
4360
4361 if (caller_profile->times->progress) {
4362 switch_time_exp_lt(&tm, caller_profile->times->progress);
4363 switch_strftime_nocheck(progress, &retsize, sizeof(progress), fmt, &tm);
4364 switch_channel_set_variable(channel, "progress_stamp", progress)switch_channel_set_variable_var_check(channel, "progress_stamp"
, progress, SWITCH_TRUE)
;
4365 }
4366
4367 if (caller_profile->times->progress_media) {
4368 switch_time_exp_lt(&tm, caller_profile->times->progress_media);
4369 switch_strftime_nocheck(progress_media, &retsize, sizeof(progress_media), fmt, &tm);
4370 switch_channel_set_variable(channel, "progress_media_stamp", progress_media)switch_channel_set_variable_var_check(channel, "progress_media_stamp"
, progress_media, SWITCH_TRUE)
;
4371 }
4372
4373 if (channel->hold_record) {
4374 switch_hold_record_t *hr;
4375 switch_stream_handle_t stream = { 0 };
4376
4377 SWITCH_STANDARD_STREAM(stream)memset(&stream, 0, sizeof(stream)); stream.data = malloc(
1024); ((stream.data) ? (void) (0) : __assert_fail ("stream.data"
, "src/switch_channel.c", 4377, __PRETTY_FUNCTION__)); memset
(stream.data, 0, 1024); stream.end = stream.data; stream.data_size
= 1024; stream.write_function = switch_console_stream_write;
stream.raw_write_function = switch_console_stream_raw_write;
stream.alloc_len = 1024; stream.alloc_chunk = 1024
;
4378
4379 stream.write_function(&stream, "{", SWITCH_VA_NONE"%s", "");
4380
4381 for (hr = channel->hold_record; hr; hr = hr->next) {
4382 stream.write_function(&stream, "{%"SWITCH_TIME_T_FMT"ld"",%"SWITCH_TIME_T_FMT"ld""},", hr->on, hr->off);
4383 }
4384 end_of((char *)stream.data)*(*(char *)stream.data == '\0' ? (char *)stream.data : (char *
)stream.data + strlen((char *)stream.data) - 1)
= '}';
4385
4386 switch_channel_set_variable(channel, "hold_events", (char *)stream.data)switch_channel_set_variable_var_check(channel, "hold_events",
(char *)stream.data, SWITCH_TRUE)
;
4387 free(stream.data);
4388 }
4389
4390 switch_time_exp_lt(&tm, caller_profile->times->hungup);
4391 switch_strftime_nocheck(end, &retsize, sizeof(end), fmt, &tm);
4392 switch_channel_set_variable(channel, "end_stamp", end)switch_channel_set_variable_var_check(channel, "end_stamp", end
, SWITCH_TRUE)
;
4393
4394 tt_created = (time_t) (caller_profile->times->created / 1000000);
4395 mtt_created = (time_t) (caller_profile->times->created / 1000);
4396 switch_snprintf(tmp, sizeof(tmp), "%" TIME_T_FMT"ld", tt_created);
4397 switch_channel_set_variable(channel, "start_epoch", tmp)switch_channel_set_variable_var_check(channel, "start_epoch",
tmp, SWITCH_TRUE)
;
4398 switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT"ld", caller_profile->times->created);
4399 switch_channel_set_variable(channel, "start_uepoch", tmp)switch_channel_set_variable_var_check(channel, "start_uepoch"
, tmp, SWITCH_TRUE)
;
4400
4401 tt_prof_created = (time_t) (caller_profile->times->profile_created / 1000000);
4402 switch_snprintf(tmp, sizeof(tmp), "%" TIME_T_FMT"ld", tt_prof_created);
4403 switch_channel_set_variable(channel, "profile_start_epoch", tmp)switch_channel_set_variable_var_check(channel, "profile_start_epoch"
, tmp, SWITCH_TRUE)
;
4404 switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT"ld", caller_profile->times->profile_created);
4405 switch_channel_set_variable(channel, "profile_start_uepoch", tmp)switch_channel_set_variable_var_check(channel, "profile_start_uepoch"
, tmp, SWITCH_TRUE)
;
4406
4407 tt_answered = (time_t) (caller_profile->times->answered / 1000000);
4408 mtt_answered = (time_t) (caller_profile->times->answered / 1000);
4409 switch_snprintf(tmp, sizeof(tmp), "%" TIME_T_FMT"ld", tt_answered);
4410 switch_channel_set_variable(channel, "answer_epoch", tmp)switch_channel_set_variable_var_check(channel, "answer_epoch"
, tmp, SWITCH_TRUE)
;
4411 switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT"ld", caller_profile->times->answered);
4412 switch_channel_set_variable(channel, "answer_uepoch", tmp)switch_channel_set_variable_var_check(channel, "answer_uepoch"
, tmp, SWITCH_TRUE)
;
4413
4414 tt_bridged = (time_t) (caller_profile->times->bridged / 1000000);
4415 mtt_bridged = (time_t) (caller_profile->times->bridged / 1000);
4416 switch_snprintf(tmp, sizeof(tmp), "%" TIME_T_FMT"ld", tt_bridged);
4417 switch_channel_set_variable(channel, "bridge_epoch", tmp)switch_channel_set_variable_var_check(channel, "bridge_epoch"
, tmp, SWITCH_TRUE)
;
4418 switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT"ld", caller_profile->times->bridged);
4419 switch_channel_set_variable(channel, "bridge_uepoch", tmp)switch_channel_set_variable_var_check(channel, "bridge_uepoch"
, tmp, SWITCH_TRUE)
;
4420
4421 tt_last_hold = (time_t) (caller_profile->times->last_hold / 1000000);
4422 switch_snprintf(tmp, sizeof(tmp), "%" TIME_T_FMT"ld", tt_last_hold);
4423 switch_channel_set_variable(channel, "last_hold_epoch", tmp)switch_channel_set_variable_var_check(channel, "last_hold_epoch"
, tmp, SWITCH_TRUE)
;
4424 switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT"ld", caller_profile->times->last_hold);
4425 switch_channel_set_variable(channel, "last_hold_uepoch", tmp)switch_channel_set_variable_var_check(channel, "last_hold_uepoch"
, tmp, SWITCH_TRUE)
;
4426
4427 tt_hold_accum = (time_t) (caller_profile->times->hold_accum / 1000000);
4428 switch_snprintf(tmp, sizeof(tmp), "%" TIME_T_FMT"ld", tt_hold_accum);
4429 switch_channel_set_variable(channel, "hold_accum_seconds", tmp)switch_channel_set_variable_var_check(channel, "hold_accum_seconds"
, tmp, SWITCH_TRUE)
;
4430 switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT"ld", caller_profile->times->hold_accum);
4431 switch_channel_set_variable(channel, "hold_accum_usec", tmp)switch_channel_set_variable_var_check(channel, "hold_accum_usec"
, tmp, SWITCH_TRUE)
;
4432 switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT"ld", caller_profile->times->hold_accum / 1000);
4433 switch_channel_set_variable(channel, "hold_accum_ms", tmp)switch_channel_set_variable_var_check(channel, "hold_accum_ms"
, tmp, SWITCH_TRUE)
;
4434
4435 tt_resurrected = (time_t) (caller_profile->times->resurrected / 1000000);
4436 switch_snprintf(tmp, sizeof(tmp), "%" TIME_T_FMT"ld", tt_resurrected);
4437 switch_channel_set_variable(channel, "resurrect_epoch", tmp)switch_channel_set_variable_var_check(channel, "resurrect_epoch"
, tmp, SWITCH_TRUE)
;
4438 switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT"ld", caller_profile->times->resurrected);
4439 switch_channel_set_variable(channel, "resurrect_uepoch", tmp)switch_channel_set_variable_var_check(channel, "resurrect_uepoch"
, tmp, SWITCH_TRUE)
;
4440
4441 tt_progress = (time_t) (caller_profile->times->progress / 1000000);
4442 mtt_progress = (time_t) (caller_profile->times->progress / 1000);
4443 switch_snprintf(tmp, sizeof(tmp), "%" TIME_T_FMT"ld", tt_progress);
4444 switch_channel_set_variable(channel, "progress_epoch", tmp)switch_channel_set_variable_var_check(channel, "progress_epoch"
, tmp, SWITCH_TRUE)
;
4445 switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT"ld", caller_profile->times->progress);
4446 switch_channel_set_variable(channel, "progress_uepoch", tmp)switch_channel_set_variable_var_check(channel, "progress_uepoch"
, tmp, SWITCH_TRUE)
;
4447
4448 tt_progress_media = (time_t) (caller_profile->times->progress_media / 1000000);
4449 mtt_progress_media = (time_t) (caller_profile->times->progress_media / 1000);
4450 switch_snprintf(tmp, sizeof(tmp), "%" TIME_T_FMT"ld", tt_progress_media);
4451 switch_channel_set_variable(channel, "progress_media_epoch", tmp)switch_channel_set_variable_var_check(channel, "progress_media_epoch"
, tmp, SWITCH_TRUE)
;
4452 switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT"ld", caller_profile->times->progress_media);
4453 switch_channel_set_variable(channel, "progress_media_uepoch", tmp)switch_channel_set_variable_var_check(channel, "progress_media_uepoch"
, tmp, SWITCH_TRUE)
;
4454
4455 tt_hungup = (time_t) (caller_profile->times->hungup / 1000000);
4456 mtt_hungup = (time_t) (caller_profile->times->hungup / 1000);
4457 switch_snprintf(tmp, sizeof(tmp), "%" TIME_T_FMT"ld", tt_hungup);
4458 switch_channel_set_variable(channel, "end_epoch", tmp)switch_channel_set_variable_var_check(channel, "end_epoch", tmp
, SWITCH_TRUE)
;
4459 switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT"ld", caller_profile->times->hungup);
4460 switch_channel_set_variable(channel, "end_uepoch", tmp)switch_channel_set_variable_var_check(channel, "end_uepoch", tmp
, SWITCH_TRUE)
;
4461
4462 duration = (int32_t) (tt_hungup - tt_created);
4463 mduration = (int32_t) (mtt_hungup - mtt_created);
4464 uduration = caller_profile->times->hungup - caller_profile->times->created;
4465
4466 if (caller_profile->times->bridged > caller_profile->times->created) {
4467 waitsec = (int32_t) (tt_bridged - tt_created);
4468 waitmsec = (int32_t) (mtt_bridged - mtt_created);
4469 waitusec = caller_profile->times->bridged - caller_profile->times->created;
4470 } else {
4471 waitsec = 0;
4472 waitmsec = 0;
4473 waitusec = 0;
4474 }
4475
4476 if (caller_profile->times->answered) {
4477 billsec = (int32_t) (tt_hungup - tt_answered);
4478 billmsec = (int32_t) (mtt_hungup - mtt_answered);
4479 billusec = caller_profile->times->hungup - caller_profile->times->answered;
4480
4481 legbillsec = (int32_t) (tt_hungup - tt_created);
4482 legbillmsec = (int32_t) (mtt_hungup - mtt_created);
4483 legbillusec = caller_profile->times->hungup - caller_profile->times->created;
4484
4485 answersec = (int32_t) (tt_answered - tt_created);
4486 answermsec = (int32_t) (mtt_answered - mtt_created);
4487 answerusec = caller_profile->times->answered - caller_profile->times->created;
4488 }
4489
4490 if (caller_profile->times->progress) {
4491 progresssec = (int32_t) (tt_progress - tt_created);
4492 progressmsec = (int32_t) (mtt_progress - mtt_created);
4493 progressusec = caller_profile->times->progress - caller_profile->times->created;
4494 }
4495
4496 if (caller_profile->times->progress_media) {
4497 progress_mediasec = (int32_t) (tt_progress_media - tt_created);
4498 progress_mediamsec = (int32_t) (mtt_progress_media - mtt_created);
4499 progress_mediausec = caller_profile->times->progress_media - caller_profile->times->created;
4500 }
4501
4502 }
4503
4504 switch_channel_set_variable(channel, "last_app", last_app)switch_channel_set_variable_var_check(channel, "last_app", last_app
, SWITCH_TRUE)
;
4505 switch_channel_set_variable(channel, "last_arg", last_arg)switch_channel_set_variable_var_check(channel, "last_arg", last_arg
, SWITCH_TRUE)
;
4506 switch_channel_set_variable(channel, "caller_id", cid_buf)switch_channel_set_variable_var_check(channel, "caller_id", cid_buf
, SWITCH_TRUE)
;
4507
4508 switch_snprintf(tmp, sizeof(tmp), "%d", duration);
4509 switch_channel_set_variable(channel, "duration", tmp)switch_channel_set_variable_var_check(channel, "duration", tmp
, SWITCH_TRUE)
;
4510
4511 switch_snprintf(tmp, sizeof(tmp), "%d", billsec);
4512 switch_channel_set_variable(channel, "billsec", tmp)switch_channel_set_variable_var_check(channel, "billsec", tmp
, SWITCH_TRUE)
;
4513
4514 switch_snprintf(tmp, sizeof(tmp), "%"SWITCH_TIME_T_FMT"ld", progresssec);
4515 switch_channel_set_variable(channel, "progresssec", tmp)switch_channel_set_variable_var_check(channel, "progresssec",
tmp, SWITCH_TRUE)
;
4516
4517 switch_snprintf(tmp, sizeof(tmp), "%d", answersec);
4518 switch_channel_set_variable(channel, "answersec", tmp)switch_channel_set_variable_var_check(channel, "answersec", tmp
, SWITCH_TRUE)
;
4519
4520 switch_snprintf(tmp, sizeof(tmp), "%d", waitsec);
4521 switch_channel_set_variable(channel, "waitsec", tmp)switch_channel_set_variable_var_check(channel, "waitsec", tmp
, SWITCH_TRUE)
;
4522
4523 switch_snprintf(tmp, sizeof(tmp), "%"SWITCH_TIME_T_FMT"ld", progress_mediasec);
4524 switch_channel_set_variable(channel, "progress_mediasec", tmp)switch_channel_set_variable_var_check(channel, "progress_mediasec"
, tmp, SWITCH_TRUE)
;
4525
4526 switch_snprintf(tmp, sizeof(tmp), "%d", legbillsec);
4527 switch_channel_set_variable(channel, "flow_billsec", tmp)switch_channel_set_variable_var_check(channel, "flow_billsec"
, tmp, SWITCH_TRUE)
;
4528
4529 switch_snprintf(tmp, sizeof(tmp), "%d", mduration);
4530 switch_channel_set_variable(channel, "mduration", tmp)switch_channel_set_variable_var_check(channel, "mduration", tmp
, SWITCH_TRUE)
;
4531
4532 switch_snprintf(tmp, sizeof(tmp), "%d", billmsec);
4533 switch_channel_set_variable(channel, "billmsec", tmp)switch_channel_set_variable_var_check(channel, "billmsec", tmp
, SWITCH_TRUE)
;
4534
4535 switch_snprintf(tmp, sizeof(tmp), "%d", progressmsec);
4536 switch_channel_set_variable(channel, "progressmsec", tmp)switch_channel_set_variable_var_check(channel, "progressmsec"
, tmp, SWITCH_TRUE)
;
4537
4538 switch_snprintf(tmp, sizeof(tmp), "%d", answermsec);
4539 switch_channel_set_variable(channel, "answermsec", tmp)switch_channel_set_variable_var_check(channel, "answermsec", tmp
, SWITCH_TRUE)
;
4540
4541 switch_snprintf(tmp, sizeof(tmp), "%d", waitmsec);
4542 switch_channel_set_variable(channel, "waitmsec", tmp)switch_channel_set_variable_var_check(channel, "waitmsec", tmp
, SWITCH_TRUE)
;
4543
4544 switch_snprintf(tmp, sizeof(tmp), "%d", progress_mediamsec);
4545 switch_channel_set_variable(channel, "progress_mediamsec", tmp)switch_channel_set_variable_var_check(channel, "progress_mediamsec"
, tmp, SWITCH_TRUE)
;
4546
4547 switch_snprintf(tmp, sizeof(tmp), "%d", legbillmsec);
4548 switch_channel_set_variable(channel, "flow_billmsec", tmp)switch_channel_set_variable_var_check(channel, "flow_billmsec"
, tmp, SWITCH_TRUE)
;
4549
4550 switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT"ld", uduration);
4551 switch_channel_set_variable(channel, "uduration", tmp)switch_channel_set_variable_var_check(channel, "uduration", tmp
, SWITCH_TRUE)
;
4552
4553 switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT"ld", billusec);
4554 switch_channel_set_variable(channel, "billusec", tmp)switch_channel_set_variable_var_check(channel, "billusec", tmp
, SWITCH_TRUE)
;
4555
4556 switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT"ld", progressusec);
4557 switch_channel_set_variable(channel, "progressusec", tmp)switch_channel_set_variable_var_check(channel, "progressusec"
, tmp, SWITCH_TRUE)
;
4558
4559 switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT"ld", answerusec);
4560 switch_channel_set_variable(channel, "answerusec", tmp)switch_channel_set_variable_var_check(channel, "answerusec", tmp
, SWITCH_TRUE)
;
4561
4562 switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT"ld", waitusec);
4563 switch_channel_set_variable(channel, "waitusec", tmp)switch_channel_set_variable_var_check(channel, "waitusec", tmp
, SWITCH_TRUE)
;
4564
4565 switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT"ld", progress_mediausec);
4566 switch_channel_set_variable(channel, "progress_mediausec", tmp)switch_channel_set_variable_var_check(channel, "progress_mediausec"
, tmp, SWITCH_TRUE)
;
4567
4568 switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT"ld", legbillusec);
4569 switch_channel_set_variable(channel, "flow_billusec", tmp)switch_channel_set_variable_var_check(channel, "flow_billusec"
, tmp, SWITCH_TRUE)
;
4570
4571 switch_mutex_unlock(channel->profile_mutex);
4572
4573 return status;
4574}
4575
4576SWITCH_DECLARE(const char *)__attribute__((visibility("default"))) const char * switch_channel_get_partner_uuid(switch_channel_t *channel)
4577{
4578 const char *uuid = NULL((void*)0);
4579
4580 if (!(uuid = switch_channel_get_variable(channel, SWITCH_SIGNAL_BOND_VARIABLE)switch_channel_get_variable_dup(channel, "signal_bond", SWITCH_TRUE
, -1)
)) {
4581 uuid = switch_channel_get_variable(channel, SWITCH_ORIGINATE_SIGNAL_BOND_VARIABLE)switch_channel_get_variable_dup(channel, "originate_signal_bond"
, SWITCH_TRUE, -1)
;
4582 }
4583
4584 return uuid;
4585}
4586
4587SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_channel_handle_cause(switch_channel_t *channel, switch_call_cause_t cause)
4588{
4589 switch_core_session_t *session = channel->session;
4590 const char *transfer_on_fail = NULL((void*)0);
4591 char *tof_data = NULL((void*)0);
4592 char *tof_array[4] = { 0 };
4593 //int tof_arrayc = 0;
4594
4595 if (!switch_channel_up_nosig(channel)(switch_channel_get_state(channel) < CS_HANGUP)) {
4596 return;
4597 }
4598
4599 transfer_on_fail = switch_channel_get_variable(channel, "transfer_on_fail")switch_channel_get_variable_dup(channel, "transfer_on_fail", SWITCH_TRUE
, -1)
;
4600 tof_data = switch_core_session_strdup(session, transfer_on_fail)switch_core_perform_session_strdup(session, transfer_on_fail,
"src/switch_channel.c", (const char *)__func__, 4600)
;
4601 switch_split(tof_data, ' ', tof_array)switch_separate_string(tof_data, ' ', tof_array, (sizeof(tof_array
) / sizeof(tof_array[0])))
;
4602 transfer_on_fail = tof_array[0];
4603
4604 /*
4605 if the variable continue_on_fail is set it can be:
4606 'true' to continue on all failures.
4607 'false' to not continue.
4608 A list of codes either names or numbers eg "user_busy,normal_temporary_failure,603"
4609 failure_causes acts as the opposite version
4610 EXCEPTION... ATTENDED_TRANSFER never is a reason to continue.......
4611 */
4612 if (cause != SWITCH_CAUSE_ATTENDED_TRANSFER) {
4613 const char *continue_on_fail = NULL((void*)0), *failure_causes = NULL((void*)0);
4614
4615 continue_on_fail = switch_channel_get_variable(channel, "continue_on_fail")switch_channel_get_variable_dup(channel, "continue_on_fail", SWITCH_TRUE
, -1)
;
4616 failure_causes = switch_channel_get_variable(channel, "failure_causes")switch_channel_get_variable_dup(channel, "failure_causes", SWITCH_TRUE
, -1)
;
4617
4618 if (continue_on_fail || failure_causes) {
4619 const char *cause_str;
4620 char cause_num[35] = "";
4621
4622 cause_str = switch_channel_cause2str(cause);
4623 switch_snprintf(cause_num, sizeof(cause_num), "%u", cause);
4624
4625 if (failure_causes) {
4626 char *lbuf = switch_core_session_strdup(session, failure_causes)switch_core_perform_session_strdup(session, failure_causes, "src/switch_channel.c"
, (const char *)__func__, 4626)
;
4627 char *argv[256] = { 0 };
4628 int argc = switch_separate_string(lbuf, ',', argv, (sizeof(argv) / sizeof(argv[0])));
4629 int i, x = 0;
4630
4631 for (i = 0; i < argc; i++) {
4632 if (!strcasecmp(argv[i], cause_str) || !strcasecmp(argv[i], cause_num)) {
4633 x++;
4634 break;
4635 }
4636 }
4637 if (!x) {
4638 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "src/switch_channel.c", (const char
*)__func__, 4638, (const char*)(session)
, SWITCH_LOG_DEBUG,
4639 "Failure causes [%s]: Cause: %s\n", failure_causes, cause_str);
4640 return;
4641 }
4642 }
4643
4644 if (continue_on_fail) {
4645 if (switch_true(continue_on_fail)) {
4646 return;
4647 } else {
4648 char *lbuf = switch_core_session_strdup(session, continue_on_fail)switch_core_perform_session_strdup(session, continue_on_fail,
"src/switch_channel.c", (const char *)__func__, 4648)
;
4649 char *argv[256] = { 0 };
4650 int argc = switch_separate_string(lbuf, ',', argv, (sizeof(argv) / sizeof(argv[0])));
4651 int i;
4652
4653 for (i = 0; i < argc; i++) {
4654 if (!strcasecmp(argv[i], cause_str) || !strcasecmp(argv[i], cause_num)) {
4655 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "src/switch_channel.c", (const char
*)__func__, 4655, (const char*)(session)
, SWITCH_LOG_DEBUG,
4656 "Continue on fail [%s]: Cause: %s\n", continue_on_fail, cause_str);
4657 return;
4658 }
4659 }
4660 }
4661 }
4662 } else {
4663 /* no answer is *always* a reason to continue */
4664 if (cause == SWITCH_CAUSE_NO_ANSWER || cause == SWITCH_CAUSE_NO_USER_RESPONSE || cause == SWITCH_CAUSE_ORIGINATOR_CANCEL) {
4665 return;
4666 }
4667 }
4668
4669 if (transfer_on_fail || failure_causes) {
4670 const char *cause_str;
4671 char cause_num[35] = "";
4672
4673 cause_str = switch_channel_cause2str(cause);
4674 switch_snprintf(cause_num, sizeof(cause_num), "%u", cause);
4675
4676 if ((tof_array[1] == NULL((void*)0) ) || (!strcasecmp(tof_array[1], "auto_cause"))){
4677 tof_array[1] = (char *) cause_str;
4678 }
4679
4680 if (failure_causes) {
4681 char *lbuf = switch_core_session_strdup(session, failure_causes)switch_core_perform_session_strdup(session, failure_causes, "src/switch_channel.c"
, (const char *)__func__, 4681)
;
4682 char *argv[256] = { 0 };
4683 int argc = switch_separate_string(lbuf, ',', argv, (sizeof(argv) / sizeof(argv[0])));
4684 int i, x = 0;
4685
4686 for (i = 0; i < argc; i++) {
4687 if (!strcasecmp(argv[i], cause_str) || !strcasecmp(argv[i], cause_num)) {
4688 x++;
4689 break;
4690 }
4691 }
4692 if (!x) {
4693 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "src/switch_channel.c", (const char
*)__func__, 4693, (const char*)(session)
, SWITCH_LOG_DEBUG,
4694 "Failure causes [%s]: Cause: %s\n", failure_causes, cause_str);
4695
4696 switch_ivr_session_transfer(session, tof_array[1], tof_array[2], tof_array[3]);
4697 }
4698 }
4699
4700 if (transfer_on_fail) {
4701 if (switch_true(transfer_on_fail)) {
4702 return;
4703 } else {
4704 char *lbuf = switch_core_session_strdup(session, transfer_on_fail)switch_core_perform_session_strdup(session, transfer_on_fail,
"src/switch_channel.c", (const char *)__func__, 4704)
;
4705 char *argv[256] = { 0 };
4706 int argc = switch_separate_string(lbuf, ',', argv, (sizeof(argv) / sizeof(argv[0])));
4707 int i;
4708
4709 for (i = 0; i < argc; i++) {
4710 if (!strcasecmp(argv[i], cause_str) || !strcasecmp(argv[i], cause_num)) {
4711 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "src/switch_channel.c", (const char
*)__func__, 4711, (const char*)(session)
, SWITCH_LOG_DEBUG,
4712 "Transfer on fail [%s]: Cause: %s\n", transfer_on_fail, cause_str);
4713 switch_ivr_session_transfer(session, tof_array[1], tof_array[2], tof_array[3]);
4714 }
4715 }
4716 }
4717 }
4718 }
4719 }
4720
4721
4722 if (!switch_channel_test_flag(channel, CF_TRANSFER) && !switch_channel_test_flag(channel, CF_CONFIRM_BLIND_TRANSFER) &&
4723 switch_channel_get_state(channel) != CS_ROUTING) {
4724 switch_channel_hangup(channel, cause)switch_channel_perform_hangup(channel, "src/switch_channel.c"
, (const char *)__func__, 4724, cause)
;
4725 }
4726}
4727
4728SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_channel_global_init(switch_memory_pool_t *pool)
4729{
4730 memset(&globals, 0, sizeof(globals));
4731 globals.pool = pool;
4732
4733 switch_mutex_init(&globals.device_mutex, SWITCH_MUTEX_NESTED0x1, pool);
4734 switch_core_hash_init(&globals.device_hash)switch_core_hash_init_case(&globals.device_hash, SWITCH_TRUE
)
;
4735}
4736
4737SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_channel_global_uninit(void)
4738{
4739 switch_core_hash_destroy(&globals.device_hash);
4740}
4741
4742
4743static void fetch_device_stats(switch_device_record_t *drec)
4744{
4745 switch_device_node_t *np;
4746
4747
4748 memset(&drec->stats, 0, sizeof(switch_device_stats_t));
4749
4750 switch_mutex_lock(drec->mutex);
4751 for(np = drec->uuid_list; np; np = np->next) {
4752 drec->stats.total++;
4753 if (np->direction == SWITCH_CALL_DIRECTION_INBOUND) {
4754 drec->stats.total_in++;
4755 } else {
4756 drec->stats.total_out++;
4757 }
4758
4759 if (!np->hup_profile) {
4760 drec->stats.offhook++;
4761 if (np->direction == SWITCH_CALL_DIRECTION_INBOUND) {
4762 drec->stats.offhook_in++;
4763 } else {
4764 drec->stats.offhook_out++;
4765 }
4766
4767 if (np->callstate == CCS_HELD) {
4768 drec->stats.held++;
4769 if (np->direction == SWITCH_CALL_DIRECTION_INBOUND) {
4770 drec->stats.held_in++;
4771 } else {
4772 drec->stats.held_out++;
4773 }
4774 } else if (np->callstate == CCS_UNHELD) {
4775 drec->stats.unheld++;
4776 if (np->direction == SWITCH_CALL_DIRECTION_INBOUND) {
4777 drec->stats.unheld_in++;
4778 } else {
4779 drec->stats.unheld_out++;
4780 }
4781 } else {
4782 if (np->callstate == CCS_EARLY) {
4783 drec->stats.early++;
4784 if (np->direction == SWITCH_CALL_DIRECTION_INBOUND) {
4785 drec->stats.early_in++;
4786 } else {
4787 drec->stats.early_out++;
4788 }
4789 } else if (np->callstate == CCS_RINGING) {
4790 drec->stats.ringing++;
4791 if (np->direction == SWITCH_CALL_DIRECTION_INBOUND) {
4792 drec->stats.ringing_in++;
4793 } else {
4794 drec->stats.ringing_out++;
4795 }
4796 } else if (np->callstate == CCS_RING_WAIT) {
4797 drec->stats.ring_wait++;
4798 } else if (np->callstate == CCS_HANGUP) {
4799 drec->stats.hup++;
4800 if (np->direction == SWITCH_CALL_DIRECTION_INBOUND) {
4801 drec->stats.hup_in++;
4802 } else {
4803 drec->stats.hup_out++;
4804 }
4805 } else if (np->callstate != CCS_DOWN) {
4806 drec->stats.active++;
4807 if (np->direction == SWITCH_CALL_DIRECTION_INBOUND) {
4808 drec->stats.active_in++;
4809 } else {
4810 drec->stats.active_out++;
4811 }
4812 }
4813 }
4814 } else {
4815 drec->stats.hup++;
4816 if (np->direction == SWITCH_CALL_DIRECTION_INBOUND) {
4817 drec->stats.hup_in++;
4818 } else {
4819 drec->stats.hup_out++;
4820 }
4821 }
4822 }
4823 switch_mutex_unlock(drec->mutex);
4824
4825}
4826
4827SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_channel_clear_device_record(switch_channel_t *channel)
4828{
4829 switch_memory_pool_t *pool;
4830 int sanity = 100;
4831 switch_device_node_t *np;
4832 switch_event_t *event;
4833
4834 if (!channel->device_node || !switch_channel_test_flag(channel, CF_FINAL_DEVICE_LEG)) {
4835 return;
4836 }
4837
4838 while(--sanity && channel->device_node->parent->refs) {
4839 switch_yield(100000)switch_sleep(100000);;
4840 }
4841
4842 switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel)SWITCH_CHANNEL_ID_SESSION, "src/switch_channel.c", (const char
*)__func__, 4842, (const char*)switch_channel_get_session(channel
)
, SWITCH_LOG_DEBUG, "Destroying device cdr %s on device [%s]\n",
4843 channel->device_node->parent->uuid,
4844 channel->device_node->parent->device_id);
4845
4846 if (switch_event_create(&event, SWITCH_EVENT_CALL_DETAIL)switch_event_create_subclass_detailed("src/switch_channel.c",
(const char * )(const char *)__func__, 4846, &event, SWITCH_EVENT_CALL_DETAIL
, ((void*)0))
== SWITCH_STATUS_SUCCESS) {
4847 int x = 0;
4848 char prefix[80] = "";
4849
4850 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Type", "device");
4851 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Device-ID", channel->device_node->parent->device_id);
4852
4853 switch_mutex_lock(channel->device_node->parent->mutex);
4854 for(np = channel->device_node->parent->uuid_list; np; np = np->next) {
4855 switch_snprintf(prefix, sizeof(prefix), "Call-%d", ++x);
4856 switch_caller_profile_event_set_data(np->hup_profile, prefix, event);
4857 }
4858 switch_mutex_unlock(channel->device_node->parent->mutex);
4859
4860 switch_event_fire(&event)switch_event_fire_detailed("src/switch_channel.c", (const char
* )(const char *)__func__, 4860, &event, ((void*)0))
;
4861 }
4862
4863 switch_mutex_lock(channel->device_node->parent->mutex);
4864 for(np = channel->device_node->parent->uuid_list; np; np = np->next) {
4865 if (np->xml_cdr) {
4866 switch_xml_free(np->xml_cdr);
4867 }
4868 if (np->event) {
4869 switch_event_destroy(&np->event);
4870 }
4871 }
4872 switch_mutex_unlock(channel->device_node->parent->mutex);
4873
4874 pool = channel->device_node->parent->pool;
4875
4876 switch_mutex_lock(globals.device_mutex);
4877 switch_core_destroy_memory_pool(&pool)switch_core_perform_destroy_memory_pool(&pool, "src/switch_channel.c"
, (const char *)__func__, 4877)
;
4878
4879 switch_mutex_unlock(globals.device_mutex);
4880
4881
4882}
4883
4884SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_channel_process_device_hangup(switch_channel_t *channel)
4885{
4886
4887 switch_channel_check_device_state(channel, channel->callstate);
4888 process_device_hup(channel);
4889
4890}
4891
4892static void process_device_hup(switch_channel_t *channel)
4893{
4894 switch_hold_record_t *hr, *newhr, *last = NULL((void*)0);
4895 switch_device_record_t *drec = NULL((void*)0);
4896 switch_device_node_t *node;
4897
4898 if (!channel->device_node) {
4899 return;
4900 }
4901
4902 switch_mutex_lock(globals.device_mutex);
4903 node = channel->device_node;
4904 drec = channel->device_node->parent;
4905
4906 node->hup_profile = switch_caller_profile_dup(drec->pool, channel->caller_profile);
4907 fetch_device_stats(drec);
4908
4909 switch_ivr_generate_xml_cdr(channel->session, &node->xml_cdr);
4910 if (switch_event_create(&node->event, SWITCH_EVENT_CALL_DETAIL)switch_event_create_subclass_detailed("src/switch_channel.c",
(const char * )(const char *)__func__, 4910, &node->event
, SWITCH_EVENT_CALL_DETAIL, ((void*)0))
== SWITCH_STATUS_SUCCESS) {
4911 switch_channel_event_set_extended_data(channel, node->event);
4912 }
4913
4914 for (hr = channel->hold_record; hr; hr = hr->next) {
4915 newhr = switch_core_alloc(drec->pool, sizeof(*newhr))switch_core_perform_alloc(drec->pool, sizeof(*newhr), "src/switch_channel.c"
, (const char *)__func__, 4915)
;
4916 newhr->on = hr->on;
4917 newhr->off = hr->off;
4918
4919 if (hr->uuid) {
4920 newhr->uuid = switch_core_strdup(drec->pool, hr->uuid)switch_core_perform_strdup(drec->pool, hr->uuid, "src/switch_channel.c"
, (const char *)__func__, 4920)
;
4921 }
4922
4923 if (!node->hold_record) {
4924 node->hold_record = newhr;
4925 } else if (last) {
4926 last->next = newhr;
4927 }
4928
4929 last = newhr;
4930 }
4931
4932 if (!drec->stats.offhook) { /* this is final call */
4933
4934 switch_core_hash_delete(globals.device_hash, drec->device_id);
4935 switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel)SWITCH_CHANNEL_ID_SESSION, "src/switch_channel.c", (const char
*)__func__, 4935, (const char*)switch_channel_get_session(channel
)
, SWITCH_LOG_DEBUG, "Processing last call from device [%s]\n",
4936 drec->device_id);
4937 switch_channel_set_flag(channel, CF_FINAL_DEVICE_LEG)switch_channel_set_flag_value(channel, CF_FINAL_DEVICE_LEG, 1
)
;
4938 } else {
4939 channel->device_node = NULL((void*)0);
4940 }
4941
4942 drec->refs--;
4943
4944 switch_mutex_unlock(globals.device_mutex);
4945
4946}
4947
4948static void switch_channel_check_device_state(switch_channel_t *channel, switch_channel_callstate_t callstate)
4949{
4950 switch_device_record_t *drec = NULL((void*)0);
4951 switch_device_state_binding_t *ptr = NULL((void*)0);
4952 switch_event_t *event = NULL((void*)0);
4953
4954 if (!channel->device_node) {
4955 return;
4956 }
4957
4958 drec = channel->device_node->parent;
4959
4960 switch_mutex_lock(globals.device_mutex);
4961 switch_mutex_lock(drec->mutex);
4962
4963 fetch_device_stats(drec);
4964
4965 if (drec->state != SDS_HANGUP) {
4966 if (drec->stats.offhook == 0 || drec->stats.hup == drec->stats.total) {
4967 drec->state = SDS_HANGUP;
4968 } else {
4969 if (drec->stats.active == 0) {
4970 if ((drec->stats.ringing_out + drec->stats.early_out) > 0 || drec->stats.ring_wait > 0) {
4971 drec->state = SDS_RINGING;
4972 } else {
4973 if (drec->stats.held > 0) {
4974 drec->state = SDS_HELD;
4975 } else if (drec->stats.unheld > 0) {
4976 drec->state = SDS_UNHELD;
4977 } else {
4978 drec->state = SDS_DOWN;
4979 }
4980 }
4981 } else if (drec->stats.active == 1) {
4982 drec->state = SDS_ACTIVE;
4983 } else {
4984 drec->state = SDS_ACTIVE_MULTI;
4985 }
4986 }
4987 }
4988
4989 if ((drec->state == SDS_DOWN && drec->last_state == SDS_DOWN) || (drec->state == SDS_HANGUP && drec->last_state == SDS_HANGUP)) {
4990 switch_mutex_unlock(drec->mutex);
4991 switch_mutex_unlock(globals.device_mutex);
4992 return;
4993 }
4994
4995 if (!drec->call_start) {
4996 drec->call_start = switch_micro_time_now();
4997 }
4998
4999 switch(drec->state) {
5000 case SDS_RINGING:
5001 if (!drec->ring_start) {
5002 drec->ring_start = switch_micro_time_now();
5003 drec->ring_stop = 0;
5004 }
5005 break;
5006 case SDS_ACTIVE:
5007 case SDS_ACTIVE_MULTI:
5008 if (!drec->active_start) {
5009 drec->active_start = switch_micro_time_now();
5010 drec->active_stop = 0;
5011 }
5012 break;
5013 case SDS_HELD:
5014 if (!drec->hold_start) {
5015 drec->hold_start = switch_micro_time_now();
5016 drec->hold_stop = 0;
5017 }
5018 break;
5019 default:
5020 break;
5021 }
5022
5023 if (callstate != CCS_UNHELD && drec->active_start && drec->state != SDS_ACTIVE && drec->state != SDS_ACTIVE_MULTI) {
5024 drec->active_stop = switch_micro_time_now();
5025 }
5026
5027 if (drec->ring_start && !drec->ring_stop && drec->state != SDS_RINGING) {
5028 drec->ring_stop = switch_micro_time_now();
5029 }
5030
5031 if (drec->hold_start && !drec->hold_stop && drec->state != SDS_HELD) {
5032 drec->hold_stop = switch_micro_time_now();
5033 }
5034
5035
5036 if (switch_event_create(&event, SWITCH_EVENT_DEVICE_STATE)switch_event_create_subclass_detailed("src/switch_channel.c",
(const char * )(const char *)__func__, 5036, &event, SWITCH_EVENT_DEVICE_STATE
, ((void*)0))
== SWITCH_STATUS_SUCCESS) {
5037 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Device-ID", drec->device_id);
5038 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Last-Device-State", switch_channel_device_state2str(drec->last_state));
5039 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Device-State", switch_channel_device_state2str(drec->state));
5040 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Device-Call-State", switch_channel_callstate2str(callstate));
5041 switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Device-Total-Legs", "%u", drec->stats.total);
5042 switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Device-Legs-Offhook", "%u", drec->stats.offhook);
5043 switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Device-Legs-Ringing", "%u", drec->stats.ringing);
5044 switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Device-Legs-Early", "%u", drec->stats.early);
5045 switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Device-Legs-Active", "%u", drec->stats.active);
5046 switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Device-Legs-Held", "%u", drec->stats.held);
5047 switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Device-Legs-UnHeld", "%u", drec->stats.unheld);
5048 switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Device-Legs-Hup", "%u", drec->stats.hup);
5049 switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Device-Talk-Time-Start-Uepoch", "%"SWITCH_TIME_T_FMT"ld", drec->active_start);
5050 if (drec->active_stop) {
5051 switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Device-Talk-Time-Stop-Uepoch", "%"SWITCH_TIME_T_FMT"ld", drec->active_stop);
5052 switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Device-Talk-Time-Milliseconds", "%u", (uint32_t)(drec->active_stop - drec->active_start) / 1000);
5053 }
5054 }
5055
5056 switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel)SWITCH_CHANNEL_ID_SESSION, "src/switch_channel.c", (const char
*)__func__, 5056, (const char*)switch_channel_get_session(channel
)
, SWITCH_LOG_DEBUG1,
5057 "%s device: %s\nState: %s Dev State: %s/%s Total:%u Offhook:%u "
5058 "Ringing:%u Early:%u Active:%u Held:%u Unheld:%u Hungup:%u Dur: %u Ringtime: %u Holdtime: %u %s\n",
5059 switch_channel_get_name(channel),
5060 drec->device_id,
5061 switch_channel_callstate2str(callstate),
5062 switch_channel_device_state2str(drec->last_state),
5063 switch_channel_device_state2str(drec->state),
5064 drec->stats.total,
5065 drec->stats.offhook,
5066 drec->stats.ringing,
5067 drec->stats.early,
5068 drec->stats.active,
5069 drec->stats.held,
5070 drec->stats.unheld,
5071 drec->stats.hup,
5072 drec->active_stop ? (uint32_t)(drec->active_stop - drec->active_start) / 1000 : 0,
5073 drec->ring_stop ? (uint32_t)(drec->ring_stop - drec->ring_start) / 1000 : 0,
5074 drec->hold_stop ? (uint32_t)(drec->hold_stop - drec->hold_start) / 1000 : 0,
5075 switch_channel_test_flag(channel, CF_FINAL_DEVICE_LEG) ? "FINAL LEG" : "");
5076
5077 for (ptr = globals.device_bindings; ptr; ptr = ptr->next) {
5078 ptr->function(channel->session, callstate, drec);
5079 }
5080
5081 drec->last_stats = drec->stats;
5082
5083 if (drec->active_stop) {
5084 drec->active_start = drec->active_stop = 0;
5085 if (drec->state == SDS_ACTIVE || drec->state == SDS_ACTIVE_MULTI) {
5086 drec->active_start = switch_micro_time_now();
5087 }
5088 }
5089
5090 if (drec->hold_stop) {
5091 drec->hold_start = drec->hold_stop = 0;
5092 if (drec->state == SDS_HELD) {
5093 drec->hold_start = switch_micro_time_now();
5094 }
5095 }
5096
5097 if (drec->ring_stop) {
5098 drec->ring_start = drec->ring_stop = 0;
5099 if (drec->state == SDS_RINGING) {
5100 drec->ring_start = switch_micro_time_now();
5101 }
5102 }
5103
5104 drec->last_call_time = switch_micro_time_now();
5105
5106 drec->last_state = drec->state;
5107
5108 switch_mutex_unlock(drec->mutex);
5109 switch_mutex_unlock(globals.device_mutex);
5110
5111
5112 if (event) {
5113 switch_event_fire(&event)switch_event_fire_detailed("src/switch_channel.c", (const char
* )(const char *)__func__, 5113, &event, ((void*)0))
;
5114 }
5115
5116}
5117
5118/* assumed to be called under a lock */
5119static void add_uuid(switch_device_record_t *drec, switch_channel_t *channel)
5120{
5121 switch_device_node_t *node;
5122
5123 switch_assert(drec)((drec) ? (void) (0) : __assert_fail ("drec", "src/switch_channel.c"
, 5123, __PRETTY_FUNCTION__))
;
5124
5125 switch_channel_set_flag(channel, CF_DEVICE_LEG)switch_channel_set_flag_value(channel, CF_DEVICE_LEG, 1);
5126 node = switch_core_alloc(drec->pool, sizeof(*node))switch_core_perform_alloc(drec->pool, sizeof(*node), "src/switch_channel.c"
, (const char *)__func__, 5126)
;
5127
5128 node->uuid = switch_core_strdup(drec->pool, switch_core_session_get_uuid(channel->session))switch_core_perform_strdup(drec->pool, switch_core_session_get_uuid
(channel->session), "src/switch_channel.c", (const char *)
__func__, 5128)
;
5129 node->parent = drec;
5130 node->callstate = channel->callstate;
5131 node->direction = channel->logical_direction == SWITCH_CALL_DIRECTION_INBOUND ? SWITCH_CALL_DIRECTION_OUTBOUND : SWITCH_CALL_DIRECTION_INBOUND;
5132
5133 channel->device_node = node;
5134
5135 if (!drec->uuid_list) {
5136 drec->uuid_list = node;
5137 drec->uuid = node->uuid;
5138 } else {
5139 drec->uuid_tail->next = node;
5140 }
5141
5142 drec->uuid_tail = node;
5143 drec->refs++;
5144}
5145
5146static switch_status_t create_device_record(switch_device_record_t **drecp, const char *device_id)
5147{
5148 switch_device_record_t *drec;
5149 switch_memory_pool_t *pool;
5150
5151 switch_assert(drecp)((drecp) ? (void) (0) : __assert_fail ("drecp", "src/switch_channel.c"
, 5151, __PRETTY_FUNCTION__))
;
5152
5153 switch_core_new_memory_pool(&pool)switch_core_perform_new_memory_pool(&pool, "src/switch_channel.c"
, (const char *)__func__, 5153)
;
5154 drec = switch_core_alloc(pool, sizeof(*drec))switch_core_perform_alloc(pool, sizeof(*drec), "src/switch_channel.c"
, (const char *)__func__, 5154)
;
5155 drec->pool = pool;
5156 drec->device_id = switch_core_strdup(drec->pool, device_id)switch_core_perform_strdup(drec->pool, device_id, "src/switch_channel.c"
, (const char *)__func__, 5156)
;
5157 switch_mutex_init(&drec->mutex, SWITCH_MUTEX_NESTED0x1, drec->pool);
5158
5159 *drecp = drec;
5160
5161 return SWITCH_STATUS_SUCCESS;
5162}
5163
5164
5165SWITCH_DECLARE(const char *)__attribute__((visibility("default"))) const char * switch_channel_set_device_id(switch_channel_t *channel, const char *device_id)
5166{
5167 switch_device_record_t *drec;
5168
5169 if (channel->device_node) {
5170 return NULL((void*)0);
5171 }
5172
5173 channel->device_id = switch_core_session_strdup(channel->session, device_id)switch_core_perform_session_strdup(channel->session, device_id
, "src/switch_channel.c", (const char *)__func__, 5173)
;
5174
5175 switch_mutex_lock(globals.device_mutex);
5176
5177 if (!(drec = switch_core_hash_find(globals.device_hash, channel->device_id))) {
5178 create_device_record(&drec, channel->device_id);
5179 switch_core_hash_insert(globals.device_hash, drec->device_id, drec)switch_core_hash_insert_destructor(globals.device_hash, drec->
device_id, drec, ((void*)0))
;
5180 }
5181
5182 add_uuid(drec, channel);
5183
5184 switch_mutex_unlock(globals.device_mutex);
5185
5186 switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel)SWITCH_CHANNEL_ID_SESSION, "src/switch_channel.c", (const char
*)__func__, 5186, (const char*)switch_channel_get_session(channel
)
, SWITCH_LOG_DEBUG, "Setting DEVICE ID to [%s]\n", device_id);
5187
5188 switch_channel_check_device_state(channel, channel->callstate);
5189
5190 return device_id;
5191}
5192
5193SWITCH_DECLARE(switch_device_record_t *)__attribute__((visibility("default"))) switch_device_record_t
*
switch_channel_get_device_record(switch_channel_t *channel)
5194{
5195 if (channel->device_node) {
5196 switch_mutex_lock(channel->device_node->parent->mutex);
5197 return channel->device_node->parent;
5198 }
5199
5200 return NULL((void*)0);
5201}
5202
5203SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_channel_release_device_record(switch_device_record_t **drecp)
5204{
5205 if (drecp && *drecp) {
5206 switch_mutex_unlock((*drecp)->mutex);
5207 *drecp = NULL((void*)0);
5208 }
5209}
5210
5211SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_channel_bind_device_state_handler(switch_device_state_function_t function, void *user_data)
5212{
5213 switch_device_state_binding_t *binding = NULL((void*)0), *ptr = NULL((void*)0);
5214 assert(function != NULL)((function != ((void*)0)) ? (void) (0) : __assert_fail ("function != ((void*)0)"
, "src/switch_channel.c", 5214, __PRETTY_FUNCTION__))
;
5215
5216 if (!(binding = (switch_device_state_binding_t *) switch_core_alloc(globals.pool, sizeof(*binding))switch_core_perform_alloc(globals.pool, sizeof(*binding), "src/switch_channel.c"
, (const char *)__func__, 5216)
)) {
5217 return SWITCH_STATUS_MEMERR;
5218 }
5219
5220 binding->function = function;
5221 binding->user_data = user_data;
5222
5223 switch_mutex_lock(globals.device_mutex);
5224 for (ptr = globals.device_bindings; ptr && ptr->next; ptr = ptr->next);
5225
5226 if (ptr) {
5227 ptr->next = binding;
5228 } else {
5229 globals.device_bindings = binding;
5230 }
5231
5232 switch_mutex_unlock(globals.device_mutex);
5233
5234 return SWITCH_STATUS_SUCCESS;
5235}
5236
5237SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_channel_unbind_device_state_handler(switch_device_state_function_t function)
5238{
5239 switch_device_state_binding_t *ptr, *last = NULL((void*)0);
5240 switch_status_t status = SWITCH_STATUS_FALSE;
5241
5242 switch_mutex_lock(globals.device_mutex);
5243 for (ptr = globals.device_bindings; ptr; ptr = ptr->next) {
5244 if (ptr->function == function) {
5245 status = SWITCH_STATUS_SUCCESS;
5246
5247 if (last) {
5248 last->next = ptr->next;
5249 } else {
5250 globals.device_bindings = ptr->next;
5251 last = NULL((void*)0);
5252 continue;
5253 }
5254 }
5255 last = ptr;
5256 }
5257 switch_mutex_unlock(globals.device_mutex);
5258
5259 return status;
5260}
5261
5262SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_channel_pass_sdp(switch_channel_t *from_channel, switch_channel_t *to_channel, const char *sdp)
5263{
5264 switch_status_t status = SWITCH_STATUS_FALSE;
5265 char *use_sdp = (char *) sdp;
5266 char *patched_sdp = NULL((void*)0);
5267
5268 if (!switch_channel_get_variable(to_channel, SWITCH_B_SDP_VARIABLE)switch_channel_get_variable_dup(to_channel, "switch_m_sdp", SWITCH_TRUE
, -1)
) {
5269 const char *var;
5270
5271 if ((var = switch_channel_get_variable(from_channel, "bypass_media_sdp_filter")switch_channel_get_variable_dup(from_channel, "bypass_media_sdp_filter"
, SWITCH_TRUE, -1)
)) {
5272 if ((patched_sdp = switch_core_media_process_sdp_filter(use_sdp, var, from_channel->session))) {
5273 use_sdp = patched_sdp;
5274 }
5275 }
5276
5277 switch_channel_set_variable(to_channel, SWITCH_B_SDP_VARIABLE, use_sdp)switch_channel_set_variable_var_check(to_channel, "switch_m_sdp"
, use_sdp, SWITCH_TRUE)
;
5278 }
5279
5280 switch_safe_free(patched_sdp)if (patched_sdp) {free(patched_sdp);patched_sdp=((void*)0);};
5281
5282 return status;
5283}
5284
5285/* For Emacs:
5286 * Local Variables:
5287 * mode:c
5288 * indent-tabs-mode:t
5289 * tab-width:4
5290 * c-basic-offset:4
5291 * End:
5292 * For VIM:
5293 * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
5294 */