| File: | src/switch_ivr.c |
| Location: | line 2169, column 16 |
| Description: | Potential leak of memory pointed to by '__retval' |
| 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 | * Paul D. Tinsley <pdt at jackhammer.org> | |||||||||
| 28 | * Neal Horman <neal at wanlink dot com> | |||||||||
| 29 | * Matt Klein <mklein@nmedia.net> | |||||||||
| 30 | * Michael Jerris <mike@jerris.com> | |||||||||
| 31 | * Ken Rice <krice at suspicious dot org> | |||||||||
| 32 | * Marc Olivier Chouinard <mochouinard@moctel.com> | |||||||||
| 33 | * | |||||||||
| 34 | * switch_ivr.c -- IVR Library | |||||||||
| 35 | * | |||||||||
| 36 | */ | |||||||||
| 37 | ||||||||||
| 38 | #include <switch.h> | |||||||||
| 39 | #include <switch_ivr.h> | |||||||||
| 40 | ||||||||||
| 41 | SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_ivr_sound_test(switch_core_session_t *session) | |||||||||
| 42 | { | |||||||||
| 43 | ||||||||||
| 44 | switch_codec_implementation_t imp = { 0 }; | |||||||||
| 45 | switch_codec_t codec = { 0 }; | |||||||||
| 46 | int16_t peak = 0; | |||||||||
| 47 | int16_t *data; | |||||||||
| 48 | switch_frame_t *read_frame = NULL((void*)0); | |||||||||
| 49 | uint32_t i; | |||||||||
| 50 | switch_channel_t *channel = switch_core_session_get_channel(session); | |||||||||
| 51 | switch_status_t status = SWITCH_STATUS_SUCCESS; | |||||||||
| 52 | int64_t global_total = 0, global_sum = 0, period_sum = 0; | |||||||||
| 53 | int period_total = 0; | |||||||||
| 54 | int period_avg = 0, global_avg = 0; | |||||||||
| 55 | int avg = 0; | |||||||||
| 56 | int period_len; | |||||||||
| 57 | ||||||||||
| 58 | switch_core_session_get_read_impl(session, &imp); | |||||||||
| 59 | ||||||||||
| 60 | period_len = imp.actual_samples_per_second / imp.samples_per_packet; | |||||||||
| 61 | ||||||||||
| 62 | if (switch_core_codec_init(&codec,switch_core_codec_init_with_bitrate(&codec, "L16", ((void *)0), imp.samples_per_second, imp.microseconds_per_packet / 1000 , imp.number_of_channels, 0, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE , ((void*)0), switch_core_session_get_pool(session)) | |||||||||
| 63 | "L16",switch_core_codec_init_with_bitrate(&codec, "L16", ((void *)0), imp.samples_per_second, imp.microseconds_per_packet / 1000 , imp.number_of_channels, 0, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE , ((void*)0), switch_core_session_get_pool(session)) | |||||||||
| 64 | NULL,switch_core_codec_init_with_bitrate(&codec, "L16", ((void *)0), imp.samples_per_second, imp.microseconds_per_packet / 1000 , imp.number_of_channels, 0, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE , ((void*)0), switch_core_session_get_pool(session)) | |||||||||
| 65 | imp.samples_per_second,switch_core_codec_init_with_bitrate(&codec, "L16", ((void *)0), imp.samples_per_second, imp.microseconds_per_packet / 1000 , imp.number_of_channels, 0, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE , ((void*)0), switch_core_session_get_pool(session)) | |||||||||
| 66 | imp.microseconds_per_packet / 1000,switch_core_codec_init_with_bitrate(&codec, "L16", ((void *)0), imp.samples_per_second, imp.microseconds_per_packet / 1000 , imp.number_of_channels, 0, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE , ((void*)0), switch_core_session_get_pool(session)) | |||||||||
| 67 | imp.number_of_channels,switch_core_codec_init_with_bitrate(&codec, "L16", ((void *)0), imp.samples_per_second, imp.microseconds_per_packet / 1000 , imp.number_of_channels, 0, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE , ((void*)0), switch_core_session_get_pool(session)) | |||||||||
| 68 | SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE, NULL,switch_core_codec_init_with_bitrate(&codec, "L16", ((void *)0), imp.samples_per_second, imp.microseconds_per_packet / 1000 , imp.number_of_channels, 0, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE , ((void*)0), switch_core_session_get_pool(session)) | |||||||||
| 69 | switch_core_session_get_pool(session))switch_core_codec_init_with_bitrate(&codec, "L16", ((void *)0), imp.samples_per_second, imp.microseconds_per_packet / 1000 , imp.number_of_channels, 0, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE , ((void*)0), switch_core_session_get_pool(session)) != SWITCH_STATUS_SUCCESS) { | |||||||||
| 70 | switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "src/switch_ivr.c", (const char *) __func__, 70, (const char*)(session), SWITCH_LOG_ERROR, "Codec Error L16@%uhz %u channels %dms\n", | |||||||||
| 71 | imp.samples_per_second, imp.number_of_channels, imp.microseconds_per_packet / 1000); | |||||||||
| 72 | return SWITCH_STATUS_FALSE; | |||||||||
| 73 | } | |||||||||
| 74 | ||||||||||
| 75 | while (switch_channel_ready(channel)switch_channel_test_ready(channel, SWITCH_TRUE, SWITCH_FALSE)) { | |||||||||
| 76 | status = switch_core_session_read_frame(session, &read_frame, SWITCH_IO_FLAG_NONE, 0); | |||||||||
| 77 | ||||||||||
| 78 | if (!SWITCH_READ_ACCEPTABLE(status)(status == SWITCH_STATUS_SUCCESS || status == SWITCH_STATUS_BREAK || status == SWITCH_STATUS_INUSE)) { | |||||||||
| 79 | break; | |||||||||
| 80 | } | |||||||||
| 81 | ||||||||||
| 82 | if (switch_test_flag(read_frame, SFF_CNG)((read_frame)->flags & SFF_CNG) || !read_frame->samples) { | |||||||||
| 83 | continue; | |||||||||
| 84 | } | |||||||||
| 85 | ||||||||||
| 86 | ||||||||||
| 87 | data = (int16_t *) read_frame->data; | |||||||||
| 88 | peak = 0; | |||||||||
| 89 | avg = 0; | |||||||||
| 90 | for (i = 0; i < read_frame->samples; i++) { | |||||||||
| 91 | const int16_t s = (int16_t) abs(data[i]); | |||||||||
| 92 | if (s > peak) { | |||||||||
| 93 | peak = s; | |||||||||
| 94 | } | |||||||||
| 95 | avg += s; | |||||||||
| 96 | } | |||||||||
| 97 | ||||||||||
| 98 | avg /= read_frame->samples; | |||||||||
| 99 | ||||||||||
| 100 | period_sum += peak; | |||||||||
| 101 | global_sum += peak; | |||||||||
| 102 | ||||||||||
| 103 | global_total++; | |||||||||
| 104 | period_total++; | |||||||||
| 105 | ||||||||||
| 106 | period_avg = (int) (period_sum / period_total); | |||||||||
| 107 | ||||||||||
| 108 | switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "src/switch_ivr.c", (const char *) __func__, 108, (const char*)(session), SWITCH_LOG_CONSOLE, | |||||||||
| 109 | "\npacket_avg=%d packet_peak=%d period_avg=%d global_avg=%d\n\n", avg, peak, period_avg, global_avg); | |||||||||
| 110 | ||||||||||
| 111 | if (period_total >= period_len) { | |||||||||
| 112 | global_avg = (int) (global_sum / global_total); | |||||||||
| 113 | period_total = 0; | |||||||||
| 114 | period_sum = 0; | |||||||||
| 115 | } | |||||||||
| 116 | ||||||||||
| 117 | } | |||||||||
| 118 | ||||||||||
| 119 | ||||||||||
| 120 | switch_core_codec_destroy(&codec); | |||||||||
| 121 | ||||||||||
| 122 | return SWITCH_STATUS_SUCCESS; | |||||||||
| 123 | ||||||||||
| 124 | } | |||||||||
| 125 | ||||||||||
| 126 | SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_ivr_sleep(switch_core_session_t *session, uint32_t ms, switch_bool_t sync, switch_input_args_t *args) | |||||||||
| 127 | { | |||||||||
| 128 | switch_channel_t *channel = switch_core_session_get_channel(session); | |||||||||
| 129 | switch_status_t status = SWITCH_STATUS_SUCCESS; | |||||||||
| 130 | switch_time_t start = switch_micro_time_now(), now, done = switch_micro_time_now() + (ms * 1000); | |||||||||
| 131 | switch_frame_t *read_frame, cng_frame = { 0 }; | |||||||||
| 132 | int32_t left; | |||||||||
| 133 | uint32_t elapsed; | |||||||||
| 134 | char data[2] = ""; | |||||||||
| 135 | ||||||||||
| 136 | switch_frame_t write_frame = { 0 }; | |||||||||
| 137 | unsigned char *abuf = NULL((void*)0); | |||||||||
| 138 | switch_codec_implementation_t imp = { 0 }; | |||||||||
| 139 | switch_codec_t codec = { 0 }; | |||||||||
| 140 | int sval = 0; | |||||||||
| 141 | const char *var; | |||||||||
| 142 | ||||||||||
| 143 | arg_recursion_check_start(args)if (args) { if (args->loops >= 25) { switch_log_printf( SWITCH_CHANNEL_ID_LOG, "src/switch_ivr.c", (const char *)__func__ , 143, ((void*)0), SWITCH_LOG_ERROR, "RECURSION ERROR! It's not the best idea to call things that collect input recursively from an input callback.\n" ); return SWITCH_STATUS_GENERR; } else {args->loops++;} }; | |||||||||
| 144 | ||||||||||
| 145 | switch_core_session_get_read_impl(session, &imp); | |||||||||
| 146 | ||||||||||
| 147 | /* | |||||||||
| 148 | if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_INBOUND && !switch_channel_test_flag(channel, CF_PROXY_MODE) && | |||||||||
| 149 | !switch_channel_media_ready(channel) && !switch_channel_test_flag(channel, CF_SERVICE)) { | |||||||||
| 150 | if ((status = switch_channel_pre_answer(channel)) != SWITCH_STATUS_SUCCESS) { | |||||||||
| 151 | switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Cannot establish media.\n"); | |||||||||
| 152 | return SWITCH_STATUS_FALSE; | |||||||||
| 153 | } | |||||||||
| 154 | } | |||||||||
| 155 | */ | |||||||||
| 156 | ||||||||||
| 157 | if (!switch_channel_media_ready(channel)switch_channel_test_ready(channel, SWITCH_TRUE, SWITCH_TRUE)) { | |||||||||
| 158 | ||||||||||
| 159 | for (elapsed=0; switch_channel_up(channel)(switch_channel_check_signal(channel, SWITCH_TRUE) || switch_channel_get_state (channel) < CS_HANGUP) && elapsed<(ms/20); elapsed++) { | |||||||||
| 160 | if (switch_channel_test_flag(channel, CF_BREAK)) { | |||||||||
| 161 | switch_channel_clear_flag(channel, CF_BREAK); | |||||||||
| 162 | switch_goto_status(SWITCH_STATUS_BREAK, end)status = SWITCH_STATUS_BREAK; goto end; | |||||||||
| 163 | } | |||||||||
| 164 | ||||||||||
| 165 | switch_yield(20 * 1000)switch_sleep(20 * 1000);; | |||||||||
| 166 | } | |||||||||
| 167 | switch_goto_status(SWITCH_STATUS_SUCCESS, end)status = SWITCH_STATUS_SUCCESS; goto end; | |||||||||
| 168 | } | |||||||||
| 169 | ||||||||||
| 170 | if ((var = switch_channel_get_variable(channel, SWITCH_SEND_SILENCE_WHEN_IDLE_VARIABLE)switch_channel_get_variable_dup(channel, "send_silence_when_idle" , SWITCH_TRUE, -1)) | |||||||||
| 171 | && (sval = atoi(var))) { | |||||||||
| 172 | SWITCH_IVR_VERIFY_SILENCE_DIVISOR(sval){ if ((sval) <= 0 && (sval) != -1) { sval = 400; } }; | |||||||||
| 173 | } | |||||||||
| 174 | ||||||||||
| 175 | if (ms > 10 && sval) { | |||||||||
| 176 | ||||||||||
| 177 | if (switch_core_codec_init(&codec,switch_core_codec_init_with_bitrate(&codec, "L16", ((void *)0), imp.actual_samples_per_second, imp.microseconds_per_packet / 1000, imp.number_of_channels, 0, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE, ((void*)0), switch_core_session_get_pool (session)) | |||||||||
| 178 | "L16",switch_core_codec_init_with_bitrate(&codec, "L16", ((void *)0), imp.actual_samples_per_second, imp.microseconds_per_packet / 1000, imp.number_of_channels, 0, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE, ((void*)0), switch_core_session_get_pool (session)) | |||||||||
| 179 | NULL,switch_core_codec_init_with_bitrate(&codec, "L16", ((void *)0), imp.actual_samples_per_second, imp.microseconds_per_packet / 1000, imp.number_of_channels, 0, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE, ((void*)0), switch_core_session_get_pool (session)) | |||||||||
| 180 | imp.actual_samples_per_second,switch_core_codec_init_with_bitrate(&codec, "L16", ((void *)0), imp.actual_samples_per_second, imp.microseconds_per_packet / 1000, imp.number_of_channels, 0, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE, ((void*)0), switch_core_session_get_pool (session)) | |||||||||
| 181 | imp.microseconds_per_packet / 1000,switch_core_codec_init_with_bitrate(&codec, "L16", ((void *)0), imp.actual_samples_per_second, imp.microseconds_per_packet / 1000, imp.number_of_channels, 0, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE, ((void*)0), switch_core_session_get_pool (session)) | |||||||||
| 182 | imp.number_of_channels,switch_core_codec_init_with_bitrate(&codec, "L16", ((void *)0), imp.actual_samples_per_second, imp.microseconds_per_packet / 1000, imp.number_of_channels, 0, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE, ((void*)0), switch_core_session_get_pool (session)) | |||||||||
| 183 | SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE, NULL,switch_core_codec_init_with_bitrate(&codec, "L16", ((void *)0), imp.actual_samples_per_second, imp.microseconds_per_packet / 1000, imp.number_of_channels, 0, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE, ((void*)0), switch_core_session_get_pool (session)) | |||||||||
| 184 | switch_core_session_get_pool(session))switch_core_codec_init_with_bitrate(&codec, "L16", ((void *)0), imp.actual_samples_per_second, imp.microseconds_per_packet / 1000, imp.number_of_channels, 0, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE, ((void*)0), switch_core_session_get_pool (session)) != SWITCH_STATUS_SUCCESS) { | |||||||||
| 185 | switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "src/switch_ivr.c", (const char *) __func__, 185, (const char*)(session), SWITCH_LOG_ERROR, "Codec Error L16@%uhz %u channels %dms\n", | |||||||||
| 186 | imp.actual_samples_per_second, imp.number_of_channels, imp.microseconds_per_packet / 1000); | |||||||||
| 187 | switch_goto_status(SWITCH_STATUS_FALSE, end)status = SWITCH_STATUS_FALSE; goto end; | |||||||||
| 188 | } | |||||||||
| 189 | ||||||||||
| 190 | ||||||||||
| 191 | switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "src/switch_ivr.c", (const char *) __func__, 191, (const char*)(session), SWITCH_LOG_DEBUG, "Codec Activated L16@%uhz %u channels %dms\n", | |||||||||
| 192 | imp.actual_samples_per_second, imp.number_of_channels, imp.microseconds_per_packet / 1000); | |||||||||
| 193 | ||||||||||
| 194 | write_frame.codec = &codec; | |||||||||
| 195 | switch_zmalloc(abuf, SWITCH_RECOMMENDED_BUFFER_SIZE)(void)((((abuf = calloc(1, (8192)))) ? (void) (0) : __assert_fail ("(abuf = calloc(1, (8192)))", "src/switch_ivr.c", 195, __PRETTY_FUNCTION__ )),abuf); | |||||||||
| 196 | write_frame.data = abuf; | |||||||||
| 197 | write_frame.buflen = SWITCH_RECOMMENDED_BUFFER_SIZE8192; | |||||||||
| 198 | write_frame.datalen = imp.decoded_bytes_per_packet; | |||||||||
| 199 | write_frame.samples = write_frame.datalen / sizeof(int16_t); | |||||||||
| 200 | ||||||||||
| 201 | } | |||||||||
| 202 | ||||||||||
| 203 | if (!write_frame.datalen) { | |||||||||
| 204 | sval = 0; | |||||||||
| 205 | } | |||||||||
| 206 | ||||||||||
| 207 | cng_frame.data = data; | |||||||||
| 208 | cng_frame.datalen = 2; | |||||||||
| 209 | cng_frame.buflen = 2; | |||||||||
| 210 | switch_set_flag((&cng_frame), SFF_CNG)((&cng_frame))->flags |= (SFF_CNG); | |||||||||
| 211 | ||||||||||
| 212 | if (sync) { | |||||||||
| 213 | switch_channel_audio_sync(channel)switch_channel_perform_audio_sync(channel, "src/switch_ivr.c" , (const char *)__func__, 213); | |||||||||
| 214 | } | |||||||||
| 215 | ||||||||||
| 216 | if (!ms) { | |||||||||
| 217 | switch_goto_status(SWITCH_STATUS_SUCCESS, end)status = SWITCH_STATUS_SUCCESS; goto end; | |||||||||
| 218 | } | |||||||||
| 219 | ||||||||||
| 220 | for (;;) { | |||||||||
| 221 | now = switch_micro_time_now(); | |||||||||
| 222 | elapsed = (int32_t) ((now - start) / 1000); | |||||||||
| 223 | left = ms - elapsed; | |||||||||
| 224 | ||||||||||
| 225 | if (!switch_channel_ready(channel)switch_channel_test_ready(channel, SWITCH_TRUE, SWITCH_FALSE)) { | |||||||||
| 226 | status = SWITCH_STATUS_FALSE; | |||||||||
| 227 | break; | |||||||||
| 228 | } | |||||||||
| 229 | ||||||||||
| 230 | if (switch_channel_test_flag(channel, CF_BREAK)) { | |||||||||
| 231 | switch_channel_clear_flag(channel, CF_BREAK); | |||||||||
| 232 | status = SWITCH_STATUS_BREAK; | |||||||||
| 233 | break; | |||||||||
| 234 | } | |||||||||
| 235 | ||||||||||
| 236 | if (now > done || left <= 0) { | |||||||||
| 237 | break; | |||||||||
| 238 | } | |||||||||
| 239 | ||||||||||
| 240 | ||||||||||
| 241 | switch_ivr_parse_all_events(session); | |||||||||
| 242 | ||||||||||
| 243 | ||||||||||
| 244 | if (args) { | |||||||||
| 245 | switch_dtmf_t dtmf = {0}; | |||||||||
| 246 | ||||||||||
| 247 | /* | |||||||||
| 248 | dtmf handler function you can hook up to be executed when a digit is dialed during playback | |||||||||
| 249 | if you return anything but SWITCH_STATUS_SUCCESS the playback will stop. | |||||||||
| 250 | */ | |||||||||
| 251 | if (switch_channel_has_dtmf(channel)) { | |||||||||
| 252 | if (!args->input_callback && !args->buf && !args->dmachine) { | |||||||||
| 253 | status = SWITCH_STATUS_BREAK; | |||||||||
| 254 | break; | |||||||||
| 255 | } | |||||||||
| 256 | switch_channel_dequeue_dtmf(channel, &dtmf); | |||||||||
| 257 | ||||||||||
| 258 | if (args->dmachine) { | |||||||||
| 259 | char ds[2] = {dtmf.digit, '\0'}; | |||||||||
| 260 | if ((status = switch_ivr_dmachine_feed(args->dmachine, ds, NULL((void*)0))) != SWITCH_STATUS_SUCCESS) { | |||||||||
| 261 | break; | |||||||||
| 262 | } | |||||||||
| 263 | } | |||||||||
| 264 | ||||||||||
| 265 | if (args->input_callback) { | |||||||||
| 266 | status = args->input_callback(session, (void *) &dtmf, SWITCH_INPUT_TYPE_DTMF, args->buf, args->buflen); | |||||||||
| 267 | } else if (args->buf) { | |||||||||
| 268 | *((char *) args->buf) = dtmf.digit; | |||||||||
| 269 | status = SWITCH_STATUS_BREAK; | |||||||||
| 270 | } | |||||||||
| 271 | } | |||||||||
| 272 | ||||||||||
| 273 | if (args->input_callback) { | |||||||||
| 274 | switch_event_t *event = NULL((void*)0); | |||||||||
| 275 | ||||||||||
| 276 | if (switch_core_session_dequeue_event(session, &event, SWITCH_FALSE) == SWITCH_STATUS_SUCCESS) { | |||||||||
| 277 | switch_status_t ostatus = args->input_callback(session, event, SWITCH_INPUT_TYPE_EVENT, args->buf, args->buflen); | |||||||||
| 278 | if (ostatus != SWITCH_STATUS_SUCCESS) { | |||||||||
| 279 | status = ostatus; | |||||||||
| 280 | } | |||||||||
| 281 | switch_event_destroy(&event); | |||||||||
| 282 | } | |||||||||
| 283 | } | |||||||||
| 284 | ||||||||||
| 285 | if (status != SWITCH_STATUS_SUCCESS) { | |||||||||
| 286 | break; | |||||||||
| 287 | } | |||||||||
| 288 | } | |||||||||
| 289 | ||||||||||
| 290 | status = switch_core_session_read_frame(session, &read_frame, SWITCH_IO_FLAG_NONE, 0); | |||||||||
| 291 | ||||||||||
| 292 | if (!SWITCH_READ_ACCEPTABLE(status)(status == SWITCH_STATUS_SUCCESS || status == SWITCH_STATUS_BREAK || status == SWITCH_STATUS_INUSE)) { | |||||||||
| 293 | break; | |||||||||
| 294 | } | |||||||||
| 295 | ||||||||||
| 296 | if (args && args->dmachine) { | |||||||||
| 297 | if ((status = switch_ivr_dmachine_ping(args->dmachine, NULL((void*)0))) != SWITCH_STATUS_SUCCESS) { | |||||||||
| 298 | break; | |||||||||
| 299 | } | |||||||||
| 300 | } | |||||||||
| 301 | ||||||||||
| 302 | if (sval && write_frame.datalen) { | |||||||||
| 303 | switch_generate_sln_silence((int16_t *) write_frame.data, write_frame.samples, imp.number_of_channels, sval); | |||||||||
| 304 | switch_core_session_write_frame(session, &write_frame, SWITCH_IO_FLAG_NONE, 0); | |||||||||
| 305 | } else { | |||||||||
| 306 | switch_core_session_write_frame(session, &cng_frame, SWITCH_IO_FLAG_NONE, 0); | |||||||||
| 307 | } | |||||||||
| 308 | } | |||||||||
| 309 | ||||||||||
| 310 | ||||||||||
| 311 | end: | |||||||||
| 312 | ||||||||||
| 313 | arg_recursion_check_stop(args)if (args) args->loops--; | |||||||||
| 314 | ||||||||||
| 315 | if (write_frame.codec) { | |||||||||
| 316 | switch_core_codec_destroy(&codec); | |||||||||
| 317 | } | |||||||||
| 318 | ||||||||||
| 319 | switch_safe_free(abuf)if (abuf) {free(abuf);abuf=((void*)0);}; | |||||||||
| 320 | ||||||||||
| 321 | return status; | |||||||||
| 322 | } | |||||||||
| 323 | ||||||||||
| 324 | static void *SWITCH_THREAD_FUNC unicast_thread_run(switch_thread_t *thread, void *obj) | |||||||||
| 325 | { | |||||||||
| 326 | switch_unicast_conninfo_t *conninfo = (switch_unicast_conninfo_t *) obj; | |||||||||
| 327 | switch_size_t len; | |||||||||
| 328 | ||||||||||
| 329 | if (!conninfo) { | |||||||||
| 330 | return NULL((void*)0); | |||||||||
| 331 | } | |||||||||
| 332 | ||||||||||
| 333 | while (switch_test_flag(conninfo, SUF_READY)((conninfo)->flags & SUF_READY) && switch_test_flag(conninfo, SUF_THREAD_RUNNING)((conninfo)->flags & SUF_THREAD_RUNNING)) { | |||||||||
| 334 | len = conninfo->write_frame.buflen; | |||||||||
| 335 | if (switch_socket_recv(conninfo->socket, conninfo->write_frame.data, &len) != SWITCH_STATUS_SUCCESS || len == 0) { | |||||||||
| 336 | break; | |||||||||
| 337 | } | |||||||||
| 338 | conninfo->write_frame.datalen = (uint32_t) len; | |||||||||
| 339 | conninfo->write_frame.samples = conninfo->write_frame.datalen / 2; | |||||||||
| 340 | switch_core_session_write_frame(conninfo->session, &conninfo->write_frame, SWITCH_IO_FLAG_NONE, conninfo->stream_id); | |||||||||
| 341 | } | |||||||||
| 342 | ||||||||||
| 343 | switch_clear_flag_locked(conninfo, SUF_READY)switch_mutex_lock(conninfo->flag_mutex); (conninfo)->flags &= ~(SUF_READY); switch_mutex_unlock(conninfo->flag_mutex );; | |||||||||
| 344 | switch_clear_flag_locked(conninfo, SUF_THREAD_RUNNING)switch_mutex_lock(conninfo->flag_mutex); (conninfo)->flags &= ~(SUF_THREAD_RUNNING); switch_mutex_unlock(conninfo-> flag_mutex);; | |||||||||
| 345 | ||||||||||
| 346 | return NULL((void*)0); | |||||||||
| 347 | } | |||||||||
| 348 | ||||||||||
| 349 | static void unicast_thread_launch(switch_unicast_conninfo_t *conninfo) | |||||||||
| 350 | { | |||||||||
| 351 | switch_thread_t *thread; | |||||||||
| 352 | switch_threadattr_t *thd_attr = NULL((void*)0); | |||||||||
| 353 | ||||||||||
| 354 | switch_threadattr_create(&thd_attr, switch_core_session_get_pool(conninfo->session)); | |||||||||
| 355 | switch_threadattr_detach_set(thd_attr, 1); | |||||||||
| 356 | switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE240 * 1024); | |||||||||
| 357 | switch_set_flag_locked(conninfo, SUF_THREAD_RUNNING)((conninfo->flag_mutex != ((void*)0)) ? (void) (0) : __assert_fail ("conninfo->flag_mutex != ((void*)0)", "src/switch_ivr.c" , 357, __PRETTY_FUNCTION__));switch_mutex_lock(conninfo->flag_mutex );(conninfo)->flags |= (SUF_THREAD_RUNNING);switch_mutex_unlock (conninfo->flag_mutex);; | |||||||||
| 358 | switch_thread_create(&thread, thd_attr, unicast_thread_run, conninfo, switch_core_session_get_pool(conninfo->session)); | |||||||||
| 359 | } | |||||||||
| 360 | ||||||||||
| 361 | SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_ivr_deactivate_unicast(switch_core_session_t *session) | |||||||||
| 362 | { | |||||||||
| 363 | switch_channel_t *channel = switch_core_session_get_channel(session); | |||||||||
| 364 | switch_unicast_conninfo_t *conninfo; | |||||||||
| 365 | int sanity = 0; | |||||||||
| 366 | ||||||||||
| 367 | if (!switch_channel_test_flag(channel, CF_UNICAST)) { | |||||||||
| 368 | return SWITCH_STATUS_FALSE; | |||||||||
| 369 | } | |||||||||
| 370 | ||||||||||
| 371 | if ((conninfo = switch_channel_get_private(channel, "unicast"))) { | |||||||||
| 372 | switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "src/switch_ivr.c", (const char *) __func__, 372, (const char*)(session), SWITCH_LOG_DEBUG, "Shutting down unicast connection\n"); | |||||||||
| 373 | switch_clear_flag_locked(conninfo, SUF_READY)switch_mutex_lock(conninfo->flag_mutex); (conninfo)->flags &= ~(SUF_READY); switch_mutex_unlock(conninfo->flag_mutex );; | |||||||||
| 374 | switch_socket_shutdown(conninfo->socket, SWITCH_SHUTDOWN_READWRITE); | |||||||||
| 375 | while (switch_test_flag(conninfo, SUF_THREAD_RUNNING)((conninfo)->flags & SUF_THREAD_RUNNING)) { | |||||||||
| 376 | switch_yield(10000)switch_sleep(10000);; | |||||||||
| 377 | if (++sanity >= 10000) { | |||||||||
| 378 | break; | |||||||||
| 379 | } | |||||||||
| 380 | } | |||||||||
| 381 | if (switch_core_codec_ready(&conninfo->read_codec)) { | |||||||||
| 382 | switch_core_codec_destroy(&conninfo->read_codec); | |||||||||
| 383 | } | |||||||||
| 384 | switch_socket_close(conninfo->socket); | |||||||||
| 385 | } | |||||||||
| 386 | switch_channel_clear_flag(channel, CF_UNICAST); | |||||||||
| 387 | return SWITCH_STATUS_SUCCESS; | |||||||||
| 388 | } | |||||||||
| 389 | ||||||||||
| 390 | SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_ivr_activate_unicast(switch_core_session_t *session, | |||||||||
| 391 | char *local_ip, | |||||||||
| 392 | switch_port_t local_port, | |||||||||
| 393 | char *remote_ip, switch_port_t remote_port, char *transport, char *flags) | |||||||||
| 394 | { | |||||||||
| 395 | switch_channel_t *channel = switch_core_session_get_channel(session); | |||||||||
| 396 | switch_unicast_conninfo_t *conninfo = switch_core_session_alloc(session, sizeof(*conninfo))switch_core_perform_session_alloc(session, sizeof(*conninfo), "src/switch_ivr.c", (const char *)__func__, 396); | |||||||||
| 397 | switch_codec_t *read_codec; | |||||||||
| 398 | ||||||||||
| 399 | switch_assert(conninfo != NULL)((conninfo != ((void*)0)) ? (void) (0) : __assert_fail ("conninfo != ((void*)0)" , "src/switch_ivr.c", 399, __PRETTY_FUNCTION__)); | |||||||||
| 400 | ||||||||||
| 401 | conninfo->local_ip = switch_core_session_strdup(session, local_ip)switch_core_perform_session_strdup(session, local_ip, "src/switch_ivr.c" , (const char *)__func__, 401); | |||||||||
| 402 | conninfo->local_port = local_port; | |||||||||
| 403 | ||||||||||
| 404 | conninfo->remote_ip = switch_core_session_strdup(session, remote_ip)switch_core_perform_session_strdup(session, remote_ip, "src/switch_ivr.c" , (const char *)__func__, 404); | |||||||||
| 405 | conninfo->remote_port = remote_port; | |||||||||
| 406 | conninfo->session = session; | |||||||||
| 407 | ||||||||||
| 408 | if (!strcasecmp(transport, "udp")) { | |||||||||
| 409 | conninfo->type = AF_INET2; | |||||||||
| 410 | conninfo->transport = SOCK_DGRAMSOCK_DGRAM; | |||||||||
| 411 | } else if (!strcasecmp(transport, "tcp")) { | |||||||||
| 412 | conninfo->type = AF_INET2; | |||||||||
| 413 | conninfo->transport = SOCK_STREAMSOCK_STREAM; | |||||||||
| 414 | } else { | |||||||||
| 415 | switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "src/switch_ivr.c", (const char *) __func__, 415, (const char*)(session), SWITCH_LOG_ERROR, "Invalid transport %s\n", transport); | |||||||||
| 416 | goto fail; | |||||||||
| 417 | } | |||||||||
| 418 | ||||||||||
| 419 | if (flags) { | |||||||||
| 420 | if (strstr(flags, "native")) { | |||||||||
| 421 | switch_set_flag(conninfo, SUF_NATIVE)(conninfo)->flags |= (SUF_NATIVE); | |||||||||
| 422 | } | |||||||||
| 423 | } | |||||||||
| 424 | ||||||||||
| 425 | switch_mutex_init(&conninfo->flag_mutex, SWITCH_MUTEX_NESTED0x1, switch_core_session_get_pool(session)); | |||||||||
| 426 | ||||||||||
| 427 | read_codec = switch_core_session_get_read_codec(session); | |||||||||
| 428 | ||||||||||
| 429 | if (!switch_test_flag(conninfo, SUF_NATIVE)((conninfo)->flags & SUF_NATIVE)) { | |||||||||
| 430 | if (switch_core_codec_init(&conninfo->read_codec,switch_core_codec_init_with_bitrate(&conninfo->read_codec , "L16", ((void*)0), read_codec->implementation->actual_samples_per_second , read_codec->implementation->microseconds_per_packet / 1000, 1, 0, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE , ((void*)0), switch_core_session_get_pool(session)) | |||||||||
| 431 | "L16",switch_core_codec_init_with_bitrate(&conninfo->read_codec , "L16", ((void*)0), read_codec->implementation->actual_samples_per_second , read_codec->implementation->microseconds_per_packet / 1000, 1, 0, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE , ((void*)0), switch_core_session_get_pool(session)) | |||||||||
| 432 | NULL,switch_core_codec_init_with_bitrate(&conninfo->read_codec , "L16", ((void*)0), read_codec->implementation->actual_samples_per_second , read_codec->implementation->microseconds_per_packet / 1000, 1, 0, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE , ((void*)0), switch_core_session_get_pool(session)) | |||||||||
| 433 | read_codec->implementation->actual_samples_per_second,switch_core_codec_init_with_bitrate(&conninfo->read_codec , "L16", ((void*)0), read_codec->implementation->actual_samples_per_second , read_codec->implementation->microseconds_per_packet / 1000, 1, 0, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE , ((void*)0), switch_core_session_get_pool(session)) | |||||||||
| 434 | read_codec->implementation->microseconds_per_packet / 1000,switch_core_codec_init_with_bitrate(&conninfo->read_codec , "L16", ((void*)0), read_codec->implementation->actual_samples_per_second , read_codec->implementation->microseconds_per_packet / 1000, 1, 0, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE , ((void*)0), switch_core_session_get_pool(session)) | |||||||||
| 435 | 1, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE,switch_core_codec_init_with_bitrate(&conninfo->read_codec , "L16", ((void*)0), read_codec->implementation->actual_samples_per_second , read_codec->implementation->microseconds_per_packet / 1000, 1, 0, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE , ((void*)0), switch_core_session_get_pool(session)) | |||||||||
| 436 | NULL, switch_core_session_get_pool(session))switch_core_codec_init_with_bitrate(&conninfo->read_codec , "L16", ((void*)0), read_codec->implementation->actual_samples_per_second , read_codec->implementation->microseconds_per_packet / 1000, 1, 0, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE , ((void*)0), switch_core_session_get_pool(session)) == SWITCH_STATUS_SUCCESS) { | |||||||||
| 437 | switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "src/switch_ivr.c", (const char *) __func__, 437, (const char*)(session), SWITCH_LOG_DEBUG, | |||||||||
| 438 | "Raw Codec Activation Success L16@%uhz 1 channel %dms\n", | |||||||||
| 439 | read_codec->implementation->actual_samples_per_second, read_codec->implementation->microseconds_per_packet / 1000); | |||||||||
| 440 | } else { | |||||||||
| 441 | switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "src/switch_ivr.c", (const char *) __func__, 441, (const char*)(session), SWITCH_LOG_DEBUG, "Raw Codec Activation Failed L16@%uhz 1 channel %dms\n", | |||||||||
| 442 | read_codec->implementation->actual_samples_per_second, read_codec->implementation->microseconds_per_packet / 1000); | |||||||||
| 443 | goto fail; | |||||||||
| 444 | } | |||||||||
| 445 | } | |||||||||
| 446 | ||||||||||
| 447 | conninfo->write_frame.data = conninfo->write_frame_data; | |||||||||
| 448 | conninfo->write_frame.buflen = sizeof(conninfo->write_frame_data); | |||||||||
| 449 | conninfo->write_frame.codec = switch_test_flag(conninfo, SUF_NATIVE)((conninfo)->flags & SUF_NATIVE) ? read_codec : &conninfo->read_codec; | |||||||||
| 450 | ||||||||||
| 451 | switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "src/switch_ivr.c", (const char *) __func__, 451, (const char*)(session), SWITCH_LOG_DEBUG, "connect %s:%d->%s:%d\n", | |||||||||
| 452 | conninfo->local_ip, conninfo->local_port, conninfo->remote_ip, conninfo->remote_port); | |||||||||
| 453 | ||||||||||
| 454 | if (switch_sockaddr_info_get(&conninfo->local_addr, | |||||||||
| 455 | conninfo->local_ip, SWITCH_UNSPEC0, conninfo->local_port, 0, | |||||||||
| 456 | switch_core_session_get_pool(session)) != SWITCH_STATUS_SUCCESS) { | |||||||||
| 457 | goto fail; | |||||||||
| 458 | } | |||||||||
| 459 | ||||||||||
| 460 | if (switch_sockaddr_info_get(&conninfo->remote_addr, | |||||||||
| 461 | conninfo->remote_ip, SWITCH_UNSPEC0, conninfo->remote_port, 0, | |||||||||
| 462 | switch_core_session_get_pool(session)) != SWITCH_STATUS_SUCCESS) { | |||||||||
| 463 | goto fail; | |||||||||
| 464 | } | |||||||||
| 465 | ||||||||||
| 466 | if (switch_socket_create(&conninfo->socket, AF_INET2, SOCK_DGRAMSOCK_DGRAM, 0, switch_core_session_get_pool(session)) == SWITCH_STATUS_SUCCESS) { | |||||||||
| 467 | if (switch_socket_bind(conninfo->socket, conninfo->local_addr) != SWITCH_STATUS_SUCCESS) { | |||||||||
| 468 | goto fail; | |||||||||
| 469 | } | |||||||||
| 470 | } else { | |||||||||
| 471 | goto fail; | |||||||||
| 472 | } | |||||||||
| 473 | ||||||||||
| 474 | switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "src/switch_ivr.c", (const char *) __func__, 474, (const char*)(session), SWITCH_LOG_INFO, "Created unicast connection %s:%d->%s:%d\n", | |||||||||
| 475 | conninfo->local_ip, conninfo->local_port, conninfo->remote_ip, conninfo->remote_port); | |||||||||
| 476 | switch_channel_set_private(channel, "unicast", conninfo); | |||||||||
| 477 | switch_channel_set_flag(channel, CF_UNICAST)switch_channel_set_flag_value(channel, CF_UNICAST, 1); | |||||||||
| 478 | switch_set_flag_locked(conninfo, SUF_READY)((conninfo->flag_mutex != ((void*)0)) ? (void) (0) : __assert_fail ("conninfo->flag_mutex != ((void*)0)", "src/switch_ivr.c" , 478, __PRETTY_FUNCTION__));switch_mutex_lock(conninfo->flag_mutex );(conninfo)->flags |= (SUF_READY);switch_mutex_unlock(conninfo ->flag_mutex);; | |||||||||
| 479 | return SWITCH_STATUS_SUCCESS; | |||||||||
| 480 | ||||||||||
| 481 | fail: | |||||||||
| 482 | ||||||||||
| 483 | switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "src/switch_ivr.c", (const char *) __func__, 483, (const char*)(session), SWITCH_LOG_CRIT, "Failure creating unicast connection %s:%d->%s:%d\n", | |||||||||
| 484 | conninfo->local_ip, conninfo->local_port, conninfo->remote_ip, conninfo->remote_port); | |||||||||
| 485 | return SWITCH_STATUS_FALSE; | |||||||||
| 486 | } | |||||||||
| 487 | ||||||||||
| 488 | SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_ivr_parse_event(switch_core_session_t *session, switch_event_t *event) | |||||||||
| 489 | { | |||||||||
| 490 | switch_channel_t *channel = switch_core_session_get_channel(session); | |||||||||
| 491 | char *cmd = switch_event_get_header(event, "call-command")switch_event_get_header_idx(event, "call-command", -1); | |||||||||
| 492 | unsigned long cmd_hash; | |||||||||
| 493 | switch_ssize_t hlen = -1; | |||||||||
| 494 | unsigned long CMD_EXECUTE = switch_hashfunc_default("execute", &hlen); | |||||||||
| 495 | unsigned long CMD_HANGUP = switch_hashfunc_default("hangup", &hlen); | |||||||||
| 496 | unsigned long CMD_NOMEDIA = switch_hashfunc_default("nomedia", &hlen); | |||||||||
| 497 | unsigned long CMD_UNICAST = switch_hashfunc_default("unicast", &hlen); | |||||||||
| 498 | unsigned long CMD_XFEREXT = switch_hashfunc_default("xferext", &hlen); | |||||||||
| 499 | char *lead_frames = switch_event_get_header(event, "lead-frames")switch_event_get_header_idx(event, "lead-frames", -1); | |||||||||
| 500 | char *event_lock = switch_event_get_header(event, "event-lock")switch_event_get_header_idx(event, "event-lock", -1); | |||||||||
| 501 | char *event_lock_pri = switch_event_get_header(event, "event-lock-pri")switch_event_get_header_idx(event, "event-lock-pri", -1); | |||||||||
| 502 | switch_status_t status = SWITCH_STATUS_FALSE; | |||||||||
| 503 | int el = 0, elp = 0; | |||||||||
| 504 | ||||||||||
| 505 | if (zstr(cmd)_zstr(cmd)) { | |||||||||
| 506 | switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "src/switch_ivr.c", (const char *) __func__, 506, (const char*)(session), SWITCH_LOG_ERROR, "Invalid Command!\n"); | |||||||||
| 507 | return SWITCH_STATUS_FALSE; | |||||||||
| 508 | } | |||||||||
| 509 | ||||||||||
| 510 | cmd_hash = switch_hashfunc_default(cmd, &hlen); | |||||||||
| 511 | ||||||||||
| 512 | switch_channel_set_flag_recursive(channel, CF_EVENT_PARSE); | |||||||||
| 513 | ||||||||||
| 514 | if (switch_true(event_lock)) { | |||||||||
| 515 | switch_channel_set_flag_recursive(channel, CF_EVENT_LOCK); | |||||||||
| 516 | el = 1; | |||||||||
| 517 | } | |||||||||
| 518 | ||||||||||
| 519 | if (switch_true(event_lock_pri)) { | |||||||||
| 520 | switch_channel_set_flag_recursive(channel, CF_EVENT_LOCK_PRI); | |||||||||
| 521 | elp = 1; | |||||||||
| 522 | } | |||||||||
| 523 | ||||||||||
| 524 | if (lead_frames) { | |||||||||
| 525 | switch_frame_t *read_frame; | |||||||||
| 526 | int frame_count = atoi(lead_frames); | |||||||||
| 527 | int max_frames = frame_count * 2; | |||||||||
| 528 | ||||||||||
| 529 | while (frame_count > 0 && --max_frames > 0) { | |||||||||
| 530 | status = switch_core_session_read_frame(session, &read_frame, SWITCH_IO_FLAG_NONE, 0); | |||||||||
| 531 | if (!SWITCH_READ_ACCEPTABLE(status)(status == SWITCH_STATUS_SUCCESS || status == SWITCH_STATUS_BREAK || status == SWITCH_STATUS_INUSE)) { | |||||||||
| 532 | goto done; | |||||||||
| 533 | } | |||||||||
| 534 | if (!switch_test_flag(read_frame, SFF_CNG)((read_frame)->flags & SFF_CNG)) { | |||||||||
| 535 | frame_count--; | |||||||||
| 536 | } | |||||||||
| 537 | } | |||||||||
| 538 | } | |||||||||
| 539 | ||||||||||
| 540 | if (cmd_hash == CMD_EXECUTE) { | |||||||||
| 541 | char *app_name = switch_event_get_header(event, "execute-app-name")switch_event_get_header_idx(event, "execute-app-name", -1); | |||||||||
| 542 | char *event_uuid = switch_event_get_header(event, "event-uuid")switch_event_get_header_idx(event, "event-uuid", -1); | |||||||||
| 543 | char *app_arg = switch_event_get_header(event, "execute-app-arg")switch_event_get_header_idx(event, "execute-app-arg", -1); | |||||||||
| 544 | char *content_type = switch_event_get_header(event, "content-type")switch_event_get_header_idx(event, "content-type", -1); | |||||||||
| 545 | char *loop_h = switch_event_get_header(event, "loops")switch_event_get_header_idx(event, "loops", -1); | |||||||||
| 546 | char *hold_bleg = switch_event_get_header(event, "hold-bleg")switch_event_get_header_idx(event, "hold-bleg", -1); | |||||||||
| 547 | int loops = 1; | |||||||||
| 548 | int inner = 0; | |||||||||
| 549 | ||||||||||
| 550 | if (zstr(app_arg)_zstr(app_arg) && !zstr(content_type)_zstr(content_type) && !strcasecmp(content_type, "text/plain")) { | |||||||||
| 551 | app_arg = switch_event_get_body(event); | |||||||||
| 552 | } | |||||||||
| 553 | ||||||||||
| 554 | if (loop_h) { | |||||||||
| 555 | loops = atoi(loop_h); | |||||||||
| 556 | } | |||||||||
| 557 | ||||||||||
| 558 | if (app_name) { | |||||||||
| 559 | int x; | |||||||||
| 560 | const char *b_uuid = NULL((void*)0); | |||||||||
| 561 | switch_core_session_t *b_session = NULL((void*)0); | |||||||||
| 562 | ||||||||||
| 563 | switch_channel_clear_flag(channel, CF_STOP_BROADCAST); | |||||||||
| 564 | ||||||||||
| 565 | if (!switch_channel_test_flag(channel, CF_BRIDGED) || switch_channel_test_flag(channel, CF_BROADCAST)) { | |||||||||
| 566 | inner++; | |||||||||
| 567 | hold_bleg = NULL((void*)0); | |||||||||
| 568 | } | |||||||||
| 569 | ||||||||||
| 570 | if (!switch_channel_test_flag(channel, CF_BROADCAST)) { | |||||||||
| 571 | switch_channel_set_flag(channel, CF_BROADCAST)switch_channel_set_flag_value(channel, CF_BROADCAST, 1); | |||||||||
| 572 | if (inner) { | |||||||||
| 573 | inner--; | |||||||||
| 574 | } | |||||||||
| 575 | } | |||||||||
| 576 | ||||||||||
| 577 | if (hold_bleg && switch_true(hold_bleg)) { | |||||||||
| 578 | if ((b_uuid = switch_channel_get_partner_uuid(channel))) { | |||||||||
| 579 | const char *stream; | |||||||||
| 580 | b_uuid = switch_core_session_strdup(session, b_uuid)switch_core_perform_session_strdup(session, b_uuid, "src/switch_ivr.c" , (const char *)__func__, 580); | |||||||||
| 581 | ||||||||||
| 582 | if (!(stream = switch_channel_get_hold_music_partner(channel))) { | |||||||||
| 583 | stream = switch_channel_get_hold_music(channel); | |||||||||
| 584 | } | |||||||||
| 585 | ||||||||||
| 586 | if (stream && switch_is_moh(stream)) { | |||||||||
| 587 | if ((b_session = switch_core_session_locate(b_uuid)switch_core_session_perform_locate(b_uuid, "src/switch_ivr.c" , (const char *)__func__, 587))) { | |||||||||
| 588 | switch_channel_t *b_channel = switch_core_session_get_channel(b_session); | |||||||||
| 589 | switch_status_t st; | |||||||||
| 590 | ||||||||||
| 591 | switch_ivr_broadcast(b_uuid, stream, SMF_ECHO_ALEG | SMF_LOOP); | |||||||||
| 592 | st = switch_channel_wait_for_flag(b_channel, CF_BROADCAST, SWITCH_TRUE, 5000, NULL((void*)0)); | |||||||||
| 593 | if (st != SWITCH_STATUS_SUCCESS && | |||||||||
| 594 | switch_channel_ready(channel)switch_channel_test_ready(channel, SWITCH_TRUE, SWITCH_FALSE) && switch_channel_ready(b_channel)switch_channel_test_ready(b_channel, SWITCH_TRUE, SWITCH_FALSE ) && !switch_channel_test_flag(b_channel, CF_BROADCAST)) { | |||||||||
| 595 | switch_core_session_kill_channel(b_session, SWITCH_SIG_BREAK)switch_core_session_perform_kill_channel(b_session, "src/switch_ivr.c" , (const char *)__func__, 595, SWITCH_SIG_BREAK); | |||||||||
| 596 | st = switch_channel_wait_for_flag(b_channel, CF_BROADCAST, SWITCH_TRUE, 5000, NULL((void*)0)); | |||||||||
| 597 | ||||||||||
| 598 | if (st != SWITCH_STATUS_SUCCESS && | |||||||||
| 599 | switch_channel_ready(channel)switch_channel_test_ready(channel, SWITCH_TRUE, SWITCH_FALSE) && switch_channel_ready(b_channel)switch_channel_test_ready(b_channel, SWITCH_TRUE, SWITCH_FALSE ) && !switch_channel_test_flag(b_channel, CF_BROADCAST)) { | |||||||||
| 600 | switch_core_session_flush_private_events(b_session); | |||||||||
| 601 | } | |||||||||
| 602 | } | |||||||||
| 603 | switch_core_session_rwunlock(b_session); | |||||||||
| 604 | } | |||||||||
| 605 | } else { | |||||||||
| 606 | b_uuid = NULL((void*)0); | |||||||||
| 607 | } | |||||||||
| 608 | } | |||||||||
| 609 | } | |||||||||
| 610 | ||||||||||
| 611 | for (x = 0; x < loops || loops < 0; x++) { | |||||||||
| 612 | switch_time_t b4, aftr; | |||||||||
| 613 | ||||||||||
| 614 | switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "src/switch_ivr.c", (const char *) __func__, 614, (const char*)(session), SWITCH_LOG_DEBUG, "%s Command Execute %s(%s)\n", | |||||||||
| 615 | switch_channel_get_name(channel), app_name, switch_str_nil(app_arg)(app_arg ? app_arg : "")); | |||||||||
| 616 | b4 = switch_micro_time_now(); | |||||||||
| 617 | ||||||||||
| 618 | if (event_uuid) { | |||||||||
| 619 | switch_channel_set_variable(channel, "app_uuid", event_uuid)switch_channel_set_variable_var_check(channel, "app_uuid", event_uuid , SWITCH_TRUE); | |||||||||
| 620 | } | |||||||||
| 621 | ||||||||||
| 622 | switch_channel_set_variable_printf(channel, "current_loop", "%d", x + 1); | |||||||||
| 623 | switch_channel_set_variable_printf(channel, "total_loops", "%d", loops); | |||||||||
| 624 | ||||||||||
| 625 | if (switch_core_session_execute_application(session, app_name, app_arg)switch_core_session_execute_application_get_flags(session, app_name , app_arg, ((void*)0)) != SWITCH_STATUS_SUCCESS) { | |||||||||
| 626 | if (!inner || switch_channel_test_flag(channel, CF_STOP_BROADCAST)) switch_channel_clear_flag(channel, CF_BROADCAST); | |||||||||
| 627 | break; | |||||||||
| 628 | } | |||||||||
| 629 | ||||||||||
| 630 | aftr = switch_micro_time_now(); | |||||||||
| 631 | if (!switch_channel_ready(channel)switch_channel_test_ready(channel, SWITCH_TRUE, SWITCH_FALSE) || switch_channel_test_flag(channel, CF_STOP_BROADCAST) || aftr - b4 < 500000) { | |||||||||
| 632 | break; | |||||||||
| 633 | } | |||||||||
| 634 | } | |||||||||
| 635 | ||||||||||
| 636 | switch_channel_set_variable(channel, "current_loop", NULL)switch_channel_set_variable_var_check(channel, "current_loop" , ((void*)0), SWITCH_TRUE); | |||||||||
| 637 | switch_channel_set_variable(channel, "total_loops", NULL)switch_channel_set_variable_var_check(channel, "total_loops", ((void*)0), SWITCH_TRUE); | |||||||||
| 638 | ||||||||||
| 639 | if (b_uuid) { | |||||||||
| 640 | if ((b_session = switch_core_session_locate(b_uuid)switch_core_session_perform_locate(b_uuid, "src/switch_ivr.c" , (const char *)__func__, 640))) { | |||||||||
| 641 | switch_channel_t *b_channel = switch_core_session_get_channel(b_session); | |||||||||
| 642 | switch_channel_stop_broadcast(b_channel)for(;;) {if (switch_channel_test_flag(b_channel, CF_BROADCAST )) {switch_channel_set_flag_value(b_channel, CF_STOP_BROADCAST , 1); switch_channel_set_flag_value(b_channel, CF_BREAK, 1); } break;}; | |||||||||
| 643 | switch_channel_wait_for_flag(b_channel, CF_BROADCAST, SWITCH_FALSE, 5000, NULL((void*)0)); | |||||||||
| 644 | switch_core_session_rwunlock(b_session); | |||||||||
| 645 | } | |||||||||
| 646 | } | |||||||||
| 647 | ||||||||||
| 648 | if (!inner) { | |||||||||
| 649 | switch_channel_clear_flag(channel, CF_BROADCAST); | |||||||||
| 650 | } | |||||||||
| 651 | ||||||||||
| 652 | if (switch_channel_test_flag(channel, CF_STOP_BROADCAST)) { | |||||||||
| 653 | switch_channel_clear_flag(channel, CF_BROADCAST); | |||||||||
| 654 | switch_channel_set_flag(channel, CF_BREAK)switch_channel_set_flag_value(channel, CF_BREAK, 1); | |||||||||
| 655 | } | |||||||||
| 656 | ||||||||||
| 657 | switch_channel_audio_sync(channel)switch_channel_perform_audio_sync(channel, "src/switch_ivr.c" , (const char *)__func__, 657); | |||||||||
| 658 | } | |||||||||
| 659 | } else if (cmd_hash == CMD_UNICAST) { | |||||||||
| 660 | char *local_ip = switch_event_get_header(event, "local-ip")switch_event_get_header_idx(event, "local-ip", -1); | |||||||||
| 661 | char *local_port = switch_event_get_header(event, "local-port")switch_event_get_header_idx(event, "local-port", -1); | |||||||||
| 662 | char *remote_ip = switch_event_get_header(event, "remote-ip")switch_event_get_header_idx(event, "remote-ip", -1); | |||||||||
| 663 | char *remote_port = switch_event_get_header(event, "remote-port")switch_event_get_header_idx(event, "remote-port", -1); | |||||||||
| 664 | char *transport = switch_event_get_header(event, "transport")switch_event_get_header_idx(event, "transport", -1); | |||||||||
| 665 | char *flags = switch_event_get_header(event, "flags")switch_event_get_header_idx(event, "flags", -1); | |||||||||
| 666 | ||||||||||
| 667 | if (zstr(local_ip)_zstr(local_ip)) { | |||||||||
| 668 | local_ip = "127.0.0.1"; | |||||||||
| 669 | } | |||||||||
| 670 | if (zstr(remote_ip)_zstr(remote_ip)) { | |||||||||
| 671 | remote_ip = "127.0.0.1"; | |||||||||
| 672 | } | |||||||||
| 673 | if (zstr(local_port)_zstr(local_port)) { | |||||||||
| 674 | local_port = "8025"; | |||||||||
| 675 | } | |||||||||
| 676 | if (zstr(remote_port)_zstr(remote_port)) { | |||||||||
| 677 | remote_port = "8026"; | |||||||||
| 678 | } | |||||||||
| 679 | if (zstr(transport)_zstr(transport)) { | |||||||||
| 680 | transport = "udp"; | |||||||||
| 681 | } | |||||||||
| 682 | ||||||||||
| 683 | switch_ivr_activate_unicast(session, local_ip, (switch_port_t) atoi(local_port), remote_ip, (switch_port_t) atoi(remote_port), transport, flags); | |||||||||
| 684 | ||||||||||
| 685 | } else if (cmd_hash == CMD_XFEREXT) { | |||||||||
| 686 | switch_event_header_t *hp; | |||||||||
| 687 | switch_caller_extension_t *extension = NULL((void*)0); | |||||||||
| 688 | ||||||||||
| 689 | ||||||||||
| 690 | if ((extension = switch_caller_extension_new(session, "xferext", "xferext")) == 0) { | |||||||||
| 691 | abort(); | |||||||||
| 692 | } | |||||||||
| 693 | ||||||||||
| 694 | for (hp = event->headers; hp; hp = hp->next) { | |||||||||
| 695 | char *app; | |||||||||
| 696 | char *data; | |||||||||
| 697 | ||||||||||
| 698 | if (!strcasecmp(hp->name, "application")) { | |||||||||
| 699 | app = strdup(hp->value)(__extension__ (__builtin_constant_p (hp->value) && ((size_t)(const void *)((hp->value) + 1) - (size_t)(const void *)(hp->value) == 1) ? (((const char *) (hp->value ))[0] == '\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len = strlen (hp->value) + 1; char *__retval = ( char *) malloc (__len); if (__retval != ((void*)0)) __retval = (char *) memcpy (__retval, hp->value, __len); __retval; } )) : __strdup (hp->value))); | |||||||||
| 700 | if (app) { | |||||||||
| 701 | data = strchr(app, ' ')(__extension__ (__builtin_constant_p (' ') && !__builtin_constant_p (app) && (' ') == '\0' ? (char *) __rawmemchr (app, ' ' ) : __builtin_strchr (app, ' '))); | |||||||||
| 702 | ||||||||||
| 703 | if (data) { | |||||||||
| 704 | *data++ = '\0'; | |||||||||
| 705 | } | |||||||||
| 706 | ||||||||||
| 707 | switch_caller_extension_add_application(session, extension, app, data); | |||||||||
| 708 | free(app); | |||||||||
| 709 | } | |||||||||
| 710 | } | |||||||||
| 711 | } | |||||||||
| 712 | ||||||||||
| 713 | switch_channel_transfer_to_extension(channel, extension); | |||||||||
| 714 | ||||||||||
| 715 | } else if (cmd_hash == CMD_HANGUP) { | |||||||||
| 716 | char *cause_name = switch_event_get_header(event, "hangup-cause")switch_event_get_header_idx(event, "hangup-cause", -1); | |||||||||
| 717 | switch_call_cause_t cause = SWITCH_CAUSE_NORMAL_CLEARING; | |||||||||
| 718 | ||||||||||
| 719 | if (cause_name) { | |||||||||
| 720 | cause = switch_channel_str2cause(cause_name); | |||||||||
| 721 | } | |||||||||
| 722 | ||||||||||
| 723 | switch_channel_hangup(channel, cause)switch_channel_perform_hangup(channel, "src/switch_ivr.c", (const char *)__func__, 723, cause); | |||||||||
| 724 | } else if (cmd_hash == CMD_NOMEDIA) { | |||||||||
| 725 | char *uuid = switch_event_get_header(event, "nomedia-uuid")switch_event_get_header_idx(event, "nomedia-uuid", -1); | |||||||||
| 726 | switch_ivr_nomedia(uuid, SMF_REBRIDGE); | |||||||||
| 727 | } | |||||||||
| 728 | ||||||||||
| 729 | status = SWITCH_STATUS_SUCCESS; | |||||||||
| 730 | ||||||||||
| 731 | done: | |||||||||
| 732 | ||||||||||
| 733 | switch_channel_clear_flag_recursive(channel, CF_EVENT_PARSE); | |||||||||
| 734 | ||||||||||
| 735 | if (el) { | |||||||||
| 736 | switch_channel_clear_flag_recursive(channel, CF_EVENT_LOCK); | |||||||||
| 737 | } | |||||||||
| 738 | ||||||||||
| 739 | if (elp) { | |||||||||
| 740 | switch_channel_clear_flag_recursive(channel, CF_EVENT_LOCK_PRI); | |||||||||
| 741 | } | |||||||||
| 742 | ||||||||||
| 743 | return switch_channel_test_flag(channel, CF_BREAK) ? SWITCH_STATUS_BREAK : status; | |||||||||
| 744 | } | |||||||||
| 745 | ||||||||||
| 746 | SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_ivr_parse_next_event(switch_core_session_t *session) | |||||||||
| 747 | { | |||||||||
| 748 | switch_event_t *event; | |||||||||
| 749 | switch_status_t status = SWITCH_STATUS_FALSE; | |||||||||
| 750 | ||||||||||
| 751 | if (switch_core_session_dequeue_private_event(session, &event) == SWITCH_STATUS_SUCCESS) { | |||||||||
| 752 | status = switch_ivr_parse_event(session, event); | |||||||||
| 753 | event->event_id = SWITCH_EVENT_PRIVATE_COMMAND; | |||||||||
| 754 | switch_event_prep_for_delivery(event)switch_event_prep_for_delivery_detailed("src/switch_ivr.c", ( const char * )(const char *)__func__, 754, event); | |||||||||
| 755 | switch_channel_event_set_data(switch_core_session_get_channel(session), event); | |||||||||
| 756 | switch_event_fire(&event)switch_event_fire_detailed("src/switch_ivr.c", (const char * ) (const char *)__func__, 756, &event, ((void*)0)); | |||||||||
| 757 | } | |||||||||
| 758 | ||||||||||
| 759 | return status; | |||||||||
| 760 | ||||||||||
| 761 | } | |||||||||
| 762 | ||||||||||
| 763 | SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_ivr_process_indications(switch_core_session_t *session, switch_core_session_message_t *message) | |||||||||
| 764 | { | |||||||||
| 765 | switch_status_t status = SWITCH_STATUS_SUCCESS; | |||||||||
| 766 | switch_channel_t *channel = switch_core_session_get_channel(session); | |||||||||
| 767 | ||||||||||
| 768 | switch(message->message_id) { | |||||||||
| 769 | case SWITCH_MESSAGE_INDICATE_ANSWER: | |||||||||
| 770 | if (switch_channel_answer(channel)switch_channel_perform_answer(channel, "src/switch_ivr.c", (const char *)__func__, 770) != SWITCH_STATUS_SUCCESS) { | |||||||||
| 771 | switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER)switch_channel_perform_hangup(channel, "src/switch_ivr.c", (const char *)__func__, 771, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER); | |||||||||
| 772 | } | |||||||||
| 773 | break; | |||||||||
| 774 | case SWITCH_MESSAGE_INDICATE_PROGRESS: | |||||||||
| 775 | if (switch_channel_pre_answer(channel)switch_channel_perform_pre_answer(channel, "src/switch_ivr.c" , (const char *)__func__, 775) != SWITCH_STATUS_SUCCESS) { | |||||||||
| 776 | switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER)switch_channel_perform_hangup(channel, "src/switch_ivr.c", (const char *)__func__, 776, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER); | |||||||||
| 777 | } | |||||||||
| 778 | break; | |||||||||
| 779 | case SWITCH_MESSAGE_INDICATE_RINGING: | |||||||||
| 780 | if (switch_channel_ring_ready(channel)switch_channel_perform_ring_ready_value(channel, SWITCH_RING_READY_RINGING , "src/switch_ivr.c", (const char *)__func__, 780) != SWITCH_STATUS_SUCCESS) { | |||||||||
| 781 | switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER)switch_channel_perform_hangup(channel, "src/switch_ivr.c", (const char *)__func__, 781, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER); | |||||||||
| 782 | } | |||||||||
| 783 | break; | |||||||||
| 784 | default: | |||||||||
| 785 | status = SWITCH_STATUS_FALSE; | |||||||||
| 786 | break; | |||||||||
| 787 | } | |||||||||
| 788 | ||||||||||
| 789 | return status; | |||||||||
| 790 | } | |||||||||
| 791 | ||||||||||
| 792 | SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_ivr_parse_all_messages(switch_core_session_t *session) | |||||||||
| 793 | { | |||||||||
| 794 | switch_core_session_message_t *message; | |||||||||
| 795 | int i = 0; | |||||||||
| 796 | ||||||||||
| 797 | switch_ivr_parse_all_signal_data(session); | |||||||||
| 798 | ||||||||||
| 799 | while (switch_core_session_dequeue_message(session, &message) == SWITCH_STATUS_SUCCESS) { | |||||||||
| 800 | i++; | |||||||||
| 801 | ||||||||||
| 802 | if (switch_ivr_process_indications(session, message) == SWITCH_STATUS_SUCCESS) { | |||||||||
| 803 | switch_core_session_free_message(&message); | |||||||||
| 804 | } else { | |||||||||
| 805 | switch_core_session_receive_message(session, message)switch_core_session_perform_receive_message(session, message, "src/switch_ivr.c", (const char *)__func__, 805); | |||||||||
| 806 | message = NULL((void*)0); | |||||||||
| 807 | } | |||||||||
| 808 | } | |||||||||
| 809 | ||||||||||
| 810 | return i ? SWITCH_STATUS_SUCCESS : SWITCH_STATUS_FALSE; | |||||||||
| 811 | } | |||||||||
| 812 | ||||||||||
| 813 | ||||||||||
| 814 | SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_ivr_parse_all_signal_data(switch_core_session_t *session) | |||||||||
| 815 | { | |||||||||
| 816 | void *data; | |||||||||
| 817 | switch_core_session_message_t msg = { 0 }; | |||||||||
| 818 | int i = 0; | |||||||||
| 819 | switch_channel_t *channel = switch_core_session_get_channel(session); | |||||||||
| 820 | ||||||||||
| 821 | if (!switch_core_session_in_thread(session)) { | |||||||||
| 822 | return SWITCH_STATUS_FALSE; | |||||||||
| 823 | } | |||||||||
| 824 | ||||||||||
| 825 | if (switch_channel_test_flag(channel, CF_SIGNAL_DATA)) { | |||||||||
| 826 | return SWITCH_STATUS_FALSE; | |||||||||
| 827 | } | |||||||||
| 828 | ||||||||||
| 829 | switch_channel_set_flag(channel, CF_SIGNAL_DATA)switch_channel_set_flag_value(channel, CF_SIGNAL_DATA, 1); | |||||||||
| 830 | ||||||||||
| 831 | msg.message_id = SWITCH_MESSAGE_INDICATE_SIGNAL_DATA; | |||||||||
| 832 | msg.from = __FILE__"src/switch_ivr.c"; | |||||||||
| 833 | ||||||||||
| 834 | while (switch_core_session_dequeue_signal_data(session, &data) == SWITCH_STATUS_SUCCESS) { | |||||||||
| 835 | i++; | |||||||||
| 836 | ||||||||||
| 837 | msg.pointer_arg = data; | |||||||||
| 838 | switch_core_session_receive_message(session, &msg)switch_core_session_perform_receive_message(session, &msg , "src/switch_ivr.c", (const char *)__func__, 838); | |||||||||
| 839 | ||||||||||
| 840 | data = NULL((void*)0); | |||||||||
| 841 | ||||||||||
| 842 | } | |||||||||
| 843 | ||||||||||
| 844 | switch_channel_clear_flag(channel, CF_SIGNAL_DATA); | |||||||||
| 845 | ||||||||||
| 846 | return i ? SWITCH_STATUS_SUCCESS : SWITCH_STATUS_FALSE; | |||||||||
| 847 | } | |||||||||
| 848 | ||||||||||
| 849 | SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_ivr_parse_all_events(switch_core_session_t *session) | |||||||||
| 850 | { | |||||||||
| 851 | int x = 0; | |||||||||
| 852 | switch_channel_t *channel; | |||||||||
| 853 | ||||||||||
| 854 | switch_ivr_parse_all_messages(session); | |||||||||
| 855 | ||||||||||
| 856 | channel = switch_core_session_get_channel(session); | |||||||||
| 857 | ||||||||||
| 858 | if (!switch_channel_test_flag(channel, CF_PROXY_MODE) && switch_channel_test_flag(channel, CF_BLOCK_BROADCAST_UNTIL_MEDIA)) { | |||||||||
| 859 | if (switch_channel_media_up(channel)(switch_channel_test_flag(channel, CF_ANSWERED) || switch_channel_test_flag (channel, CF_EARLY_MEDIA))) { | |||||||||
| 860 | switch_channel_clear_flag(channel, CF_BLOCK_BROADCAST_UNTIL_MEDIA); | |||||||||
| 861 | } else { | |||||||||
| 862 | return SWITCH_STATUS_SUCCESS; | |||||||||
| 863 | } | |||||||||
| 864 | } | |||||||||
| 865 | ||||||||||
| 866 | while (switch_ivr_parse_next_event(session) == SWITCH_STATUS_SUCCESS) { | |||||||||
| 867 | x++; | |||||||||
| 868 | } | |||||||||
| 869 | ||||||||||
| 870 | return SWITCH_STATUS_SUCCESS; | |||||||||
| 871 | } | |||||||||
| 872 | ||||||||||
| 873 | ||||||||||
| 874 | SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_ivr_park(switch_core_session_t *session, switch_input_args_t *args) | |||||||||
| 875 | { | |||||||||
| 876 | switch_status_t status = SWITCH_STATUS_SUCCESS; | |||||||||
| 877 | switch_channel_t *channel = switch_core_session_get_channel(session); | |||||||||
| 878 | switch_frame_t *read_frame = NULL((void*)0); | |||||||||
| 879 | int stream_id = 0; | |||||||||
| 880 | switch_event_t *event; | |||||||||
| 881 | switch_unicast_conninfo_t *conninfo = NULL((void*)0); | |||||||||
| 882 | uint32_t rate = 0; | |||||||||
| 883 | uint32_t bpf = 0; | |||||||||
| 884 | const char *to; | |||||||||
| 885 | int timeout = 0; | |||||||||
| 886 | time_t expires = 0; | |||||||||
| 887 | switch_codec_implementation_t read_impl = { 0 }; | |||||||||
| 888 | switch_call_cause_t timeout_cause = SWITCH_CAUSE_NORMAL_CLEARING; | |||||||||
| 889 | switch_codec_t codec = { 0 }; | |||||||||
| 890 | int sval = 0; | |||||||||
| 891 | const char *var; | |||||||||
| 892 | switch_frame_t write_frame = { 0 }; | |||||||||
| 893 | unsigned char *abuf = NULL((void*)0); | |||||||||
| 894 | switch_codec_implementation_t imp = { 0 }; | |||||||||
| 895 | ||||||||||
| 896 | ||||||||||
| 897 | ||||||||||
| 898 | if (switch_channel_test_flag(channel, CF_RECOVERED) && switch_channel_test_flag(channel, CF_CONTROLLED)) { | |||||||||
| 899 | switch_channel_clear_flag(channel, CF_CONTROLLED); | |||||||||
| 900 | } | |||||||||
| 901 | ||||||||||
| 902 | if (switch_channel_test_flag(channel, CF_CONTROLLED)) { | |||||||||
| 903 | switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "src/switch_ivr.c", (const char *) __func__, 903, (const char*)(session), SWITCH_LOG_ERROR, "Cannot park channels that are under control already.\n"); | |||||||||
| 904 | return SWITCH_STATUS_FALSE; | |||||||||
| 905 | } | |||||||||
| 906 | ||||||||||
| 907 | if (switch_channel_get_state(channel) == CS_RESET) { | |||||||||
| 908 | return SWITCH_STATUS_FALSE; | |||||||||
| 909 | } | |||||||||
| 910 | ||||||||||
| 911 | arg_recursion_check_start(args)if (args) { if (args->loops >= 25) { switch_log_printf( SWITCH_CHANNEL_ID_LOG, "src/switch_ivr.c", (const char *)__func__ , 911, ((void*)0), SWITCH_LOG_ERROR, "RECURSION ERROR! It's not the best idea to call things that collect input recursively from an input callback.\n" ); return SWITCH_STATUS_GENERR; } else {args->loops++;} }; | |||||||||
| 912 | ||||||||||
| 913 | if ((to = switch_channel_get_variable(channel, "park_timeout")switch_channel_get_variable_dup(channel, "park_timeout", SWITCH_TRUE , -1))) { | |||||||||
| 914 | char *cause_str; | |||||||||
| 915 | ||||||||||
| 916 | if ((cause_str = strchr(to, ':')(__extension__ (__builtin_constant_p (':') && !__builtin_constant_p (to) && (':') == '\0' ? (char *) __rawmemchr (to, ':' ) : __builtin_strchr (to, ':'))))) { | |||||||||
| 917 | timeout_cause = switch_channel_str2cause(cause_str + 1); | |||||||||
| 918 | } | |||||||||
| 919 | ||||||||||
| 920 | if ((timeout = atoi(to)) < 0) { | |||||||||
| 921 | timeout = 0; | |||||||||
| 922 | } else { | |||||||||
| 923 | expires = switch_epoch_time_now(NULL((void*)0)) + timeout; | |||||||||
| 924 | } | |||||||||
| 925 | switch_channel_set_variable(channel, "park_timeout", NULL)switch_channel_set_variable_var_check(channel, "park_timeout" , ((void*)0), SWITCH_TRUE); | |||||||||
| 926 | switch_channel_set_variable(channel, SWITCH_PARK_AFTER_BRIDGE_VARIABLE, NULL)switch_channel_set_variable_var_check(channel, "park_after_bridge" , ((void*)0), SWITCH_TRUE); | |||||||||
| 927 | } | |||||||||
| 928 | ||||||||||
| 929 | switch_channel_set_flag(channel, CF_CONTROLLED)switch_channel_set_flag_value(channel, CF_CONTROLLED, 1); | |||||||||
| 930 | switch_channel_set_flag(channel, CF_PARK)switch_channel_set_flag_value(channel, CF_PARK, 1); | |||||||||
| 931 | ||||||||||
| 932 | if (switch_event_create(&event, SWITCH_EVENT_CHANNEL_PARK)switch_event_create_subclass_detailed("src/switch_ivr.c", (const char * )(const char *)__func__, 932, &event, SWITCH_EVENT_CHANNEL_PARK , ((void*)0)) == SWITCH_STATUS_SUCCESS) { | |||||||||
| 933 | switch_channel_event_set_data(channel, event); | |||||||||
| 934 | switch_event_fire(&event)switch_event_fire_detailed("src/switch_ivr.c", (const char * ) (const char *)__func__, 934, &event, ((void*)0)); | |||||||||
| 935 | } | |||||||||
| 936 | ||||||||||
| 937 | while (switch_channel_ready(channel)switch_channel_test_ready(channel, SWITCH_TRUE, SWITCH_FALSE) && switch_channel_test_flag(channel, CF_CONTROLLED) && switch_channel_test_flag(channel, CF_PARK)) { | |||||||||
| 938 | ||||||||||
| 939 | if (!rate && switch_channel_media_ready(channel)switch_channel_test_ready(channel, SWITCH_TRUE, SWITCH_TRUE)) { | |||||||||
| 940 | switch_core_session_get_read_impl(session, &read_impl); | |||||||||
| 941 | rate = read_impl.actual_samples_per_second; | |||||||||
| 942 | bpf = read_impl.decoded_bytes_per_packet; | |||||||||
| 943 | ||||||||||
| 944 | if ((var = switch_channel_get_variable(channel, SWITCH_SEND_SILENCE_WHEN_IDLE_VARIABLE)switch_channel_get_variable_dup(channel, "send_silence_when_idle" , SWITCH_TRUE, -1)) && (sval = atoi(var))) { | |||||||||
| 945 | switch_core_session_get_read_impl(session, &imp); | |||||||||
| 946 | ||||||||||
| 947 | if (switch_core_codec_init(&codec,switch_core_codec_init_with_bitrate(&codec, "L16", ((void *)0), imp.actual_samples_per_second, imp.microseconds_per_packet / 1000, imp.number_of_channels, 0, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE, ((void*)0), switch_core_session_get_pool (session)) | |||||||||
| 948 | "L16",switch_core_codec_init_with_bitrate(&codec, "L16", ((void *)0), imp.actual_samples_per_second, imp.microseconds_per_packet / 1000, imp.number_of_channels, 0, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE, ((void*)0), switch_core_session_get_pool (session)) | |||||||||
| 949 | NULL,switch_core_codec_init_with_bitrate(&codec, "L16", ((void *)0), imp.actual_samples_per_second, imp.microseconds_per_packet / 1000, imp.number_of_channels, 0, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE, ((void*)0), switch_core_session_get_pool (session)) | |||||||||
| 950 | imp.actual_samples_per_second,switch_core_codec_init_with_bitrate(&codec, "L16", ((void *)0), imp.actual_samples_per_second, imp.microseconds_per_packet / 1000, imp.number_of_channels, 0, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE, ((void*)0), switch_core_session_get_pool (session)) | |||||||||
| 951 | imp.microseconds_per_packet / 1000,switch_core_codec_init_with_bitrate(&codec, "L16", ((void *)0), imp.actual_samples_per_second, imp.microseconds_per_packet / 1000, imp.number_of_channels, 0, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE, ((void*)0), switch_core_session_get_pool (session)) | |||||||||
| 952 | imp.number_of_channels,switch_core_codec_init_with_bitrate(&codec, "L16", ((void *)0), imp.actual_samples_per_second, imp.microseconds_per_packet / 1000, imp.number_of_channels, 0, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE, ((void*)0), switch_core_session_get_pool (session)) | |||||||||
| 953 | SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE, NULL,switch_core_codec_init_with_bitrate(&codec, "L16", ((void *)0), imp.actual_samples_per_second, imp.microseconds_per_packet / 1000, imp.number_of_channels, 0, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE, ((void*)0), switch_core_session_get_pool (session)) | |||||||||
| 954 | switch_core_session_get_pool(session))switch_core_codec_init_with_bitrate(&codec, "L16", ((void *)0), imp.actual_samples_per_second, imp.microseconds_per_packet / 1000, imp.number_of_channels, 0, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE, ((void*)0), switch_core_session_get_pool (session)) != SWITCH_STATUS_SUCCESS) { | |||||||||
| 955 | switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "src/switch_ivr.c", (const char *) __func__, 955, (const char*)(session), SWITCH_LOG_ERROR, "Codec Error L16@%uhz %u channels %dms\n", | |||||||||
| 956 | imp.samples_per_second, imp.number_of_channels, imp.microseconds_per_packet / 1000); | |||||||||
| 957 | switch_goto_status(SWITCH_STATUS_FALSE, end)status = SWITCH_STATUS_FALSE; goto end; | |||||||||
| 958 | } | |||||||||
| 959 | ||||||||||
| 960 | ||||||||||
| 961 | switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "src/switch_ivr.c", (const char *) __func__, 961, (const char*)(session), SWITCH_LOG_DEBUG, "Codec Activated L16@%uhz %u channels %dms\n", | |||||||||
| 962 | imp.samples_per_second, imp.number_of_channels, imp.microseconds_per_packet / 1000); | |||||||||
| 963 | ||||||||||
| 964 | write_frame.codec = &codec; | |||||||||
| 965 | switch_zmalloc(abuf, SWITCH_RECOMMENDED_BUFFER_SIZE)(void)((((abuf = calloc(1, (8192)))) ? (void) (0) : __assert_fail ("(abuf = calloc(1, (8192)))", "src/switch_ivr.c", 965, __PRETTY_FUNCTION__ )),abuf); | |||||||||
| 966 | write_frame.data = abuf; | |||||||||
| 967 | write_frame.buflen = SWITCH_RECOMMENDED_BUFFER_SIZE8192; | |||||||||
| 968 | write_frame.datalen = imp.decoded_bytes_per_packet; | |||||||||
| 969 | write_frame.samples = write_frame.datalen / sizeof(int16_t); | |||||||||
| 970 | } | |||||||||
| 971 | } | |||||||||
| 972 | ||||||||||
| 973 | if (rate) { | |||||||||
| 974 | if (switch_channel_test_flag(channel, CF_SERVICE)) { | |||||||||
| 975 | switch_cond_next(); | |||||||||
| 976 | status = SWITCH_STATUS_SUCCESS; | |||||||||
| 977 | } else { | |||||||||
| 978 | status = switch_core_session_read_frame(session, &read_frame, SWITCH_IO_FLAG_NONE, stream_id); | |||||||||
| 979 | } | |||||||||
| 980 | } else { | |||||||||
| 981 | switch_yield(20000)switch_sleep(20000);; | |||||||||
| 982 | ||||||||||
| 983 | if (switch_core_session_dequeue_private_event(session, &event) == SWITCH_STATUS_SUCCESS) { | |||||||||
| 984 | switch_ivr_parse_event(session, event); | |||||||||
| 985 | switch_event_destroy(&event); | |||||||||
| 986 | } | |||||||||
| 987 | ||||||||||
| 988 | status = SWITCH_STATUS_SUCCESS; | |||||||||
| 989 | } | |||||||||
| 990 | ||||||||||
| 991 | if (!SWITCH_READ_ACCEPTABLE(status)(status == SWITCH_STATUS_SUCCESS || status == SWITCH_STATUS_BREAK || status == SWITCH_STATUS_INUSE)) { | |||||||||
| 992 | break; | |||||||||
| 993 | } | |||||||||
| 994 | ||||||||||
| 995 | if (rate && write_frame.data && sval) { | |||||||||
| 996 | switch_generate_sln_silence((int16_t *) write_frame.data, write_frame.samples, read_impl.number_of_channels, sval); | |||||||||
| 997 | switch_core_session_write_frame(session, &write_frame, SWITCH_IO_FLAG_NONE, 0); | |||||||||
| 998 | } | |||||||||
| 999 | ||||||||||
| 1000 | if (expires && switch_epoch_time_now(NULL((void*)0)) >= expires) { | |||||||||
| 1001 | switch_channel_hangup(channel, timeout_cause)switch_channel_perform_hangup(channel, "src/switch_ivr.c", (const char *)__func__, 1001, timeout_cause); | |||||||||
| 1002 | break; | |||||||||
| 1003 | } | |||||||||
| 1004 | ||||||||||
| 1005 | if (switch_channel_test_flag(channel, CF_UNICAST)) { | |||||||||
| 1006 | if (!switch_channel_media_ready(channel)switch_channel_test_ready(channel, SWITCH_TRUE, SWITCH_TRUE)) { | |||||||||
| 1007 | if (switch_channel_pre_answer(channel)switch_channel_perform_pre_answer(channel, "src/switch_ivr.c" , (const char *)__func__, 1007) != SWITCH_STATUS_SUCCESS) { | |||||||||
| 1008 | switch_goto_status(SWITCH_STATUS_FALSE, end)status = SWITCH_STATUS_FALSE; goto end; | |||||||||
| 1009 | } | |||||||||
| 1010 | } | |||||||||
| 1011 | ||||||||||
| 1012 | if (!conninfo) { | |||||||||
| 1013 | if (!(conninfo = switch_channel_get_private(channel, "unicast"))) { | |||||||||
| 1014 | switch_channel_clear_flag(channel, CF_UNICAST); | |||||||||
| 1015 | } | |||||||||
| 1016 | ||||||||||
| 1017 | if (conninfo) { | |||||||||
| 1018 | unicast_thread_launch(conninfo); | |||||||||
| 1019 | } | |||||||||
| 1020 | } | |||||||||
| 1021 | ||||||||||
| 1022 | if (conninfo) { | |||||||||
| 1023 | switch_size_t len = 0; | |||||||||
| 1024 | uint32_t flags = 0; | |||||||||
| 1025 | switch_byte_t decoded[SWITCH_RECOMMENDED_BUFFER_SIZE8192]; | |||||||||
| 1026 | uint32_t dlen = sizeof(decoded); | |||||||||
| 1027 | switch_status_t tstatus; | |||||||||
| 1028 | switch_byte_t *sendbuf = NULL((void*)0); | |||||||||
| 1029 | uint32_t sendlen = 0; | |||||||||
| 1030 | ||||||||||
| 1031 | switch_assert(read_frame)((read_frame) ? (void) (0) : __assert_fail ("read_frame", "src/switch_ivr.c" , 1031, __PRETTY_FUNCTION__)); | |||||||||
| 1032 | ||||||||||
| 1033 | if (switch_test_flag(read_frame, SFF_CNG)((read_frame)->flags & SFF_CNG)) { | |||||||||
| 1034 | sendlen = bpf; | |||||||||
| 1035 | switch_assert(sendlen <= SWITCH_RECOMMENDED_BUFFER_SIZE)((sendlen <= 8192) ? (void) (0) : __assert_fail ("sendlen <= 8192" , "src/switch_ivr.c", 1035, __PRETTY_FUNCTION__)); | |||||||||
| 1036 | memset(decoded, 255, sendlen); | |||||||||
| 1037 | sendbuf = decoded; | |||||||||
| 1038 | tstatus = SWITCH_STATUS_SUCCESS; | |||||||||
| 1039 | } else { | |||||||||
| 1040 | if (switch_test_flag(conninfo, SUF_NATIVE)((conninfo)->flags & SUF_NATIVE)) { | |||||||||
| 1041 | tstatus = SWITCH_STATUS_NOOP; | |||||||||
| 1042 | } else { | |||||||||
| 1043 | switch_codec_t *read_codec = switch_core_session_get_read_codec(session); | |||||||||
| 1044 | tstatus = switch_core_codec_decode(read_codec, | |||||||||
| 1045 | &conninfo->read_codec, | |||||||||
| 1046 | read_frame->data, | |||||||||
| 1047 | read_frame->datalen, read_impl.actual_samples_per_second, decoded, &dlen, &rate, &flags); | |||||||||
| 1048 | } | |||||||||
| 1049 | switch (tstatus) { | |||||||||
| 1050 | case SWITCH_STATUS_NOOP: | |||||||||
| 1051 | case SWITCH_STATUS_BREAK: | |||||||||
| 1052 | sendbuf = read_frame->data; | |||||||||
| 1053 | sendlen = read_frame->datalen; | |||||||||
| 1054 | tstatus = SWITCH_STATUS_SUCCESS; | |||||||||
| 1055 | break; | |||||||||
| 1056 | case SWITCH_STATUS_SUCCESS: | |||||||||
| 1057 | sendbuf = decoded; | |||||||||
| 1058 | sendlen = dlen; | |||||||||
| 1059 | tstatus = SWITCH_STATUS_SUCCESS; | |||||||||
| 1060 | break; | |||||||||
| 1061 | default: | |||||||||
| 1062 | switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "src/switch_ivr.c", (const char *) __func__, 1062, (const char*)(session), SWITCH_LOG_NOTICE, "Codec Error\n"); | |||||||||
| 1063 | switch_ivr_deactivate_unicast(session); | |||||||||
| 1064 | break; | |||||||||
| 1065 | } | |||||||||
| 1066 | } | |||||||||
| 1067 | ||||||||||
| 1068 | if (tstatus == SWITCH_STATUS_SUCCESS) { | |||||||||
| 1069 | len = sendlen; | |||||||||
| 1070 | if (switch_socket_sendto(conninfo->socket, conninfo->remote_addr, 0, (void *) sendbuf, &len) != SWITCH_STATUS_SUCCESS) { | |||||||||
| 1071 | switch_ivr_deactivate_unicast(session); | |||||||||
| 1072 | } | |||||||||
| 1073 | } | |||||||||
| 1074 | } | |||||||||
| 1075 | } | |||||||||
| 1076 | ||||||||||
| 1077 | switch_ivr_parse_all_events(session); | |||||||||
| 1078 | ||||||||||
| 1079 | ||||||||||
| 1080 | if (switch_channel_has_dtmf(channel)) { | |||||||||
| 1081 | switch_dtmf_t dtmf = { 0 }; | |||||||||
| 1082 | ||||||||||
| 1083 | if (args && !args->input_callback && !args->buf && !args->dmachine) { | |||||||||
| 1084 | status = SWITCH_STATUS_BREAK; | |||||||||
| 1085 | break; | |||||||||
| 1086 | } | |||||||||
| 1087 | ||||||||||
| 1088 | switch_channel_dequeue_dtmf(channel, &dtmf); | |||||||||
| 1089 | ||||||||||
| 1090 | if (args) { | |||||||||
| 1091 | if (args->dmachine) { | |||||||||
| 1092 | char ds[2] = {dtmf.digit, '\0'}; | |||||||||
| 1093 | if ((status = switch_ivr_dmachine_feed(args->dmachine, ds, NULL((void*)0))) != SWITCH_STATUS_SUCCESS) { | |||||||||
| 1094 | break; | |||||||||
| 1095 | } | |||||||||
| 1096 | } | |||||||||
| 1097 | ||||||||||
| 1098 | if (args->input_callback) { | |||||||||
| 1099 | if ((status = args->input_callback(session, (void *) &dtmf, SWITCH_INPUT_TYPE_DTMF, args->buf, args->buflen)) != SWITCH_STATUS_SUCCESS) { | |||||||||
| 1100 | break; | |||||||||
| 1101 | } | |||||||||
| 1102 | } | |||||||||
| 1103 | } | |||||||||
| 1104 | } | |||||||||
| 1105 | ||||||||||
| 1106 | if (switch_core_session_dequeue_event(session, &event, SWITCH_FALSE) == SWITCH_STATUS_SUCCESS) { | |||||||||
| 1107 | if (args && args->input_callback) { | |||||||||
| 1108 | switch_status_t ostatus; | |||||||||
| 1109 | ||||||||||
| 1110 | if ((ostatus = args->input_callback(session, event, SWITCH_INPUT_TYPE_EVENT, args->buf, args->buflen)) != SWITCH_STATUS_SUCCESS) { | |||||||||
| 1111 | status = ostatus; | |||||||||
| 1112 | break; | |||||||||
| 1113 | } | |||||||||
| 1114 | } else { | |||||||||
| 1115 | switch_channel_event_set_data(channel, event); | |||||||||
| 1116 | switch_event_fire(&event)switch_event_fire_detailed("src/switch_ivr.c", (const char * ) (const char *)__func__, 1116, &event, ((void*)0)); | |||||||||
| 1117 | } | |||||||||
| 1118 | } | |||||||||
| 1119 | ||||||||||
| 1120 | if (args && args->dmachine) { | |||||||||
| 1121 | if ((status = switch_ivr_dmachine_ping(args->dmachine, NULL((void*)0))) != SWITCH_STATUS_SUCCESS) { | |||||||||
| 1122 | break; | |||||||||
| 1123 | } | |||||||||
| 1124 | } | |||||||||
| 1125 | ||||||||||
| 1126 | ||||||||||
| 1127 | } | |||||||||
| 1128 | ||||||||||
| 1129 | end: | |||||||||
| 1130 | ||||||||||
| 1131 | arg_recursion_check_stop(args)if (args) args->loops--; | |||||||||
| 1132 | ||||||||||
| 1133 | if (write_frame.codec) { | |||||||||
| 1134 | switch_core_codec_destroy(&codec); | |||||||||
| 1135 | } | |||||||||
| 1136 | ||||||||||
| 1137 | switch_safe_free(abuf)if (abuf) {free(abuf);abuf=((void*)0);}; | |||||||||
| 1138 | ||||||||||
| 1139 | switch_channel_clear_flag(channel, CF_CONTROLLED); | |||||||||
| 1140 | switch_channel_clear_flag(channel, CF_PARK); | |||||||||
| 1141 | ||||||||||
| 1142 | if (switch_event_create(&event, SWITCH_EVENT_CHANNEL_UNPARK)switch_event_create_subclass_detailed("src/switch_ivr.c", (const char * )(const char *)__func__, 1142, &event, SWITCH_EVENT_CHANNEL_UNPARK , ((void*)0)) == SWITCH_STATUS_SUCCESS) { | |||||||||
| 1143 | switch_channel_event_set_data(channel, event); | |||||||||
| 1144 | switch_event_fire(&event)switch_event_fire_detailed("src/switch_ivr.c", (const char * ) (const char *)__func__, 1144, &event, ((void*)0)); | |||||||||
| 1145 | } | |||||||||
| 1146 | ||||||||||
| 1147 | if (switch_channel_test_flag(channel, CF_UNICAST)) { | |||||||||
| 1148 | switch_ivr_deactivate_unicast(session); | |||||||||
| 1149 | } | |||||||||
| 1150 | ||||||||||
| 1151 | return status; | |||||||||
| 1152 | } | |||||||||
| 1153 | ||||||||||
| 1154 | SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_ivr_collect_digits_callback(switch_core_session_t *session, switch_input_args_t *args, uint32_t digit_timeout, | |||||||||
| 1155 | uint32_t abs_timeout) | |||||||||
| 1156 | { | |||||||||
| 1157 | switch_channel_t *channel = switch_core_session_get_channel(session); | |||||||||
| 1158 | switch_status_t status = SWITCH_STATUS_SUCCESS; | |||||||||
| 1159 | switch_time_t abs_started = 0, digit_started = 0; | |||||||||
| 1160 | uint32_t abs_elapsed = 0, digit_elapsed = 0; | |||||||||
| 1161 | ||||||||||
| 1162 | if (!args) { | |||||||||
| 1163 | return SWITCH_STATUS_GENERR; | |||||||||
| 1164 | } | |||||||||
| 1165 | ||||||||||
| 1166 | arg_recursion_check_start(args)if (args) { if (args->loops >= 25) { switch_log_printf( SWITCH_CHANNEL_ID_LOG, "src/switch_ivr.c", (const char *)__func__ , 1166, ((void*)0), SWITCH_LOG_ERROR, "RECURSION ERROR! It's not the best idea to call things that collect input recursively from an input callback.\n" ); return SWITCH_STATUS_GENERR; } else {args->loops++;} }; | |||||||||
| 1167 | ||||||||||
| 1168 | if (abs_timeout) { | |||||||||
| 1169 | abs_started = switch_micro_time_now(); | |||||||||
| 1170 | } | |||||||||
| 1171 | if (digit_timeout) { | |||||||||
| 1172 | digit_started = switch_micro_time_now(); | |||||||||
| 1173 | } | |||||||||
| 1174 | ||||||||||
| 1175 | while (switch_channel_ready(channel)switch_channel_test_ready(channel, SWITCH_TRUE, SWITCH_FALSE)) { | |||||||||
| 1176 | switch_frame_t *read_frame = NULL((void*)0); | |||||||||
| 1177 | switch_event_t *event; | |||||||||
| 1178 | switch_dtmf_t dtmf = { 0 }; | |||||||||
| 1179 | ||||||||||
| 1180 | if (switch_channel_test_flag(channel, CF_BREAK)) { | |||||||||
| 1181 | switch_channel_clear_flag(channel, CF_BREAK); | |||||||||
| 1182 | status = SWITCH_STATUS_BREAK; | |||||||||
| 1183 | break; | |||||||||
| 1184 | } | |||||||||
| 1185 | ||||||||||
| 1186 | if (abs_timeout) { | |||||||||
| 1187 | abs_elapsed = (uint32_t) ((switch_micro_time_now() - abs_started) / 1000); | |||||||||
| 1188 | if (abs_elapsed >= abs_timeout) { | |||||||||
| 1189 | status = SWITCH_STATUS_TIMEOUT; | |||||||||
| 1190 | break; | |||||||||
| 1191 | } | |||||||||
| 1192 | } | |||||||||
| 1193 | if (digit_timeout) { | |||||||||
| 1194 | digit_elapsed = (uint32_t) ((switch_micro_time_now() - digit_started) / 1000); | |||||||||
| 1195 | if (digit_elapsed >= digit_timeout) { | |||||||||
| 1196 | status = SWITCH_STATUS_TIMEOUT; | |||||||||
| 1197 | break; | |||||||||
| 1198 | } | |||||||||
| 1199 | } | |||||||||
| 1200 | ||||||||||
| 1201 | ||||||||||
| 1202 | switch_ivr_parse_all_events(session); | |||||||||
| 1203 | ||||||||||
| 1204 | ||||||||||
| 1205 | if (switch_channel_has_dtmf(channel)) { | |||||||||
| 1206 | if (!args->input_callback && !args->buf && !args->dmachine) { | |||||||||
| 1207 | status = SWITCH_STATUS_BREAK; | |||||||||
| 1208 | break; | |||||||||
| 1209 | } | |||||||||
| 1210 | switch_channel_dequeue_dtmf(channel, &dtmf); | |||||||||
| 1211 | ||||||||||
| 1212 | if (args->dmachine) { | |||||||||
| 1213 | char ds[2] = {dtmf.digit, '\0'}; | |||||||||
| 1214 | if ((status = switch_ivr_dmachine_feed(args->dmachine, ds, NULL((void*)0))) != SWITCH_STATUS_SUCCESS) { | |||||||||
| 1215 | break; | |||||||||
| 1216 | } | |||||||||
| 1217 | } | |||||||||
| 1218 | ||||||||||
| 1219 | if (args->input_callback) { | |||||||||
| 1220 | status = args->input_callback(session, (void *) &dtmf, SWITCH_INPUT_TYPE_DTMF, args->buf, args->buflen); | |||||||||
| 1221 | } | |||||||||
| 1222 | ||||||||||
| 1223 | if (digit_timeout) { | |||||||||
| 1224 | digit_started = switch_micro_time_now(); | |||||||||
| 1225 | } | |||||||||
| 1226 | } | |||||||||
| 1227 | ||||||||||
| 1228 | if (switch_core_session_dequeue_event(session, &event, SWITCH_FALSE) == SWITCH_STATUS_SUCCESS) { | |||||||||
| 1229 | switch_status_t ostatus = args->input_callback(session, event, SWITCH_INPUT_TYPE_EVENT, args->buf, args->buflen); | |||||||||
| 1230 | if (ostatus != SWITCH_STATUS_SUCCESS) { | |||||||||
| 1231 | status = ostatus; | |||||||||
| 1232 | } | |||||||||
| 1233 | switch_event_destroy(&event); | |||||||||
| 1234 | } | |||||||||
| 1235 | ||||||||||
| 1236 | if (status != SWITCH_STATUS_SUCCESS) { | |||||||||
| 1237 | break; | |||||||||
| 1238 | } | |||||||||
| 1239 | ||||||||||
| 1240 | if (switch_channel_test_flag(channel, CF_SERVICE)) { | |||||||||
| 1241 | switch_cond_next(); | |||||||||
| 1242 | } else { | |||||||||
| 1243 | status = switch_core_session_read_frame(session, &read_frame, SWITCH_IO_FLAG_NONE, 0); | |||||||||
| 1244 | } | |||||||||
| 1245 | ||||||||||
| 1246 | if (!SWITCH_READ_ACCEPTABLE(status)(status == SWITCH_STATUS_SUCCESS || status == SWITCH_STATUS_BREAK || status == SWITCH_STATUS_INUSE)) { | |||||||||
| 1247 | break; | |||||||||
| 1248 | } | |||||||||
| 1249 | ||||||||||
| 1250 | if (args && args->dmachine) { | |||||||||
| 1251 | if ((status = switch_ivr_dmachine_ping(args->dmachine, NULL((void*)0))) != SWITCH_STATUS_SUCCESS) { | |||||||||
| 1252 | break; | |||||||||
| 1253 | } | |||||||||
| 1254 | } | |||||||||
| 1255 | ||||||||||
| 1256 | if (read_frame && args && (args->read_frame_callback)) { | |||||||||
| 1257 | if ((status = args->read_frame_callback(session, read_frame, args->user_data)) != SWITCH_STATUS_SUCCESS) { | |||||||||
| 1258 | break; | |||||||||
| 1259 | } | |||||||||
| 1260 | } | |||||||||
| 1261 | } | |||||||||
| 1262 | ||||||||||
| 1263 | arg_recursion_check_stop(args)if (args) args->loops--; | |||||||||
| 1264 | ||||||||||
| 1265 | return status; | |||||||||
| 1266 | } | |||||||||
| 1267 | ||||||||||
| 1268 | SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_ivr_collect_digits_count(switch_core_session_t *session, | |||||||||
| 1269 | char *buf, | |||||||||
| 1270 | switch_size_t buflen, | |||||||||
| 1271 | switch_size_t maxdigits, | |||||||||
| 1272 | const char *terminators, char *terminator, | |||||||||
| 1273 | uint32_t first_timeout, uint32_t digit_timeout, uint32_t abs_timeout) | |||||||||
| 1274 | { | |||||||||
| 1275 | switch_size_t i = 0, x = strlen(buf); | |||||||||
| 1276 | switch_channel_t *channel = switch_core_session_get_channel(session); | |||||||||
| 1277 | switch_status_t status = SWITCH_STATUS_FALSE; | |||||||||
| 1278 | switch_time_t started = 0, digit_started = 0; | |||||||||
| 1279 | uint32_t abs_elapsed = 0, digit_elapsed = 0; | |||||||||
| 1280 | uint32_t eff_timeout = 0; | |||||||||
| 1281 | switch_frame_t write_frame = { 0 }; | |||||||||
| 1282 | unsigned char *abuf = NULL((void*)0); | |||||||||
| 1283 | switch_codec_implementation_t imp = { 0 }; | |||||||||
| 1284 | switch_codec_t codec = { 0 }; | |||||||||
| 1285 | int sval = 0; | |||||||||
| 1286 | const char *var; | |||||||||
| 1287 | ||||||||||
| 1288 | if ((var = switch_channel_get_variable(channel, SWITCH_SEND_SILENCE_WHEN_IDLE_VARIABLE)switch_channel_get_variable_dup(channel, "send_silence_when_idle" , SWITCH_TRUE, -1)) && (sval = atoi(var))) { | |||||||||
| 1289 | switch_core_session_get_read_impl(session, &imp); | |||||||||
| 1290 | ||||||||||
| 1291 | if (switch_core_codec_init(&codec,switch_core_codec_init_with_bitrate(&codec, "L16", ((void *)0), imp.samples_per_second, imp.microseconds_per_packet / 1000 , imp.number_of_channels, 0, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE , ((void*)0), switch_core_session_get_pool(session)) | |||||||||
| 1292 | "L16",switch_core_codec_init_with_bitrate(&codec, "L16", ((void *)0), imp.samples_per_second, imp.microseconds_per_packet / 1000 , imp.number_of_channels, 0, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE , ((void*)0), switch_core_session_get_pool(session)) | |||||||||
| 1293 | NULL,switch_core_codec_init_with_bitrate(&codec, "L16", ((void *)0), imp.samples_per_second, imp.microseconds_per_packet / 1000 , imp.number_of_channels, 0, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE , ((void*)0), switch_core_session_get_pool(session)) | |||||||||
| 1294 | imp.samples_per_second,switch_core_codec_init_with_bitrate(&codec, "L16", ((void *)0), imp.samples_per_second, imp.microseconds_per_packet / 1000 , imp.number_of_channels, 0, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE , ((void*)0), switch_core_session_get_pool(session)) | |||||||||
| 1295 | imp.microseconds_per_packet / 1000,switch_core_codec_init_with_bitrate(&codec, "L16", ((void *)0), imp.samples_per_second, imp.microseconds_per_packet / 1000 , imp.number_of_channels, 0, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE , ((void*)0), switch_core_session_get_pool(session)) | |||||||||
| 1296 | imp.number_of_channels,switch_core_codec_init_with_bitrate(&codec, "L16", ((void *)0), imp.samples_per_second, imp.microseconds_per_packet / 1000 , imp.number_of_channels, 0, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE , ((void*)0), switch_core_session_get_pool(session)) | |||||||||
| 1297 | SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE, NULL,switch_core_codec_init_with_bitrate(&codec, "L16", ((void *)0), imp.samples_per_second, imp.microseconds_per_packet / 1000 , imp.number_of_channels, 0, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE , ((void*)0), switch_core_session_get_pool(session)) | |||||||||
| 1298 | switch_core_session_get_pool(session))switch_core_codec_init_with_bitrate(&codec, "L16", ((void *)0), imp.samples_per_second, imp.microseconds_per_packet / 1000 , imp.number_of_channels, 0, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE , ((void*)0), switch_core_session_get_pool(session)) != SWITCH_STATUS_SUCCESS) { | |||||||||
| 1299 | switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "src/switch_ivr.c", (const char *) __func__, 1299, (const char*)(session), SWITCH_LOG_ERROR, "Codec Error L16@%uhz %u channels %dms\n", | |||||||||
| 1300 | imp.samples_per_second, imp.number_of_channels, imp.microseconds_per_packet / 1000); | |||||||||
| 1301 | return SWITCH_STATUS_FALSE; | |||||||||
| 1302 | } | |||||||||
| 1303 | ||||||||||
| 1304 | ||||||||||
| 1305 | switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "src/switch_ivr.c", (const char *) __func__, 1305, (const char*)(session), SWITCH_LOG_DEBUG, "Codec Activated L16@%uhz %u channels %dms\n", | |||||||||
| 1306 | imp.samples_per_second, imp.number_of_channels, imp.microseconds_per_packet / 1000); | |||||||||
| 1307 | ||||||||||
| 1308 | write_frame.codec = &codec; | |||||||||
| 1309 | switch_zmalloc(abuf, SWITCH_RECOMMENDED_BUFFER_SIZE)(void)((((abuf = calloc(1, (8192)))) ? (void) (0) : __assert_fail ("(abuf = calloc(1, (8192)))", "src/switch_ivr.c", 1309, __PRETTY_FUNCTION__ )),abuf); | |||||||||
| 1310 | write_frame.data = abuf; | |||||||||
| 1311 | write_frame.buflen = SWITCH_RECOMMENDED_BUFFER_SIZE8192; | |||||||||
| 1312 | write_frame.datalen = imp.decoded_bytes_per_packet; | |||||||||
| 1313 | write_frame.samples = write_frame.datalen / sizeof(int16_t); | |||||||||
| 1314 | } | |||||||||
| 1315 | ||||||||||
| 1316 | if (terminator != NULL((void*)0)) { | |||||||||
| 1317 | *terminator = '\0'; | |||||||||
| 1318 | } | |||||||||
| 1319 | ||||||||||
| 1320 | if (!zstr(terminators)_zstr(terminators)) { | |||||||||
| 1321 | for (i = 0; i < x; i++) { | |||||||||
| 1322 | if (strchr(terminators, buf[i])(__extension__ (__builtin_constant_p (buf[i]) && !__builtin_constant_p (terminators) && (buf[i]) == '\0' ? (char *) __rawmemchr (terminators, buf[i]) : __builtin_strchr (terminators, buf[i ]))) && terminator != NULL((void*)0)) { | |||||||||
| 1323 | *terminator = buf[i]; | |||||||||
| 1324 | buf[i] = '\0'; | |||||||||
| 1325 | switch_safe_free(abuf)if (abuf) {free(abuf);abuf=((void*)0);}; | |||||||||
| 1326 | return SWITCH_STATUS_SUCCESS; | |||||||||
| 1327 | } | |||||||||
| 1328 | } | |||||||||
| 1329 | } | |||||||||
| 1330 | ||||||||||
| 1331 | if (abs_timeout) { | |||||||||
| 1332 | started = switch_micro_time_now(); | |||||||||
| 1333 | } | |||||||||
| 1334 | ||||||||||
| 1335 | if (digit_timeout && first_timeout) { | |||||||||
| 1336 | eff_timeout = first_timeout; | |||||||||
| 1337 | } else if (digit_timeout && !first_timeout) { | |||||||||
| 1338 | first_timeout = eff_timeout = digit_timeout; | |||||||||
| 1339 | } else if (first_timeout) { | |||||||||
| 1340 | digit_timeout = eff_timeout = first_timeout; | |||||||||
| 1341 | } | |||||||||
| 1342 | ||||||||||
| 1343 | ||||||||||
| 1344 | if (eff_timeout) { | |||||||||
| 1345 | digit_started = switch_micro_time_now(); | |||||||||
| 1346 | } | |||||||||
| 1347 | ||||||||||
| 1348 | while (switch_channel_ready(channel)switch_channel_test_ready(channel, SWITCH_TRUE, SWITCH_FALSE)) { | |||||||||
| 1349 | switch_frame_t *read_frame; | |||||||||
| 1350 | ||||||||||
| 1351 | if (abs_timeout) { | |||||||||
| 1352 | abs_elapsed = (uint32_t) ((switch_micro_time_now() - started) / 1000); | |||||||||
| 1353 | if (abs_elapsed >= abs_timeout) { | |||||||||
| 1354 | status = SWITCH_STATUS_TIMEOUT; | |||||||||
| 1355 | break; | |||||||||
| 1356 | } | |||||||||
| 1357 | } | |||||||||
| 1358 | ||||||||||
| 1359 | ||||||||||
| 1360 | switch_ivr_parse_all_events(session); | |||||||||
| 1361 | ||||||||||
| 1362 | ||||||||||
| 1363 | ||||||||||
| 1364 | if (eff_timeout) { | |||||||||
| 1365 | digit_elapsed = (uint32_t) ((switch_micro_time_now() - digit_started) / 1000); | |||||||||
| 1366 | ||||||||||
| 1367 | if (digit_elapsed >= eff_timeout) { | |||||||||
| 1368 | status = SWITCH_STATUS_TIMEOUT; | |||||||||
| 1369 | break; | |||||||||
| 1370 | } | |||||||||
| 1371 | } | |||||||||
| 1372 | ||||||||||
| 1373 | if (switch_channel_has_dtmf(channel)) { | |||||||||
| 1374 | switch_dtmf_t dtmf = { 0 }; | |||||||||
| 1375 | switch_size_t y; | |||||||||
| 1376 | ||||||||||
| 1377 | if (eff_timeout) { | |||||||||
| 1378 | eff_timeout = digit_timeout; | |||||||||
| 1379 | digit_started = switch_micro_time_now(); | |||||||||
| 1380 | } | |||||||||
| 1381 | ||||||||||
| 1382 | for (y = 0; y <= maxdigits; y++) { | |||||||||
| 1383 | if (switch_channel_dequeue_dtmf(channel, &dtmf) != SWITCH_STATUS_SUCCESS) { | |||||||||
| 1384 | break; | |||||||||
| 1385 | } | |||||||||
| 1386 | ||||||||||
| 1387 | if (!zstr(terminators)_zstr(terminators) && strchr(terminators, dtmf.digit)(__extension__ (__builtin_constant_p (dtmf.digit) && ! __builtin_constant_p (terminators) && (dtmf.digit) == '\0' ? (char *) __rawmemchr (terminators, dtmf.digit) : __builtin_strchr (terminators, dtmf.digit))) && terminator != NULL((void*)0)) { | |||||||||
| 1388 | *terminator = dtmf.digit; | |||||||||
| 1389 | switch_safe_free(abuf)if (abuf) {free(abuf);abuf=((void*)0);}; | |||||||||
| 1390 | return SWITCH_STATUS_SUCCESS; | |||||||||
| 1391 | } | |||||||||
| 1392 | ||||||||||
| 1393 | ||||||||||
| 1394 | buf[x++] = dtmf.digit; | |||||||||
| 1395 | buf[x] = '\0'; | |||||||||
| 1396 | ||||||||||
| 1397 | if (x >= buflen || x >= maxdigits) { | |||||||||
| 1398 | switch_safe_free(abuf)if (abuf) {free(abuf);abuf=((void*)0);}; | |||||||||
| 1399 | return SWITCH_STATUS_SUCCESS; | |||||||||
| 1400 | } | |||||||||
| 1401 | } | |||||||||
| 1402 | } | |||||||||
| 1403 | ||||||||||
| 1404 | if (switch_channel_test_flag(channel, CF_SERVICE)) { | |||||||||
| 1405 | switch_cond_next(); | |||||||||
| 1406 | } else { | |||||||||
| 1407 | status = switch_core_session_read_frame(session, &read_frame, SWITCH_IO_FLAG_NONE, 0); | |||||||||
| 1408 | if (!SWITCH_READ_ACCEPTABLE(status)(status == SWITCH_STATUS_SUCCESS || status == SWITCH_STATUS_BREAK || status == SWITCH_STATUS_INUSE)) { | |||||||||
| 1409 | break; | |||||||||
| 1410 | } | |||||||||
| 1411 | ||||||||||
| 1412 | if (write_frame.data) { | |||||||||
| 1413 | switch_generate_sln_silence((int16_t *) write_frame.data, write_frame.samples, imp.number_of_channels, sval); | |||||||||
| 1414 | switch_core_session_write_frame(session, &write_frame, SWITCH_IO_FLAG_NONE, 0); | |||||||||
| 1415 | } | |||||||||
| 1416 | ||||||||||
| 1417 | } | |||||||||
| 1418 | } | |||||||||
| 1419 | ||||||||||
| 1420 | if (write_frame.codec) { | |||||||||
| 1421 | switch_core_codec_destroy(&codec); | |||||||||
| 1422 | } | |||||||||
| 1423 | ||||||||||
| 1424 | switch_safe_free(abuf)if (abuf) {free(abuf);abuf=((void*)0);}; | |||||||||
| 1425 | ||||||||||
| 1426 | return status; | |||||||||
| 1427 | } | |||||||||
| 1428 | ||||||||||
| 1429 | SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_ivr_hold(switch_core_session_t *session, const char *message, switch_bool_t moh) | |||||||||
| 1430 | { | |||||||||
| 1431 | switch_core_session_message_t msg = { 0 }; | |||||||||
| 1432 | switch_channel_t *channel = switch_core_session_get_channel(session); | |||||||||
| 1433 | const char *stream; | |||||||||
| 1434 | const char *other_uuid; | |||||||||
| 1435 | switch_event_t *event; | |||||||||
| 1436 | ||||||||||
| 1437 | msg.message_id = SWITCH_MESSAGE_INDICATE_HOLD; | |||||||||
| 1438 | msg.string_arg = message; | |||||||||
| 1439 | msg.from = __FILE__"src/switch_ivr.c"; | |||||||||
| 1440 | ||||||||||
| 1441 | switch_channel_set_flag(channel, CF_HOLD)switch_channel_set_flag_value(channel, CF_HOLD, 1); | |||||||||
| 1442 | switch_channel_set_flag(channel, CF_SUSPEND)switch_channel_set_flag_value(channel, CF_SUSPEND, 1); | |||||||||
| 1443 | ||||||||||
| 1444 | switch_core_session_receive_message(session, &msg)switch_core_session_perform_receive_message(session, &msg , "src/switch_ivr.c", (const char *)__func__, 1444); | |||||||||
| 1445 | ||||||||||
| 1446 | if (moh && (stream = switch_channel_get_hold_music(channel))) { | |||||||||
| 1447 | if ((other_uuid = switch_channel_get_partner_uuid(channel))) { | |||||||||
| 1448 | switch_ivr_broadcast(other_uuid, stream, SMF_ECHO_ALEG | SMF_LOOP); | |||||||||
| 1449 | } | |||||||||
| 1450 | } | |||||||||
| 1451 | ||||||||||
| 1452 | if (switch_event_create(&event, SWITCH_EVENT_CHANNEL_HOLD)switch_event_create_subclass_detailed("src/switch_ivr.c", (const char * )(const char *)__func__, 1452, &event, SWITCH_EVENT_CHANNEL_HOLD , ((void*)0)) == SWITCH_STATUS_SUCCESS) { | |||||||||
| 1453 | switch_channel_event_set_data(channel, event); | |||||||||
| 1454 | switch_event_fire(&event)switch_event_fire_detailed("src/switch_ivr.c", (const char * ) (const char *)__func__, 1454, &event, ((void*)0)); | |||||||||
| 1455 | } | |||||||||
| 1456 | ||||||||||
| 1457 | ||||||||||
| 1458 | return SWITCH_STATUS_SUCCESS; | |||||||||
| 1459 | } | |||||||||
| 1460 | ||||||||||
| 1461 | SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_ivr_hold_uuid(const char *uuid, const char *message, switch_bool_t moh) | |||||||||
| 1462 | { | |||||||||
| 1463 | switch_core_session_t *session; | |||||||||
| 1464 | ||||||||||
| 1465 | if ((session = switch_core_session_locate(uuid)switch_core_session_perform_locate(uuid, "src/switch_ivr.c", ( const char *)__func__, 1465))) { | |||||||||
| 1466 | switch_ivr_hold(session, message, moh); | |||||||||
| 1467 | switch_core_session_rwunlock(session); | |||||||||
| 1468 | } | |||||||||
| 1469 | ||||||||||
| 1470 | return SWITCH_STATUS_SUCCESS; | |||||||||
| 1471 | } | |||||||||
| 1472 | ||||||||||
| 1473 | SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_ivr_hold_toggle_uuid(const char *uuid, const char *message, switch_bool_t moh) | |||||||||
| 1474 | { | |||||||||
| 1475 | switch_core_session_t *session; | |||||||||
| 1476 | switch_channel_t *channel; | |||||||||
| 1477 | switch_channel_callstate_t callstate; | |||||||||
| 1478 | ||||||||||
| 1479 | if ((session = switch_core_session_locate(uuid)switch_core_session_perform_locate(uuid, "src/switch_ivr.c", ( const char *)__func__, 1479))) { | |||||||||
| 1480 | if ((channel = switch_core_session_get_channel(session))) { | |||||||||
| 1481 | callstate = switch_channel_get_callstate(channel); | |||||||||
| 1482 | ||||||||||
| 1483 | if (callstate == CCS_ACTIVE) { | |||||||||
| 1484 | switch_ivr_hold(session, message, moh); | |||||||||
| 1485 | } else if (callstate == CCS_HELD) { | |||||||||
| 1486 | switch_ivr_unhold(session); | |||||||||
| 1487 | } | |||||||||
| 1488 | } | |||||||||
| 1489 | switch_core_session_rwunlock(session); | |||||||||
| 1490 | } | |||||||||
| 1491 | ||||||||||
| 1492 | return SWITCH_STATUS_SUCCESS; | |||||||||
| 1493 | } | |||||||||
| 1494 | ||||||||||
| 1495 | SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_ivr_unhold(switch_core_session_t *session) | |||||||||
| 1496 | { | |||||||||
| 1497 | switch_core_session_message_t msg = { 0 }; | |||||||||
| 1498 | switch_channel_t *channel = switch_core_session_get_channel(session); | |||||||||
| 1499 | const char *other_uuid; | |||||||||
| 1500 | switch_core_session_t *b_session; | |||||||||
| 1501 | switch_event_t *event; | |||||||||
| 1502 | ||||||||||
| 1503 | msg.message_id = SWITCH_MESSAGE_INDICATE_UNHOLD; | |||||||||
| 1504 | msg.from = __FILE__"src/switch_ivr.c"; | |||||||||
| 1505 | ||||||||||
| 1506 | switch_channel_clear_flag(channel, CF_HOLD); | |||||||||
| 1507 | switch_channel_clear_flag(channel, CF_SUSPEND); | |||||||||
| 1508 | ||||||||||
| 1509 | switch_core_session_receive_message(session, &msg)switch_core_session_perform_receive_message(session, &msg , "src/switch_ivr.c", (const char *)__func__, 1509); | |||||||||
| 1510 | ||||||||||
| 1511 | ||||||||||
| 1512 | if ((other_uuid = switch_channel_get_partner_uuid(channel)) && (b_session = switch_core_session_locate(other_uuid)switch_core_session_perform_locate(other_uuid, "src/switch_ivr.c" , (const char *)__func__, 1512))) { | |||||||||
| 1513 | switch_channel_t *b_channel = switch_core_session_get_channel(b_session); | |||||||||
| 1514 | switch_channel_stop_broadcast(b_channel)for(;;) {if (switch_channel_test_flag(b_channel, CF_BROADCAST )) {switch_channel_set_flag_value(b_channel, CF_STOP_BROADCAST , 1); switch_channel_set_flag_value(b_channel, CF_BREAK, 1); } break;}; | |||||||||
| 1515 | switch_channel_wait_for_flag(b_channel, CF_BROADCAST, SWITCH_FALSE, 5000, NULL((void*)0)); | |||||||||
| 1516 | switch_core_session_rwunlock(b_session); | |||||||||
| 1517 | } | |||||||||
| 1518 | ||||||||||
| 1519 | ||||||||||
| 1520 | if (switch_event_create(&event, SWITCH_EVENT_CHANNEL_UNHOLD)switch_event_create_subclass_detailed("src/switch_ivr.c", (const char * )(const char *)__func__, 1520, &event, SWITCH_EVENT_CHANNEL_UNHOLD , ((void*)0)) == SWITCH_STATUS_SUCCESS) { | |||||||||
| 1521 | switch_channel_event_set_data(channel, event); | |||||||||
| 1522 | switch_event_fire(&event)switch_event_fire_detailed("src/switch_ivr.c", (const char * ) (const char *)__func__, 1522, &event, ((void*)0)); | |||||||||
| 1523 | } | |||||||||
| 1524 | ||||||||||
| 1525 | return SWITCH_STATUS_SUCCESS; | |||||||||
| 1526 | } | |||||||||
| 1527 | ||||||||||
| 1528 | SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_ivr_unhold_uuid(const char *uuid) | |||||||||
| 1529 | { | |||||||||
| 1530 | switch_core_session_t *session; | |||||||||
| 1531 | ||||||||||
| 1532 | if ((session = switch_core_session_locate(uuid)switch_core_session_perform_locate(uuid, "src/switch_ivr.c", ( const char *)__func__, 1532))) { | |||||||||
| 1533 | switch_ivr_unhold(session); | |||||||||
| 1534 | switch_core_session_rwunlock(session); | |||||||||
| 1535 | } | |||||||||
| 1536 | ||||||||||
| 1537 | return SWITCH_STATUS_SUCCESS; | |||||||||
| 1538 | } | |||||||||
| 1539 | ||||||||||
| 1540 | SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_ivr_media(const char *uuid, switch_media_flag_t flags) | |||||||||
| 1541 | { | |||||||||
| 1542 | const char *other_uuid = NULL((void*)0); | |||||||||
| 1543 | switch_channel_t *channel, *other_channel = NULL((void*)0); | |||||||||
| 1544 | switch_core_session_t *session, *other_session; | |||||||||
| 1545 | switch_core_session_message_t msg = { 0 }; | |||||||||
| 1546 | switch_status_t status = SWITCH_STATUS_GENERR; | |||||||||
| 1547 | uint8_t swap = 0; | |||||||||
| 1548 | switch_frame_t *read_frame = NULL((void*)0); | |||||||||
| 1549 | ||||||||||
| 1550 | msg.message_id = SWITCH_MESSAGE_INDICATE_MEDIA; | |||||||||
| 1551 | msg.from = __FILE__"src/switch_ivr.c"; | |||||||||
| 1552 | ||||||||||
| 1553 | if ((session = switch_core_session_locate(uuid)switch_core_session_perform_locate(uuid, "src/switch_ivr.c", ( const char *)__func__, 1553))) { | |||||||||
| 1554 | channel = switch_core_session_get_channel(session); | |||||||||
| 1555 | ||||||||||
| 1556 | if (switch_channel_test_flag(channel, CF_MEDIA_TRANS)) { | |||||||||
| 1557 | switch_core_session_rwunlock(session); | |||||||||
| 1558 | return SWITCH_STATUS_INUSE; | |||||||||
| 1559 | } | |||||||||
| 1560 | ||||||||||
| 1561 | switch_channel_set_flag(channel, CF_MEDIA_TRANS)switch_channel_set_flag_value(channel, CF_MEDIA_TRANS, 1); | |||||||||
| 1562 | ||||||||||
| 1563 | if ((flags & SMF_REBRIDGE) && !switch_channel_test_flag(channel, CF_BRIDGE_ORIGINATOR)) { | |||||||||
| 1564 | swap = 1; | |||||||||
| 1565 | } | |||||||||
| 1566 | ||||||||||
| 1567 | if (switch_channel_test_flag(channel, CF_PROXY_MODE)) { | |||||||||
| 1568 | status = SWITCH_STATUS_SUCCESS; | |||||||||
| 1569 | ||||||||||
| 1570 | /* If we had early media in bypass mode before, it is no longer relevant */ | |||||||||
| 1571 | if (switch_channel_test_flag(channel, CF_EARLY_MEDIA)) { | |||||||||
| 1572 | switch_core_session_message_t msg2 = { 0 }; | |||||||||
| 1573 | ||||||||||
| 1574 | msg2.message_id = SWITCH_MESSAGE_INDICATE_CLEAR_PROGRESS; | |||||||||
| 1575 | msg2.from = __FILE__"src/switch_ivr.c"; | |||||||||
| 1576 | switch_core_session_receive_message(session, &msg2)switch_core_session_perform_receive_message(session, &msg2 , "src/switch_ivr.c", (const char *)__func__, 1576); | |||||||||
| 1577 | } | |||||||||
| 1578 | ||||||||||
| 1579 | if ((flags & SMF_REPLYONLY_A)) { | |||||||||
| 1580 | msg.numeric_arg = 1; | |||||||||
| 1581 | } | |||||||||
| 1582 | ||||||||||
| 1583 | if (switch_core_session_receive_message(session, &msg)switch_core_session_perform_receive_message(session, &msg , "src/switch_ivr.c", (const char *)__func__, 1583) != SWITCH_STATUS_SUCCESS) { | |||||||||
| 1584 | switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "src/switch_ivr.c", (const char *) __func__, 1584, (const char*)(session), SWITCH_LOG_ERROR, "Can't re-establsh media on %s\n", switch_channel_get_name(channel)); | |||||||||
| 1585 | switch_core_session_rwunlock(session); | |||||||||
| 1586 | return SWITCH_STATUS_GENERR; | |||||||||
| 1587 | } | |||||||||
| 1588 | ||||||||||
| 1589 | if ((flags & SMF_REPLYONLY_B)) { | |||||||||
| 1590 | msg.numeric_arg = 1; | |||||||||
| 1591 | } else { | |||||||||
| 1592 | msg.numeric_arg = 0; | |||||||||
| 1593 | } | |||||||||
| 1594 | ||||||||||
| 1595 | if ((flags & SMF_IMMEDIATE)) { | |||||||||
| 1596 | switch_channel_wait_for_flag(channel, CF_REQ_MEDIA, SWITCH_FALSE, 250, NULL((void*)0)); | |||||||||
| 1597 | switch_yield(250000)switch_sleep(250000);; | |||||||||
| 1598 | } else { | |||||||||
| 1599 | switch_channel_wait_for_flag(channel, CF_REQ_MEDIA, SWITCH_FALSE, 10000, NULL((void*)0)); | |||||||||
| 1600 | switch_channel_wait_for_flag(channel, CF_MEDIA_ACK, SWITCH_TRUE, 10000, NULL((void*)0)); | |||||||||
| 1601 | switch_channel_wait_for_flag(channel, CF_MEDIA_SET, SWITCH_TRUE, 10000, NULL((void*)0)); | |||||||||
| 1602 | switch_core_session_read_frame(session, &read_frame, SWITCH_IO_FLAG_NONE, 0); | |||||||||
| 1603 | } | |||||||||
| 1604 | ||||||||||
| 1605 | if ((flags & SMF_REBRIDGE) | |||||||||
| 1606 | && (other_uuid = switch_channel_get_variable(channel, SWITCH_SIGNAL_BRIDGE_VARIABLE)switch_channel_get_variable_dup(channel, "signal_bridge_to", SWITCH_TRUE , -1)) | |||||||||
| 1607 | && (other_session = switch_core_session_locate(other_uuid)switch_core_session_perform_locate(other_uuid, "src/switch_ivr.c" , (const char *)__func__, 1607))) { | |||||||||
| 1608 | other_channel = switch_core_session_get_channel(other_session); | |||||||||
| 1609 | switch_assert(other_channel != NULL)((other_channel != ((void*)0)) ? (void) (0) : __assert_fail ( "other_channel != ((void*)0)", "src/switch_ivr.c", 1609, __PRETTY_FUNCTION__ )); | |||||||||
| 1610 | switch_core_session_receive_message(other_session, &msg)switch_core_session_perform_receive_message(other_session, & msg, "src/switch_ivr.c", (const char *)__func__, 1610); | |||||||||
| 1611 | switch_channel_wait_for_flag(other_channel, CF_REQ_MEDIA, SWITCH_FALSE, 10000, NULL((void*)0)); | |||||||||
| 1612 | switch_channel_wait_for_flag(other_channel, CF_MEDIA_ACK, SWITCH_TRUE, 10000, NULL((void*)0)); | |||||||||
| 1613 | switch_channel_wait_for_flag(other_channel, CF_MEDIA_SET, SWITCH_TRUE, 10000, NULL((void*)0)); | |||||||||
| 1614 | switch_core_session_read_frame(other_session, &read_frame, SWITCH_IO_FLAG_NONE, 0); | |||||||||
| 1615 | switch_channel_clear_state_handler(other_channel, NULL((void*)0)); | |||||||||
| 1616 | switch_core_session_rwunlock(other_session); | |||||||||
| 1617 | } | |||||||||
| 1618 | if (other_channel) { | |||||||||
| 1619 | switch_channel_clear_state_handler(channel, NULL((void*)0)); | |||||||||
| 1620 | } | |||||||||
| 1621 | } | |||||||||
| 1622 | ||||||||||
| 1623 | switch_channel_clear_flag(channel, CF_MEDIA_TRANS); | |||||||||
| 1624 | switch_core_session_rwunlock(session); | |||||||||
| 1625 | ||||||||||
| 1626 | if (other_channel) { | |||||||||
| 1627 | if (swap) { | |||||||||
| 1628 | switch_ivr_uuid_bridge(other_uuid, uuid); | |||||||||
| 1629 | } else { | |||||||||
| 1630 | switch_ivr_uuid_bridge(uuid, other_uuid); | |||||||||
| 1631 | } | |||||||||
| 1632 | switch_channel_wait_for_flag(channel, CF_BRIDGED, SWITCH_TRUE, 1000, NULL((void*)0)); | |||||||||
| 1633 | switch_channel_wait_for_flag(other_channel, CF_BRIDGED, SWITCH_TRUE, 1000, NULL((void*)0)); | |||||||||
| 1634 | } | |||||||||
| 1635 | } | |||||||||
| 1636 | ||||||||||
| 1637 | return status; | |||||||||
| 1638 | } | |||||||||
| 1639 | ||||||||||
| 1640 | SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_ivr_nomedia(const char *uuid, switch_media_flag_t flags) | |||||||||
| 1641 | { | |||||||||
| 1642 | const char *other_uuid; | |||||||||
| 1643 | switch_channel_t *channel, *other_channel = NULL((void*)0); | |||||||||
| 1644 | switch_core_session_t *session, *other_session = NULL((void*)0); | |||||||||
| 1645 | switch_core_session_message_t msg = { 0 }; | |||||||||
| 1646 | switch_status_t status = SWITCH_STATUS_GENERR; | |||||||||
| 1647 | uint8_t swap = 0; | |||||||||
| 1648 | ||||||||||
| 1649 | msg.message_id = SWITCH_MESSAGE_INDICATE_NOMEDIA; | |||||||||
| 1650 | msg.from = __FILE__"src/switch_ivr.c"; | |||||||||
| 1651 | ||||||||||
| 1652 | if ((session = switch_core_session_locate(uuid)switch_core_session_perform_locate(uuid, "src/switch_ivr.c", ( const char *)__func__, 1652))) { | |||||||||
| 1653 | status = SWITCH_STATUS_SUCCESS; | |||||||||
| 1654 | channel = switch_core_session_get_channel(session); | |||||||||
| 1655 | ||||||||||
| 1656 | if (switch_channel_test_flag(channel, CF_MEDIA_TRANS)) { | |||||||||
| 1657 | switch_core_session_rwunlock(session); | |||||||||
| 1658 | return SWITCH_STATUS_INUSE; | |||||||||
| 1659 | } | |||||||||
| 1660 | ||||||||||
| 1661 | switch_channel_set_flag(channel, CF_MEDIA_TRANS)switch_channel_set_flag_value(channel, CF_MEDIA_TRANS, 1); | |||||||||
| 1662 | ||||||||||
| 1663 | if ((flags & SMF_REBRIDGE) && !switch_channel_test_flag(channel, CF_BRIDGE_ORIGINATOR)) { | |||||||||
| 1664 | swap = 1; | |||||||||
| 1665 | } | |||||||||
| 1666 | ||||||||||
| 1667 | switch_channel_set_flag(channel, CF_REDIRECT)switch_channel_set_flag_value(channel, CF_REDIRECT, 1); | |||||||||
| 1668 | switch_channel_set_flag(channel, CF_RESET)switch_channel_set_flag_value(channel, CF_RESET, 1); | |||||||||
| 1669 | ||||||||||
| 1670 | if ((flags & SMF_FORCE) || !switch_channel_test_flag(channel, CF_PROXY_MODE)) { | |||||||||
| 1671 | if ((flags & SMF_REBRIDGE) && (other_uuid = switch_channel_get_variable(channel, SWITCH_BRIDGE_VARIABLE)switch_channel_get_variable_dup(channel, "bridge_to", SWITCH_TRUE , -1)) && | |||||||||
| 1672 | (other_session = switch_core_session_locate(other_uuid)switch_core_session_perform_locate(other_uuid, "src/switch_ivr.c" , (const char *)__func__, 1672))) { | |||||||||
| 1673 | other_channel = switch_core_session_get_channel(other_session); | |||||||||
| 1674 | ||||||||||
| 1675 | switch_channel_set_flag(other_channel, CF_RESET)switch_channel_set_flag_value(other_channel, CF_RESET, 1); | |||||||||
| 1676 | switch_channel_set_flag(other_channel, CF_REDIRECT)switch_channel_set_flag_value(other_channel, CF_REDIRECT, 1); | |||||||||
| 1677 | ||||||||||
| 1678 | if (!switch_core_session_in_thread(session)) { | |||||||||
| 1679 | switch_channel_set_state(channel, CS_PARK)switch_channel_perform_set_state(channel, "src/switch_ivr.c", (const char *)__func__, 1679, CS_PARK); | |||||||||
| 1680 | } | |||||||||
| 1681 | switch_channel_set_state(other_channel, CS_PARK)switch_channel_perform_set_state(other_channel, "src/switch_ivr.c" , (const char *)__func__, 1681, CS_PARK); | |||||||||
| 1682 | if (switch_core_session_in_thread(session)) { | |||||||||
| 1683 | switch_yield(100000)switch_sleep(100000);; | |||||||||
| 1684 | } else { | |||||||||
| 1685 | switch_channel_wait_for_state(other_channel, channel, CS_PARK); | |||||||||
| 1686 | } | |||||||||
| 1687 | switch_core_session_receive_message(other_session, &msg)switch_core_session_perform_receive_message(other_session, & msg, "src/switch_ivr.c", (const char *)__func__, 1687); | |||||||||
| 1688 | switch_channel_wait_for_flag(other_channel, CF_REQ_MEDIA, SWITCH_FALSE, 10000, NULL((void*)0)); | |||||||||
| 1689 | //switch_channel_wait_for_flag(other_channel, CF_MEDIA_ACK, SWITCH_TRUE, 10000, NULL); | |||||||||
| 1690 | switch_channel_wait_for_flag(other_channel, CF_MEDIA_SET, SWITCH_TRUE, 10000, NULL((void*)0)); | |||||||||
| 1691 | } | |||||||||
| 1692 | ||||||||||
| 1693 | switch_core_session_receive_message(session, &msg)switch_core_session_perform_receive_message(session, &msg , "src/switch_ivr.c", (const char *)__func__, 1693); | |||||||||
| 1694 | ||||||||||
| 1695 | if (other_channel) { | |||||||||
| 1696 | if (!switch_core_session_in_thread(session)) { | |||||||||
| 1697 | switch_channel_wait_for_state(channel, NULL((void*)0), CS_PARK); | |||||||||
| 1698 | switch_channel_wait_for_flag(channel, CF_REQ_MEDIA, SWITCH_FALSE, 10000, NULL((void*)0)); | |||||||||
| 1699 | switch_channel_wait_for_flag(channel, CF_MEDIA_ACK, SWITCH_TRUE, 10000, NULL((void*)0)); | |||||||||
| 1700 | switch_channel_wait_for_flag(channel, CF_MEDIA_SET, SWITCH_TRUE, 10000, NULL((void*)0)); | |||||||||
| 1701 | } | |||||||||
| 1702 | ||||||||||
| 1703 | if (swap) { | |||||||||
| 1704 | switch_ivr_signal_bridge(other_session, session); | |||||||||
| 1705 | } else { | |||||||||
| 1706 | switch_ivr_signal_bridge(session, other_session); | |||||||||
| 1707 | } | |||||||||
| 1708 | ||||||||||
| 1709 | if (switch_core_session_in_thread(session)) { | |||||||||
| 1710 | switch_yield(100000)switch_sleep(100000);; | |||||||||
| 1711 | } else { | |||||||||
| 1712 | switch_channel_wait_for_state(other_channel, channel, CS_HIBERNATE); | |||||||||
| 1713 | } | |||||||||
| 1714 | ||||||||||
| 1715 | if (!switch_core_session_in_thread(session)) { | |||||||||
| 1716 | switch_channel_wait_for_state(channel, other_channel, CS_HIBERNATE); | |||||||||
| 1717 | } | |||||||||
| 1718 | switch_core_session_rwunlock(other_session); | |||||||||
| 1719 | } | |||||||||
| 1720 | } | |||||||||
| 1721 | ||||||||||
| 1722 | switch_channel_clear_flag(channel, CF_MEDIA_TRANS); | |||||||||
| 1723 | switch_core_session_rwunlock(session); | |||||||||
| 1724 | } | |||||||||
| 1725 | ||||||||||
| 1726 | ||||||||||
| 1727 | ||||||||||
| 1728 | return status; | |||||||||
| 1729 | } | |||||||||
| 1730 | ||||||||||
| 1731 | SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_ivr_session_transfer(switch_core_session_t *session, const char *extension, const char *dialplan, | |||||||||
| 1732 | const char *context) | |||||||||
| 1733 | { | |||||||||
| 1734 | switch_channel_t *channel = switch_core_session_get_channel(session); | |||||||||
| 1735 | switch_caller_profile_t *profile, *new_profile; | |||||||||
| 1736 | switch_core_session_message_t msg = { 0 }; | |||||||||
| 1737 | switch_core_session_t *other_session; | |||||||||
| 1738 | switch_channel_t *other_channel = NULL((void*)0); | |||||||||
| 1739 | const char *uuid = NULL((void*)0); | |||||||||
| 1740 | const char *max_forwards; | |||||||||
| 1741 | const char *forwardvar = switch_channel_get_variable(channel, SWITCH_MAX_FORWARDS_VARIABLE)switch_channel_get_variable_dup(channel, "max_forwards", SWITCH_TRUE , -1); | |||||||||
| 1742 | int forwardval = 70; | |||||||||
| 1743 | const char *use_dialplan = dialplan, *use_context = context; | |||||||||
| 1744 | ||||||||||
| 1745 | if (!zstr(forwardvar)_zstr(forwardvar)) { | |||||||||
| 1746 | forwardval = atoi(forwardvar) - 1; | |||||||||
| 1747 | } | |||||||||
| 1748 | if (forwardval <= 0) { | |||||||||
| 1749 | switch_channel_hangup(channel, SWITCH_CAUSE_EXCHANGE_ROUTING_ERROR)switch_channel_perform_hangup(channel, "src/switch_ivr.c", (const char *)__func__, 1749, SWITCH_CAUSE_EXCHANGE_ROUTING_ERROR); | |||||||||
| 1750 | return SWITCH_STATUS_FALSE; | |||||||||
| 1751 | } | |||||||||
| 1752 | ||||||||||
| 1753 | max_forwards = switch_core_session_sprintf(session, "%d", forwardval); | |||||||||
| 1754 | switch_channel_set_variable(channel, SWITCH_MAX_FORWARDS_VARIABLE, max_forwards)switch_channel_set_variable_var_check(channel, "max_forwards" , max_forwards, SWITCH_TRUE); | |||||||||
| 1755 | ||||||||||
| 1756 | switch_core_session_reset(session, SWITCH_TRUE, SWITCH_TRUE); | |||||||||
| 1757 | switch_channel_clear_flag(channel, CF_ORIGINATING); | |||||||||
| 1758 | ||||||||||
| 1759 | /* clear all state handlers */ | |||||||||
| 1760 | switch_channel_clear_state_handler(channel, NULL((void*)0)); | |||||||||
| 1761 | ||||||||||
| 1762 | /* reset temp hold music */ | |||||||||
| 1763 | switch_channel_set_variable(channel, SWITCH_TEMP_HOLD_MUSIC_VARIABLE, NULL)switch_channel_set_variable_var_check(channel, "temp_hold_music" , ((void*)0), SWITCH_TRUE); | |||||||||
| 1764 | ||||||||||
| 1765 | if ((profile = switch_channel_get_caller_profile(channel))) { | |||||||||
| 1766 | const char *var; | |||||||||
| 1767 | ||||||||||
| 1768 | if (zstr(dialplan)_zstr(dialplan) && (var = switch_channel_get_variable(channel, "force_transfer_dialplan")switch_channel_get_variable_dup(channel, "force_transfer_dialplan" , SWITCH_TRUE, -1))) { | |||||||||
| 1769 | use_dialplan = var; | |||||||||
| 1770 | } | |||||||||
| 1771 | ||||||||||
| 1772 | if (zstr(context)_zstr(context) && (var = switch_channel_get_variable(channel, "force_transfer_context")switch_channel_get_variable_dup(channel, "force_transfer_context" , SWITCH_TRUE, -1))) { | |||||||||
| 1773 | use_context = var; | |||||||||
| 1774 | } | |||||||||
| 1775 | ||||||||||
| 1776 | if (zstr(use_dialplan)_zstr(use_dialplan)) { | |||||||||
| 1777 | use_dialplan = profile->dialplan; | |||||||||
| 1778 | if (!zstr(use_dialplan)_zstr(use_dialplan) && !strcasecmp(use_dialplan, "inline")) { | |||||||||
| 1779 | use_dialplan = NULL((void*)0); | |||||||||
| 1780 | } | |||||||||
| 1781 | } | |||||||||
| 1782 | ||||||||||
| 1783 | if (zstr(use_context)_zstr(use_context)) { | |||||||||
| 1784 | use_context = profile->context; | |||||||||
| 1785 | } | |||||||||
| 1786 | ||||||||||
| 1787 | if (zstr(use_dialplan)_zstr(use_dialplan)) { | |||||||||
| 1788 | use_dialplan = "XML"; | |||||||||
| 1789 | } | |||||||||
| 1790 | ||||||||||
| 1791 | if (zstr(use_context)_zstr(use_context)) { | |||||||||
| 1792 | use_context = "default"; | |||||||||
| 1793 | } | |||||||||
| 1794 | ||||||||||
| 1795 | if (zstr(extension)_zstr(extension)) { | |||||||||
| 1796 | extension = "service"; | |||||||||
| 1797 | } | |||||||||
| 1798 | ||||||||||
| 1799 | new_profile = switch_caller_profile_clone(session, profile); | |||||||||
| 1800 | ||||||||||
| 1801 | new_profile->dialplan = switch_core_strdup(new_profile->pool, use_dialplan)switch_core_perform_strdup(new_profile->pool, use_dialplan , "src/switch_ivr.c", (const char *)__func__, 1801); | |||||||||
| 1802 | new_profile->context = switch_core_strdup(new_profile->pool, use_context)switch_core_perform_strdup(new_profile->pool, use_context, "src/switch_ivr.c", (const char *)__func__, 1802); | |||||||||
| 1803 | new_profile->destination_number = switch_core_strdup(new_profile->pool, extension)switch_core_perform_strdup(new_profile->pool, extension, "src/switch_ivr.c" , (const char *)__func__, 1803); | |||||||||
| 1804 | new_profile->rdnis = switch_core_strdup(new_profile->pool, profile->destination_number)switch_core_perform_strdup(new_profile->pool, profile-> destination_number, "src/switch_ivr.c", (const char *)__func__ , 1804); | |||||||||
| 1805 | ||||||||||
| 1806 | switch_channel_set_variable(channel, SWITCH_SIGNAL_BOND_VARIABLE, NULL)switch_channel_set_variable_var_check(channel, "signal_bond", ((void*)0), SWITCH_TRUE); | |||||||||
| 1807 | ||||||||||
| 1808 | /* Set CF_TRANSFER flag before hanging up bleg to avoid race condition */ | |||||||||
| 1809 | switch_channel_set_flag(channel, CF_TRANSFER)switch_channel_set_flag_value(channel, CF_TRANSFER, 1); | |||||||||
| 1810 | ||||||||||
| 1811 | /* If HANGUP_AFTER_BRIDGE is set to 'true', SWITCH_SIGNAL_BRIDGE_VARIABLE | |||||||||
| 1812 | * will not have a value, so we need to check SWITCH_BRIDGE_VARIABLE */ | |||||||||
| 1813 | ||||||||||
| 1814 | uuid = switch_channel_get_variable(channel, SWITCH_SIGNAL_BRIDGE_VARIABLE)switch_channel_get_variable_dup(channel, "signal_bridge_to", SWITCH_TRUE , -1); | |||||||||
| 1815 | ||||||||||
| 1816 | if (!uuid) { | |||||||||
| 1817 | uuid = switch_channel_get_variable(channel, SWITCH_BRIDGE_VARIABLE)switch_channel_get_variable_dup(channel, "bridge_to", SWITCH_TRUE , -1); | |||||||||
| 1818 | } | |||||||||
| 1819 | ||||||||||
| 1820 | if (uuid && (other_session = switch_core_session_locate(uuid)switch_core_session_perform_locate(uuid, "src/switch_ivr.c", ( const char *)__func__, 1820))) { | |||||||||
| 1821 | other_channel = switch_core_session_get_channel(other_session); | |||||||||
| 1822 | switch_channel_set_variable(other_channel, SWITCH_SIGNAL_BOND_VARIABLE, NULL)switch_channel_set_variable_var_check(other_channel, "signal_bond" , ((void*)0), SWITCH_TRUE); | |||||||||
| 1823 | switch_core_session_rwunlock(other_session); | |||||||||
| 1824 | } | |||||||||
| 1825 | ||||||||||
| 1826 | if ((uuid = switch_channel_get_variable(channel, SWITCH_SIGNAL_BRIDGE_VARIABLE)switch_channel_get_variable_dup(channel, "signal_bridge_to", SWITCH_TRUE , -1)) | |||||||||
| 1827 | && (other_session = switch_core_session_locate(uuid)switch_core_session_perform_locate(uuid, "src/switch_ivr.c", ( const char *)__func__, 1827))) { | |||||||||
| 1828 | other_channel = switch_core_session_get_channel(other_session); | |||||||||
| 1829 | ||||||||||
| 1830 | switch_channel_set_variable(channel, SWITCH_SIGNAL_BRIDGE_VARIABLE, NULL)switch_channel_set_variable_var_check(channel, "signal_bridge_to" , ((void*)0), SWITCH_TRUE); | |||||||||
| 1831 | switch_channel_set_variable(other_channel, SWITCH_SIGNAL_BRIDGE_VARIABLE, NULL)switch_channel_set_variable_var_check(other_channel, "signal_bridge_to" , ((void*)0), SWITCH_TRUE); | |||||||||
| 1832 | ||||||||||
| 1833 | switch_channel_set_variable(channel, SWITCH_BRIDGE_VARIABLE, NULL)switch_channel_set_variable_var_check(channel, "bridge_to", ( (void*)0), SWITCH_TRUE); | |||||||||
| 1834 | switch_channel_set_variable(other_channel, SWITCH_BRIDGE_VARIABLE, NULL)switch_channel_set_variable_var_check(other_channel, "bridge_to" , ((void*)0), SWITCH_TRUE); | |||||||||
| 1835 | ||||||||||
| 1836 | /* If we are transferring the CALLER out of the bridge, we do not want to hang up on them */ | |||||||||
| 1837 | switch_channel_set_variable(channel, SWITCH_HANGUP_AFTER_BRIDGE_VARIABLE, "false")switch_channel_set_variable_var_check(channel, "hangup_after_bridge" , "false", SWITCH_TRUE); | |||||||||
| 1838 | ||||||||||
| 1839 | switch_channel_hangup(other_channel, SWITCH_CAUSE_BLIND_TRANSFER)switch_channel_perform_hangup(other_channel, "src/switch_ivr.c" , (const char *)__func__, 1839, SWITCH_CAUSE_BLIND_TRANSFER); | |||||||||
| 1840 | switch_ivr_media(uuid, SMF_NONE); | |||||||||
| 1841 | ||||||||||
| 1842 | switch_core_session_rwunlock(other_session); | |||||||||
| 1843 | } | |||||||||
| 1844 | ||||||||||
| 1845 | switch_channel_set_caller_profile(channel, new_profile); | |||||||||
| 1846 | ||||||||||
| 1847 | switch_channel_set_state(channel, CS_ROUTING)switch_channel_perform_set_state(channel, "src/switch_ivr.c", (const char *)__func__, 1847, CS_ROUTING); | |||||||||
| 1848 | switch_channel_audio_sync(channel)switch_channel_perform_audio_sync(channel, "src/switch_ivr.c" , (const char *)__func__, 1848); | |||||||||
| 1849 | ||||||||||
| 1850 | msg.message_id = SWITCH_MESSAGE_INDICATE_TRANSFER; | |||||||||
| 1851 | msg.from = __FILE__"src/switch_ivr.c"; | |||||||||
| 1852 | switch_core_session_receive_message(session, &msg)switch_core_session_perform_receive_message(session, &msg , "src/switch_ivr.c", (const char *)__func__, 1852); | |||||||||
| 1853 | ||||||||||
| 1854 | switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "src/switch_ivr.c", (const char *) __func__, 1854, (const char*)(session), SWITCH_LOG_NOTICE, "Transfer %s to %s[%s@%s]\n", switch_channel_get_name(channel), use_dialplan, | |||||||||
| 1855 | extension, use_context); | |||||||||
| 1856 | ||||||||||
| 1857 | ||||||||||
| 1858 | new_profile->transfer_source = switch_core_sprintf(new_profile->pool, "%ld:%s:bl_xfer:%s/%s/%s", | |||||||||
| 1859 | (long) switch_epoch_time_now(NULL((void*)0)), new_profile->uuid_str, | |||||||||
| 1860 | extension, use_context, use_dialplan); | |||||||||
| 1861 | switch_channel_add_variable_var_check(channel, SWITCH_TRANSFER_HISTORY_VARIABLE"transfer_history", new_profile->transfer_source, SWITCH_FALSE, SWITCH_STACK_PUSH); | |||||||||
| 1862 | switch_channel_set_variable_var_check(channel, SWITCH_TRANSFER_SOURCE_VARIABLE"transfer_source", new_profile->transfer_source, SWITCH_FALSE); | |||||||||
| 1863 | return SWITCH_STATUS_SUCCESS; | |||||||||
| 1864 | } | |||||||||
| 1865 | ||||||||||
| 1866 | return SWITCH_STATUS_FALSE; | |||||||||
| 1867 | } | |||||||||
| 1868 | ||||||||||
| 1869 | SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_ivr_transfer_variable(switch_core_session_t *sessa, switch_core_session_t *sessb, char *var) | |||||||||
| 1870 | { | |||||||||
| 1871 | switch_channel_t *chana = switch_core_session_get_channel(sessa); | |||||||||
| 1872 | switch_channel_t *chanb = switch_core_session_get_channel(sessb); | |||||||||
| 1873 | switch_event_t *var_event; | |||||||||
| 1874 | ||||||||||
| 1875 | const char *val = NULL((void*)0); | |||||||||
| 1876 | uint8_t prefix = 0; | |||||||||
| 1877 | ||||||||||
| 1878 | if (var && *var == '~') { | |||||||||
| 1879 | var++; | |||||||||
| 1880 | prefix = 1; | |||||||||
| 1881 | } | |||||||||
| 1882 | ||||||||||
| 1883 | if (var && !prefix) { | |||||||||
| 1884 | if ((val = switch_channel_get_variable(chana, var)switch_channel_get_variable_dup(chana, var, SWITCH_TRUE, -1))) { | |||||||||
| 1885 | switch_channel_set_variable(chanb, var, val)switch_channel_set_variable_var_check(chanb, var, val, SWITCH_TRUE ); | |||||||||
| 1886 | } | |||||||||
| 1887 | } else { | |||||||||
| 1888 | switch_event_header_t *hi; | |||||||||
| 1889 | ||||||||||
| 1890 | switch_channel_get_variables(chana, &var_event); | |||||||||
| 1891 | ||||||||||
| 1892 | for (hi = var_event->headers; hi; hi = hi->next) { | |||||||||
| 1893 | char *vvar = hi->name; | |||||||||
| 1894 | char *vval = hi->value; | |||||||||
| 1895 | if (vvar && vval && (!prefix || (var && !strncmp((char *) vvar, var, strlen(var))(__extension__ (__builtin_constant_p (strlen(var)) && ((__builtin_constant_p ((char *) vvar) && strlen ((char *) vvar) < ((size_t) (strlen(var)))) || (__builtin_constant_p (var) && strlen (var) < ((size_t) (strlen(var)))) ) ? __extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p ((char *) vvar) && __builtin_constant_p (var) && (__s1_len = __builtin_strlen ((char *) vvar), __s2_len = __builtin_strlen (var), (!((size_t)(const void *)(((char *) vvar) + 1) - (size_t )(const void *)((char *) vvar) == 1) || __s1_len >= 4) && (!((size_t)(const void *)((var) + 1) - (size_t)(const void * )(var) == 1) || __s2_len >= 4)) ? __builtin_strcmp ((char * ) vvar, var) : (__builtin_constant_p ((char *) vvar) && ((size_t)(const void *)(((char *) vvar) + 1) - (size_t)(const void *)((char *) vvar) == 1) && (__s1_len = __builtin_strlen ((char *) vvar), __s1_len < 4) ? (__builtin_constant_p (var ) && ((size_t)(const void *)((var) + 1) - (size_t)(const void *)(var) == 1) ? __builtin_strcmp ((char *) vvar, var) : (__extension__ ({ const unsigned char *__s2 = (const unsigned char *) (const char *) (var); int __result = (((const unsigned char *) (const char *) ((char *) vvar))[0] - __s2[0]); if (__s1_len > 0 && __result == 0) { __result = (((const unsigned char *) (const char *) ((char *) vvar))[1] - __s2[1]); if (__s1_len > 1 && __result == 0) { __result = (((const unsigned char *) (const char *) ((char *) vvar))[2] - __s2[2]); if (__s1_len > 2 && __result == 0) __result = (((const unsigned char *) (const char *) ((char *) vvar))[3] - __s2[3]); } } __result ; }))) : (__builtin_constant_p (var) && ((size_t)(const void *)((var) + 1) - (size_t)(const void *)(var) == 1) && (__s2_len = __builtin_strlen (var), __s2_len < 4) ? (__builtin_constant_p ((char *) vvar) && ((size_t)(const void *)(((char *) vvar) + 1) - (size_t)(const void *)((char *) vvar) == 1) ? __builtin_strcmp ((char *) vvar, var) : (- (__extension__ ({ const unsigned char *__s2 = (const unsigned char *) (const char *) ((char *) vvar ); int __result = (((const unsigned char *) (const char *) (var ))[0] - __s2[0]); if (__s2_len > 0 && __result == 0 ) { __result = (((const unsigned char *) (const char *) (var) )[1] - __s2[1]); if (__s2_len > 1 && __result == 0 ) { __result = (((const unsigned char *) (const char *) (var) )[2] - __s2[2]); if (__s2_len > 2 && __result == 0 ) __result = (((const unsigned char *) (const char *) (var))[ 3] - __s2[3]); } } __result; })))) : __builtin_strcmp ((char * ) vvar, var)))); }) : strncmp ((char *) vvar, var, strlen(var ))))))) { | |||||||||
| 1896 | switch_channel_set_variable(chanb, (char *) vvar, (char *) vval)switch_channel_set_variable_var_check(chanb, (char *) vvar, ( char *) vval, SWITCH_TRUE); | |||||||||
| 1897 | } | |||||||||
| 1898 | } | |||||||||
| 1899 | ||||||||||
| 1900 | switch_event_destroy(&var_event); | |||||||||
| 1901 | } | |||||||||
| 1902 | ||||||||||
| 1903 | return SWITCH_STATUS_SUCCESS; | |||||||||
| 1904 | } | |||||||||
| 1905 | ||||||||||
| 1906 | /******************************************************************************************************/ | |||||||||
| 1907 | ||||||||||
| 1908 | struct switch_ivr_digit_stream_parser { | |||||||||
| 1909 | int pool_auto_created; | |||||||||
| 1910 | switch_memory_pool_t *pool; | |||||||||
| 1911 | switch_hash_t *hash; | |||||||||
| 1912 | switch_size_t maxlen; | |||||||||
| 1913 | switch_size_t buflen; | |||||||||
| 1914 | switch_size_t minlen; | |||||||||
| 1915 | char terminator; | |||||||||
| 1916 | unsigned int digit_timeout_ms; | |||||||||
| 1917 | }; | |||||||||
| 1918 | ||||||||||
| 1919 | struct switch_ivr_digit_stream { | |||||||||
| 1920 | char *digits; | |||||||||
| 1921 | switch_time_t last_digit_time; | |||||||||
| 1922 | }; | |||||||||
| 1923 | ||||||||||
| 1924 | SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_ivr_digit_stream_parser_new(switch_memory_pool_t *pool, switch_ivr_digit_stream_parser_t ** parser) | |||||||||
| 1925 | { | |||||||||
| 1926 | switch_status_t status = SWITCH_STATUS_FALSE; | |||||||||
| 1927 | ||||||||||
| 1928 | if (parser != NULL((void*)0)) { | |||||||||
| 1929 | int pool_auto_created = 0; | |||||||||
| 1930 | ||||||||||
| 1931 | /* if the caller didn't provide a pool, make one */ | |||||||||
| 1932 | if (pool == NULL((void*)0)) { | |||||||||
| 1933 | switch_core_new_memory_pool(&pool)switch_core_perform_new_memory_pool(&pool, "src/switch_ivr.c" , (const char *)__func__, 1933); | |||||||||
| 1934 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_ivr.c", (const char *)__func__ , 1934, ((void*)0), SWITCH_LOG_DEBUG, "created a memory pool\n"); | |||||||||
| 1935 | if (pool != NULL((void*)0)) { | |||||||||
| 1936 | pool_auto_created = 1; | |||||||||
| 1937 | } | |||||||||
| 1938 | } | |||||||||
| 1939 | /* if we have a pool, make a parser object */ | |||||||||
| 1940 | if (pool != NULL((void*)0)) { | |||||||||
| 1941 | *parser = (switch_ivr_digit_stream_parser_t *) switch_core_alloc(pool, sizeof(switch_ivr_digit_stream_parser_t))switch_core_perform_alloc(pool, sizeof(switch_ivr_digit_stream_parser_t ), "src/switch_ivr.c", (const char *)__func__, 1941); | |||||||||
| 1942 | } | |||||||||
| 1943 | /* if we have parser object, initialize it for the caller */ | |||||||||
| 1944 | if (pool && *parser != NULL((void*)0)) { | |||||||||
| 1945 | memset(*parser, 0, sizeof(switch_ivr_digit_stream_parser_t)); | |||||||||
| 1946 | (*parser)->pool_auto_created = pool_auto_created; | |||||||||
| 1947 | (*parser)->pool = pool; | |||||||||
| 1948 | (*parser)->digit_timeout_ms = 1000; | |||||||||
| 1949 | switch_core_hash_init(&(*parser)->hash)switch_core_hash_init_case(&(*parser)->hash, SWITCH_TRUE ); | |||||||||
| 1950 | ||||||||||
| 1951 | status = SWITCH_STATUS_SUCCESS; | |||||||||
| 1952 | } else { | |||||||||
| 1953 | status = SWITCH_STATUS_MEMERR; | |||||||||
| 1954 | /* if we can't create a parser object,clean up the pool if we created it */ | |||||||||
| 1955 | if (pool != NULL((void*)0) && pool_auto_created) { | |||||||||
| 1956 | switch_core_destroy_memory_pool(&pool)switch_core_perform_destroy_memory_pool(&pool, "src/switch_ivr.c" , (const char *)__func__, 1956); | |||||||||
| 1957 | } | |||||||||
| 1958 | } | |||||||||
| 1959 | } | |||||||||
| 1960 | ||||||||||
| 1961 | return status; | |||||||||
| 1962 | } | |||||||||
| 1963 | ||||||||||
| 1964 | SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_ivr_digit_stream_parser_destroy(switch_ivr_digit_stream_parser_t *parser) | |||||||||
| 1965 | { | |||||||||
| 1966 | switch_status_t status = SWITCH_STATUS_FALSE; | |||||||||
| 1967 | ||||||||||
| 1968 | if (parser != NULL((void*)0)) { | |||||||||
| 1969 | if (parser->hash != NULL((void*)0)) { | |||||||||
| 1970 | switch_core_hash_destroy(&parser->hash); | |||||||||
| 1971 | parser->hash = NULL((void*)0); | |||||||||
| 1972 | } | |||||||||
| 1973 | /* free the memory pool if we created it */ | |||||||||
| 1974 | if (parser->pool_auto_created && parser->pool != NULL((void*)0)) { | |||||||||
| 1975 | status = switch_core_destroy_memory_pool(&parser->pool)switch_core_perform_destroy_memory_pool(&parser->pool, "src/switch_ivr.c", (const char *)__func__, 1975); | |||||||||
| 1976 | } | |||||||||
| 1977 | } | |||||||||
| 1978 | ||||||||||
| 1979 | return status; | |||||||||
| 1980 | } | |||||||||
| 1981 | ||||||||||
| 1982 | SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_ivr_digit_stream_new(switch_ivr_digit_stream_parser_t *parser, switch_ivr_digit_stream_t ** stream) | |||||||||
| 1983 | { | |||||||||
| 1984 | switch_status_t status = SWITCH_STATUS_FALSE; | |||||||||
| 1985 | ||||||||||
| 1986 | /* if we have a parser object memory pool and a stream object pointer that is null */ | |||||||||
| 1987 | if (parser && stream && *stream == NULL((void*)0)) { | |||||||||
| 1988 | *stream = (switch_ivr_digit_stream_t *) malloc(sizeof(**stream)); | |||||||||
| 1989 | switch_assert(*stream)((*stream) ? (void) (0) : __assert_fail ("*stream", "src/switch_ivr.c" , 1989, __PRETTY_FUNCTION__)); | |||||||||
| 1990 | memset(*stream, 0, sizeof(**stream)); | |||||||||
| 1991 | switch_zmalloc((*stream)->digits, parser->buflen + 1)(void)(((((*stream)->digits = calloc(1, (parser->buflen + 1)))) ? (void) (0) : __assert_fail ("((*stream)->digits = calloc(1, (parser->buflen + 1)))" , "src/switch_ivr.c", 1991, __PRETTY_FUNCTION__)),(*stream)-> digits); | |||||||||
| 1992 | status = SWITCH_STATUS_SUCCESS; | |||||||||
| 1993 | } | |||||||||
| 1994 | ||||||||||
| 1995 | return status; | |||||||||
| 1996 | } | |||||||||
| 1997 | ||||||||||
| 1998 | SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_ivr_digit_stream_destroy(switch_ivr_digit_stream_t ** stream) | |||||||||
| 1999 | { | |||||||||
| 2000 | switch_status_t status = SWITCH_STATUS_FALSE; | |||||||||
| 2001 | ||||||||||
| 2002 | if (*stream) { | |||||||||
| 2003 | switch_safe_free((*stream)->digits)if ((*stream)->digits) {free((*stream)->digits);(*stream )->digits=((void*)0);}; | |||||||||
| 2004 | free(*stream); | |||||||||
| 2005 | *stream = NULL((void*)0); | |||||||||
| 2006 | status = SWITCH_STATUS_SUCCESS; | |||||||||
| 2007 | } | |||||||||
| 2008 | ||||||||||
| 2009 | return status; | |||||||||
| 2010 | } | |||||||||
| 2011 | ||||||||||
| 2012 | SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_ivr_digit_stream_parser_set_event(switch_ivr_digit_stream_parser_t *parser, char *digits, void *data) | |||||||||
| 2013 | { | |||||||||
| 2014 | switch_status_t status = SWITCH_STATUS_FALSE; | |||||||||
| 2015 | ||||||||||
| 2016 | if (parser != NULL((void*)0) && digits != NULL((void*)0) && *digits && parser->hash != NULL((void*)0)) { | |||||||||
| 2017 | ||||||||||
| 2018 | status = switch_core_hash_insert(parser->hash, digits, data)switch_core_hash_insert_destructor(parser->hash, digits, data , ((void*)0)); | |||||||||
| 2019 | if (status == SWITCH_STATUS_SUCCESS) { | |||||||||
| 2020 | switch_size_t len = strlen(digits); | |||||||||
| 2021 | ||||||||||
| 2022 | /* if we don't have a terminator, then we have to try and | |||||||||
| 2023 | * figure out when a digit set is completed, therefore we | |||||||||
| 2024 | * keep track of the min and max digit lengths | |||||||||
| 2025 | */ | |||||||||
| 2026 | ||||||||||
| 2027 | if (len > parser->buflen) { | |||||||||
| 2028 | parser->buflen = len; | |||||||||
| 2029 | } | |||||||||
| 2030 | ||||||||||
| 2031 | if (parser->terminator == '\0') { | |||||||||
| 2032 | if (len > parser->maxlen) { | |||||||||
| 2033 | parser->maxlen = len; | |||||||||
| 2034 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_ivr.c", (const char *)__func__ , 2034, ((void*)0), SWITCH_LOG_DEBUG, "max len %u\n", (uint32_t) parser->maxlen); | |||||||||
| 2035 | } | |||||||||
| 2036 | if (parser->minlen == 0 || len < parser->minlen) { | |||||||||
| 2037 | parser->minlen = len; | |||||||||
| 2038 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_ivr.c", (const char *)__func__ , 2038, ((void*)0), SWITCH_LOG_DEBUG, "min len %u\n", (uint32_t) parser->minlen); | |||||||||
| 2039 | } | |||||||||
| 2040 | } else { | |||||||||
| 2041 | /* since we have a terminator, reset min and max */ | |||||||||
| 2042 | parser->minlen = 0; | |||||||||
| 2043 | parser->maxlen = 0; | |||||||||
| 2044 | } | |||||||||
| 2045 | } | |||||||||
| 2046 | } | |||||||||
| 2047 | if (status != SWITCH_STATUS_SUCCESS) { | |||||||||
| 2048 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_ivr.c", (const char *)__func__ , 2048, ((void*)0), SWITCH_LOG_DEBUG, "unable to add hash for '%s'\n", digits); | |||||||||
| 2049 | } | |||||||||
| 2050 | ||||||||||
| 2051 | return status; | |||||||||
| 2052 | } | |||||||||
| 2053 | ||||||||||
| 2054 | SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_ivr_digit_stream_parser_del_event(switch_ivr_digit_stream_parser_t *parser, char *digits) | |||||||||
| 2055 | { | |||||||||
| 2056 | switch_status_t status = SWITCH_STATUS_FALSE; | |||||||||
| 2057 | ||||||||||
| 2058 | if (parser != NULL((void*)0) && digits != NULL((void*)0) && *digits) { | |||||||||
| 2059 | status = switch_core_hash_delete(parser->hash, digits); | |||||||||
| 2060 | } | |||||||||
| 2061 | ||||||||||
| 2062 | if (status != SWITCH_STATUS_SUCCESS) { | |||||||||
| 2063 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_ivr.c", (const char *)__func__ , 2063, ((void*)0), SWITCH_LOG_DEBUG, "unable to del hash for '%s'\n", digits); | |||||||||
| 2064 | } | |||||||||
| 2065 | ||||||||||
| 2066 | return status; | |||||||||
| 2067 | } | |||||||||
| 2068 | ||||||||||
| 2069 | SWITCH_DECLARE(void *)__attribute__((visibility("default"))) void * switch_ivr_digit_stream_parser_feed(switch_ivr_digit_stream_parser_t *parser, switch_ivr_digit_stream_t *stream, char digit) | |||||||||
| 2070 | { | |||||||||
| 2071 | void *result = NULL((void*)0); | |||||||||
| 2072 | switch_size_t len; | |||||||||
| 2073 | ||||||||||
| 2074 | switch_assert(parser)((parser) ? (void) (0) : __assert_fail ("parser", "src/switch_ivr.c" , 2074, __PRETTY_FUNCTION__)); | |||||||||
| 2075 | switch_assert(stream)((stream) ? (void) (0) : __assert_fail ("stream", "src/switch_ivr.c" , 2075, __PRETTY_FUNCTION__)); | |||||||||
| 2076 | switch_assert(stream->digits)((stream->digits) ? (void) (0) : __assert_fail ("stream->digits" , "src/switch_ivr.c", 2076, __PRETTY_FUNCTION__)); | |||||||||
| 2077 | ||||||||||
| 2078 | len = strlen(stream->digits); | |||||||||
| 2079 | ||||||||||
| 2080 | /* handle new digit arrivals */ | |||||||||
| 2081 | if (digit) { | |||||||||
| 2082 | /* if it's not a terminator digit, add it to the collected digits */ | |||||||||
| 2083 | if (digit != parser->terminator) { | |||||||||
| 2084 | /* if collected digits length >= the max length of the keys | |||||||||
| 2085 | * in the hash table, then left shift the digit string | |||||||||
| 2086 | */ | |||||||||
| 2087 | if (len > 0 && parser->maxlen != 0 && len >= parser->maxlen) { | |||||||||
| 2088 | char *src = stream->digits + 1; | |||||||||
| 2089 | char *dst = stream->digits; | |||||||||
| 2090 | ||||||||||
| 2091 | while (*src) { | |||||||||
| 2092 | *(dst++) = *(src++); | |||||||||
| 2093 | } | |||||||||
| 2094 | *dst = digit; | |||||||||
| 2095 | } else { | |||||||||
| 2096 | *(stream->digits + (len++)) = digit; | |||||||||
| 2097 | *(stream->digits + len) = '\0'; | |||||||||
| 2098 | stream->last_digit_time = switch_micro_time_now() / 1000; | |||||||||
| 2099 | } | |||||||||
| 2100 | } | |||||||||
| 2101 | } | |||||||||
| 2102 | ||||||||||
| 2103 | /* don't allow collected digit string testing if there are varying sized keys until timeout */ | |||||||||
| 2104 | if (parser->maxlen - parser->minlen > 0 && (switch_micro_time_now() / 1000) - stream->last_digit_time < parser->digit_timeout_ms) { | |||||||||
| 2105 | len = 0; | |||||||||
| 2106 | } | |||||||||
| 2107 | /* if we have digits to test */ | |||||||||
| 2108 | if (len) { | |||||||||
| 2109 | result = switch_core_hash_find(parser->hash, stream->digits); | |||||||||
| 2110 | /* if we matched the digit string, or this digit is the terminator | |||||||||
| 2111 | * reset the collected digits for next digit string | |||||||||
| 2112 | */ | |||||||||
| 2113 | if (result != NULL((void*)0) || parser->terminator == digit) { | |||||||||
| 2114 | *stream->digits = '\0'; | |||||||||
| 2115 | } | |||||||||
| 2116 | } | |||||||||
| 2117 | ||||||||||
| 2118 | ||||||||||
| 2119 | return result; | |||||||||
| 2120 | } | |||||||||
| 2121 | ||||||||||
| 2122 | SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_ivr_digit_stream_reset(switch_ivr_digit_stream_t *stream) | |||||||||
| 2123 | { | |||||||||
| 2124 | switch_status_t status = SWITCH_STATUS_FALSE; | |||||||||
| 2125 | switch_assert(stream)((stream) ? (void) (0) : __assert_fail ("stream", "src/switch_ivr.c" , 2125, __PRETTY_FUNCTION__)); | |||||||||
| 2126 | switch_assert(stream->digits)((stream->digits) ? (void) (0) : __assert_fail ("stream->digits" , "src/switch_ivr.c", 2126, __PRETTY_FUNCTION__)); | |||||||||
| 2127 | ||||||||||
| 2128 | *stream->digits = '\0'; | |||||||||
| 2129 | stream->last_digit_time = 0; | |||||||||
| 2130 | status = SWITCH_STATUS_SUCCESS; | |||||||||
| 2131 | ||||||||||
| 2132 | return status; | |||||||||
| 2133 | } | |||||||||
| 2134 | ||||||||||
| 2135 | SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_ivr_digit_stream_parser_set_terminator(switch_ivr_digit_stream_parser_t *parser, char digit) | |||||||||
| 2136 | { | |||||||||
| 2137 | switch_status_t status = SWITCH_STATUS_FALSE; | |||||||||
| 2138 | ||||||||||
| 2139 | if (parser != NULL((void*)0)) { | |||||||||
| 2140 | parser->terminator = digit; | |||||||||
| 2141 | /* since we have a terminator, reset min and max */ | |||||||||
| 2142 | parser->minlen = 0; | |||||||||
| 2143 | parser->maxlen = 0; | |||||||||
| 2144 | status = SWITCH_STATUS_SUCCESS; | |||||||||
| 2145 | } | |||||||||
| 2146 | ||||||||||
| 2147 | return status; | |||||||||
| 2148 | } | |||||||||
| 2149 | ||||||||||
| 2150 | SWITCH_DECLARE(int)__attribute__((visibility("default"))) int switch_ivr_set_xml_profile_data(switch_xml_t xml, switch_caller_profile_t *caller_profile, int off) | |||||||||
| 2151 | { | |||||||||
| 2152 | switch_xml_t param; | |||||||||
| 2153 | ||||||||||
| 2154 | if (!(param = switch_xml_add_child_d(xml, "username", off++)switch_xml_set_flag(switch_xml_add_child(xml, (__extension__ ( __builtin_constant_p ("username") && ((size_t)(const void *)(("username") + 1) - (size_t)(const void *)("username") == 1) ? (((const char *) ("username"))[0] == '\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len = strlen ("username" ) + 1; char *__retval = (char *) malloc (__len); if (__retval != ((void*)0)) __retval = (char *) memcpy (__retval, "username" , __len); __retval; })) : __strdup ("username"))), off++), SWITCH_XML_NAMEM ))) { | |||||||||
| ||||||||||
| 2155 | return -1; | |||||||||
| 2156 | } | |||||||||
| 2157 | switch_xml_set_txt_d(param, caller_profile->username)switch_xml_set_flag(switch_xml_set_txt(param, (__extension__ ( __builtin_constant_p (caller_profile->username) && ((size_t)(const void *)((caller_profile->username) + 1) - (size_t)(const void *)(caller_profile->username) == 1) ? ( ((const char *) (caller_profile->username))[0] == '\0' ? ( char *) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len = strlen (caller_profile->username) + 1; char *__retval = (char *) malloc (__len); if (__retval != ((void*)0)) __retval = (char *) memcpy (__retval, caller_profile->username, __len); __retval ; })) : __strdup (caller_profile->username)))), SWITCH_XML_TXTM ); | |||||||||
| 2158 | ||||||||||
| 2159 | if (!(param = switch_xml_add_child_d(xml, "dialplan", off++)switch_xml_set_flag(switch_xml_add_child(xml, (__extension__ ( __builtin_constant_p ("dialplan") && ((size_t)(const void *)(("dialplan") + 1) - (size_t)(const void *)("dialplan") == 1) ? (((const char *) ("dialplan"))[0] == '\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len = strlen ("dialplan" ) + 1; char *__retval = (char *) malloc (__len); if (__retval != ((void*)0)) __retval = (char *) memcpy (__retval, "dialplan" , __len); __retval; })) : __strdup ("dialplan"))), off++), SWITCH_XML_NAMEM ))) { | |||||||||
| 2160 | return -1; | |||||||||
| 2161 | } | |||||||||
| 2162 | switch_xml_set_txt_d(param, caller_profile->dialplan)switch_xml_set_flag(switch_xml_set_txt(param, (__extension__ ( __builtin_constant_p (caller_profile->dialplan) && ((size_t)(const void *)((caller_profile->dialplan) + 1) - (size_t)(const void *)(caller_profile->dialplan) == 1) ? ( ((const char *) (caller_profile->dialplan))[0] == '\0' ? ( char *) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len = strlen (caller_profile->dialplan) + 1; char *__retval = (char *) malloc (__len); if (__retval != ((void*)0)) __retval = (char *) memcpy (__retval, caller_profile->dialplan, __len); __retval ; })) : __strdup (caller_profile->dialplan)))), SWITCH_XML_TXTM ); | |||||||||
| 2163 | ||||||||||
| 2164 | if (!(param = switch_xml_add_child_d(xml, "caller_id_name", off++)switch_xml_set_flag(switch_xml_add_child(xml, (__extension__ ( __builtin_constant_p ("caller_id_name") && ((size_t)( const void *)(("caller_id_name") + 1) - (size_t)(const void * )("caller_id_name") == 1) ? (((const char *) ("caller_id_name" ))[0] == '\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len = strlen ("caller_id_name") + 1; char *__retval = (char *) malloc (__len); if (__retval != ((void*)0)) __retval = (char *) memcpy (__retval, "caller_id_name", __len); __retval ; })) : __strdup ("caller_id_name"))), off++), SWITCH_XML_NAMEM ))) { | |||||||||
| 2165 | return -1; | |||||||||
| 2166 | } | |||||||||
| 2167 | switch_xml_set_txt_d(param, caller_profile->caller_id_name)switch_xml_set_flag(switch_xml_set_txt(param, (__extension__ ( __builtin_constant_p (caller_profile->caller_id_name) && ((size_t)(const void *)((caller_profile->caller_id_name) + 1) - (size_t)(const void *)(caller_profile->caller_id_name ) == 1) ? (((const char *) (caller_profile->caller_id_name ))[0] == '\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len = strlen (caller_profile->caller_id_name) + 1 ; char *__retval = (char *) malloc (__len); if (__retval != ( (void*)0)) __retval = (char *) memcpy (__retval, caller_profile ->caller_id_name, __len); __retval; })) : __strdup (caller_profile ->caller_id_name)))), SWITCH_XML_TXTM); | |||||||||
| 2168 | ||||||||||
| 2169 | if (!(param = switch_xml_add_child_d(xml, "caller_id_number", off++)switch_xml_set_flag(switch_xml_add_child(xml, (__extension__ ( __builtin_constant_p ("caller_id_number") && ((size_t )(const void *)(("caller_id_number") + 1) - (size_t)(const void *)("caller_id_number") == 1) ? (((const char *) ("caller_id_number" ))[0] == '\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len = strlen ("caller_id_number") + 1; char *__retval = (char *) malloc (__len); if (__retval != ((void*)0)) __retval = (char *) memcpy (__retval, "caller_id_number", __len); __retval ; })) : __strdup ("caller_id_number"))), off++), SWITCH_XML_NAMEM ))) { | |||||||||
| ||||||||||
| 2170 | return -1; | |||||||||
| 2171 | } | |||||||||
| 2172 | switch_xml_set_txt_d(param, caller_profile->caller_id_number)switch_xml_set_flag(switch_xml_set_txt(param, (__extension__ ( __builtin_constant_p (caller_profile->caller_id_number) && ((size_t)(const void *)((caller_profile->caller_id_number ) + 1) - (size_t)(const void *)(caller_profile->caller_id_number ) == 1) ? (((const char *) (caller_profile->caller_id_number ))[0] == '\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len = strlen (caller_profile->caller_id_number) + 1; char *__retval = (char *) malloc (__len); if (__retval != ((void*)0)) __retval = (char *) memcpy (__retval, caller_profile ->caller_id_number, __len); __retval; })) : __strdup (caller_profile ->caller_id_number)))), SWITCH_XML_TXTM); | |||||||||
| 2173 | ||||||||||
| 2174 | if (!(param = switch_xml_add_child_d(xml, "callee_id_name", off++)switch_xml_set_flag(switch_xml_add_child(xml, (__extension__ ( __builtin_constant_p ("callee_id_name") && ((size_t)( const void *)(("callee_id_name") + 1) - (size_t)(const void * )("callee_id_name") == 1) ? (((const char *) ("callee_id_name" ))[0] == '\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len = strlen ("callee_id_name") + 1; char *__retval = (char *) malloc (__len); if (__retval != ((void*)0)) __retval = (char *) memcpy (__retval, "callee_id_name", __len); __retval ; })) : __strdup ("callee_id_name"))), off++), SWITCH_XML_NAMEM ))) { | |||||||||
| 2175 | return -1; | |||||||||
| 2176 | } | |||||||||
| 2177 | switch_xml_set_txt_d(param, caller_profile->callee_id_name)switch_xml_set_flag(switch_xml_set_txt(param, (__extension__ ( __builtin_constant_p (caller_profile->callee_id_name) && ((size_t)(const void *)((caller_profile->callee_id_name) + 1) - (size_t)(const void *)(caller_profile->callee_id_name ) == 1) ? (((const char *) (caller_profile->callee_id_name ))[0] == '\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len = strlen (caller_profile->callee_id_name) + 1 ; char *__retval = (char *) malloc (__len); if (__retval != ( (void*)0)) __retval = (char *) memcpy (__retval, caller_profile ->callee_id_name, __len); __retval; })) : __strdup (caller_profile ->callee_id_name)))), SWITCH_XML_TXTM); | |||||||||
| 2178 | ||||||||||
| 2179 | if (!(param = switch_xml_add_child_d(xml, "callee_id_number", off++)switch_xml_set_flag(switch_xml_add_child(xml, (__extension__ ( __builtin_constant_p ("callee_id_number") && ((size_t )(const void *)(("callee_id_number") + 1) - (size_t)(const void *)("callee_id_number") == 1) ? (((const char *) ("callee_id_number" ))[0] == '\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len = strlen ("callee_id_number") + 1; char *__retval = (char *) malloc (__len); if (__retval != ((void*)0)) __retval = (char *) memcpy (__retval, "callee_id_number", __len); __retval ; })) : __strdup ("callee_id_number"))), off++), SWITCH_XML_NAMEM ))) { | |||||||||
| 2180 | return -1; | |||||||||
| 2181 | } | |||||||||
| 2182 | switch_xml_set_txt_d(param, caller_profile->callee_id_number)switch_xml_set_flag(switch_xml_set_txt(param, (__extension__ ( __builtin_constant_p (caller_profile->callee_id_number) && ((size_t)(const void *)((caller_profile->callee_id_number ) + 1) - (size_t)(const void *)(caller_profile->callee_id_number ) == 1) ? (((const char *) (caller_profile->callee_id_number ))[0] == '\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len = strlen (caller_profile->callee_id_number) + 1; char *__retval = (char *) malloc (__len); if (__retval != ((void*)0)) __retval = (char *) memcpy (__retval, caller_profile ->callee_id_number, __len); __retval; })) : __strdup (caller_profile ->callee_id_number)))), SWITCH_XML_TXTM); | |||||||||
| 2183 | ||||||||||
| 2184 | if (!(param = switch_xml_add_child_d(xml, "ani", off++)switch_xml_set_flag(switch_xml_add_child(xml, (__extension__ ( __builtin_constant_p ("ani") && ((size_t)(const void * )(("ani") + 1) - (size_t)(const void *)("ani") == 1) ? (((const char *) ("ani"))[0] == '\0' ? (char *) calloc ((size_t) 1, ( size_t) 1) : ({ size_t __len = strlen ("ani") + 1; char *__retval = (char *) malloc (__len); if (__retval != ((void*)0)) __retval = (char *) memcpy (__retval, "ani", __len); __retval; })) : __strdup ("ani"))), off++), SWITCH_XML_NAMEM))) { | |||||||||
| 2185 | return -1; | |||||||||
| 2186 | } | |||||||||
| 2187 | switch_xml_set_txt_d(param, caller_profile->ani)switch_xml_set_flag(switch_xml_set_txt(param, (__extension__ ( __builtin_constant_p (caller_profile->ani) && ((size_t )(const void *)((caller_profile->ani) + 1) - (size_t)(const void *)(caller_profile->ani) == 1) ? (((const char *) (caller_profile ->ani))[0] == '\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len = strlen (caller_profile->ani) + 1; char *__retval = (char *) malloc (__len); if (__retval != ((void* )0)) __retval = (char *) memcpy (__retval, caller_profile-> ani, __len); __retval; })) : __strdup (caller_profile->ani )))), SWITCH_XML_TXTM); | |||||||||
| 2188 | ||||||||||
| 2189 | if (!(param = switch_xml_add_child_d(xml, "aniii", off++)switch_xml_set_flag(switch_xml_add_child(xml, (__extension__ ( __builtin_constant_p ("aniii") && ((size_t)(const void *)(("aniii") + 1) - (size_t)(const void *)("aniii") == 1) ? ( ((const char *) ("aniii"))[0] == '\0' ? (char *) calloc ((size_t ) 1, (size_t) 1) : ({ size_t __len = strlen ("aniii") + 1; char *__retval = (char *) malloc (__len); if (__retval != ((void* )0)) __retval = (char *) memcpy (__retval, "aniii", __len); __retval ; })) : __strdup ("aniii"))), off++), SWITCH_XML_NAMEM))) { | |||||||||
| 2190 | return -1; | |||||||||
| 2191 | } | |||||||||
| 2192 | switch_xml_set_txt_d(param, caller_profile->aniii)switch_xml_set_flag(switch_xml_set_txt(param, (__extension__ ( __builtin_constant_p (caller_profile->aniii) && (( size_t)(const void *)((caller_profile->aniii) + 1) - (size_t )(const void *)(caller_profile->aniii) == 1) ? (((const char *) (caller_profile->aniii))[0] == '\0' ? (char *) calloc ( (size_t) 1, (size_t) 1) : ({ size_t __len = strlen (caller_profile ->aniii) + 1; char *__retval = (char *) malloc (__len); if (__retval != ((void*)0)) __retval = (char *) memcpy (__retval , caller_profile->aniii, __len); __retval; })) : __strdup ( caller_profile->aniii)))), SWITCH_XML_TXTM); | |||||||||
| 2193 | ||||||||||
| 2194 | ||||||||||
| 2195 | if (!(param = switch_xml_add_child_d(xml, "network_addr", off++)switch_xml_set_flag(switch_xml_add_child(xml, (__extension__ ( __builtin_constant_p ("network_addr") && ((size_t)(const void *)(("network_addr") + 1) - (size_t)(const void *)("network_addr" ) == 1) ? (((const char *) ("network_addr"))[0] == '\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len = strlen ("network_addr") + 1; char *__retval = (char *) malloc (__len ); if (__retval != ((void*)0)) __retval = (char *) memcpy (__retval , "network_addr", __len); __retval; })) : __strdup ("network_addr" ))), off++), SWITCH_XML_NAMEM))) { | |||||||||
| 2196 | return -1; | |||||||||
| 2197 | } | |||||||||
| 2198 | switch_xml_set_txt_d(param, caller_profile->network_addr)switch_xml_set_flag(switch_xml_set_txt(param, (__extension__ ( __builtin_constant_p (caller_profile->network_addr) && ((size_t)(const void *)((caller_profile->network_addr) + 1 ) - (size_t)(const void *)(caller_profile->network_addr) == 1) ? (((const char *) (caller_profile->network_addr))[0] == '\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len = strlen (caller_profile->network_addr) + 1; char *__retval = (char *) malloc (__len); if (__retval != ((void*)0)) __retval = (char *) memcpy (__retval, caller_profile->network_addr , __len); __retval; })) : __strdup (caller_profile->network_addr )))), SWITCH_XML_TXTM); | |||||||||
| 2199 | ||||||||||
| 2200 | if (!(param = switch_xml_add_child_d(xml, "rdnis", off++)switch_xml_set_flag(switch_xml_add_child(xml, (__extension__ ( __builtin_constant_p ("rdnis") && ((size_t)(const void *)(("rdnis") + 1) - (size_t)(const void *)("rdnis") == 1) ? ( ((const char *) ("rdnis"))[0] == '\0' ? (char *) calloc ((size_t ) 1, (size_t) 1) : ({ size_t __len = strlen ("rdnis") + 1; char *__retval = (char *) malloc (__len); if (__retval != ((void* )0)) __retval = (char *) memcpy (__retval, "rdnis", __len); __retval ; })) : __strdup ("rdnis"))), off++), SWITCH_XML_NAMEM))) { | |||||||||
| 2201 | return -1; | |||||||||
| 2202 | } | |||||||||
| 2203 | switch_xml_set_txt_d(param, caller_profile->rdnis)switch_xml_set_flag(switch_xml_set_txt(param, (__extension__ ( __builtin_constant_p (caller_profile->rdnis) && (( size_t)(const void *)((caller_profile->rdnis) + 1) - (size_t )(const void *)(caller_profile->rdnis) == 1) ? (((const char *) (caller_profile->rdnis))[0] == '\0' ? (char *) calloc ( (size_t) 1, (size_t) 1) : ({ size_t __len = strlen (caller_profile ->rdnis) + 1; char *__retval = (char *) malloc (__len); if (__retval != ((void*)0)) __retval = (char *) memcpy (__retval , caller_profile->rdnis, __len); __retval; })) : __strdup ( caller_profile->rdnis)))), SWITCH_XML_TXTM); | |||||||||
| 2204 | ||||||||||
| 2205 | if (!(param = switch_xml_add_child_d(xml, "destination_number", off++)switch_xml_set_flag(switch_xml_add_child(xml, (__extension__ ( __builtin_constant_p ("destination_number") && ((size_t )(const void *)(("destination_number") + 1) - (size_t)(const void *)("destination_number") == 1) ? (((const char *) ("destination_number" ))[0] == '\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len = strlen ("destination_number") + 1; char *__retval = (char *) malloc (__len); if (__retval != ((void*)0)) __retval = (char *) memcpy (__retval, "destination_number", __len); __retval ; })) : __strdup ("destination_number"))), off++), SWITCH_XML_NAMEM ))) { | |||||||||
| 2206 | return -1; | |||||||||
| 2207 | } | |||||||||
| 2208 | switch_xml_set_txt_d(param, caller_profile->destination_number)switch_xml_set_flag(switch_xml_set_txt(param, (__extension__ ( __builtin_constant_p (caller_profile->destination_number) && ((size_t)(const void *)((caller_profile->destination_number ) + 1) - (size_t)(const void *)(caller_profile->destination_number ) == 1) ? (((const char *) (caller_profile->destination_number ))[0] == '\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len = strlen (caller_profile->destination_number ) + 1; char *__retval = (char *) malloc (__len); if (__retval != ((void*)0)) __retval = (char *) memcpy (__retval, caller_profile ->destination_number, __len); __retval; })) : __strdup (caller_profile ->destination_number)))), SWITCH_XML_TXTM); | |||||||||
| 2209 | ||||||||||
| 2210 | if (!(param = switch_xml_add_child_d(xml, "uuid", off++)switch_xml_set_flag(switch_xml_add_child(xml, (__extension__ ( __builtin_constant_p ("uuid") && ((size_t)(const void *)(("uuid") + 1) - (size_t)(const void *)("uuid") == 1) ? (( (const char *) ("uuid"))[0] == '\0' ? (char *) calloc ((size_t ) 1, (size_t) 1) : ({ size_t __len = strlen ("uuid") + 1; char *__retval = (char *) malloc (__len); if (__retval != ((void* )0)) __retval = (char *) memcpy (__retval, "uuid", __len); __retval ; })) : __strdup ("uuid"))), off++), SWITCH_XML_NAMEM))) { | |||||||||
| 2211 | return -1; | |||||||||
| 2212 | } | |||||||||
| 2213 | switch_xml_set_txt_d(param, caller_profile->uuid)switch_xml_set_flag(switch_xml_set_txt(param, (__extension__ ( __builtin_constant_p (caller_profile->uuid) && ((size_t )(const void *)((caller_profile->uuid) + 1) - (size_t)(const void *)(caller_profile->uuid) == 1) ? (((const char *) (caller_profile ->uuid))[0] == '\0' ? (char *) calloc ((size_t) 1, (size_t ) 1) : ({ size_t __len = strlen (caller_profile->uuid) + 1 ; char *__retval = (char *) malloc (__len); if (__retval != ( (void*)0)) __retval = (char *) memcpy (__retval, caller_profile ->uuid, __len); __retval; })) : __strdup (caller_profile-> uuid)))), SWITCH_XML_TXTM); | |||||||||
| 2214 | ||||||||||
| 2215 | if (!(param = switch_xml_add_child_d(xml, "source", off++)switch_xml_set_flag(switch_xml_add_child(xml, (__extension__ ( __builtin_constant_p ("source") && ((size_t)(const void *)(("source") + 1) - (size_t)(const void *)("source") == 1) ? (((const char *) ("source"))[0] == '\0' ? (char *) calloc (( size_t) 1, (size_t) 1) : ({ size_t __len = strlen ("source") + 1; char *__retval = (char *) malloc (__len); if (__retval != ((void*)0)) __retval = (char *) memcpy (__retval, "source", __len ); __retval; })) : __strdup ("source"))), off++), SWITCH_XML_NAMEM ))) { | |||||||||
| 2216 | return -1; | |||||||||
| 2217 | } | |||||||||
| 2218 | switch_xml_set_txt_d(param, caller_profile->source)switch_xml_set_flag(switch_xml_set_txt(param, (__extension__ ( __builtin_constant_p (caller_profile->source) && ( (size_t)(const void *)((caller_profile->source) + 1) - (size_t )(const void *)(caller_profile->source) == 1) ? (((const char *) (caller_profile->source))[0] == '\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len = strlen (caller_profile ->source) + 1; char *__retval = (char *) malloc (__len); if (__retval != ((void*)0)) __retval = (char *) memcpy (__retval , caller_profile->source, __len); __retval; })) : __strdup (caller_profile->source)))), SWITCH_XML_TXTM); | |||||||||
| 2219 | ||||||||||
| 2220 | if (caller_profile->transfer_source) { | |||||||||
| 2221 | if (!(param = switch_xml_add_child_d(xml, "transfer_source", off++)switch_xml_set_flag(switch_xml_add_child(xml, (__extension__ ( __builtin_constant_p ("transfer_source") && ((size_t) (const void *)(("transfer_source") + 1) - (size_t)(const void *)("transfer_source") == 1) ? (((const char *) ("transfer_source" ))[0] == '\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len = strlen ("transfer_source") + 1; char *__retval = (char *) malloc (__len); if (__retval != ((void*)0)) __retval = (char *) memcpy (__retval, "transfer_source", __len); __retval ; })) : __strdup ("transfer_source"))), off++), SWITCH_XML_NAMEM ))) { | |||||||||
| 2222 | return -1; | |||||||||
| 2223 | } | |||||||||
| 2224 | switch_xml_set_txt_d(param, caller_profile->transfer_source)switch_xml_set_flag(switch_xml_set_txt(param, (__extension__ ( __builtin_constant_p (caller_profile->transfer_source) && ((size_t)(const void *)((caller_profile->transfer_source) + 1) - (size_t)(const void *)(caller_profile->transfer_source ) == 1) ? (((const char *) (caller_profile->transfer_source ))[0] == '\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len = strlen (caller_profile->transfer_source) + 1; char *__retval = (char *) malloc (__len); if (__retval != ((void*)0)) __retval = (char *) memcpy (__retval, caller_profile ->transfer_source, __len); __retval; })) : __strdup (caller_profile ->transfer_source)))), SWITCH_XML_TXTM); | |||||||||
| 2225 | } | |||||||||
| 2226 | ||||||||||
| 2227 | if (!(param = switch_xml_add_child_d(xml, "context", off++)switch_xml_set_flag(switch_xml_add_child(xml, (__extension__ ( __builtin_constant_p ("context") && ((size_t)(const void *)(("context") + 1) - (size_t)(const void *)("context") == 1 ) ? (((const char *) ("context"))[0] == '\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len = strlen ("context" ) + 1; char *__retval = (char *) malloc (__len); if (__retval != ((void*)0)) __retval = (char *) memcpy (__retval, "context" , __len); __retval; })) : __strdup ("context"))), off++), SWITCH_XML_NAMEM ))) { | |||||||||
| 2228 | return -1; | |||||||||
| 2229 | } | |||||||||
| 2230 | switch_xml_set_txt_d(param, caller_profile->context)switch_xml_set_flag(switch_xml_set_txt(param, (__extension__ ( __builtin_constant_p (caller_profile->context) && ( (size_t)(const void *)((caller_profile->context) + 1) - (size_t )(const void *)(caller_profile->context) == 1) ? (((const char *) (caller_profile->context))[0] == '\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len = strlen (caller_profile ->context) + 1; char *__retval = (char *) malloc (__len); if (__retval != ((void*)0)) __retval = (char *) memcpy (__retval , caller_profile->context, __len); __retval; })) : __strdup (caller_profile->context)))), SWITCH_XML_TXTM); | |||||||||
| 2231 | ||||||||||
| 2232 | if (!(param = switch_xml_add_child_d(xml, "chan_name", off++)switch_xml_set_flag(switch_xml_add_child(xml, (__extension__ ( __builtin_constant_p ("chan_name") && ((size_t)(const void *)(("chan_name") + 1) - (size_t)(const void *)("chan_name" ) == 1) ? (((const char *) ("chan_name"))[0] == '\0' ? (char * ) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len = strlen ( "chan_name") + 1; char *__retval = (char *) malloc (__len); if (__retval != ((void*)0)) __retval = (char *) memcpy (__retval , "chan_name", __len); __retval; })) : __strdup ("chan_name") )), off++), SWITCH_XML_NAMEM))) { | |||||||||
| 2233 | return -1; | |||||||||
| 2234 | } | |||||||||
| 2235 | switch_xml_set_txt_d(param, caller_profile->chan_name)switch_xml_set_flag(switch_xml_set_txt(param, (__extension__ ( __builtin_constant_p (caller_profile->chan_name) && ((size_t)(const void *)((caller_profile->chan_name) + 1) - (size_t)(const void *)(caller_profile->chan_name) == 1) ? (((const char *) (caller_profile->chan_name))[0] == '\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len = strlen (caller_profile->chan_name) + 1; char *__retval = ( char *) malloc (__len); if (__retval != ((void*)0)) __retval = (char *) memcpy (__retval, caller_profile->chan_name, __len ); __retval; })) : __strdup (caller_profile->chan_name)))) , SWITCH_XML_TXTM); | |||||||||
| 2236 | ||||||||||
| 2237 | ||||||||||
| 2238 | if (caller_profile->soft) { | |||||||||
| 2239 | profile_node_t *pn; | |||||||||
| 2240 | ||||||||||
| 2241 | for (pn = caller_profile->soft; pn; pn = pn->next) { | |||||||||
| 2242 | ||||||||||
| 2243 | if (!(param = switch_xml_add_child_d(xml, pn->var, off++)switch_xml_set_flag(switch_xml_add_child(xml, (__extension__ ( __builtin_constant_p (pn->var) && ((size_t)(const void *)((pn->var) + 1) - (size_t)(const void *)(pn->var) == 1) ? (((const char *) (pn->var))[0] == '\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len = strlen (pn-> var) + 1; char *__retval = (char *) malloc (__len); if (__retval != ((void*)0)) __retval = (char *) memcpy (__retval, pn-> var, __len); __retval; })) : __strdup (pn->var))), off++), SWITCH_XML_NAMEM))) { | |||||||||
| 2244 | return -1; | |||||||||
| 2245 | } | |||||||||
| 2246 | switch_xml_set_txt_d(param, pn->val)switch_xml_set_flag(switch_xml_set_txt(param, (__extension__ ( __builtin_constant_p (pn->val) && ((size_t)(const void *)((pn->val) + 1) - (size_t)(const void *)(pn->val) == 1) ? (((const char *) (pn->val))[0] == '\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len = strlen (pn-> val) + 1; char *__retval = (char *) malloc (__len); if (__retval != ((void*)0)) __retval = (char *) memcpy (__retval, pn-> val, __len); __retval; })) : __strdup (pn->val)))), SWITCH_XML_TXTM ); | |||||||||
| 2247 | } | |||||||||
| 2248 | ||||||||||
| 2249 | } | |||||||||
| 2250 | ||||||||||
| 2251 | ||||||||||
| 2252 | return off; | |||||||||
| 2253 | } | |||||||||
| 2254 | ||||||||||
| 2255 | static int switch_ivr_set_xml_chan_var(switch_xml_t xml, const char *var, const char *val, int off) | |||||||||
| 2256 | { | |||||||||
| 2257 | char *data; | |||||||||
| 2258 | switch_size_t dlen = strlen(val) * 3 + 1; | |||||||||
| 2259 | switch_xml_t variable; | |||||||||
| 2260 | ||||||||||
| 2261 | if (!val) val = ""; | |||||||||
| 2262 | ||||||||||
| 2263 | if (!zstr(var)_zstr(var) && ((variable = switch_xml_add_child_d(xml, var, off++)switch_xml_set_flag(switch_xml_add_child(xml, (__extension__ ( __builtin_constant_p (var) && ((size_t)(const void *) ((var) + 1) - (size_t)(const void *)(var) == 1) ? (((const char *) (var))[0] == '\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len = strlen (var) + 1; char *__retval = (char *) malloc (__len); if (__retval != ((void*)0)) __retval = (char *) memcpy (__retval, var, __len); __retval; })) : __strdup ( var))), off++), SWITCH_XML_NAMEM)))) { | |||||||||
| 2264 | if ((data = malloc(dlen))) { | |||||||||
| 2265 | memset(data, 0, dlen); | |||||||||
| 2266 | switch_url_encode(val, data, dlen); | |||||||||
| 2267 | switch_xml_set_txt_d(variable, data)switch_xml_set_flag(switch_xml_set_txt(variable, (__extension__ (__builtin_constant_p (data) && ((size_t)(const void *)((data) + 1) - (size_t)(const void *)(data) == 1) ? (((const char *) (data))[0] == '\0' ? (char *) calloc ((size_t) 1, (size_t ) 1) : ({ size_t __len = strlen (data) + 1; char *__retval = ( char *) malloc (__len); if (__retval != ((void*)0)) __retval = (char *) memcpy (__retval, data, __len); __retval; })) : __strdup (data)))), SWITCH_XML_TXTM); | |||||||||
| 2268 | free(data); | |||||||||
| 2269 | } else abort(); | |||||||||
| 2270 | } | |||||||||
| 2271 | ||||||||||
| 2272 | return off; | |||||||||
| 2273 | ||||||||||
| 2274 | } | |||||||||
| 2275 | ||||||||||
| 2276 | ||||||||||
| 2277 | SWITCH_DECLARE(int)__attribute__((visibility("default"))) int switch_ivr_set_xml_chan_vars(switch_xml_t xml, switch_channel_t *channel, int off) | |||||||||
| 2278 | { | |||||||||
| 2279 | ||||||||||
| 2280 | switch_event_header_t *hi = switch_channel_variable_first(channel); | |||||||||
| 2281 | ||||||||||
| 2282 | if (!hi) | |||||||||
| 2283 | return off; | |||||||||
| 2284 | ||||||||||
| 2285 | for (; hi; hi = hi->next) { | |||||||||
| 2286 | if (hi->idx) { | |||||||||
| 2287 | int i; | |||||||||
| 2288 | ||||||||||
| 2289 | for (i = 0; i < hi->idx; i++) { | |||||||||
| 2290 | off = switch_ivr_set_xml_chan_var(xml, hi->name, hi->array[i], off); | |||||||||
| 2291 | } | |||||||||
| 2292 | } else { | |||||||||
| 2293 | off = switch_ivr_set_xml_chan_var(xml, hi->name, hi->value, off); | |||||||||
| 2294 | } | |||||||||
| 2295 | } | |||||||||
| 2296 | switch_channel_variable_last(channel); | |||||||||
| 2297 | ||||||||||
| 2298 | return off; | |||||||||
| 2299 | } | |||||||||
| 2300 | ||||||||||
| 2301 | SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_ivr_generate_xml_cdr(switch_core_session_t *session, switch_xml_t *xml_cdr) | |||||||||
| 2302 | { | |||||||||
| 2303 | switch_channel_t *channel = switch_core_session_get_channel(session); | |||||||||
| 2304 | switch_caller_profile_t *caller_profile; | |||||||||
| 2305 | switch_xml_t variables, cdr, x_main_cp, x_caller_profile, x_caller_extension, x_times, time_tag, | |||||||||
| 2306 | x_application, x_callflow, x_inner_extension, x_apps, x_o, x_channel_data, x_field, xhr, x_hold; | |||||||||
| 2307 | switch_app_log_t *app_log; | |||||||||
| 2308 | char tmp[512], *f; | |||||||||
| 2309 | int cdr_off = 0, v_off = 0, cd_off = 0; | |||||||||
| 2310 | switch_hold_record_t *hold_record = switch_channel_get_hold_record(channel), *hr; | |||||||||
| 2311 | ||||||||||
| 2312 | if (*xml_cdr) { | |||||||||
| 2313 | cdr = *xml_cdr; | |||||||||
| 2314 | } else { | |||||||||
| 2315 | if (!(cdr = switch_xml_new("cdr"))) { | |||||||||
| 2316 | return SWITCH_STATUS_SUCCESS; | |||||||||
| 2317 | } | |||||||||
| 2318 | } | |||||||||
| 2319 | ||||||||||
| 2320 | switch_xml_set_attr_d(cdr, "core-uuid", switch_core_get_uuid())switch_xml_set_attr(switch_xml_set_flag(cdr, SWITCH_XML_DUP), (__extension__ (__builtin_constant_p ("core-uuid") && ((size_t)(const void *)(("core-uuid") + 1) - (size_t)(const void *)("core-uuid") == 1) ? (((const char *) ("core-uuid"))[0] == '\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len = strlen ("core-uuid") + 1; char *__retval = (char *) malloc (__len); if (__retval != ((void*)0)) __retval = (char *) memcpy (__retval, "core-uuid", __len); __retval; })) : __strdup ("core-uuid" ))), (__extension__ (__builtin_constant_p ((switch_core_get_uuid () ? switch_core_get_uuid() : "")) && ((size_t)(const void *)(((switch_core_get_uuid() ? switch_core_get_uuid() : "" )) + 1) - (size_t)(const void *)((switch_core_get_uuid() ? switch_core_get_uuid () : "")) == 1) ? (((const char *) ((switch_core_get_uuid() ? switch_core_get_uuid() : "")))[0] == '\0' ? (char *) calloc ( (size_t) 1, (size_t) 1) : ({ size_t __len = strlen ((switch_core_get_uuid () ? switch_core_get_uuid() : "")) + 1; char *__retval = (char *) malloc (__len); if (__retval != ((void*)0)) __retval = (char *) memcpy (__retval, (switch_core_get_uuid() ? switch_core_get_uuid () : ""), __len); __retval; })) : __strdup ((switch_core_get_uuid () ? switch_core_get_uuid() : ""))))); | |||||||||
| 2321 | switch_xml_set_attr_d(cdr, "switchname", switch_core_get_switchname())switch_xml_set_attr(switch_xml_set_flag(cdr, SWITCH_XML_DUP), (__extension__ (__builtin_constant_p ("switchname") && ((size_t)(const void *)(("switchname") + 1) - (size_t)(const void *)("switchname") == 1) ? (((const char *) ("switchname" ))[0] == '\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len = strlen ("switchname") + 1; char *__retval = ( char *) malloc (__len); if (__retval != ((void*)0)) __retval = (char *) memcpy (__retval, "switchname", __len); __retval; } )) : __strdup ("switchname"))), (__extension__ (__builtin_constant_p ((switch_core_get_switchname() ? switch_core_get_switchname( ) : "")) && ((size_t)(const void *)(((switch_core_get_switchname () ? switch_core_get_switchname() : "")) + 1) - (size_t)(const void *)((switch_core_get_switchname() ? switch_core_get_switchname () : "")) == 1) ? (((const char *) ((switch_core_get_switchname () ? switch_core_get_switchname() : "")))[0] == '\0' ? (char * ) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len = strlen ( (switch_core_get_switchname() ? switch_core_get_switchname() : "")) + 1; char *__retval = (char *) malloc (__len); if (__retval != ((void*)0)) __retval = (char *) memcpy (__retval, (switch_core_get_switchname () ? switch_core_get_switchname() : ""), __len); __retval; }) ) : __strdup ((switch_core_get_switchname() ? switch_core_get_switchname () : ""))))); | |||||||||
| 2322 | ||||||||||
| 2323 | if (!(x_channel_data = switch_xml_add_child_d(cdr, "channel_data", cdr_off++)switch_xml_set_flag(switch_xml_add_child(cdr, (__extension__ ( __builtin_constant_p ("channel_data") && ((size_t)(const void *)(("channel_data") + 1) - (size_t)(const void *)("channel_data" ) == 1) ? (((const char *) ("channel_data"))[0] == '\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len = strlen ("channel_data") + 1; char *__retval = (char *) malloc (__len ); if (__retval != ((void*)0)) __retval = (char *) memcpy (__retval , "channel_data", __len); __retval; })) : __strdup ("channel_data" ))), cdr_off++), SWITCH_XML_NAMEM))) { | |||||||||
| 2324 | goto error; | |||||||||
| 2325 | } | |||||||||
| 2326 | ||||||||||
| 2327 | x_field = switch_xml_add_child_d(x_channel_data, "state", cd_off++)switch_xml_set_flag(switch_xml_add_child(x_channel_data, (__extension__ (__builtin_constant_p ("state") && ((size_t)(const void *)(("state") + 1) - (size_t)(const void *)("state") == 1) ? ( ((const char *) ("state"))[0] == '\0' ? (char *) calloc ((size_t ) 1, (size_t) 1) : ({ size_t __len = strlen ("state") + 1; char *__retval = (char *) malloc (__len); if (__retval != ((void* )0)) __retval = (char *) memcpy (__retval, "state", __len); __retval ; })) : __strdup ("state"))), cd_off++), SWITCH_XML_NAMEM); | |||||||||
| 2328 | switch_xml_set_txt_d(x_field, switch_channel_state_name(switch_channel_get_state(channel)))switch_xml_set_flag(switch_xml_set_txt(x_field, (__extension__ (__builtin_constant_p (switch_channel_state_name(switch_channel_get_state (channel))) && ((size_t)(const void *)((switch_channel_state_name (switch_channel_get_state(channel))) + 1) - (size_t)(const void *)(switch_channel_state_name(switch_channel_get_state(channel ))) == 1) ? (((const char *) (switch_channel_state_name(switch_channel_get_state (channel))))[0] == '\0' ? (char *) calloc ((size_t) 1, (size_t ) 1) : ({ size_t __len = strlen (switch_channel_state_name(switch_channel_get_state (channel))) + 1; char *__retval = (char *) malloc (__len); if (__retval != ((void*)0)) __retval = (char *) memcpy (__retval , switch_channel_state_name(switch_channel_get_state(channel) ), __len); __retval; })) : __strdup (switch_channel_state_name (switch_channel_get_state(channel)))))), SWITCH_XML_TXTM); | |||||||||
| 2329 | ||||||||||
| 2330 | x_field = switch_xml_add_child_d(x_channel_data, "direction", cd_off++)switch_xml_set_flag(switch_xml_add_child(x_channel_data, (__extension__ (__builtin_constant_p ("direction") && ((size_t)(const void *)(("direction") + 1) - (size_t)(const void *)("direction" ) == 1) ? (((const char *) ("direction"))[0] == '\0' ? (char * ) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len = strlen ( "direction") + 1; char *__retval = (char *) malloc (__len); if (__retval != ((void*)0)) __retval = (char *) memcpy (__retval , "direction", __len); __retval; })) : __strdup ("direction") )), cd_off++), SWITCH_XML_NAMEM); | |||||||||
| 2331 | switch_xml_set_txt_d(x_field, switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND ? "outbound" : "inbound")switch_xml_set_flag(switch_xml_set_txt(x_field, (__extension__ (__builtin_constant_p (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND ? "outbound" : "inbound") && ((size_t)(const void *) ((switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND ? "outbound" : "inbound") + 1) - (size_t)(const void *)(switch_channel_direction (channel) == SWITCH_CALL_DIRECTION_OUTBOUND ? "outbound" : "inbound" ) == 1) ? (((const char *) (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND ? "outbound" : "inbound")) [0] == '\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len = strlen (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND ? "outbound" : "inbound") + 1; char *__retval = (char *) malloc (__len); if (__retval != ((void*)0)) __retval = (char *) memcpy (__retval, switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND ? "outbound" : "inbound", __len); __retval; })) : __strdup ( switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND ? "outbound" : "inbound")))), SWITCH_XML_TXTM); | |||||||||
| 2332 | ||||||||||
| 2333 | x_field = switch_xml_add_child_d(x_channel_data, "state_number", cd_off++)switch_xml_set_flag(switch_xml_add_child(x_channel_data, (__extension__ (__builtin_constant_p ("state_number") && ((size_t)( const void *)(("state_number") + 1) - (size_t)(const void *)( "state_number") == 1) ? (((const char *) ("state_number"))[0] == '\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len = strlen ("state_number") + 1; char *__retval = (char * ) malloc (__len); if (__retval != ((void*)0)) __retval = (char *) memcpy (__retval, "state_number", __len); __retval; })) : __strdup ("state_number"))), cd_off++), SWITCH_XML_NAMEM); | |||||||||
| 2334 | switch_snprintf(tmp, sizeof(tmp), "%d", switch_channel_get_state(channel)); | |||||||||
| 2335 | switch_xml_set_txt_d(x_field, tmp)switch_xml_set_flag(switch_xml_set_txt(x_field, (__extension__ (__builtin_constant_p (tmp) && ((size_t)(const void * )((tmp) + 1) - (size_t)(const void *)(tmp) == 1) ? (((const char *) (tmp))[0] == '\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len = strlen (tmp) + 1; char *__retval = (char *) malloc (__len); if (__retval != ((void*)0)) __retval = (char *) memcpy (__retval, tmp, __len); __retval; })) : __strdup ( tmp)))), SWITCH_XML_TXTM); | |||||||||
| 2336 | ||||||||||
| 2337 | if ((f = switch_channel_get_flag_string(channel))) { | |||||||||
| 2338 | x_field = switch_xml_add_child_d(x_channel_data, "flags", cd_off++)switch_xml_set_flag(switch_xml_add_child(x_channel_data, (__extension__ (__builtin_constant_p ("flags") && ((size_t)(const void *)(("flags") + 1) - (size_t)(const void *)("flags") == 1) ? ( ((const char *) ("flags"))[0] == '\0' ? (char *) calloc ((size_t ) 1, (size_t) 1) : ({ size_t __len = strlen ("flags") + 1; char *__retval = (char *) malloc (__len); if (__retval != ((void* )0)) __retval = (char *) memcpy (__retval, "flags", __len); __retval ; })) : __strdup ("flags"))), cd_off++), SWITCH_XML_NAMEM); | |||||||||
| 2339 | switch_xml_set_txt_d(x_field, f)switch_xml_set_flag(switch_xml_set_txt(x_field, (__extension__ (__builtin_constant_p (f) && ((size_t)(const void *) ((f) + 1) - (size_t)(const void *)(f) == 1) ? (((const char * ) (f))[0] == '\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len = strlen (f) + 1; char *__retval = (char *) malloc (__len); if (__retval != ((void*)0)) __retval = (char *) memcpy (__retval, f, __len); __retval; })) : __strdup (f)))), SWITCH_XML_TXTM ); | |||||||||
| 2340 | free(f); | |||||||||
| 2341 | } | |||||||||
| 2342 | ||||||||||
| 2343 | if ((f = switch_channel_get_cap_string(channel))) { | |||||||||
| 2344 | x_field = switch_xml_add_child_d(x_channel_data, "caps", cd_off++)switch_xml_set_flag(switch_xml_add_child(x_channel_data, (__extension__ (__builtin_constant_p ("caps") && ((size_t)(const void *)(("caps") + 1) - (size_t)(const void *)("caps") == 1) ? (( (const char *) ("caps"))[0] == '\0' ? (char *) calloc ((size_t ) 1, (size_t) 1) : ({ size_t __len = strlen ("caps") + 1; char *__retval = (char *) malloc (__len); if (__retval != ((void* )0)) __retval = (char *) memcpy (__retval, "caps", __len); __retval ; })) : __strdup ("caps"))), cd_off++), SWITCH_XML_NAMEM); | |||||||||
| 2345 | switch_xml_set_txt_d(x_field, f)switch_xml_set_flag(switch_xml_set_txt(x_field, (__extension__ (__builtin_constant_p (f) && ((size_t)(const void *) ((f) + 1) - (size_t)(const void *)(f) == 1) ? (((const char * ) (f))[0] == '\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len = strlen (f) + 1; char *__retval = (char *) malloc (__len); if (__retval != ((void*)0)) __retval = (char *) memcpy (__retval, f, __len); __retval; })) : __strdup (f)))), SWITCH_XML_TXTM ); | |||||||||
| 2346 | free(f); | |||||||||
| 2347 | } | |||||||||
| 2348 | ||||||||||
| 2349 | ||||||||||
| 2350 | if (!(variables = switch_xml_add_child_d(cdr, "variables", cdr_off++)switch_xml_set_flag(switch_xml_add_child(cdr, (__extension__ ( __builtin_constant_p ("variables") && ((size_t)(const void *)(("variables") + 1) - (size_t)(const void *)("variables" ) == 1) ? (((const char *) ("variables"))[0] == '\0' ? (char * ) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len = strlen ( "variables") + 1; char *__retval = (char *) malloc (__len); if (__retval != ((void*)0)) __retval = (char *) memcpy (__retval , "variables", __len); __retval; })) : __strdup ("variables") )), cdr_off++), SWITCH_XML_NAMEM))) { | |||||||||
| 2351 | goto error; | |||||||||
| 2352 | } | |||||||||
| 2353 | ||||||||||
| 2354 | switch_ivr_set_xml_chan_vars(variables, channel, v_off); | |||||||||
| 2355 | ||||||||||
| 2356 | ||||||||||
| 2357 | if ((app_log = switch_core_session_get_app_log(session))) { | |||||||||
| 2358 | int app_off = 0; | |||||||||
| 2359 | switch_app_log_t *ap; | |||||||||
| 2360 | ||||||||||
| 2361 | if (!(x_apps = switch_xml_add_child_d(cdr, "app_log", cdr_off++)switch_xml_set_flag(switch_xml_add_child(cdr, (__extension__ ( __builtin_constant_p ("app_log") && ((size_t)(const void *)(("app_log") + 1) - (size_t)(const void *)("app_log") == 1 ) ? (((const char *) ("app_log"))[0] == '\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len = strlen ("app_log" ) + 1; char *__retval = (char *) malloc (__len); if (__retval != ((void*)0)) __retval = (char *) memcpy (__retval, "app_log" , __len); __retval; })) : __strdup ("app_log"))), cdr_off++), SWITCH_XML_NAMEM))) { | |||||||||
| 2362 | goto error; | |||||||||
| 2363 | } | |||||||||
| 2364 | for (ap = app_log; ap; ap = ap->next) { | |||||||||
| 2365 | char tmp[128]; | |||||||||
| 2366 | ||||||||||
| 2367 | if (!(x_application = switch_xml_add_child_d(x_apps, "application", app_off++)switch_xml_set_flag(switch_xml_add_child(x_apps, (__extension__ (__builtin_constant_p ("application") && ((size_t)(const void *)(("application") + 1) - (size_t)(const void *)("application" ) == 1) ? (((const char *) ("application"))[0] == '\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len = strlen ("application") + 1; char *__retval = (char *) malloc (__len ); if (__retval != ((void*)0)) __retval = (char *) memcpy (__retval , "application", __len); __retval; })) : __strdup ("application" ))), app_off++), SWITCH_XML_NAMEM))) { | |||||||||
| 2368 | goto error; | |||||||||
| 2369 | } | |||||||||
| 2370 | ||||||||||
| 2371 | switch_xml_set_attr_d(x_application, "app_name", ap->app)switch_xml_set_attr(switch_xml_set_flag(x_application, SWITCH_XML_DUP ), (__extension__ (__builtin_constant_p ("app_name") && ((size_t)(const void *)(("app_name") + 1) - (size_t)(const void *)("app_name") == 1) ? (((const char *) ("app_name"))[0] == '\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len = strlen ("app_name") + 1; char *__retval = (char *) malloc ( __len); if (__retval != ((void*)0)) __retval = (char *) memcpy (__retval, "app_name", __len); __retval; })) : __strdup ("app_name" ))), (__extension__ (__builtin_constant_p ((ap->app ? ap-> app : "")) && ((size_t)(const void *)(((ap->app ? ap ->app : "")) + 1) - (size_t)(const void *)((ap->app ? ap ->app : "")) == 1) ? (((const char *) ((ap->app ? ap-> app : "")))[0] == '\0' ? (char *) calloc ((size_t) 1, (size_t ) 1) : ({ size_t __len = strlen ((ap->app ? ap->app : "" )) + 1; char *__retval = (char *) malloc (__len); if (__retval != ((void*)0)) __retval = (char *) memcpy (__retval, (ap-> app ? ap->app : ""), __len); __retval; })) : __strdup ((ap ->app ? ap->app : ""))))); | |||||||||
| 2372 | switch_xml_set_attr_d(x_application, "app_data", ap->arg)switch_xml_set_attr(switch_xml_set_flag(x_application, SWITCH_XML_DUP ), (__extension__ (__builtin_constant_p ("app_data") && ((size_t)(const void *)(("app_data") + 1) - (size_t)(const void *)("app_data") == 1) ? (((const char *) ("app_data"))[0] == '\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len = strlen ("app_data") + 1; char *__retval = (char *) malloc ( __len); if (__retval != ((void*)0)) __retval = (char *) memcpy (__retval, "app_data", __len); __retval; })) : __strdup ("app_data" ))), (__extension__ (__builtin_constant_p ((ap->arg ? ap-> arg : "")) && ((size_t)(const void *)(((ap->arg ? ap ->arg : "")) + 1) - (size_t)(const void *)((ap->arg ? ap ->arg : "")) == 1) ? (((const char *) ((ap->arg ? ap-> arg : "")))[0] == '\0' ? (char *) calloc ((size_t) 1, (size_t ) 1) : ({ size_t __len = strlen ((ap->arg ? ap->arg : "" )) + 1; char *__retval = (char *) malloc (__len); if (__retval != ((void*)0)) __retval = (char *) memcpy (__retval, (ap-> arg ? ap->arg : ""), __len); __retval; })) : __strdup ((ap ->arg ? ap->arg : ""))))); | |||||||||
| 2373 | ||||||||||
| 2374 | switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT"ld", ap->stamp); | |||||||||
| 2375 | switch_xml_set_attr_d_buf(x_application, "app_stamp", tmp)switch_xml_set_attr(switch_xml_set_flag(x_application, SWITCH_XML_DUP ), (__extension__ (__builtin_constant_p ("app_stamp") && ((size_t)(const void *)(("app_stamp") + 1) - (size_t)(const void *)("app_stamp") == 1) ? (((const char *) ("app_stamp"))[0] == '\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len = strlen ("app_stamp") + 1; char *__retval = (char *) malloc (__len); if (__retval != ((void*)0)) __retval = (char *) memcpy (__retval, "app_stamp", __len); __retval; })) : __strdup ("app_stamp" ))), (__extension__ (__builtin_constant_p (tmp) && (( size_t)(const void *)((tmp) + 1) - (size_t)(const void *)(tmp ) == 1) ? (((const char *) (tmp))[0] == '\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len = strlen (tmp) + 1 ; char *__retval = (char *) malloc (__len); if (__retval != ( (void*)0)) __retval = (char *) memcpy (__retval, tmp, __len); __retval; })) : __strdup (tmp)))); | |||||||||
| 2376 | } | |||||||||
| 2377 | } | |||||||||
| 2378 | ||||||||||
| 2379 | if (hold_record) { | |||||||||
| 2380 | int cf_off = 0; | |||||||||
| 2381 | ||||||||||
| 2382 | if (!(xhr = switch_xml_add_child_d(cdr, "hold-record", cdr_off++)switch_xml_set_flag(switch_xml_add_child(cdr, (__extension__ ( __builtin_constant_p ("hold-record") && ((size_t)(const void *)(("hold-record") + 1) - (size_t)(const void *)("hold-record" ) == 1) ? (((const char *) ("hold-record"))[0] == '\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len = strlen ("hold-record") + 1; char *__retval = (char *) malloc (__len ); if (__retval != ((void*)0)) __retval = (char *) memcpy (__retval , "hold-record", __len); __retval; })) : __strdup ("hold-record" ))), cdr_off++), SWITCH_XML_NAMEM))) { | |||||||||
| 2383 | goto error; | |||||||||
| 2384 | } | |||||||||
| 2385 | ||||||||||
| 2386 | for (hr = hold_record; hr; hr = hr->next) { | |||||||||
| 2387 | char *t = tmp; | |||||||||
| 2388 | if (!(x_hold = switch_xml_add_child_d(xhr, "hold", cf_off++)switch_xml_set_flag(switch_xml_add_child(xhr, (__extension__ ( __builtin_constant_p ("hold") && ((size_t)(const void *)(("hold") + 1) - (size_t)(const void *)("hold") == 1) ? (( (const char *) ("hold"))[0] == '\0' ? (char *) calloc ((size_t ) 1, (size_t) 1) : ({ size_t __len = strlen ("hold") + 1; char *__retval = (char *) malloc (__len); if (__retval != ((void* )0)) __retval = (char *) memcpy (__retval, "hold", __len); __retval ; })) : __strdup ("hold"))), cf_off++), SWITCH_XML_NAMEM))) { | |||||||||
| 2389 | goto error; | |||||||||
| 2390 | } | |||||||||
| 2391 | ||||||||||
| 2392 | switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT"ld", hr->on); | |||||||||
| 2393 | switch_xml_set_attr_d(x_hold, "on", t)switch_xml_set_attr(switch_xml_set_flag(x_hold, SWITCH_XML_DUP ), (__extension__ (__builtin_constant_p ("on") && ((size_t )(const void *)(("on") + 1) - (size_t)(const void *)("on") == 1) ? (((const char *) ("on"))[0] == '\0' ? (char *) calloc ( (size_t) 1, (size_t) 1) : ({ size_t __len = strlen ("on") + 1 ; char *__retval = (char *) malloc (__len); if (__retval != ( (void*)0)) __retval = (char *) memcpy (__retval, "on", __len) ; __retval; })) : __strdup ("on"))), (__extension__ (__builtin_constant_p ((t ? t : "")) && ((size_t)(const void *)(((t ? t : "" )) + 1) - (size_t)(const void *)((t ? t : "")) == 1) ? (((const char *) ((t ? t : "")))[0] == '\0' ? (char *) calloc ((size_t ) 1, (size_t) 1) : ({ size_t __len = strlen ((t ? t : "")) + 1 ; char *__retval = (char *) malloc (__len); if (__retval != ( (void*)0)) __retval = (char *) memcpy (__retval, (t ? t : "") , __len); __retval; })) : __strdup ((t ? t : ""))))); | |||||||||
| 2394 | ||||||||||
| 2395 | switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT"ld", hr->off); | |||||||||
| 2396 | switch_xml_set_attr_d(x_hold, "off", t)switch_xml_set_attr(switch_xml_set_flag(x_hold, SWITCH_XML_DUP ), (__extension__ (__builtin_constant_p ("off") && (( size_t)(const void *)(("off") + 1) - (size_t)(const void *)("off" ) == 1) ? (((const char *) ("off"))[0] == '\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len = strlen ("off") + 1; char *__retval = (char *) malloc (__len); if (__retval != ((void*)0)) __retval = (char *) memcpy (__retval, "off", __len ); __retval; })) : __strdup ("off"))), (__extension__ (__builtin_constant_p ((t ? t : "")) && ((size_t)(const void *)(((t ? t : "" )) + 1) - (size_t)(const void *)((t ? t : "")) == 1) ? (((const char *) ((t ? t : "")))[0] == '\0' ? (char *) calloc ((size_t ) 1, (size_t) 1) : ({ size_t __len = strlen ((t ? t : "")) + 1 ; char *__retval = (char *) malloc (__len); if (__retval != ( (void*)0)) __retval = (char *) memcpy (__retval, (t ? t : "") , __len); __retval; })) : __strdup ((t ? t : ""))))); | |||||||||
| 2397 | ||||||||||
| 2398 | if (hr->uuid) { | |||||||||
| 2399 | switch_xml_set_attr_d(x_hold, "bridged-to", hr->uuid)switch_xml_set_attr(switch_xml_set_flag(x_hold, SWITCH_XML_DUP ), (__extension__ (__builtin_constant_p ("bridged-to") && ((size_t)(const void *)(("bridged-to") + 1) - (size_t)(const void *)("bridged-to") == 1) ? (((const char *) ("bridged-to" ))[0] == '\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len = strlen ("bridged-to") + 1; char *__retval = ( char *) malloc (__len); if (__retval != ((void*)0)) __retval = (char *) memcpy (__retval, "bridged-to", __len); __retval; } )) : __strdup ("bridged-to"))), (__extension__ (__builtin_constant_p ((hr->uuid ? hr->uuid : "")) && ((size_t)(const void *)(((hr->uuid ? hr->uuid : "")) + 1) - (size_t)(const void *)((hr->uuid ? hr->uuid : "")) == 1) ? (((const char *) ((hr->uuid ? hr->uuid : "")))[0] == '\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len = strlen ( (hr->uuid ? hr->uuid : "")) + 1; char *__retval = (char *) malloc (__len); if (__retval != ((void*)0)) __retval = (char *) memcpy (__retval, (hr->uuid ? hr->uuid : ""), __len ); __retval; })) : __strdup ((hr->uuid ? hr->uuid : "") )))); | |||||||||
| 2400 | } | |||||||||
| 2401 | ||||||||||
| 2402 | ||||||||||
| 2403 | } | |||||||||
| 2404 | ||||||||||
| 2405 | ||||||||||
| 2406 | } | |||||||||
| 2407 | ||||||||||
| 2408 | ||||||||||
| 2409 | ||||||||||
| 2410 | caller_profile = switch_channel_get_caller_profile(channel); | |||||||||
| 2411 | ||||||||||
| 2412 | while (caller_profile) { | |||||||||
| 2413 | int cf_off = 0; | |||||||||
| 2414 | int cp_off = 0; | |||||||||
| 2415 | ||||||||||
| 2416 | if (!(x_callflow = switch_xml_add_child_d(cdr, "callflow", cdr_off++)switch_xml_set_flag(switch_xml_add_child(cdr, (__extension__ ( __builtin_constant_p ("callflow") && ((size_t)(const void *)(("callflow") + 1) - (size_t)(const void *)("callflow") == 1) ? (((const char *) ("callflow"))[0] == '\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len = strlen ("callflow" ) + 1; char *__retval = (char *) malloc (__len); if (__retval != ((void*)0)) __retval = (char *) memcpy (__retval, "callflow" , __len); __retval; })) : __strdup ("callflow"))), cdr_off++) , SWITCH_XML_NAMEM))) { | |||||||||
| 2417 | goto error; | |||||||||
| 2418 | } | |||||||||
| 2419 | ||||||||||
| 2420 | if (!zstr(caller_profile->dialplan)_zstr(caller_profile->dialplan)) { | |||||||||
| 2421 | switch_xml_set_attr_d(x_callflow, "dialplan", caller_profile->dialplan)switch_xml_set_attr(switch_xml_set_flag(x_callflow, SWITCH_XML_DUP ), (__extension__ (__builtin_constant_p ("dialplan") && ((size_t)(const void *)(("dialplan") + 1) - (size_t)(const void *)("dialplan") == 1) ? (((const char *) ("dialplan"))[0] == '\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len = strlen ("dialplan") + 1; char *__retval = (char *) malloc ( __len); if (__retval != ((void*)0)) __retval = (char *) memcpy (__retval, "dialplan", __len); __retval; })) : __strdup ("dialplan" ))), (__extension__ (__builtin_constant_p ((caller_profile-> dialplan ? caller_profile->dialplan : "")) && ((size_t )(const void *)(((caller_profile->dialplan ? caller_profile ->dialplan : "")) + 1) - (size_t)(const void *)((caller_profile ->dialplan ? caller_profile->dialplan : "")) == 1) ? (( (const char *) ((caller_profile->dialplan ? caller_profile ->dialplan : "")))[0] == '\0' ? (char *) calloc ((size_t) 1 , (size_t) 1) : ({ size_t __len = strlen ((caller_profile-> dialplan ? caller_profile->dialplan : "")) + 1; char *__retval = (char *) malloc (__len); if (__retval != ((void*)0)) __retval = (char *) memcpy (__retval, (caller_profile->dialplan ? caller_profile ->dialplan : ""), __len); __retval; })) : __strdup ((caller_profile ->dialplan ? caller_profile->dialplan : ""))))); | |||||||||
| 2422 | } | |||||||||
| 2423 | ||||||||||
| 2424 | if (!zstr(caller_profile->uuid_str)_zstr(caller_profile->uuid_str)) { | |||||||||
| 2425 | switch_xml_set_attr_d(x_callflow, "unique-id", caller_profile->uuid_str)switch_xml_set_attr(switch_xml_set_flag(x_callflow, SWITCH_XML_DUP ), (__extension__ (__builtin_constant_p ("unique-id") && ((size_t)(const void *)(("unique-id") + 1) - (size_t)(const void *)("unique-id") == 1) ? (((const char *) ("unique-id"))[0] == '\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len = strlen ("unique-id") + 1; char *__retval = (char *) malloc (__len); if (__retval != ((void*)0)) __retval = (char *) memcpy (__retval, "unique-id", __len); __retval; })) : __strdup ("unique-id" ))), (__extension__ (__builtin_constant_p ((caller_profile-> uuid_str ? caller_profile->uuid_str : "")) && ((size_t )(const void *)(((caller_profile->uuid_str ? caller_profile ->uuid_str : "")) + 1) - (size_t)(const void *)((caller_profile ->uuid_str ? caller_profile->uuid_str : "")) == 1) ? (( (const char *) ((caller_profile->uuid_str ? caller_profile ->uuid_str : "")))[0] == '\0' ? (char *) calloc ((size_t) 1 , (size_t) 1) : ({ size_t __len = strlen ((caller_profile-> uuid_str ? caller_profile->uuid_str : "")) + 1; char *__retval = (char *) malloc (__len); if (__retval != ((void*)0)) __retval = (char *) memcpy (__retval, (caller_profile->uuid_str ? caller_profile ->uuid_str : ""), __len); __retval; })) : __strdup ((caller_profile ->uuid_str ? caller_profile->uuid_str : ""))))); | |||||||||
| 2426 | } | |||||||||
| 2427 | ||||||||||
| 2428 | if (!zstr(caller_profile->clone_of)_zstr(caller_profile->clone_of)) { | |||||||||
| 2429 | switch_xml_set_attr_d(x_callflow, "clone-of", caller_profile->clone_of)switch_xml_set_attr(switch_xml_set_flag(x_callflow, SWITCH_XML_DUP ), (__extension__ (__builtin_constant_p ("clone-of") && ((size_t)(const void *)(("clone-of") + 1) - (size_t)(const void *)("clone-of") == 1) ? (((const char *) ("clone-of"))[0] == '\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len = strlen ("clone-of") + 1; char *__retval = (char *) malloc ( __len); if (__retval != ((void*)0)) __retval = (char *) memcpy (__retval, "clone-of", __len); __retval; })) : __strdup ("clone-of" ))), (__extension__ (__builtin_constant_p ((caller_profile-> clone_of ? caller_profile->clone_of : "")) && ((size_t )(const void *)(((caller_profile->clone_of ? caller_profile ->clone_of : "")) + 1) - (size_t)(const void *)((caller_profile ->clone_of ? caller_profile->clone_of : "")) == 1) ? (( (const char *) ((caller_profile->clone_of ? caller_profile ->clone_of : "")))[0] == '\0' ? (char *) calloc ((size_t) 1 , (size_t) 1) : ({ size_t __len = strlen ((caller_profile-> clone_of ? caller_profile->clone_of : "")) + 1; char *__retval = (char *) malloc (__len); if (__retval != ((void*)0)) __retval = (char *) memcpy (__retval, (caller_profile->clone_of ? caller_profile ->clone_of : ""), __len); __retval; })) : __strdup ((caller_profile ->clone_of ? caller_profile->clone_of : ""))))); | |||||||||
| 2430 | } | |||||||||
| 2431 | ||||||||||
| 2432 | if (!zstr(caller_profile->profile_index)_zstr(caller_profile->profile_index)) { | |||||||||
| 2433 | switch_xml_set_attr_d(x_callflow, "profile_index", caller_profile->profile_index)switch_xml_set_attr(switch_xml_set_flag(x_callflow, SWITCH_XML_DUP ), (__extension__ (__builtin_constant_p ("profile_index") && ((size_t)(const void *)(("profile_index") + 1) - (size_t)(const void *)("profile_index") == 1) ? (((const char *) ("profile_index" ))[0] == '\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len = strlen ("profile_index") + 1; char *__retval = (char *) malloc (__len); if (__retval != ((void*)0)) __retval = (char *) memcpy (__retval, "profile_index", __len); __retval ; })) : __strdup ("profile_index"))), (__extension__ (__builtin_constant_p ((caller_profile->profile_index ? caller_profile->profile_index : "")) && ((size_t)(const void *)(((caller_profile-> profile_index ? caller_profile->profile_index : "")) + 1) - (size_t)(const void *)((caller_profile->profile_index ? caller_profile ->profile_index : "")) == 1) ? (((const char *) ((caller_profile ->profile_index ? caller_profile->profile_index : ""))) [0] == '\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len = strlen ((caller_profile->profile_index ? caller_profile ->profile_index : "")) + 1; char *__retval = (char *) malloc (__len); if (__retval != ((void*)0)) __retval = (char *) memcpy (__retval, (caller_profile->profile_index ? caller_profile ->profile_index : ""), __len); __retval; })) : __strdup (( caller_profile->profile_index ? caller_profile->profile_index : ""))))); | |||||||||
| 2434 | } | |||||||||
| 2435 | ||||||||||
| 2436 | if (caller_profile->caller_extension) { | |||||||||
| 2437 | switch_caller_application_t *ap; | |||||||||
| 2438 | int app_off = 0; | |||||||||
| 2439 | ||||||||||
| 2440 | if (!(x_caller_extension = switch_xml_add_child_d(x_callflow, "extension", cf_off++)switch_xml_set_flag(switch_xml_add_child(x_callflow, (__extension__ (__builtin_constant_p ("extension") && ((size_t)(const void *)(("extension") + 1) - (size_t)(const void *)("extension" ) == 1) ? (((const char *) ("extension"))[0] == '\0' ? (char * ) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len = strlen ( "extension") + 1; char *__retval = (char *) malloc (__len); if (__retval != ((void*)0)) __retval = (char *) memcpy (__retval , "extension", __len); __retval; })) : __strdup ("extension") )), cf_off++), SWITCH_XML_NAMEM))) { | |||||||||
| 2441 | goto error; | |||||||||
| 2442 | } | |||||||||
| 2443 | ||||||||||
| 2444 | switch_xml_set_attr_d(x_caller_extension, "name", caller_profile->caller_extension->extension_name)switch_xml_set_attr(switch_xml_set_flag(x_caller_extension, SWITCH_XML_DUP ), (__extension__ (__builtin_constant_p ("name") && ( (size_t)(const void *)(("name") + 1) - (size_t)(const void *) ("name") == 1) ? (((const char *) ("name"))[0] == '\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len = strlen ("name") + 1; char *__retval = (char *) malloc (__len); if ( __retval != ((void*)0)) __retval = (char *) memcpy (__retval, "name", __len); __retval; })) : __strdup ("name"))), (__extension__ (__builtin_constant_p ((caller_profile->caller_extension-> extension_name ? caller_profile->caller_extension->extension_name : "")) && ((size_t)(const void *)(((caller_profile-> caller_extension->extension_name ? caller_profile->caller_extension ->extension_name : "")) + 1) - (size_t)(const void *)((caller_profile ->caller_extension->extension_name ? caller_profile-> caller_extension->extension_name : "")) == 1) ? (((const char *) ((caller_profile->caller_extension->extension_name ? caller_profile->caller_extension->extension_name : "") ))[0] == '\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len = strlen ((caller_profile->caller_extension-> extension_name ? caller_profile->caller_extension->extension_name : "")) + 1; char *__retval = (char *) malloc (__len); if (__retval != ((void*)0)) __retval = (char *) memcpy (__retval, (caller_profile ->caller_extension->extension_name ? caller_profile-> caller_extension->extension_name : ""), __len); __retval; } )) : __strdup ((caller_profile->caller_extension->extension_name ? caller_profile->caller_extension->extension_name : "" ))))); | |||||||||
| 2445 | switch_xml_set_attr_d(x_caller_extension, "number", caller_profile->caller_extension->extension_number)switch_xml_set_attr(switch_xml_set_flag(x_caller_extension, SWITCH_XML_DUP ), (__extension__ (__builtin_constant_p ("number") && ((size_t)(const void *)(("number") + 1) - (size_t)(const void *)("number") == 1) ? (((const char *) ("number"))[0] == '\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len = strlen ("number") + 1; char *__retval = (char *) malloc (__len ); if (__retval != ((void*)0)) __retval = (char *) memcpy (__retval , "number", __len); __retval; })) : __strdup ("number"))), (__extension__ (__builtin_constant_p ((caller_profile->caller_extension-> extension_number ? caller_profile->caller_extension->extension_number : "")) && ((size_t)(const void *)(((caller_profile-> caller_extension->extension_number ? caller_profile->caller_extension ->extension_number : "")) + 1) - (size_t)(const void *)((caller_profile ->caller_extension->extension_number ? caller_profile-> caller_extension->extension_number : "")) == 1) ? (((const char *) ((caller_profile->caller_extension->extension_number ? caller_profile->caller_extension->extension_number : "")))[0] == '\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len = strlen ((caller_profile->caller_extension ->extension_number ? caller_profile->caller_extension-> extension_number : "")) + 1; char *__retval = (char *) malloc (__len); if (__retval != ((void*)0)) __retval = (char *) memcpy (__retval, (caller_profile->caller_extension->extension_number ? caller_profile->caller_extension->extension_number : ""), __len); __retval; })) : __strdup ((caller_profile->caller_extension ->extension_number ? caller_profile->caller_extension-> extension_number : ""))))); | |||||||||
| 2446 | if (caller_profile->caller_extension->current_application) { | |||||||||
| 2447 | switch_xml_set_attr_d(x_caller_extension, "current_app", caller_profile->caller_extension->current_application->application_name)switch_xml_set_attr(switch_xml_set_flag(x_caller_extension, SWITCH_XML_DUP ), (__extension__ (__builtin_constant_p ("current_app") && ((size_t)(const void *)(("current_app") + 1) - (size_t)(const void *)("current_app") == 1) ? (((const char *) ("current_app" ))[0] == '\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len = strlen ("current_app") + 1; char *__retval = ( char *) malloc (__len); if (__retval != ((void*)0)) __retval = (char *) memcpy (__retval, "current_app", __len); __retval; } )) : __strdup ("current_app"))), (__extension__ (__builtin_constant_p ((caller_profile->caller_extension->current_application ->application_name ? caller_profile->caller_extension-> current_application->application_name : "")) && (( size_t)(const void *)(((caller_profile->caller_extension-> current_application->application_name ? caller_profile-> caller_extension->current_application->application_name : "")) + 1) - (size_t)(const void *)((caller_profile->caller_extension ->current_application->application_name ? caller_profile ->caller_extension->current_application->application_name : "")) == 1) ? (((const char *) ((caller_profile->caller_extension ->current_application->application_name ? caller_profile ->caller_extension->current_application->application_name : "")))[0] == '\0' ? (char *) calloc ((size_t) 1, (size_t) 1 ) : ({ size_t __len = strlen ((caller_profile->caller_extension ->current_application->application_name ? caller_profile ->caller_extension->current_application->application_name : "")) + 1; char *__retval = (char *) malloc (__len); if (__retval != ((void*)0)) __retval = (char *) memcpy (__retval, (caller_profile ->caller_extension->current_application->application_name ? caller_profile->caller_extension->current_application ->application_name : ""), __len); __retval; })) : __strdup ((caller_profile->caller_extension->current_application ->application_name ? caller_profile->caller_extension-> current_application->application_name : ""))))); | |||||||||
| 2448 | } | |||||||||
| 2449 | ||||||||||
| 2450 | for (ap = caller_profile->caller_extension->applications; ap; ap = ap->next) { | |||||||||
| 2451 | if (!(x_application = switch_xml_add_child_d(x_caller_extension, "application", app_off++)switch_xml_set_flag(switch_xml_add_child(x_caller_extension, ( __extension__ (__builtin_constant_p ("application") && ((size_t)(const void *)(("application") + 1) - (size_t)(const void *)("application") == 1) ? (((const char *) ("application" ))[0] == '\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len = strlen ("application") + 1; char *__retval = ( char *) malloc (__len); if (__retval != ((void*)0)) __retval = (char *) memcpy (__retval, "application", __len); __retval; } )) : __strdup ("application"))), app_off++), SWITCH_XML_NAMEM ))) { | |||||||||
| 2452 | goto error; | |||||||||
| 2453 | } | |||||||||
| 2454 | if (ap == caller_profile->caller_extension->current_application) { | |||||||||
| 2455 | switch_xml_set_attr_d(x_application, "last_executed", "true")switch_xml_set_attr(switch_xml_set_flag(x_application, SWITCH_XML_DUP ), (__extension__ (__builtin_constant_p ("last_executed") && ((size_t)(const void *)(("last_executed") + 1) - (size_t)(const void *)("last_executed") == 1) ? (((const char *) ("last_executed" ))[0] == '\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len = strlen ("last_executed") + 1; char *__retval = (char *) malloc (__len); if (__retval != ((void*)0)) __retval = (char *) memcpy (__retval, "last_executed", __len); __retval ; })) : __strdup ("last_executed"))), (__extension__ (__builtin_constant_p (("true" ? "true" : "")) && ((size_t)(const void *)( (("true" ? "true" : "")) + 1) - (size_t)(const void *)(("true" ? "true" : "")) == 1) ? (((const char *) (("true" ? "true" : "")))[0] == '\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len = strlen (("true" ? "true" : "")) + 1; char * __retval = (char *) malloc (__len); if (__retval != ((void*)0 )) __retval = (char *) memcpy (__retval, ("true" ? "true" : "" ), __len); __retval; })) : __strdup (("true" ? "true" : ""))) )); | |||||||||
| 2456 | } | |||||||||
| 2457 | switch_xml_set_attr_d(x_application, "app_name", ap->application_name)switch_xml_set_attr(switch_xml_set_flag(x_application, SWITCH_XML_DUP ), (__extension__ (__builtin_constant_p ("app_name") && ((size_t)(const void *)(("app_name") + 1) - (size_t)(const void *)("app_name") == 1) ? (((const char *) ("app_name"))[0] == '\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len = strlen ("app_name") + 1; char *__retval = (char *) malloc ( __len); if (__retval != ((void*)0)) __retval = (char *) memcpy (__retval, "app_name", __len); __retval; })) : __strdup ("app_name" ))), (__extension__ (__builtin_constant_p ((ap->application_name ? ap->application_name : "")) && ((size_t)(const void *)(((ap->application_name ? ap->application_name : "") ) + 1) - (size_t)(const void *)((ap->application_name ? ap ->application_name : "")) == 1) ? (((const char *) ((ap-> application_name ? ap->application_name : "")))[0] == '\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len = strlen ((ap->application_name ? ap->application_name : "")) + 1; char *__retval = (char *) malloc (__len); if (__retval != ((void*)0)) __retval = (char *) memcpy (__retval, (ap-> application_name ? ap->application_name : ""), __len); __retval ; })) : __strdup ((ap->application_name ? ap->application_name : ""))))); | |||||||||
| 2458 | switch_xml_set_attr_d(x_application, "app_data", ap->application_data)switch_xml_set_attr(switch_xml_set_flag(x_application, SWITCH_XML_DUP ), (__extension__ (__builtin_constant_p ("app_data") && ((size_t)(const void *)(("app_data") + 1) - (size_t)(const void *)("app_data") == 1) ? (((const char *) ("app_data"))[0] == '\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len = strlen ("app_data") + 1; char *__retval = (char *) malloc ( __len); if (__retval != ((void*)0)) __retval = (char *) memcpy (__retval, "app_data", __len); __retval; })) : __strdup ("app_data" ))), (__extension__ (__builtin_constant_p ((ap->application_data ? ap->application_data : "")) && ((size_t)(const void *)(((ap->application_data ? ap->application_data : "") ) + 1) - (size_t)(const void *)((ap->application_data ? ap ->application_data : "")) == 1) ? (((const char *) ((ap-> application_data ? ap->application_data : "")))[0] == '\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len = strlen ((ap->application_data ? ap->application_data : "")) + 1; char *__retval = (char *) malloc (__len); if (__retval != ((void*)0)) __retval = (char *) memcpy (__retval, (ap-> application_data ? ap->application_data : ""), __len); __retval ; })) : __strdup ((ap->application_data ? ap->application_data : ""))))); | |||||||||
| 2459 | } | |||||||||
| 2460 | ||||||||||
| 2461 | if (caller_profile->caller_extension->children) { | |||||||||
| 2462 | switch_caller_profile_t *cp = NULL((void*)0); | |||||||||
| 2463 | int i_off = 0, i_app_off = 0; | |||||||||
| 2464 | for (cp = caller_profile->caller_extension->children; cp; cp = cp->next) { | |||||||||
| 2465 | ||||||||||
| 2466 | if (!cp->caller_extension) { | |||||||||
| 2467 | continue; | |||||||||
| 2468 | } | |||||||||
| 2469 | if (!(x_inner_extension = switch_xml_add_child_d(x_caller_extension, "sub_extensions", app_off++)switch_xml_set_flag(switch_xml_add_child(x_caller_extension, ( __extension__ (__builtin_constant_p ("sub_extensions") && ((size_t)(const void *)(("sub_extensions") + 1) - (size_t)(const void *)("sub_extensions") == 1) ? (((const char *) ("sub_extensions" ))[0] == '\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len = strlen ("sub_extensions") + 1; char *__retval = (char *) malloc (__len); if (__retval != ((void*)0)) __retval = (char *) memcpy (__retval, "sub_extensions", __len); __retval ; })) : __strdup ("sub_extensions"))), app_off++), SWITCH_XML_NAMEM ))) { | |||||||||
| 2470 | goto error; | |||||||||
| 2471 | } | |||||||||
| 2472 | ||||||||||
| 2473 | if (!(x_caller_extension = switch_xml_add_child_d(x_inner_extension, "extension", i_off++)switch_xml_set_flag(switch_xml_add_child(x_inner_extension, ( __extension__ (__builtin_constant_p ("extension") && ( (size_t)(const void *)(("extension") + 1) - (size_t)(const void *)("extension") == 1) ? (((const char *) ("extension"))[0] == '\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len = strlen ("extension") + 1; char *__retval = (char *) malloc (__len); if (__retval != ((void*)0)) __retval = (char *) memcpy (__retval, "extension", __len); __retval; })) : __strdup ("extension" ))), i_off++), SWITCH_XML_NAMEM))) { | |||||||||
| 2474 | goto error; | |||||||||
| 2475 | } | |||||||||
| 2476 | switch_xml_set_attr_d(x_caller_extension, "name", cp->caller_extension->extension_name)switch_xml_set_attr(switch_xml_set_flag(x_caller_extension, SWITCH_XML_DUP ), (__extension__ (__builtin_constant_p ("name") && ( (size_t)(const void *)(("name") + 1) - (size_t)(const void *) ("name") == 1) ? (((const char *) ("name"))[0] == '\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len = strlen ("name") + 1; char *__retval = (char *) malloc (__len); if ( __retval != ((void*)0)) __retval = (char *) memcpy (__retval, "name", __len); __retval; })) : __strdup ("name"))), (__extension__ (__builtin_constant_p ((cp->caller_extension->extension_name ? cp->caller_extension->extension_name : "")) && ((size_t)(const void *)(((cp->caller_extension->extension_name ? cp->caller_extension->extension_name : "")) + 1) - ( size_t)(const void *)((cp->caller_extension->extension_name ? cp->caller_extension->extension_name : "")) == 1) ? ( ((const char *) ((cp->caller_extension->extension_name ? cp->caller_extension->extension_name : "")))[0] == '\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len = strlen ((cp->caller_extension->extension_name ? cp-> caller_extension->extension_name : "")) + 1; char *__retval = (char *) malloc (__len); if (__retval != ((void*)0)) __retval = (char *) memcpy (__retval, (cp->caller_extension->extension_name ? cp->caller_extension->extension_name : ""), __len); __retval ; })) : __strdup ((cp->caller_extension->extension_name ? cp->caller_extension->extension_name : ""))))); | |||||||||
| 2477 | switch_xml_set_attr_d(x_caller_extension, "number", cp->caller_extension->extension_number)switch_xml_set_attr(switch_xml_set_flag(x_caller_extension, SWITCH_XML_DUP ), (__extension__ (__builtin_constant_p ("number") && ((size_t)(const void *)(("number") + 1) - (size_t)(const void *)("number") == 1) ? (((const char *) ("number"))[0] == '\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len = strlen ("number") + 1; char *__retval = (char *) malloc (__len ); if (__retval != ((void*)0)) __retval = (char *) memcpy (__retval , "number", __len); __retval; })) : __strdup ("number"))), (__extension__ (__builtin_constant_p ((cp->caller_extension->extension_number ? cp->caller_extension->extension_number : "")) && ((size_t)(const void *)(((cp->caller_extension->extension_number ? cp->caller_extension->extension_number : "")) + 1) - (size_t)(const void *)((cp->caller_extension->extension_number ? cp->caller_extension->extension_number : "")) == 1) ? (((const char *) ((cp->caller_extension->extension_number ? cp->caller_extension->extension_number : "")))[0] == '\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len = strlen ((cp->caller_extension->extension_number ? cp ->caller_extension->extension_number : "")) + 1; char * __retval = (char *) malloc (__len); if (__retval != ((void*)0 )) __retval = (char *) memcpy (__retval, (cp->caller_extension ->extension_number ? cp->caller_extension->extension_number : ""), __len); __retval; })) : __strdup ((cp->caller_extension ->extension_number ? cp->caller_extension->extension_number : ""))))); | |||||||||
| 2478 | switch_xml_set_attr_d(x_caller_extension, "dialplan", cp->dialplan)switch_xml_set_attr(switch_xml_set_flag(x_caller_extension, SWITCH_XML_DUP ), (__extension__ (__builtin_constant_p ("dialplan") && ((size_t)(const void *)(("dialplan") + 1) - (size_t)(const void *)("dialplan") == 1) ? (((const char *) ("dialplan"))[0] == '\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len = strlen ("dialplan") + 1; char *__retval = (char *) malloc ( __len); if (__retval != ((void*)0)) __retval = (char *) memcpy (__retval, "dialplan", __len); __retval; })) : __strdup ("dialplan" ))), (__extension__ (__builtin_constant_p ((cp->dialplan ? cp->dialplan : "")) && ((size_t)(const void *)((( cp->dialplan ? cp->dialplan : "")) + 1) - (size_t)(const void *)((cp->dialplan ? cp->dialplan : "")) == 1) ? (( (const char *) ((cp->dialplan ? cp->dialplan : "")))[0] == '\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len = strlen ((cp->dialplan ? cp->dialplan : "")) + 1 ; char *__retval = (char *) malloc (__len); if (__retval != ( (void*)0)) __retval = (char *) memcpy (__retval, (cp->dialplan ? cp->dialplan : ""), __len); __retval; })) : __strdup (( cp->dialplan ? cp->dialplan : ""))))); | |||||||||
| 2479 | if (cp->caller_extension->current_application) { | |||||||||
| 2480 | switch_xml_set_attr_d(x_caller_extension, "current_app", cp->caller_extension->current_application->application_name)switch_xml_set_attr(switch_xml_set_flag(x_caller_extension, SWITCH_XML_DUP ), (__extension__ (__builtin_constant_p ("current_app") && ((size_t)(const void *)(("current_app") + 1) - (size_t)(const void *)("current_app") == 1) ? (((const char *) ("current_app" ))[0] == '\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len = strlen ("current_app") + 1; char *__retval = ( char *) malloc (__len); if (__retval != ((void*)0)) __retval = (char *) memcpy (__retval, "current_app", __len); __retval; } )) : __strdup ("current_app"))), (__extension__ (__builtin_constant_p ((cp->caller_extension->current_application->application_name ? cp->caller_extension->current_application->application_name : "")) && ((size_t)(const void *)(((cp->caller_extension ->current_application->application_name ? cp->caller_extension ->current_application->application_name : "")) + 1) - ( size_t)(const void *)((cp->caller_extension->current_application ->application_name ? cp->caller_extension->current_application ->application_name : "")) == 1) ? (((const char *) ((cp-> caller_extension->current_application->application_name ? cp->caller_extension->current_application->application_name : "")))[0] == '\0' ? (char *) calloc ((size_t) 1, (size_t) 1 ) : ({ size_t __len = strlen ((cp->caller_extension->current_application ->application_name ? cp->caller_extension->current_application ->application_name : "")) + 1; char *__retval = (char *) malloc (__len); if (__retval != ((void*)0)) __retval = (char *) memcpy (__retval, (cp->caller_extension->current_application-> application_name ? cp->caller_extension->current_application ->application_name : ""), __len); __retval; })) : __strdup ((cp->caller_extension->current_application->application_name ? cp->caller_extension->current_application->application_name : ""))))); | |||||||||
| 2481 | } | |||||||||
| 2482 | ||||||||||
| 2483 | for (ap = cp->caller_extension->applications; ap; ap = ap->next) { | |||||||||
| 2484 | if (!(x_application = switch_xml_add_child_d(x_caller_extension, "application", i_app_off++)switch_xml_set_flag(switch_xml_add_child(x_caller_extension, ( __extension__ (__builtin_constant_p ("application") && ((size_t)(const void *)(("application") + 1) - (size_t)(const void *)("application") == 1) ? (((const char *) ("application" ))[0] == '\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len = strlen ("application") + 1; char *__retval = ( char *) malloc (__len); if (__retval != ((void*)0)) __retval = (char *) memcpy (__retval, "application", __len); __retval; } )) : __strdup ("application"))), i_app_off++), SWITCH_XML_NAMEM ))) { | |||||||||
| 2485 | goto error; | |||||||||
| 2486 | } | |||||||||
| 2487 | if (ap == cp->caller_extension->current_application) { | |||||||||
| 2488 | switch_xml_set_attr_d(x_application, "last_executed", "true")switch_xml_set_attr(switch_xml_set_flag(x_application, SWITCH_XML_DUP ), (__extension__ (__builtin_constant_p ("last_executed") && ((size_t)(const void *)(("last_executed") + 1) - (size_t)(const void *)("last_executed") == 1) ? (((const char *) ("last_executed" ))[0] == '\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len = strlen ("last_executed") + 1; char *__retval = (char *) malloc (__len); if (__retval != ((void*)0)) __retval = (char *) memcpy (__retval, "last_executed", __len); __retval ; })) : __strdup ("last_executed"))), (__extension__ (__builtin_constant_p (("true" ? "true" : "")) && ((size_t)(const void *)( (("true" ? "true" : "")) + 1) - (size_t)(const void *)(("true" ? "true" : "")) == 1) ? (((const char *) (("true" ? "true" : "")))[0] == '\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len = strlen (("true" ? "true" : "")) + 1; char * __retval = (char *) malloc (__len); if (__retval != ((void*)0 )) __retval = (char *) memcpy (__retval, ("true" ? "true" : "" ), __len); __retval; })) : __strdup (("true" ? "true" : ""))) )); | |||||||||
| 2489 | } | |||||||||
| 2490 | switch_xml_set_attr_d(x_application, "app_name", ap->application_name)switch_xml_set_attr(switch_xml_set_flag(x_application, SWITCH_XML_DUP ), (__extension__ (__builtin_constant_p ("app_name") && ((size_t)(const void *)(("app_name") + 1) - (size_t)(const void *)("app_name") == 1) ? (((const char *) ("app_name"))[0] == '\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len = strlen ("app_name") + 1; char *__retval = (char *) malloc ( __len); if (__retval != ((void*)0)) __retval = (char *) memcpy (__retval, "app_name", __len); __retval; })) : __strdup ("app_name" ))), (__extension__ (__builtin_constant_p ((ap->application_name ? ap->application_name : "")) && ((size_t)(const void *)(((ap->application_name ? ap->application_name : "") ) + 1) - (size_t)(const void *)((ap->application_name ? ap ->application_name : "")) == 1) ? (((const char *) ((ap-> application_name ? ap->application_name : "")))[0] == '\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len = strlen ((ap->application_name ? ap->application_name : "")) + 1; char *__retval = (char *) malloc (__len); if (__retval != ((void*)0)) __retval = (char *) memcpy (__retval, (ap-> application_name ? ap->application_name : ""), __len); __retval ; })) : __strdup ((ap->application_name ? ap->application_name : ""))))); | |||||||||
| 2491 | switch_xml_set_attr_d(x_application, "app_data", ap->application_data)switch_xml_set_attr(switch_xml_set_flag(x_application, SWITCH_XML_DUP ), (__extension__ (__builtin_constant_p ("app_data") && ((size_t)(const void *)(("app_data") + 1) - (size_t)(const void *)("app_data") == 1) ? (((const char *) ("app_data"))[0] == '\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len = strlen ("app_data") + 1; char *__retval = (char *) malloc ( __len); if (__retval != ((void*)0)) __retval = (char *) memcpy (__retval, "app_data", __len); __retval; })) : __strdup ("app_data" ))), (__extension__ (__builtin_constant_p ((ap->application_data ? ap->application_data : "")) && ((size_t)(const void *)(((ap->application_data ? ap->application_data : "") ) + 1) - (size_t)(const void *)((ap->application_data ? ap ->application_data : "")) == 1) ? (((const char *) ((ap-> application_data ? ap->application_data : "")))[0] == '\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len = strlen ((ap->application_data ? ap->application_data : "")) + 1; char *__retval = (char *) malloc (__len); if (__retval != ((void*)0)) __retval = (char *) memcpy (__retval, (ap-> application_data ? ap->application_data : ""), __len); __retval ; })) : __strdup ((ap->application_data ? ap->application_data : ""))))); | |||||||||
| 2492 | } | |||||||||
| 2493 | } | |||||||||
| 2494 | } | |||||||||
| 2495 | } | |||||||||
| 2496 | ||||||||||
| 2497 | if (!(x_main_cp = switch_xml_add_child_d(x_callflow, "caller_profile", cf_off++)switch_xml_set_flag(switch_xml_add_child(x_callflow, (__extension__ (__builtin_constant_p ("caller_profile") && ((size_t )(const void *)(("caller_profile") + 1) - (size_t)(const void *)("caller_profile") == 1) ? (((const char *) ("caller_profile" ))[0] == '\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len = strlen ("caller_profile") + 1; char *__retval = (char *) malloc (__len); if (__retval != ((void*)0)) __retval = (char *) memcpy (__retval, "caller_profile", __len); __retval ; })) : __strdup ("caller_profile"))), cf_off++), SWITCH_XML_NAMEM ))) { | |||||||||
| 2498 | goto error; | |||||||||
| 2499 | } | |||||||||
| 2500 | ||||||||||
| 2501 | cp_off += switch_ivr_set_xml_profile_data(x_main_cp, caller_profile, 0); | |||||||||
| 2502 | ||||||||||
| 2503 | if (caller_profile->origination_caller_profile) { | |||||||||
| 2504 | switch_caller_profile_t *cp = NULL((void*)0); | |||||||||
| 2505 | int off = 0; | |||||||||
| 2506 | if (!(x_o = switch_xml_add_child_d(x_main_cp, "origination", cp_off++)switch_xml_set_flag(switch_xml_add_child(x_main_cp, (__extension__ (__builtin_constant_p ("origination") && ((size_t)(const void *)(("origination") + 1) - (size_t)(const void *)("origination" ) == 1) ? (((const char *) ("origination"))[0] == '\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len = strlen ("origination") + 1; char *__retval = (char *) malloc (__len ); if (__retval != ((void*)0)) __retval = (char *) memcpy (__retval , "origination", __len); __retval; })) : __strdup ("origination" ))), cp_off++), SWITCH_XML_NAMEM))) { | |||||||||
| 2507 | goto error; | |||||||||
| 2508 | } | |||||||||
| 2509 | ||||||||||
| 2510 | for (cp = caller_profile->origination_caller_profile; cp; cp = cp->next) { | |||||||||
| 2511 | if (!(x_caller_profile = switch_xml_add_child_d(x_o, "origination_caller_profile", off++)switch_xml_set_flag(switch_xml_add_child(x_o, (__extension__ ( __builtin_constant_p ("origination_caller_profile") && ((size_t)(const void *)(("origination_caller_profile") + 1) - (size_t)(const void *)("origination_caller_profile") == 1) ? (((const char *) ("origination_caller_profile"))[0] == '\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len = strlen ("origination_caller_profile") + 1; char *__retval = ( char *) malloc (__len); if (__retval != ((void*)0)) __retval = (char *) memcpy (__retval, "origination_caller_profile", __len ); __retval; })) : __strdup ("origination_caller_profile"))), off++), SWITCH_XML_NAMEM))) { | |||||||||
| 2512 | goto error; | |||||||||
| 2513 | } | |||||||||
| 2514 | switch_ivr_set_xml_profile_data(x_caller_profile, cp, 0); | |||||||||
| 2515 | } | |||||||||
| 2516 | } | |||||||||
| 2517 | ||||||||||
| 2518 | if (caller_profile->originator_caller_profile) { | |||||||||
| 2519 | switch_caller_profile_t *cp = NULL((void*)0); | |||||||||
| 2520 | int off = 0; | |||||||||
| 2521 | if (!(x_o = switch_xml_add_child_d(x_main_cp, "originator", cp_off++)switch_xml_set_flag(switch_xml_add_child(x_main_cp, (__extension__ (__builtin_constant_p ("originator") && ((size_t)(const void *)(("originator") + 1) - (size_t)(const void *)("originator" ) == 1) ? (((const char *) ("originator"))[0] == '\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len = strlen ("originator") + 1; char *__retval = (char *) malloc (__len) ; if (__retval != ((void*)0)) __retval = (char *) memcpy (__retval , "originator", __len); __retval; })) : __strdup ("originator" ))), cp_off++), SWITCH_XML_NAMEM))) { | |||||||||
| 2522 | goto error; | |||||||||
| 2523 | } | |||||||||
| 2524 | ||||||||||
| 2525 | for (cp = caller_profile->originator_caller_profile; cp; cp = cp->next) { | |||||||||
| 2526 | if (!(x_caller_profile = switch_xml_add_child_d(x_o, "originator_caller_profile", off++)switch_xml_set_flag(switch_xml_add_child(x_o, (__extension__ ( __builtin_constant_p ("originator_caller_profile") && ((size_t)(const void *)(("originator_caller_profile") + 1) - (size_t)(const void *)("originator_caller_profile") == 1) ? ( ((const char *) ("originator_caller_profile"))[0] == '\0' ? ( char *) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len = strlen ("originator_caller_profile") + 1; char *__retval = (char *) malloc (__len); if (__retval != ((void*)0)) __retval = (char *) memcpy (__retval, "originator_caller_profile", __len); __retval ; })) : __strdup ("originator_caller_profile"))), off++), SWITCH_XML_NAMEM ))) { | |||||||||
| 2527 | goto error; | |||||||||
| 2528 | } | |||||||||
| 2529 | switch_ivr_set_xml_profile_data(x_caller_profile, cp, 0); | |||||||||
| 2530 | } | |||||||||
| 2531 | } | |||||||||
| 2532 | ||||||||||
| 2533 | if (caller_profile->originatee_caller_profile) { | |||||||||
| 2534 | switch_caller_profile_t *cp = NULL((void*)0); | |||||||||
| 2535 | int off = 0; | |||||||||
| 2536 | if (!(x_o = switch_xml_add_child_d(x_main_cp, "originatee", cp_off++)switch_xml_set_flag(switch_xml_add_child(x_main_cp, (__extension__ (__builtin_constant_p ("originatee") && ((size_t)(const void *)(("originatee") + 1) - (size_t)(const void *)("originatee" ) == 1) ? (((const char *) ("originatee"))[0] == '\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len = strlen ("originatee") + 1; char *__retval = (char *) malloc (__len) ; if (__retval != ((void*)0)) __retval = (char *) memcpy (__retval , "originatee", __len); __retval; })) : __strdup ("originatee" ))), cp_off++), SWITCH_XML_NAMEM))) { | |||||||||
| 2537 | goto error; | |||||||||
| 2538 | } | |||||||||
| 2539 | for (cp = caller_profile->originatee_caller_profile; cp; cp = cp->next) { | |||||||||
| 2540 | if (!(x_caller_profile = switch_xml_add_child_d(x_o, "originatee_caller_profile", off++)switch_xml_set_flag(switch_xml_add_child(x_o, (__extension__ ( __builtin_constant_p ("originatee_caller_profile") && ((size_t)(const void *)(("originatee_caller_profile") + 1) - (size_t)(const void *)("originatee_caller_profile") == 1) ? ( ((const char *) ("originatee_caller_profile"))[0] == '\0' ? ( char *) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len = strlen ("originatee_caller_profile") + 1; char *__retval = (char *) malloc (__len); if (__retval != ((void*)0)) __retval = (char *) memcpy (__retval, "originatee_caller_profile", __len); __retval ; })) : __strdup ("originatee_caller_profile"))), off++), SWITCH_XML_NAMEM ))) { | |||||||||
| 2541 | goto error; | |||||||||
| 2542 | } | |||||||||
| 2543 | switch_ivr_set_xml_profile_data(x_caller_profile, cp, 0); | |||||||||
| 2544 | } | |||||||||
| 2545 | } | |||||||||
| 2546 | ||||||||||
| 2547 | if (caller_profile->times) { | |||||||||
| 2548 | int t_off = 0; | |||||||||
| 2549 | if (!(x_times = switch_xml_add_child_d(x_callflow, "times", cf_off++)switch_xml_set_flag(switch_xml_add_child(x_callflow, (__extension__ (__builtin_constant_p ("times") && ((size_t)(const void *)(("times") + 1) - (size_t)(const void *)("times") == 1) ? ( ((const char *) ("times"))[0] == '\0' ? (char *) calloc ((size_t ) 1, (size_t) 1) : ({ size_t __len = strlen ("times") + 1; char *__retval = (char *) malloc (__len); if (__retval != ((void* )0)) __retval = (char *) memcpy (__retval, "times", __len); __retval ; })) : __strdup ("times"))), cf_off++), SWITCH_XML_NAMEM))) { | |||||||||
| 2550 | goto error; | |||||||||
| 2551 | } | |||||||||
| 2552 | if (!(time_tag = switch_xml_add_child_d(x_times, "created_time", t_off++)switch_xml_set_flag(switch_xml_add_child(x_times, (__extension__ (__builtin_constant_p ("created_time") && ((size_t)( const void *)(("created_time") + 1) - (size_t)(const void *)( "created_time") == 1) ? (((const char *) ("created_time"))[0] == '\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len = strlen ("created_time") + 1; char *__retval = (char * ) malloc (__len); if (__retval != ((void*)0)) __retval = (char *) memcpy (__retval, "created_time", __len); __retval; })) : __strdup ("created_time"))), t_off++), SWITCH_XML_NAMEM))) { | |||||||||
| 2553 | goto error; | |||||||||
| 2554 | } | |||||||||
| 2555 | switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT"ld", caller_profile->times->created); | |||||||||
| 2556 | switch_xml_set_txt_d(time_tag, tmp)switch_xml_set_flag(switch_xml_set_txt(time_tag, (__extension__ (__builtin_constant_p (tmp) && ((size_t)(const void * )((tmp) + 1) - (size_t)(const void *)(tmp) == 1) ? (((const char *) (tmp))[0] == '\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len = strlen (tmp) + 1; char *__retval = (char *) malloc (__len); if (__retval != ((void*)0)) __retval = (char *) memcpy (__retval, tmp, __len); __retval; })) : __strdup ( tmp)))), SWITCH_XML_TXTM); | |||||||||
| 2557 | ||||||||||
| 2558 | if (!(time_tag = switch_xml_add_child_d(x_times, "profile_created_time", t_off++)switch_xml_set_flag(switch_xml_add_child(x_times, (__extension__ (__builtin_constant_p ("profile_created_time") && (( size_t)(const void *)(("profile_created_time") + 1) - (size_t )(const void *)("profile_created_time") == 1) ? (((const char *) ("profile_created_time"))[0] == '\0' ? (char *) calloc (( size_t) 1, (size_t) 1) : ({ size_t __len = strlen ("profile_created_time" ) + 1; char *__retval = (char *) malloc (__len); if (__retval != ((void*)0)) __retval = (char *) memcpy (__retval, "profile_created_time" , __len); __retval; })) : __strdup ("profile_created_time"))) , t_off++), SWITCH_XML_NAMEM))) { | |||||||||
| 2559 | goto error; | |||||||||
| 2560 | } | |||||||||
| 2561 | switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT"ld", caller_profile->times->profile_created); | |||||||||
| 2562 | switch_xml_set_txt_d(time_tag, tmp)switch_xml_set_flag(switch_xml_set_txt(time_tag, (__extension__ (__builtin_constant_p (tmp) && ((size_t)(const void * )((tmp) + 1) - (size_t)(const void *)(tmp) == 1) ? (((const char *) (tmp))[0] == '\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len = strlen (tmp) + 1; char *__retval = (char *) malloc (__len); if (__retval != ((void*)0)) __retval = (char *) memcpy (__retval, tmp, __len); __retval; })) : __strdup ( tmp)))), SWITCH_XML_TXTM); | |||||||||
| 2563 | ||||||||||
| 2564 | if (!(time_tag = switch_xml_add_child_d(x_times, "progress_time", t_off++)switch_xml_set_flag(switch_xml_add_child(x_times, (__extension__ (__builtin_constant_p ("progress_time") && ((size_t) (const void *)(("progress_time") + 1) - (size_t)(const void * )("progress_time") == 1) ? (((const char *) ("progress_time") )[0] == '\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len = strlen ("progress_time") + 1; char *__retval = (char *) malloc (__len); if (__retval != ((void*)0)) __retval = (char *) memcpy (__retval, "progress_time", __len); __retval; })) : __strdup ("progress_time"))), t_off++), SWITCH_XML_NAMEM))) { | |||||||||
| 2565 | goto error; | |||||||||
| 2566 | } | |||||||||
| 2567 | switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT"ld", caller_profile->times->progress); | |||||||||
| 2568 | switch_xml_set_txt_d(time_tag, tmp)switch_xml_set_flag(switch_xml_set_txt(time_tag, (__extension__ (__builtin_constant_p (tmp) && ((size_t)(const void * )((tmp) + 1) - (size_t)(const void *)(tmp) == 1) ? (((const char *) (tmp))[0] == '\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len = strlen (tmp) + 1; char *__retval = (char *) malloc (__len); if (__retval != ((void*)0)) __retval = (char *) memcpy (__retval, tmp, __len); __retval; })) : __strdup ( tmp)))), SWITCH_XML_TXTM); | |||||||||
| 2569 | ||||||||||
| 2570 | ||||||||||
| 2571 | if (!(time_tag = switch_xml_add_child_d(x_times, "progress_media_time", t_off++)switch_xml_set_flag(switch_xml_add_child(x_times, (__extension__ (__builtin_constant_p ("progress_media_time") && ((size_t )(const void *)(("progress_media_time") + 1) - (size_t)(const void *)("progress_media_time") == 1) ? (((const char *) ("progress_media_time" ))[0] == '\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len = strlen ("progress_media_time") + 1; char *__retval = (char *) malloc (__len); if (__retval != ((void*)0)) __retval = (char *) memcpy (__retval, "progress_media_time", __len); __retval ; })) : __strdup ("progress_media_time"))), t_off++), SWITCH_XML_NAMEM ))) { | |||||||||
| 2572 | goto error; | |||||||||
| 2573 | } | |||||||||
| 2574 | switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT"ld", caller_profile->times->progress_media); | |||||||||
| 2575 | switch_xml_set_txt_d(time_tag, tmp)switch_xml_set_flag(switch_xml_set_txt(time_tag, (__extension__ (__builtin_constant_p (tmp) && ((size_t)(const void * )((tmp) + 1) - (size_t)(const void *)(tmp) == 1) ? (((const char *) (tmp))[0] == '\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len = strlen (tmp) + 1; char *__retval = (char *) malloc (__len); if (__retval != ((void*)0)) __retval = (char *) memcpy (__retval, tmp, __len); __retval; })) : __strdup ( tmp)))), SWITCH_XML_TXTM); | |||||||||
| 2576 | ||||||||||
| 2577 | if (!(time_tag = switch_xml_add_child_d(x_times, "answered_time", t_off++)switch_xml_set_flag(switch_xml_add_child(x_times, (__extension__ (__builtin_constant_p ("answered_time") && ((size_t) (const void *)(("answered_time") + 1) - (size_t)(const void * )("answered_time") == 1) ? (((const char *) ("answered_time") )[0] == '\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len = strlen ("answered_time") + 1; char *__retval = (char *) malloc (__len); if (__retval != ((void*)0)) __retval = (char *) memcpy (__retval, "answered_time", __len); __retval; })) : __strdup ("answered_time"))), t_off++), SWITCH_XML_NAMEM))) { | |||||||||
| 2578 | goto error; | |||||||||
| 2579 | } | |||||||||
| 2580 | switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT"ld", caller_profile->times->answered); | |||||||||
| 2581 | switch_xml_set_txt_d(time_tag, tmp)switch_xml_set_flag(switch_xml_set_txt(time_tag, (__extension__ (__builtin_constant_p (tmp) && ((size_t)(const void * )((tmp) + 1) - (size_t)(const void *)(tmp) == 1) ? (((const char *) (tmp))[0] == '\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len = strlen (tmp) + 1; char *__retval = (char *) malloc (__len); if (__retval != ((void*)0)) __retval = (char *) memcpy (__retval, tmp, __len); __retval; })) : __strdup ( tmp)))), SWITCH_XML_TXTM); | |||||||||
| 2582 | ||||||||||
| 2583 | if (!(time_tag = switch_xml_add_child_d(x_times, "bridged_time", t_off++)switch_xml_set_flag(switch_xml_add_child(x_times, (__extension__ (__builtin_constant_p ("bridged_time") && ((size_t)( const void *)(("bridged_time") + 1) - (size_t)(const void *)( "bridged_time") == 1) ? (((const char *) ("bridged_time"))[0] == '\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len = strlen ("bridged_time") + 1; char *__retval = (char * ) malloc (__len); if (__retval != ((void*)0)) __retval = (char *) memcpy (__retval, "bridged_time", __len); __retval; })) : __strdup ("bridged_time"))), t_off++), SWITCH_XML_NAMEM))) { | |||||||||
| 2584 | goto error; | |||||||||
| 2585 | } | |||||||||
| 2586 | switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT"ld", caller_profile->times->bridged); | |||||||||
| 2587 | switch_xml_set_txt_d(time_tag, tmp)switch_xml_set_flag(switch_xml_set_txt(time_tag, (__extension__ (__builtin_constant_p (tmp) && ((size_t)(const void * )((tmp) + 1) - (size_t)(const void *)(tmp) == 1) ? (((const char *) (tmp))[0] == '\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len = strlen (tmp) + 1; char *__retval = (char *) malloc (__len); if (__retval != ((void*)0)) __retval = (char *) memcpy (__retval, tmp, __len); __retval; })) : __strdup ( tmp)))), SWITCH_XML_TXTM); | |||||||||
| 2588 | ||||||||||
| 2589 | if (!(time_tag = switch_xml_add_child_d(x_times, "last_hold_time", t_off++)switch_xml_set_flag(switch_xml_add_child(x_times, (__extension__ (__builtin_constant_p ("last_hold_time") && ((size_t )(const void *)(("last_hold_time") + 1) - (size_t)(const void *)("last_hold_time") == 1) ? (((const char *) ("last_hold_time" ))[0] == '\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len = strlen ("last_hold_time") + 1; char *__retval = (char *) malloc (__len); if (__retval != ((void*)0)) __retval = (char *) memcpy (__retval, "last_hold_time", __len); __retval ; })) : __strdup ("last_hold_time"))), t_off++), SWITCH_XML_NAMEM ))) { | |||||||||
| 2590 | goto error; | |||||||||
| 2591 | } | |||||||||
| 2592 | switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT"ld", caller_profile->times->last_hold); | |||||||||
| 2593 | switch_xml_set_txt_d(time_tag, tmp)switch_xml_set_flag(switch_xml_set_txt(time_tag, (__extension__ (__builtin_constant_p (tmp) && ((size_t)(const void * )((tmp) + 1) - (size_t)(const void *)(tmp) == 1) ? (((const char *) (tmp))[0] == '\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len = strlen (tmp) + 1; char *__retval = (char *) malloc (__len); if (__retval != ((void*)0)) __retval = (char *) memcpy (__retval, tmp, __len); __retval; })) : __strdup ( tmp)))), SWITCH_XML_TXTM); | |||||||||
| 2594 | ||||||||||
| 2595 | if (!(time_tag = switch_xml_add_child_d(x_times, "hold_accum_time", t_off++)switch_xml_set_flag(switch_xml_add_child(x_times, (__extension__ (__builtin_constant_p ("hold_accum_time") && ((size_t )(const void *)(("hold_accum_time") + 1) - (size_t)(const void *)("hold_accum_time") == 1) ? (((const char *) ("hold_accum_time" ))[0] == '\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len = strlen ("hold_accum_time") + 1; char *__retval = (char *) malloc (__len); if (__retval != ((void*)0)) __retval = (char *) memcpy (__retval, "hold_accum_time", __len); __retval ; })) : __strdup ("hold_accum_time"))), t_off++), SWITCH_XML_NAMEM ))) { | |||||||||
| 2596 | goto error; | |||||||||
| 2597 | } | |||||||||
| 2598 | switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT"ld", caller_profile->times->hold_accum); | |||||||||
| 2599 | switch_xml_set_txt_d(time_tag, tmp)switch_xml_set_flag(switch_xml_set_txt(time_tag, (__extension__ (__builtin_constant_p (tmp) && ((size_t)(const void * )((tmp) + 1) - (size_t)(const void *)(tmp) == 1) ? (((const char *) (tmp))[0] == '\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len = strlen (tmp) + 1; char *__retval = (char *) malloc (__len); if (__retval != ((void*)0)) __retval = (char *) memcpy (__retval, tmp, __len); __retval; })) : __strdup ( tmp)))), SWITCH_XML_TXTM); | |||||||||
| 2600 | ||||||||||
| 2601 | if (!(time_tag = switch_xml_add_child_d(x_times, "hangup_time", t_off++)switch_xml_set_flag(switch_xml_add_child(x_times, (__extension__ (__builtin_constant_p ("hangup_time") && ((size_t)(const void *)(("hangup_time") + 1) - (size_t)(const void *)("hangup_time" ) == 1) ? (((const char *) ("hangup_time"))[0] == '\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len = strlen ("hangup_time") + 1; char *__retval = (char *) malloc (__len ); if (__retval != ((void*)0)) __retval = (char *) memcpy (__retval , "hangup_time", __len); __retval; })) : __strdup ("hangup_time" ))), t_off++), SWITCH_XML_NAMEM))) { | |||||||||
| 2602 | goto error; | |||||||||
| 2603 | } | |||||||||
| 2604 | switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT"ld", caller_profile->times->hungup); | |||||||||
| 2605 | switch_xml_set_txt_d(time_tag, tmp)switch_xml_set_flag(switch_xml_set_txt(time_tag, (__extension__ (__builtin_constant_p (tmp) && ((size_t)(const void * )((tmp) + 1) - (size_t)(const void *)(tmp) == 1) ? (((const char *) (tmp))[0] == '\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len = strlen (tmp) + 1; char *__retval = (char *) malloc (__len); if (__retval != ((void*)0)) __retval = (char *) memcpy (__retval, tmp, __len); __retval; })) : __strdup ( tmp)))), SWITCH_XML_TXTM); | |||||||||
| 2606 | ||||||||||
| 2607 | if (!(time_tag = switch_xml_add_child_d(x_times, "resurrect_time", t_off++)switch_xml_set_flag(switch_xml_add_child(x_times, (__extension__ (__builtin_constant_p ("resurrect_time") && ((size_t )(const void *)(("resurrect_time") + 1) - (size_t)(const void *)("resurrect_time") == 1) ? (((const char *) ("resurrect_time" ))[0] == '\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len = strlen ("resurrect_time") + 1; char *__retval = (char *) malloc (__len); if (__retval != ((void*)0)) __retval = (char *) memcpy (__retval, "resurrect_time", __len); __retval ; })) : __strdup ("resurrect_time"))), t_off++), SWITCH_XML_NAMEM ))) { | |||||||||
| 2608 | goto error; | |||||||||
| 2609 | } | |||||||||
| 2610 | switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT"ld", caller_profile->times->resurrected); | |||||||||
| 2611 | switch_xml_set_txt_d(time_tag, tmp)switch_xml_set_flag(switch_xml_set_txt(time_tag, (__extension__ (__builtin_constant_p (tmp) && ((size_t)(const void * )((tmp) + 1) - (size_t)(const void *)(tmp) == 1) ? (((const char *) (tmp))[0] == '\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len = strlen (tmp) + 1; char *__retval = (char *) malloc (__len); if (__retval != ((void*)0)) __retval = (char *) memcpy (__retval, tmp, __len); __retval; })) : __strdup ( tmp)))), SWITCH_XML_TXTM); | |||||||||
| 2612 | ||||||||||
| 2613 | if (!(time_tag = switch_xml_add_child_d(x_times, "transfer_time", t_off++)switch_xml_set_flag(switch_xml_add_child(x_times, (__extension__ (__builtin_constant_p ("transfer_time") && ((size_t) (const void *)(("transfer_time") + 1) - (size_t)(const void * )("transfer_time") == 1) ? (((const char *) ("transfer_time") )[0] == '\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len = strlen ("transfer_time") + 1; char *__retval = (char *) malloc (__len); if (__retval != ((void*)0)) __retval = (char *) memcpy (__retval, "transfer_time", __len); __retval; })) : __strdup ("transfer_time"))), t_off++), SWITCH_XML_NAMEM))) { | |||||||||
| 2614 | goto error; | |||||||||
| 2615 | } | |||||||||
| 2616 | switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT"ld", caller_profile->times->transferred); | |||||||||
| 2617 | switch_xml_set_txt_d(time_tag, tmp)switch_xml_set_flag(switch_xml_set_txt(time_tag, (__extension__ (__builtin_constant_p (tmp) && ((size_t)(const void * )((tmp) + 1) - (size_t)(const void *)(tmp) == 1) ? (((const char *) (tmp))[0] == '\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len = strlen (tmp) + 1; char *__retval = (char *) malloc (__len); if (__retval != ((void*)0)) __retval = (char *) memcpy (__retval, tmp, __len); __retval; })) : __strdup ( tmp)))), SWITCH_XML_TXTM); | |||||||||
| 2618 | } | |||||||||
| 2619 | ||||||||||
| 2620 | caller_profile = caller_profile->next; | |||||||||
| 2621 | } | |||||||||
| 2622 | ||||||||||
| 2623 | *xml_cdr = cdr; | |||||||||
| 2624 | ||||||||||
| 2625 | return SWITCH_STATUS_SUCCESS; | |||||||||
| 2626 | ||||||||||
| 2627 | error: | |||||||||
| 2628 | ||||||||||
| 2629 | if (cdr) { | |||||||||
| 2630 | switch_xml_free(cdr); | |||||||||
| 2631 | } | |||||||||
| 2632 | ||||||||||
| 2633 | return SWITCH_STATUS_FALSE; | |||||||||
| 2634 | } | |||||||||
| 2635 | ||||||||||
| 2636 | static void switch_ivr_set_json_profile_data(cJSON *json, switch_caller_profile_t *caller_profile) | |||||||||
| 2637 | { | |||||||||
| 2638 | cJSON_AddItemToObject(json, "username", cJSON_CreateString((char *)caller_profile->username)); | |||||||||
| 2639 | cJSON_AddItemToObject(json, "dialplan", cJSON_CreateString((char *)caller_profile->dialplan)); | |||||||||
| 2640 | cJSON_AddItemToObject(json, "caller_id_name", cJSON_CreateString((char *)caller_profile->caller_id_name)); | |||||||||
| 2641 | cJSON_AddItemToObject(json, "ani", cJSON_CreateString((char *)caller_profile->ani)); | |||||||||
| 2642 | cJSON_AddItemToObject(json, "aniii", cJSON_CreateString((char *)caller_profile->aniii)); | |||||||||
| 2643 | cJSON_AddItemToObject(json, "caller_id_number", cJSON_CreateString((char *)caller_profile->caller_id_number)); | |||||||||
| 2644 | cJSON_AddItemToObject(json, "network_addr", cJSON_CreateString((char *)caller_profile->network_addr)); | |||||||||
| 2645 | cJSON_AddItemToObject(json, "rdnis", cJSON_CreateString((char *)caller_profile->rdnis)); | |||||||||
| 2646 | cJSON_AddItemToObject(json, "destination_number", cJSON_CreateString(caller_profile->destination_number)); | |||||||||
| 2647 | cJSON_AddItemToObject(json, "uuid", cJSON_CreateString(caller_profile->uuid)); | |||||||||
| 2648 | cJSON_AddItemToObject(json, "source", cJSON_CreateString((char *)caller_profile->source)); | |||||||||
| 2649 | cJSON_AddItemToObject(json, "context", cJSON_CreateString((char *)caller_profile->context)); | |||||||||
| 2650 | cJSON_AddItemToObject(json, "chan_name", cJSON_CreateString(caller_profile->chan_name)); | |||||||||
| 2651 | } | |||||||||
| 2652 | ||||||||||
| 2653 | static void switch_ivr_set_json_chan_vars(cJSON *json, switch_channel_t *channel, switch_bool_t urlencode) | |||||||||
| 2654 | { | |||||||||
| 2655 | switch_event_header_t *hi = switch_channel_variable_first(channel); | |||||||||
| 2656 | ||||||||||
| 2657 | if (!hi) | |||||||||
| 2658 | return; | |||||||||
| 2659 | ||||||||||
| 2660 | for (; hi; hi = hi->next) { | |||||||||
| 2661 | if (!zstr(hi->name)_zstr(hi->name) && !zstr(hi->value)_zstr(hi->value)) { | |||||||||
| 2662 | char *data = hi->value; | |||||||||
| 2663 | if (urlencode) { | |||||||||
| 2664 | switch_size_t dlen = strlen(hi->value) * 3; | |||||||||
| 2665 | ||||||||||
| 2666 | if ((data = malloc(dlen))) { | |||||||||
| 2667 | memset(data, 0, dlen); | |||||||||
| 2668 | switch_url_encode(hi->value, data, dlen); | |||||||||
| 2669 | } | |||||||||
| 2670 | } | |||||||||
| 2671 | ||||||||||
| 2672 | cJSON_AddItemToObject(json, hi->name, cJSON_CreateString(data)); | |||||||||
| 2673 | ||||||||||
| 2674 | if (data != hi->value) { | |||||||||
| 2675 | switch_safe_free(data)if (data) {free(data);data=((void*)0);}; | |||||||||
| 2676 | } | |||||||||
| 2677 | } | |||||||||
| 2678 | } | |||||||||
| 2679 | switch_channel_variable_last(channel); | |||||||||
| 2680 | } | |||||||||
| 2681 | ||||||||||
| 2682 | ||||||||||
| 2683 | ||||||||||
| 2684 | SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_ivr_generate_json_cdr(switch_core_session_t *session, cJSON **json_cdr, switch_bool_t urlencode) | |||||||||
| 2685 | { | |||||||||
| 2686 | cJSON *cdr = cJSON_CreateObject(); | |||||||||
| 2687 | switch_channel_t *channel = switch_core_session_get_channel(session); | |||||||||
| 2688 | switch_caller_profile_t *caller_profile; | |||||||||
| 2689 | cJSON *variables, *j_main_cp, *j_caller_profile, *j_caller_extension, *j_caller_extension_apps, *j_times, | |||||||||
| 2690 | *j_application, *j_callflow, *j_inner_extension, *j_app_log, *j_apps, *j_o, *j_o_profiles, *j_channel_data; | |||||||||
| 2691 | switch_app_log_t *app_log; | |||||||||
| 2692 | char tmp[512], *f; | |||||||||
| 2693 | ||||||||||
| 2694 | cJSON_AddItemToObject(cdr, "core-uuid", cJSON_CreateString(switch_core_get_uuid())); | |||||||||
| 2695 | cJSON_AddItemToObject(cdr, "switchname", cJSON_CreateString(switch_core_get_switchname())); | |||||||||
| 2696 | j_channel_data = cJSON_CreateObject(); | |||||||||
| 2697 | ||||||||||
| 2698 | cJSON_AddItemToObject(cdr, "channel_data", j_channel_data); | |||||||||
| 2699 | ||||||||||
| 2700 | cJSON_AddItemToObject(j_channel_data, "state", cJSON_CreateString((char *) switch_channel_state_name(switch_channel_get_state(channel)))); | |||||||||
| 2701 | cJSON_AddItemToObject(j_channel_data, "direction", cJSON_CreateString(switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND ? "outbound" : "inbound")); | |||||||||
| 2702 | ||||||||||
| 2703 | switch_snprintf(tmp, sizeof(tmp), "%d", switch_channel_get_state(channel)); | |||||||||
| 2704 | cJSON_AddItemToObject(j_channel_data, "state_number", cJSON_CreateString((char *) tmp)); | |||||||||
| 2705 | ||||||||||
| 2706 | if ((f = switch_channel_get_flag_string(channel))) { | |||||||||
| 2707 | cJSON_AddItemToObject(j_channel_data, "flags", cJSON_CreateString((char *) f)); | |||||||||
| 2708 | free(f); | |||||||||
| 2709 | } | |||||||||
| 2710 | ||||||||||
| 2711 | if ((f = switch_channel_get_cap_string(channel))) { | |||||||||
| 2712 | cJSON_AddItemToObject(j_channel_data, "caps", cJSON_CreateString((char *) f)); | |||||||||
| 2713 | free(f); | |||||||||
| 2714 | } | |||||||||
| 2715 | ||||||||||
| 2716 | variables = cJSON_CreateObject(); | |||||||||
| 2717 | cJSON_AddItemToObject(cdr, "variables", variables); | |||||||||
| 2718 | ||||||||||
| 2719 | switch_ivr_set_json_chan_vars(variables, channel, urlencode); | |||||||||
| 2720 | ||||||||||
| 2721 | ||||||||||
| 2722 | if ((app_log = switch_core_session_get_app_log(session))) { | |||||||||
| 2723 | switch_app_log_t *ap; | |||||||||
| 2724 | ||||||||||
| 2725 | j_app_log = cJSON_CreateObject(); | |||||||||
| 2726 | j_apps = cJSON_CreateArray(); | |||||||||
| 2727 | ||||||||||
| 2728 | cJSON_AddItemToObject(cdr, "app_log", j_app_log); | |||||||||
| 2729 | cJSON_AddItemToObject(j_app_log, "applications", j_apps); | |||||||||
| 2730 | ||||||||||
| 2731 | for (ap = app_log; ap; ap = ap->next) { | |||||||||
| 2732 | j_application = cJSON_CreateObject(); | |||||||||
| 2733 | ||||||||||
| 2734 | cJSON_AddItemToObject(j_application, "app_name", cJSON_CreateString(ap->app)); | |||||||||
| 2735 | cJSON_AddItemToObject(j_application, "app_data", cJSON_CreateString(ap->arg)); | |||||||||
| 2736 | ||||||||||
| 2737 | cJSON_AddItemToArray(j_apps, j_application); | |||||||||
| 2738 | } | |||||||||
| 2739 | } | |||||||||
| 2740 | ||||||||||
| 2741 | ||||||||||
| 2742 | caller_profile = switch_channel_get_caller_profile(channel); | |||||||||
| 2743 | ||||||||||
| 2744 | while (caller_profile) { | |||||||||
| 2745 | ||||||||||
| 2746 | j_callflow = cJSON_CreateObject(); | |||||||||
| 2747 | ||||||||||
| 2748 | cJSON_AddItemToObject(cdr, "callflow", j_callflow); | |||||||||
| 2749 | ||||||||||
| 2750 | if (!zstr(caller_profile->dialplan)_zstr(caller_profile->dialplan)) { | |||||||||
| 2751 | cJSON_AddItemToObject(j_callflow, "dialplan", cJSON_CreateString((char *)caller_profile->dialplan)); | |||||||||
| 2752 | } | |||||||||
| 2753 | ||||||||||
| 2754 | if (!zstr(caller_profile->profile_index)_zstr(caller_profile->profile_index)) { | |||||||||
| 2755 | cJSON_AddItemToObject(j_callflow, "profile_index", cJSON_CreateString((char *)caller_profile->profile_index)); | |||||||||
| 2756 | } | |||||||||
| 2757 | ||||||||||
| 2758 | if (caller_profile->caller_extension) { | |||||||||
| 2759 | switch_caller_application_t *ap; | |||||||||
| 2760 | ||||||||||
| 2761 | j_caller_extension = cJSON_CreateObject(); | |||||||||
| 2762 | j_caller_extension_apps = cJSON_CreateArray(); | |||||||||
| 2763 | ||||||||||
| 2764 | cJSON_AddItemToObject(j_callflow, "extension", j_caller_extension); | |||||||||
| 2765 | ||||||||||
| 2766 | cJSON_AddItemToObject(j_caller_extension, "name", cJSON_CreateString(caller_profile->caller_extension->extension_name)); | |||||||||
| 2767 | cJSON_AddItemToObject(j_caller_extension, "number", cJSON_CreateString(caller_profile->caller_extension->extension_number)); | |||||||||
| 2768 | cJSON_AddItemToObject(j_caller_extension, "applications", j_caller_extension_apps); | |||||||||
| 2769 | ||||||||||
| 2770 | if (caller_profile->caller_extension->current_application) { | |||||||||
| 2771 | cJSON_AddItemToObject(j_caller_extension, "current_app", cJSON_CreateString(caller_profile->caller_extension->current_application->application_name)); | |||||||||
| 2772 | } | |||||||||
| 2773 | ||||||||||
| 2774 | for (ap = caller_profile->caller_extension->applications; ap; ap = ap->next) { | |||||||||
| 2775 | j_application = cJSON_CreateObject(); | |||||||||
| 2776 | ||||||||||
| 2777 | cJSON_AddItemToArray(j_caller_extension_apps, j_application); | |||||||||
| 2778 | ||||||||||
| 2779 | if (ap == caller_profile->caller_extension->current_application) { | |||||||||
| 2780 | cJSON_AddItemToObject(j_application, "last_executed", cJSON_CreateString("true")); | |||||||||
| 2781 | } | |||||||||
| 2782 | cJSON_AddItemToObject(j_application, "app_name", cJSON_CreateString(ap->application_name)); | |||||||||
| 2783 | cJSON_AddItemToObject(j_application, "app_data", cJSON_CreateString(switch_str_nil(ap->application_data)(ap->application_data ? ap->application_data : ""))); | |||||||||
| 2784 | } | |||||||||
| 2785 | ||||||||||
| 2786 | if (caller_profile->caller_extension->children) { | |||||||||
| 2787 | switch_caller_profile_t *cp = NULL((void*)0); | |||||||||
| 2788 | j_inner_extension = cJSON_CreateArray(); | |||||||||
| 2789 | cJSON_AddItemToObject(j_caller_extension, "sub_extensions", j_inner_extension); | |||||||||
| 2790 | for (cp = caller_profile->caller_extension->children; cp; cp = cp->next) { | |||||||||
| 2791 | ||||||||||
| 2792 | if (!cp->caller_extension) { | |||||||||
| 2793 | continue; | |||||||||
| 2794 | } | |||||||||
| 2795 | ||||||||||
| 2796 | j_caller_extension = cJSON_CreateObject(); | |||||||||
| 2797 | cJSON_AddItemToArray(j_inner_extension, j_caller_extension); | |||||||||
| 2798 | ||||||||||
| 2799 | cJSON_AddItemToObject(j_caller_extension, "name", cJSON_CreateString(cp->caller_extension->extension_name)); | |||||||||
| 2800 | cJSON_AddItemToObject(j_caller_extension, "number", cJSON_CreateString(cp->caller_extension->extension_number)); | |||||||||
| 2801 | ||||||||||
| 2802 | cJSON_AddItemToObject(j_caller_extension, "dialplan", cJSON_CreateString((char *)cp->dialplan)); | |||||||||
| 2803 | ||||||||||
| 2804 | if (cp->caller_extension->current_application) { | |||||||||
| 2805 | cJSON_AddItemToObject(j_caller_extension, "current_app", cJSON_CreateString(cp->caller_extension->current_application->application_name)); | |||||||||
| 2806 | } | |||||||||
| 2807 | ||||||||||
| 2808 | j_caller_extension_apps = cJSON_CreateArray(); | |||||||||
| 2809 | cJSON_AddItemToObject(j_caller_extension, "applications", j_caller_extension_apps); | |||||||||
| 2810 | for (ap = cp->caller_extension->applications; ap; ap = ap->next) { | |||||||||
| 2811 | j_application = cJSON_CreateObject(); | |||||||||
| 2812 | cJSON_AddItemToArray(j_caller_extension_apps, j_application); | |||||||||
| 2813 | ||||||||||
| 2814 | if (ap == cp->caller_extension->current_application) { | |||||||||
| 2815 | cJSON_AddItemToObject(j_application, "last_executed", cJSON_CreateString("true")); | |||||||||
| 2816 | } | |||||||||
| 2817 | cJSON_AddItemToObject(j_application, "app_name", cJSON_CreateString(ap->application_name)); | |||||||||
| 2818 | cJSON_AddItemToObject(j_application, "app_data", cJSON_CreateString(switch_str_nil(ap->application_data)(ap->application_data ? ap->application_data : ""))); | |||||||||
| 2819 | } | |||||||||
| 2820 | } | |||||||||
| 2821 | } | |||||||||
| 2822 | } | |||||||||
| 2823 | ||||||||||
| 2824 | j_main_cp = cJSON_CreateObject(); | |||||||||
| 2825 | cJSON_AddItemToObject(j_callflow, "caller_profile", j_main_cp); | |||||||||
| 2826 | ||||||||||
| 2827 | switch_ivr_set_json_profile_data(j_main_cp, caller_profile); | |||||||||
| 2828 | ||||||||||
| 2829 | if (caller_profile->originator_caller_profile) { | |||||||||
| 2830 | switch_caller_profile_t *cp = NULL((void*)0); | |||||||||
| 2831 | ||||||||||
| 2832 | j_o = cJSON_CreateObject(); | |||||||||
| 2833 | cJSON_AddItemToObject(j_main_cp, "originator", j_o); | |||||||||
| 2834 | ||||||||||
| 2835 | j_o_profiles = cJSON_CreateArray(); | |||||||||
| 2836 | cJSON_AddItemToObject(j_o, "originator_caller_profiles", j_o_profiles); | |||||||||
| 2837 | ||||||||||
| 2838 | for (cp = caller_profile->originator_caller_profile; cp; cp = cp->next) { | |||||||||
| 2839 | j_caller_profile = cJSON_CreateObject(); | |||||||||
| 2840 | cJSON_AddItemToArray(j_o_profiles, j_caller_profile); | |||||||||
| 2841 | ||||||||||
| 2842 | switch_ivr_set_json_profile_data(j_caller_profile, cp); | |||||||||
| 2843 | } | |||||||||
| 2844 | } | |||||||||
| 2845 | ||||||||||
| 2846 | if (caller_profile->originatee_caller_profile) { | |||||||||
| 2847 | switch_caller_profile_t *cp = NULL((void*)0); | |||||||||
| 2848 | ||||||||||
| 2849 | j_o = cJSON_CreateObject(); | |||||||||
| 2850 | cJSON_AddItemToObject(j_main_cp, "originatee", j_o); | |||||||||
| 2851 | ||||||||||
| 2852 | j_o_profiles = cJSON_CreateArray(); | |||||||||
| 2853 | cJSON_AddItemToObject(j_o, "originatee_caller_profiles", j_o_profiles); | |||||||||
| 2854 | ||||||||||
| 2855 | for (cp = caller_profile->originatee_caller_profile; cp; cp = cp->next) { | |||||||||
| 2856 | j_caller_profile = cJSON_CreateObject(); | |||||||||
| 2857 | cJSON_AddItemToArray(j_o_profiles, j_caller_profile); | |||||||||
| 2858 | ||||||||||
| 2859 | switch_ivr_set_json_profile_data(j_caller_profile, cp); | |||||||||
| 2860 | } | |||||||||
| 2861 | } | |||||||||
| 2862 | ||||||||||
| 2863 | if (caller_profile->times) { | |||||||||
| 2864 | ||||||||||
| 2865 | j_times = cJSON_CreateObject(); | |||||||||
| 2866 | cJSON_AddItemToObject(j_callflow, "times", j_times); | |||||||||
| 2867 | ||||||||||
| 2868 | switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT"ld", caller_profile->times->created); | |||||||||
| 2869 | cJSON_AddItemToObject(j_times, "created_time", cJSON_CreateString(tmp)); | |||||||||
| 2870 | ||||||||||
| 2871 | switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT"ld", caller_profile->times->profile_created); | |||||||||
| 2872 | cJSON_AddItemToObject(j_times, "profile_created_time", cJSON_CreateString(tmp)); | |||||||||
| 2873 | ||||||||||
| 2874 | switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT"ld", caller_profile->times->progress); | |||||||||
| 2875 | cJSON_AddItemToObject(j_times, "progress_time", cJSON_CreateString(tmp)); | |||||||||
| 2876 | ||||||||||
| 2877 | switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT"ld", caller_profile->times->progress_media); | |||||||||
| 2878 | cJSON_AddItemToObject(j_times, "progress_media_time", cJSON_CreateString(tmp)); | |||||||||
| 2879 | ||||||||||
| 2880 | switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT"ld", caller_profile->times->answered); | |||||||||
| 2881 | cJSON_AddItemToObject(j_times, "answered_time", cJSON_CreateString(tmp)); | |||||||||
| 2882 | ||||||||||
| 2883 | switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT"ld", caller_profile->times->bridged); | |||||||||
| 2884 | cJSON_AddItemToObject(j_times, "bridged_time", cJSON_CreateString(tmp)); | |||||||||
| 2885 | ||||||||||
| 2886 | switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT"ld", caller_profile->times->last_hold); | |||||||||
| 2887 | cJSON_AddItemToObject(j_times, "last_hold_time", cJSON_CreateString(tmp)); | |||||||||
| 2888 | ||||||||||
| 2889 | switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT"ld", caller_profile->times->hold_accum); | |||||||||
| 2890 | cJSON_AddItemToObject(j_times, "hold_accum_time", cJSON_CreateString(tmp)); | |||||||||
| 2891 | ||||||||||
| 2892 | switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT"ld", caller_profile->times->hungup); | |||||||||
| 2893 | cJSON_AddItemToObject(j_times, "hangup_time", cJSON_CreateString(tmp)); | |||||||||
| 2894 | ||||||||||
| 2895 | switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT"ld", caller_profile->times->resurrected); | |||||||||
| 2896 | cJSON_AddItemToObject(j_times, "resurrect_time", cJSON_CreateString(tmp)); | |||||||||
| 2897 | ||||||||||
| 2898 | switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT"ld", caller_profile->times->transferred); | |||||||||
| 2899 | cJSON_AddItemToObject(j_times, "transfer_time", cJSON_CreateString(tmp)); | |||||||||
| 2900 | ||||||||||
| 2901 | } | |||||||||
| 2902 | ||||||||||
| 2903 | caller_profile = caller_profile->next; | |||||||||
| 2904 | } | |||||||||
| 2905 | ||||||||||
| 2906 | *json_cdr = cdr; | |||||||||
| 2907 | ||||||||||
| 2908 | return SWITCH_STATUS_SUCCESS; | |||||||||
| 2909 | ||||||||||
| 2910 | } | |||||||||
| 2911 | ||||||||||
| 2912 | ||||||||||
| 2913 | SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_ivr_park_session(switch_core_session_t *session) | |||||||||
| 2914 | { | |||||||||
| 2915 | switch_channel_t *channel = switch_core_session_get_channel(session); | |||||||||
| 2916 | switch_channel_set_state(channel, CS_PARK)switch_channel_perform_set_state(channel, "src/switch_ivr.c", (const char *)__func__, 2916, CS_PARK); | |||||||||
| 2917 | switch_channel_set_flag(channel, CF_TRANSFER)switch_channel_set_flag_value(channel, CF_TRANSFER, 1); | |||||||||
| 2918 | ||||||||||
| 2919 | } | |||||||||
| 2920 | ||||||||||
| 2921 | SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_ivr_delay_echo(switch_core_session_t *session, uint32_t delay_ms) | |||||||||
| 2922 | { | |||||||||
| 2923 | stfu_instance_t *jb; | |||||||||
| 2924 | int qlen = 0; | |||||||||
| 2925 | stfu_frame_t *jb_frame; | |||||||||
| 2926 | switch_frame_t *read_frame, write_frame = { 0 }; | |||||||||
| 2927 | switch_status_t status; | |||||||||
| 2928 | switch_channel_t *channel = switch_core_session_get_channel(session); | |||||||||
| 2929 | uint32_t interval; | |||||||||
| 2930 | uint32_t ts = 0; | |||||||||
| 2931 | switch_codec_implementation_t read_impl = { 0 }; | |||||||||
| 2932 | switch_core_session_get_read_impl(session, &read_impl); | |||||||||
| 2933 | ||||||||||
| 2934 | ||||||||||
| 2935 | if (delay_ms < 1 || delay_ms > 10000) { | |||||||||
| 2936 | switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "src/switch_ivr.c", (const char *) __func__, 2936, (const char*)(session), SWITCH_LOG_ERROR, "Invalid delay [%d] must be between 1 and 10000\n", delay_ms); | |||||||||
| 2937 | return; | |||||||||
| 2938 | } | |||||||||
| 2939 | ||||||||||
| 2940 | interval = read_impl.microseconds_per_packet / 1000; | |||||||||
| 2941 | //samples = switch_samples_per_packet(read_impl.samples_per_second, interval); | |||||||||
| 2942 | ||||||||||
| 2943 | if (delay_ms < interval * 2) { | |||||||||
| 2944 | delay_ms = interval * 2; | |||||||||
| 2945 | switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "src/switch_ivr.c", (const char *) __func__, 2945, (const char*)(session), SWITCH_LOG_WARNING, "Minimum possible delay for this codec (%d) has been chosen\n", delay_ms); | |||||||||
| 2946 | } | |||||||||
| 2947 | ||||||||||
| 2948 | ||||||||||
| 2949 | qlen = delay_ms / (interval); | |||||||||
| 2950 | switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "src/switch_ivr.c", (const char *) __func__, 2950, (const char*)(session), SWITCH_LOG_DEBUG, "Setting delay to %dms (%d frames)\n", delay_ms, qlen); | |||||||||
| 2951 | jb = stfu_n_init(qlen, qlen, read_impl.samples_per_packet, read_impl.samples_per_second, 0); | |||||||||
| 2952 | ||||||||||
| 2953 | write_frame.codec = switch_core_session_get_read_codec(session); | |||||||||
| 2954 | ||||||||||
| 2955 | while (switch_channel_ready(channel)switch_channel_test_ready(channel, SWITCH_TRUE, SWITCH_FALSE)) { | |||||||||
| 2956 | status = switch_core_session_read_frame(session, &read_frame, SWITCH_IO_FLAG_NONE, 0); | |||||||||
| 2957 | if (!SWITCH_READ_ACCEPTABLE(status)(status == SWITCH_STATUS_SUCCESS || status == SWITCH_STATUS_BREAK || status == SWITCH_STATUS_INUSE)) { | |||||||||
| 2958 | break; | |||||||||
| 2959 | } | |||||||||
| 2960 | ||||||||||
| 2961 | stfu_n_eat(jb, ts, 0, read_frame->payload, read_frame->data, read_frame->datalen, 0)stfu_n_add_data(jb, ts, 0, read_frame->payload, read_frame ->data, read_frame->datalen, 0, 0); | |||||||||
| 2962 | ts += read_impl.samples_per_packet; | |||||||||
| 2963 | ||||||||||
| 2964 | if ((jb_frame = stfu_n_read_a_frame(jb))) { | |||||||||
| 2965 | write_frame.data = jb_frame->data; | |||||||||
| 2966 | write_frame.datalen = (uint32_t) jb_frame->dlen; | |||||||||
| 2967 | write_frame.buflen = (uint32_t) jb_frame->dlen; | |||||||||
| 2968 | status = switch_core_session_write_frame(session, &write_frame, SWITCH_IO_FLAG_NONE, 0); | |||||||||
| 2969 | if (!SWITCH_READ_ACCEPTABLE(status)(status == SWITCH_STATUS_SUCCESS || status == SWITCH_STATUS_BREAK || status == SWITCH_STATUS_INUSE)) { | |||||||||
| 2970 | break; | |||||||||
| 2971 | } | |||||||||
| 2972 | } | |||||||||
| 2973 | } | |||||||||
| 2974 | ||||||||||
| 2975 | stfu_n_destroy(&jb); | |||||||||
| 2976 | } | |||||||||
| 2977 | ||||||||||
| 2978 | SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_ivr_say(switch_core_session_t *session, | |||||||||
| 2979 | const char *tosay, | |||||||||
| 2980 | const char *module_name, | |||||||||
| 2981 | const char *say_type, | |||||||||
| 2982 | const char *say_method, | |||||||||
| 2983 | const char *say_gender, | |||||||||
| 2984 | switch_input_args_t *args) | |||||||||
| 2985 | { | |||||||||
| 2986 | switch_say_interface_t *si; | |||||||||
| 2987 | switch_channel_t *channel; | |||||||||
| 2988 | switch_status_t status = SWITCH_STATUS_FALSE; | |||||||||
| 2989 | const char *save_path = NULL((void*)0), *chan_lang = NULL((void*)0), *lang = NULL((void*)0), *sound_path = NULL((void*)0); | |||||||||
| 2990 | switch_event_t *hint_data; | |||||||||
| 2991 | switch_xml_t cfg, xml = NULL((void*)0), language = NULL((void*)0), macros = NULL((void*)0), phrases = NULL((void*)0); | |||||||||
| 2992 | char *p; | |||||||||
| 2993 | ||||||||||
| 2994 | switch_assert(session)((session) ? (void) (0) : __assert_fail ("session", "src/switch_ivr.c" , 2994, __PRETTY_FUNCTION__)); | |||||||||
| 2995 | channel = switch_core_session_get_channel(session); | |||||||||
| 2996 | switch_assert(channel)((channel) ? (void) (0) : __assert_fail ("channel", "src/switch_ivr.c" , 2996, __PRETTY_FUNCTION__)); | |||||||||
| 2997 | ||||||||||
| 2998 | arg_recursion_check_start(args)if (args) { if (args->loops >= 25) { switch_log_printf( SWITCH_CHANNEL_ID_LOG, "src/switch_ivr.c", (const char *)__func__ , 2998, ((void*)0), SWITCH_LOG_ERROR, "RECURSION ERROR! It's not the best idea to call things that collect input recursively from an input callback.\n" ); return SWITCH_STATUS_GENERR; } else {args->loops++;} }; | |||||||||
| 2999 | ||||||||||
| 3000 | ||||||||||
| 3001 | if (zstr(module_name)_zstr(module_name)) { | |||||||||
| 3002 | module_name = "en"; | |||||||||
| 3003 | } | |||||||||
| 3004 | ||||||||||
| 3005 | if (module_name) { | |||||||||
| 3006 | char *p; | |||||||||
| 3007 | p = switch_core_session_strdup(session, module_name)switch_core_perform_session_strdup(session, module_name, "src/switch_ivr.c" , (const char *)__func__, 3007); | |||||||||
| 3008 | module_name = p; | |||||||||
| 3009 | ||||||||||
| 3010 | if ((p = strchr(module_name, ':')(__extension__ (__builtin_constant_p (':') && !__builtin_constant_p (module_name) && (':') == '\0' ? (char *) __rawmemchr (module_name, ':') : __builtin_strchr (module_name, ':'))))) { | |||||||||
| 3011 | *p++ = '\0'; | |||||||||
| 3012 | chan_lang = p; | |||||||||
| 3013 | } | |||||||||
| 3014 | } | |||||||||
| 3015 | ||||||||||
| 3016 | if (!chan_lang) { | |||||||||
| 3017 | lang = switch_channel_get_variable(channel, "language")switch_channel_get_variable_dup(channel, "language", SWITCH_TRUE , -1); | |||||||||
| 3018 | ||||||||||
| 3019 | if (!lang) { | |||||||||
| 3020 | chan_lang = switch_channel_get_variable(channel, "default_language")switch_channel_get_variable_dup(channel, "default_language", SWITCH_TRUE , -1); | |||||||||
| 3021 | if (!chan_lang) { | |||||||||
| 3022 | chan_lang = module_name; | |||||||||
| 3023 | } | |||||||||
| 3024 | switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "src/switch_ivr.c", (const char *) __func__, 3024, (const char*)(session), SWITCH_LOG_DEBUG, "No language specified - Using [%s]\n", chan_lang); | |||||||||
| 3025 | } else { | |||||||||
| 3026 | chan_lang = lang; | |||||||||
| 3027 | } | |||||||||
| 3028 | } | |||||||||
| 3029 | ||||||||||
| 3030 | switch_event_create(&hint_data, SWITCH_EVENT_REQUEST_PARAMS)switch_event_create_subclass_detailed("src/switch_ivr.c", (const char * )(const char *)__func__, 3030, &hint_data, SWITCH_EVENT_REQUEST_PARAMS , ((void*)0)); | |||||||||
| 3031 | switch_assert(hint_data)((hint_data) ? (void) (0) : __assert_fail ("hint_data", "src/switch_ivr.c" , 3031, __PRETTY_FUNCTION__)); | |||||||||
| 3032 | ||||||||||
| 3033 | switch_event_add_header_string(hint_data, SWITCH_STACK_BOTTOM, "macro_name", "say_app"); | |||||||||
| 3034 | switch_event_add_header_string(hint_data, SWITCH_STACK_BOTTOM, "lang", chan_lang); | |||||||||
| 3035 | switch_channel_event_set_data(channel, hint_data); | |||||||||
| 3036 | ||||||||||
| 3037 | if (switch_xml_locate_language(&xml, &cfg, hint_data, &language, &phrases, ¯os, chan_lang) != SWITCH_STATUS_SUCCESS) { | |||||||||
| 3038 | goto done; | |||||||||
| 3039 | } | |||||||||
| 3040 | ||||||||||
| 3041 | if ((p = (char *) switch_xml_attr(language, "say-module"))) { | |||||||||
| 3042 | module_name = switch_core_session_strdup(session, p)switch_core_perform_session_strdup(session, p, "src/switch_ivr.c" , (const char *)__func__, 3042); | |||||||||
| 3043 | } else if ((p = (char *) switch_xml_attr(language, "module"))) { | |||||||||
| 3044 | module_name = switch_core_session_strdup(session, p)switch_core_perform_session_strdup(session, p, "src/switch_ivr.c" , (const char *)__func__, 3044); | |||||||||
| 3045 | switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "src/switch_ivr.c", (const char *) __func__, 3045, (const char*)(session), SWITCH_LOG_WARNING, "Deprecated usage of module attribute\n"); | |||||||||
| 3046 | } else { | |||||||||
| 3047 | module_name = chan_lang; | |||||||||
| 3048 | } | |||||||||
| 3049 | ||||||||||
| 3050 | if (!(sound_path = (char *) switch_xml_attr(language, "sound-prefix"))) { | |||||||||
| 3051 | if (!(sound_path = (char *) switch_xml_attr(language, "sound-path"))) { | |||||||||
| 3052 | sound_path = (char *) switch_xml_attr(language, "sound_path"); | |||||||||
| 3053 | } | |||||||||
| 3054 | } | |||||||||
| 3055 | ||||||||||
| 3056 | if (channel) { | |||||||||
| 3057 | const char *p = switch_channel_get_variable(channel, "sound_prefix_enforced")switch_channel_get_variable_dup(channel, "sound_prefix_enforced" , SWITCH_TRUE, -1); | |||||||||
| 3058 | if (!switch_true(p)) { | |||||||||
| 3059 | save_path = switch_channel_get_variable(channel, "sound_prefix")switch_channel_get_variable_dup(channel, "sound_prefix", SWITCH_TRUE , -1); | |||||||||
| 3060 | if (sound_path) { | |||||||||
| 3061 | switch_channel_set_variable(channel, "sound_prefix", sound_path)switch_channel_set_variable_var_check(channel, "sound_prefix" , sound_path, SWITCH_TRUE); | |||||||||
| 3062 | } | |||||||||
| 3063 | } | |||||||||
| 3064 | } | |||||||||
| 3065 | ||||||||||
| 3066 | if ((si = switch_loadable_module_get_say_interface(module_name))) { | |||||||||
| 3067 | /* should go back and proto all the say mods to const.... */ | |||||||||
| 3068 | switch_say_args_t say_args = {0}; | |||||||||
| 3069 | ||||||||||
| 3070 | say_args.type = switch_ivr_get_say_type_by_name(say_type); | |||||||||
| 3071 | say_args.method = switch_ivr_get_say_method_by_name(say_method); | |||||||||
| 3072 | say_args.gender = switch_ivr_get_say_gender_by_name(say_gender); | |||||||||
| 3073 | ||||||||||
| 3074 | status = si->say_function(session, (char *) tosay, &say_args, args); | |||||||||
| 3075 | } else { | |||||||||
| 3076 | switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "src/switch_ivr.c", (const char *) __func__, 3076, (const char*)(session), SWITCH_LOG_ERROR, "Invalid SAY Interface [%s]!\n", module_name); | |||||||||
| 3077 | status = SWITCH_STATUS_FALSE; | |||||||||
| 3078 | } | |||||||||
| 3079 | ||||||||||
| 3080 | done: | |||||||||
| 3081 | ||||||||||
| 3082 | arg_recursion_check_stop(args)if (args) args->loops--; | |||||||||
| 3083 | ||||||||||
| 3084 | ||||||||||
| 3085 | if (hint_data) { | |||||||||
| 3086 | switch_event_destroy(&hint_data); | |||||||||
| 3087 | } | |||||||||
| 3088 | ||||||||||
| 3089 | if (save_path) { | |||||||||
| 3090 | switch_channel_set_variable(channel, "sound_prefix", save_path)switch_channel_set_variable_var_check(channel, "sound_prefix" , save_path, SWITCH_TRUE); | |||||||||
| 3091 | } | |||||||||
| 3092 | ||||||||||
| 3093 | if (xml) { | |||||||||
| 3094 | switch_xml_free(xml); | |||||||||
| 3095 | } | |||||||||
| 3096 | ||||||||||
| 3097 | return status; | |||||||||
| 3098 | } | |||||||||
| 3099 | ||||||||||
| 3100 | SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_ivr_say_string(switch_core_session_t *session, | |||||||||
| 3101 | const char *lang, | |||||||||
| 3102 | const char *ext, | |||||||||
| 3103 | const char *tosay, | |||||||||
| 3104 | const char *module_name, | |||||||||
| 3105 | const char *say_type, | |||||||||
| 3106 | const char *say_method, | |||||||||
| 3107 | const char *say_gender, | |||||||||
| 3108 | char **rstr) | |||||||||
| 3109 | { | |||||||||
| 3110 | switch_say_interface_t *si; | |||||||||
| 3111 | switch_channel_t *channel = NULL((void*)0); | |||||||||
| 3112 | switch_status_t status = SWITCH_STATUS_FALSE; | |||||||||
| 3113 | const char *save_path = NULL((void*)0), *chan_lang = NULL((void*)0), *sound_path = NULL((void*)0); | |||||||||
| 3114 | switch_event_t *hint_data; | |||||||||
| 3115 | switch_xml_t cfg, xml = NULL((void*)0), language = NULL((void*)0), macros = NULL((void*)0), phrases = NULL((void*)0); | |||||||||
| 3116 | ||||||||||
| 3117 | if (session) { | |||||||||
| 3118 | channel = switch_core_session_get_channel(session); | |||||||||
| 3119 | ||||||||||
| 3120 | if (!lang) { | |||||||||
| 3121 | lang = switch_channel_get_variable(channel, "language")switch_channel_get_variable_dup(channel, "language", SWITCH_TRUE , -1); | |||||||||
| 3122 | ||||||||||
| 3123 | if (!lang) { | |||||||||
| 3124 | chan_lang = switch_channel_get_variable(channel, "default_language")switch_channel_get_variable_dup(channel, "default_language", SWITCH_TRUE , -1); | |||||||||
| 3125 | if (!chan_lang) { | |||||||||
| 3126 | chan_lang = "en"; | |||||||||
| 3127 | } | |||||||||
| 3128 | switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "src/switch_ivr.c", (const char *) __func__, 3128, (const char*)(session), SWITCH_LOG_DEBUG, "No language specified - Using [%s]\n", chan_lang); | |||||||||
| 3129 | } else { | |||||||||
| 3130 | chan_lang = lang; | |||||||||
| 3131 | } | |||||||||
| 3132 | } | |||||||||
| 3133 | } | |||||||||
| 3134 | ||||||||||
| 3135 | if (!lang) lang = "en"; | |||||||||
| 3136 | if (!chan_lang) chan_lang = lang; | |||||||||
| 3137 | ||||||||||
| 3138 | switch_event_create(&hint_data, SWITCH_EVENT_REQUEST_PARAMS)switch_event_create_subclass_detailed("src/switch_ivr.c", (const char * )(const char *)__func__, 3138, &hint_data, SWITCH_EVENT_REQUEST_PARAMS , ((void*)0)); | |||||||||
| 3139 | switch_assert(hint_data)((hint_data) ? (void) (0) : __assert_fail ("hint_data", "src/switch_ivr.c" , 3139, __PRETTY_FUNCTION__)); | |||||||||
| 3140 | ||||||||||
| 3141 | switch_event_add_header_string(hint_data, SWITCH_STACK_BOTTOM, "macro_name", "say_app"); | |||||||||
| 3142 | switch_event_add_header_string(hint_data, SWITCH_STACK_BOTTOM, "lang", chan_lang); | |||||||||
| 3143 | ||||||||||
| 3144 | if (channel) { | |||||||||
| 3145 | switch_channel_event_set_data(channel, hint_data); | |||||||||
| 3146 | } | |||||||||
| 3147 | ||||||||||
| 3148 | if (switch_xml_locate_language(&xml, &cfg, hint_data, &language, &phrases, ¯os, chan_lang) != SWITCH_STATUS_SUCCESS) { | |||||||||
| 3149 | goto done; | |||||||||
| 3150 | } | |||||||||
| 3151 | ||||||||||
| 3152 | if ((module_name = switch_xml_attr(language, "say-module"))) { | |||||||||
| 3153 | } else if ((module_name = switch_xml_attr(language, "module"))) { | |||||||||
| 3154 | switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "src/switch_ivr.c", (const char *) __func__, 3154, (const char*)(session), SWITCH_LOG_WARNING, "Deprecated usage of module attribute\n"); | |||||||||
| 3155 | } else { | |||||||||
| 3156 | module_name = chan_lang; | |||||||||
| 3157 | } | |||||||||
| 3158 | ||||||||||
| 3159 | if (!(sound_path = (char *) switch_xml_attr(language, "sound-prefix"))) { | |||||||||
| 3160 | if (!(sound_path = (char *) switch_xml_attr(language, "sound-path"))) { | |||||||||
| 3161 | sound_path = (char *) switch_xml_attr(language, "sound_path"); | |||||||||
| 3162 | } | |||||||||
| 3163 | } | |||||||||
| 3164 | ||||||||||
| 3165 | if (channel) { | |||||||||
| 3166 | const char *p = switch_channel_get_variable(channel, "sound_prefix_enforced")switch_channel_get_variable_dup(channel, "sound_prefix_enforced" , SWITCH_TRUE, -1); | |||||||||
| 3167 | if (!switch_true(p)) { | |||||||||
| 3168 | save_path = switch_channel_get_variable(channel, "sound_prefix")switch_channel_get_variable_dup(channel, "sound_prefix", SWITCH_TRUE , -1); | |||||||||
| 3169 | if (sound_path) { | |||||||||
| 3170 | switch_channel_set_variable(channel, "sound_prefix", sound_path)switch_channel_set_variable_var_check(channel, "sound_prefix" , sound_path, SWITCH_TRUE); | |||||||||
| 3171 | } | |||||||||
| 3172 | } | |||||||||
| 3173 | } | |||||||||
| 3174 | ||||||||||
| 3175 | if ((si = switch_loadable_module_get_say_interface(module_name)) && si->say_string_function) { | |||||||||
| 3176 | /* should go back and proto all the say mods to const.... */ | |||||||||
| 3177 | switch_say_args_t say_args = {0}; | |||||||||
| 3178 | ||||||||||
| 3179 | say_args.type = switch_ivr_get_say_type_by_name(say_type); | |||||||||
| 3180 | say_args.method = switch_ivr_get_say_method_by_name(say_method); | |||||||||
| 3181 | say_args.gender = switch_ivr_get_say_gender_by_name(say_gender); | |||||||||
| 3182 | say_args.ext = ext; | |||||||||
| 3183 | status = si->say_string_function(session, (char *) tosay, &say_args, rstr); | |||||||||
| 3184 | } else { | |||||||||
| 3185 | switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "src/switch_ivr.c", (const char *) __func__, 3185, (const char*)(session), SWITCH_LOG_ERROR, "Invalid SAY Interface [%s]!\n", module_name); | |||||||||
| 3186 | status = SWITCH_STATUS_FALSE; | |||||||||
| 3187 | } | |||||||||
| 3188 | ||||||||||
| 3189 | done: | |||||||||
| 3190 | ||||||||||
| 3191 | if (hint_data) { | |||||||||
| 3192 | switch_event_destroy(&hint_data); | |||||||||
| 3193 | } | |||||||||
| 3194 | ||||||||||
| 3195 | if (save_path && channel) { | |||||||||
| 3196 | switch_channel_set_variable(channel, "sound_prefix", save_path)switch_channel_set_variable_var_check(channel, "sound_prefix" , save_path, SWITCH_TRUE); | |||||||||
| 3197 | } | |||||||||
| 3198 | ||||||||||
| 3199 | if (xml) { | |||||||||
| 3200 | switch_xml_free(xml); | |||||||||
| 3201 | } | |||||||||
| 3202 | ||||||||||
| 3203 | return status; | |||||||||
| 3204 | } | |||||||||
| 3205 | ||||||||||
| 3206 | ||||||||||
| 3207 | static const char *get_prefixed_str(char *buffer, size_t buffer_size, const char *prefix, size_t prefix_size, const char *str) | |||||||||
| 3208 | { | |||||||||
| 3209 | size_t str_len; | |||||||||
| 3210 | ||||||||||
| 3211 | if (!buffer) { | |||||||||
| 3212 | /* | |||||||||
| 3213 | if buffer is null then it just returns the str without the prefix appended, otherwise buffer contains the prefix followed by the original string | |||||||||
| 3214 | */ | |||||||||
| 3215 | ||||||||||
| 3216 | return str; | |||||||||
| 3217 | } | |||||||||
| 3218 | ||||||||||
| 3219 | str_len = strlen(str); | |||||||||
| 3220 | memcpy(buffer, prefix, prefix_size); | |||||||||
| 3221 | ||||||||||
| 3222 | if (str_len + prefix_size + 1 > buffer_size) { | |||||||||
| 3223 | memcpy(buffer + prefix_size, str, buffer_size - prefix_size - 1); | |||||||||
| 3224 | buffer[buffer_size - prefix_size - 1] = '\0'; | |||||||||
| 3225 | } else { | |||||||||
| 3226 | memcpy(buffer + prefix_size, str, str_len + 1); | |||||||||
| 3227 | } | |||||||||
| 3228 | ||||||||||
| 3229 | return buffer; | |||||||||
| 3230 | } | |||||||||
| 3231 | ||||||||||
| 3232 | SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_ivr_set_user_xml(switch_core_session_t *session, const char *prefix, | |||||||||
| 3233 | const char *user, const char *domain, switch_xml_t x_user) | |||||||||
| 3234 | { | |||||||||
| 3235 | switch_xml_t x_params, x_param; | |||||||||
| 3236 | char *number_alias; | |||||||||
| 3237 | switch_channel_t *channel = switch_core_session_get_channel(session); | |||||||||
| 3238 | switch_status_t status = SWITCH_STATUS_FALSE; | |||||||||
| 3239 | ||||||||||
| 3240 | char *prefix_buffer = NULL((void*)0); | |||||||||
| 3241 | size_t buffer_size = 0; | |||||||||
| 3242 | size_t prefix_size = 0; | |||||||||
| 3243 | ||||||||||
| 3244 | ||||||||||
| 3245 | status = SWITCH_STATUS_SUCCESS; | |||||||||
| 3246 | ||||||||||
| 3247 | if (!zstr(prefix)_zstr(prefix)) { | |||||||||
| 3248 | prefix_size = strlen(prefix); | |||||||||
| 3249 | buffer_size = 1024 + prefix_size + 1; | |||||||||
| 3250 | prefix_buffer = switch_core_session_alloc(session, buffer_size)switch_core_perform_session_alloc(session, buffer_size, "src/switch_ivr.c" , (const char *)__func__, 3250); | |||||||||
| 3251 | } | |||||||||
| 3252 | ||||||||||
| 3253 | if ((number_alias = (char *) switch_xml_attr(x_user, "number-alias"))) { | |||||||||
| 3254 | switch_channel_set_variable(channel, get_prefixed_str(prefix_buffer, buffer_size, prefix, prefix_size, "number_alias"), number_alias)switch_channel_set_variable_var_check(channel, get_prefixed_str (prefix_buffer, buffer_size, prefix, prefix_size, "number_alias" ), number_alias, SWITCH_TRUE); | |||||||||
| 3255 | } | |||||||||
| 3256 | ||||||||||
| 3257 | if ((x_params = switch_xml_child(x_user, "variables"))) { | |||||||||
| 3258 | for (x_param = switch_xml_child(x_params, "variable"); x_param; x_param = x_param->next) { | |||||||||
| 3259 | const char *var = switch_xml_attr(x_param, "name"); | |||||||||
| 3260 | const char *val = switch_xml_attr(x_param, "value"); | |||||||||
| 3261 | ||||||||||
| 3262 | if (var && val) { | |||||||||
| 3263 | switch_channel_set_variable(channel, get_prefixed_str(prefix_buffer, buffer_size, prefix, prefix_size, var), val)switch_channel_set_variable_var_check(channel, get_prefixed_str (prefix_buffer, buffer_size, prefix, prefix_size, var), val, SWITCH_TRUE ); | |||||||||
| 3264 | } | |||||||||
| 3265 | } | |||||||||
| 3266 | } | |||||||||
| 3267 | ||||||||||
| 3268 | if ((x_params = switch_xml_child(x_user, "profile-variables"))) { | |||||||||
| 3269 | for (x_param = switch_xml_child(x_params, "variable"); x_param; x_param = x_param->next) { | |||||||||
| 3270 | const char *var = switch_xml_attr(x_param, "name"); | |||||||||
| 3271 | const char *val = switch_xml_attr(x_param, "value"); | |||||||||
| 3272 | ||||||||||
| 3273 | if (var && val) { | |||||||||
| 3274 | switch_channel_set_profile_var(channel, get_prefixed_str(prefix_buffer, buffer_size, prefix, prefix_size, var), val); | |||||||||
| 3275 | } | |||||||||
| 3276 | } | |||||||||
| 3277 | } | |||||||||
| 3278 | ||||||||||
| 3279 | if (user && domain) { | |||||||||
| 3280 | switch_channel_set_variable(channel, get_prefixed_str(prefix_buffer, buffer_size, prefix, prefix_size, "user_name"), user)switch_channel_set_variable_var_check(channel, get_prefixed_str (prefix_buffer, buffer_size, prefix, prefix_size, "user_name" ), user, SWITCH_TRUE); | |||||||||
| 3281 | switch_channel_set_variable(channel, get_prefixed_str(prefix_buffer, buffer_size, prefix, prefix_size, "domain_name"), domain)switch_channel_set_variable_var_check(channel, get_prefixed_str (prefix_buffer, buffer_size, prefix, prefix_size, "domain_name" ), domain, SWITCH_TRUE); | |||||||||
| 3282 | } | |||||||||
| 3283 | ||||||||||
| 3284 | return status; | |||||||||
| 3285 | } | |||||||||
| 3286 | ||||||||||
| 3287 | SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_ivr_set_user(switch_core_session_t *session, const char *data) | |||||||||
| 3288 | { | |||||||||
| 3289 | switch_xml_t x_user = 0; | |||||||||
| 3290 | char *user, *domain; | |||||||||
| 3291 | switch_status_t status = SWITCH_STATUS_FALSE; | |||||||||
| 3292 | ||||||||||
| 3293 | char *prefix; | |||||||||
| 3294 | ||||||||||
| 3295 | if (zstr(data)_zstr(data)) { | |||||||||
| 3296 | goto error; | |||||||||
| 3297 | } | |||||||||
| 3298 | ||||||||||
| 3299 | user = switch_core_session_strdup(session, data)switch_core_perform_session_strdup(session, data, "src/switch_ivr.c" , (const char *)__func__, 3299); | |||||||||
| 3300 | ||||||||||
| 3301 | if ((prefix = strchr(user, ' ')(__extension__ (__builtin_constant_p (' ') && !__builtin_constant_p (user) && (' ') == '\0' ? (char *) __rawmemchr (user , ' ') : __builtin_strchr (user, ' '))))) { | |||||||||
| 3302 | *prefix++ = 0; | |||||||||
| 3303 | } | |||||||||
| 3304 | ||||||||||
| 3305 | if (!(domain = strchr(user, '@')(__extension__ (__builtin_constant_p ('@') && !__builtin_constant_p (user) && ('@') == '\0' ? (char *) __rawmemchr (user , '@') : __builtin_strchr (user, '@'))))) { | |||||||||
| 3306 | goto error; | |||||||||
| 3307 | } | |||||||||
| 3308 | ||||||||||
| 3309 | *domain++ = '\0'; | |||||||||
| 3310 | ||||||||||
| 3311 | ||||||||||
| 3312 | if (switch_xml_locate_user_merged("id", user, domain, NULL((void*)0), &x_user, NULL((void*)0)) != SWITCH_STATUS_SUCCESS) { | |||||||||
| 3313 | switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "src/switch_ivr.c", (const char *) __func__, 3313, (const char*)(session), SWITCH_LOG_WARNING, "can't find user [%s@%s]\n", user, domain); | |||||||||
| 3314 | goto done; | |||||||||
| 3315 | } | |||||||||
| 3316 | ||||||||||
| 3317 | status = switch_ivr_set_user_xml(session, prefix, user, domain, x_user); | |||||||||
| 3318 | ||||||||||
| 3319 | goto done; | |||||||||
| 3320 | ||||||||||
| 3321 | error: | |||||||||
| 3322 | switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "src/switch_ivr.c", (const char *) __func__, 3322, (const char*)(session), SWITCH_LOG_ERROR, "No user@domain specified.\n"); | |||||||||
| 3323 | ||||||||||
| 3324 | done: | |||||||||
| 3325 | ||||||||||
| 3326 | if (x_user) { | |||||||||
| 3327 | switch_xml_free(x_user); | |||||||||
| 3328 | } | |||||||||
| 3329 | ||||||||||
| 3330 | return status; | |||||||||
| 3331 | } | |||||||||
| 3332 | ||||||||||
| 3333 | SWITCH_DECLARE(switch_bool_t)__attribute__((visibility("default"))) switch_bool_t switch_ivr_uuid_exists(const char *uuid) | |||||||||
| 3334 | { | |||||||||
| 3335 | switch_bool_t exists = SWITCH_FALSE; | |||||||||
| 3336 | switch_core_session_t *psession = NULL((void*)0); | |||||||||
| 3337 | ||||||||||
| 3338 | if ((psession = switch_core_session_locate(uuid)switch_core_session_perform_locate(uuid, "src/switch_ivr.c", ( const char *)__func__, 3338))) { | |||||||||
| 3339 | switch_core_session_rwunlock(psession); | |||||||||
| 3340 | exists = 1; | |||||||||
| 3341 | } | |||||||||
| 3342 | ||||||||||
| 3343 | return exists; | |||||||||
| 3344 | } | |||||||||
| 3345 | ||||||||||
| 3346 | SWITCH_DECLARE(switch_bool_t)__attribute__((visibility("default"))) switch_bool_t switch_ivr_uuid_force_exists(const char *uuid) | |||||||||
| 3347 | { | |||||||||
| 3348 | switch_bool_t exists = SWITCH_FALSE; | |||||||||
| 3349 | switch_core_session_t *psession = NULL((void*)0); | |||||||||
| 3350 | ||||||||||
| 3351 | if ((psession = switch_core_session_force_locate(uuid)switch_core_session_perform_force_locate(uuid, "src/switch_ivr.c" , (const char *)__func__, 3351))) { | |||||||||
| 3352 | switch_core_session_rwunlock(psession); | |||||||||
| 3353 | exists = 1; | |||||||||
| 3354 | } | |||||||||
| 3355 | ||||||||||
| 3356 | return exists; | |||||||||
| 3357 | } | |||||||||
| 3358 | ||||||||||
| 3359 | SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_ivr_process_fh(switch_core_session_t *session, const char *cmd, switch_file_handle_t *fhp) | |||||||||
| 3360 | { | |||||||||
| 3361 | if (zstr(cmd)_zstr(cmd)) { | |||||||||
| 3362 | return SWITCH_STATUS_SUCCESS; | |||||||||
| 3363 | } | |||||||||
| 3364 | ||||||||||
| 3365 | if (fhp) { | |||||||||
| 3366 | if (!switch_test_flag(fhp, SWITCH_FILE_OPEN)((fhp)->flags & SWITCH_FILE_OPEN)) { | |||||||||
| 3367 | return SWITCH_STATUS_FALSE; | |||||||||
| 3368 | } | |||||||||
| 3369 | ||||||||||
| 3370 | if (!strncasecmp(cmd, "speed", 5)) { | |||||||||
| 3371 | char *p; | |||||||||
| 3372 | ||||||||||
| 3373 | if ((p = strchr(cmd, ':')(__extension__ (__builtin_constant_p (':') && !__builtin_constant_p (cmd) && (':') == '\0' ? (char *) __rawmemchr (cmd, ':' ) : __builtin_strchr (cmd, ':'))))) { | |||||||||
| 3374 | p++; | |||||||||
| 3375 | if (*p == '+' || *p == '-') { | |||||||||
| 3376 | int step; | |||||||||
| 3377 | if (!(step = atoi(p))) { | |||||||||
| 3378 | step = 1; | |||||||||
| 3379 | } | |||||||||
| 3380 | fhp->speed += step; | |||||||||
| 3381 | } else { | |||||||||
| 3382 | int speed = atoi(p); | |||||||||
| 3383 | fhp->speed = speed; | |||||||||
| 3384 | } | |||||||||
| 3385 | return SWITCH_STATUS_SUCCESS; | |||||||||
| 3386 | } | |||||||||
| 3387 | ||||||||||
| 3388 | return SWITCH_STATUS_FALSE; | |||||||||
| 3389 | ||||||||||
| 3390 | } else if (!strncasecmp(cmd, "volume", 6)) { | |||||||||
| 3391 | char *p; | |||||||||
| 3392 | ||||||||||
| 3393 | if ((p = strchr(cmd, ':')(__extension__ (__builtin_constant_p (':') && !__builtin_constant_p (cmd) && (':') == '\0' ? (char *) __rawmemchr (cmd, ':' ) : __builtin_strchr (cmd, ':'))))) { | |||||||||
| 3394 | p++; | |||||||||
| 3395 | if (*p == '+' || *p == '-') { | |||||||||
| 3396 | int step; | |||||||||
| 3397 | if (!(step = atoi(p))) { | |||||||||
| 3398 | step = 1; | |||||||||
| 3399 | } | |||||||||
| 3400 | fhp->vol += step; | |||||||||
| 3401 | } else { | |||||||||
| 3402 | int vol = atoi(p); | |||||||||
| 3403 | fhp->vol = vol; | |||||||||
| 3404 | } | |||||||||
| 3405 | return SWITCH_STATUS_SUCCESS; | |||||||||
| 3406 | } | |||||||||
| 3407 | ||||||||||
| 3408 | if (fhp->vol) { | |||||||||
| 3409 | switch_normalize_volume(fhp->vol)if (fhp->vol > 4) fhp->vol = 4; if (fhp->vol < -4) fhp->vol = -4;; | |||||||||
| 3410 | } | |||||||||
| 3411 | ||||||||||
| 3412 | return SWITCH_STATUS_FALSE; | |||||||||
| 3413 | } else if (!strcasecmp(cmd, "pause")) { | |||||||||
| 3414 | if (switch_test_flag(fhp, SWITCH_FILE_PAUSE)((fhp)->flags & SWITCH_FILE_PAUSE)) { | |||||||||
| 3415 | switch_clear_flag(fhp, SWITCH_FILE_PAUSE)(fhp)->flags &= ~(SWITCH_FILE_PAUSE); | |||||||||
| 3416 | } else { | |||||||||
| 3417 | switch_set_flag(fhp, SWITCH_FILE_PAUSE)(fhp)->flags |= (SWITCH_FILE_PAUSE); | |||||||||
| 3418 | } | |||||||||
| 3419 | return SWITCH_STATUS_SUCCESS; | |||||||||
| 3420 | } else if (!strcasecmp(cmd, "stop")) { | |||||||||
| 3421 | switch_set_flag(fhp, SWITCH_FILE_DONE)(fhp)->flags |= (SWITCH_FILE_DONE); | |||||||||
| 3422 | return SWITCH_STATUS_FALSE; | |||||||||
| 3423 | } else if (!strcasecmp(cmd, "truncate")) { | |||||||||
| 3424 | switch_core_file_truncate(fhp, 0); | |||||||||
| 3425 | } else if (!strcasecmp(cmd, "restart")) { | |||||||||
| 3426 | unsigned int pos = 0; | |||||||||
| 3427 | fhp->speed = 0; | |||||||||
| 3428 | switch_core_file_seek(fhp, &pos, 0, SEEK_SET0); | |||||||||
| 3429 | return SWITCH_STATUS_SUCCESS; | |||||||||
| 3430 | } else if (!strncasecmp(cmd, "seek", 4)) { | |||||||||
| 3431 | //switch_codec_t *codec; | |||||||||
| 3432 | unsigned int samps = 0; | |||||||||
| 3433 | unsigned int pos = 0; | |||||||||
| 3434 | char *p; | |||||||||
| 3435 | //codec = switch_core_session_get_read_codec(session); | |||||||||
| 3436 | ||||||||||
| 3437 | if ((p = strchr(cmd, ':')(__extension__ (__builtin_constant_p (':') && !__builtin_constant_p (cmd) && (':') == '\0' ? (char *) __rawmemchr (cmd, ':' ) : __builtin_strchr (cmd, ':'))))) { | |||||||||
| 3438 | p++; | |||||||||
| 3439 | if (*p == '+' || *p == '-') { | |||||||||
| 3440 | int step; | |||||||||
| 3441 | int32_t target; | |||||||||
| 3442 | if (!(step = atoi(p))) { | |||||||||
| 3443 | step = 1000; | |||||||||
| 3444 | } | |||||||||
| 3445 | ||||||||||
| 3446 | samps = step * (fhp->native_rate / 1000); | |||||||||
| 3447 | target = (int32_t)fhp->offset_pos + samps; | |||||||||
| 3448 | ||||||||||
| 3449 | if (target < 0) { | |||||||||
| 3450 | target = 0; | |||||||||
| 3451 | } | |||||||||
| 3452 | ||||||||||
| 3453 | switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "src/switch_ivr.c", (const char *) __func__, 3453, (const char*)(session), SWITCH_LOG_DEBUG, "seek to position %d\n", target); | |||||||||
| 3454 | switch_core_file_seek(fhp, &pos, target, SEEK_SET0); | |||||||||
| 3455 | ||||||||||
| 3456 | } else { | |||||||||
| 3457 | samps = switch_atoui(p) * (fhp->native_rate / 1000); | |||||||||
| 3458 | switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "src/switch_ivr.c", (const char *) __func__, 3458, (const char*)(session), SWITCH_LOG_DEBUG, "seek to position %d\n", samps); | |||||||||
| 3459 | switch_core_file_seek(fhp, &pos, samps, SEEK_SET0); | |||||||||
| 3460 | } | |||||||||
| 3461 | } | |||||||||
| 3462 | ||||||||||
| 3463 | return SWITCH_STATUS_SUCCESS; | |||||||||
| 3464 | } | |||||||||
| 3465 | } | |||||||||
| 3466 | ||||||||||
| 3467 | if (!strcmp(cmd, "true")__extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p (cmd) && __builtin_constant_p ("true") && (__s1_len = __builtin_strlen (cmd), __s2_len = __builtin_strlen ("true" ), (!((size_t)(const void *)((cmd) + 1) - (size_t)(const void *)(cmd) == 1) || __s1_len >= 4) && (!((size_t)(const void *)(("true") + 1) - (size_t)(const void *)("true") == 1) || __s2_len >= 4)) ? __builtin_strcmp (cmd, "true") : (__builtin_constant_p (cmd) && ((size_t)(const void *)((cmd) + 1) - (size_t )(const void *)(cmd) == 1) && (__s1_len = __builtin_strlen (cmd), __s1_len < 4) ? (__builtin_constant_p ("true") && ((size_t)(const void *)(("true") + 1) - (size_t)(const void * )("true") == 1) ? __builtin_strcmp (cmd, "true") : (__extension__ ({ const unsigned char *__s2 = (const unsigned char *) (const char *) ("true"); int __result = (((const unsigned char *) ( const char *) (cmd))[0] - __s2[0]); if (__s1_len > 0 && __result == 0) { __result = (((const unsigned char *) (const char *) (cmd))[1] - __s2[1]); if (__s1_len > 1 && __result == 0) { __result = (((const unsigned char *) (const char *) (cmd))[2] - __s2[2]); if (__s1_len > 2 && __result == 0) __result = (((const unsigned char *) (const char *) (cmd))[3] - __s2[3]); } } __result; }))) : (__builtin_constant_p ("true") && ((size_t)(const void *)(("true") + 1) - ( size_t)(const void *)("true") == 1) && (__s2_len = __builtin_strlen ("true"), __s2_len < 4) ? (__builtin_constant_p (cmd) && ((size_t)(const void *)((cmd) + 1) - (size_t)(const void *)( cmd) == 1) ? __builtin_strcmp (cmd, "true") : (- (__extension__ ({ const unsigned char *__s2 = (const unsigned char *) (const char *) (cmd); int __result = (((const unsigned char *) (const char *) ("true"))[0] - __s2[0]); if (__s2_len > 0 && __result == 0) { __result = (((const unsigned char *) (const char *) ("true"))[1] - __s2[1]); if (__s2_len > 1 && __result == 0) { __result = (((const unsigned char *) (const char *) ("true"))[2] - __s2[2]); if (__s2_len > 2 && __result == 0) __result = (((const unsigned char *) (const char *) ("true"))[3] - __s2[3]); } } __result; })))) : __builtin_strcmp (cmd, "true")))); }) || !strcmp(cmd, "undefined")__extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p (cmd) && __builtin_constant_p ("undefined") && (__s1_len = __builtin_strlen (cmd), __s2_len = __builtin_strlen ("undefined"), (!((size_t)(const void *)((cmd) + 1) - (size_t )(const void *)(cmd) == 1) || __s1_len >= 4) && (! ((size_t)(const void *)(("undefined") + 1) - (size_t)(const void *)("undefined") == 1) || __s2_len >= 4)) ? __builtin_strcmp (cmd, "undefined") : (__builtin_constant_p (cmd) && ( (size_t)(const void *)((cmd) + 1) - (size_t)(const void *)(cmd ) == 1) && (__s1_len = __builtin_strlen (cmd), __s1_len < 4) ? (__builtin_constant_p ("undefined") && ((size_t )(const void *)(("undefined") + 1) - (size_t)(const void *)("undefined" ) == 1) ? __builtin_strcmp (cmd, "undefined") : (__extension__ ({ const unsigned char *__s2 = (const unsigned char *) (const char *) ("undefined"); int __result = (((const unsigned char *) (const char *) (cmd))[0] - __s2[0]); if (__s1_len > 0 && __result == 0) { __result = (((const unsigned char *) (const char *) (cmd))[1] - __s2[1]); if (__s1_len > 1 && __result == 0) { __result = (((const unsigned char *) (const char *) (cmd))[2] - __s2[2]); if (__s1_len > 2 && __result == 0) __result = (((const unsigned char *) (const char *) (cmd))[3] - __s2[3]); } } __result; }))) : (__builtin_constant_p ("undefined") && ((size_t)(const void *)(("undefined" ) + 1) - (size_t)(const void *)("undefined") == 1) && (__s2_len = __builtin_strlen ("undefined"), __s2_len < 4) ? (__builtin_constant_p (cmd) && ((size_t)(const void *)((cmd) + 1) - (size_t)(const void *)(cmd) == 1) ? __builtin_strcmp (cmd, "undefined") : (- (__extension__ ({ const unsigned char *__s2 = (const unsigned char *) (const char *) (cmd); int __result = (((const unsigned char *) (const char *) ("undefined"))[0] - __s2[0]); if (__s2_len > 0 && __result == 0) { __result = (((const unsigned char *) (const char *) ("undefined"))[1] - __s2[1]); if (__s2_len > 1 && __result == 0) { __result = (((const unsigned char *) (const char *) ("undefined"))[2] - __s2[2]); if (__s2_len > 2 && __result == 0) __result = (((const unsigned char *) (const char *) ("undefined"))[3] - __s2[3]); } } __result; })))) : __builtin_strcmp (cmd, "undefined" )))); })) { | |||||||||
| 3468 | return SWITCH_STATUS_SUCCESS; | |||||||||
| 3469 | } | |||||||||
| 3470 | ||||||||||
| 3471 | return SWITCH_STATUS_FALSE; | |||||||||
| 3472 | ||||||||||
| 3473 | } | |||||||||
| 3474 | ||||||||||
| 3475 | #define START_SAMPLES32768 32768 | |||||||||
| 3476 | ||||||||||
| 3477 | SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_ivr_insert_file(switch_core_session_t *session, const char *file, const char *insert_file, switch_size_t sample_point) | |||||||||
| 3478 | { | |||||||||
| 3479 | switch_file_handle_t orig_fh = { 0 }; | |||||||||
| 3480 | switch_file_handle_t new_fh = { 0 }; | |||||||||
| 3481 | switch_codec_implementation_t read_impl = { 0 }; | |||||||||
| 3482 | char *tmp_file; | |||||||||
| 3483 | switch_uuid_t uuid; | |||||||||
| 3484 | char uuid_str[SWITCH_UUID_FORMATTED_LENGTH256 + 1]; | |||||||||
| 3485 | int16_t *abuf = NULL((void*)0); | |||||||||
| 3486 | switch_size_t olen = 0; | |||||||||
| 3487 | int asis = 0; | |||||||||
| 3488 | switch_channel_t *channel = switch_core_session_get_channel(session); | |||||||||
| 3489 | switch_size_t sample_count = 0; | |||||||||
| 3490 | uint32_t pos = 0; | |||||||||
| 3491 | char *ext; | |||||||||
| 3492 | ||||||||||
| 3493 | switch_uuid_get(&uuid); | |||||||||
| 3494 | switch_uuid_format(uuid_str, &uuid); | |||||||||
| 3495 | ||||||||||
| 3496 | if ((ext = strrchr(file, '.'))) { | |||||||||
| 3497 | ext++; | |||||||||
| 3498 | } else { | |||||||||
| 3499 | ext = "wav"; | |||||||||
| 3500 | } | |||||||||
| 3501 | ||||||||||
| 3502 | tmp_file = switch_core_session_sprintf(session, "%s%smsg_%s.%s", | |||||||||
| 3503 | SWITCH_GLOBAL_dirs.temp_dir, SWITCH_PATH_SEPARATOR"/", uuid_str, ext); | |||||||||
| 3504 | ||||||||||
| 3505 | switch_core_session_get_read_impl(session, &read_impl); | |||||||||
| 3506 | ||||||||||
| 3507 | new_fh.channels = read_impl.number_of_channels; | |||||||||
| 3508 | new_fh.native_rate = read_impl.actual_samples_per_second; | |||||||||
| 3509 | ||||||||||
| 3510 | ||||||||||
| 3511 | if (switch_core_file_open(&new_fh,switch_core_perform_file_open("src/switch_ivr.c", (const char *)__func__, 3514, &new_fh, tmp_file, new_fh.channels, read_impl .actual_samples_per_second, SWITCH_FILE_FLAG_WRITE | SWITCH_FILE_DATA_SHORT , ((void*)0)) | |||||||||
| 3512 | tmp_file,switch_core_perform_file_open("src/switch_ivr.c", (const char *)__func__, 3514, &new_fh, tmp_file, new_fh.channels, read_impl .actual_samples_per_second, SWITCH_FILE_FLAG_WRITE | SWITCH_FILE_DATA_SHORT , ((void*)0)) | |||||||||
| 3513 | new_fh.channels,switch_core_perform_file_open("src/switch_ivr.c", (const char *)__func__, 3514, &new_fh, tmp_file, new_fh.channels, read_impl .actual_samples_per_second, SWITCH_FILE_FLAG_WRITE | SWITCH_FILE_DATA_SHORT , ((void*)0)) | |||||||||
| 3514 | read_impl.actual_samples_per_second, SWITCH_FILE_FLAG_WRITE | SWITCH_FILE_DATA_SHORT, NULL)switch_core_perform_file_open("src/switch_ivr.c", (const char *)__func__, 3514, &new_fh, tmp_file, new_fh.channels, read_impl .actual_samples_per_second, SWITCH_FILE_FLAG_WRITE | SWITCH_FILE_DATA_SHORT , ((void*)0)) != SWITCH_STATUS_SUCCESS) { | |||||||||
| 3515 | switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "src/switch_ivr.c", (const char *) __func__, 3515, (const char*)(session), SWITCH_LOG_ERROR, "Failed to open file %s\n", tmp_file); | |||||||||
| 3516 | goto end; | |||||||||
| 3517 | } | |||||||||
| 3518 | ||||||||||
| 3519 | ||||||||||
| 3520 | if (switch_core_file_open(&orig_fh,switch_core_perform_file_open("src/switch_ivr.c", (const char *)__func__, 3523, &orig_fh, file, new_fh.channels, read_impl .actual_samples_per_second, SWITCH_FILE_FLAG_READ | SWITCH_FILE_DATA_SHORT , ((void*)0)) | |||||||||
| 3521 | file,switch_core_perform_file_open("src/switch_ivr.c", (const char *)__func__, 3523, &orig_fh, file, new_fh.channels, read_impl .actual_samples_per_second, SWITCH_FILE_FLAG_READ | SWITCH_FILE_DATA_SHORT , ((void*)0)) | |||||||||
| 3522 | new_fh.channels,switch_core_perform_file_open("src/switch_ivr.c", (const char *)__func__, 3523, &orig_fh, file, new_fh.channels, read_impl .actual_samples_per_second, SWITCH_FILE_FLAG_READ | SWITCH_FILE_DATA_SHORT , ((void*)0)) | |||||||||
| 3523 | read_impl.actual_samples_per_second, SWITCH_FILE_FLAG_READ | SWITCH_FILE_DATA_SHORT, NULL)switch_core_perform_file_open("src/switch_ivr.c", (const char *)__func__, 3523, &orig_fh, file, new_fh.channels, read_impl .actual_samples_per_second, SWITCH_FILE_FLAG_READ | SWITCH_FILE_DATA_SHORT , ((void*)0)) != SWITCH_STATUS_SUCCESS) { | |||||||||
| 3524 | switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "src/switch_ivr.c", (const char *) __func__, 3524, (const char*)(session), SWITCH_LOG_ERROR, "Failed to open file %s\n", file); | |||||||||
| 3525 | goto end; | |||||||||
| 3526 | } | |||||||||
| 3527 | ||||||||||
| 3528 | ||||||||||
| 3529 | switch_zmalloc(abuf, START_SAMPLES * sizeof(*abuf))(void)((((abuf = calloc(1, (32768 * sizeof(*abuf))))) ? (void ) (0) : __assert_fail ("(abuf = calloc(1, (32768 * sizeof(*abuf))))" , "src/switch_ivr.c", 3529, __PRETTY_FUNCTION__)),abuf); | |||||||||
| 3530 | ||||||||||
| 3531 | if (switch_test_flag((&orig_fh), SWITCH_FILE_NATIVE)(((&orig_fh))->flags & SWITCH_FILE_NATIVE)) { | |||||||||
| 3532 | asis = 1; | |||||||||
| 3533 | } | |||||||||
| 3534 | ||||||||||
| 3535 | while (switch_channel_ready(channel)switch_channel_test_ready(channel, SWITCH_TRUE, SWITCH_FALSE)) { | |||||||||
| 3536 | olen = START_SAMPLES32768; | |||||||||
| 3537 | ||||||||||
| 3538 | if (!asis) { | |||||||||
| 3539 | olen /= 2; | |||||||||
| 3540 | } | |||||||||
| 3541 | ||||||||||
| 3542 | if ((sample_count + olen) > sample_point) { | |||||||||
| 3543 | olen = sample_point - sample_count; | |||||||||
| 3544 | } | |||||||||
| 3545 | ||||||||||
| 3546 | if (!olen || switch_core_file_read(&orig_fh, abuf, &olen) != SWITCH_STATUS_SUCCESS || !olen) { | |||||||||
| 3547 | break; | |||||||||
| 3548 | } | |||||||||
| 3549 | ||||||||||
| 3550 | sample_count += olen; | |||||||||
| 3551 | ||||||||||
| 3552 | switch_core_file_write(&new_fh, abuf, &olen); | |||||||||
| 3553 | } | |||||||||
| 3554 | ||||||||||
| 3555 | switch_core_file_close(&orig_fh); | |||||||||
| 3556 | ||||||||||
| 3557 | ||||||||||
| 3558 | if (switch_core_file_open(&orig_fh,switch_core_perform_file_open("src/switch_ivr.c", (const char *)__func__, 3561, &orig_fh, insert_file, new_fh.channels , read_impl.actual_samples_per_second, SWITCH_FILE_FLAG_READ | SWITCH_FILE_DATA_SHORT, ((void*)0)) | |||||||||
| 3559 | insert_file,switch_core_perform_file_open("src/switch_ivr.c", (const char *)__func__, 3561, &orig_fh, insert_file, new_fh.channels , read_impl.actual_samples_per_second, SWITCH_FILE_FLAG_READ | SWITCH_FILE_DATA_SHORT, ((void*)0)) | |||||||||
| 3560 | new_fh.channels,switch_core_perform_file_open("src/switch_ivr.c", (const char *)__func__, 3561, &orig_fh, insert_file, new_fh.channels , read_impl.actual_samples_per_second, SWITCH_FILE_FLAG_READ | SWITCH_FILE_DATA_SHORT, ((void*)0)) | |||||||||
| 3561 | read_impl.actual_samples_per_second, SWITCH_FILE_FLAG_READ | SWITCH_FILE_DATA_SHORT, NULL)switch_core_perform_file_open("src/switch_ivr.c", (const char *)__func__, 3561, &orig_fh, insert_file, new_fh.channels , read_impl.actual_samples_per_second, SWITCH_FILE_FLAG_READ | SWITCH_FILE_DATA_SHORT, ((void*)0)) != SWITCH_STATUS_SUCCESS) { | |||||||||
| 3562 | switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "src/switch_ivr.c", (const char *) __func__, 3562, (const char*)(session), SWITCH_LOG_ERROR, "Failed to open file %s\n", file); | |||||||||
| 3563 | goto end; | |||||||||
| 3564 | } | |||||||||
| 3565 | ||||||||||
| 3566 | ||||||||||
| 3567 | while (switch_channel_ready(channel)switch_channel_test_ready(channel, SWITCH_TRUE, SWITCH_FALSE)) { | |||||||||
| 3568 | olen = START_SAMPLES32768; | |||||||||
| 3569 | ||||||||||
| 3570 | if (!asis) { | |||||||||
| 3571 | olen /= 2; | |||||||||
| 3572 | } | |||||||||
| 3573 | ||||||||||
| 3574 | if (switch_core_file_read(&orig_fh, abuf, &olen) != SWITCH_STATUS_SUCCESS || !olen) { | |||||||||
| 3575 | break; | |||||||||
| 3576 | } | |||||||||
| 3577 | ||||||||||
| 3578 | sample_count += olen; | |||||||||
| 3579 | ||||||||||
| 3580 | switch_core_file_write(&new_fh, abuf, &olen); | |||||||||
| 3581 | } | |||||||||
| 3582 | ||||||||||
| 3583 | switch_core_file_close(&orig_fh); | |||||||||
| 3584 | ||||||||||
| 3585 | if (switch_core_file_open(&orig_fh,switch_core_perform_file_open("src/switch_ivr.c", (const char *)__func__, 3588, &orig_fh, file, new_fh.channels, read_impl .actual_samples_per_second, SWITCH_FILE_FLAG_READ | SWITCH_FILE_DATA_SHORT , ((void*)0)) | |||||||||
| 3586 | file,switch_core_perform_file_open("src/switch_ivr.c", (const char *)__func__, 3588, &orig_fh, file, new_fh.channels, read_impl .actual_samples_per_second, SWITCH_FILE_FLAG_READ | SWITCH_FILE_DATA_SHORT , ((void*)0)) | |||||||||
| 3587 | new_fh.channels,switch_core_perform_file_open("src/switch_ivr.c", (const char *)__func__, 3588, &orig_fh, file, new_fh.channels, read_impl .actual_samples_per_second, SWITCH_FILE_FLAG_READ | SWITCH_FILE_DATA_SHORT , ((void*)0)) | |||||||||
| 3588 | read_impl.actual_samples_per_second, SWITCH_FILE_FLAG_READ | SWITCH_FILE_DATA_SHORT, NULL)switch_core_perform_file_open("src/switch_ivr.c", (const char *)__func__, 3588, &orig_fh, file, new_fh.channels, read_impl .actual_samples_per_second, SWITCH_FILE_FLAG_READ | SWITCH_FILE_DATA_SHORT , ((void*)0)) != SWITCH_STATUS_SUCCESS) { | |||||||||
| 3589 | switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "src/switch_ivr.c", (const char *) __func__, 3589, (const char*)(session), SWITCH_LOG_ERROR, "Failed to open file %s\n", file); | |||||||||
| 3590 | goto end; | |||||||||
| 3591 | } | |||||||||
| 3592 | ||||||||||
| 3593 | pos = 0; | |||||||||
| 3594 | switch_core_file_seek(&orig_fh, &pos, sample_point, SEEK_SET0); | |||||||||
| 3595 | ||||||||||
| 3596 | while (switch_channel_ready(channel)switch_channel_test_ready(channel, SWITCH_TRUE, SWITCH_FALSE)) { | |||||||||
| 3597 | olen = START_SAMPLES32768; | |||||||||
| 3598 | ||||||||||
| 3599 | if (!asis) { | |||||||||
| 3600 | olen /= 2; | |||||||||
| 3601 | } | |||||||||
| 3602 | ||||||||||
| 3603 | if (switch_core_file_read(&orig_fh, abuf, &olen) != SWITCH_STATUS_SUCCESS || !olen) { | |||||||||
| 3604 | break; | |||||||||
| 3605 | } | |||||||||
| 3606 | ||||||||||
| 3607 | sample_count += olen; | |||||||||
| 3608 | ||||||||||
| 3609 | switch_core_file_write(&new_fh, abuf, &olen); | |||||||||
| 3610 | } | |||||||||
| 3611 | ||||||||||
| 3612 | end: | |||||||||
| 3613 | ||||||||||
| 3614 | if (switch_test_flag((&orig_fh), SWITCH_FILE_OPEN)(((&orig_fh))->flags & SWITCH_FILE_OPEN)) { | |||||||||
| 3615 | switch_core_file_close(&orig_fh); | |||||||||
| 3616 | } | |||||||||
| 3617 | ||||||||||
| 3618 | if (switch_test_flag((&new_fh), SWITCH_FILE_OPEN)(((&new_fh))->flags & SWITCH_FILE_OPEN)) { | |||||||||
| 3619 | switch_core_file_close(&new_fh); | |||||||||
| 3620 | } | |||||||||
| 3621 | ||||||||||
| 3622 | switch_file_rename(tmp_file, file, switch_core_session_get_pool(session)); | |||||||||
| 3623 | unlink(tmp_file); | |||||||||
| 3624 | ||||||||||
| 3625 | switch_safe_free(abuf)if (abuf) {free(abuf);abuf=((void*)0);}; | |||||||||
| 3626 | ||||||||||
| 3627 | return SWITCH_STATUS_SUCCESS; | |||||||||
| 3628 | } | |||||||||
| 3629 | ||||||||||
| 3630 | ||||||||||
| 3631 | SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_ivr_create_message_reply(switch_event_t **reply, switch_event_t *message, const char *new_proto) | |||||||||
| 3632 | { | |||||||||
| 3633 | switch_status_t status = SWITCH_STATUS_SUCCESS; | |||||||||
| 3634 | ||||||||||
| 3635 | if ((status = switch_event_dup_reply(reply, message) != SWITCH_STATUS_SUCCESS)) { | |||||||||
| 3636 | abort(); | |||||||||
| 3637 | } | |||||||||
| 3638 | ||||||||||
| 3639 | switch_event_add_header_string(*reply, SWITCH_STACK_BOTTOM, "proto", new_proto); | |||||||||
| 3640 | ||||||||||
| 3641 | return status; | |||||||||
| 3642 | } | |||||||||
| 3643 | ||||||||||
| 3644 | SWITCH_DECLARE(char *)__attribute__((visibility("default"))) char * switch_ivr_check_presence_mapping(const char *exten_name, const char *domain_name) | |||||||||
| 3645 | { | |||||||||
| 3646 | char *cf = "presence_map.conf"; | |||||||||
| 3647 | switch_xml_t cfg, xml, x_domains, x_domain, x_exten; | |||||||||
| 3648 | char *r = NULL((void*)0); | |||||||||
| 3649 | switch_event_t *params = NULL((void*)0); | |||||||||
| 3650 | switch_regex_t *re = NULL((void*)0); | |||||||||
| 3651 | int proceed = 0, ovector[100]; | |||||||||
| 3652 | ||||||||||
| 3653 | switch_event_create(¶ms, SWITCH_EVENT_REQUEST_PARAMS)switch_event_create_subclass_detailed("src/switch_ivr.c", (const char * )(const char *)__func__, 3653, ¶ms, SWITCH_EVENT_REQUEST_PARAMS , ((void*)0)); | |||||||||
| 3654 | switch_assert(params)((params) ? (void) (0) : __assert_fail ("params", "src/switch_ivr.c" , 3654, __PRETTY_FUNCTION__)); | |||||||||
| 3655 | ||||||||||
| 3656 | if ( !zstr(domain_name)_zstr(domain_name) ) { | |||||||||
| 3657 | switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "domain", domain_name); | |||||||||
| 3658 | } | |||||||||
| 3659 | ||||||||||
| 3660 | if ( !zstr(exten_name)_zstr(exten_name) ) { | |||||||||
| 3661 | switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "exten", exten_name); | |||||||||
| 3662 | } | |||||||||
| 3663 | ||||||||||
| 3664 | if (!(xml = switch_xml_open_cfg(cf, &cfg, params))) { | |||||||||
| 3665 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_ivr.c", (const char *)__func__ , 3665, ((void*)0), SWITCH_LOG_ERROR, "Open of %s failed\n", cf); | |||||||||
| 3666 | goto end; | |||||||||
| 3667 | } | |||||||||
| 3668 | ||||||||||
| 3669 | if (!(x_domains = switch_xml_child(cfg, "domains"))) { | |||||||||
| 3670 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_ivr.c", (const char *)__func__ , 3670, ((void*)0), SWITCH_LOG_ERROR, "Can't find any domains!\n"); | |||||||||
| 3671 | goto end; | |||||||||
| 3672 | } | |||||||||
| 3673 | ||||||||||
| 3674 | for (x_domain = switch_xml_child(x_domains, "domain"); x_domain; x_domain = x_domain->next) { | |||||||||
| 3675 | const char *dname = switch_xml_attr(x_domain, "name"); | |||||||||
| 3676 | if (!dname || (strcasecmp(dname, "*") && strcasecmp(domain_name, dname))) continue; | |||||||||
| 3677 | ||||||||||
| 3678 | for (x_exten = switch_xml_child(x_domain, "exten"); x_exten; x_exten = x_exten->next) { | |||||||||
| 3679 | const char *regex = switch_xml_attr(x_exten, "regex"); | |||||||||
| 3680 | const char *proto = switch_xml_attr(x_exten, "proto"); | |||||||||
| 3681 | ||||||||||
| 3682 | if (!zstr(regex)_zstr(regex) && !zstr(proto)_zstr(proto)) { | |||||||||
| 3683 | proceed = switch_regex_perform(exten_name, regex, &re, ovector, sizeof(ovector) / sizeof(ovector[0])); | |||||||||
| 3684 | switch_regex_safe_free(re)if (re) { switch_regex_free(re); re = ((void*)0); }; | |||||||||
| 3685 | ||||||||||
| 3686 | if (proceed) { | |||||||||
| 3687 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_ivr.c", (const char *)__func__ , 3687, ((void*)0), SWITCH_LOG_DEBUG1, "Mapping %s@%s to proto %s matching expression [%s]\n", | |||||||||
| 3688 | exten_name, domain_name, proto, regex); | |||||||||
| 3689 | r = strdup(proto)(__extension__ (__builtin_constant_p (proto) && ((size_t )(const void *)((proto) + 1) - (size_t)(const void *)(proto) == 1) ? (((const char *) (proto))[0] == '\0' ? (char *) calloc ( (size_t) 1, (size_t) 1) : ({ size_t __len = strlen (proto) + 1 ; char *__retval = (char *) malloc (__len); if (__retval != ( (void*)0)) __retval = (char *) memcpy (__retval, proto, __len ); __retval; })) : __strdup (proto))); | |||||||||
| 3690 | goto end; | |||||||||
| 3691 | } | |||||||||
| 3692 | ||||||||||
| 3693 | } | |||||||||
| 3694 | } | |||||||||
| 3695 | } | |||||||||
| 3696 | ||||||||||
| 3697 | end: | |||||||||
| 3698 | switch_event_destroy(¶ms); | |||||||||
| 3699 | ||||||||||
| 3700 | if (xml) { | |||||||||
| 3701 | switch_xml_free(xml); | |||||||||
| 3702 | } | |||||||||
| 3703 | ||||||||||
| 3704 | return r; | |||||||||
| 3705 | ||||||||||
| 3706 | } | |||||||||
| 3707 | ||||||||||
| 3708 | SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_ivr_kill_uuid(const char *uuid, switch_call_cause_t cause) | |||||||||
| 3709 | { | |||||||||
| 3710 | switch_core_session_t *session; | |||||||||
| 3711 | ||||||||||
| 3712 | if (zstr(uuid)_zstr(uuid) || !(session = switch_core_session_locate(uuid)switch_core_session_perform_locate(uuid, "src/switch_ivr.c", ( const char *)__func__, 3712))) { | |||||||||
| 3713 | return SWITCH_STATUS_FALSE; | |||||||||
| 3714 | } else { | |||||||||
| 3715 | switch_channel_t *channel = switch_core_session_get_channel(session); | |||||||||
| 3716 | switch_channel_hangup(channel, cause)switch_channel_perform_hangup(channel, "src/switch_ivr.c", (const char *)__func__, 3716, cause); | |||||||||
| 3717 | switch_core_session_rwunlock(session); | |||||||||
| 3718 | return SWITCH_STATUS_SUCCESS; | |||||||||
| 3719 | } | |||||||||
| 3720 | } | |||||||||
| 3721 | ||||||||||
| 3722 | SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_ivr_blind_transfer_ack(switch_core_session_t *session, switch_bool_t success) | |||||||||
| 3723 | { | |||||||||
| 3724 | switch_channel_t *channel = switch_core_session_get_channel(session); | |||||||||
| 3725 | switch_status_t status = SWITCH_STATUS_FALSE; | |||||||||
| 3726 | ||||||||||
| 3727 | if (switch_channel_test_flag(channel, CF_CONFIRM_BLIND_TRANSFER)) { | |||||||||
| 3728 | switch_core_session_t *other_session; | |||||||||
| 3729 | const char *uuid = switch_channel_get_variable(channel, "blind_transfer_uuid")switch_channel_get_variable_dup(channel, "blind_transfer_uuid" , SWITCH_TRUE, -1); | |||||||||
| 3730 | ||||||||||
| 3731 | switch_channel_clear_flag(channel, CF_CONFIRM_BLIND_TRANSFER); | |||||||||
| 3732 | ||||||||||
| 3733 | if (!zstr(uuid)_zstr(uuid) && (other_session = switch_core_session_locate(uuid)switch_core_session_perform_locate(uuid, "src/switch_ivr.c", ( const char *)__func__, 3733))) { | |||||||||
| 3734 | switch_core_session_message_t msg = { 0 }; | |||||||||
| 3735 | msg.message_id = SWITCH_MESSAGE_INDICATE_BLIND_TRANSFER_RESPONSE; | |||||||||
| 3736 | msg.from = __FILE__"src/switch_ivr.c"; | |||||||||
| 3737 | msg.numeric_arg = success; | |||||||||
| 3738 | switch_core_session_receive_message(other_session, &msg)switch_core_session_perform_receive_message(other_session, & msg, "src/switch_ivr.c", (const char *)__func__, 3738); | |||||||||
| 3739 | switch_core_session_rwunlock(other_session); | |||||||||
| 3740 | status = SWITCH_STATUS_SUCCESS; | |||||||||
| 3741 | } | |||||||||
| 3742 | } | |||||||||
| 3743 | ||||||||||
| 3744 | return status; | |||||||||
| 3745 | ||||||||||
| 3746 | } | |||||||||
| 3747 | ||||||||||
| 3748 | /* For Emacs: | |||||||||
| 3749 | * Local Variables: | |||||||||
| 3750 | * mode:c | |||||||||
| 3751 | * indent-tabs-mode:t | |||||||||
| 3752 | * tab-width:4 | |||||||||
| 3753 | * c-basic-offset:4 | |||||||||
| 3754 | * End: | |||||||||
| 3755 | * For VIM: | |||||||||
| 3756 | * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet: | |||||||||
| 3757 | */ |