Bug Summary

File:switch_channel.c
Warning:line 1535, column 12
Potential leak of memory pointed to by 'r'

Annotated Source Code

Press '?' to see keyboard shortcuts

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