]> git.ipfire.org Git - thirdparty/freeswitch.git/blame - src/switch_cpp.cpp
[core] Coverity fixes
[thirdparty/freeswitch.git] / src / switch_cpp.cpp
CommitLineData
df1ab07c 1/*
03845667 2 * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
6e7d5d08 3 * Copyright (C) 2005-2014, Anthony Minessale II <anthm@freeswitch.org>
03845667
MJ
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
ae220d33 20 * Anthony Minessale II <anthm@freeswitch.org>
03845667
MJ
21 * Portions created by the Initial Developer are Copyright (C)
22 * the Initial Developer. All Rights Reserved.
23 *
24 * Contributor(s):
df1ab07c 25 *
ae220d33 26 * Anthony Minessale II <anthm@freeswitch.org>
03845667
MJ
27 *
28 *
29 * switch_cpp.cpp -- C++ wrapper
30 *
31 */
32
83f84876
AM
33#include <switch.h>
34#include <switch_cpp.h>
35
8107c49a
MJ
36#ifdef _MSC_VER
37#pragma warning(disable:4127 4003)
38#endif
39
eec83be1
AM
40static void event_handler(switch_event_t *event)
41{
a1cf7067
AM
42 EventConsumer *E = (EventConsumer *) event->bind_user_data;
43 switch_event_t *dup;
df1ab07c 44
a1cf7067
AM
45 switch_event_dup(&dup, event);
46
47 if (switch_queue_trypush(E->events, dup) != SWITCH_STATUS_SUCCESS) {
48 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Cannot queue any more events.....\n");
1e22ba2b 49 switch_event_destroy(&dup);
a1cf7067
AM
50 }
51
eec83be1
AM
52}
53
830755ac 54SWITCH_DECLARE_CONSTRUCTOR EventConsumer::EventConsumer(const char *event_name, const char *subclass_name, int len)
eec83be1 55{
a7f74af7 56
df1ab07c 57 switch_core_new_memory_pool(&pool);
830755ac 58 switch_queue_create(&events, len, pool);
05bf1d83 59 node_index = 0;
0e41c484 60 ready = 1;
df1ab07c 61
a7f74af7
AM
62 if (!zstr(event_name)) {
63 bind(event_name, subclass_name);
eec83be1 64 }
a7f74af7
AM
65}
66
67SWITCH_DECLARE(int) EventConsumer::bind(const char *event_name, const char *subclass_name)
68{
69 switch_event_types_t event_id = SWITCH_EVENT_CUSTOM;
a7f74af7 70
1e22ba2b
AM
71 if (!ready) {
72 return 0;
73 }
74
94d28e0f
MJ
75 if (switch_name_event(event_name, &event_id) != SWITCH_STATUS_SUCCESS) {
76 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Can't bind to %s, event not found\n", event_name);
77 return 0;
78 }
a7f74af7
AM
79
80 if (zstr(subclass_name)) {
81 subclass_name = NULL;
82 }
df1ab07c
SS
83
84 if (node_index <= SWITCH_EVENT_ALL &&
7fd3aff6 85 switch_event_bind_removable(__FILE__, event_id, subclass_name, event_handler, this, &enodes[node_index]) == SWITCH_STATUS_SUCCESS) {
78eb8f61 86 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "bound to %s %s\n", event_name, switch_str_nil(subclass_name));
7fd3aff6 87 node_index++;
a7f74af7 88 return 1;
eec83be1 89 }
94d28e0f
MJ
90
91 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Cannot bind to %s %s\n", event_name, switch_str_nil(subclass_name));
92 return 0;
a1cf7067
AM
93}
94
eec83be1 95
b992e296 96SWITCH_DECLARE(Event *) EventConsumer::pop(int block, int timeout)
a1cf7067
AM
97{
98 void *pop = NULL;
99 Event *ret = NULL;
100 switch_event_t *event;
bb9afcb3 101 switch_status_t res;
1e22ba2b
AM
102
103 if (!ready) {
104 return NULL;
105 }
df1ab07c 106
a1cf7067 107 if (block) {
b992e296 108 if (timeout > 0) {
bb9afcb3 109 res = switch_queue_pop_timeout(events, &pop, (switch_interval_time_t) timeout * 1000); // millisec rather than microsec
b992e296 110 } else {
bb9afcb3 111 res = switch_queue_pop(events, &pop);
b992e296 112 }
a1cf7067 113 } else {
bb9afcb3 114 res = switch_queue_trypop(events, &pop);
a1cf7067
AM
115 }
116
bb9afcb3
JK
117 (void)res;
118
a1cf7067 119 if ((event = (switch_event_t *) pop)) {
cf22bd97 120 ret = new Event(event, 1);
a1cf7067 121 }
eec83be1 122
a1cf7067
AM
123 return ret;
124}
eec83be1 125
1e22ba2b 126SWITCH_DECLARE(void) EventConsumer::cleanup()
eec83be1 127{
1e22ba2b 128
7fd3aff6 129 uint32_t i;
1e22ba2b
AM
130 void *pop;
131
132 if (!ready) {
133 return;
df1ab07c 134 }
1e22ba2b
AM
135
136 ready = 0;
a7f74af7 137
7fd3aff6
AM
138 for (i = 0; i < node_index; i++) {
139 switch_event_unbind(&enodes[i]);
140 }
a1cf7067 141
1e22ba2b
AM
142 node_index = 0;
143
bb9afcb3 144 switch_queue_interrupt_all(events);
608ca822 145
1e22ba2b
AM
146 while(switch_queue_trypop(events, &pop) == SWITCH_STATUS_SUCCESS) {
147 switch_event_t *event = (switch_event_t *) pop;
148 switch_event_destroy(&event);
149 }
150
151
a1cf7067 152 switch_core_destroy_memory_pool(&pool);
1e22ba2b
AM
153
154}
155
156
157SWITCH_DECLARE_CONSTRUCTOR EventConsumer::~EventConsumer()
158{
159 cleanup();
eec83be1 160}
aa47e3e5
AM
161
162SWITCH_DECLARE_CONSTRUCTOR IVRMenu::IVRMenu(IVRMenu *main,
163 const char *name,
164 const char *greeting_sound,
165 const char *short_greeting_sound,
166 const char *invalid_sound,
167 const char *exit_sound,
fb34ff9a 168 const char *transfer_sound,
aa47e3e5
AM
169 const char *confirm_macro,
170 const char *confirm_key,
85c26566
BW
171 const char *tts_engine,
172 const char *tts_voice,
aa47e3e5
AM
173 int confirm_attempts,
174 int inter_timeout,
175 int digit_len,
176 int timeout,
fb06cc2d
AM
177 int max_failures,
178 int max_timeouts)
aa47e3e5
AM
179{
180 menu = NULL;
181 switch_core_new_memory_pool(&pool);
182 switch_assert(pool);
df7637f6 183 if (zstr(name)) {
aa47e3e5
AM
184 name = "no name";
185 }
186
df1ab07c 187 switch_ivr_menu_init(&menu, main ? main->menu : NULL, name, greeting_sound, short_greeting_sound, invalid_sound,
fb34ff9a 188 exit_sound, transfer_sound, confirm_macro, confirm_key, tts_engine, tts_voice, confirm_attempts, inter_timeout,
85c26566 189 digit_len, timeout, max_failures, max_timeouts, pool);
df1ab07c 190
aa47e3e5
AM
191
192}
df1ab07c 193
aa47e3e5
AM
194SWITCH_DECLARE_CONSTRUCTOR IVRMenu::~IVRMenu()
195{
196 if (menu) {
197 switch_ivr_menu_stack_free(menu);
198 }
199 switch_core_destroy_memory_pool(&pool);
200}
201
202SWITCH_DECLARE(void) IVRMenu::bindAction(char *action, const char *arg, const char *bind)
203{
204 switch_ivr_action_t ivr_action = SWITCH_IVR_ACTION_NOOP;
205
878bbceb 206 this_check_void();
df1ab07c 207
aa47e3e5
AM
208 if (switch_ivr_menu_str2action(action, &ivr_action) == SWITCH_STATUS_SUCCESS) {
209 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "bind %s to %s(%s)\n", bind, action, arg);
210 switch_ivr_menu_bind_action(menu, ivr_action, arg, bind);
211 } else {
212 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "invalid action %s\n", action);
213 }
214}
215
216SWITCH_DECLARE(void) IVRMenu::execute(CoreSession *session, const char *name)
217{
878bbceb 218 this_check_void();
aa47e3e5
AM
219 switch_ivr_menu_execute(session->session, menu, (char *)name, NULL);
220}
221
802794b9 222SWITCH_DECLARE_CONSTRUCTOR API::API(CoreSession *s)
8f5a873d 223{
802794b9
AM
224 if (s) {
225 session = s->session;
226 } else {
227 session = NULL;
228 }
8f5a873d
AM
229}
230
231SWITCH_DECLARE_CONSTRUCTOR API::~API()
232{
3a00260d 233 return;
8f5a873d
AM
234}
235
236
1a2131de 237SWITCH_DECLARE(const char *) API::execute(const char *cmd, const char *arg)
8f5a873d
AM
238{
239 switch_stream_handle_t stream = { 0 };
878bbceb 240 this_check("");
4d7a0ac0 241
8f5a873d 242 SWITCH_STANDARD_STREAM(stream);
4d7a0ac0
AM
243
244 if (zstr(cmd)) {
245 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "No application specified\n");
246 stream.write_function(&stream, "-ERR No application specified");
247 } else {
248 switch_api_execute(cmd, arg, session, &stream);
249 }
250
3a00260d 251 return (char *) stream.data;
8f5a873d
AM
252}
253
072ec6a7
AM
254
255/* we have to do this as a string because swig and languages can't find an embedded way to pass a big int */
8812477e 256SWITCH_DECLARE(char *) API::getTime(void)
072ec6a7
AM
257{
258 switch_time_t now = switch_micro_time_now() / 1000;
259 snprintf(time_buf, sizeof(time_buf), "%" SWITCH_TIME_T_FMT, now);
260 return time_buf;
261}
262
263
264
1a2131de 265SWITCH_DECLARE(const char *) API::executeString(const char *cmd)
8f5a873d
AM
266{
267 char *arg;
268 switch_stream_handle_t stream = { 0 };
cc2efd55 269 char *mycmd = NULL;
8f5a873d 270
878bbceb
AM
271 this_check("");
272
4e997750
ML
273 SWITCH_STANDARD_STREAM(stream);
274
275 if (zstr(cmd)) {
276 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "No application specified\n");
277 stream.write_function(&stream, "-ERR No application specified");
278 } else {
279 mycmd = strdup(cmd);
cc2efd55 280
4e997750
ML
281 switch_assert(mycmd);
282
283 if ((arg = strchr(mycmd, ' '))) {
284 *arg++ = '\0';
285 }
cc2efd55 286
4e997750
ML
287 switch_api_execute(mycmd, arg, session, &stream);
288 switch_safe_free(mycmd);
8f5a873d
AM
289 }
290
3a00260d 291 return (char *) stream.data;
8f5a873d 292}
e028f269 293
069d4681 294SWITCH_DECLARE_CONSTRUCTOR Event::Event(const char *type, const char *subclass_name)
ae76db7b
AM
295{
296 switch_event_types_t event_id;
ae76db7b 297
c5086b15
AM
298 if (!strcasecmp(type, "json") && !zstr(subclass_name)) {
299 if (switch_event_create_json(&event, subclass_name) != SWITCH_STATUS_SUCCESS) {
300 return;
301 }
df1ab07c 302
c5086b15
AM
303 event_id = event->event_id;
304
305 } else {
306 if (switch_name_event(type, &event_id) != SWITCH_STATUS_SUCCESS) {
307 event_id = SWITCH_EVENT_MESSAGE;
308 }
7aa7dd7e 309
c5086b15
AM
310 if (!zstr(subclass_name) && event_id != SWITCH_EVENT_CUSTOM) {
311 switch_log_printf(SWITCH_CHANNEL_LOG,SWITCH_LOG_WARNING, "Changing event type to custom because you specified a subclass name!\n");
312 event_id = SWITCH_EVENT_CUSTOM;
313 }
314
315 if (switch_event_create_subclass(&event, event_id, subclass_name) != SWITCH_STATUS_SUCCESS) {
316 switch_log_printf(SWITCH_CHANNEL_LOG,SWITCH_LOG_ERROR, "Failed to create event!\n");
317 event = NULL;
318 }
7aa7dd7e
BW
319 }
320
59526679
AM
321 serialized_string = NULL;
322 mine = 1;
323}
324
069d4681 325SWITCH_DECLARE_CONSTRUCTOR Event::Event(switch_event_t *wrap_me, int free_me)
59526679
AM
326{
327 event = wrap_me;
328 mine = free_me;
329 serialized_string = NULL;
ae76db7b
AM
330}
331
069d4681 332SWITCH_DECLARE_CONSTRUCTOR Event::~Event()
ae76db7b 333{
59526679
AM
334
335 if (serialized_string) {
336 free(serialized_string);
337 }
338
339 if (event && mine) {
ae76db7b
AM
340 switch_event_destroy(&event);
341 }
342}
343
7333d46d
AM
344SWITCH_DECLARE(int)Event::chat_execute(const char *app, const char *data)
345{
346 return (int) switch_core_execute_chat_app(event, app, data);
347}
348
349SWITCH_DECLARE(int)Event::chat_send(const char *dest_proto)
350{
351 if (zstr(dest_proto)) {
352 dest_proto = switch_event_get_header(event, "dest_proto");
353 }
354
355 return (int) switch_core_chat_send(dest_proto, event);
356}
59526679 357
069d4681 358SWITCH_DECLARE(const char *)Event::serialize(const char *format)
59526679 359{
878bbceb
AM
360 this_check("");
361
59526679 362
a1cf7067 363 switch_safe_free(serialized_string);
df1ab07c 364
59526679
AM
365 if (!event) {
366 return "";
367 }
368
369 if (format && !strcasecmp(format, "xml")) {
59526679 370 switch_xml_t xml;
59526679
AM
371 if ((xml = switch_event_xmlize(event, SWITCH_VA_NONE))) {
372 serialized_string = switch_xml_toxml(xml, SWITCH_FALSE);
373 switch_xml_free(xml);
374 return serialized_string;
375 } else {
376 return "";
377 }
c5086b15
AM
378 } else if (format && !strcasecmp(format, "json")) {
379 switch_event_serialize_json(event, &serialized_string);
380 return serialized_string;
59526679
AM
381 } else {
382 if (switch_event_serialize(event, &serialized_string, SWITCH_TRUE) == SWITCH_STATUS_SUCCESS) {
9b8a5edd 383 char *new_serialized_string = switch_mprintf("%s", serialized_string);
e858a1d8
AM
384 free(serialized_string);
385 serialized_string = new_serialized_string;
59526679
AM
386 return serialized_string;
387 }
388 }
df1ab07c 389
59526679
AM
390 return "";
391
392}
393
069d4681 394SWITCH_DECLARE(bool) Event::fire(void)
ae76db7b 395{
878bbceb
AM
396
397 this_check(false);
398
59526679
AM
399 if (!mine) {
400 switch_log_printf(SWITCH_CHANNEL_LOG,SWITCH_LOG_ERROR, "Not My event!\n");
401 return false;
402 }
403
ae76db7b 404 if (event) {
2b5f3563
AM
405 switch_event_t *new_event;
406 if (switch_event_dup(&new_event, event) == SWITCH_STATUS_SUCCESS) {
7aa7dd7e
BW
407 if (switch_event_fire(&new_event) != SWITCH_STATUS_SUCCESS) {
408 switch_log_printf(SWITCH_CHANNEL_LOG,SWITCH_LOG_ERROR, "Failed to fire the event!\n");
409 switch_event_destroy(&new_event);
410 return false;
411 }
2b5f3563 412 return true;
7aa7dd7e
BW
413 } else {
414 switch_log_printf(SWITCH_CHANNEL_LOG,SWITCH_LOG_ERROR, "Failed to dup the event!\n");
2b5f3563 415 }
7aa7dd7e
BW
416 } else {
417 switch_log_printf(SWITCH_CHANNEL_LOG,SWITCH_LOG_ERROR, "Trying to fire an event that does not exist!\n");
ae76db7b
AM
418 }
419 return false;
420}
421
b6d649fc 422SWITCH_DECLARE(bool) Event::setPriority(switch_priority_t priority)
ae76db7b 423{
878bbceb
AM
424 this_check(false);
425
ae76db7b
AM
426 if (event) {
427 switch_event_set_priority(event, priority);
428 return true;
7aa7dd7e
BW
429 } else {
430 switch_log_printf(SWITCH_CHANNEL_LOG,SWITCH_LOG_ERROR, "Trying to setPriority an event that does not exist!\n");
ae76db7b
AM
431 }
432 return false;
433}
434
c27a26e3 435SWITCH_DECLARE(const char *)Event::getHeader(const char *header_name)
ae76db7b 436{
878bbceb
AM
437 this_check("");
438
4e997750
ML
439 if (zstr(header_name)) {
440 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Trying to getHeader an invalid header!\n");
441 return NULL;
442 }
443
ae76db7b
AM
444 if (event) {
445 return switch_event_get_header(event, header_name);
7aa7dd7e
BW
446 } else {
447 switch_log_printf(SWITCH_CHANNEL_LOG,SWITCH_LOG_ERROR, "Trying to getHeader an event that does not exist!\n");
ae76db7b
AM
448 }
449 return NULL;
450}
451
b6d649fc 452SWITCH_DECLARE(bool) Event::addHeader(const char *header_name, const char *value)
ae76db7b 453{
878bbceb
AM
454 this_check(false);
455
ae76db7b
AM
456 if (event) {
457 return switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, header_name, value) == SWITCH_STATUS_SUCCESS ? true : false;
7aa7dd7e
BW
458 } else {
459 switch_log_printf(SWITCH_CHANNEL_LOG,SWITCH_LOG_ERROR, "Trying to addHeader an event that does not exist!\n");
ae76db7b
AM
460 }
461
462 return false;
463}
464
b6d649fc 465SWITCH_DECLARE(bool) Event::delHeader(const char *header_name)
ae76db7b 466{
878bbceb
AM
467 this_check(false);
468
4e997750
ML
469 if (zstr(header_name)) {
470 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Trying to delHeader an invalid header!\n");
471 return false;
472 }
473
ae76db7b
AM
474 if (event) {
475 return switch_event_del_header(event, header_name) == SWITCH_STATUS_SUCCESS ? true : false;
7aa7dd7e
BW
476 } else {
477 switch_log_printf(SWITCH_CHANNEL_LOG,SWITCH_LOG_ERROR, "Trying to delHeader an event that does not exist!\n");
ae76db7b
AM
478 }
479
480 return false;
481}
482
483
b6d649fc 484SWITCH_DECLARE(bool) Event::addBody(const char *value)
ae76db7b 485{
878bbceb
AM
486 this_check(false);
487
ae76db7b
AM
488 if (event) {
489 return switch_event_add_body(event, "%s", value) == SWITCH_STATUS_SUCCESS ? true : false;
7aa7dd7e
BW
490 } else {
491 switch_log_printf(SWITCH_CHANNEL_LOG,SWITCH_LOG_ERROR, "Trying to addBody an event that does not exist!\n");
ae76db7b 492 }
df1ab07c 493
ae76db7b
AM
494 return false;
495}
496
b6d649fc 497SWITCH_DECLARE(char *)Event::getBody(void)
ae76db7b 498{
df1ab07c 499
878bbceb
AM
500 this_check((char *)"");
501
ae76db7b
AM
502 if (event) {
503 return switch_event_get_body(event);
7aa7dd7e
BW
504 } else {
505 switch_log_printf(SWITCH_CHANNEL_LOG,SWITCH_LOG_ERROR, "Trying to getBody an event that does not exist!\n");
ae76db7b 506 }
df1ab07c 507
ae76db7b
AM
508 return NULL;
509}
510
d5e4046d 511SWITCH_DECLARE(const char *)Event::getType(void)
b6d649fc 512{
878bbceb
AM
513 this_check("");
514
b6d649fc
AM
515 if (event) {
516 return switch_event_name(event->event_id);
7aa7dd7e
BW
517 } else {
518 switch_log_printf(SWITCH_CHANNEL_LOG,SWITCH_LOG_ERROR, "Trying to getType an event that does not exist!\n");
b6d649fc 519 }
df1ab07c 520
d5e4046d 521 return (char *) "invalid";
b6d649fc
AM
522}
523
6cf606f2
SD
524SWITCH_DECLARE(bool)Event::merge(Event *to_merge)
525{
526 this_check(false);
527
528 if (!event) {
529 switch_log_printf(SWITCH_CHANNEL_LOG,SWITCH_LOG_ERROR, "Trying to merge to an event that does not exist!\n");
530 return false;
531 }
532
533 if (!to_merge || !to_merge->event) {
534 switch_log_printf(SWITCH_CHANNEL_LOG,SWITCH_LOG_ERROR, "Trying to merge from an event that does not exist!\n");
535 return false;
536 }
537
538 switch_event_merge(event, to_merge->event);
539
540 return true;
541}
a3ccefa7
AM
542
543SWITCH_DECLARE_CONSTRUCTOR DTMF::DTMF(char idigit, uint32_t iduration)
544{
545 digit = idigit;
546
547 if (iduration == 0) {
a358cf8e 548 iduration = SWITCH_DEFAULT_DTMF_DURATION;
a3ccefa7
AM
549 }
550
551 duration = iduration;
552}
553
554SWITCH_DECLARE_CONSTRUCTOR DTMF::~DTMF()
555{
df1ab07c 556
a3ccefa7
AM
557}
558
559
069d4681 560SWITCH_DECLARE_CONSTRUCTOR Stream::Stream()
ae76db7b
AM
561{
562 SWITCH_STANDARD_STREAM(mystream);
563 stream_p = &mystream;
564 mine = 1;
565}
566
069d4681 567SWITCH_DECLARE_CONSTRUCTOR Stream::Stream(switch_stream_handle_t *sp)
ae76db7b
AM
568{
569 stream_p = sp;
570 mine = 0;
571}
572
573
069d4681 574SWITCH_DECLARE_CONSTRUCTOR Stream::~Stream()
ae76db7b
AM
575{
576 if (mine) {
577 switch_safe_free(mystream.data);
578 }
579}
580
31f78d8c 581/* WARNING!! you are not encouraged to use this unless you understand the risk!!! */
1a4e6e30 582SWITCH_DECLARE(const char *) Stream::read(int *len)
31f78d8c
SD
583{
584 uint8_t *buff;
31f78d8c 585
1a4e6e30 586 this_check(NULL);
31f78d8c 587
1a4e6e30 588 if (!stream_p->read_function) return NULL;
31f78d8c 589
1a4e6e30 590 buff = stream_p->read_function(stream_p, len);
31f78d8c 591
aa15994c
SD
592 if (!buff || *len <= 0) {
593 *len = 0;
594 return NULL;
595 }
31f78d8c 596
1a4e6e30 597 return (const char *)buff;
31f78d8c
SD
598}
599
069d4681 600SWITCH_DECLARE(void) Stream::write(const char *data)
ae76db7b 601{
878bbceb 602 this_check_void();
ae76db7b
AM
603 stream_p->write_function(stream_p, "%s", data);
604}
605
1a4e6e30 606SWITCH_DECLARE(void) Stream::raw_write(const char *data, int len)
31f78d8c
SD
607{
608 this_check_void();
1a4e6e30 609 stream_p->raw_write_function(stream_p, (uint8_t *)data, len);
31f78d8c
SD
610}
611
069d4681 612SWITCH_DECLARE(const char *)Stream::get_data()
ae76db7b 613{
878bbceb
AM
614 this_check("");
615
ae76db7b
AM
616 return stream_p ? (const char *)stream_p->data : NULL;
617}
e028f269
MJ
618
619
47985c56 620SWITCH_DECLARE_CONSTRUCTOR CoreSession::CoreSession()
e028f269 621{
24a27c6e 622 init_vars();
e028f269 623}
83f84876 624
df5afbca 625SWITCH_DECLARE_CONSTRUCTOR CoreSession::CoreSession(char *nuuid, CoreSession *a_leg)
83f84876 626{
0ba25358
AM
627 switch_channel_t *other_channel = NULL;
628
a06997ee 629 init_vars();
24a27c6e 630
0ba25358
AM
631 if (a_leg && a_leg->session) {
632 other_channel = switch_core_session_get_channel(a_leg->session);
633 }
634
301ea9fb 635 if (!strchr(nuuid, '/') && (session = switch_core_session_force_locate(nuuid))) {
94b22258 636 uuid = strdup(nuuid);
d895c81d 637 channel = switch_core_session_get_channel(session);
94b22258 638 allocated = 1;
ae76db7b 639 } else {
2261b687 640 cause = SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER;
d3e320ef 641 if (switch_ivr_originate(a_leg ? a_leg->session : NULL, &session, &cause, nuuid, 60, NULL, NULL, NULL, NULL, NULL, SOF_NONE, NULL, NULL)
a579a283 642 == SWITCH_STATUS_SUCCESS) {
d895c81d 643 channel = switch_core_session_get_channel(session);
ae76db7b
AM
644 allocated = 1;
645 switch_set_flag(this, S_HUP);
646 uuid = strdup(switch_core_session_get_uuid(session));
4b929592 647 switch_channel_set_state(switch_core_session_get_channel(session), CS_SOFT_EXECUTE);
0ba25358 648 switch_channel_wait_for_state(channel, other_channel, CS_SOFT_EXECUTE);
ae76db7b
AM
649 }
650 }
83f84876
AM
651}
652
47985c56 653SWITCH_DECLARE_CONSTRUCTOR CoreSession::CoreSession(switch_core_session_t *new_session)
83f84876
AM
654{
655 init_vars();
24a27c6e 656
35865bd9 657 if (new_session && switch_core_session_read_lock_hangup(new_session) == SWITCH_STATUS_SUCCESS) {
6d1f4f6d
MJ
658 session = new_session;
659 channel = switch_core_session_get_channel(session);
660 allocated = 1;
11fc21f7 661 uuid = strdup(switch_core_session_get_uuid(session));
6d1f4f6d 662 }
83f84876
AM
663}
664
47985c56 665SWITCH_DECLARE_CONSTRUCTOR CoreSession::~CoreSession()
83f84876 666{
75dbe890 667 this_check_void();
540445cb 668 if (allocated) destroy();
83f84876
AM
669}
670
a5e10ebc
AM
671SWITCH_DECLARE(char *) CoreSession::getXMLCDR()
672{
df1ab07c 673
3a6bb506 674 switch_xml_t cdr = NULL;
878bbceb
AM
675
676 this_check((char *)"");
d5e4046d 677 sanity_check((char *)"");
a5e10ebc
AM
678
679 switch_safe_free(xml_cdr_text);
680
681 if (switch_ivr_generate_xml_cdr(session, &cdr) == SWITCH_STATUS_SUCCESS) {
682 xml_cdr_text = switch_xml_toxml(cdr, SWITCH_FALSE);
683 switch_xml_free(cdr);
684 }
685
686 return (char *) (xml_cdr_text ? xml_cdr_text : "");
687}
688
689SWITCH_DECLARE(void) CoreSession::setEventData(Event *e)
690{
878bbceb 691 this_check_void();
a5e10ebc 692 sanity_check_noreturn;
df1ab07c 693
a5e10ebc
AM
694 if (channel && e->event) {
695 switch_channel_event_set_data(channel, e->event);
696 }
697}
698
47985c56 699SWITCH_DECLARE(int) CoreSession::answer()
83f84876
AM
700{
701 switch_status_t status;
878bbceb 702 this_check(-1);
83f84876
AM
703 sanity_check(-1);
704 status = switch_channel_answer(channel);
705 return status == SWITCH_STATUS_SUCCESS ? 1 : 0;
706}
707
9b8a5edd
AM
708
709SWITCH_DECLARE(int) CoreSession::print(char *txt)
710{
711 switch_status_t status;
712 status = switch_core_session_print(session, switch_str_nil(txt));
713 this_check(-1);
714 sanity_check(-1);
715 return status == SWITCH_STATUS_SUCCESS ? 1 : 0;
716}
717
c4e350ab
AM
718SWITCH_DECLARE(int) CoreSession::insertFile(const char *file, const char *insert_file, int sample_point)
719{
720 switch_status_t status;
721 this_check(-1);
722 sanity_check(-1);
723 status = switch_ivr_insert_file(session, file, insert_file, (switch_size_t)sample_point);
724 return status == SWITCH_STATUS_SUCCESS ? 1 : 0;
725}
726
47985c56 727SWITCH_DECLARE(int) CoreSession::preAnswer()
83f84876
AM
728{
729 switch_status_t status;
878bbceb 730 this_check(-1);
83f84876 731 sanity_check(-1);
8107c49a 732 status = switch_channel_pre_answer(channel);
83f84876
AM
733 return status == SWITCH_STATUS_SUCCESS ? 1 : 0;
734}
735
f4239d95
AM
736SWITCH_DECLARE(void) CoreSession::hangupState(void)
737{
df1ab07c 738 sanity_check_noreturn;
f4239d95 739 this->begin_allow_threads();
74bfa46a 740 if (switch_channel_down(channel)) {
d13a46ac 741 switch_core_session_hangup_state(session, SWITCH_FALSE);
74bfa46a 742 }
f4239d95
AM
743 this->end_allow_threads();
744}
745
bf91ac16 746SWITCH_DECLARE(void) CoreSession::hangup(const char *cause)
83f84876 747{
878bbceb 748 this_check_void();
df1ab07c 749 sanity_check_noreturn;
c2d5f970 750 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "CoreSession::hangup\n");
996cfa54 751 this->begin_allow_threads();
4fc4c523 752 switch_channel_hangup(channel, switch_channel_str2cause(cause));
996cfa54 753 this->end_allow_threads();
83f84876
AM
754}
755
47985c56 756SWITCH_DECLARE(void) CoreSession::setPrivate(char *var, void *val)
59526679 757{
878bbceb 758 this_check_void();
59526679
AM
759 sanity_check_noreturn;
760 switch_channel_set_private(channel, var, val);
761}
762
47985c56 763SWITCH_DECLARE(void *)CoreSession::getPrivate(char *var)
59526679 764{
878bbceb 765 this_check(NULL);
59526679
AM
766 sanity_check(NULL);
767 return switch_channel_get_private(channel, var);
768}
769
47985c56 770SWITCH_DECLARE(void) CoreSession::setVariable(char *var, char *val)
83f84876 771{
878bbceb 772 this_check_void();
f32f6f24 773 sanity_check_noreturn;
49b9d7f9 774 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "CoreSession::setVariable('%s', '%s')\n", var, val);
5cd072a3 775 switch_channel_set_variable_var_check(channel, var, val, SWITCH_FALSE);
83f84876
AM
776}
777
47985c56 778SWITCH_DECLARE(const char *)CoreSession::getVariable(char *var)
83f84876 779{
878bbceb
AM
780 this_check("");
781 sanity_check("");
343d77a4 782 return switch_channel_get_variable(channel, var);
83f84876
AM
783}
784
b32de058 785SWITCH_DECLARE(void) CoreSession::execute(const char *app, const char *data)
83f84876 786{
878bbceb 787 this_check_void();
f32f6f24 788 sanity_check_noreturn;
83f84876 789
4d7a0ac0
AM
790 if (zstr(app)) {
791 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "No application specified\n");
792 return;
df1ab07c 793 }
4d7a0ac0 794
b32de058
AM
795 begin_allow_threads();
796 switch_core_session_execute_application(session, app, data);
797 end_allow_threads();
83f84876
AM
798}
799
47985c56 800SWITCH_DECLARE(void) CoreSession::setDTMFCallback(void *cbfunc, char *funcargs) {
6f78befa 801
878bbceb 802 this_check_void();
a06997ee
AM
803 sanity_check_noreturn;
804
6f78befa
TL
805 cb_state.funcargs = funcargs;
806 cb_state.function = cbfunc;
807
df1ab07c 808 args.buf = &cb_state;
6f78befa
TL
809 args.buflen = sizeof(cb_state); // not sure what this is used for, copy mod_spidermonkey
810
811 switch_channel_set_private(channel, "CoreSession", this);
df1ab07c 812
6f78befa
TL
813 // we cannot set the actual callback to a python function, because
814 // the callback is a function pointer with a specific signature.
815 // so, set it to the following c function which will act as a proxy,
816 // finding the python callback in the args callback args structure
df1ab07c 817 args.input_callback = dtmf_callback;
6f78befa
TL
818 ap = &args;
819
820
821}
f45d0601 822
47985c56 823SWITCH_DECLARE(void) CoreSession::sendEvent(Event *sendME)
59526679 824{
878bbceb
AM
825 this_check_void();
826 sanity_check_noreturn;
827
2b5f3563
AM
828 if (sendME->event) {
829 switch_event_t *new_event;
830 if (switch_event_dup(&new_event, sendME->event) == SWITCH_STATUS_SUCCESS) {
831 switch_core_session_receive_event(session, &new_event);
832 }
59526679
AM
833 }
834}
835
47985c56 836SWITCH_DECLARE(int) CoreSession::speak(char *text)
83f84876
AM
837{
838 switch_status_t status;
83f84876 839
878bbceb 840 this_check(-1);
83f84876 841 sanity_check(-1);
6f78befa 842
f45d0601 843 if (!tts_name) {
c2d5f970 844 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "No TTS engine specified\n");
f45d0601
MJ
845 return SWITCH_STATUS_FALSE;
846 }
847
848 if (!voice_name) {
c2d5f970 849 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "No TTS voice specified\n");
f45d0601
MJ
850 return SWITCH_STATUS_FALSE;
851 }
852
160edc55 853
fedefcb6 854 begin_allow_threads();
160edc55 855 status = switch_ivr_speak_text(session, tts_name, voice_name, text, ap);
fedefcb6 856 end_allow_threads();
83f84876
AM
857 return status == SWITCH_STATUS_SUCCESS ? 1 : 0;
858}
859
47985c56 860SWITCH_DECLARE(void) CoreSession::set_tts_parms(char *tts_name_p, char *voice_name_p)
83f84876 861{
3199f5ce 862 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "set_tts_parms is deprecated. Use set_tts_params.\n");
878bbceb 863 this_check_void();
f32f6f24 864 sanity_check_noreturn;
83f84876
AM
865 switch_safe_free(tts_name);
866 switch_safe_free(voice_name);
867 tts_name = strdup(tts_name_p);
868 voice_name = strdup(voice_name_p);
869}
870
3199f5ce
WK
871SWITCH_DECLARE(void) CoreSession::set_tts_params(char *tts_name_p, char *voice_name_p)
872{
873 this_check_void();
874 sanity_check_noreturn;
875 switch_safe_free(tts_name);
876 switch_safe_free(voice_name);
3930250b
MY
877 tts_name = strdup(switch_str_nil(tts_name_p));
878 voice_name = strdup(switch_str_nil(voice_name_p));
3199f5ce 879}
c806a20d 880
3bc20b3c
BW
881SWITCH_DECLARE(int) CoreSession::collectDigits(int abs_timeout) {
882 return collectDigits(0, abs_timeout);
883}
884
885SWITCH_DECLARE(int) CoreSession::collectDigits(int digit_timeout, int abs_timeout) {
878bbceb 886 this_check(-1);
c806a20d
TL
887 sanity_check(-1);
888 begin_allow_threads();
3bc20b3c 889 switch_ivr_collect_digits_callback(session, ap, digit_timeout, abs_timeout);
c806a20d 890 end_allow_threads();
a4301f0d 891 return SWITCH_STATUS_SUCCESS;
df1ab07c 892}
c806a20d 893
444c93c3
MJ
894SWITCH_DECLARE(char *) CoreSession::getDigits(int maxdigits, char *terminators, int timeout)
895{
896 return getDigits(maxdigits, terminators, timeout, 0);
897}
898
48fab6f6
BW
899SWITCH_DECLARE(char *) CoreSession::getDigits(int maxdigits, char *terminators, int timeout, int interdigit)
900{
901 return getDigits(maxdigits, terminators, timeout, interdigit, 0);
902}
903
df1ab07c
SS
904SWITCH_DECLARE(char *) CoreSession::getDigits(int maxdigits,
905 char *terminators,
444c93c3 906 int timeout,
48fab6f6
BW
907 int interdigit,
908 int abstimeout)
83f84876 909{
878bbceb 910 this_check((char *)"");
d5e4046d 911 sanity_check((char *)"");
fedefcb6 912 begin_allow_threads();
4fda174f 913 char terminator;
6f78befa 914
85fc8c37 915 memset(dtmf_buf, 0, sizeof(dtmf_buf));
df1ab07c 916 switch_ivr_collect_digits_count(session,
7963c404
MJ
917 dtmf_buf,
918 sizeof(dtmf_buf),
df1ab07c
SS
919 maxdigits,
920 terminators,
921 &terminator,
48fab6f6 922 (uint32_t) timeout, (uint32_t)interdigit, (uint32_t)abstimeout);
b997c4fc
V
923
924 /* Only log DTMF buffer if sensitive_dtmf channel variable not set to true */
925 if (!(switch_channel_var_true(switch_core_session_get_channel(session), SWITCH_SENSITIVE_DTMF_VARIABLE))) {
926 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "getDigits dtmf_buf: %s\n", dtmf_buf);
927 }
928
fedefcb6 929 end_allow_threads();
7963c404 930 return dtmf_buf;
83f84876
AM
931}
932
47985c56 933SWITCH_DECLARE(int) CoreSession::transfer(char *extension, char *dialplan, char *context)
83f84876
AM
934{
935 switch_status_t status;
878bbceb 936 this_check(-1);
83f84876 937 sanity_check(-1);
e028f269 938 begin_allow_threads();
83f84876 939 status = switch_ivr_session_transfer(session, extension, dialplan, context);
c2d5f970 940 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "transfer result: %d\n", status);
e028f269 941 end_allow_threads();
83f84876
AM
942 return status == SWITCH_STATUS_SUCCESS ? 1 : 0;
943}
944
8e0b64a1
AM
945
946SWITCH_DECLARE(char *) CoreSession::read(int min_digits,
947 int max_digits,
948 const char *prompt_audio_file,
949 int timeout,
cfa30468
AM
950 const char *valid_terminators,
951 int digit_timeout)
8e0b64a1 952{
878bbceb
AM
953 this_check((char *)"");
954 sanity_check((char *)"");
8e0b64a1
AM
955 if (min_digits < 1) {
956 min_digits = 1;
957 }
958
959 if (max_digits < 1) {
960 max_digits = 1;
961 }
962
963 if (timeout < 1) {
964 timeout = 1;
965 }
966
5195d311 967 begin_allow_threads();
df1ab07c 968 switch_ivr_read(session, min_digits, max_digits, prompt_audio_file, NULL, dtmf_buf,
cfa30468 969 sizeof(dtmf_buf), timeout, valid_terminators, (uint32_t)digit_timeout);
5195d311
AM
970 end_allow_threads();
971
8e0b64a1
AM
972 return dtmf_buf;
973}
974
df1ab07c
SS
975SWITCH_DECLARE(char *) CoreSession::playAndGetDigits(int min_digits,
976 int max_digits,
977 int max_tries,
978 int timeout,
979 char *terminators,
980 char *audio_files,
69f73575 981 char *bad_input_audio_files,
dbb40708 982 char *digits_regex,
cfa30468 983 const char *var_name,
e4d47319
MC
984 int digit_timeout,
985 const char *transfer_on_failure)
83f84876 986{
d5e4046d 987 sanity_check((char *)"");
878bbceb 988 this_check((char *)"");
fedefcb6 989 begin_allow_threads();
85fc8c37 990 memset(dtmf_buf, 0, sizeof(dtmf_buf));
df1ab07c 991 switch_play_and_get_digits( session,
7963c404
MJ
992 (uint32_t) min_digits,
993 (uint32_t) max_digits,
df1ab07c
SS
994 (uint32_t) max_tries,
995 (uint32_t) timeout,
996 terminators,
997 audio_files,
7963c404
MJ
998 bad_input_audio_files,
999 var_name,
df1ab07c
SS
1000 dtmf_buf,
1001 sizeof(dtmf_buf),
7963c404
MJ
1002 digits_regex,
1003 (uint32_t) digit_timeout,
1004 transfer_on_failure);
6f78befa 1005
fedefcb6 1006 end_allow_threads();
85fc8c37 1007 return dtmf_buf;
83f84876
AM
1008}
1009
ae4e48fa
SD
1010SWITCH_DECLARE(void) CoreSession::detectSpeech(char *arg0, char *arg1, char *arg2, char *arg3)
1011{
1012 this_check_void();
1013 sanity_check_noreturn;
1014
1015 begin_allow_threads();
1016
1017 if (!arg0) return;
1018
1019 if (!strcasecmp(arg0, "grammar") && arg1 && arg2) {
1020 switch_ivr_detect_speech_load_grammar(session, arg1, arg2);
1021 } else if (!strcasecmp(arg0, "nogrammar") && arg1) {
1022 switch_ivr_detect_speech_unload_grammar(session, arg1);
1023 } else if (!strcasecmp(arg0, "grammaron") && arg1) {
1024 switch_ivr_detect_speech_enable_grammar(session, arg1);
1025 } else if (!strcasecmp(arg0, "grammaroff") && arg1) {
1026 switch_ivr_detect_speech_disable_grammar(session, arg1);
1027 } else if (!strcasecmp(arg0, "grammarsalloff")) {
1028 switch_ivr_detect_speech_disable_all_grammars(session);
1029 } else if (!strcasecmp(arg0, "init") && arg1 && arg2) {
1030 switch_ivr_detect_speech_init(session, arg1, arg2, NULL);
1031 } else if (!strcasecmp(arg0, "pause")) {
1032 switch_ivr_pause_detect_speech(session);
1033 } else if (!strcasecmp(arg0, "resume")) {
1034 switch_ivr_resume_detect_speech(session);
1035 } else if (!strcasecmp(arg0, "stop")) {
1036 switch_ivr_stop_detect_speech(session);
1037 } else if (!strcasecmp(arg0, "param") && arg1 && arg2) {
1038 switch_ivr_set_param_detect_speech(session, arg1, arg2);
1039 } else if (!strcasecmp(arg0, "start-input-timers")) {
1040 switch_ivr_detect_speech_start_input_timers(session);
1041 } else if (!strcasecmp(arg0, "start_input_timers")) {
1042 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "start_input_timers is deprecated, please use start-input-timers instead!\n");
1043 switch_ivr_detect_speech_start_input_timers(session);
1044 } else if (arg1 && arg2 && arg3) {
1045 switch_ivr_detect_speech(session, arg0, arg1, arg2, arg3, NULL);
1046 }
1047
1048 end_allow_threads();
1049}
1050
1051SWITCH_DECLARE(char *) CoreSession::playAndDetectSpeech(char *file, char *engine, char *grammar)
1052{
1053 sanity_check((char *)"");
1054 this_check((char *)"");
1055 begin_allow_threads();
1056
1057 char *result = NULL;
1058
623fecd5 1059 switch_status_t status = switch_ivr_play_and_detect_speech(session, file, engine, grammar, &result, 0, ap);
ae4e48fa
SD
1060 if (status == SWITCH_STATUS_SUCCESS) {
1061 // good
1062 } else if (status == SWITCH_STATUS_GENERR) {
1063 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "GRAMMAR ERROR\n");
1064 } else if (status == SWITCH_STATUS_NOT_INITALIZED) {
1065 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "ASR INIT ERROR\n");
1066 } else {
623fecd5 1067 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "ERROR status = %d\n", status);
ae4e48fa
SD
1068 }
1069
1070 end_allow_threads();
1071
623fecd5 1072 return result ? strdup(result) : NULL; // remeber to free me
ae4e48fa
SD
1073}
1074
df1ab07c 1075SWITCH_DECLARE(void) CoreSession::say(const char *tosay, const char *module_name, const char *say_type, const char *say_method, const char *say_gender)
40efe06a 1076{
878bbceb 1077 this_check_void();
40efe06a
AM
1078 sanity_check_noreturn;
1079 if (!(tosay && module_name && say_type && say_method)) {
c2d5f970 1080 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Error! invalid args.\n");
40efe06a
AM
1081 return;
1082 }
1083 begin_allow_threads();
7c16b84a 1084 switch_ivr_say(session, tosay, module_name, say_type, say_method, say_gender, ap);
40efe06a
AM
1085 end_allow_threads();
1086}
1087
df1ab07c 1088SWITCH_DECLARE(void) CoreSession::sayPhrase(const char *phrase_name, const char *phrase_data, const char *phrase_lang)
40efe06a 1089{
878bbceb 1090 this_check_void();
40efe06a 1091 sanity_check_noreturn;
df1ab07c 1092
40efe06a 1093 if (!(phrase_name)) {
c2d5f970 1094 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Error! invalid args.\n");
40efe06a
AM
1095 return;
1096 }
1097
1098 begin_allow_threads();
1099 switch_ivr_phrase_macro(session, phrase_name, phrase_data, phrase_lang, ap);
1100 end_allow_threads();
1101}
1102
47985c56 1103SWITCH_DECLARE(int) CoreSession::streamFile(char *file, int starting_sample_count) {
f45d0601
MJ
1104
1105 switch_status_t status;
59526679 1106 //switch_file_handle_t fh = { 0 };
622a2733 1107 const char *prebuf;
f2495ec8 1108 switch_file_handle_t local_fh;
f45d0601 1109
878bbceb 1110 this_check(-1);
f45d0601 1111 sanity_check(-1);
df1ab07c 1112
59526679
AM
1113 memset(&local_fh, 0, sizeof(local_fh));
1114 fhp = &local_fh;
1115 local_fh.samples = starting_sample_count;
f45d0601 1116
f45d0601
MJ
1117
1118 if ((prebuf = switch_channel_get_variable(this->channel, "stream_prebuffer"))) {
1119 int maybe = atoi(prebuf);
1120 if (maybe > 0) {
59526679 1121 local_fh.prebuf = maybe;
f45d0601
MJ
1122 }
1123 }
1124
59526679
AM
1125 begin_allow_threads();
1126 status = switch_ivr_play_file(session, fhp, file, ap);
1127 end_allow_threads();
1128
a3ccefa7 1129 fhp = NULL;
df1ab07c 1130
f45d0601
MJ
1131 return status == SWITCH_STATUS_SUCCESS ? 1 : 0;
1132
1133}
1134
71054917 1135SWITCH_DECLARE(int) CoreSession::sleep(int ms, int sync) {
32bbdb74
AM
1136
1137 switch_status_t status;
1138
1139 this_check(-1);
1140 sanity_check(-1);
df1ab07c 1141
32bbdb74 1142 begin_allow_threads();
71054917 1143 status = switch_ivr_sleep(session, ms, (switch_bool_t) sync, ap);
32bbdb74
AM
1144 end_allow_threads();
1145
1146 return status == SWITCH_STATUS_SUCCESS ? 1 : 0;
1147
1148}
1149
47985c56 1150SWITCH_DECLARE(bool) CoreSession::ready() {
f45d0601 1151
878bbceb 1152 this_check(false);
83ebebc5
AM
1153
1154 if (!session) {
1155 return false;
1156 }
1157 sanity_check(false);
1158
482badff 1159 return switch_channel_ready(channel) != 0;
fedefcb6
MJ
1160}
1161
334abcda
AM
1162
1163SWITCH_DECLARE(bool) CoreSession::bridged() {
1164
1165 this_check(false);
1166
1167 if (!session) {
1168 return false;
1169 }
1170 sanity_check(false);
1171
1172 return (switch_channel_up(channel) && switch_channel_test_flag(channel, CF_BRIDGED));
1173}
1174
830a8493
AM
1175SWITCH_DECLARE(bool) CoreSession::mediaReady() {
1176
1177 this_check(false);
df1ab07c 1178 sanity_check(false);
830a8493
AM
1179 return switch_channel_media_ready(channel) != 0;
1180}
1181
1182SWITCH_DECLARE(bool) CoreSession::answered() {
1183
1184 this_check(false);
df1ab07c 1185 sanity_check(false);
830a8493
AM
1186 return switch_channel_test_flag(channel, CF_ANSWERED) != 0;
1187}
1188
ddd1ae14
AM
1189SWITCH_DECLARE(void) CoreSession::destroy(void)
1190{
1191 this_check_void();
df1ab07c 1192
4025b424
AM
1193 if (!allocated) {
1194 return;
1195 }
ddd1ae14 1196
540445cb
AM
1197 allocated = 0;
1198
ddd1ae14 1199 switch_safe_free(xml_cdr_text);
df1ab07c 1200 switch_safe_free(uuid);
ddd1ae14
AM
1201 switch_safe_free(tts_name);
1202 switch_safe_free(voice_name);
1203
1204 if (session) {
523e0653
AM
1205 if (!channel) {
1206 channel = switch_core_session_get_channel(session);
1207 }
1208
1209 if (channel) {
df1ab07c 1210 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG,
540445cb 1211 "%s destroy/unlink session from object\n", switch_channel_get_name(channel));
523e0653 1212 switch_channel_set_private(channel, "CoreSession", NULL);
540445cb
AM
1213 if (switch_channel_up(channel) && switch_test_flag(this, S_HUP) && !switch_channel_test_flag(channel, CF_TRANSFER)) {
1214 switch_channel_hangup(channel, SWITCH_CAUSE_NORMAL_CLEARING);
1215 }
523e0653 1216 }
540445cb 1217
ddd1ae14
AM
1218 switch_core_session_rwunlock(session);
1219 session = NULL;
523e0653 1220 channel = NULL;
ddd1ae14
AM
1221 }
1222
4025b424 1223 init_vars();
df1ab07c 1224
ddd1ae14
AM
1225}
1226
c54f0c39
AM
1227SWITCH_DECLARE(const char *) CoreSession::hangupCause()
1228{
2261b687 1229 this_check(NULL);
c54f0c39
AM
1230 return switch_channel_cause2str(cause);
1231}
1232
635e2fb5
AM
1233SWITCH_DECLARE(const char *) CoreSession::getState()
1234{
1235 this_check(NULL);
1236
1237 if (channel) {
1238 return switch_channel_state_name(switch_channel_get_state(channel));
1239 }
1240
1241 return "ERROR";
1242
1243}
1244
5a5f3081 1245SWITCH_DECLARE(int) CoreSession::originate(CoreSession *a_leg_session, char *dest, int timeout, switch_state_handler_table_t *handlers)
e028f269
MJ
1246{
1247
e028f269 1248 switch_core_session_t *aleg_core_session = NULL;
e028f269 1249
878bbceb 1250 this_check(0);
878bbceb 1251
e028f269
MJ
1252 cause = SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER;
1253
700aa0df
TL
1254 if (a_leg_session != NULL) {
1255 aleg_core_session = a_leg_session->session;
e028f269
MJ
1256 }
1257
700aa0df 1258 // this session has no valid switch_core_session_t at this point, and therefore
df1ab07c 1259 // no valid channel. since the threadstate is stored in the channel, and there
700aa0df
TL
1260 // is none, if we try to call begin_alllow_threads it will fail miserably.
1261 // use the 'a leg session' to do the thread swapping stuff.
3d3ee88d 1262 if (a_leg_session) a_leg_session->begin_allow_threads();
e028f269 1263
df1ab07c
SS
1264 if (switch_ivr_originate(aleg_core_session,
1265 &session,
1266 &cause,
1267 dest,
e028f269 1268 timeout,
df1ab07c
SS
1269 handlers,
1270 NULL,
1271 NULL,
c5f1d9ec 1272 NULL,
a579a283 1273 NULL,
2fa0c491 1274 SOF_NONE,
d3e320ef 1275 NULL,
2fa0c491 1276 NULL) != SWITCH_STATUS_SUCCESS) {
e028f269
MJ
1277 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Error Creating Outgoing Channel! [%s]\n", dest);
1278 goto failed;
1279
1280 }
1281
3d3ee88d 1282 if (a_leg_session) a_leg_session->end_allow_threads();
d895c81d 1283 channel = switch_core_session_get_channel(session);
94b22258 1284 allocated = 1;
2a3be1dc
MR
1285 switch_safe_free(uuid);
1286 uuid = strdup(switch_core_session_get_uuid(session));
4b929592 1287 switch_channel_set_state(switch_core_session_get_channel(session), CS_SOFT_EXECUTE);
ae76db7b 1288
e028f269
MJ
1289 return SWITCH_STATUS_SUCCESS;
1290
1291 failed:
3d3ee88d 1292 if (a_leg_session) a_leg_session->end_allow_threads();
e028f269
MJ
1293 return SWITCH_STATUS_FALSE;
1294}
1295
df1ab07c 1296SWITCH_DECLARE(int) CoreSession::recordFile(char *file_name, int time_limit, int silence_threshold, int silence_hits)
bd2c91b0 1297{
bd2c91b0 1298 switch_status_t status;
f2495ec8 1299 switch_file_handle_t local_fh;
bd2c91b0 1300
878bbceb
AM
1301 this_check(-1);
1302 sanity_check(-1);
1303
15051696 1304 if (!file_name) return 0;
a3ccefa7
AM
1305 memset(&local_fh, 0, sizeof(local_fh));
1306 fhp = &local_fh;
1307 local_fh.thresh = silence_threshold;
3a67cbf4 1308 local_fh.silence_hits = silence_hits;
a3ccefa7 1309
bd2c91b0 1310 begin_allow_threads();
1d91b7d6 1311 status = switch_ivr_record_file(session, &local_fh, file_name, ap, time_limit);
bd2c91b0 1312 end_allow_threads();
a3ccefa7
AM
1313
1314 fhp = NULL;
1315
bd2c91b0
MJ
1316 return status == SWITCH_STATUS_SUCCESS ? 1 : 0;
1317
1318}
e028f269 1319
df1ab07c 1320SWITCH_DECLARE(int) CoreSession::flushEvents()
6f78befa
TL
1321{
1322 switch_event_t *event;
6f78befa 1323
878bbceb
AM
1324 this_check(-1);
1325 sanity_check(-1);
1326
6f78befa
TL
1327 if (!session) {
1328 return SWITCH_STATUS_FALSE;
1329 }
6f78befa 1330
99026e02 1331 while (switch_core_session_dequeue_event(session, &event, SWITCH_TRUE) == SWITCH_STATUS_SUCCESS) {
6f78befa
TL
1332 switch_event_destroy(&event);
1333 }
1334 return SWITCH_STATUS_SUCCESS;
1335}
1336
df1ab07c 1337SWITCH_DECLARE(int) CoreSession::flushDigits()
6f78befa 1338{
878bbceb
AM
1339 this_check(-1);
1340 sanity_check(-1);
482badff 1341 switch_channel_flush_dtmf(switch_core_session_get_channel(session));
6f78befa
TL
1342 return SWITCH_STATUS_SUCCESS;
1343}
1344
df1ab07c 1345SWITCH_DECLARE(int) CoreSession::setAutoHangup(bool val)
6f78befa 1346{
878bbceb
AM
1347 this_check(-1);
1348 sanity_check(-1);
1349
6f78befa
TL
1350 if (!session) {
1351 return SWITCH_STATUS_FALSE;
df1ab07c 1352 }
6f78befa
TL
1353 if (val) {
1354 switch_set_flag(this, S_HUP);
1355 } else {
1356 switch_clear_flag(this, S_HUP);
1357 }
1358 return SWITCH_STATUS_SUCCESS;
1359}
1360
df1ab07c 1361SWITCH_DECLARE(void) CoreSession::waitForAnswer(CoreSession *calling_session)
7f4c8a6d
AM
1362{
1363 this_check_void();
1364 sanity_check_noreturn;
df1ab07c 1365
7f4c8a6d
AM
1366 switch_ivr_wait_for_answer(calling_session ? calling_session->session : NULL, session);
1367
1368}
1369
47985c56 1370SWITCH_DECLARE(void) CoreSession::setHangupHook(void *hangup_func) {
6f78befa 1371
878bbceb 1372 this_check_void();
a06997ee 1373 sanity_check_noreturn;
df1ab07c 1374
c2d5f970 1375 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "CoreSession::seHangupHook, hangup_func: %p\n", hangup_func);
6f78befa
TL
1376 on_hangup = hangup_func;
1377 switch_channel_t *channel = switch_core_session_get_channel(session);
6f78befa
TL
1378
1379 hook_state = switch_channel_get_state(channel);
1380 switch_channel_set_private(channel, "CoreSession", this);
1381 switch_core_event_hook_add_state_change(session, hanguphook);
fedefcb6
MJ
1382}
1383
e60f37f6
AM
1384SWITCH_DECLARE(void) CoreSession::consoleLog(char *level_str, char *msg)
1385{
1386 switch_log_level_t level = SWITCH_LOG_DEBUG;
1387 if (level_str) {
1388 level = switch_log_str2level(level_str);
1389 if (level == SWITCH_LOG_INVALID) {
1390 level = SWITCH_LOG_DEBUG;
1391 }
1392 }
1393 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), level, "%s", switch_str_nil(msg));
1394}
1395
74262ee9
TC
1396SWITCH_DECLARE(void) CoreSession::consoleLog2(char *level_str, char *file, char *func, int line, char *msg)
1397{
1398 switch_log_level_t level = SWITCH_LOG_DEBUG;
1399 if (level_str) {
1400 level = switch_log_str2level(level_str);
1401 if (level == SWITCH_LOG_INVALID) {
1402 level = SWITCH_LOG_DEBUG;
1403 }
1404 }
1405 switch_log_printf(SWITCH_CHANNEL_ID_SESSION, file, func, line, (const char*)session,
1406 level, "%s", switch_str_nil(msg));
1407}
1408
e028f269
MJ
1409/* ---- methods not bound to CoreSession instance ---- */
1410
c017c24b
AM
1411
1412SWITCH_DECLARE(int) globalSetVariable(const char *var, const char *val, const char *val2)
1413{
1414 if (zstr(val)) val = NULL;
1415 if (zstr(val2)) val2 = NULL;
df1ab07c 1416
c017c24b 1417 if (val2) {
ea5e699c 1418 return switch_core_set_var_conditional(var, val, val2);
c017c24b
AM
1419 } else {
1420 switch_core_set_variable(var, val);
ea5e699c 1421 return SWITCH_STATUS_SUCCESS;
c017c24b
AM
1422 }
1423}
1424
2faaee0e
AM
1425SWITCH_DECLARE(void) setGlobalVariable(char *var_name, char *var_val)
1426{
1427 switch_core_set_variable(var_name, var_val);
1428}
1429
1430SWITCH_DECLARE(char *) getGlobalVariable(char *var_name)
1431{
1432 return switch_core_get_variable_dup(var_name);
1433}
1434
1435
428cd029
AM
1436SWITCH_DECLARE(bool) running(void)
1437{
1438 return switch_core_running() ? true : false;
1439}
1440
8f5a873d
AM
1441SWITCH_DECLARE(void) consoleLog(char *level_str, char *msg)
1442{
1443 return console_log(level_str, msg);
1444}
1445
d1ec6432 1446SWITCH_DECLARE(void) consoleLog2(char *level_str, char *file, char *func, int line, char *msg)
8f5a873d 1447{
d1ec6432 1448 return console_log2(level_str, file, func, line, msg);
8f5a873d 1449}
e028f269 1450
d1ec6432 1451SWITCH_DECLARE(void) consoleCleanLog(char *msg)
a99df489 1452{
d1ec6432 1453 return console_clean_log(msg);
a99df489
BW
1454}
1455
47985c56 1456SWITCH_DECLARE(void) console_log(char *level_str, char *msg)
e028f269
MJ
1457{
1458 switch_log_level_t level = SWITCH_LOG_DEBUG;
1459 if (level_str) {
1460 level = switch_log_str2level(level_str);
cc71ce69
MJ
1461 if (level == SWITCH_LOG_INVALID) {
1462 level = SWITCH_LOG_DEBUG;
1463 }
e028f269 1464 }
9b8a5edd 1465
ae76db7b 1466 switch_log_printf(SWITCH_CHANNEL_LOG, level, "%s", switch_str_nil(msg));
e028f269
MJ
1467}
1468
d1ec6432 1469SWITCH_DECLARE(void) console_log2(char *level_str, char *file, char *func, int line, char *msg)
a99df489
BW
1470{
1471 switch_log_level_t level = SWITCH_LOG_DEBUG;
1472 if (level_str) {
1473 level = switch_log_str2level(level_str);
1474 if (level == SWITCH_LOG_INVALID) {
1475 level = SWITCH_LOG_DEBUG;
1476 }
1477 }
1478 switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, func, line, NULL, level, "%s", switch_str_nil(msg));
1479}
1480
d1ec6432
TC
1481SWITCH_DECLARE(void) console_clean_log(char *msg)
1482{
1483 switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN,SWITCH_LOG_DEBUG, "%s", switch_str_nil(msg));
1484}
1485
89c5f3bf
BW
1486SWITCH_DECLARE(bool) email(char *to, char *from, char *headers, char *body, char *file, char *convert_cmd, char *convert_ext)
1487{
1488 if (switch_simple_email(to, from, headers, body, file, convert_cmd, convert_ext) == SWITCH_TRUE) {
1489 return true;
1490 }
1491 return false;
1492}
e028f269 1493
1af72288 1494SWITCH_DECLARE(void) switch_msleep(unsigned ms)
369e6065
MJ
1495{
1496 switch_sleep(ms * 1000);
1497 return;
1498}
1499
47985c56 1500SWITCH_DECLARE(void) bridge(CoreSession &session_a, CoreSession &session_b)
e028f269 1501{
e028f269
MJ
1502 switch_input_callback_function_t dtmf_func = NULL;
1503 switch_input_args_t args;
920ef82c
AM
1504 switch_channel_t *channel_a = NULL, *channel_b = NULL;
1505 const char *err = "Channels not ready\n";
df1ab07c 1506
920ef82c
AM
1507 if (session_a.allocated && session_a.session && session_b.allocated && session_b.session) {
1508 channel_a = switch_core_session_get_channel(session_a.session);
1509 channel_b = switch_core_session_get_channel(session_b.session);
1510
1511 if (switch_channel_ready(channel_a) && switch_channel_ready(channel_b)) {
1512 session_a.begin_allow_threads();
93cc3dc5 1513 if (switch_channel_direction(channel_a) == SWITCH_CALL_DIRECTION_INBOUND && !switch_channel_media_ready(channel_a)) {
88ae7890 1514 switch_channel_pre_answer(channel_a);
920ef82c 1515 }
88ae7890 1516
920ef82c
AM
1517 if (switch_channel_ready(channel_a) && switch_channel_ready(channel_b)) {
1518 args = session_a.get_cb_args(); // get the cb_args data structure for session a
1519 dtmf_func = args.input_callback; // get the call back function
1520 err = NULL;
1521 switch_ivr_multi_threaded_bridge(session_a.session, session_b.session, dtmf_func, args.buf, args.buf);
920ef82c 1522 }
df5afbca 1523 session_a.end_allow_threads();
920ef82c
AM
1524 }
1525 }
1526
1527 if (err) {
c2d5f970 1528 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session_a.session), SWITCH_LOG_ERROR, "%s", err);
920ef82c 1529 }
e028f269 1530
e028f269
MJ
1531
1532}
1533
df1ab07c 1534SWITCH_DECLARE_NONSTD(switch_status_t) hanguphook(switch_core_session_t *session_hungup)
6f78befa 1535{
3ff3f327
MJ
1536 if (session_hungup) {
1537 switch_channel_t *channel = switch_core_session_get_channel(session_hungup);
1538 CoreSession *coresession = NULL;
1539 switch_channel_state_t state = switch_channel_get_state(channel);
1540
1541 if ((coresession = (CoreSession *) switch_channel_get_private(channel, "CoreSession"))) {
1542 if (coresession->hook_state != state) {
1543 coresession->cause = switch_channel_get_cause(channel);
1544 coresession->hook_state = state;
1545 coresession->check_hangup_hook();
1546 }
6f78befa 1547 }
6f78befa 1548
3ff3f327
MJ
1549 return SWITCH_STATUS_SUCCESS;
1550 } else {
1551 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "hangup hook called with null session, something is horribly wrong\n");
1552 return SWITCH_STATUS_FALSE;
1553 }
6f78befa
TL
1554}
1555
1556
df1ab07c
SS
1557SWITCH_DECLARE_NONSTD(switch_status_t) dtmf_callback(switch_core_session_t *session_cb,
1558 void *input,
1559 switch_input_type_t itype,
1560 void *buf,
8b8a7f14 1561 unsigned int buflen) {
df1ab07c 1562
482badff 1563 switch_channel_t *channel = switch_core_session_get_channel(session_cb);
6f78befa 1564 CoreSession *coresession = NULL;
6f78befa 1565
6f78befa 1566 coresession = (CoreSession *) switch_channel_get_private(channel, "CoreSession");
59526679 1567
6f78befa 1568 if (!coresession) {
6f78befa
TL
1569 return SWITCH_STATUS_FALSE;
1570 }
1571
4780a3d3 1572 return coresession->run_dtmf_callback(input, itype);
6f78befa
TL
1573}
1574
59526679 1575
fe854bdb 1576SWITCH_DECLARE(switch_status_t) CoreSession::process_callback_result(char *result)
e028f269 1577{
df1ab07c 1578
878bbceb
AM
1579 this_check(SWITCH_STATUS_FALSE);
1580 sanity_check(SWITCH_STATUS_FALSE);
df1ab07c 1581
c4369fc8 1582 return switch_ivr_process_fh(session, result, fhp);
e028f269
MJ
1583}
1584
83f84876
AM
1585/* For Emacs:
1586 * Local Variables:
1587 * mode:c
1588 * indent-tabs-mode:t
1589 * tab-width:4
1590 * c-basic-offset:4
1591 * End:
1592 * For VIM:
32adc789 1593 * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
83f84876 1594 */